diff --git a/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs b/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs
index e499285c84a80..945242123cdaf 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs
@@ -259,6 +259,18 @@ private BoundExpression CheckValue(BoundExpression expr, BindValueKind valueKind
return ToBadExpression(expr, resultKind);
}
+ internal static bool IsTypeOrValueExpression(BoundExpression expression)
+ {
+ switch (expression?.Kind)
+ {
+ case BoundKind.TypeOrValueExpression:
+ case BoundKind.QueryClause when ((BoundQueryClause)expression).Value.Kind == BoundKind.TypeOrValueExpression:
+ return true;
+ default:
+ return false;
+ }
+ }
+
///
/// The purpose of this method is to determine if the expression satisfies desired capabilities.
/// If it is not then this code gives an appropriate error message.
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder.cs b/src/Compilers/CSharp/Portable/Binder/Binder.cs
index 46c6af1a94164..84890dc597c16 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder.cs
@@ -347,7 +347,7 @@ internal bool BindingTopLevelScriptCode
get
{
var containingMember = this.ContainingMemberOrLambda;
- switch (containingMember.Kind)
+ switch (containingMember?.Kind)
{
case SymbolKind.Method:
// global statements
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
index 7bc3346493e5b..3237a101afdd8 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
@@ -455,8 +455,7 @@ private static bool IsMethodGroupWithTypeOrValueReceiver(BoundNode node)
return false;
}
- BoundNode receiverOpt = ((BoundMethodGroup)node).ReceiverOpt;
- return receiverOpt != null && receiverOpt.Kind == BoundKind.TypeOrValueExpression;
+ return Binder.IsTypeOrValueExpression(((BoundMethodGroup)node).ReceiverOpt);
}
private BoundMethodGroup FixMethodGroupWithTypeOrValue(BoundMethodGroup group, Conversion conversion, DiagnosticBag diagnostics)
@@ -572,7 +571,7 @@ private bool MemberGroupFinalValidationAccessibilityChecks(BoundExpression recei
//note that the same assert does not hold for all properties. Some properties and (all indexers) are not referenceable by name, yet
//their binding brings them through here, perhaps needlessly.
- if (receiverOpt != null && receiverOpt.Kind == BoundKind.TypeOrValueExpression)
+ if (IsTypeOrValueExpression(receiverOpt))
{
// TypeOrValue expression isn't replaced only if the invocation is late bound, in which case it can't be extension method.
// None of the checks below apply if the receiver can't be classified as a type or value.
@@ -678,7 +677,7 @@ private static bool IsMemberAccessedThroughVariableOrValue(BoundExpression recei
return !IsMemberAccessedThroughType(receiverOpt);
}
- private static bool IsMemberAccessedThroughType(BoundExpression receiverOpt)
+ internal static bool IsMemberAccessedThroughType(BoundExpression receiverOpt)
{
if (receiverOpt == null)
{
@@ -696,7 +695,7 @@ private static bool IsMemberAccessedThroughType(BoundExpression receiverOpt)
///
/// Was the receiver expression compiler-generated?
///
- private static bool WasImplicitReceiver(BoundExpression receiverOpt)
+ internal static bool WasImplicitReceiver(BoundExpression receiverOpt)
{
if (receiverOpt == null) return true;
if (!receiverOpt.WasCompilerGenerated) return false;
@@ -808,8 +807,8 @@ private bool MethodGroupConversionHasErrors(
MethodSymbol selectedMethod = conversion.Method;
- if (MemberGroupFinalValidation(receiverOpt, selectedMethod, syntax, diagnostics, isExtensionMethod) ||
- !MethodGroupIsCompatibleWithDelegate(receiverOpt, isExtensionMethod, selectedMethod, delegateType, syntax.Location, diagnostics))
+ if (!MethodGroupIsCompatibleWithDelegate(receiverOpt, isExtensionMethod, selectedMethod, delegateType, syntax.Location, diagnostics) ||
+ MemberGroupFinalValidation(receiverOpt, selectedMethod, syntax, diagnostics, isExtensionMethod))
{
return true;
}
@@ -864,8 +863,12 @@ private bool MethodGroupConversionDoesNotExistOrHasErrors(
diagnostics.Add(delegateMismatchLocation, useSiteDiagnostics);
if (!conversion.Exists)
{
- // No overload for '{0}' matches delegate '{1}'
- diagnostics.Add(ErrorCode.ERR_MethDelegateMismatch, delegateMismatchLocation, boundMethodGroup.Name, delegateType);
+ if (!Conversions.ReportDelegateMethodGroupDiagnostics(this, boundMethodGroup, delegateType, diagnostics))
+ {
+ // No overload for '{0}' matches delegate '{1}'
+ diagnostics.Add(ErrorCode.ERR_MethDelegateMismatch, delegateMismatchLocation, boundMethodGroup.Name, delegateType);
+ }
+
return true;
}
else
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
index b5e2811d66d11..4e62a54b2914f 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
@@ -26,12 +26,12 @@ internal partial class Binder
/// The reference was explicitly specified in syntax.
/// True if "this" is not available due to the current method/property/field initializer being static.
/// True if a reference to "this" is available.
- private bool HasThis(bool isExplicit, out bool inStaticContext)
+ internal bool HasThis(bool isExplicit, out bool inStaticContext)
{
- var member = this.ContainingMemberOrLambda.ContainingNonLambdaMember();
- if (member.IsStatic)
+ var memberOpt = this.ContainingMemberOrLambda?.ContainingNonLambdaMember();
+ if (memberOpt?.IsStatic == true)
{
- inStaticContext = member.Kind == SymbolKind.Field || member.Kind == SymbolKind.Method || member.Kind == SymbolKind.Property;
+ inStaticContext = memberOpt.Kind == SymbolKind.Field || memberOpt.Kind == SymbolKind.Method || memberOpt.Kind == SymbolKind.Property;
return false;
}
@@ -42,7 +42,7 @@ private bool HasThis(bool isExplicit, out bool inStaticContext)
return false;
}
- var containingType = member.ContainingType;
+ var containingType = memberOpt?.ContainingType;
bool inTopLevelScriptMember = (object)containingType != null && containingType.IsScriptClass;
// "this" is not allowed in field initializers (that are not script variable initializers):
@@ -1953,8 +1953,12 @@ private void GenerateExplicitConversionErrors(
{
case BoundKind.MethodGroup:
{
- // TODO: report more specific diagnostics here for failed method group conversions
- diagnostics.Add(ErrorCode.ERR_NoExplicitConv, syntax.Location, MessageID.IDS_SK_METHOD.Localize(), targetType);
+ if (targetType.TypeKind != TypeKind.Delegate ||
+ !MethodGroupConversionDoesNotExistOrHasErrors((BoundMethodGroup)operand, (NamedTypeSymbol)targetType, syntax.Location, diagnostics, out _))
+ {
+ diagnostics.Add(ErrorCode.ERR_NoExplicitConv, syntax.Location, MessageID.IDS_SK_METHOD.Localize(), targetType);
+ }
+
return;
}
case BoundKind.TupleLiteral:
@@ -3598,16 +3602,22 @@ private BoundExpression BindDelegateCreationExpression(ObjectCreationExpressionS
}
methodGroup.PopulateWithSingleMethod(argument, sourceDelegate.DelegateInvokeMethod);
-
HashSet useSiteDiagnostics = null;
Conversion conv = Conversions.MethodGroupConversion(argument.Syntax, methodGroup, type, ref useSiteDiagnostics);
diagnostics.Add(node, useSiteDiagnostics);
if (!conv.Exists)
{
- // No overload for '{0}' matches delegate '{1}'
- diagnostics.Add(ErrorCode.ERR_MethDelegateMismatch, node.Location,
- sourceDelegate.Name, // duplicate questionable Dev10 diagnostic
- type);
+ var boundMethodGroup = new BoundMethodGroup(
+ argument.Syntax, default, WellKnownMemberNames.DelegateInvokeName, ImmutableArray.Create(sourceDelegate.DelegateInvokeMethod),
+ sourceDelegate.DelegateInvokeMethod, null, BoundMethodGroupFlags.None, argument, LookupResultKind.Viable);
+ if (!Conversions.ReportDelegateMethodGroupDiagnostics(this, boundMethodGroup, type, diagnostics))
+ {
+ // If we could not produce a more specialized diagnostic, we report
+ // No overload for '{0}' matches delegate '{1}'
+ diagnostics.Add(ErrorCode.ERR_MethDelegateMismatch, node.Location,
+ sourceDelegate.DelegateInvokeMethod,
+ type);
+ }
}
else
{
@@ -4860,8 +4870,10 @@ private bool TryPerformConstructorOverloadResolution(
}
else
{
- result.ReportDiagnostics(this, errorLocation, diagnostics,
- errorName, null, analyzedArguments, candidateConstructors, typeContainingConstructors, null);
+ result.ReportDiagnostics(
+ binder: this, location: errorLocation, nodeOpt: null, diagnostics,
+ name: errorName, receiver: null, invokedExpression: null, analyzedArguments,
+ memberGroup: candidateConstructors, typeContainingConstructors, delegateTypeBeingInvoked: null);
}
}
@@ -5823,7 +5835,9 @@ private MethodGroupResolution BindExtensionMethod(
AnalyzedArguments analyzedArguments,
BoundExpression left,
ImmutableArray typeArguments,
- bool isMethodGroupConversion)
+ bool isMethodGroupConversion,
+ RefKind returnRefKind,
+ TypeSymbol returnType)
{
var firstResult = new MethodGroupResolution();
AnalyzedArguments actualArguments = null;
@@ -5872,7 +5886,17 @@ private MethodGroupResolution BindExtensionMethod(
var overloadResolutionResult = OverloadResolutionResult.GetInstance();
bool allowRefOmittedArguments = methodGroup.Receiver.IsExpressionOfComImportType();
HashSet useSiteDiagnostics = null;
- OverloadResolution.MethodInvocationOverloadResolution(methodGroup.Methods, methodGroup.TypeArguments, actualArguments, overloadResolutionResult, ref useSiteDiagnostics, isMethodGroupConversion, allowRefOmittedArguments);
+ OverloadResolution.MethodInvocationOverloadResolution(
+ methods: methodGroup.Methods,
+ typeArguments: methodGroup.TypeArguments,
+ receiver: methodGroup.Receiver,
+ arguments: actualArguments,
+ result: overloadResolutionResult,
+ useSiteDiagnostics: ref useSiteDiagnostics,
+ isMethodGroupConversion: isMethodGroupConversion,
+ allowRefOmittedArguments: allowRefOmittedArguments,
+ returnRefKind: returnRefKind,
+ returnType: returnType);
diagnostics.Add(expression, useSiteDiagnostics);
var sealedDiagnostics = diagnostics.ToReadOnlyAndFree();
var result = new MethodGroupResolution(methodGroup, null, overloadResolutionResult, actualArguments, methodGroup.ResultKind, sealedDiagnostics);
@@ -6737,7 +6761,7 @@ private BoundExpression BindIndexerOrIndexedPropertyAccess(
OverloadResolutionResult overloadResolutionResult = OverloadResolutionResult.GetInstance();
bool allowRefOmittedArguments = receiverOpt.IsExpressionOfComImportType();
HashSet useSiteDiagnostics = null;
- this.OverloadResolution.PropertyOverloadResolution(propertyGroup, analyzedArguments, overloadResolutionResult, allowRefOmittedArguments, ref useSiteDiagnostics);
+ this.OverloadResolution.PropertyOverloadResolution(propertyGroup, receiverOpt, analyzedArguments, overloadResolutionResult, allowRefOmittedArguments, ref useSiteDiagnostics);
diagnostics.Add(syntax, useSiteDiagnostics);
BoundExpression propertyAccess;
@@ -6768,13 +6792,15 @@ private BoundExpression BindIndexerOrIndexedPropertyAccess(
var name = candidate.IsIndexer ? SyntaxFacts.GetText(SyntaxKind.ThisKeyword) : candidate.Name;
overloadResolutionResult.ReportDiagnostics(
- this,
- syntax.Location,
- diagnostics,
- name,
- null,
- analyzedArguments,
- candidates,
+ binder: this,
+ location: syntax.Location,
+ nodeOpt: syntax,
+ diagnostics: diagnostics,
+ name: name,
+ receiver: null,
+ invokedExpression: null,
+ arguments: analyzedArguments,
+ memberGroup: candidates,
typeContainingConstructor: null,
delegateTypeBeingInvoked: null);
}
@@ -6861,14 +6887,26 @@ private ErrorPropertySymbol CreateErrorPropertySymbol(ImmutableArray
+ /// The node associated with the method group
+ /// The arguments of the invocation (or the delegate type, if a method group conversion)
+ /// True if it is a method group conversion
+ ///
+ ///
+ /// If a method group conversion, the desired ref kind of the delegate
+ /// If a method group conversion, the desired return type of the delegate.
+ /// May be null during inference if the return type of the delegate needs to be computed.
internal MethodGroupResolution ResolveMethodGroup(
BoundMethodGroup node,
AnalyzedArguments analyzedArguments,
bool isMethodGroupConversion,
ref HashSet useSiteDiagnostics,
- bool inferWithDynamic = false)
+ bool inferWithDynamic = false,
+ RefKind returnRefKind = default,
+ TypeSymbol returnType = null)
{
- return ResolveMethodGroup(node, node.Syntax, node.Name, analyzedArguments, isMethodGroupConversion, ref useSiteDiagnostics, inferWithDynamic: inferWithDynamic);
+ return ResolveMethodGroup(
+ node, node.Syntax, node.Name, analyzedArguments, isMethodGroupConversion, ref useSiteDiagnostics,
+ inferWithDynamic: inferWithDynamic, returnRefKind: returnRefKind, returnType: returnType);
}
internal MethodGroupResolution ResolveMethodGroup(
@@ -6879,11 +6917,14 @@ internal MethodGroupResolution ResolveMethodGroup(
bool isMethodGroupConversion,
ref HashSet useSiteDiagnostics,
bool inferWithDynamic = false,
- bool allowUnexpandedForm = true)
+ bool allowUnexpandedForm = true,
+ RefKind returnRefKind = default,
+ TypeSymbol returnType = null)
{
var methodResolution = ResolveMethodGroupInternal(
node, expression, methodName, analyzedArguments, isMethodGroupConversion, ref useSiteDiagnostics,
- inferWithDynamic: inferWithDynamic, allowUnexpandedForm: allowUnexpandedForm);
+ inferWithDynamic: inferWithDynamic, allowUnexpandedForm: allowUnexpandedForm,
+ returnRefKind: returnRefKind, returnType: returnType);
if (methodResolution.IsEmpty && !methodResolution.HasAnyErrors)
{
Debug.Assert(node.LookupError == null);
@@ -6904,11 +6945,14 @@ private MethodGroupResolution ResolveMethodGroupInternal(
bool isMethodGroupConversion,
ref HashSet useSiteDiagnostics,
bool inferWithDynamic = false,
- bool allowUnexpandedForm = true)
+ bool allowUnexpandedForm = true,
+ RefKind returnRefKind = default,
+ TypeSymbol returnType = null)
{
var methodResolution = ResolveDefaultMethodGroup(
methodGroup, analyzedArguments, isMethodGroupConversion, ref useSiteDiagnostics,
- inferWithDynamic: inferWithDynamic, allowUnexpandedForm: allowUnexpandedForm);
+ inferWithDynamic: inferWithDynamic, allowUnexpandedForm: allowUnexpandedForm,
+ returnRefKind: returnRefKind, returnType: returnType);
// If the method group's receiver is dynamic then there is no point in looking for extension methods;
// it's going to be a dynamic invocation.
@@ -6917,7 +6961,9 @@ private MethodGroupResolution ResolveMethodGroupInternal(
return methodResolution;
}
- var extensionMethodResolution = BindExtensionMethod(expression, methodName, analyzedArguments, methodGroup.ReceiverOpt, methodGroup.TypeArgumentsOpt, isMethodGroupConversion);
+ var extensionMethodResolution = BindExtensionMethod(
+ expression, methodName, analyzedArguments, methodGroup.ReceiverOpt, methodGroup.TypeArgumentsOpt, isMethodGroupConversion,
+ returnRefKind: returnRefKind, returnType: returnType);
bool preferExtensionMethodResolution = false;
if (extensionMethodResolution.HasAnyApplicableMethod)
@@ -6969,7 +7015,9 @@ private MethodGroupResolution ResolveDefaultMethodGroup(
bool isMethodGroupConversion,
ref HashSet useSiteDiagnostics,
bool inferWithDynamic = false,
- bool allowUnexpandedForm = true)
+ bool allowUnexpandedForm = true,
+ RefKind returnRefKind = default,
+ TypeSymbol returnType = null)
{
var methods = node.Methods;
if (methods.Length == 0)
@@ -7015,9 +7063,18 @@ private MethodGroupResolution ResolveDefaultMethodGroup(
var result = OverloadResolutionResult.GetInstance();
bool allowRefOmittedArguments = methodGroup.Receiver.IsExpressionOfComImportType();
OverloadResolution.MethodInvocationOverloadResolution(
- methodGroup.Methods, methodGroup.TypeArguments, analyzedArguments,
- result, ref useSiteDiagnostics, isMethodGroupConversion, allowRefOmittedArguments,
- inferWithDynamic: inferWithDynamic, allowUnexpandedForm: allowUnexpandedForm);
+ methods: methodGroup.Methods,
+ typeArguments: methodGroup.TypeArguments,
+ receiver: methodGroup.Receiver,
+ arguments: analyzedArguments,
+ result: result,
+ useSiteDiagnostics: ref useSiteDiagnostics,
+ isMethodGroupConversion: isMethodGroupConversion,
+ allowRefOmittedArguments: allowRefOmittedArguments,
+ inferWithDynamic: inferWithDynamic,
+ allowUnexpandedForm: allowUnexpandedForm,
+ returnRefKind: returnRefKind,
+ returnType: returnType);
return new MethodGroupResolution(methodGroup, null, result, analyzedArguments, methodGroup.ResultKind, sealedDiagnostics);
}
}
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
index ce729d50da236..76564690dd19e 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
@@ -497,7 +497,13 @@ private BoundExpression BindDelegateInvocation(
methodGroup.PopulateWithSingleMethod(boundExpression, delegateType.DelegateInvokeMethod);
var overloadResolutionResult = OverloadResolutionResult.GetInstance();
HashSet useSiteDiagnostics = null;
- OverloadResolution.MethodInvocationOverloadResolution(methodGroup.Methods, methodGroup.TypeArguments, analyzedArguments, overloadResolutionResult, ref useSiteDiagnostics);
+ OverloadResolution.MethodInvocationOverloadResolution(
+ methods: methodGroup.Methods,
+ typeArguments: methodGroup.TypeArguments,
+ receiver: methodGroup.Receiver,
+ arguments: analyzedArguments,
+ result: overloadResolutionResult,
+ useSiteDiagnostics: ref useSiteDiagnostics);
diagnostics.Add(node, useSiteDiagnostics);
// If overload resolution on the "Invoke" method found an applicable candidate, and one of the arguments
@@ -943,8 +949,9 @@ private BoundCall BindInvocationExpressionContinued(
{
// Since there were no argument errors to report, we report an error on the invocation itself.
string name = (object)delegateTypeOpt == null ? methodName : null;
- result.ReportDiagnostics(this, GetLocationForOverloadResolutionDiagnostic(node, expression), diagnostics, name,
- methodGroup.Receiver, analyzedArguments, methodGroup.Methods.ToImmutable(),
+ result.ReportDiagnostics(
+ binder: this, location: GetLocationForOverloadResolutionDiagnostic(node, expression), nodeOpt: node, diagnostics: diagnostics, name: name,
+ receiver: methodGroup.Receiver, invokedExpression: expression, arguments: analyzedArguments, memberGroup: methodGroup.Methods.ToImmutable(),
typeContainingConstructor: null, delegateTypeBeingInvoked: delegateTypeOpt,
queryClause: queryClause);
}
diff --git a/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs b/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs
index b87a3b4eba052..609dfba587f03 100644
--- a/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs
@@ -807,7 +807,15 @@ private MethodSymbol PerformForEachPatternOverloadResolution(TypeSymbol patternT
OverloadResolutionResult overloadResolutionResult = OverloadResolutionResult.GetInstance();
HashSet useSiteDiagnostics = null;
- this.OverloadResolution.MethodInvocationOverloadResolution(candidateMethods, typeArguments, arguments, overloadResolutionResult, ref useSiteDiagnostics);
+ // We create a dummy receiver of the invocation so MethodInvocationOverloadResolution knows it was invoked from an instance, not a type
+ var dummyReceiver = new BoundImplicitReceiver(_syntax.Expression, patternType);
+ this.OverloadResolution.MethodInvocationOverloadResolution(
+ methods: candidateMethods,
+ typeArguments: typeArguments,
+ receiver: dummyReceiver,
+ arguments: arguments,
+ result: overloadResolutionResult,
+ useSiteDiagnostics: ref useSiteDiagnostics);
diagnostics.Add(_syntax.Expression, useSiteDiagnostics);
MethodSymbol result = null;
diff --git a/src/Compilers/CSharp/Portable/Binder/InMethodBinder.cs b/src/Compilers/CSharp/Portable/Binder/InMethodBinder.cs
index 25786784debab..eb68a032e2c06 100644
--- a/src/Compilers/CSharp/Portable/Binder/InMethodBinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/InMethodBinder.cs
@@ -238,12 +238,8 @@ protected override void AddLookupSymbolsInfoInSingleBinder(LookupSymbolsInfo res
internal static bool ReportConflictWithParameter(Symbol parameter, Symbol newSymbol, string name, Location newLocation, DiagnosticBag diagnostics)
{
var oldLocation = parameter.Locations[0];
-#if PATTERNS_FIXED
Debug.Assert(oldLocation != newLocation || oldLocation == Location.None || newLocation.SourceTree?.GetRoot().ContainsDiagnostics == true,
"same nonempty location refers to different symbols?");
-#else
- if (oldLocation == newLocation) return false;
-#endif
SymbolKind parameterKind = parameter.Kind;
// Quirk of the way we represent lambda parameters.
diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs
index 8753c001b9551..051303c722d0e 100644
--- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs
@@ -71,7 +71,8 @@ private static MethodGroupResolution ResolveDelegateMethodGroup(Binder binder, B
{
var analyzedArguments = AnalyzedArguments.GetInstance();
GetDelegateArguments(source.Syntax, analyzedArguments, delegateInvokeMethodOpt.Parameters, binder.Compilation);
- var resolution = binder.ResolveMethodGroup(source, analyzedArguments, isMethodGroupConversion: true, ref useSiteDiagnostics, inferWithDynamic: true);
+ var resolution = binder.ResolveMethodGroup(source, analyzedArguments, useSiteDiagnostics: ref useSiteDiagnostics, inferWithDynamic: true,
+ isMethodGroupConversion: true, returnRefKind: delegateInvokeMethodOpt.RefKind, returnType: delegateInvokeMethodOpt.ReturnType);
analyzedArguments.Free();
return resolution;
}
@@ -165,10 +166,13 @@ public static bool ReportDelegateMethodGroupDiagnostics(Binder binder, BoundMeth
{
var overloadDiagnostics = DiagnosticBag.GetInstance();
- result.ReportDiagnostics(binder, expr.Syntax.Location, overloadDiagnostics,
- expr.Name,
- resolution.MethodGroup.Receiver, resolution.AnalyzedArguments, resolution.MethodGroup.Methods.ToImmutable(),
- typeContainingConstructor: null, delegateTypeBeingInvoked: null, isMethodGroupConversion: true);
+ result.ReportDiagnostics(
+ binder: binder, location: expr.Syntax.Location, nodeOpt: expr.Syntax, diagnostics: overloadDiagnostics,
+ name: expr.Name,
+ receiver: resolution.MethodGroup.Receiver, invokedExpression: expr.Syntax, arguments: resolution.AnalyzedArguments,
+ memberGroup: resolution.MethodGroup.Methods.ToImmutable(),
+ typeContainingConstructor: null, delegateTypeBeingInvoked: null,
+ isMethodGroupConversion: true, returnRefKind: invokeMethodOpt?.RefKind, delegateType: targetType);
if (!overloadDiagnostics.IsEmptyWithoutResolution)
{
@@ -189,12 +193,21 @@ public Conversion MethodGroupConversion(SyntaxNode syntax, MethodGroup methodGro
{
var analyzedArguments = AnalyzedArguments.GetInstance();
var result = OverloadResolutionResult.GetInstance();
+ var delegateInvokeMethod = delegateType.DelegateInvokeMethod;
- Debug.Assert((object)delegateType.DelegateInvokeMethod != null && !delegateType.DelegateInvokeMethod.HasUseSiteError,
+ Debug.Assert((object)delegateInvokeMethod != null && !delegateInvokeMethod.HasUseSiteError,
"This method should only be called for valid delegate types");
- GetDelegateArguments(syntax, analyzedArguments, delegateType.DelegateInvokeMethod.Parameters, Compilation);
+ GetDelegateArguments(syntax, analyzedArguments, delegateInvokeMethod.Parameters, Compilation);
_binder.OverloadResolution.MethodInvocationOverloadResolution(
- methodGroup.Methods, methodGroup.TypeArguments, analyzedArguments, result, ref useSiteDiagnostics, isMethodGroupConversion: true);
+ methods: methodGroup.Methods,
+ typeArguments: methodGroup.TypeArguments,
+ receiver: methodGroup.Receiver,
+ arguments: analyzedArguments,
+ result: result,
+ useSiteDiagnostics: ref useSiteDiagnostics,
+ isMethodGroupConversion: true,
+ returnRefKind: delegateInvokeMethod.RefKind,
+ returnType: delegateInvokeMethod.ReturnType);
var conversion = ToConversion(result, methodGroup, delegateType);
analyzedArguments.Free();
diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MemberAnalysisResult.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MemberAnalysisResult.cs
index f04fae2774315..ae3a9d22c7159 100644
--- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MemberAnalysisResult.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MemberAnalysisResult.cs
@@ -1,8 +1,11 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+using System;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Symbols;
+using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp
@@ -14,6 +17,7 @@ internal struct MemberAnalysisResult
public readonly ImmutableArray ConversionsOpt;
public readonly ImmutableArray BadArgumentsOpt;
public readonly ImmutableArray ArgsToParamsOpt;
+ public readonly ImmutableArray ConstraintFailureDiagnostics;
public readonly int BadParameter;
public readonly MemberResolutionKind Kind;
@@ -24,18 +28,14 @@ internal struct MemberAnalysisResult
///
public readonly bool HasAnyRefOmittedArgument;
- private MemberAnalysisResult(MemberResolutionKind kind)
- : this(kind, default(ImmutableArray), default(ImmutableArray), default(ImmutableArray))
- {
- }
-
private MemberAnalysisResult(
MemberResolutionKind kind,
- ImmutableArray badArgumentsOpt,
- ImmutableArray argsToParamsOpt,
- ImmutableArray conversionsOpt,
+ ImmutableArray badArgumentsOpt = default,
+ ImmutableArray argsToParamsOpt = default,
+ ImmutableArray conversionsOpt = default,
int missingParameter = -1,
- bool hasAnyRefOmittedArgument = false)
+ bool hasAnyRefOmittedArgument = false,
+ ImmutableArray constraintFailureDiagnosticsOpt = default)
{
this.Kind = kind;
this.BadArgumentsOpt = badArgumentsOpt;
@@ -43,6 +43,7 @@ private MemberAnalysisResult(
this.ConversionsOpt = conversionsOpt;
this.BadParameter = missingParameter;
this.HasAnyRefOmittedArgument = hasAnyRefOmittedArgument;
+ this.ConstraintFailureDiagnostics = constraintFailureDiagnosticsOpt.NullToEmpty();
}
public override bool Equals(object obj)
@@ -164,45 +165,34 @@ public static MemberAnalysisResult NameUsedForPositional(int argumentPosition)
{
return new MemberAnalysisResult(
MemberResolutionKind.NameUsedForPositional,
- ImmutableArray.Create(argumentPosition),
- default(ImmutableArray),
- default(ImmutableArray));
+ badArgumentsOpt: ImmutableArray.Create(argumentPosition));
}
public static MemberAnalysisResult BadNonTrailingNamedArgument(int argumentPosition)
{
return new MemberAnalysisResult(
MemberResolutionKind.BadNonTrailingNamedArgument,
- ImmutableArray.Create(argumentPosition),
- default(ImmutableArray),
- default(ImmutableArray));
+ badArgumentsOpt: ImmutableArray.Create(argumentPosition));
}
public static MemberAnalysisResult NoCorrespondingParameter(int argumentPosition)
{
return new MemberAnalysisResult(
MemberResolutionKind.NoCorrespondingParameter,
- ImmutableArray.Create(argumentPosition),
- default(ImmutableArray),
- default(ImmutableArray));
+ badArgumentsOpt: ImmutableArray.Create(argumentPosition));
}
public static MemberAnalysisResult NoCorrespondingNamedParameter(int argumentPosition)
{
return new MemberAnalysisResult(
MemberResolutionKind.NoCorrespondingNamedParameter,
- ImmutableArray.Create(argumentPosition),
- default(ImmutableArray),
- default(ImmutableArray));
+ badArgumentsOpt: ImmutableArray.Create(argumentPosition));
}
public static MemberAnalysisResult RequiredParameterMissing(int parameterPosition)
{
return new MemberAnalysisResult(
MemberResolutionKind.RequiredParameterMissing,
- default(ImmutableArray),
- default(ImmutableArray),
- default(ImmutableArray),
missingParameter: parameterPosition);
}
@@ -242,16 +232,28 @@ public static MemberAnalysisResult TypeInferenceExtensionInstanceArgumentFailed(
return new MemberAnalysisResult(MemberResolutionKind.TypeInferenceExtensionInstanceArgument);
}
+ public static MemberAnalysisResult StaticInstanceMismatch()
+ {
+ return new MemberAnalysisResult(MemberResolutionKind.StaticInstanceMismatch);
+ }
+
public static MemberAnalysisResult ConstructedParameterFailedConstraintsCheck(int parameterPosition)
{
return new MemberAnalysisResult(
MemberResolutionKind.ConstructedParameterFailedConstraintCheck,
- default(ImmutableArray),
- default(ImmutableArray),
- default(ImmutableArray),
missingParameter: parameterPosition);
}
+ public static MemberAnalysisResult WrongRefKind()
+ {
+ return new MemberAnalysisResult(MemberResolutionKind.WrongRefKind);
+ }
+
+ public static MemberAnalysisResult WrongReturnType()
+ {
+ return new MemberAnalysisResult(MemberResolutionKind.WrongReturnType);
+ }
+
public static MemberAnalysisResult LessDerived()
{
return new MemberAnalysisResult(MemberResolutionKind.LessDerived);
@@ -276,5 +278,10 @@ public static MemberAnalysisResult Worst()
{
return new MemberAnalysisResult(MemberResolutionKind.Worst);
}
+
+ internal static MemberAnalysisResult ConstraintFailure(ImmutableArray constraintFailureDiagnostics)
+ {
+ return new MemberAnalysisResult(MemberResolutionKind.ConstraintFailure, constraintFailureDiagnosticsOpt: constraintFailureDiagnostics);
+ }
}
}
diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MemberResolutionKind.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MemberResolutionKind.cs
index d4cb85d243311..7d92f3075402a 100644
--- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MemberResolutionKind.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MemberResolutionKind.cs
@@ -93,10 +93,31 @@ internal enum MemberResolutionKind : byte
TypeInferenceExtensionInstanceArgument,
///
- /// The candidate member was rejected because it a constraint on a type parameter was not satisfied.
+ /// The candidate member was rejected because a constraint on the type of a parameter was not satisfied.
///
ConstructedParameterFailedConstraintCheck,
+ ///
+ /// The candidate method's type arguments do not satisfy their constraints.
+ ///
+ ConstraintFailure,
+
+ ///
+ /// The candidate member was rejected because it was an instance member accessed from a type,
+ /// or a static member accessed from an instance.
+ ///
+ StaticInstanceMismatch,
+
+ ///
+ /// The candidate method in a delegate conversion was rejected because the ref kind of its return does not match the delegate.
+ ///
+ WrongRefKind,
+
+ ///
+ /// The candidate method in a delegate conversion was rejected because its return type does not match the return type of the delegate.
+ ///
+ WrongReturnType,
+
///
/// The candidate member was rejected because another member further down in the inheritance hierarchy was
/// present.
diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs
index d6169a8534b8e..ed26a29d69481 100644
--- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs
@@ -1320,10 +1320,11 @@ private bool MethodGroupReturnTypeInference(Binder binder, BoundExpression sourc
// this part of the code is only called if the targetType has an unfixed type argument in the output
// type, which is not the case for invalid delegate invoke methods.
- Debug.Assert((object)delegateType.DelegateInvokeMethod != null && !delegateType.DelegateInvokeMethod.HasUseSiteError,
+ var delegateInvokeMethod = delegateType.DelegateInvokeMethod;
+ Debug.Assert((object)delegateInvokeMethod != null && !delegateType.DelegateInvokeMethod.HasUseSiteError,
"This method should only be called for valid delegate types");
- TypeSymbol delegateReturnType = delegateType.DelegateInvokeMethod.ReturnType;
+ TypeSymbol delegateReturnType = delegateInvokeMethod.ReturnType;
if ((object)delegateReturnType == null || delegateReturnType.SpecialType == SpecialType.System_Void)
{
return false;
@@ -1337,7 +1338,7 @@ private bool MethodGroupReturnTypeInference(Binder binder, BoundExpression sourc
return false;
}
- var returnType = MethodGroupReturnType(binder, (BoundMethodGroup)source, fixedDelegateParameters, ref useSiteDiagnostics);
+ var returnType = MethodGroupReturnType(binder, (BoundMethodGroup)source, fixedDelegateParameters, delegateInvokeMethod.RefKind, ref useSiteDiagnostics);
if ((object)returnType == null || returnType.SpecialType == SpecialType.System_Void)
{
return false;
@@ -1348,12 +1349,19 @@ private bool MethodGroupReturnTypeInference(Binder binder, BoundExpression sourc
return true;
}
- private static TypeSymbol MethodGroupReturnType(Binder binder, BoundMethodGroup source, ImmutableArray delegateParameters, ref HashSet useSiteDiagnostics)
+ private static TypeSymbol MethodGroupReturnType(
+ Binder binder, BoundMethodGroup source,
+ ImmutableArray delegateParameters,
+ RefKind delegateRefKind,
+ ref HashSet useSiteDiagnostics)
{
var analyzedArguments = AnalyzedArguments.GetInstance();
Conversions.GetDelegateArguments(source.Syntax, analyzedArguments, delegateParameters, binder.Compilation);
- var resolution = binder.ResolveMethodGroup(source, analyzedArguments, isMethodGroupConversion: true, useSiteDiagnostics: ref useSiteDiagnostics);
+ var resolution = binder.ResolveMethodGroup(source, analyzedArguments, useSiteDiagnostics: ref useSiteDiagnostics,
+ isMethodGroupConversion: true, returnRefKind: delegateRefKind,
+ // Since we are trying to infer the return type, it is not an input to resolving the method group
+ returnType: null);
TypeSymbol type = null;
diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs
index 4ed48bd45b8a1..063646076be75 100644
--- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs
@@ -1,5 +1,6 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
@@ -110,60 +111,77 @@ public void ObjectCreationOverloadResolution(ImmutableArray constr
public void MethodInvocationOverloadResolution(
ArrayBuilder methods,
ArrayBuilder typeArguments,
+ BoundExpression receiver,
AnalyzedArguments arguments,
OverloadResolutionResult result,
ref HashSet useSiteDiagnostics,
bool isMethodGroupConversion = false,
bool allowRefOmittedArguments = false,
bool inferWithDynamic = false,
- bool allowUnexpandedForm = true)
+ bool allowUnexpandedForm = true,
+ RefKind returnRefKind = default,
+ TypeSymbol returnType = null)
{
MethodOrPropertyOverloadResolution(
- methods, typeArguments, arguments, result, isMethodGroupConversion,
+ methods, typeArguments, receiver, arguments, result, isMethodGroupConversion,
allowRefOmittedArguments, ref useSiteDiagnostics, inferWithDynamic: inferWithDynamic,
- allowUnexpandedForm: allowUnexpandedForm);
+ allowUnexpandedForm: allowUnexpandedForm,
+ returnRefKind: returnRefKind,
+ returnType: returnType);
}
// Perform overload resolution on the given property group, with the given arguments and
// names. The names can be null if no names were supplied to any arguments.
public void PropertyOverloadResolution(
ArrayBuilder indexers,
+ BoundExpression receiverOpt,
AnalyzedArguments arguments,
OverloadResolutionResult result,
bool allowRefOmittedArguments,
ref HashSet useSiteDiagnostics)
{
ArrayBuilder typeArguments = ArrayBuilder.GetInstance();
- MethodOrPropertyOverloadResolution(indexers, typeArguments, arguments, result, isMethodGroupConversion: false, allowRefOmittedArguments: allowRefOmittedArguments, useSiteDiagnostics: ref useSiteDiagnostics);
+ MethodOrPropertyOverloadResolution(
+ indexers, typeArguments, receiverOpt, arguments, result, isMethodGroupConversion: false,
+ allowRefOmittedArguments: allowRefOmittedArguments, useSiteDiagnostics: ref useSiteDiagnostics);
typeArguments.Free();
}
internal void MethodOrPropertyOverloadResolution(
ArrayBuilder members,
ArrayBuilder typeArguments,
+ BoundExpression receiver,
AnalyzedArguments arguments,
OverloadResolutionResult result,
bool isMethodGroupConversion,
bool allowRefOmittedArguments,
ref HashSet useSiteDiagnostics,
bool inferWithDynamic = false,
- bool allowUnexpandedForm = true)
+ bool allowUnexpandedForm = true,
+ RefKind returnRefKind = default,
+ TypeSymbol returnType = null)
where TMember : Symbol
{
var results = result.ResultsBuilder;
// First, attempt overload resolution not getting complete results.
PerformMemberOverloadResolution(
- results, members, typeArguments, arguments, false, isMethodGroupConversion,
- allowRefOmittedArguments, ref useSiteDiagnostics, inferWithDynamic: inferWithDynamic,
- allowUnexpandedForm: allowUnexpandedForm);
+ results: results, members: members, typeArguments: typeArguments,
+ receiver: receiver, arguments: arguments, completeResults: false,
+ isMethodGroupConversion: isMethodGroupConversion, returnRefKind: returnRefKind, returnType: returnType,
+ allowRefOmittedArguments: allowRefOmittedArguments, useSiteDiagnostics: ref useSiteDiagnostics,
+ inferWithDynamic: inferWithDynamic, allowUnexpandedForm: allowUnexpandedForm);
if (!OverloadResolutionResultIsValid(results, arguments.HasDynamicArgument))
{
// We didn't get a single good result. Get full results of overload resolution and return those.
result.Clear();
- PerformMemberOverloadResolution(results, members, typeArguments, arguments, true, isMethodGroupConversion,
- allowRefOmittedArguments, ref useSiteDiagnostics, allowUnexpandedForm: allowUnexpandedForm);
+ PerformMemberOverloadResolution(
+ results: results, members: members, typeArguments: typeArguments,
+ receiver: receiver, arguments: arguments, completeResults: true,
+ isMethodGroupConversion: isMethodGroupConversion, returnRefKind: returnRefKind, returnType: returnType,
+ allowRefOmittedArguments: allowRefOmittedArguments, useSiteDiagnostics: ref useSiteDiagnostics,
+ allowUnexpandedForm: allowUnexpandedForm);
}
}
@@ -205,9 +223,12 @@ private void PerformMemberOverloadResolution(
ArrayBuilder> results,
ArrayBuilder members,
ArrayBuilder typeArguments,
+ BoundExpression receiver,
AnalyzedArguments arguments,
bool completeResults,
bool isMethodGroupConversion,
+ RefKind returnRefKind,
+ TypeSymbol returnType,
bool allowRefOmittedArguments,
ref HashSet useSiteDiagnostics,
bool inferWithDynamic = false,
@@ -236,7 +257,7 @@ private void PerformMemberOverloadResolution(
for (int i = 0; i < members.Count; i++)
{
AddMemberToCandidateSet(
- members[i], results, members, typeArguments, arguments, completeResults,
+ members[i], results, members, typeArguments, receiver, arguments, completeResults,
isMethodGroupConversion, allowRefOmittedArguments, containingTypeMapOpt, inferWithDynamic: inferWithDynamic,
useSiteDiagnostics: ref useSiteDiagnostics, allowUnexpandedForm: allowUnexpandedForm);
}
@@ -252,6 +273,18 @@ private void PerformMemberOverloadResolution(
// SPEC: The set of candidate methods is reduced to contain only methods from the most derived types.
RemoveLessDerivedMembers(results, ref useSiteDiagnostics);
+ if (Compilation.LanguageVersion.AllowImprovedOverloadCandidates())
+ {
+ RemoveStaticInstanceMismatches(results, arguments, receiver);
+
+ RemoveConstraintViolations(results);
+
+ if (isMethodGroupConversion)
+ {
+ RemoveDelegateConversionsWithWrongReturnType(results, ref useSiteDiagnostics, returnRefKind, returnType);
+ }
+ }
+
// NB: As in dev12, we do this AFTER removing less derived members.
// Also note that less derived members are not actually removed - they are simply flagged.
ReportUseSiteDiagnostics(results, ref useSiteDiagnostics);
@@ -273,6 +306,151 @@ private void PerformMemberOverloadResolution(
// as that is not part of overload resolution.
}
+ private void RemoveStaticInstanceMismatches(
+ ArrayBuilder> results,
+ AnalyzedArguments arguments,
+ BoundExpression receiverOpt) where TMember : Symbol
+ {
+ // When the feature 'ImprovedOverloadCandidates' is enabled, we do not include instance members when the receiver
+ // is a type, or static members when the receiver is an instance. This does not apply to extension method invocations,
+ // because extension methods are only considered when the receiver is an instance. It also does not apply when the
+ // receiver is a TypeOrValueExpression, which is used to handle the receiver of a Color-Color ambiguity, where either
+ // an instance or a static member would be acceptable.
+ if (arguments.IsExtensionMethodInvocation || Binder.IsTypeOrValueExpression(receiverOpt))
+ {
+ return;
+ }
+
+ bool isImplicitReceiver = Binder.WasImplicitReceiver(receiverOpt);
+ // isStaticContext includes both places where `this` isn't available, and places where it
+ // cannot be used (e.g. a field initializer or a constructor-initializer)
+ bool isStaticContext = !_binder.HasThis(!isImplicitReceiver, out bool inStaticContext) || inStaticContext;
+ if (isImplicitReceiver && !isStaticContext)
+ {
+ return;
+ }
+
+ // We are in a context where only instance (or only static) methods are permitted. We reject the others.
+ bool keepStatic = isImplicitReceiver && isStaticContext || Binder.IsMemberAccessedThroughType(receiverOpt);
+
+ for (int f = 0; f < results.Count; ++f)
+ {
+ var result = results[f];
+ TMember member = result.Member;
+ if (result.Result.IsValid && member.IsStatic != keepStatic)
+ {
+ results[f] = new MemberResolutionResult(member, result.LeastOverriddenMember, MemberAnalysisResult.StaticInstanceMismatch());
+ }
+ }
+ }
+
+ private void RemoveConstraintViolations(ArrayBuilder> results) where TMember : Symbol
+ {
+ // When the feature 'ImprovedOverloadCandidates' is enabled, we do not include methods for which the type arguments
+ // violate the constraints of the method's type parameters.
+
+ // Constraint violations apply to method in a method group, not to properties in a "property group".
+ if (typeof(TMember) != typeof(MethodSymbol))
+ {
+ return;
+ }
+
+ for (int f = 0; f < results.Count; ++f)
+ {
+ var result = results[f];
+ var member = (MethodSymbol)(Symbol)result.Member;
+ // a constraint failure on the method trumps (for reporting purposes) a previously-detected
+ // constraint failure on the constructed type of a parameter
+ if ((result.Result.IsValid || result.Result.Kind == MemberResolutionKind.ConstructedParameterFailedConstraintCheck) &&
+ FailsConstraintChecks(member, out ArrayBuilder constraintFailureDiagnosticsOpt))
+ {
+ results[f] = new MemberResolutionResult(
+ result.Member, result.LeastOverriddenMember,
+ MemberAnalysisResult.ConstraintFailure(constraintFailureDiagnosticsOpt.ToImmutableAndFree()));
+ }
+ }
+ }
+
+ private bool FailsConstraintChecks(MethodSymbol method, out ArrayBuilder constraintFailureDiagnosticsOpt)
+ {
+ if (method.Arity == 0 || method.OriginalDefinition == (object)method)
+ {
+ constraintFailureDiagnosticsOpt = null;
+ return false;
+ }
+
+ var diagnosticsBuilder = ArrayBuilder.GetInstance();
+ ArrayBuilder useSiteDiagnosticsBuilder = null;
+ bool constraintsSatisfied = ConstraintsHelper.CheckMethodConstraints(
+ method,
+ this.Conversions,
+ this.Compilation,
+ diagnosticsBuilder,
+ ref useSiteDiagnosticsBuilder);
+
+ if (!constraintsSatisfied)
+ {
+ if (useSiteDiagnosticsBuilder != null)
+ {
+ diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder);
+ useSiteDiagnosticsBuilder.Free();
+ }
+
+ constraintFailureDiagnosticsOpt = diagnosticsBuilder;
+ return true;
+ }
+
+ diagnosticsBuilder.Free();
+ useSiteDiagnosticsBuilder?.Free();
+ constraintFailureDiagnosticsOpt = null;
+ return false;
+ }
+
+ ///
+ /// Remove candidates to a delegate conversion where the method's return ref kind or return type is wrong.
+ ///
+ /// The ref kind of the delegate's return, if known. This is only unknown in
+ /// error scenarios, such as a delegate type that has no invoke method.
+ /// The return type of the delegate, if known. It isn't
+ /// known when we're attempting to infer the return type of a method group for type inference.
+ private void RemoveDelegateConversionsWithWrongReturnType(
+ ArrayBuilder> results,
+ ref HashSet useSiteDiagnostics,
+ RefKind? returnRefKind,
+ TypeSymbol returnType) where TMember : Symbol
+ {
+ // When the feature 'ImprovedOverloadCandidates' is enabled, then a delegate conversion overload resolution
+ // rejects candidates that have the wrong return ref kind or return type.
+
+ // Delegate conversions apply to method in a method group, not to properties in a "property group".
+ Debug.Assert(typeof(TMember) == typeof(MethodSymbol));
+
+ for (int f = 0; f < results.Count; ++f)
+ {
+ var result = results[f];
+ if (!result.Result.IsValid)
+ {
+ continue;
+ }
+
+ var method = (MethodSymbol)(Symbol)result.Member;
+ bool returnsMatch =
+ (object)returnType == null ||
+ method.ReturnType.Equals(returnType, TypeCompareKind.AllIgnoreOptions) ||
+ returnRefKind == RefKind.None && Conversions.HasIdentityOrImplicitReferenceConversion(method.ReturnType, returnType, ref useSiteDiagnostics);
+ if (!returnsMatch)
+ {
+ results[f] = new MemberResolutionResult(
+ result.Member, result.LeastOverriddenMember, MemberAnalysisResult.WrongReturnType());
+ }
+ else if (method.RefKind != returnRefKind)
+ {
+ results[f] = new MemberResolutionResult(
+ result.Member, result.LeastOverriddenMember, MemberAnalysisResult.WrongRefKind());
+ }
+ }
+ }
+
private static Dictionary> PartitionMembersByContainingType(ArrayBuilder members) where TMember : Symbol
{
Dictionary> containingTypeMap = new Dictionary>();
@@ -424,6 +602,7 @@ private void AddMemberToCandidateSet(
ArrayBuilder> results,
ArrayBuilder members,
ArrayBuilder typeArguments,
+ BoundExpression receiverOpt,
AnalyzedArguments arguments,
bool completeResults,
bool isMethodGroupConversion,
@@ -2943,7 +3122,9 @@ private MemberResolutionResult IsApplicable(
//
// Suppose there is a call M("", null). Type inference infers that T is string.
// M is then not an applicable candidate *NOT* because string violates the
- // constraint on T. That is not checked until "final validation". Rather, the
+ // constraint on T. That is not checked until "final validation" (although when
+ // feature 'ImprovedOverloadCandidates' is enabled in later language versions
+ // it is checked on the candidate before overload resolution). Rather, the
// method is not a candidate because string violates the constraint *on U*.
// The constructed method has formal parameter type X, which is not legal.
// In the case given, the generic method is eliminated and the object version wins.
diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolutionResult.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolutionResult.cs
index ad08d7943b7bf..d9c4206728077 100644
--- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolutionResult.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolutionResult.cs
@@ -6,6 +6,7 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
+using System;
#if DEBUG
using System.Text;
@@ -184,15 +185,19 @@ private static ThreeState TryGetBestResult(ArrayBuilder(
Binder binder,
Location location,
+ SyntaxNode nodeOpt,
DiagnosticBag diagnostics,
string name,
BoundExpression receiver,
+ SyntaxNode invokedExpression,
AnalyzedArguments arguments,
ImmutableArray memberGroup, // the T is just a convenience for the caller
NamedTypeSymbol typeContainingConstructor,
NamedTypeSymbol delegateTypeBeingInvoked,
CSharpSyntaxNode queryClause = null,
- bool isMethodGroupConversion = false) where T : Symbol
+ bool isMethodGroupConversion = false,
+ RefKind? returnRefKind = null,
+ TypeSymbol delegateType = null) where T : Symbol
{
Debug.Assert(!this.Succeeded, "Don't ask for diagnostic info on a successful overload resolution result.");
@@ -257,18 +262,38 @@ internal void ReportDiagnostics(
// do so, then odds are extremely good that the failure is the ultimate cause
// of the overload resolution failing to find any applicable method. Report
// the errors out of each lambda argument, if there were any.
+ // NOTE: There isn't a MemberResolutionKind for this error condition.
if (HadLambdaConversionError(diagnostics, arguments))
{
return;
}
- // NOTE: There isn't a MemberResolutionKind for this error condition.
+ // If there is any instance(or alternatively static) method accessed through a
+ // type(or alternatively expression) then the first such method is the best bad method.
+ // To retain existing behavior, we use the location of the invoked expression for the error.
+
+ if (HadStaticInstanceMismatch(diagnostics, symbols, invokedExpression?.GetLocation() ?? location, binder, receiver, nodeOpt))
+ {
+ return;
+ }
+
+ // When overload resolution is being done to resolve a method group conversion (to a delegate type),
+ // if there is any method being converted to a delegate type, but the method's return
+ // ref kind does not match the delegate, then the first such method is the best bad method.
+ // Otherwise if there is any method whose return type does not match the delegate, then the
+ // first such method is the best bad method
+
+ if (isMethodGroupConversion && returnRefKind != null &&
+ HadReturnMismatch(location, diagnostics, returnRefKind.GetValueOrDefault(), delegateType))
+ {
+ return;
+ }
- // If there is any such method that has a bad conversion or out/ref mismatch
+ // Otherwise, if there is any such method that has a bad argument conversion or out/ref mismatch
// then the first such method found is the best bad method.
- if (HadBadArguments(diagnostics, binder.Compilation, name, arguments, symbols, location, binder.Flags, isMethodGroupConversion))
+ if (HadBadArguments(diagnostics, binder, name, arguments, symbols, location, binder.Flags, isMethodGroupConversion))
{
return;
}
@@ -277,10 +302,19 @@ internal void ReportDiagnostics(
AssertNone(MemberResolutionKind.BadArguments);
// Otherwise, if there is any such method where type inference succeeded but inferred
- // a type that violates its own constraints then the first such method is
+ // type arguments that violate the constraints on the method, then the first such method is
+ // the best bad method.
+
+ if (HadConstraintFailure(location, diagnostics))
+ {
+ return;
+ }
+
+ // Otherwise, if there is any such method where type inference succeeded but inferred
+ // a parameter type that violates its own constraints then the first such method is
// the best bad method.
- if (ConstraintsCheckFailed(binder.Conversions, binder.Compilation, diagnostics, location))
+ if (HadConstructedParameterFailedConstraintCheck(binder.Conversions, binder.Compilation, diagnostics, location))
{
return;
}
@@ -528,6 +562,90 @@ private bool InaccessibleTypeArgument(
return true;
}
+ private bool HadStaticInstanceMismatch(
+ DiagnosticBag diagnostics,
+ ImmutableArray symbols,
+ Location location,
+ Binder binder,
+ BoundExpression receiverOpt,
+ SyntaxNode nodeOpt)
+ {
+ var staticInstanceMismatch = GetFirstMemberKind(MemberResolutionKind.StaticInstanceMismatch);
+ if (staticInstanceMismatch.IsNull)
+ {
+ return false;
+ }
+
+ Symbol symbol = staticInstanceMismatch.Member;
+
+ // Certain compiler-generated invocations produce custom diagnostics.
+ if (receiverOpt?.Kind == BoundKind.QueryClause)
+ {
+ // Could not find an implementation of the query pattern for source type '{0}'. '{1}' not found.
+ diagnostics.Add(ErrorCode.ERR_QueryNoProvider, location, receiverOpt.Type, symbol.Name);
+ }
+ else if (binder.Flags.Includes(BinderFlags.CollectionInitializerAddMethod))
+ {
+ diagnostics.Add(ErrorCode.ERR_InitializerAddHasWrongSignature, location, symbol);
+ }
+ else if (nodeOpt?.Kind() == SyntaxKind.AwaitExpression && symbol.Name == WellKnownMemberNames.GetAwaiter)
+ {
+ diagnostics.Add(ErrorCode.ERR_BadAwaitArg, location, receiverOpt.Type);
+ }
+ else
+ {
+ ErrorCode errorCode =
+ symbol.IsStatic ? ErrorCode.ERR_ObjectProhibited :
+ Binder.WasImplicitReceiver(receiverOpt) && binder.InFieldInitializer && !binder.BindingTopLevelScriptCode ? ErrorCode.ERR_FieldInitRefNonstatic :
+ ErrorCode.ERR_ObjectRequired;
+ // error CS0176: Member 'Program.M(B)' cannot be accessed with an instance reference; qualify it with a type name instead
+ // -or-
+ // error CS0120: An object reference is required for the non-static field, method, or property 'Program.M(B)'
+ diagnostics.Add(new DiagnosticInfoWithSymbols(
+ errorCode,
+ new object[] { symbol },
+ symbols), location);
+ }
+
+ return true;
+ }
+
+ private bool HadReturnMismatch(Location location, DiagnosticBag diagnostics, RefKind refKind, TypeSymbol delegateType)
+ {
+ var mismatch = GetFirstMemberKind(MemberResolutionKind.WrongRefKind);
+ if (!mismatch.IsNull)
+ {
+ diagnostics.Add(ErrorCode.ERR_DelegateRefMismatch, location, mismatch.Member, delegateType);
+ return true;
+ }
+
+ mismatch = GetFirstMemberKind(MemberResolutionKind.WrongReturnType);
+ if (!mismatch.IsNull)
+ {
+ var method = (MethodSymbol)(Symbol)mismatch.Member;
+ diagnostics.Add(ErrorCode.ERR_BadRetType, location, method, method.ReturnType);
+ return true;
+ }
+
+ return false;
+ }
+
+ private bool HadConstraintFailure(Location location, DiagnosticBag diagnostics)
+ {
+ var constraintFailure = GetFirstMemberKind(MemberResolutionKind.ConstraintFailure);
+ if (constraintFailure.IsNull)
+ {
+ return false;
+ }
+
+ foreach (var pair in constraintFailure.Result.ConstraintFailureDiagnostics)
+ {
+ diagnostics.Add(new CSDiagnostic(pair.DiagnosticInfo, location));
+ }
+
+ return true;
+ }
+
private bool TypeInferenceFailed(
Binder binder,
DiagnosticBag diagnostics,
@@ -738,7 +856,7 @@ private static void ReportBadParameterCount(
return;
}
- private bool ConstraintsCheckFailed(
+ private bool HadConstructedParameterFailedConstraintCheck(
ConversionsBase conversions,
Compilation compilation,
DiagnosticBag diagnostics,
@@ -763,8 +881,11 @@ private bool ConstraintsCheckFailed(
// rather that the constraint on *Nullable* is violated; Nullable is not a legal
// type, and so this is not an applicable candidate.
//
- // Checking whether constraints are violated *on T in Q* happens *after* overload resolution
- // successfully chooses a unique best method.
+ // In language versions before the feature 'ImprovedOverloadCandidates' was added to the language,
+ // checking whether constraints are violated *on T in Q* occurs *after* overload resolution
+ // successfully chooses a unique best method; but with the addition of the
+ // feature 'ImprovedOverloadCandidates', constraint checks on the method's own type arguments
+ // occurs during candidate selection.
//
// Note that this failure need not involve type inference; Q(null, null) would also be
// illegal for the same reason.
@@ -851,7 +972,7 @@ private static bool HadLambdaConversionError(DiagnosticBag diagnostics, Analyzed
private bool HadBadArguments(
DiagnosticBag diagnostics,
- Compilation compilation,
+ Binder binder,
string name,
AnalyzedArguments arguments,
ImmutableArray symbols,
@@ -902,15 +1023,15 @@ private bool HadBadArguments(
foreach (var arg in badArg.Result.BadArgumentsOpt)
{
- ReportBadArgumentError(diagnostics, compilation, name, arguments, symbols, location, badArg, method, arg);
+ ReportBadArgumentError(diagnostics, binder, name, arguments, symbols, location, badArg, method, arg);
}
return true;
}
- private static void ReportBadArgumentError(
+ private void ReportBadArgumentError(
DiagnosticBag diagnostics,
- Compilation compilation,
+ Binder binder,
string name,
AnalyzedArguments arguments,
ImmutableArray symbols,
@@ -972,11 +1093,18 @@ private static void ReportBadArgumentError(
argument.Kind != BoundKind.OutVariablePendingInference &&
argument.Kind != BoundKind.DiscardExpression)
{
+ TypeSymbol parameterType = UnwrapIfParamsArray(parameter, isLastParameter) is TypeSymbol t ? t : parameter.Type;
+
// If the problem is that a lambda isn't convertible to the given type, also report why.
// The argument and parameter type might match, but may not have same in/out modifiers
if (argument.Kind == BoundKind.UnboundLambda && refArg == refParameter)
{
- ((UnboundLambda)argument).GenerateAnonymousFunctionConversionError(diagnostics, parameter.Type);
+ ((UnboundLambda)argument).GenerateAnonymousFunctionConversionError(diagnostics, parameterType);
+ }
+ else if (argument.Kind == BoundKind.MethodGroup && parameterType.TypeKind == TypeKind.Delegate &&
+ Conversions.ReportDelegateMethodGroupDiagnostics(binder, (BoundMethodGroup)argument, parameterType, diagnostics))
+ {
+ // a diagnostic has been reported by ReportDelegateMethodGroupDiagnostics
}
else
{
@@ -1053,7 +1181,7 @@ private static void ReportBadArgumentError(
isParams: false,
refKind: refArg);
- SymbolDistinguisher distinguisher = new SymbolDistinguisher(compilation, displayArg, UnwrapIfParamsArray(parameter, isLastParameter));
+ SymbolDistinguisher distinguisher = new SymbolDistinguisher(binder.Compilation, displayArg, UnwrapIfParamsArray(parameter, isLastParameter));
// CS1503: Argument {0}: cannot convert from '{1}' to '{2}'
diagnostics.Add(
diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs
index 4f5b1d799f80c..4a02efdaa4c87 100644
--- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs
+++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs
@@ -4841,7 +4841,7 @@ internal static string ERR_FloatOverflow {
}
///
- /// Looks up a localized string similar to foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public definition for '{1}'.
+ /// Looks up a localized string similar to foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'.
///
internal static string ERR_ForEachMissingMember {
get {
diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx
index 3178e2140048f..b7d744c72165f 100644
--- a/src/Compilers/CSharp/Portable/CSharpResources.resx
+++ b/src/Compilers/CSharp/Portable/CSharpResources.resx
@@ -2604,7 +2604,7 @@ A catch() block after a catch (System.Exception e) block can catch non-CLS excep
#r is only allowed in scripts
- foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public definition for '{1}'
+ foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'Invalid type for parameter {0} in XML comment cref attribute: '{1}'
diff --git a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs
index 302d7bbc5040e..62ad5fa5cc387 100644
--- a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs
+++ b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs
@@ -49,7 +49,7 @@ public static void AddToMap(BoundNode root, Dictionary= MessageID.IDS_FeatureAttributesOnBackingFields.RequiredVersion();
}
+
+ internal static bool AllowImprovedOverloadCandidates(this LanguageVersion self)
+ {
+ return self >= MessageID.IDS_FeatureImprovedOverloadCandidates.RequiredVersion();
+ }
}
}
diff --git a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs
index e6076dff7deea..2c22277f35828 100644
--- a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs
@@ -613,8 +613,7 @@ public static bool CheckConstraints(
ConversionsBase conversions,
SyntaxNode syntaxNode,
Compilation currentCompilation,
- DiagnosticBag diagnostics,
- BitVector skipParameters = default(BitVector))
+ DiagnosticBag diagnostics)
{
if (!RequiresChecking(method))
{
@@ -623,7 +622,7 @@ public static bool CheckConstraints(
var diagnosticsBuilder = ArrayBuilder.GetInstance();
ArrayBuilder useSiteDiagnosticsBuilder = null;
- var result = CheckMethodConstraints(method, conversions, currentCompilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder, skipParameters);
+ var result = CheckMethodConstraints(method, conversions, currentCompilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder);
if (useSiteDiagnosticsBuilder != null)
{
@@ -688,7 +687,7 @@ private static bool CheckTypeConstraints(
ref useSiteDiagnosticsBuilder);
}
- private static bool CheckMethodConstraints(
+ public static bool CheckMethodConstraints(
MethodSymbol method,
ConversionsBase conversions,
Compilation currentCompilation,
@@ -774,6 +773,7 @@ private static bool CheckConstraints(
HashSet ignoreTypeConstraintsDependentOnTypeParametersOpt)
{
Debug.Assert(substitution != null);
+
// The type parameters must be original definitions of type parameters from the containing symbol.
Debug.Assert(ReferenceEquals(typeParameter.ContainingSymbol, containingSymbol.OriginalDefinition));
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
index 295b41afcae2e..acc94c24d0715 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
@@ -4141,8 +4141,8 @@ Blok catch() po bloku catch (System.Exception e) může zachytit výjimky, kter
- foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public definition for '{1}'
- Příkaz foreach nejde použít pro proměnné typu {0}, protože {0} neobsahuje veřejnou definici pro {1}.
+ foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'
+ Příkaz foreach nejde použít pro proměnné typu {0}, protože {0} neobsahuje veřejnou definici pro {1}.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
index f83a782a786fa..7b87e16901634 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
@@ -4141,8 +4141,8 @@ Ein catch()-Block nach einem catch (System.Exception e)-Block kann nicht-CLS-Aus
- foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public definition for '{1}'
- Eine foreach-Anweisung kann nicht für Variablen vom Typ "{0}" verwendet werden, da "{0}" keine öffentliche Definition für "{1}" enthält.
+ foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'
+ Eine foreach-Anweisung kann nicht für Variablen vom Typ "{0}" verwendet werden, da "{0}" keine öffentliche Definition für "{1}" enthält.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
index 8d4feb9eacc7e..263153c19ae24 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
@@ -4141,8 +4141,8 @@ Un bloque catch() después de un bloque catch (System.Exception e) puede abarcar
- foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public definition for '{1}'
- La instrucción foreach no puede funcionar en variables de tipo '{0}' porque '{0}' no contiene ninguna definición pública para '{1}'
+ foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'
+ La instrucción foreach no puede funcionar en variables de tipo '{0}' porque '{0}' no contiene ninguna definición pública para '{1}'
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
index 4bd455eb0860a..2f256d8c4bad6 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
@@ -4141,8 +4141,8 @@ Un bloc catch() après un bloc catch (System.Exception e) peut intercepter des e
- foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public definition for '{1}'
- L'instruction foreach ne peut pas fonctionner sur des variables de type '{0}', car '{0}' ne contient pas de définition publique pour '{1}'
+ foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'
+ L'instruction foreach ne peut pas fonctionner sur des variables de type '{0}', car '{0}' ne contient pas de définition publique pour '{1}'
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
index 6b71e3ed4adcf..4ab1dc95b0aba 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
@@ -4141,8 +4141,8 @@ Un blocco catch() dopo un blocco catch (System.Exception e) è in grado di rilev
- foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public definition for '{1}'
- L'istruzione foreach non può funzionare con variabili di tipo '{0}' perché '{0}' non contiene una definizione pubblica per '{1}'
+ foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'
+ L'istruzione foreach non può funzionare con variabili di tipo '{0}' perché '{0}' non contiene una definizione pubblica per '{1}'
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
index b0ba89a18fde3..935b77d9d8397 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
@@ -4141,8 +4141,8 @@ AssemblyInfo.cs ファイルで RuntimeCompatibilityAttribute が false に設
- foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public definition for '{1}'
- foreach ステートメントは、'{0}' が '{1}' のパブリック定義を含んでいないため、型 '{0}' の変数に対して使用できません。
+ foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'
+ foreach ステートメントは、'{0}' が '{1}' のパブリック定義を含んでいないため、型 '{0}' の変数に対して使用できません。
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
index 5964ba1d21d98..053a848aee946 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
@@ -4141,8 +4141,8 @@ catch (System.Exception e) 블록 뒤의 catch() 블록은 RuntimeCompatibilityA
- foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public definition for '{1}'
- {0}'에는 '{1}'에 대한 공용 정의가 포함되어 있지 않아 '{0}' 형식 변수에서 foreach 문을 수행할 수 없습니다.
+ foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'
+ {0}'에는 '{1}'에 대한 공용 정의가 포함되어 있지 않아 '{0}' 형식 변수에서 foreach 문을 수행할 수 없습니다.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
index 3fa8d88eb9e3c..f4a8f3e6859de 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
@@ -4141,8 +4141,8 @@ Blok catch() po bloku catch (System.Exception e) może przechwytywać wyjątki n
- foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public definition for '{1}'
- Instrukcja foreach nie może operować na zmiennych typu „{0}”, ponieważ „{0}” nie zawiera definicji publicznej elementu „{1}”
+ foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'
+ Instrukcja foreach nie może operować na zmiennych typu „{0}”, ponieważ „{0}” nie zawiera definicji publicznej elementu „{1}”
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
index 8da7eec0a3595..201e1b77935a2 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
@@ -4141,8 +4141,8 @@ Um bloco catch() depois de um bloco catch (System.Exception e) poderá capturar
- foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public definition for '{1}'
- Instrução foreach não pode operar em variáveis do tipo "{0}" porque "{0}" não contém uma definição pública para "{1}"
+ foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'
+ Instrução foreach não pode operar em variáveis do tipo "{0}" porque "{0}" não contém uma definição pública para "{1}"
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
index 395bfa09caa9e..d44eeb2c221e0 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
@@ -4141,8 +4141,8 @@ A catch() block after a catch (System.Exception e) block can catch non-CLS excep
- foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public definition for '{1}'
- Оператор foreach не работает с переменными типа "{0}", так как "{0}" не содержит открытого определения для "{1}".
+ foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'
+ Оператор foreach не работает с переменными типа "{0}", так как "{0}" не содержит открытого определения для "{1}".
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
index d0f8bdb24ce06..cc734920e8e4a 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
@@ -4141,8 +4141,8 @@ RuntimeCompatibilityAttribute AssemblyInfo.cs dosyasında false olarak ayarlanm
- foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public definition for '{1}'
- {0}' bir '{1}' ortak tanım içermediğinden veya erişilemez olduğundan foreach deyimi '{0}' türündeki değişkenlerde çalışamaz
+ foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'
+ {0}' bir '{1}' ortak tanım içermediğinden veya erişilemez olduğundan foreach deyimi '{0}' türündeki değişkenlerde çalışamaz
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
index a6567020b924a..4278b44d63ace 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
@@ -4141,8 +4141,8 @@ A catch() block after a catch (System.Exception e) block can catch non-CLS excep
- foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public definition for '{1}'
- “{0}”不包含“{1}”的公共定义,因此 foreach 语句不能作用于“{0}”类型的变量
+ foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'
+ “{0}”不包含“{1}”的公共定义,因此 foreach 语句不能作用于“{0}”类型的变量
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
index 862c51a1a77e7..a6f7959aff069 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
@@ -4141,8 +4141,8 @@ A catch() block after a catch (System.Exception e) block can catch non-CLS excep
- foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public definition for '{1}'
- foreach 陳述式不可用在類型 '{0}' 的變數上,因為 '{0}' 未包含 '{1}' 的公用定義。
+ foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'
+ foreach 陳述式不可用在類型 '{0}' 的變數上,因為 '{0}' 未包含 '{1}' 的公用定義。
diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs
index 250f664a211a5..9b93f09a20580 100644
--- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs
+++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs
@@ -4234,19 +4234,19 @@ public static void Run()
CreateCompilationWithMscorlibAndSystemCore(source).VerifyDiagnostics(
// (9,105): error CS1525: Invalid expression term 'int'
// genD = (D) GenericMethod<((System.Linq.Expressions.Expression>)(() => int)).Compile()()>
- Diagnostic(ErrorCode.ERR_InvalidExprTerm, "int").WithArguments("int"),
+ Diagnostic(ErrorCode.ERR_InvalidExprTerm, "int").WithArguments("int").WithLocation(9, 105),
// (9,123): error CS1525: Invalid expression term '}'
// genD = (D) GenericMethod<((System.Linq.Expressions.Expression>)(() => int)).Compile()()>
- Diagnostic(ErrorCode.ERR_InvalidExprTerm, "").WithArguments("}"),
+ Diagnostic(ErrorCode.ERR_InvalidExprTerm, "").WithArguments("}").WithLocation(9, 123),
// (8,9): error CS0246: The type or namespace name 'Goo' could not be found (are you missing a using directive or an assembly reference?)
// Goo f = new Goo {
- Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Goo").WithArguments("Goo"),
+ Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Goo").WithArguments("Goo").WithLocation(8, 9),
// (8,21): error CS0246: The type or namespace name 'Goo' could not be found (are you missing a using directive or an assembly reference?)
// Goo f = new Goo {
- Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Goo").WithArguments("Goo"),
- // (9,20): error CS0030: Cannot convert type 'method' to 'MemberInitializerTest.D'
+ Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Goo").WithArguments("Goo").WithLocation(8, 21),
+ // (9,29): error CS0411: The type arguments for method 'MemberInitializerTest.GenericMethod()' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// genD = (D) GenericMethod<((System.Linq.Expressions.Expression>)(() => int)).Compile()()>
- Diagnostic(ErrorCode.ERR_NoExplicitConv, "(D) GenericMethod").WithArguments("method", "MemberInitializerTest.D"));
+ Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "GenericMethod").WithArguments("MemberInitializerTest.GenericMethod()").WithLocation(9, 29));
}
[WorkItem(545191, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545191")]
diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenRefReturnTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenRefReturnTests.cs
index d584968000e0e..51df283a33f3b 100644
--- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenRefReturnTests.cs
+++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenRefReturnTests.cs
@@ -2784,6 +2784,14 @@ static void Main()
}
}";
+ CreateStandardCompilation(source, parseOptions: TestOptions.WithoutImprovedOverloadCandidates).VerifyDiagnostics(
+ // (24,13): error CS8189: Ref mismatch between 'A.F()' and delegate 'D'
+ // B.F(o.F, 2);
+ Diagnostic(ErrorCode.ERR_DelegateRefMismatch, "o.F").WithArguments("A.F()", "D").WithLocation(24, 13),
+ // (26,24): error CS8189: Ref mismatch between 'A.F()' and delegate 'D'
+ // B.F(new D(o.F), 3);
+ Diagnostic(ErrorCode.ERR_DelegateRefMismatch, "o.F").WithArguments("A.F()", "D").WithLocation(26, 24)
+ );
CreateStandardCompilation(source).VerifyDiagnostics(
// (24,13): error CS8189: Ref mismatch between 'A.F()' and delegate 'D'
// B.F(o.F, 2);
@@ -2828,6 +2836,14 @@ static void Main()
}
}";
+ CreateStandardCompilation(source, parseOptions: TestOptions.WithoutImprovedOverloadCandidates).VerifyDiagnostics(
+ // (23,13): error CS8189: Ref mismatch between 'A.F()' and delegate 'D'
+ // B.F(o.F, 2);
+ Diagnostic(ErrorCode.ERR_DelegateRefMismatch, "o.F").WithArguments("A.F()", "D").WithLocation(23, 13),
+ // (25,24): error CS8189: Ref mismatch between 'A.F()' and delegate 'D'
+ // B.F(new D(o.F), 3);
+ Diagnostic(ErrorCode.ERR_DelegateRefMismatch, "o.F").WithArguments("A.F()", "D").WithLocation(25, 24)
+ );
CreateStandardCompilation(source).VerifyDiagnostics(
// (23,13): error CS8189: Ref mismatch between 'A.F()' and delegate 'D'
// B.F(o.F, 2);
@@ -3301,7 +3317,7 @@ static void Main()
";
- CreateCompilationWithMscorlib45AndCSruntime(source).VerifyEmitDiagnostics(
+ CreateCompilationWithMscorlib45AndCSruntime(source, parseOptions: TestOptions.WithoutImprovedOverloadCandidates).VerifyEmitDiagnostics(
// (10,30): error CS0407: 'string Program.M1()' has the wrong return type
// RefFunc1