From f8ac7b99037ea05ca13716f4c924070230605d46 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Thu, 28 Dec 2023 08:28:46 -0800 Subject: [PATCH 1/4] Params Collections - Adjust binding in presence of dynamic arguments Implements changes proposed in https://github.com/dotnet/csharplang/pull/7792. --- .../RemoveUnnecessaryCastTests.cs | 26 +- .../Portable/Binder/Binder.ValueChecks.cs | 2 +- .../Portable/Binder/Binder_Attributes.cs | 10 +- .../Portable/Binder/Binder_Conversions.cs | 113 +- .../Portable/Binder/Binder_Deconstruct.cs | 2 +- .../Portable/Binder/Binder_Expressions.cs | 692 ++++-- .../Portable/Binder/Binder_Invocation.cs | 327 ++- .../CSharp/Portable/Binder/Binder_Query.cs | 2 +- .../Portable/Binder/Binder_Statements.cs | 2 +- .../Portable/Binder/ForEachLoopBinder.cs | 5 +- .../Semantics/Conversions/Conversions.cs | 12 +- .../OverloadResolution/MethodTypeInference.cs | 6 +- .../OverloadResolution/OverloadResolution.cs | 270 ++- .../CSharp/Portable/CSharpResources.resx | 24 + .../CSharp/Portable/Errors/ErrorCode.cs | 6 + .../CSharp/Portable/Errors/ErrorFacts.cs | 9 + .../Generated/ErrorFacts.Generated.cs | 3 + .../LocalRewriter_StringInterpolation.cs | 4 +- .../Lowering/SyntheticBoundNodeFactory.cs | 8 +- .../Portable/Symbols/SymbolExtensions.cs | 2 +- .../Portable/xlf/CSharpResources.cs.xlf | 40 + .../Portable/xlf/CSharpResources.de.xlf | 40 + .../Portable/xlf/CSharpResources.es.xlf | 40 + .../Portable/xlf/CSharpResources.fr.xlf | 40 + .../Portable/xlf/CSharpResources.it.xlf | 40 + .../Portable/xlf/CSharpResources.ja.xlf | 40 + .../Portable/xlf/CSharpResources.ko.xlf | 40 + .../Portable/xlf/CSharpResources.pl.xlf | 40 + .../Portable/xlf/CSharpResources.pt-BR.xlf | 40 + .../Portable/xlf/CSharpResources.ru.xlf | 40 + .../Portable/xlf/CSharpResources.tr.xlf | 40 + .../Portable/xlf/CSharpResources.zh-Hans.xlf | 40 + .../Portable/xlf/CSharpResources.zh-Hant.xlf | 40 + .../Test/Emit/CodeGen/CodeGenDynamicTests.cs | 284 ++- .../CodeGenShortCircuitOperatorTests.cs | 7 + .../CSharp/Test/Emit/CodeGen/CodeGenTests.cs | 71 +- .../Test/Emit/PDB/PDBDynamicLocalsTests.cs | 19 +- .../Emit2/Semantics/ParamsCollectionTests.cs | 2110 +++++++++++++++++ .../Semantics/PrimaryConstructorTests.cs | 6 +- .../Test/Emit2/Semantics/RecordTests.cs | 6 +- .../Semantics/RefReadonlyParameterTests.cs | 71 +- ...onTests_IDynamicIndexerAccessExpression.cs | 19 +- ...ationTests_IDynamicInvocationExpression.cs | 40 +- ...nTests_IDynamicObjectCreationExpression.cs | 18 +- ...ationTests_IInterpolatedStringOperation.cs | 11 +- ...perationTests_IObjectCreationExpression.cs | 13 + .../Test/Semantic/Semantics/DynamicTests.cs | 106 +- .../Semantic/Semantics/InterpolationTests.cs | 83 +- .../Semantic/Semantics/LocalFunctionTests.cs | 12 +- .../NonTrailingNamedArgumentsTests.cs | 44 +- .../Semantics/NullableReferenceTypesTests.cs | 36 +- .../RawInterpolationTests_Handler.cs | 17 +- .../Semantic/Semantics/SemanticErrorTests.cs | 206 +- ...nticModelGetSemanticInfoTests_LateBound.cs | 173 +- .../Test/Syntax/Diagnostics/DiagnosticTest.cs | 3 + .../Test/ExpressionCompiler/DynamicTests.cs | 7 + .../RemoveUnnecessaryCastTests_AsTests.cs | 24 +- .../SimplifyTypeNamesTests.cs | 18 +- 58 files changed, 4739 insertions(+), 710 deletions(-) diff --git a/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs b/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs index 6cac2c66dbdae..5c025934f6835 100644 --- a/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs +++ b/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs @@ -4532,6 +4532,11 @@ static bool Goo(int x, object y, object z) { return true; } + + static bool Goo(long x, object y, object z) + { + return true; + } } """; @@ -4568,7 +4573,19 @@ class C { } } - + + int this[long x, object s, object d] + { + get + { + return 0; + } + + set + { + } + } + void Goo(dynamic xx) { var y = this[x: xx, s: "", d: (object)""]; @@ -4681,7 +4698,12 @@ static bool Goo(object y, int x, object z) { return true; } - } + + static bool Goo(object y, long x, object z) + { + return true; + } + } """; await VerifyCS.VerifyCodeFixAsync(source, source); diff --git a/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs b/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs index 0c63912c6f438..9509ad57fd5cc 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs @@ -474,7 +474,7 @@ private BoundExpression CheckValue(BoundExpression expr, BindValueKind valueKind { var methodGroup = (BoundMethodGroup)expr; CompoundUseSiteInfo useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics); - var resolution = this.ResolveMethodGroup(methodGroup, analyzedArguments: null, isMethodGroupConversion: false, useSiteInfo: ref useSiteInfo); + var resolution = this.ResolveMethodGroup(methodGroup, analyzedArguments: null, useSiteInfo: ref useSiteInfo, options: OverloadResolution.Options.None); diagnostics.Add(expr.Syntax, useSiteInfo); Symbol otherSymbol = null; bool resolvedToMethodGroup = resolution.MethodGroup != null; diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Attributes.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Attributes.cs index befc13329b9b2..c4f4d432714ce 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Attributes.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Attributes.cs @@ -204,7 +204,15 @@ private BoundAttribute BindAttributeCore(AttributeSyntax node, NamedTypeSymbol a out var memberResolutionResult, out var candidateConstructors, allowProtectedConstructorsOfBaseType: true, - suppressUnsupportedRequiredMembersError: false); + out CompoundUseSiteInfo overloadResolutionUseSiteInfo); + + ReportConstructorUseSiteDiagnostics(node.Location, diagnostics, suppressUnsupportedRequiredMembersError: false, in overloadResolutionUseSiteInfo); + + if (memberResolutionResult.IsNotNull) + { + this.CheckAndCoerceArguments(memberResolutionResult, analyzedArguments.ConstructorArguments, diagnostics, receiver: null, invokedAsExtensionMethod: false); + } + attributeConstructor = memberResolutionResult.Member; expanded = memberResolutionResult.Resolution == MemberResolutionKind.ApplicableInExpandedForm; argsToParamsOpt = memberResolutionResult.Result.ArgsToParamsOpt; diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs index 1bf2439c22ac2..4bc8bdffd659f 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs @@ -571,7 +571,7 @@ private BoundCollectionExpression ConvertCollectionExpression( return BindCollectionExpressionForErrorRecovery(node, targetType, diagnostics); } - var syntax = (ExpressionSyntax)node.Syntax; + var syntax = node.Syntax; if (LocalRewriter.IsAllocatingRefStructCollectionExpression(node, collectionTypeKind, elementType, Compilation)) { diagnostics.Add(node.HasSpreadElements(out _, out _) @@ -1733,83 +1733,86 @@ private bool MemberGroupFinalValidationAccessibilityChecks(BoundExpression? rece { // Perform final validation of the method to be invoked. - Debug.Assert(memberSymbol.Kind != SymbolKind.Method || + Debug.Assert(memberSymbol is not MethodSymbol { MethodKind: not MethodKind.Constructor } || memberSymbol.CanBeReferencedByName); //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 (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. - Debug.Assert(!invokedAsExtensionMethod); - } - else if (!memberSymbol.RequiresInstanceReceiver()) + if (receiverOpt != null || memberSymbol is not MethodSymbol { MethodKind: MethodKind.Constructor }) { - Debug.Assert(!invokedAsExtensionMethod || (receiverOpt != null)); - - if (invokedAsExtensionMethod) + 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. + Debug.Assert(!invokedAsExtensionMethod); + } + else if (!memberSymbol.RequiresInstanceReceiver()) { - if (IsMemberAccessedThroughType(receiverOpt)) + Debug.Assert(!invokedAsExtensionMethod || (receiverOpt != null)); + + if (invokedAsExtensionMethod) { - if (receiverOpt.Kind == BoundKind.QueryClause) + if (IsMemberAccessedThroughType(receiverOpt)) + { + if (receiverOpt.Kind == BoundKind.QueryClause) + { + RoslynDebug.Assert(receiverOpt.Type is object); + // Could not find an implementation of the query pattern for source type '{0}'. '{1}' not found. + diagnostics.Add(ErrorCode.ERR_QueryNoProvider, node.Location, receiverOpt.Type, memberSymbol.Name); + } + else + { + // An object reference is required for the non-static field, method, or property '{0}' + diagnostics.Add(ErrorCode.ERR_ObjectRequired, node.Location, memberSymbol); + } + return true; + } + } + else if (!WasImplicitReceiver(receiverOpt) && IsMemberAccessedThroughVariableOrValue(receiverOpt)) + { + if (this.Flags.Includes(BinderFlags.CollectionInitializerAddMethod)) + { + diagnostics.Add(ErrorCode.ERR_InitializerAddHasWrongSignature, node.Location, memberSymbol); + } + else if (node.Kind() == SyntaxKind.AwaitExpression && memberSymbol.Name == WellKnownMemberNames.GetAwaiter) { RoslynDebug.Assert(receiverOpt.Type is object); - // Could not find an implementation of the query pattern for source type '{0}'. '{1}' not found. - diagnostics.Add(ErrorCode.ERR_QueryNoProvider, node.Location, receiverOpt.Type, memberSymbol.Name); + diagnostics.Add(ErrorCode.ERR_BadAwaitArg, node.Location, receiverOpt.Type); } else { - // An object reference is required for the non-static field, method, or property '{0}' - diagnostics.Add(ErrorCode.ERR_ObjectRequired, node.Location, memberSymbol); + diagnostics.Add(ErrorCode.ERR_ObjectProhibited, node.Location, memberSymbol); } return true; } } - else if (!WasImplicitReceiver(receiverOpt) && IsMemberAccessedThroughVariableOrValue(receiverOpt)) + else if (IsMemberAccessedThroughType(receiverOpt)) { - if (this.Flags.Includes(BinderFlags.CollectionInitializerAddMethod)) - { - diagnostics.Add(ErrorCode.ERR_InitializerAddHasWrongSignature, node.Location, memberSymbol); - } - else if (node.Kind() == SyntaxKind.AwaitExpression && memberSymbol.Name == WellKnownMemberNames.GetAwaiter) - { - RoslynDebug.Assert(receiverOpt.Type is object); - diagnostics.Add(ErrorCode.ERR_BadAwaitArg, node.Location, receiverOpt.Type); - } - else - { - diagnostics.Add(ErrorCode.ERR_ObjectProhibited, node.Location, memberSymbol); - } + diagnostics.Add(ErrorCode.ERR_ObjectRequired, node.Location, memberSymbol); return true; } - } - else if (IsMemberAccessedThroughType(receiverOpt)) - { - diagnostics.Add(ErrorCode.ERR_ObjectRequired, node.Location, memberSymbol); - return true; - } - else if (WasImplicitReceiver(receiverOpt)) - { - if (InFieldInitializer && !ContainingType!.IsScriptClass || InConstructorInitializer || InAttributeArgument) + else if (WasImplicitReceiver(receiverOpt)) { - SyntaxNode errorNode = node; - if (node.Parent != null && node.Parent.Kind() == SyntaxKind.InvocationExpression) + if (InFieldInitializer && !ContainingType!.IsScriptClass || InConstructorInitializer || InAttributeArgument) { - errorNode = node.Parent; - } + SyntaxNode errorNode = node; + if (node.Parent != null && node.Parent.Kind() == SyntaxKind.InvocationExpression) + { + errorNode = node.Parent; + } - ErrorCode code = InFieldInitializer ? ErrorCode.ERR_FieldInitRefNonstatic : ErrorCode.ERR_ObjectRequired; - diagnostics.Add(code, errorNode.Location, memberSymbol); - return true; - } + ErrorCode code = InFieldInitializer ? ErrorCode.ERR_FieldInitRefNonstatic : ErrorCode.ERR_ObjectRequired; + diagnostics.Add(code, errorNode.Location, memberSymbol); + return true; + } - // If we could access the member through implicit "this" the receiver would be a BoundThisReference. - // If it is null it means that the instance member is inaccessible. - if (receiverOpt == null || ContainingMember().IsStatic) - { - Error(diagnostics, ErrorCode.ERR_ObjectRequired, node, memberSymbol); - return true; + // If we could access the member through implicit "this" the receiver would be a BoundThisReference. + // If it is null it means that the instance member is inaccessible. + if (receiverOpt == null || ContainingMember().IsStatic) + { + Error(diagnostics, ErrorCode.ERR_ObjectRequired, node, memberSymbol); + return true; + } } } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs index 7ba4c6e41ac76..0e9c9f8b4bcb7 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs @@ -669,7 +669,7 @@ private BoundExpression MakeDeconstructInvocationExpression( // Those placeholders are also recorded in the outVar for easy access below, by the `SetInferredType` call on the outVar nodes. BoundExpression result = BindMethodGroupInvocation( rightSyntax, rightSyntax, methodName, (BoundMethodGroup)memberAccess, analyzedArguments, diagnostics, queryClause: null, - allowUnexpandedForm: true, anyApplicableCandidates: out anyApplicableCandidates); + ignoreNormalFormIfHasValidParamsParameter: false, anyApplicableCandidates: out anyApplicableCandidates); result.WasCompilerGenerated = true; diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index 66ea1b51b2f41..4929ca7a96b03 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -4363,7 +4363,6 @@ private BoundExpression BindConstructorInitializerCore( { TypeSymbol constructorReturnType = constructor.ReturnType; Debug.Assert(constructorReturnType.IsVoidType()); //true of all constructors - NamedTypeSymbol baseType = containingType.BaseTypeNoUseSiteDiagnostics; // Get the bound arguments and the argument names. // : this(__arglist()) is legal @@ -4449,17 +4448,49 @@ private BoundExpression BindConstructorInitializerCore( if (initializerArgumentListOpt != null && analyzedArguments.HasDynamicArgument) { - diagnostics.Add(ErrorCode.ERR_NoDynamicPhantomOnBaseCtor, errorLocation); + BoundExpression result = null; + CompoundUseSiteInfo useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics); + ImmutableArray accessibleConstructors = GetAccessibleConstructorsForOverloadResolution(initializerType, allowProtectedConstructorsOfBaseType: true, allInstanceConstructors: out _, ref useSiteInfo); + OverloadResolutionResult overloadResolutionResult = OverloadResolutionResult.GetInstance(); + this.OverloadResolution.ObjectCreationOverloadResolution(accessibleConstructors, analyzedArguments, overloadResolutionResult, dynamicResolution: true, ref useSiteInfo); - return new BoundBadExpression( - syntax: initializerArgumentListOpt.Parent, - resultKind: LookupResultKind.Empty, - symbols: ImmutableArray.Empty, //CONSIDER: we could look for a matching constructor on System.ValueType - childBoundNodes: BuildArgumentsForErrorRecovery(analyzedArguments), - type: constructorReturnType); - } + if (overloadResolutionResult.HasAnyApplicableMember) + { + var finalApplicableCandidates = GetCandidatesPassingFinalValidation(nonNullSyntax, overloadResolutionResult, receiverOpt: null, default(ImmutableArray), invokedAsExtensionMethod: false, diagnostics); + + if (finalApplicableCandidates.Length == 1) + { + Debug.Assert(finalApplicableCandidates[0].IsApplicable); + + if (!IsAmbiguousDynamicParamsArgument(analyzedArguments.Arguments, finalApplicableCandidates[0], out SyntaxNode argumentSyntax)) + { + // PROTOTYPE(ParamsCollections): This code path is affected by https://github.com/dotnet/roslyn/issues/71399 + result = BindConstructorInitializerCoreContinued(found: true, initializerArgumentListOpt, constructor, analyzedArguments, constructorReturnType, + initializerType, isBaseConstructorInitializer, nonNullSyntax, errorLocation, enableCallerInfo, + finalApplicableCandidates[0], accessibleConstructors, in useSiteInfo, diagnostics); + } + } - BoundExpression receiver = ThisReference(nonNullSyntax, initializerType, wasCompilerGenerated: true); + if (result == null) + { + diagnostics.Add(ErrorCode.ERR_NoDynamicPhantomOnBaseCtor, errorLocation); + diagnostics.Add(errorLocation, useSiteInfo); + + result = new BoundBadExpression( + syntax: initializerArgumentListOpt.Parent, + resultKind: LookupResultKind.Empty, + symbols: accessibleConstructors.Cast(), + childBoundNodes: BuildArgumentsForErrorRecovery(analyzedArguments), + type: constructorReturnType); + } + } + + overloadResolutionResult.Free(); + if (result != null) + { + return result; + } + } MemberResolutionResult memberResolutionResult; ImmutableArray candidateConstructors; @@ -4473,127 +4504,158 @@ private BoundExpression BindConstructorInitializerCore( out memberResolutionResult, out candidateConstructors, allowProtectedConstructorsOfBaseType: true, - suppressUnsupportedRequiredMembersError: true); - MethodSymbol resultMember = memberResolutionResult.Member; + out CompoundUseSiteInfo overloadResolutionUseSiteInfo); - validateRecordCopyConstructor(constructor, baseType, resultMember, errorLocation, diagnostics); + return BindConstructorInitializerCoreContinued(found, initializerArgumentListOpt, constructor, analyzedArguments, constructorReturnType, + initializerType, isBaseConstructorInitializer, nonNullSyntax, errorLocation, enableCallerInfo, memberResolutionResult, candidateConstructors, in overloadResolutionUseSiteInfo, diagnostics); + } + finally + { + analyzedArguments.Free(); + } + } - if (found) + private BoundExpression BindConstructorInitializerCoreContinued( + bool found, + ArgumentListSyntax initializerArgumentListOpt, + MethodSymbol constructor, + AnalyzedArguments analyzedArguments, + TypeSymbol constructorReturnType, + NamedTypeSymbol initializerType, + bool isBaseConstructorInitializer, + CSharpSyntaxNode nonNullSyntax, + Location errorLocation, + bool enableCallerInfo, + MemberResolutionResult memberResolutionResult, + ImmutableArray candidateConstructors, + in CompoundUseSiteInfo overloadResolutionUseSiteInfo, + BindingDiagnosticBag diagnostics) + { + ReportConstructorUseSiteDiagnostics(errorLocation, diagnostics, suppressUnsupportedRequiredMembersError: true, in overloadResolutionUseSiteInfo); + + if (memberResolutionResult.IsNotNull) + { + this.CheckAndCoerceArguments(memberResolutionResult, analyzedArguments, diagnostics, receiver: null, invokedAsExtensionMethod: false); + } + + NamedTypeSymbol baseType = constructor.ContainingType.BaseTypeNoUseSiteDiagnostics; + + MethodSymbol resultMember = memberResolutionResult.Member; + + BoundExpression receiver = ThisReference(nonNullSyntax, initializerType, wasCompilerGenerated: true); + validateRecordCopyConstructor(constructor, baseType, resultMember, errorLocation, diagnostics); + + if (found) + { + bool hasErrors = false; + + if (resultMember == constructor) { - bool hasErrors = false; + Debug.Assert(initializerType.IsErrorType() || + (initializerArgumentListOpt != null && initializerArgumentListOpt.Parent.Kind() == SyntaxKind.ThisConstructorInitializer)); + diagnostics.Add(ErrorCode.ERR_RecursiveConstructorCall, + errorLocation, + constructor); - if (resultMember == constructor) - { - Debug.Assert(initializerType.IsErrorType() || - (initializerArgumentListOpt != null && initializerArgumentListOpt.Parent.Kind() == SyntaxKind.ThisConstructorInitializer)); - diagnostics.Add(ErrorCode.ERR_RecursiveConstructorCall, - errorLocation, - constructor); + hasErrors = true; // prevent recursive constructor from being emitted + } + else if (resultMember.HasParameterContainingPointerType()) + { + // What if some of the arguments are implicit? Dev10 reports unsafe errors + // if the implied argument would have an unsafe type. We need to check + // the parameters explicitly, since there won't be bound nodes for the implied + // arguments until lowering. - hasErrors = true; // prevent recursive constructor from being emitted - } - else if (resultMember.HasParameterContainingPointerType()) - { - // What if some of the arguments are implicit? Dev10 reports unsafe errors - // if the implied argument would have an unsafe type. We need to check - // the parameters explicitly, since there won't be bound nodes for the implied - // arguments until lowering. + // Don't worry about double reporting (i.e. for both the argument and the parameter) + // because only one unsafe diagnostic is allowed per scope - the others are suppressed. + hasErrors = ReportUnsafeIfNotAllowed(errorLocation, diagnostics); + } - // Don't worry about double reporting (i.e. for both the argument and the parameter) - // because only one unsafe diagnostic is allowed per scope - the others are suppressed. - hasErrors = ReportUnsafeIfNotAllowed(errorLocation, diagnostics); - } + ReportDiagnosticsIfObsolete(diagnostics, resultMember, nonNullSyntax, hasBaseReceiver: isBaseConstructorInitializer); - ReportDiagnosticsIfObsolete(diagnostics, resultMember, nonNullSyntax, hasBaseReceiver: isBaseConstructorInitializer); + var expanded = memberResolutionResult.Result.Kind == MemberResolutionKind.ApplicableInExpandedForm; + var argsToParamsOpt = memberResolutionResult.Result.ArgsToParamsOpt; - var expanded = memberResolutionResult.Result.Kind == MemberResolutionKind.ApplicableInExpandedForm; - var argsToParamsOpt = memberResolutionResult.Result.ArgsToParamsOpt; + if (constructor is SynthesizedPrimaryConstructor primaryConstructor) + { + var parametersPassedToBase = new OrderedSet(); - if (constructor is SynthesizedPrimaryConstructor primaryConstructor) + for (int i = 0; i < analyzedArguments.Arguments.Count; i++) { - var parametersPassedToBase = new OrderedSet(); + if (analyzedArguments.RefKind(i) is (RefKind.Ref or RefKind.Out)) + { + continue; + } - for (int i = 0; i < analyzedArguments.Arguments.Count; i++) + if (TryGetPrimaryConstructorParameterUsedAsValue(primaryConstructor, analyzedArguments.Argument(i)) is (ParameterSymbol parameter, SyntaxNode syntax)) { - if (analyzedArguments.RefKind(i) is (RefKind.Ref or RefKind.Out)) + if (expanded) { - continue; - } + var baseParameter = GetCorrespondingParameter(i, resultMember.Parameters, argsToParamsOpt, expanded: true); - if (TryGetPrimaryConstructorParameterUsedAsValue(primaryConstructor, analyzedArguments.Argument(i)) is (ParameterSymbol parameter, SyntaxNode syntax)) - { - if (expanded) + if (baseParameter.Ordinal == resultMember.ParameterCount - 1) { - var baseParameter = GetCorrespondingParameter(i, resultMember.Parameters, argsToParamsOpt, expanded: true); - - if (baseParameter.Ordinal == resultMember.ParameterCount - 1) - { - continue; - } + continue; } + } - if (parametersPassedToBase.Add(parameter)) + if (parametersPassedToBase.Add(parameter)) + { + if (primaryConstructor.GetCapturedParameters().ContainsKey(parameter)) { - if (primaryConstructor.GetCapturedParameters().ContainsKey(parameter)) - { - diagnostics.Add(ErrorCode.WRN_CapturedPrimaryConstructorParameterPassedToBase, syntax.Location, parameter); - } + diagnostics.Add(ErrorCode.WRN_CapturedPrimaryConstructorParameterPassedToBase, syntax.Location, parameter); } } } - - primaryConstructor.SetParametersPassedToTheBase(parametersPassedToBase); } - BindDefaultArgumentsAndParamsCollection(nonNullSyntax, resultMember.Parameters, analyzedArguments.Arguments, analyzedArguments.RefKinds, analyzedArguments.Names, ref argsToParamsOpt, out var defaultArguments, expanded, enableCallerInfo, diagnostics); + primaryConstructor.SetParametersPassedToTheBase(parametersPassedToBase); + } - var arguments = analyzedArguments.Arguments.ToImmutable(); - var refKinds = analyzedArguments.RefKinds.ToImmutableOrNull(); + BindDefaultArgumentsAndParamsCollection(nonNullSyntax, resultMember.Parameters, analyzedArguments.Arguments, analyzedArguments.RefKinds, analyzedArguments.Names, ref argsToParamsOpt, out var defaultArguments, expanded, enableCallerInfo, diagnostics); - if (resultMember.HasSetsRequiredMembers && !constructor.HasSetsRequiredMembers) - { - hasErrors = true; - // This constructor must add 'SetsRequiredMembers' because it chains to a constructor that has that attribute. - diagnostics.Add(ErrorCode.ERR_ChainingToSetsRequiredMembersRequiresSetsRequiredMembers, errorLocation); - } + var arguments = analyzedArguments.Arguments.ToImmutable(); + var refKinds = analyzedArguments.RefKinds.ToImmutableOrNull(); - return new BoundCall( - nonNullSyntax, - receiver, - initialBindingReceiverIsSubjectToCloning: ReceiverIsSubjectToCloning(receiver, resultMember), - resultMember, - arguments, - analyzedArguments.GetNames(), - refKinds, - isDelegateCall: false, - expanded, - invokedAsExtensionMethod: false, - argsToParamsOpt: argsToParamsOpt, - defaultArguments: defaultArguments, - resultKind: LookupResultKind.Viable, - type: constructorReturnType, - hasErrors: hasErrors) - { WasCompilerGenerated = initializerArgumentListOpt == null }; - } - else + if (resultMember.HasSetsRequiredMembers && !constructor.HasSetsRequiredMembers) { - var result = CreateBadCall( - node: nonNullSyntax, - name: WellKnownMemberNames.InstanceConstructorName, - receiver: receiver, - methods: candidateConstructors, - resultKind: LookupResultKind.OverloadResolutionFailure, - typeArgumentsWithAnnotations: ImmutableArray.Empty, - analyzedArguments: analyzedArguments, - invokedAsExtensionMethod: false, - isDelegate: false); - result.WasCompilerGenerated = initializerArgumentListOpt == null; - return result; + hasErrors = true; + // This constructor must add 'SetsRequiredMembers' because it chains to a constructor that has that attribute. + diagnostics.Add(ErrorCode.ERR_ChainingToSetsRequiredMembersRequiresSetsRequiredMembers, errorLocation); } + + return new BoundCall( + nonNullSyntax, + receiver, + initialBindingReceiverIsSubjectToCloning: ReceiverIsSubjectToCloning(receiver, resultMember), + resultMember, + arguments, + analyzedArguments.GetNames(), + refKinds, + isDelegateCall: false, + expanded, + invokedAsExtensionMethod: false, + argsToParamsOpt: argsToParamsOpt, + defaultArguments: defaultArguments, + resultKind: LookupResultKind.Viable, + type: constructorReturnType, + hasErrors: hasErrors) + { WasCompilerGenerated = initializerArgumentListOpt == null }; } - finally + else { - analyzedArguments.Free(); + var result = CreateBadCall( + node: nonNullSyntax, + name: WellKnownMemberNames.InstanceConstructorName, + receiver: receiver, + methods: candidateConstructors, + resultKind: LookupResultKind.OverloadResolutionFailure, + typeArgumentsWithAnnotations: ImmutableArray.Empty, + analyzedArguments: analyzedArguments, + invokedAsExtensionMethod: false, + isDelegate: false); + result.WasCompilerGenerated = initializerArgumentListOpt == null; + return result; } static void validateRecordCopyConstructor(MethodSymbol constructor, NamedTypeSymbol baseType, MethodSymbol resultMember, Location errorLocation, BindingDiagnosticBag diagnostics) @@ -6087,9 +6149,6 @@ protected BoundExpression BindClassCreationExpression( hasErrors = true; } - CompoundUseSiteInfo useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics); - BoundObjectInitializerExpressionBase boundInitializerOpt = null; - // If we have a dynamic argument then do overload resolution to see if there are one or more // applicable candidates. If there are, then this is a dynamic object creation; we'll work out // which ctor to call at runtime. If we have a dynamic argument but no applicable candidates @@ -6097,30 +6156,82 @@ protected BoundExpression BindClassCreationExpression( if (analyzedArguments.HasDynamicArgument) { + CompoundUseSiteInfo useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics); OverloadResolutionResult overloadResolutionResult = OverloadResolutionResult.GetInstance(); - this.OverloadResolution.ObjectCreationOverloadResolution(GetAccessibleConstructorsForOverloadResolution(type, ref useSiteInfo), analyzedArguments, overloadResolutionResult, ref useSiteInfo); - diagnostics.Add(node, useSiteInfo); - useSiteInfo = new CompoundUseSiteInfo(useSiteInfo); + ImmutableArray accessibleConstructors = GetAccessibleConstructorsForOverloadResolution(type, ref useSiteInfo); + this.OverloadResolution.ObjectCreationOverloadResolution(accessibleConstructors, analyzedArguments, overloadResolutionResult, dynamicResolution: true, ref useSiteInfo); if (overloadResolutionResult.HasAnyApplicableMember) { - var argArray = BuildArgumentsForDynamicInvocation(analyzedArguments, diagnostics); - var refKindsArray = analyzedArguments.RefKinds.ToImmutableOrNull(); + var finalApplicableCandidates = GetCandidatesPassingFinalValidation(node, overloadResolutionResult, receiverOpt: null, default(ImmutableArray), invokedAsExtensionMethod: false, diagnostics); - hasErrors &= ReportBadDynamicArguments(node, argArray, refKindsArray, diagnostics, queryClause: null); + if (finalApplicableCandidates.Length == 1) + { + Debug.Assert(finalApplicableCandidates[0].IsApplicable); - boundInitializerOpt = makeBoundInitializerOpt(); - result = new BoundDynamicObjectCreationExpression( - node, - typeName, - argArray, - analyzedArguments.GetNames(), - refKindsArray, - boundInitializerOpt, - overloadResolutionResult.GetAllApplicableMembers(), - wasTargetTyped, - type, - hasErrors); + if (IsAmbiguousDynamicParamsArgument(analyzedArguments.Arguments, finalApplicableCandidates[0], out SyntaxNode argumentSyntax)) + { + MethodSymbol singleCandidate = finalApplicableCandidates[0].Member; + + // We're only in trouble if a dynamic argument is passed to the + // params parameter and is ambiguous at compile time between normal + // and expanded form i.e., there is exactly one dynamic argument to + // a params parameter, and we know that runtime binder might not be + // able to handle the disambiguation + if (!singleCandidate.Parameters.Last().Type.IsSZArray()) + { + Error(diagnostics, + ErrorCode.ERR_ParamsCollectionAmbiguousDynamicArgument, + argumentSyntax, singleCandidate); + } + } + else + { + if (!type.IsAbstract) + { + // PROTOTYPE(ParamsCollections): This code path is affected by https://github.com/dotnet/roslyn/issues/71399 + result = BindClassCreationExpressionContinued(node, typeNode, type, analyzedArguments, initializerSyntaxOpt, + initializerTypeOpt, wasTargetTyped, finalApplicableCandidates[0], accessibleConstructors, in useSiteInfo, diagnostics); + } + else + { + result = CreateBadClassCreationExpression(node, typeNode, type, analyzedArguments, + initializerSyntaxOpt, initializerTypeOpt, finalApplicableCandidates[0], accessibleConstructors, in useSiteInfo, diagnostics); + } + } + } + + if (result == null) + { + if (finalApplicableCandidates.Length != 1 && + HasApplicableMemberWithPossiblyExpandedNonArrayParamsCollection(analyzedArguments.Arguments, finalApplicableCandidates)) + { + Error(diagnostics, + ErrorCode.WRN_DynamicDispatchToParamsCollectionConstructor, + node); + } + + var argArray = BuildArgumentsForDynamicInvocation(analyzedArguments, diagnostics); + var refKindsArray = analyzedArguments.RefKinds.ToImmutableOrNull(); + + hasErrors &= ReportBadDynamicArguments(node, argArray, refKindsArray, diagnostics, queryClause: null); + + BoundObjectInitializerExpressionBase boundInitializerOpt; + boundInitializerOpt = MakeBoundInitializerOpt(typeNode, type, initializerSyntaxOpt, initializerTypeOpt, diagnostics); + result = new BoundDynamicObjectCreationExpression( + node, + typeName, + argArray, + analyzedArguments.GetNames(), + refKindsArray, + boundInitializerOpt, + overloadResolutionResult.GetAllApplicableMembers(), + wasTargetTyped, + type, + hasErrors); + + diagnostics.Add(node, useSiteInfo); + } } overloadResolutionResult.Free(); @@ -6140,61 +6251,107 @@ protected BoundExpression BindClassCreationExpression( out MemberResolutionResult memberResolutionResult, out ImmutableArray candidateConstructors, allowProtectedConstructorsOfBaseType: false, - suppressUnsupportedRequiredMembersError: false) && + out CompoundUseSiteInfo overloadResolutionUseSiteInfo) && !type.IsAbstract) { - var method = memberResolutionResult.Member; + return BindClassCreationExpressionContinued(node, typeNode, type, analyzedArguments, initializerSyntaxOpt, initializerTypeOpt, wasTargetTyped, memberResolutionResult, candidateConstructors, in overloadResolutionUseSiteInfo, diagnostics); + } - bool hasError = false; + return CreateBadClassCreationExpression(node, typeNode, type, analyzedArguments, initializerSyntaxOpt, initializerTypeOpt, memberResolutionResult, candidateConstructors, in overloadResolutionUseSiteInfo, diagnostics); + } - // What if some of the arguments are implicit? Dev10 reports unsafe errors - // if the implied argument would have an unsafe type. We need to check - // the parameters explicitly, since there won't be bound nodes for the implied - // arguments until lowering. - if (method.HasParameterContainingPointerType()) - { - // Don't worry about double reporting (i.e. for both the argument and the parameter) - // because only one unsafe diagnostic is allowed per scope - the others are suppressed. - hasError = ReportUnsafeIfNotAllowed(node, diagnostics) || hasError; - } + private BoundObjectCreationExpression BindClassCreationExpressionContinued( + SyntaxNode node, + SyntaxNode typeNode, + NamedTypeSymbol type, + AnalyzedArguments analyzedArguments, + InitializerExpressionSyntax initializerSyntaxOpt, + TypeSymbol initializerTypeOpt, + bool wasTargetTyped, + MemberResolutionResult memberResolutionResult, + ImmutableArray candidateConstructors, + in CompoundUseSiteInfo overloadResolutionUseSiteInfo, + BindingDiagnosticBag diagnostics) + { + ReportConstructorUseSiteDiagnostics(typeNode.Location, diagnostics, suppressUnsupportedRequiredMembersError: false, in overloadResolutionUseSiteInfo); - ReportDiagnosticsIfObsolete(diagnostics, method, node, hasBaseReceiver: false); - // NOTE: Use-site diagnostics were reported during overload resolution. + if (memberResolutionResult.IsNotNull) + { + this.CheckAndCoerceArguments(memberResolutionResult, analyzedArguments, diagnostics, receiver: null, invokedAsExtensionMethod: false); + } - ConstantValue constantValueOpt = (initializerSyntaxOpt == null && method.IsDefaultValueTypeConstructor()) ? - FoldParameterlessValueTypeConstructor(type) : - null; + var method = memberResolutionResult.Member; - var expanded = memberResolutionResult.Result.Kind == MemberResolutionKind.ApplicableInExpandedForm; - var argToParams = memberResolutionResult.Result.ArgsToParamsOpt; - BindDefaultArgumentsAndParamsCollection(node, method.Parameters, analyzedArguments.Arguments, analyzedArguments.RefKinds, analyzedArguments.Names, ref argToParams, out var defaultArguments, expanded, enableCallerInfo: true, diagnostics); + bool hasError = false; - var arguments = analyzedArguments.Arguments.ToImmutable(); - var refKinds = analyzedArguments.RefKinds.ToImmutableOrNull(); + // What if some of the arguments are implicit? Dev10 reports unsafe errors + // if the implied argument would have an unsafe type. We need to check + // the parameters explicitly, since there won't be bound nodes for the implied + // arguments until lowering. + if (method.HasParameterContainingPointerType()) + { + // Don't worry about double reporting (i.e. for both the argument and the parameter) + // because only one unsafe diagnostic is allowed per scope - the others are suppressed. + hasError = ReportUnsafeIfNotAllowed(node, diagnostics) || hasError; + } - boundInitializerOpt = makeBoundInitializerOpt(); - var creation = new BoundObjectCreationExpression( - node, - method, - candidateConstructors, - arguments, - analyzedArguments.GetNames(), - refKinds, - expanded, - argToParams, - defaultArguments, - constantValueOpt, - boundInitializerOpt, - wasTargetTyped, - type, - hasError); + ReportDiagnosticsIfObsolete(diagnostics, method, node, hasBaseReceiver: false); + // NOTE: Use-site diagnostics were reported during overload resolution. - CheckRequiredMembersInObjectInitializer(creation.Constructor, creation.InitializerExpressionOpt?.Initializers ?? default, creation.Syntax, diagnostics); + ConstantValue constantValueOpt = (initializerSyntaxOpt == null && method.IsDefaultValueTypeConstructor()) ? + FoldParameterlessValueTypeConstructor(type) : + null; - return creation; + var expanded = memberResolutionResult.Result.Kind == MemberResolutionKind.ApplicableInExpandedForm; + var argToParams = memberResolutionResult.Result.ArgsToParamsOpt; + BindDefaultArgumentsAndParamsCollection(node, method.Parameters, analyzedArguments.Arguments, analyzedArguments.RefKinds, analyzedArguments.Names, ref argToParams, out var defaultArguments, expanded, enableCallerInfo: true, diagnostics); + + var arguments = analyzedArguments.Arguments.ToImmutable(); + var refKinds = analyzedArguments.RefKinds.ToImmutableOrNull(); + BoundObjectInitializerExpressionBase boundInitializerOpt; + boundInitializerOpt = MakeBoundInitializerOpt(typeNode, type, initializerSyntaxOpt, initializerTypeOpt, diagnostics); + var creation = new BoundObjectCreationExpression( + node, + method, + candidateConstructors, + arguments, + analyzedArguments.GetNames(), + refKinds, + expanded, + argToParams, + defaultArguments, + constantValueOpt, + boundInitializerOpt, + wasTargetTyped, + type, + hasError); + + CheckRequiredMembersInObjectInitializer(creation.Constructor, creation.InitializerExpressionOpt?.Initializers ?? default, creation.Syntax, diagnostics); + + return creation; + } + + private BoundExpression CreateBadClassCreationExpression( + SyntaxNode node, + SyntaxNode typeNode, + NamedTypeSymbol type, + AnalyzedArguments analyzedArguments, + InitializerExpressionSyntax initializerSyntaxOpt, + TypeSymbol initializerTypeOpt, + MemberResolutionResult memberResolutionResult, + ImmutableArray candidateConstructors, + in CompoundUseSiteInfo overloadResolutionUseSiteInfo, + BindingDiagnosticBag diagnostics) + { + ReportConstructorUseSiteDiagnostics(typeNode.Location, diagnostics, suppressUnsupportedRequiredMembersError: false, in overloadResolutionUseSiteInfo); + + if (memberResolutionResult.IsNotNull) + { + this.CheckAndCoerceArguments(memberResolutionResult, analyzedArguments, diagnostics, receiver: null, invokedAsExtensionMethod: false); } LookupResultKind resultKind; + CompoundUseSiteInfo useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics); if (type.IsAbstract) { @@ -6220,23 +6377,23 @@ protected BoundExpression BindClassCreationExpression( childNodes.AddRange(BuildArgumentsForErrorRecovery(analyzedArguments, candidateConstructors)); if (initializerSyntaxOpt != null) { - childNodes.Add(boundInitializerOpt ?? makeBoundInitializerOpt()); + childNodes.Add(MakeBoundInitializerOpt(typeNode, type, initializerSyntaxOpt, initializerTypeOpt, diagnostics)); } return new BoundBadExpression(node, resultKind, symbols.ToImmutableAndFree(), childNodes.ToImmutableAndFree(), type); + } - BoundObjectInitializerExpressionBase makeBoundInitializerOpt() + private BoundObjectInitializerExpressionBase MakeBoundInitializerOpt(SyntaxNode typeNode, NamedTypeSymbol type, InitializerExpressionSyntax initializerSyntaxOpt, TypeSymbol initializerTypeOpt, BindingDiagnosticBag diagnostics) + { + if (initializerSyntaxOpt != null) { - if (initializerSyntaxOpt != null) - { - return BindInitializerExpression(syntax: initializerSyntaxOpt, - type: initializerTypeOpt ?? type, - typeSyntax: typeNode, - isForNewInstance: true, - diagnostics: diagnostics); - } - return null; + return BindInitializerExpression(syntax: initializerSyntaxOpt, + type: initializerTypeOpt ?? type, + typeSyntax: typeNode, + isForNewInstance: true, + diagnostics: diagnostics); } + return null; } private BoundExpression BindInterfaceCreationExpression(ObjectCreationExpressionSyntax node, NamedTypeSymbol type, BindingDiagnosticBag diagnostics) @@ -6466,11 +6623,11 @@ internal bool TryPerformConstructorOverloadResolution( out MemberResolutionResult memberResolutionResult, out ImmutableArray candidateConstructors, bool allowProtectedConstructorsOfBaseType, - bool suppressUnsupportedRequiredMembersError) // Last to make named arguments more convenient. + out CompoundUseSiteInfo useSiteInfo) { // Get accessible constructors for performing overload resolution. ImmutableArray allInstanceConstructors; - CompoundUseSiteInfo useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics); + useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics); candidateConstructors = GetAccessibleConstructorsForOverloadResolution(typeContainingConstructors, allowProtectedConstructorsOfBaseType, out allInstanceConstructors, ref useSiteInfo); OverloadResolutionResult result = OverloadResolutionResult.GetInstance(); @@ -6478,18 +6635,14 @@ internal bool TryPerformConstructorOverloadResolution( // Indicates whether overload resolution successfully chose an accessible constructor. bool succeededConsideringAccessibility = false; - // Indicates whether overload resolution resulted in a single best match, even though it might be inaccessible. - bool succeededIgnoringAccessibility = false; - if (candidateConstructors.Any()) { // We have at least one accessible candidate constructor, perform overload resolution with accessible candidateConstructors. - this.OverloadResolution.ObjectCreationOverloadResolution(candidateConstructors, analyzedArguments, result, ref useSiteInfo); + this.OverloadResolution.ObjectCreationOverloadResolution(candidateConstructors, analyzedArguments, result, dynamicResolution: false, ref useSiteInfo); if (result.Succeeded) { succeededConsideringAccessibility = true; - succeededIgnoringAccessibility = true; } } @@ -6499,11 +6652,10 @@ internal bool TryPerformConstructorOverloadResolution( // We might have a best match constructor which is inaccessible. // Try overload resolution with all instance constructors to generate correct diagnostics and semantic info for this case. OverloadResolutionResult inaccessibleResult = OverloadResolutionResult.GetInstance(); - this.OverloadResolution.ObjectCreationOverloadResolution(allInstanceConstructors, analyzedArguments, inaccessibleResult, ref useSiteInfo); + this.OverloadResolution.ObjectCreationOverloadResolution(allInstanceConstructors, analyzedArguments, inaccessibleResult, dynamicResolution: false, ref useSiteInfo); if (inaccessibleResult.Succeeded) { - succeededIgnoringAccessibility = true; candidateConstructors = allInstanceConstructors; result.Free(); result = inaccessibleResult; @@ -6514,15 +6666,8 @@ internal bool TryPerformConstructorOverloadResolution( } } - ReportConstructorUseSiteDiagnostics(errorLocation, diagnostics, suppressUnsupportedRequiredMembersError, useSiteInfo); - - if (succeededIgnoringAccessibility) - { - this.CheckAndCoerceArguments(result.ValidResult, analyzedArguments, diagnostics, receiver: null, invokedAsExtensionMethod: false); - } - // Fill in the out parameter with the result, if there was one; it might be inaccessible. - memberResolutionResult = succeededIgnoringAccessibility ? + memberResolutionResult = result.Succeeded ? result.ValidResult : default(MemberResolutionResult); // Invalid results are not interesting - we have enough info in candidateConstructors. @@ -6532,7 +6677,7 @@ internal bool TryPerformConstructorOverloadResolution( // on the constructor if there were no errors on the arguments. if (!succeededConsideringAccessibility && !suppressResultDiagnostics) { - if (succeededIgnoringAccessibility) + if (result.Succeeded) { // It is not legal to directly call a protected constructor on a base class unless // the "this" of the call is known to be of the current type. That is, it is @@ -6571,7 +6716,7 @@ internal bool TryPerformConstructorOverloadResolution( return succeededConsideringAccessibility; } - internal static bool ReportConstructorUseSiteDiagnostics(Location errorLocation, BindingDiagnosticBag diagnostics, bool suppressUnsupportedRequiredMembersError, CompoundUseSiteInfo useSiteInfo) + internal static bool ReportConstructorUseSiteDiagnostics(Location errorLocation, BindingDiagnosticBag diagnostics, bool suppressUnsupportedRequiredMembersError, in CompoundUseSiteInfo useSiteInfo) { if (suppressUnsupportedRequiredMembersError && useSiteInfo.AccumulatesDiagnostics && useSiteInfo.Diagnostics is { Count: not 0 }) { @@ -7268,7 +7413,7 @@ private BoundExpression MakeMemberAccessValue(BoundExpression expr, BindingDiagn { var methodGroup = (BoundMethodGroup)expr; CompoundUseSiteInfo useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics); - var resolution = this.ResolveMethodGroup(methodGroup, analyzedArguments: null, isMethodGroupConversion: false, useSiteInfo: ref useSiteInfo); + var resolution = this.ResolveMethodGroup(methodGroup, analyzedArguments: null, useSiteInfo: ref useSiteInfo, options: OverloadResolution.Options.None); diagnostics.Add(expr.Syntax, useSiteInfo); if (!expr.HasAnyErrors) { @@ -7715,11 +7860,18 @@ protected MethodGroupResolution BindExtensionMethod( AnalyzedArguments analyzedArguments, BoundExpression left, ImmutableArray typeArgumentsWithAnnotations, - bool isMethodGroupConversion, + OverloadResolution.Options options, RefKind returnRefKind, TypeSymbol returnType, - bool withDependencies) + bool withDependencies, + in CallingConventionInfo callingConvention = default) { + Debug.Assert((options & ~(OverloadResolution.Options.IsMethodGroupConversion | + OverloadResolution.Options.IsFunctionPointerResolution | + OverloadResolution.Options.InferWithDynamic | + OverloadResolution.Options.IgnoreNormalFormIfHasValidParamsParameter | + OverloadResolution.Options.DynamicResolution)) == 0); + var firstResult = new MethodGroupResolution(); AnalyzedArguments actualArguments = null; @@ -7768,7 +7920,11 @@ protected MethodGroupResolution BindExtensionMethod( var overloadResolutionResult = OverloadResolutionResult.GetInstance(); // If we're in a parameter default value or attribute argument, this is an error scenario, so avoid checking // for COM imported types to avoid a binding cycle. - bool allowRefOmittedArguments = !InParameterDefaultValue && !InAttributeArgument && methodGroup.Receiver.IsExpressionOfComImportType(); + if (!InParameterDefaultValue && !InAttributeArgument && methodGroup.Receiver.IsExpressionOfComImportType()) + { + options |= OverloadResolution.Options.AllowRefOmittedArguments; + } + CompoundUseSiteInfo useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics); OverloadResolution.MethodInvocationOverloadResolution( methods: methodGroup.Methods, @@ -7777,11 +7933,10 @@ protected MethodGroupResolution BindExtensionMethod( arguments: actualArguments, result: overloadResolutionResult, useSiteInfo: ref useSiteInfo, - isMethodGroupConversion: isMethodGroupConversion, - allowRefOmittedArguments: allowRefOmittedArguments, + options: options | OverloadResolution.Options.IsExtensionMethodResolution, returnRefKind: returnRefKind, returnType: returnType, - isExtensionMethodResolution: true); + in callingConvention); diagnostics.Add(expression, useSiteInfo); var sealedDiagnostics = diagnostics.ToReadOnlyAndFree(); @@ -9103,9 +9258,11 @@ private BoundExpression BindIndexerOrIndexedPropertyAccess( // so we don't care if we accidentally miss a parameter being applicable. bool allowRefOmittedArguments = !InParameterDefaultValue && !InAttributeArgument && receiver.IsExpressionOfComImportType(); CompoundUseSiteInfo useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics); - this.OverloadResolution.PropertyOverloadResolution(propertyGroup, receiver, analyzedArguments, overloadResolutionResult, allowRefOmittedArguments, ref useSiteInfo); + this.OverloadResolution.PropertyOverloadResolution(propertyGroup, receiver, analyzedArguments, overloadResolutionResult, + options: (allowRefOmittedArguments ? OverloadResolution.Options.AllowRefOmittedArguments : OverloadResolution.Options.None) | + (analyzedArguments.HasDynamicArgument ? OverloadResolution.Options.DynamicResolution : OverloadResolution.Options.None), + ref useSiteInfo); diagnostics.Add(syntax, useSiteInfo); - BoundExpression propertyAccess; if (analyzedArguments.HasDynamicArgument && overloadResolutionResult.HasAnyApplicableMember) { @@ -9113,11 +9270,63 @@ private BoundExpression BindIndexerOrIndexedPropertyAccess( // and an ambiguity error may be reported. Also additional checks are performed in runtime final validation // that are not performed at compile-time. // Only if the set of final applicable candidates is empty we know for sure the call will fail at runtime. - var finalApplicableCandidates = GetCandidatesPassingFinalValidation(syntax, overloadResolutionResult, receiver, default(ImmutableArray), diagnostics); + var finalApplicableCandidates = GetCandidatesPassingFinalValidation(syntax, overloadResolutionResult, receiver, default(ImmutableArray), invokedAsExtensionMethod: false, diagnostics); + + if (finalApplicableCandidates.Length == 1) + { + Debug.Assert(finalApplicableCandidates[0].IsApplicable); + + if (IsAmbiguousDynamicParamsArgument(analyzedArguments.Arguments, finalApplicableCandidates[0], out SyntaxNode argumentSyntax)) + { + PropertySymbol singleCandidate = finalApplicableCandidates[0].LeastOverriddenMember; + + // We're only in trouble if a dynamic argument is passed to the + // params parameter and is ambiguous at compile time between normal + // and expanded form i.e., there is exactly one dynamic argument to + // a params parameter, and we know that runtime binder might not be + // able to handle the disambiguation + if (!singleCandidate.Parameters.Last().Type.IsSZArray()) + { + Error(diagnostics, + ErrorCode.ERR_ParamsCollectionAmbiguousDynamicArgument, + argumentSyntax, singleCandidate); + } + } + else + { + var resultWithSingleCandidate = OverloadResolutionResult.GetInstance(); + resultWithSingleCandidate.ResultsBuilder.Add(finalApplicableCandidates[0]); + overloadResolutionResult.Free(); + + // PROTOTYPE(ParamsCollections): This code path is affected by https://github.com/dotnet/roslyn/issues/71399 + return BindIndexerOrIndexedPropertyAccessContinued(syntax, receiver, propertyGroup, analyzedArguments, resultWithSingleCandidate, diagnostics); + } + } + + if (finalApplicableCandidates.Length != 1 && + HasApplicableMemberWithPossiblyExpandedNonArrayParamsCollection(analyzedArguments.Arguments, finalApplicableCandidates)) + { + Error(diagnostics, + ErrorCode.WRN_DynamicDispatchToParamsCollectionIndexer, + syntax); + } + overloadResolutionResult.Free(); - return BindDynamicIndexer(syntax, receiver, analyzedArguments, finalApplicableCandidates, diagnostics); + return BindDynamicIndexer(syntax, receiver, analyzedArguments, finalApplicableCandidates.SelectAsArray(r => r.Member), diagnostics); } + return BindIndexerOrIndexedPropertyAccessContinued(syntax, receiver, propertyGroup, analyzedArguments, overloadResolutionResult, diagnostics); + } + + private BoundExpression BindIndexerOrIndexedPropertyAccessContinued( + SyntaxNode syntax, + BoundExpression receiver, + ArrayBuilder propertyGroup, + AnalyzedArguments analyzedArguments, + OverloadResolutionResult overloadResolutionResult, + BindingDiagnosticBag diagnostics) + { + BoundExpression propertyAccess; ImmutableArray argumentNames = analyzedArguments.GetNames(); ImmutableArray argumentRefKinds = analyzedArguments.RefKinds.ToImmutableOrNull(); if (!overloadResolutionResult.Succeeded) @@ -9458,7 +9667,7 @@ void makeCall(SyntaxNode syntax, BoundExpression receiver, MethodSymbol method, { WasCompilerGenerated = true }; indexerOrSliceAccess = BindMethodGroupInvocation(syntax, syntax, method.Name, boundMethodGroup, analyzedArguments, - diagnostics, queryClause: null, allowUnexpandedForm: false, anyApplicableCandidates: out bool _).MakeCompilerGenerated(); + diagnostics, queryClause: null, ignoreNormalFormIfHasValidParamsParameter: true, anyApplicableCandidates: out bool _).MakeCompilerGenerated(); analyzedArguments.Free(); } @@ -9566,27 +9775,28 @@ 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 CompoundUseSiteInfo useSiteInfo, - bool inferWithDynamic = false, + OverloadResolution.Options options, RefKind returnRefKind = default, TypeSymbol returnType = null, - bool isFunctionPointerResolution = false, in CallingConventionInfo callingConventionInfo = default) { + Debug.Assert((options & ~(OverloadResolution.Options.IsMethodGroupConversion | + OverloadResolution.Options.IsFunctionPointerResolution | + OverloadResolution.Options.InferWithDynamic)) == 0); + return ResolveMethodGroup( - node, node.Syntax, node.Name, analyzedArguments, isMethodGroupConversion, ref useSiteInfo, - inferWithDynamic: inferWithDynamic, returnRefKind: returnRefKind, returnType: returnType, - isFunctionPointerResolution: isFunctionPointerResolution, callingConventionInfo: callingConventionInfo); + node, node.Syntax, node.Name, analyzedArguments, ref useSiteInfo, + options, returnRefKind: returnRefKind, returnType: returnType, + callingConventionInfo: callingConventionInfo); } internal MethodGroupResolution ResolveMethodGroup( @@ -9594,20 +9804,17 @@ internal MethodGroupResolution ResolveMethodGroup( SyntaxNode expression, string methodName, AnalyzedArguments analyzedArguments, - bool isMethodGroupConversion, ref CompoundUseSiteInfo useSiteInfo, - bool inferWithDynamic = false, - bool allowUnexpandedForm = true, + OverloadResolution.Options options, RefKind returnRefKind = default, TypeSymbol returnType = null, - bool isFunctionPointerResolution = false, in CallingConventionInfo callingConventionInfo = default) { var methodResolution = ResolveMethodGroupInternal( - node, expression, methodName, analyzedArguments, isMethodGroupConversion, ref useSiteInfo, - inferWithDynamic: inferWithDynamic, allowUnexpandedForm: allowUnexpandedForm, + node, expression, methodName, analyzedArguments, ref useSiteInfo, + options, returnRefKind: returnRefKind, returnType: returnType, - isFunctionPointerResolution: isFunctionPointerResolution, callingConvention: callingConventionInfo); + callingConvention: callingConventionInfo); if (methodResolution.IsEmpty && !methodResolution.HasAnyErrors) { Debug.Assert(node.LookupError == null); @@ -9633,13 +9840,10 @@ internal MethodGroupResolution ResolveMethodGroupForFunctionPointer( return ResolveDefaultMethodGroup( methodGroup, analyzedArguments, - isMethodGroupConversion: true, ref useSiteInfo, - inferWithDynamic: false, - allowUnexpandedForm: true, + options: OverloadResolution.Options.IsMethodGroupConversion | OverloadResolution.Options.IsFunctionPointerResolution, returnRefKind, returnType, - isFunctionPointerResolution: true, callingConventionInfo); } @@ -9648,19 +9852,16 @@ private MethodGroupResolution ResolveMethodGroupInternal( SyntaxNode expression, string methodName, AnalyzedArguments analyzedArguments, - bool isMethodGroupConversion, ref CompoundUseSiteInfo useSiteInfo, - bool inferWithDynamic = false, - bool allowUnexpandedForm = true, + OverloadResolution.Options options, RefKind returnRefKind = default, TypeSymbol returnType = null, - bool isFunctionPointerResolution = false, in CallingConventionInfo callingConvention = default) { var methodResolution = ResolveDefaultMethodGroup( - methodGroup, analyzedArguments, isMethodGroupConversion, ref useSiteInfo, - inferWithDynamic, allowUnexpandedForm, - returnRefKind, returnType, isFunctionPointerResolution, callingConvention); + methodGroup, analyzedArguments, ref useSiteInfo, + options, + returnRefKind, returnType, callingConvention); // 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. @@ -9670,8 +9871,9 @@ private MethodGroupResolution ResolveMethodGroupInternal( } var extensionMethodResolution = BindExtensionMethod( - expression, methodName, analyzedArguments, methodGroup.ReceiverOpt, methodGroup.TypeArgumentsOpt, isMethodGroupConversion, - returnRefKind: returnRefKind, returnType: returnType, withDependencies: useSiteInfo.AccumulatesDependencies); + expression, methodName, analyzedArguments, methodGroup.ReceiverOpt, methodGroup.TypeArgumentsOpt, options, + returnRefKind: returnRefKind, returnType: returnType, withDependencies: useSiteInfo.AccumulatesDependencies, + in callingConvention); bool preferExtensionMethodResolution = false; if (extensionMethodResolution.HasAnyApplicableMethod) @@ -9720,15 +9922,18 @@ private MethodGroupResolution ResolveMethodGroupInternal( private MethodGroupResolution ResolveDefaultMethodGroup( BoundMethodGroup node, AnalyzedArguments analyzedArguments, - bool isMethodGroupConversion, ref CompoundUseSiteInfo useSiteInfo, - bool inferWithDynamic = false, - bool allowUnexpandedForm = true, + OverloadResolution.Options options, RefKind returnRefKind = default, TypeSymbol returnType = null, - bool isFunctionPointerResolution = false, in CallingConventionInfo callingConvention = default) { + Debug.Assert((options & ~(OverloadResolution.Options.IsMethodGroupConversion | + OverloadResolution.Options.IsFunctionPointerResolution | + OverloadResolution.Options.InferWithDynamic | + OverloadResolution.Options.IgnoreNormalFormIfHasValidParamsParameter | + OverloadResolution.Options.DynamicResolution)) == 0); + var methods = node.Methods; if (methods.Length == 0) { @@ -9774,7 +9979,11 @@ private MethodGroupResolution ResolveDefaultMethodGroup( // We check for being in a default parameter value or attribute to avoid a cycle. If we're binding these, // this entire expression is bad, so we don't care whether this is a COM import type and we can safely // just pass false here. - bool allowRefOmittedArguments = !InParameterDefaultValue && !InAttributeArgument && methodGroup.Receiver.IsExpressionOfComImportType(); + if (!InParameterDefaultValue && !InAttributeArgument && methodGroup.Receiver.IsExpressionOfComImportType()) + { + options |= OverloadResolution.Options.AllowRefOmittedArguments; + } + OverloadResolution.MethodInvocationOverloadResolution( methodGroup.Methods, methodGroup.TypeArguments, @@ -9782,14 +9991,9 @@ private MethodGroupResolution ResolveDefaultMethodGroup( analyzedArguments, result, ref useSiteInfo, - isMethodGroupConversion, - allowRefOmittedArguments, - inferWithDynamic, - allowUnexpandedForm, + options, returnRefKind, returnType, - isFunctionPointerResolution, - isExtensionMethodResolution: false, callingConvention); // Note: the MethodGroupResolution instance is responsible for freeing its copy of analyzed arguments diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs index c7c5e8c060690..def151e1ba7f2 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs @@ -72,7 +72,7 @@ private static ImmutableArray GetOriginalMethods(OverloadResolutio /// Optional type arguments. /// The syntax for the query clause generating this invocation expression, if any. /// True to allow invocation of fields and properties of delegate type. Only methods are allowed otherwise. - /// False to prevent selecting a params method in unexpanded form. + /// True to prevent selecting a params method in unexpanded form. /// Synthesized method invocation expression. internal BoundExpression MakeInvocationExpression( SyntaxNode node, @@ -85,7 +85,7 @@ internal BoundExpression MakeInvocationExpression( ImmutableArray<(string Name, Location Location)?> names = default, CSharpSyntaxNode? queryClause = null, bool allowFieldsAndProperties = false, - bool allowUnexpandedForm = true, + bool ignoreNormalFormIfHasValidParamsParameter = false, bool searchExtensionMethodsIfNecessary = true) { Debug.Assert(receiver != null); @@ -136,7 +136,7 @@ internal BoundExpression MakeInvocationExpression( BoundExpression result = BindInvocationExpression( node, node, methodName, boundExpression, analyzedArguments, diagnostics, queryClause, - allowUnexpandedForm: allowUnexpandedForm); + ignoreNormalFormIfHasValidParamsParameter: ignoreNormalFormIfHasValidParamsParameter); // Query operator can't be called dynamically. if (queryClause != null && result.Kind == BoundKind.DynamicInvocation) @@ -302,7 +302,7 @@ private BoundExpression BindInvocationExpression( AnalyzedArguments analyzedArguments, BindingDiagnosticBag diagnostics, CSharpSyntaxNode queryClause = null, - bool allowUnexpandedForm = true) + bool ignoreNormalFormIfHasValidParamsParameter = false) { BoundExpression result; NamedTypeSymbol delegateType; @@ -320,7 +320,7 @@ private BoundExpression BindInvocationExpression( ReportSuppressionIfNeeded(boundExpression, diagnostics); result = BindMethodGroupInvocation( node, expression, methodName, (BoundMethodGroup)boundExpression, analyzedArguments, - diagnostics, queryClause, allowUnexpandedForm: allowUnexpandedForm, anyApplicableCandidates: out _); + diagnostics, queryClause, ignoreNormalFormIfHasValidParamsParameter: ignoreNormalFormIfHasValidParamsParameter, anyApplicableCandidates: out _); } else if ((object)(delegateType = GetDelegateType(boundExpression)) != null) { @@ -579,14 +579,41 @@ private BoundExpression BindDelegateInvocation( receiver: methodGroup.Receiver, arguments: analyzedArguments, result: overloadResolutionResult, - useSiteInfo: ref useSiteInfo); + useSiteInfo: ref useSiteInfo, + options: analyzedArguments.HasDynamicArgument ? OverloadResolution.Options.DynamicResolution : OverloadResolution.Options.None); diagnostics.Add(node, useSiteInfo); // If overload resolution on the "Invoke" method found an applicable candidate, and one of the arguments // was dynamic then treat this as a dynamic call. if (analyzedArguments.HasDynamicArgument && overloadResolutionResult.HasAnyApplicableMember) { - result = BindDynamicInvocation(node, boundExpression, analyzedArguments, overloadResolutionResult.GetAllApplicableMembers(), diagnostics, queryClause); + var applicable = overloadResolutionResult.Results.Single(r => r.IsApplicable); + + // We have to do a dynamic dispatch only when a dynamic argument is + // passed to the params parameter and is ambiguous at compile time between normal + // and expanded form i.e., there is exactly one dynamic argument to + // a params parameter. + + if (IsAmbiguousDynamicParamsArgument(analyzedArguments.Arguments, applicable, out SyntaxNode argumentSyntax)) + { + MethodSymbol singleCandidate = applicable.Member; + + // We know that runtime binder might not be + // able to handle the disambiguation + if (!singleCandidate.Parameters.Last().Type.IsSZArray()) + { + Error(diagnostics, + ErrorCode.ERR_ParamsCollectionAmbiguousDynamicArgument, + argumentSyntax, singleCandidate); + } + + result = BindDynamicInvocation(node, boundExpression, analyzedArguments, overloadResolutionResult.GetAllApplicableMembers(), diagnostics, queryClause); + } + else + { + // PROTOTYPE(ParamsCollections): This code path is affected by https://github.com/dotnet/roslyn/issues/71399 + result = BindInvocationExpressionContinued(node, expression, methodName, overloadResolutionResult, analyzedArguments, methodGroup, delegateType, diagnostics, queryClause); + } } else { @@ -598,12 +625,27 @@ private BoundExpression BindDelegateInvocation( return result; } - private static bool HasApplicableConditionalMethod(OverloadResolutionResult results) + private static bool HasApplicableConditionalMethod(ImmutableArray> finalApplicableCandidates) { - var r = results.Results; - for (int i = 0; i < r.Length; ++i) + foreach (var candidate in finalApplicableCandidates) { - if (r[i].IsApplicable && r[i].Member.IsConditional) + if (candidate.Member.IsConditional) + { + return true; + } + } + + return false; + } + + private bool HasApplicableMemberWithPossiblyExpandedNonArrayParamsCollection(ArrayBuilder arguments, ImmutableArray> finalApplicableCandidates) + where TMember : Symbol + { + foreach (var candidate in finalApplicableCandidates) + { + if ((candidate.Result.Kind == MemberResolutionKind.ApplicableInExpandedForm || + IsAmbiguousDynamicParamsArgument(arguments, candidate, argumentSyntax: out _)) && + !candidate.Member.GetParameters().Last().Type.IsSZArray()) { return true; } @@ -620,14 +662,16 @@ private BoundExpression BindMethodGroupInvocation( AnalyzedArguments analyzedArguments, BindingDiagnosticBag diagnostics, CSharpSyntaxNode queryClause, - bool allowUnexpandedForm, + bool ignoreNormalFormIfHasValidParamsParameter, out bool anyApplicableCandidates) { - BoundExpression result; + BoundExpression result = null; CompoundUseSiteInfo useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics); var resolution = this.ResolveMethodGroup( - methodGroup, expression, methodName, analyzedArguments, isMethodGroupConversion: false, - useSiteInfo: ref useSiteInfo, allowUnexpandedForm: allowUnexpandedForm); + methodGroup, expression, methodName, analyzedArguments, + useSiteInfo: ref useSiteInfo, + options: (ignoreNormalFormIfHasValidParamsParameter ? OverloadResolution.Options.IgnoreNormalFormIfHasValidParamsParameter : OverloadResolution.Options.None) | + (analyzedArguments.HasDynamicArgument ? OverloadResolution.Options.DynamicResolution : OverloadResolution.Options.None)); diagnostics.Add(expression, useSiteInfo); anyApplicableCandidates = resolution.ResultKind == LookupResultKind.Viable && resolution.OverloadResolutionResult.HasAnyApplicableMember; @@ -689,50 +733,63 @@ private BoundExpression BindMethodGroupInvocation( if (resolution.AnalyzedArguments.HasDynamicArgument && resolution.OverloadResolutionResult.HasAnyApplicableMember) { - if (resolution.IsLocalFunctionInvocation) + // Note that the runtime binder may consider candidates that haven't passed compile-time final validation + // and an ambiguity error may be reported. Also additional checks are performed in runtime final validation + // that are not performed at compile-time. + // Only if the set of final applicable candidates is empty we know for sure the call will fail at runtime. + var finalApplicableCandidates = GetCandidatesPassingFinalValidation(syntax, resolution.OverloadResolutionResult, + methodGroup.ReceiverOpt, + methodGroup.TypeArgumentsOpt, + invokedAsExtensionMethod: resolution.IsExtensionMethodGroup, + diagnostics); + + if (finalApplicableCandidates.Length == 0) { - result = BindLocalFunctionInvocationWithDynamicArgument( - syntax, expression, methodName, methodGroup, - diagnostics, queryClause, resolution); + result = CreateBadCall(syntax, methodGroup, methodGroup.ResultKind, analyzedArguments); } - else if (resolution.IsExtensionMethodGroup) + else if (finalApplicableCandidates.Length == 1) { - // error CS1973: 'T' has no applicable method named 'M' but appears to have an - // extension method by that name. Extension methods cannot be dynamically dispatched. Consider - // casting the dynamic arguments or calling the extension method without the extension method - // syntax. - - // We found an extension method, so the instance associated with the method group must have - // existed and had a type. - Debug.Assert(methodGroup.InstanceOpt != null && (object)methodGroup.InstanceOpt.Type != null); + Debug.Assert(finalApplicableCandidates[0].IsApplicable); - Error(diagnostics, ErrorCode.ERR_BadArgTypeDynamicExtension, syntax, methodGroup.InstanceOpt.Type, methodGroup.Name); - result = CreateBadCall(syntax, methodGroup, methodGroup.ResultKind, analyzedArguments); + result = TryEarlyBindSingleCandidateInvocationWithDynamicArgument(syntax, expression, methodName, methodGroup, diagnostics, queryClause, resolution, finalApplicableCandidates[0]); } - else + + if (result is null) { - if (HasApplicableConditionalMethod(resolution.OverloadResolutionResult)) - { - // warning CS1974: The dynamically dispatched call to method 'Goo' may fail at runtime - // because one or more applicable overloads are conditional methods - Error(diagnostics, ErrorCode.WRN_DynamicDispatchToConditionalMethod, syntax, methodGroup.Name); - } + Debug.Assert(finalApplicableCandidates.Length > 0); - // Note that the runtime binder may consider candidates that haven't passed compile-time final validation - // and an ambiguity error may be reported. Also additional checks are performed in runtime final validation - // that are not performed at compile-time. - // Only if the set of final applicable candidates is empty we know for sure the call will fail at runtime. - var finalApplicableCandidates = GetCandidatesPassingFinalValidation(syntax, resolution.OverloadResolutionResult, - methodGroup.ReceiverOpt, - methodGroup.TypeArgumentsOpt, - diagnostics); - if (finalApplicableCandidates.Length > 0) + if (resolution.IsExtensionMethodGroup) { - result = BindDynamicInvocation(syntax, methodGroup, resolution.AnalyzedArguments, finalApplicableCandidates, diagnostics, queryClause); + // error CS1973: 'T' has no applicable method named 'M' but appears to have an + // extension method by that name. Extension methods cannot be dynamically dispatched. Consider + // casting the dynamic arguments or calling the extension method without the extension method + // syntax. + + // We found an extension method, so the instance associated with the method group must have + // existed and had a type. + Debug.Assert(methodGroup.InstanceOpt != null && (object)methodGroup.InstanceOpt.Type != null); + + Error(diagnostics, ErrorCode.ERR_BadArgTypeDynamicExtension, syntax, methodGroup.InstanceOpt.Type, methodGroup.Name); + result = CreateBadCall(syntax, methodGroup, methodGroup.ResultKind, analyzedArguments); } else { - result = CreateBadCall(syntax, methodGroup, methodGroup.ResultKind, analyzedArguments); + if (HasApplicableConditionalMethod(finalApplicableCandidates)) + { + // warning CS1974: The dynamically dispatched call to method 'Goo' may fail at runtime + // because one or more applicable overloads are conditional methods + Error(diagnostics, ErrorCode.WRN_DynamicDispatchToConditionalMethod, syntax, methodGroup.Name); + } + + if (finalApplicableCandidates.Length != 1 && + HasApplicableMemberWithPossiblyExpandedNonArrayParamsCollection(resolution.AnalyzedArguments.Arguments, finalApplicableCandidates)) + { + Error(diagnostics, + ErrorCode.WRN_DynamicDispatchToParamsCollectionMethod, + syntax, methodGroup.Name); + } + + result = BindDynamicInvocation(syntax, methodGroup, resolution.AnalyzedArguments, finalApplicableCandidates.SelectAsArray(r => r.Member), diagnostics, queryClause); } } } @@ -752,119 +809,129 @@ private BoundExpression BindMethodGroupInvocation( return result; } - private BoundExpression BindLocalFunctionInvocationWithDynamicArgument( + private bool IsAmbiguousDynamicParamsArgument(ArrayBuilder arguments, MemberResolutionResult candidate, out SyntaxNode argumentSyntax) + where TMethodOrPropertySymbol : Symbol + { + if (OverloadResolution.IsValidParams(this, candidate.LeastOverriddenMember) && + candidate.Result.Kind == MemberResolutionKind.ApplicableInNormalForm) + { + var parameters = candidate.Member.GetParameters(); + var lastParamIndex = parameters.Length - 1; + + for (int i = 0; i < arguments.Count; ++i) + { + var arg = arguments[i]; + if (arg.HasDynamicType() && + candidate.Result.ParameterFromArgument(i) == lastParamIndex) + { + argumentSyntax = arg.Syntax; + return true; + } + } + } + + argumentSyntax = null; + return false; + } + + private BoundExpression TryEarlyBindSingleCandidateInvocationWithDynamicArgument( SyntaxNode syntax, SyntaxNode expression, string methodName, BoundMethodGroup boundMethodGroup, BindingDiagnosticBag diagnostics, CSharpSyntaxNode queryClause, - MethodGroupResolution resolution) + MethodGroupResolution resolution, + MemberResolutionResult methodResolutionResult) { - // Invocations of local functions with dynamic arguments don't need - // to be dispatched as dynamic invocations since they cannot be - // overloaded. Instead, we'll just emit a standard call with - // dynamic implicit conversions for any dynamic arguments. There - // are two exceptions: "params", and unconstructed generics. While - // implementing those cases with dynamic invocations is possible, - // we have decided the implementation complexity is not worth it. - // Refer to the comments below for the exact semantics. - - Debug.Assert(resolution.IsLocalFunctionInvocation); - Debug.Assert(resolution.OverloadResolutionResult.Succeeded); - Debug.Assert(queryClause == null); + MethodSymbol singleCandidate = methodResolutionResult.LeastOverriddenMember; + if (boundMethodGroup.TypeArgumentsOpt.IsDefaultOrEmpty && singleCandidate.IsGenericMethod) + { + // If we call an unconstructed generic function with a + // dynamic argument in a place where it influences the type + // parameters, we need to dynamically dispatch the call (as the + // function must be constructed at runtime). We disallow that + // when we know that runtime binder will not be able to handle the case. + // See https://github.com/dotnet/roslyn/issues/21317 - var validResult = resolution.OverloadResolutionResult.ValidResult; - var args = resolution.AnalyzedArguments.Arguments.ToImmutable(); - var refKindsArray = resolution.AnalyzedArguments.RefKinds.ToImmutableOrNull(); + // However, doing a specific analysis of each + // argument and its corresponding parameter to check if it's + // generic (and allow dynamic in non-generic parameters) doesn't + // seem to worth the complexity. So, just disallow any mixing of dynamic and + // inferred generics. (Explicit generic arguments are fine) - ReportBadDynamicArguments(syntax, args, refKindsArray, diagnostics, queryClause); + if (OverloadResolution.IsValidParams(this, singleCandidate) && + !singleCandidate.Parameters.Last().Type.IsSZArray()) + { + Error(diagnostics, + ErrorCode.ERR_CantInferMethTypeArgs_DynamicArgumentWithParamsCollections, + syntax, singleCandidate); + } + else if (singleCandidate.MethodKind == MethodKind.LocalFunction) + { + Error(diagnostics, + ErrorCode.ERR_DynamicLocalFunctionTypeParameter, + syntax, singleCandidate.Name); + } - var localFunction = validResult.Member; - var methodResult = validResult.Result; + return null; + } - // We're only in trouble if a dynamic argument is passed to the - // params parameter and is ambiguous at compile time between normal - // and expanded form i.e., there is exactly one dynamic argument to - // a params parameter - // See https://github.com/dotnet/roslyn/issues/10708 - if (OverloadResolution.IsValidParams(this, localFunction) && - methodResult.Kind == MemberResolutionKind.ApplicableInNormalForm) + if (IsAmbiguousDynamicParamsArgument(resolution.AnalyzedArguments.Arguments, methodResolutionResult, out SyntaxNode argumentSyntax)) { - var parameters = localFunction.Parameters; - - Debug.Assert(parameters.Last().IsParams); - - var lastParamIndex = parameters.Length - 1; - - for (int i = 0; i < args.Length; ++i) + // We're only in trouble if a dynamic argument is passed to the + // params parameter and is ambiguous at compile time between normal + // and expanded form i.e., there is exactly one dynamic argument to + // a params parameter, and we know that runtime binder might not be + // able to handle the disambiguation + // See https://github.com/dotnet/roslyn/issues/10708 + if (!singleCandidate.Parameters.Last().Type.IsSZArray()) { - var arg = args[i]; - if (arg.HasDynamicType() && - methodResult.ParameterFromArgument(i) == lastParamIndex) - { - // PROTOTYPE(ParamsCollections): non-array params case might need similar error for a non-local-function case. - Error(diagnostics, - ErrorCode.ERR_DynamicLocalFunctionParamsParameter, - syntax, parameters.Last().Name, localFunction.Name); - return BindDynamicInvocation( - syntax, - boundMethodGroup, - resolution.AnalyzedArguments, - resolution.OverloadResolutionResult.GetAllApplicableMembers(), - diagnostics, - queryClause); - } + Error(diagnostics, + ErrorCode.ERR_ParamsCollectionAmbiguousDynamicArgument, + argumentSyntax, singleCandidate); + } + else if (singleCandidate.MethodKind == MethodKind.LocalFunction) + { + Error(diagnostics, + ErrorCode.ERR_DynamicLocalFunctionParamsParameter, + argumentSyntax, singleCandidate.Parameters.Last().Name, singleCandidate.Name); } - } - // If we call an unconstructed generic local function with a - // dynamic argument in a place where it influences the type - // parameters, we need to dynamically dispatch the call (as the - // function must be constructed at runtime). We cannot do that, so - // disallow that. However, doing a specific analysis of each - // argument and its corresponding parameter to check if it's - // generic (and allow dynamic in non-generic parameters) may break - // overload resolution in the future, if we ever allow overloaded - // local functions. So, just disallow any mixing of dynamic and - // inferred generics. (Explicit generic arguments are fine) - // See https://github.com/dotnet/roslyn/issues/21317 - if (boundMethodGroup.TypeArgumentsOpt.IsDefaultOrEmpty && localFunction.IsGenericMethod) - { - Error(diagnostics, - ErrorCode.ERR_DynamicLocalFunctionTypeParameter, - syntax, localFunction.Name); - return BindDynamicInvocation( - syntax, - boundMethodGroup, - resolution.AnalyzedArguments, - resolution.OverloadResolutionResult.GetAllApplicableMembers(), - diagnostics, - queryClause); + return null; } - return BindInvocationExpressionContinued( + var resultWithSingleCandidate = OverloadResolutionResult.GetInstance(); + resultWithSingleCandidate.ResultsBuilder.Add(methodResolutionResult); + + // PROTOTYPE(ParamsCollections): This code path is affected by https://github.com/dotnet/roslyn/issues/71399 + BoundExpression result = BindInvocationExpressionContinued( node: syntax, expression: expression, methodName: methodName, - result: resolution.OverloadResolutionResult, + result: resultWithSingleCandidate, analyzedArguments: resolution.AnalyzedArguments, methodGroup: resolution.MethodGroup, delegateTypeOpt: null, diagnostics: diagnostics, queryClause: queryClause); + + resultWithSingleCandidate.Free(); + + return result; } - private ImmutableArray GetCandidatesPassingFinalValidation( + private ImmutableArray> GetCandidatesPassingFinalValidation( SyntaxNode syntax, OverloadResolutionResult overloadResolutionResult, BoundExpression receiverOpt, ImmutableArray typeArgumentsOpt, + bool invokedAsExtensionMethod, BindingDiagnosticBag diagnostics) where TMethodOrPropertySymbol : Symbol { Debug.Assert(overloadResolutionResult.HasAnyApplicableMember); - var finalCandidates = ArrayBuilder.GetInstance(); + var finalCandidates = ArrayBuilder>.GetInstance(); BindingDiagnosticBag firstFailed = null; var candidateDiagnostics = BindingDiagnosticBag.GetInstance(diagnostics); @@ -881,10 +948,10 @@ private ImmutableArray GetCandidatesPassingFinalValidat // * If F is an instance method, the method group must have resulted from a simple-name, a member-access through a variable or value, // or a member-access whose receiver can't be classified as a type or value until after overload resolution (see §7.6.4.1). - if (!MemberGroupFinalValidationAccessibilityChecks(receiverOpt, result.Member, syntax, candidateDiagnostics, invokedAsExtensionMethod: false) && + if (!MemberGroupFinalValidationAccessibilityChecks(receiverOpt, result.Member, syntax, candidateDiagnostics, invokedAsExtensionMethod: invokedAsExtensionMethod) && (typeArgumentsOpt.IsDefault || ((MethodSymbol)(object)result.Member).CheckConstraints(new ConstraintsHelper.CheckConstraintsArgs(this.Compilation, this.Conversions, includeNullability: false, syntax.Location, candidateDiagnostics)))) { - finalCandidates.Add(result.Member); + finalCandidates.Add(result); continue; } @@ -1881,7 +1948,7 @@ private BoundCall CreateBadCall( private static bool IsUnboundGeneric(MethodSymbol method) { - return method.IsGenericMethod && method.ConstructedFrom() == method; + return method.IsGenericMethod && method.ConstructedFrom == method; } // Arbitrary limit on the number of parameter lists from overload @@ -2177,7 +2244,7 @@ private void EnsureNameofExpressionSymbols(BoundMethodGroup methodGroup, Binding { // Check that the method group contains something applicable. Otherwise error. CompoundUseSiteInfo useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics); - var resolution = ResolveMethodGroup(methodGroup, analyzedArguments: null, isMethodGroupConversion: false, useSiteInfo: ref useSiteInfo); + var resolution = ResolveMethodGroup(methodGroup, analyzedArguments: null, useSiteInfo: ref useSiteInfo, options: OverloadResolution.Options.None); diagnostics.Add(methodGroup.Syntax, useSiteInfo); diagnostics.AddRange(resolution.Diagnostics); if (resolution.IsExtensionMethodGroup) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs index 91200a736e053..491a87033364c 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs @@ -957,7 +957,7 @@ protected BoundCall MakeQueryInvocation(CSharpSyntaxNode node, BoundExpression r { var methodGroup = (BoundMethodGroup)ultimateReceiver; CompoundUseSiteInfo useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics); - var resolution = this.ResolveMethodGroup(methodGroup, analyzedArguments: null, isMethodGroupConversion: false, useSiteInfo: ref useSiteInfo); + var resolution = this.ResolveMethodGroup(methodGroup, analyzedArguments: null, useSiteInfo: ref useSiteInfo, options: OverloadResolution.Options.None); diagnostics.Add(node, useSiteInfo); diagnostics.AddRange(resolution.Diagnostics); if (resolution.HasAnyErrors) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs index 5254ca9d384dc..23b91a2b6ac92 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs @@ -4050,7 +4050,7 @@ internal PatternLookupResult PerformPatternMethodLookup(BoundExpression receiver analyzedArguments, bindingDiagnostics, queryClause: null, - allowUnexpandedForm: false, + ignoreNormalFormIfHasValidParamsParameter: true, anyApplicableCandidates: out _); analyzedArguments.Free(); diff --git a/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs b/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs index 963e4c98b89ec..d2a0b20057f9f 100644 --- a/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs @@ -1405,7 +1405,8 @@ private MethodArgumentInfo PerformForEachPatternOverloadResolution(SyntaxNode sy receiver: dummyReceiver, arguments: analyzedArguments, result: overloadResolutionResult, - useSiteInfo: ref useSiteInfo); + useSiteInfo: ref useSiteInfo, + options: OverloadResolution.Options.None); diagnostics.Add(collectionSyntax, useSiteInfo); MethodSymbol result = null; @@ -1476,7 +1477,7 @@ private MethodArgumentInfo FindForEachPatternMethodViaExtension(SyntaxNode synta analyzedArguments, collectionExpr, typeArgumentsWithAnnotations: default, - isMethodGroupConversion: false, + options: OverloadResolution.Options.None, returnRefKind: default, returnType: null, withDependencies: diagnostics.AccumulatesDependencies); diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs index 9a78f04f0200c..47e1fcf13453c 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs @@ -284,15 +284,17 @@ private static MethodGroupResolution ResolveDelegateOrFunctionPointerMethodGroup { var analyzedArguments = AnalyzedArguments.GetInstance(); GetDelegateOrFunctionPointerArguments(source.Syntax, analyzedArguments, delegateInvokeMethodOpt.Parameters, binder.Compilation); - var resolution = binder.ResolveMethodGroup(source, analyzedArguments, useSiteInfo: ref useSiteInfo, inferWithDynamic: true, - isMethodGroupConversion: true, returnRefKind: delegateInvokeMethodOpt.RefKind, returnType: delegateInvokeMethodOpt.ReturnType, - isFunctionPointerResolution: isFunctionPointer, callingConventionInfo: callingConventionInfo); + var resolution = binder.ResolveMethodGroup(source, analyzedArguments, useSiteInfo: ref useSiteInfo, + options: OverloadResolution.Options.InferWithDynamic | OverloadResolution.Options.IsMethodGroupConversion | + (isFunctionPointer ? OverloadResolution.Options.IsFunctionPointerResolution : OverloadResolution.Options.None), + returnRefKind: delegateInvokeMethodOpt.RefKind, returnType: delegateInvokeMethodOpt.ReturnType, + callingConventionInfo: callingConventionInfo); analyzedArguments.Free(); return resolution; } else { - return binder.ResolveMethodGroup(source, analyzedArguments: null, isMethodGroupConversion: true, ref useSiteInfo); + return binder.ResolveMethodGroup(source, analyzedArguments: null, ref useSiteInfo, options: OverloadResolution.Options.IsMethodGroupConversion); } } @@ -419,7 +421,7 @@ public Conversion MethodGroupConversion(SyntaxNode syntax, MethodGroup methodGro arguments: analyzedArguments, result: result, useSiteInfo: ref useSiteInfo, - isMethodGroupConversion: true, + options: OverloadResolution.Options.IsMethodGroupConversion, returnRefKind: delegateInvokeMethod.RefKind, returnType: delegateInvokeMethod.ReturnType); var conversion = ToConversion(result, methodGroup, delegateType.DelegateInvokeMethod.ParameterCount); diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs index c5427c2b59a7a..017fc652b6222 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs @@ -1485,10 +1485,12 @@ private TypeWithAnnotations MethodGroupReturnType( Conversions.GetDelegateOrFunctionPointerArguments(source.Syntax, analyzedArguments, delegateParameters, binder.Compilation); var resolution = binder.ResolveMethodGroup(source, analyzedArguments, useSiteInfo: ref useSiteInfo, - isMethodGroupConversion: true, returnRefKind: delegateRefKind, + options: OverloadResolution.Options.IsMethodGroupConversion | + (isFunctionPointerResolution ? OverloadResolution.Options.IsFunctionPointerResolution : OverloadResolution.Options.None), + returnRefKind: delegateRefKind, // Since we are trying to infer the return type, it is not an input to resolving the method group returnType: null, - isFunctionPointerResolution: isFunctionPointerResolution, callingConventionInfo: in callingConventionInfo); + callingConventionInfo: in callingConventionInfo); TypeWithAnnotations type = default; diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs index 60f543e5f07f5..86744c389d7f7 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs @@ -4,6 +4,7 @@ #nullable disable +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; @@ -97,21 +98,36 @@ private static bool SingleValidResult(ArrayBuilder constructors, AnalyzedArguments arguments, OverloadResolutionResult result, ref CompoundUseSiteInfo useSiteInfo) + public void ObjectCreationOverloadResolution(ImmutableArray constructors, AnalyzedArguments arguments, OverloadResolutionResult result, bool dynamicResolution, ref CompoundUseSiteInfo useSiteInfo) { + Debug.Assert(!dynamicResolution || arguments.HasDynamicArgument); + var results = result.ResultsBuilder; // First, attempt overload resolution not getting complete results. - PerformObjectCreationOverloadResolution(results, constructors, arguments, false, ref useSiteInfo); + PerformObjectCreationOverloadResolution(results, constructors, arguments, completeResults: false, dynamicResolution: dynamicResolution, ref useSiteInfo); if (!OverloadResolutionResultIsValid(results, arguments.HasDynamicArgument)) { // We didn't get a single good result. Get full results of overload resolution and return those. result.Clear(); - PerformObjectCreationOverloadResolution(results, constructors, arguments, true, ref useSiteInfo); + PerformObjectCreationOverloadResolution(results, constructors, arguments, completeResults: true, dynamicResolution: dynamicResolution, ref useSiteInfo); } } + [Flags] + public enum Options : byte + { + None = 0, + IsMethodGroupConversion = 0b_00000001, + AllowRefOmittedArguments = 0b_00000010, + InferWithDynamic = 0b_00000100, + IgnoreNormalFormIfHasValidParamsParameter = 0b_00001000, + IsFunctionPointerResolution = 0b_00010000, + IsExtensionMethodResolution = 0b_00100000, + DynamicResolution = 0b_01000000, + } + // Perform overload resolution on the given method group, with the given arguments and // names. The names can be null if no names were supplied to any arguments. public void MethodInvocationOverloadResolution( @@ -121,21 +137,22 @@ public void MethodInvocationOverloadResolution( AnalyzedArguments arguments, OverloadResolutionResult result, ref CompoundUseSiteInfo useSiteInfo, - bool isMethodGroupConversion = false, - bool allowRefOmittedArguments = false, - bool inferWithDynamic = false, - bool allowUnexpandedForm = true, + Options options, RefKind returnRefKind = default, TypeSymbol returnType = null, - bool isFunctionPointerResolution = false, - bool isExtensionMethodResolution = false, in CallingConventionInfo callingConventionInfo = default) { + Debug.Assert((options & Options.DynamicResolution) == 0 || arguments.HasDynamicArgument); + Debug.Assert((options & Options.InferWithDynamic) == 0 || (options & Options.DynamicResolution) == 0); + Debug.Assert((options & Options.IsFunctionPointerResolution) == 0 || (options & Options.DynamicResolution) == 0); + Debug.Assert((options & Options.IsMethodGroupConversion) == 0 || (options & Options.DynamicResolution) == 0); + Debug.Assert((options & Options.InferWithDynamic) == 0 || (options & Options.IsMethodGroupConversion) != 0); + MethodOrPropertyOverloadResolution( methods, typeArguments, receiver, arguments, result, - isMethodGroupConversion, allowRefOmittedArguments, ref useSiteInfo, inferWithDynamic, - allowUnexpandedForm, returnRefKind, returnType, isFunctionPointerResolution: isFunctionPointerResolution, - isExtensionMethodResolution: isExtensionMethodResolution, in callingConventionInfo); + ref useSiteInfo, options, + returnRefKind, returnType, + in callingConventionInfo); } // Perform overload resolution on the given property group, with the given arguments and @@ -145,13 +162,18 @@ public void PropertyOverloadResolution( BoundExpression receiverOpt, AnalyzedArguments arguments, OverloadResolutionResult result, - bool allowRefOmittedArguments, + Options options, ref CompoundUseSiteInfo useSiteInfo) { + Debug.Assert((options & Options.DynamicResolution) == 0 || arguments.HasDynamicArgument); + + options &= (Options.AllowRefOmittedArguments | Options.DynamicResolution); + ArrayBuilder typeArguments = ArrayBuilder.GetInstance(); MethodOrPropertyOverloadResolution( - indexers, typeArguments, receiverOpt, arguments, result, isMethodGroupConversion: false, - allowRefOmittedArguments: allowRefOmittedArguments, useSiteInfo: ref useSiteInfo, + indexers, typeArguments, receiverOpt, arguments, result, + useSiteInfo: ref useSiteInfo, + options, callingConventionInfo: default); typeArguments.Free(); } @@ -162,15 +184,10 @@ internal void MethodOrPropertyOverloadResolution( BoundExpression receiver, AnalyzedArguments arguments, OverloadResolutionResult result, - bool isMethodGroupConversion, - bool allowRefOmittedArguments, ref CompoundUseSiteInfo useSiteInfo, - bool inferWithDynamic = false, - bool allowUnexpandedForm = true, + Options options, RefKind returnRefKind = default, TypeSymbol returnType = null, - bool isFunctionPointerResolution = false, - bool isExtensionMethodResolution = false, in CallingConventionInfo callingConventionInfo = default) where TMember : Symbol { @@ -179,14 +196,14 @@ internal void MethodOrPropertyOverloadResolution( // No need to check for overridden or hidden methods if the members were // resolved as extension methods and the extension methods are defined in // types derived from System.Object. - bool checkOverriddenOrHidden = !(isExtensionMethodResolution && + bool checkOverriddenOrHidden = !((options & Options.IsExtensionMethodResolution) != 0 && members.All(static m => m.ContainingSymbol is NamedTypeSymbol { BaseTypeNoUseSiteDiagnostics.SpecialType: SpecialType.System_Object })); // First, attempt overload resolution not getting complete results. PerformMemberOverloadResolution( - results, members, typeArguments, receiver, arguments, completeResults: false, isMethodGroupConversion, - returnRefKind, returnType, allowRefOmittedArguments, isFunctionPointerResolution, callingConventionInfo, - ref useSiteInfo, inferWithDynamic: inferWithDynamic, allowUnexpandedForm: allowUnexpandedForm, checkOverriddenOrHidden: checkOverriddenOrHidden); + results, members, typeArguments, receiver, arguments, completeResults: false, + returnRefKind, returnType, callingConventionInfo, + ref useSiteInfo, options, checkOverriddenOrHidden: checkOverriddenOrHidden); if (!OverloadResolutionResultIsValid(results, arguments.HasDynamicArgument)) { @@ -194,9 +211,9 @@ internal void MethodOrPropertyOverloadResolution( result.Clear(); PerformMemberOverloadResolution( results, members, typeArguments, receiver, arguments, - completeResults: true, isMethodGroupConversion, returnRefKind, returnType, - allowRefOmittedArguments, isFunctionPointerResolution, callingConventionInfo, - ref useSiteInfo, inferWithDynamic: false, allowUnexpandedForm: allowUnexpandedForm, checkOverriddenOrHidden: checkOverriddenOrHidden); + completeResults: true, returnRefKind, returnType, + callingConventionInfo, + ref useSiteInfo, options, checkOverriddenOrHidden: checkOverriddenOrHidden); } } @@ -241,15 +258,11 @@ private void PerformMemberOverloadResolution( BoundExpression receiver, AnalyzedArguments arguments, bool completeResults, - bool isMethodGroupConversion, RefKind returnRefKind, TypeSymbol returnType, - bool allowRefOmittedArguments, - bool isFunctionPointerResolution, in CallingConventionInfo callingConventionInfo, ref CompoundUseSiteInfo useSiteInfo, - bool inferWithDynamic, - bool allowUnexpandedForm, + Options options, bool checkOverriddenOrHidden) where TMember : Symbol { @@ -281,12 +294,9 @@ private void PerformMemberOverloadResolution( typeArguments, arguments, completeResults, - isMethodGroupConversion, - allowRefOmittedArguments, containingTypeMapOpt, - inferWithDynamic: inferWithDynamic, useSiteInfo: ref useSiteInfo, - allowUnexpandedForm: allowUnexpandedForm, + options, checkOverriddenOrHidden: checkOverriddenOrHidden); } @@ -301,7 +311,21 @@ private void PerformMemberOverloadResolution( // SPEC: The set of candidate methods is reduced to contain only methods from the most derived types. if (checkOverriddenOrHidden) { - RemoveLessDerivedMembers(results, ref useSiteInfo); + if ((options & Options.DynamicResolution) != 0) + { + // 'AddMemberToCandidateSet' takes care of hiding by name and by override, + // but we still need to take care of hiding by signature in order to + // avoid false ambiguous resolution. The 'RemoveLessDerivedMembers' helper, + // however, does more than that and, therefore, is not suitable for our situation. + // That is due to the fact that 'dynamic' converts to anything else, and + // a method applicable at compile time, might actually be inapplicable at runtime, + // therefore shouldn't shadow members with different signature from base, etc. + RemoveHiddenMembers(results); + } + else + { + RemoveLessDerivedMembers(results, ref useSiteInfo); + } } if (Compilation.LanguageVersion.AllowImprovedOverloadCandidates()) @@ -310,13 +334,13 @@ private void PerformMemberOverloadResolution( RemoveConstraintViolations(results, template: new CompoundUseSiteInfo(useSiteInfo)); - if (isMethodGroupConversion) + if ((options & Options.IsMethodGroupConversion) != 0) { - RemoveDelegateConversionsWithWrongReturnType(results, ref useSiteInfo, returnRefKind, returnType, isFunctionPointerResolution); + RemoveDelegateConversionsWithWrongReturnType(results, ref useSiteInfo, returnRefKind, returnType, isFunctionPointerConversion: (options & Options.IsFunctionPointerResolution) != 0); } } - if (isFunctionPointerResolution) + if ((options & Options.IsFunctionPointerResolution) != 0) { RemoveCallingConventionMismatches(results, callingConventionInfo); RemoveMethodsNotDeclaredStatic(results); @@ -334,15 +358,82 @@ private void PerformMemberOverloadResolution( return; } - // SPEC: The best method of the set of candidate methods is identified. If a single best method cannot be identified, - // SPEC: the method invocation is ambiguous, and a binding-time error occurs. + if ((options & Options.DynamicResolution) == 0) + { + // SPEC: The best method of the set of candidate methods is identified. If a single best method cannot be identified, + // SPEC: the method invocation is ambiguous, and a binding-time error occurs. - RemoveWorseMembers(results, arguments, ref useSiteInfo); + RemoveWorseMembers(results, arguments, ref useSiteInfo); + } // Note, the caller is responsible for "final validation", // as that is not part of overload resolution. } + private static readonly ObjectPool> s_HiddenSymbolsSetPool = PooledHashSet.CreatePool(Microsoft.CodeAnalysis.CSharp.Symbols.SymbolEqualityComparer.AllIgnoreOptions); + + private static void RemoveHiddenMembers(ArrayBuilder> results) + where TMember : Symbol + { + PooledHashSet hiddenSymbols = null; + + for (int f = 0; f < results.Count; ++f) + { + var result = results[f]; + + if (!result.Result.IsValid) + { + continue; + } + + foreach (Symbol hidden in getHiddenMembers(result.LeastOverriddenMember.ConstructedFrom())) + { + if (hiddenSymbols == null) + { + hiddenSymbols = s_HiddenSymbolsSetPool.Allocate(); + } + + Debug.Assert(hidden == hidden.ConstructedFrom()); + hiddenSymbols.Add(hidden); + } + } + + if (hiddenSymbols is not null) + { + for (int f = 0; f < results.Count; ++f) + { + var result = results[f]; + + if (!result.Result.IsValid) + { + continue; + } + + if (hiddenSymbols.Contains(result.Member.ConstructedFrom())) + { + results[f] = result.WithResult(MemberAnalysisResult.LessDerived()); + } + } + } + + hiddenSymbols?.Free(); + + static ImmutableArray getHiddenMembers(Symbol member) + { + switch (member) + { + case MethodSymbol method: + return method.OverriddenOrHiddenMembers.HiddenMembers; + case PropertySymbol property: + return property.OverriddenOrHiddenMembers.HiddenMembers; + case EventSymbol @event: + return @event.OverriddenOrHiddenMembers.HiddenMembers; + default: + return ImmutableArray.Empty; + } + } + } + internal void FunctionPointerOverloadResolution( ArrayBuilder funcPtrBuilder, AnalyzedArguments analyzedArguments, @@ -360,12 +451,9 @@ internal void FunctionPointerOverloadResolution( typeArgumentsBuilder, analyzedArguments, completeResults: true, - isMethodGroupConversion: false, - allowRefOmittedArguments: false, + options: Options.None, containingTypeMapOpt: null, - inferWithDynamic: false, - useSiteInfo: ref useSiteInfo, - allowUnexpandedForm: true); + useSiteInfo: ref useSiteInfo); ReportUseSiteInfo(overloadResolutionResult.ResultsBuilder, ref useSiteInfo); } @@ -768,8 +856,7 @@ private MemberAnalysisResult IsConstructorApplicableInNormalForm( arguments.Arguments.Count, argumentAnalysis.ArgsToParamsOpt, arguments.RefKinds, - isMethodGroupConversion: false, - allowRefOmittedArguments: false, + options: Options.None, _binder, hasAnyRefOmittedArgument: out _); @@ -809,8 +896,7 @@ private MemberAnalysisResult IsConstructorApplicableInExpandedForm( arguments.Arguments.Count, argumentAnalysis.ArgsToParamsOpt, arguments.RefKinds, - isMethodGroupConversion: false, - allowRefOmittedArguments: false); + options: Options.None); // A vararg ctor is never applicable in its expanded form because // it is never a params method. @@ -838,12 +924,9 @@ private void AddMemberToCandidateSet( ArrayBuilder typeArguments, AnalyzedArguments arguments, bool completeResults, - bool isMethodGroupConversion, - bool allowRefOmittedArguments, Dictionary> containingTypeMapOpt, - bool inferWithDynamic, ref CompoundUseSiteInfo useSiteInfo, - bool allowUnexpandedForm, + Options options, bool checkOverriddenOrHidden = true) where TMember : Symbol { @@ -952,18 +1035,16 @@ private void AddMemberToCandidateSet( // Second, we need to determine if the method is applicable in its normal form or its expanded form. - var normalResult = (allowUnexpandedForm || !IsValidParams(_binder, leastOverriddenMember)) - ? IsMemberApplicableInNormalForm( + var normalResult = ((options & Options.IgnoreNormalFormIfHasValidParamsParameter) != 0 && IsValidParams(_binder, leastOverriddenMember)) + ? default(MemberResolutionResult) + : IsMemberApplicableInNormalForm( member, leastOverriddenMember, typeArguments, arguments, - isMethodGroupConversion: isMethodGroupConversion, - allowRefOmittedArguments: allowRefOmittedArguments, - inferWithDynamic: inferWithDynamic, + options, completeResults: completeResults, - useSiteInfo: ref useSiteInfo) - : default(MemberResolutionResult); + useSiteInfo: ref useSiteInfo); var result = normalResult; if (!normalResult.Result.IsValid) @@ -973,14 +1054,14 @@ private void AddMemberToCandidateSet( // tricks you can pull to make overriding methods [indexers] inconsistent with overridden // methods [indexers] (or implementing methods [indexers] inconsistent with interfaces). - if (!isMethodGroupConversion && IsValidParams(_binder, leastOverriddenMember)) + if ((options & Options.IsMethodGroupConversion) == 0 && IsValidParams(_binder, leastOverriddenMember)) { var expandedResult = IsMemberApplicableInExpandedForm( member, leastOverriddenMember, typeArguments, arguments, - allowRefOmittedArguments: allowRefOmittedArguments, + allowRefOmittedArguments: (options & Options.AllowRefOmittedArguments) != 0, completeResults: completeResults, useSiteInfo: ref useSiteInfo); @@ -1486,6 +1567,7 @@ private void PerformObjectCreationOverloadResolution( ImmutableArray constructors, AnalyzedArguments arguments, bool completeResults, + bool dynamicResolution, ref CompoundUseSiteInfo useSiteInfo) { // SPEC: The instance constructor to invoke is determined using the overload resolution @@ -1501,10 +1583,13 @@ private void PerformObjectCreationOverloadResolution( ReportUseSiteInfo(results, ref useSiteInfo); - // The best method of the set of candidate methods is identified. If a single best - // method cannot be identified, the method invocation is ambiguous, and a binding-time - // error occurs. - RemoveWorseMembers(results, arguments, ref useSiteInfo); + if (!dynamicResolution) + { + // The best method of the set of candidate methods is identified. If a single best + // method cannot be identified, the method invocation is ambiguous, and a binding-time + // error occurs. + RemoveWorseMembers(results, arguments, ref useSiteInfo); + } return; } @@ -3305,9 +3390,12 @@ internal static void GetEffectiveParameterTypes( out ImmutableArray parameterRefKinds) { bool hasAnyRefOmittedArgument; + Options options = (isMethodGroupConversion ? Options.IsMethodGroupConversion : Options.None) | + (allowRefOmittedArguments ? Options.AllowRefOmittedArguments : Options.None); + EffectiveParameters effectiveParameters = expanded ? - GetEffectiveParametersInExpandedForm(method, argumentCount, argToParamMap, argumentRefKinds, isMethodGroupConversion, allowRefOmittedArguments, binder, out hasAnyRefOmittedArgument) : - GetEffectiveParametersInNormalForm(method, argumentCount, argToParamMap, argumentRefKinds, isMethodGroupConversion, allowRefOmittedArguments, binder, out hasAnyRefOmittedArgument); + GetEffectiveParametersInExpandedForm(method, argumentCount, argToParamMap, argumentRefKinds, options, binder, out hasAnyRefOmittedArgument) : + GetEffectiveParametersInNormalForm(method, argumentCount, argToParamMap, argumentRefKinds, options, binder, out hasAnyRefOmittedArgument); parameterTypes = effectiveParameters.ParameterTypes; parameterRefKinds = effectiveParameters.ParameterRefKinds; } @@ -3333,8 +3421,7 @@ private static EffectiveParameters GetEffectiveParametersInNormalForm( int argumentCount, ImmutableArray argToParamMap, ArrayBuilder argumentRefKinds, - bool isMethodGroupConversion, - bool allowRefOmittedArguments, + Options options, Binder binder, out bool hasAnyRefOmittedArgument) where TMember : Symbol { @@ -3371,7 +3458,7 @@ private static EffectiveParameters GetEffectiveParametersInNormalForm( types.Add(parameter.TypeWithAnnotations); RefKind argRefKind = hasAnyRefArg ? argumentRefKinds[arg] : RefKind.None; - RefKind paramRefKind = GetEffectiveParameterRefKind(parameter, argRefKind, isMethodGroupConversion, allowRefOmittedArguments, binder, ref hasAnyRefOmittedArgument); + RefKind paramRefKind = GetEffectiveParameterRefKind(parameter, argRefKind, options, binder, ref hasAnyRefOmittedArgument); if (refs == null) { @@ -3394,8 +3481,7 @@ private static EffectiveParameters GetEffectiveParametersInNormalForm( private static RefKind GetEffectiveParameterRefKind( ParameterSymbol parameter, RefKind argRefKind, - bool isMethodGroupConversion, - bool allowRefOmittedArguments, + Options options, Binder binder, ref bool hasAnyRefOmittedArgument) { @@ -3406,7 +3492,7 @@ private static RefKind GetEffectiveParameterRefKind( // There are even more relaxations with 'ref readonly' parameters feature: // - 'ref' argument is allowed to match 'in' parameter, // - 'ref', 'in', none argument is allowed to match 'ref readonly' parameter. - if (!isMethodGroupConversion) + if ((options & Options.IsMethodGroupConversion) == 0) { if (paramRefKind == RefKind.In) { @@ -3433,7 +3519,7 @@ private static RefKind GetEffectiveParameterRefKind( // Omit ref feature for COM interop: We can pass arguments by value for ref parameters if we are calling a method/property on an instance of a COM imported type. // We must ignore the 'ref' on the parameter while determining the applicability of argument for the given method call. // During argument rewriting, we will replace the argument value with a temporary local and pass that local by reference. - if (allowRefOmittedArguments && paramRefKind == RefKind.Ref && argRefKind == RefKind.None && !binder.InAttributeArgument) + if ((options & Options.AllowRefOmittedArguments) != 0 && paramRefKind == RefKind.Ref && argRefKind == RefKind.None && !binder.InAttributeArgument) { hasAnyRefOmittedArgument = true; return RefKind.None; @@ -3471,11 +3557,10 @@ private EffectiveParameters GetEffectiveParametersInExpandedForm( int argumentCount, ImmutableArray argToParamMap, ArrayBuilder argumentRefKinds, - bool isMethodGroupConversion, - bool allowRefOmittedArguments) where TMember : Symbol + Options options) where TMember : Symbol { bool discarded; - return GetEffectiveParametersInExpandedForm(member, argumentCount, argToParamMap, argumentRefKinds, isMethodGroupConversion, allowRefOmittedArguments, _binder, hasAnyRefOmittedArgument: out discarded); + return GetEffectiveParametersInExpandedForm(member, argumentCount, argToParamMap, argumentRefKinds, options, _binder, hasAnyRefOmittedArgument: out discarded); } private static EffectiveParameters GetEffectiveParametersInExpandedForm( @@ -3483,8 +3568,7 @@ private static EffectiveParameters GetEffectiveParametersInExpandedForm int argumentCount, ImmutableArray argToParamMap, ArrayBuilder argumentRefKinds, - bool isMethodGroupConversion, - bool allowRefOmittedArguments, + Options options, Binder binder, out bool hasAnyRefOmittedArgument) where TMember : Symbol { @@ -3522,7 +3606,7 @@ private static EffectiveParameters GetEffectiveParametersInExpandedForm } var argRefKind = hasAnyRefArg ? argumentRefKinds[arg] : RefKind.None; - var paramRefKind = GetEffectiveParameterRefKind(parameter, argRefKind, isMethodGroupConversion, allowRefOmittedArguments, binder, ref hasAnyRefOmittedArgument); + var paramRefKind = GetEffectiveParameterRefKind(parameter, argRefKind, options, binder, ref hasAnyRefOmittedArgument); refs.Add(paramRefKind); if (paramRefKind != RefKind.None) @@ -3541,16 +3625,14 @@ private MemberResolutionResult IsMemberApplicableInNormalForm( TMember leastOverriddenMember, // method or property ArrayBuilder typeArguments, AnalyzedArguments arguments, - bool isMethodGroupConversion, - bool allowRefOmittedArguments, - bool inferWithDynamic, + Options options, bool completeResults, ref CompoundUseSiteInfo useSiteInfo) where TMember : Symbol { // AnalyzeArguments matches arguments to parameter names and positions. // For that purpose we use the most derived member. - var argumentAnalysis = AnalyzeArguments(member, arguments, isMethodGroupConversion, expanded: false); + var argumentAnalysis = AnalyzeArguments(member, arguments, isMethodGroupConversion: (options & Options.IsMethodGroupConversion) != 0, expanded: false); if (!argumentAnalysis.IsValid) { switch (argumentAnalysis.Kind) @@ -3583,12 +3665,11 @@ private MemberResolutionResult IsMemberApplicableInNormalForm( arguments.Arguments.Count, argumentAnalysis.ArgsToParamsOpt, arguments.RefKinds, - isMethodGroupConversion, - allowRefOmittedArguments, + options, _binder, out hasAnyRefOmittedArgument); - Debug.Assert(!hasAnyRefOmittedArgument || allowRefOmittedArguments); + Debug.Assert(!hasAnyRefOmittedArgument || (options & Options.AllowRefOmittedArguments) != 0); // The member passed to the following call is returned in the result (possibly a constructed version of it). // The applicability is checked based on effective parameters passed in. @@ -3598,7 +3679,7 @@ private MemberResolutionResult IsMemberApplicableInNormalForm( isExpanded: false, argumentAnalysis.ArgsToParamsOpt, hasAnyRefOmittedArgument: hasAnyRefOmittedArgument, - inferWithDynamic: inferWithDynamic, + inferWithDynamic: (options & Options.InferWithDynamic) != 0, completeResults: completeResults, useSiteInfo: ref useSiteInfo); @@ -3645,8 +3726,7 @@ private MemberResolutionResult IsMemberApplicableInExpandedForm params collections + + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + + + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + + + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 26e8642e672bb..bd8bb43f221ce 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2282,6 +2282,12 @@ internal enum ErrorCode ERR_InvalidExperimentalDiagID = 9211, ERR_SpreadMissingMember = 9212, + ERR_CantInferMethTypeArgs_DynamicArgumentWithParamsCollections = 9501, // PROTOTYPE(ParamsCollections): Pack numbers + ERR_ParamsCollectionAmbiguousDynamicArgument = 9502, + WRN_DynamicDispatchToParamsCollectionMethod = 9503, + WRN_DynamicDispatchToParamsCollectionIndexer = 9504, + WRN_DynamicDispatchToParamsCollectionConstructor = 9505, + #endregion // Note: you will need to do the following after adding warnings: diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs index d442207612fb0..7c2ca9fbc2881 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs @@ -553,6 +553,10 @@ internal static int GetWarningLevel(ErrorCode code) case ErrorCode.WRN_Experimental: case ErrorCode.WRN_CollectionExpressionRefStructMayAllocate: case ErrorCode.WRN_CollectionExpressionRefStructSpreadMayAllocate: + case ErrorCode.WRN_DynamicDispatchToParamsCollectionMethod: + case ErrorCode.WRN_DynamicDispatchToParamsCollectionIndexer: + case ErrorCode.WRN_DynamicDispatchToParamsCollectionConstructor: + return 1; default: return 0; @@ -2410,6 +2414,11 @@ internal static bool IsBuildOnlyDiagnostic(ErrorCode code) case ErrorCode.ERR_CollectionExpressionImmutableArray: case ErrorCode.ERR_InvalidExperimentalDiagID: case ErrorCode.ERR_SpreadMissingMember: + case ErrorCode.ERR_CantInferMethTypeArgs_DynamicArgumentWithParamsCollections: + case ErrorCode.ERR_ParamsCollectionAmbiguousDynamicArgument: + case ErrorCode.WRN_DynamicDispatchToParamsCollectionMethod: + case ErrorCode.WRN_DynamicDispatchToParamsCollectionIndexer: + case ErrorCode.WRN_DynamicDispatchToParamsCollectionConstructor: return false; default: // NOTE: All error codes must be explicitly handled in this switch statement diff --git a/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs b/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs index c8feebec6fef9..5e544c1ca1e79 100644 --- a/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs @@ -337,6 +337,9 @@ public static bool IsWarning(ErrorCode code) case ErrorCode.WRN_Experimental: case ErrorCode.WRN_CollectionExpressionRefStructMayAllocate: case ErrorCode.WRN_CollectionExpressionRefStructSpreadMayAllocate: + case ErrorCode.WRN_DynamicDispatchToParamsCollectionMethod: + case ErrorCode.WRN_DynamicDispatchToParamsCollectionIndexer: + case ErrorCode.WRN_DynamicDispatchToParamsCollectionConstructor: return true; default: return false; diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_StringInterpolation.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_StringInterpolation.cs index 291ca6e5308a2..a148a9ee88dd6 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_StringInterpolation.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_StringInterpolation.cs @@ -27,7 +27,7 @@ private BoundExpression RewriteInterpolatedStringConversion(BoundConversion conv // produced for the arguments until after we've done overload resolution. So we produce the invocation // and then lower it along with its arguments. var result = _factory.StaticCall(stringFactory, "Create", expressions.ToImmutableAndFree(), - allowUnexpandedForm: false // if an interpolation expression is the null literal, it should not match a params parameter. + ignoreNormalFormIfHasValidParamsParameter: true // if an interpolation expression is the null literal, it should not match a params parameter. ); if (!result.HasAnyErrors) { @@ -352,7 +352,7 @@ public override BoundNode VisitInterpolatedString(BoundInterpolatedString node) expressions.Insert(0, format); var stringType = node.Type; result = _factory.StaticCall(stringType, "Format", expressions.ToImmutableAndFree(), - allowUnexpandedForm: false // if an interpolation expression is the null literal, it should not match a params parameter. + ignoreNormalFormIfHasValidParamsParameter: true // if an interpolation expression is the null literal, it should not match a params parameter. ); } diff --git a/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs b/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs index 63ca71c9390ef..c16985cc428f2 100644 --- a/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs +++ b/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs @@ -102,7 +102,7 @@ internal BoundExpression MakeInvocationExpression( ImmutableArray args, BindingDiagnosticBag diagnostics, ImmutableArray typeArgs = default(ImmutableArray), - bool allowUnexpandedForm = true) + bool ignoreNormalFormIfHasValidParamsParameter = false) { if (_binder is null || _binder.Flags != flags) { @@ -117,7 +117,7 @@ internal BoundExpression MakeInvocationExpression( diagnostics, typeArgs: typeArgs.IsDefault ? default(ImmutableArray) : typeArgs.SelectAsArray(t => TypeWithAnnotations.Create(t)), allowFieldsAndProperties: false, - allowUnexpandedForm: allowUnexpandedForm); + ignoreNormalFormIfHasValidParamsParameter: ignoreNormalFormIfHasValidParamsParameter); } /// @@ -744,9 +744,9 @@ public BoundExpression StaticCall(TypeSymbol receiver, string name, params Bound return MakeInvocationExpression(BinderFlags.None, this.Syntax, this.Type(receiver), name, args.ToImmutableArray(), this.Diagnostics); } - public BoundExpression StaticCall(TypeSymbol receiver, string name, ImmutableArray args, bool allowUnexpandedForm) + public BoundExpression StaticCall(TypeSymbol receiver, string name, ImmutableArray args, bool ignoreNormalFormIfHasValidParamsParameter) { - return MakeInvocationExpression(BinderFlags.None, this.Syntax, this.Type(receiver), name, args, this.Diagnostics, allowUnexpandedForm: allowUnexpandedForm); + return MakeInvocationExpression(BinderFlags.None, this.Syntax, this.Type(receiver), name, args, this.Diagnostics, ignoreNormalFormIfHasValidParamsParameter: ignoreNormalFormIfHasValidParamsParameter); } public BoundExpression StaticCall(BinderFlags flags, TypeSymbol receiver, string name, ImmutableArray typeArgs, params BoundExpression[] args) diff --git a/src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs b/src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs index 93c478ea3a88f..2aa0d93d48f98 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs @@ -207,7 +207,7 @@ public static Symbol ConstructedFrom(this Symbol symbol) return ((MethodSymbol)symbol).ConstructedFrom; default: - throw ExceptionUtilities.UnexpectedValue(symbol.Kind); + return symbol; } } diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 94d5055d11f23..12b3ff41042a5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -372,6 +372,11 @@ {0} nelze převést na typ {1}, protože návratový typ se neshoduje s návratovým typem delegáta. + + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + + __arglist cannot have an argument passed by 'in' or 'out' __arglist nemůže mít argument předávaný pomocí in nebo out @@ -1502,6 +1507,11 @@ Funkce parameter null-checking se nepodporuje. + + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + + The params parameter must have a valid collection type The params parameter must have a valid collection type @@ -2587,6 +2597,36 @@ Odkaz analyzátoru byl zadán vícekrát + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + Use of result of '{0}' in this context may expose variables referenced by parameter '{1}' outside of their declaration scope Použití výsledku {0} v tomto kontextu může vystavit proměnné, na které odkazuje parametr {1}, mimo rozsah jejich oboru. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index e2614491e3511..55d0837b0a33c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -372,6 +372,11 @@ {0} kann nicht in den Typ „{1}“ konvertiert werden, da der Rückgabetyp nicht mit dem Rückgabetyp des Delegaten übereinstimmt + + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + + __arglist cannot have an argument passed by 'in' or 'out' "__arglist" darf kein über "in" oder "out" übergebenes Argument umfassen. @@ -1502,6 +1507,11 @@ Das "Parameter null-checking"-Feature wird nicht unterstützt. + + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + + The params parameter must have a valid collection type The params parameter must have a valid collection type @@ -2587,6 +2597,36 @@ Mehrfacher Verweis auf Analysetool + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + Use of result of '{0}' in this context may expose variables referenced by parameter '{1}' outside of their declaration scope Durch die Verwendung des Ergebnisses von "{0}" in diesem Kontext können vom Parameter "{1}" referenzierte Variablen außerhalb ihres Deklarationsbereichs verfügbar gemacht werden. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 5cd27352712b6..5817b69a91897 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -372,6 +372,11 @@ No se puede convertir {0} al tipo "{1}" porque el tipo de valor devuelto no coincide con el tipo de valor devuelto delegado + + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + + __arglist cannot have an argument passed by 'in' or 'out' __arglist no puede tener un argumento que se ha pasado con "in" o "out" @@ -1502,6 +1507,11 @@ No se admite la característica "parameter null-checking". + + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + + The params parameter must have a valid collection type The params parameter must have a valid collection type @@ -2587,6 +2597,36 @@ Referencia del analizador especificada varias veces + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + Use of result of '{0}' in this context may expose variables referenced by parameter '{1}' outside of their declaration scope Usar el resultado de "{0}" en este contexto puede exponer variables a las que el parámetro "{1}" hace referencia fuera de su ámbito de declaración diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 12965ac29aa39..f2d151f1268e5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -372,6 +372,11 @@ Impossible de convertir {0} en type « {1} », car le type de retour ne correspond pas au type de retour délégué + + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + + __arglist cannot have an argument passed by 'in' or 'out' __arglist ne peut pas avoir un argument passé par 'in' ou 'out' @@ -1502,6 +1507,11 @@ La fonctionnalité « paramètre null-checking » n’est pas prise en charge. + + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + + The params parameter must have a valid collection type The params parameter must have a valid collection type @@ -2587,6 +2597,36 @@ Référence de l’analyseur spécifiée plusieurs fois + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + Use of result of '{0}' in this context may expose variables referenced by parameter '{1}' outside of their declaration scope Utiliser un résultat de '{0}' dans ce contexte peut exposer les variables référencées par le paramètre '{1}' en dehors de la portée de leur déclaration diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index f90ee322c6363..edc97a284c779 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -372,6 +372,11 @@ Non è possibile convertire {0} nel tipo ' {1}' perché il tipo restituito non corrisponde al tipo restituito del delegato + + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + + __arglist cannot have an argument passed by 'in' or 'out' __arglist non può contenere un argomento passato da 'in' o 'out' @@ -1502,6 +1507,11 @@ La funzionalità 'parameter null-checking' non è supportata. + + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + + The params parameter must have a valid collection type The params parameter must have a valid collection type @@ -2587,6 +2597,36 @@ Riferimento analizzatore specificato più volte + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + Use of result of '{0}' in this context may expose variables referenced by parameter '{1}' outside of their declaration scope L'uso del risultato di '{0}' in questo contesto può esporre variabili a cui fa riferimento il parametro '{1}' all'esterno del relativo ambito di dichiarazione diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 41289ae4ea548..badf6d95b2e48 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -372,6 +372,11 @@ 戻り値の型がデリゲート戻り値の型と一致しないため、{0} を型 '{1}' に変換できません + + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + + __arglist cannot have an argument passed by 'in' or 'out' __arglist では、'in' や 'out' で引数を渡すことができません @@ -1502,6 +1507,11 @@ 'parameter null-checking' 機能はサポートされていません。 + + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + + The params parameter must have a valid collection type The params parameter must have a valid collection type @@ -2587,6 +2597,36 @@ 複数回指定されたアナライザー参照 + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + Use of result of '{0}' in this context may expose variables referenced by parameter '{1}' outside of their declaration scope このコンテキストで '{0}' の結果を使用すると、パラメーター '{1}' によって参照される変数が宣言のスコープ外に公開される可能性があります diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 1393265ca93ed..b77fa1dc8046f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -372,6 +372,11 @@ 반환 형식이 대리자 반환 형식과 일치하지 않기 때문에 {0}을(를) '{1}' 형식으로 변환할 수 없습니다. + + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + + __arglist cannot have an argument passed by 'in' or 'out' __arglist는 'in' 또는 'out'으로 전달되는 인수를 가질 수 없습니다. @@ -1502,6 +1507,11 @@ 'parameter null-checking' 기능은 지원되지 않습니다. + + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + + The params parameter must have a valid collection type The params parameter must have a valid collection type @@ -2587,6 +2597,36 @@ 여러 번 지정된 분석기 참조 + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + Use of result of '{0}' in this context may expose variables referenced by parameter '{1}' outside of their declaration scope 이 컨텍스트에서 '{0}' 결과를 사용하면 선언 범위 외부에서 '{1}' 매개 변수가 참조하는 변수가 노출될 수 있습니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index ce315f1166d09..9ff325c1166ad 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -372,6 +372,11 @@ Nie można przekonwertować {0} na typ "{1}", ponieważ zwracany typ jest niezgodny ze zwracanym typem delegowania + + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + + __arglist cannot have an argument passed by 'in' or 'out' Element __arglist nie może mieć argumentu przekazywanego przez parametr „in” ani „out” @@ -1502,6 +1507,11 @@ Funkcja „sprawdzanie wartości null parametru” nie jest obsługiwana. + + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + + The params parameter must have a valid collection type The params parameter must have a valid collection type @@ -2587,6 +2597,36 @@ Odwołanie do analizatora określono wiele razy + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + Use of result of '{0}' in this context may expose variables referenced by parameter '{1}' outside of their declaration scope Użycie wyniku „{0}” w tym kontekście może uwidocznić zmienne przywoływane przez parametr „{1}” poza zakresem deklaracji diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 832aaf7cfffe5..75180b74bf9c2 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -372,6 +372,11 @@ Não é possível converter {0} para o tipo '{1}' porque o tipo de retorno não corresponde ao tipo de retorno delegado + + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + + __arglist cannot have an argument passed by 'in' or 'out' __arglist não pode ter um argumento passado por 'in' ou 'out' @@ -1502,6 +1507,11 @@ O recurso de 'verificação nula de parâmetro' não tem suporte. + + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + + The params parameter must have a valid collection type The params parameter must have a valid collection type @@ -2587,6 +2597,36 @@ Referência do analisador especificada várias vezes + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + Use of result of '{0}' in this context may expose variables referenced by parameter '{1}' outside of their declaration scope O uso do resultado de '{0}' nesse contexto pode expor variáveis referenciadas por parâmetro '{1}' fora de seu escopo de declaração diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 1a11fdbc0952a..57a9cfeb63622 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -372,6 +372,11 @@ Невозможно преобразовать {0} в тип "{1}", поскольку возвращаемый тип не совпадает с возвращаемым типом делегата + + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + + __arglist cannot have an argument passed by 'in' or 'out' В __arglist невозможно передать аргумент с помощью in или out @@ -1502,6 +1507,11 @@ Функция "проверка значений NULL параметров" не поддерживается. + + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + + The params parameter must have a valid collection type The params parameter must have a valid collection type @@ -2587,6 +2597,36 @@ Ссылка на анализатор указана несколько раз + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + Use of result of '{0}' in this context may expose variables referenced by parameter '{1}' outside of their declaration scope Использование результата "{0}" в этом контексте может представить переменные, на которые ссылается параметр "{1}", за пределами области их объявления diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 88e4bfc5a6ab5..3d38cc59646e8 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -372,6 +372,11 @@ Dönüş türü temsilci dönüş türüyle eşleşmediğinden {0}, ' {1} ' türüne dönüştürülemiyor + + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + + __arglist cannot have an argument passed by 'in' or 'out' __arglist, 'in' veya 'out' tarafından geçirilen bir bağımsız değişkene sahip olamaz @@ -1502,6 +1507,11 @@ 'Parametre null denetimi' özelliği desteklenmiyor. + + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + + The params parameter must have a valid collection type The params parameter must have a valid collection type @@ -2587,6 +2597,36 @@ Çözümleyici referansı birden çok kez belirtildi + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + Use of result of '{0}' in this context may expose variables referenced by parameter '{1}' outside of their declaration scope Bu bağlamda '{0}' sonucunun kullanılması, '{1}' parametresi tarafından başvurulan değişkenleri bildirim kapsamının dışında gösterebilir. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 0109aceb12540..09765f56109db 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -372,6 +372,11 @@ 无法将 {0} 转换为类型“{1}”,因为返回类型与委托返回类型不匹配 + + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + + __arglist cannot have an argument passed by 'in' or 'out' __arglist 不能有 "in" 或 "out" 传递的参数 @@ -1502,6 +1507,11 @@ 不支持 'parameter null-checking' 功能。 + + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + + The params parameter must have a valid collection type The params parameter must have a valid collection type @@ -2587,6 +2597,36 @@ 已多次指定分析器引用 + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + Use of result of '{0}' in this context may expose variables referenced by parameter '{1}' outside of their declaration scope 在此上下文中使用“{0}”的结果可能会在变量声明范围以外公开由参数“{1}”引用的变量 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index b493e910af114..1bac80eac638b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -372,6 +372,11 @@ 無法將 {0} 轉換成類型 '{1}',因為傳回型別不符合委派傳回型別 + + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + + __arglist cannot have an argument passed by 'in' or 'out' __arglist 不得包含 'in' 或 'out' 傳遞的引數 @@ -1502,6 +1507,11 @@ 不支援 'parameter null-checking' 功能。 + + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + + The params parameter must have a valid collection type The params parameter must have a valid collection type @@ -2587,6 +2597,36 @@ 已指定多次分析器參考 + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + + + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + + Use of result of '{0}' in this context may expose variables referenced by parameter '{1}' outside of their declaration scope 在此內容中使用 '{0}' 的結果,可能會將參數 '{1}' 參考的變數公開在其宣告範圍外 diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDynamicTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDynamicTests.cs index 407a1feb30ece..d25b343adfaac 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDynamicTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDynamicTests.cs @@ -236,7 +236,7 @@ public void Missing_Binder() class C { public C(int a) { } - + public C(long a) { } void F(dynamic d) { new C(d.M(d.M = d[-d], d[(int)d()] = d * d.M)); @@ -6275,6 +6275,10 @@ public int F(C a, C b, double c) { return 1; } + public int F(C a, C b, string c) + { + return 1; + } }"; CompileAndVerifyIL(source, "C.M", @" { @@ -6344,6 +6348,10 @@ public int F(C a, C b, double c) { return 1; } + public int F(C a, C b, string c) + { + return 1; + } }"; CompileAndVerifyIL(source, "C.M", @" { @@ -6413,6 +6421,10 @@ public int F(C a, C b, double c) { return 1; } + public int F(C a, C b, string c) + { + return 1; + } }"; CompileAndVerifyIL(source, "C.M", @" { @@ -6477,6 +6489,7 @@ public void InvokeMember_Static_Outer() public class A { public static void M(int x) { } + public static void M(double x) { } public class B { @@ -6541,6 +6554,7 @@ public void InvokeMember_Static_Outer_AmbiguousAtRuntime() public class A { public static void M(A x) { } + public static void M(double x) { } public void M(string x) { } public class B @@ -6627,10 +6641,12 @@ public static void M1(string s) { } public static void M1(int s) { } public static void M2(string s) { } + public static void M2(double s) { } public void M2(int s) { } public void M2(int s, int q) { } public void M3(int s) { } + public void M3(string s) { } public static void M3(int s, int q) { } } @@ -6755,10 +6771,12 @@ public static void M1(string s) { } public static void M1(int s) { } public static void M2(string s) { } + public static void M2(double s) { } public void M2(int s) { } public void M2(int s, int q) { } public void M3(int s) { } + public void M3(string s) { } public static void M3(int s, int q) { } } @@ -6886,10 +6904,12 @@ public static void M1(string s) { } public static void M1(int s) { } public static void M2(string s) { } + public static void M2(double s) { } public void M2(int s) { } public void M2(int s, int q) { } public void M3(int s) { } + public void M3(string s) { } public static void M3(int s, int q) { } } @@ -7012,10 +7032,12 @@ public static void M1(string s) { } public static void M1(int s) { } public static void M2(string s) { } + public static void M2(double s) { } public void M2(int s) { } public void M2(int s, int q) { } public void M3(int s) { } + public void M3(string s) { } public static void M3(int s, int q) { } } @@ -7140,10 +7162,12 @@ public static void M1(string s) { } public static void M1(int s) { } public static void M2(string s) { } + public static void M2(double s) { } public void M2(int s) { } public void M2(int s, int q) { } public void M3(int s) { } + public void M3(string s) { } public static void M3(int s, int q) { } } @@ -7266,10 +7290,12 @@ public static void M1(string s) { } public static void M1(int s) { } public static void M2(string s) { } + public static void M2(double s) { } public void M2(int s) { } public void M2(int s, int q) { } public void M3(int s) { } + public void M3(string s) { } public static void M3(int s, int q) { } } @@ -7393,6 +7419,7 @@ public void InvokeMember_ColorColor_InFieldInitializer() public class Color { public int F(int a) { return 1; } + public int F(long a) { return 1; } } public class C @@ -7453,6 +7480,7 @@ public void InvokeMember_ColorColor_InScriptVariableInitializer() public class Color { public int F(int a) { return 1; } + public int F(long a) { return 1; } } "; var lib = CreateCompilation(sourceLib); @@ -7546,6 +7574,7 @@ public void InvokeMember_ColorColor_InScriptMethod() public class Color { public int F(int a) { return 1; } + public int F(long a) { return 1; } } "; var lib = CreateCompilation(sourceLib); @@ -7936,6 +7965,10 @@ public int F(C a, C b, double c) { return 1; } + public int F(C a, C b, string c) + { + return 1; + } }"; CompileAndVerifyIL(source, "C.M", @" { @@ -8808,6 +8841,12 @@ public void M() f(d, d, ref lo, out ld); } + + public void f(ref long a, out int b, ref dynamic c, out object d) + { + b = 1; + d = null; + } }"; CompileAndVerifyIL(source, "C.M", @" { @@ -8890,6 +8929,7 @@ public void M(dynamic d) public class D { public static void F(int a) {} + public static void F(long a) {} } "; CompileAndVerifyIL(source, "C.M", @" @@ -8939,7 +8979,7 @@ public class C { static dynamic d = true; - public static void f(dynamic d) + public static void f(bool d) { } @@ -8947,6 +8987,10 @@ public static void M() { f(d); } + + public static void f(int d) + { + } }"; CompileAndVerifyIL(source, "C.M", @" { @@ -8999,6 +9043,9 @@ static void Goo(dynamic x) { System.Action a = () => Goo(x); } + static void Goo(int x) + { + } } "; CompileAndVerifyIL(source, "C.<>c__DisplayClass0_0.b__0", @" @@ -9058,6 +9105,7 @@ public struct S { public int X; public void goo(int a) {} + public void goo(long a) {} } "; // Dev11 produces more efficient code, see bug 547265: @@ -9119,6 +9167,7 @@ public struct S { public int X; public void goo(int a) {} + public void goo(long a) {} } "; CompileAndVerifyIL(source, "C.M", @" @@ -9172,6 +9221,8 @@ public void M(dynamic d) { this.Equals(d); } + + bool Equals(int i) => false; } "; CompileAndVerifyIL(source, "S.M", @" @@ -9231,6 +9282,7 @@ public struct S { public int X; public void goo(int a) {} + public void goo(long a) {} } "; CompileAndVerifyIL(source, "C.M", @" @@ -9291,6 +9343,7 @@ public struct S { public int X; public void goo(int a) {} + public void goo(long a) {} } "; CompileAndVerifyIL(source, "C.M", @" @@ -9355,6 +9408,7 @@ public struct S { public int X; public void goo(int a) {} + public void goo(long a) {} } "; // Dev11 produces more efficient code, see bug 547265: @@ -9424,6 +9478,7 @@ public struct S { public int X; public void goo(int a) {} + public void goo(long a) {} } "; // Dev11 produces more efficient code, see bug 547265: @@ -9492,6 +9547,7 @@ public struct S { public int X; public void goo(int a) {} + public void goo(long a) {} } "; // Dev11 produces more efficient code, see bug 547265: @@ -9672,6 +9728,7 @@ public struct S { public int X; public void goo(int a) {} + public void goo(long a) {} } "; CompileAndVerifyIL(source, "C.M", @" @@ -9732,6 +9789,7 @@ public struct S { public int X; public void goo(int a) {} + public void goo(long a) {} } "; CompileAndVerifyIL(source, "C.M", @" @@ -9792,6 +9850,7 @@ public struct S { public int X; public void goo(int a) {} + public void goo(long a) {} } "; CompileAndVerifyIL(source, "C.M", @" @@ -9850,6 +9909,7 @@ public struct S { public int X; public void goo(int a) {} + public void goo(long a) {} } "; CompileAndVerifyIL(source, "C.M", @" @@ -10188,10 +10248,10 @@ .maxstack 7 } [Fact] - public void Invoke_Static() + public void Invoke_Static_01() { string source = @" -public delegate int F(int a, bool b, C c); +public delegate int F(int a, bool b, params C[] c); public class C { @@ -10251,6 +10311,76 @@ .maxstack 7 "); } + [Fact] + public void Invoke_Static_02() + { + string source = @" +public delegate int F(int a, bool b, C c); + +public class C +{ + public dynamic M(F f, dynamic d) + { + return f(d, d, d); + } +}"; + CompileAndVerifyIL(source, "C.M", @" +{ + // Code size 204 (0xcc) + .maxstack 6 + IL_0000: ldarg.1 + IL_0001: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__0"" + IL_0006: brtrue.s IL_002c + IL_0008: ldc.i4.0 + IL_0009: ldtoken ""int"" + IL_000e: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)"" + IL_0013: ldtoken ""C"" + IL_0018: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)"" + IL_001d: call ""System.Runtime.CompilerServices.CallSiteBinder Microsoft.CSharp.RuntimeBinder.Binder.Convert(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, System.Type, System.Type)"" + IL_0022: call ""System.Runtime.CompilerServices.CallSite> System.Runtime.CompilerServices.CallSite>.Create(System.Runtime.CompilerServices.CallSiteBinder)"" + IL_0027: stsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__0"" + IL_002c: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__0"" + IL_0031: ldfld ""System.Func System.Runtime.CompilerServices.CallSite>.Target"" + IL_0036: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__0"" + IL_003b: ldarg.2 + IL_003c: callvirt ""int System.Func.Invoke(System.Runtime.CompilerServices.CallSite, object)"" + IL_0041: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__1"" + IL_0046: brtrue.s IL_006c + IL_0048: ldc.i4.0 + IL_0049: ldtoken ""bool"" + IL_004e: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)"" + IL_0053: ldtoken ""C"" + IL_0058: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)"" + IL_005d: call ""System.Runtime.CompilerServices.CallSiteBinder Microsoft.CSharp.RuntimeBinder.Binder.Convert(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, System.Type, System.Type)"" + IL_0062: call ""System.Runtime.CompilerServices.CallSite> System.Runtime.CompilerServices.CallSite>.Create(System.Runtime.CompilerServices.CallSiteBinder)"" + IL_0067: stsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__1"" + IL_006c: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__1"" + IL_0071: ldfld ""System.Func System.Runtime.CompilerServices.CallSite>.Target"" + IL_0076: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__1"" + IL_007b: ldarg.2 + IL_007c: callvirt ""bool System.Func.Invoke(System.Runtime.CompilerServices.CallSite, object)"" + IL_0081: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__2"" + IL_0086: brtrue.s IL_00ac + IL_0088: ldc.i4.0 + IL_0089: ldtoken ""C"" + IL_008e: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)"" + IL_0093: ldtoken ""C"" + IL_0098: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)"" + IL_009d: call ""System.Runtime.CompilerServices.CallSiteBinder Microsoft.CSharp.RuntimeBinder.Binder.Convert(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, System.Type, System.Type)"" + IL_00a2: call ""System.Runtime.CompilerServices.CallSite> System.Runtime.CompilerServices.CallSite>.Create(System.Runtime.CompilerServices.CallSiteBinder)"" + IL_00a7: stsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__2"" + IL_00ac: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__2"" + IL_00b1: ldfld ""System.Func System.Runtime.CompilerServices.CallSite>.Target"" + IL_00b6: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__2"" + IL_00bb: ldarg.2 + IL_00bc: callvirt ""C System.Func.Invoke(System.Runtime.CompilerServices.CallSite, object)"" + IL_00c1: callvirt ""int F.Invoke(int, bool, C)"" + IL_00c6: box ""int"" + IL_00cb: ret +} +"); + } + [Fact] public void Invoke_Invoke() { @@ -10358,6 +10488,10 @@ static object Goo(object x) { return x; } + static object Goo(int x) + { + return x; + } }"; CompileAndVerifyIL(source, "C..ctor", @" { @@ -10430,8 +10564,10 @@ class C : B { C(dynamic x) : base((int)Goo(x)) { } - static Action Goo; + static D Goo; } + +delegate void D(params object[] x); "; CompileAndVerifyIL(source, "C..ctor", @" { @@ -10451,7 +10587,7 @@ .maxstack 10 IL_002d: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__1"" IL_0032: ldfld ""System.Func System.Runtime.CompilerServices.CallSite>.Target"" IL_0037: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__1"" - IL_003c: ldsfld ""System.Runtime.CompilerServices.CallSite, object, object>> C.<>o__0.<>p__0"" + IL_003c: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__0"" IL_0041: brtrue.s IL_0077 IL_0043: ldc.i4.0 IL_0044: ldtoken ""C"" @@ -10471,14 +10607,14 @@ .maxstack 10 IL_0062: call ""Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, string)"" IL_0067: stelem.ref IL_0068: call ""System.Runtime.CompilerServices.CallSiteBinder Microsoft.CSharp.RuntimeBinder.Binder.Invoke(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, System.Type, System.Collections.Generic.IEnumerable)"" - IL_006d: call ""System.Runtime.CompilerServices.CallSite, object, object>> System.Runtime.CompilerServices.CallSite, object, object>>.Create(System.Runtime.CompilerServices.CallSiteBinder)"" - IL_0072: stsfld ""System.Runtime.CompilerServices.CallSite, object, object>> C.<>o__0.<>p__0"" - IL_0077: ldsfld ""System.Runtime.CompilerServices.CallSite, object, object>> C.<>o__0.<>p__0"" - IL_007c: ldfld ""System.Func, object, object> System.Runtime.CompilerServices.CallSite, object, object>>.Target"" - IL_0081: ldsfld ""System.Runtime.CompilerServices.CallSite, object, object>> C.<>o__0.<>p__0"" - IL_0086: ldsfld ""System.Action C.Goo"" + IL_006d: call ""System.Runtime.CompilerServices.CallSite> System.Runtime.CompilerServices.CallSite>.Create(System.Runtime.CompilerServices.CallSiteBinder)"" + IL_0072: stsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__0"" + IL_0077: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__0"" + IL_007c: ldfld ""System.Func System.Runtime.CompilerServices.CallSite>.Target"" + IL_0081: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__0"" + IL_0086: ldsfld ""D C.Goo"" IL_008b: ldarg.1 - IL_008c: callvirt ""object System.Func, object, object>.Invoke(System.Runtime.CompilerServices.CallSite, System.Action, object)"" + IL_008c: callvirt ""object System.Func.Invoke(System.Runtime.CompilerServices.CallSite, D, object)"" IL_0091: callvirt ""int System.Func.Invoke(System.Runtime.CompilerServices.CallSite, object)"" IL_0096: call ""B..ctor(int)"" IL_009b: ret @@ -10501,8 +10637,10 @@ class C : B { C(dynamic x) : base((int)Goo(x)) { } - static Action Goo { get; set; } + static D Goo { get; set; } } + +delegate void D(params object[] x); "; CompileAndVerifyIL(source, "C..ctor", @" { @@ -10522,7 +10660,7 @@ .maxstack 10 IL_002d: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__1"" IL_0032: ldfld ""System.Func System.Runtime.CompilerServices.CallSite>.Target"" IL_0037: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__1"" - IL_003c: ldsfld ""System.Runtime.CompilerServices.CallSite, object, object>> C.<>o__0.<>p__0"" + IL_003c: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__0"" IL_0041: brtrue.s IL_0077 IL_0043: ldc.i4.0 IL_0044: ldtoken ""C"" @@ -10542,14 +10680,14 @@ .maxstack 10 IL_0062: call ""Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, string)"" IL_0067: stelem.ref IL_0068: call ""System.Runtime.CompilerServices.CallSiteBinder Microsoft.CSharp.RuntimeBinder.Binder.Invoke(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, System.Type, System.Collections.Generic.IEnumerable)"" - IL_006d: call ""System.Runtime.CompilerServices.CallSite, object, object>> System.Runtime.CompilerServices.CallSite, object, object>>.Create(System.Runtime.CompilerServices.CallSiteBinder)"" - IL_0072: stsfld ""System.Runtime.CompilerServices.CallSite, object, object>> C.<>o__0.<>p__0"" - IL_0077: ldsfld ""System.Runtime.CompilerServices.CallSite, object, object>> C.<>o__0.<>p__0"" - IL_007c: ldfld ""System.Func, object, object> System.Runtime.CompilerServices.CallSite, object, object>>.Target"" - IL_0081: ldsfld ""System.Runtime.CompilerServices.CallSite, object, object>> C.<>o__0.<>p__0"" - IL_0086: call ""System.Action C.Goo.get"" + IL_006d: call ""System.Runtime.CompilerServices.CallSite> System.Runtime.CompilerServices.CallSite>.Create(System.Runtime.CompilerServices.CallSiteBinder)"" + IL_0072: stsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__0"" + IL_0077: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__0"" + IL_007c: ldfld ""System.Func System.Runtime.CompilerServices.CallSite>.Target"" + IL_0081: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__0"" + IL_0086: call ""D C.Goo.get"" IL_008b: ldarg.1 - IL_008c: callvirt ""object System.Func, object, object>.Invoke(System.Runtime.CompilerServices.CallSite, System.Action, object)"" + IL_008c: callvirt ""object System.Func.Invoke(System.Runtime.CompilerServices.CallSite, D, object)"" IL_0091: callvirt ""int System.Func.Invoke(System.Runtime.CompilerServices.CallSite, object)"" IL_0096: call ""B..ctor(int)"" IL_009b: ret @@ -11135,6 +11273,8 @@ public dynamic M(dynamic d) { return a.b[d]; } + + int this[long i] { get { return 0; } set { } } }"; CompileAndVerifyIL(source, "C.M", @" { @@ -11188,6 +11328,11 @@ Public ReadOnly Property IndexedProperty(arg As Integer) As Integer Return arg End Get End Property + Public ReadOnly Property IndexedProperty(arg As Long) As Long + Get + Return arg + End Get + End Property End Class "; var vb = CreateVisualBasicCompilation(GetUniqueName(), vbSource); @@ -11283,6 +11428,13 @@ End Get Set End Set End Property + Public Property IndexedProperty(arg As Long) As Long + Get + Return arg + End Get + Set + End Set + End Property End Class "; var vb = CreateVisualBasicCompilation(GetUniqueName(), vbSource); @@ -11385,6 +11537,13 @@ End Get Set End Set End Property + Public Property IndexedProperty(arg As Long) As Long + Get + Return arg + End Get + Set + End Set + End Property End Class "; var vb = CreateVisualBasicCompilation(GetUniqueName(), vbSource); @@ -11561,9 +11720,11 @@ public void GetIndex_IndexerWithByRefParam() var ilRef = MetadataReference.CreateFromImage(TestResources.MetadataTests.Interop.IndexerWithByRefParam.AsImmutableOrNull()); string source = @" +using System.Runtime.InteropServices; + class C { - B b; + BB b; dynamic d; object M() @@ -11571,12 +11732,18 @@ object M() return b[d]; } } + +[ComImport, Guid(""0002095E-0000-0000-C000-000000000046"")] +interface BB : B +{ + long this[long x] {get;} +} "; CompileAndVerifyIL(source, "C.M", references: new MetadataReference[] { SystemCoreRef, CSharpRef, ilRef }, expectedOptimizedIL: @" { // Code size 92 (0x5c) .maxstack 7 - IL_0000: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__2.<>p__0"" + IL_0000: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__2.<>p__0"" IL_0005: brtrue.s IL_003b IL_0007: ldc.i4.0 IL_0008: ldtoken ""C"" @@ -11596,16 +11763,16 @@ .maxstack 7 IL_0026: call ""Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, string)"" IL_002b: stelem.ref IL_002c: call ""System.Runtime.CompilerServices.CallSiteBinder Microsoft.CSharp.RuntimeBinder.Binder.GetIndex(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, System.Type, System.Collections.Generic.IEnumerable)"" - IL_0031: call ""System.Runtime.CompilerServices.CallSite> System.Runtime.CompilerServices.CallSite>.Create(System.Runtime.CompilerServices.CallSiteBinder)"" - IL_0036: stsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__2.<>p__0"" - IL_003b: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__2.<>p__0"" - IL_0040: ldfld ""System.Func System.Runtime.CompilerServices.CallSite>.Target"" - IL_0045: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__2.<>p__0"" + IL_0031: call ""System.Runtime.CompilerServices.CallSite> System.Runtime.CompilerServices.CallSite>.Create(System.Runtime.CompilerServices.CallSiteBinder)"" + IL_0036: stsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__2.<>p__0"" + IL_003b: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__2.<>p__0"" + IL_0040: ldfld ""System.Func System.Runtime.CompilerServices.CallSite>.Target"" + IL_0045: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__2.<>p__0"" IL_004a: ldarg.0 - IL_004b: ldfld ""B C.b"" + IL_004b: ldfld ""BB C.b"" IL_0050: ldarg.0 IL_0051: ldfld ""dynamic C.d"" - IL_0056: callvirt ""object System.Func.Invoke(System.Runtime.CompilerServices.CallSite, B, object)"" + IL_0056: callvirt ""object System.Func.Invoke(System.Runtime.CompilerServices.CallSite, BB, object)"" IL_005b: ret } "); @@ -11859,7 +12026,7 @@ .maxstack 8 } [Fact] - public void SetIndex_ValueTypeReceiver_Local() + public void SetIndex_ValueTypeReceiver_Local_01() { string source = @" public class C @@ -11875,6 +12042,7 @@ public struct S { public int X; public int this[int index] { get { return index; } set { } } + public long this[long index] { get { return index; } set { } } } "; // Dev11 produces more efficient code, see bug 547265: @@ -11925,6 +12093,56 @@ .locals init (S V_0) //s }"); } + [Fact] + public void SetIndex_ValueTypeReceiver_Local_02() + { + string source = @" +public class C +{ + public void M(dynamic d) + { + S s = new S(); + s[d] = 1; + } +} + +public struct S +{ + public int X; + public int this[int index] { get { return index; } set { } } +} +"; + + CompileAndVerifyIL(source, "C.M", @" +{ + // Code size 81 (0x51) + .maxstack 4 + .locals init (S V_0) //s + IL_0000: ldloca.s V_0 + IL_0002: initobj ""S"" + IL_0008: ldloca.s V_0 + IL_000a: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__0"" + IL_000f: brtrue.s IL_0035 + IL_0011: ldc.i4.0 + IL_0012: ldtoken ""int"" + IL_0017: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)"" + IL_001c: ldtoken ""C"" + IL_0021: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)"" + IL_0026: call ""System.Runtime.CompilerServices.CallSiteBinder Microsoft.CSharp.RuntimeBinder.Binder.Convert(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, System.Type, System.Type)"" + IL_002b: call ""System.Runtime.CompilerServices.CallSite> System.Runtime.CompilerServices.CallSite>.Create(System.Runtime.CompilerServices.CallSiteBinder)"" + IL_0030: stsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__0"" + IL_0035: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__0"" + IL_003a: ldfld ""System.Func System.Runtime.CompilerServices.CallSite>.Target"" + IL_003f: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__0.<>p__0"" + IL_0044: ldarg.1 + IL_0045: callvirt ""int System.Func.Invoke(System.Runtime.CompilerServices.CallSite, object)"" + IL_004a: ldc.i4.1 + IL_004b: call ""void S.this[int].set"" + IL_0050: ret +} +"); + } + [Fact] public void SetMember() { @@ -14406,6 +14624,8 @@ void M(dynamic d) { d } }; } + + public void Add(long a) { } } "; CompileAndVerifyIL(source, "C.M", @" diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenShortCircuitOperatorTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenShortCircuitOperatorTests.cs index 1e209dcbeab81..063c9eaf72adb 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenShortCircuitOperatorTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenShortCircuitOperatorTests.cs @@ -2580,6 +2580,7 @@ class Program interface IDisposable1 { void Dispose(int i); + void Dispose(long i); } class C1 : IDisposable1 @@ -2591,6 +2592,9 @@ public void Dispose(int i) System.Console.WriteLine(disposed); disposed = true; } + public void Dispose(long i) + { + } } struct S1 : IDisposable1 @@ -2602,6 +2606,9 @@ public void Dispose(int i) System.Console.WriteLine(disposed); disposed = true; } + public void Dispose(long i) + { + } } static void Main(string[] args) diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTests.cs index 1cbdb9c050c71..01f5760ca2a16 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTests.cs @@ -15531,6 +15531,7 @@ class M object a = Test((dynamic)2); static object Test(object obj) => obj; + static object Test(string obj) => obj; static void Main() { @@ -15547,7 +15548,7 @@ static void Main() // Code size 115 (0x73) .maxstack 10 IL_0000: ldarg.0 - IL_0001: ldsfld ""System.Runtime.CompilerServices.CallSite> M.<>o__3.<>p__0"" + IL_0001: ldsfld ""System.Runtime.CompilerServices.CallSite> M.<>o__4.<>p__0"" IL_0006: brtrue.s IL_0043 IL_0008: ldc.i4.0 IL_0009: ldstr ""Test"" @@ -15570,10 +15571,10 @@ .maxstack 10 IL_0033: stelem.ref IL_0034: call ""System.Runtime.CompilerServices.CallSiteBinder Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, string, System.Collections.Generic.IEnumerable, System.Type, System.Collections.Generic.IEnumerable)"" IL_0039: call ""System.Runtime.CompilerServices.CallSite> System.Runtime.CompilerServices.CallSite>.Create(System.Runtime.CompilerServices.CallSiteBinder)"" - IL_003e: stsfld ""System.Runtime.CompilerServices.CallSite> M.<>o__3.<>p__0"" - IL_0043: ldsfld ""System.Runtime.CompilerServices.CallSite> M.<>o__3.<>p__0"" + IL_003e: stsfld ""System.Runtime.CompilerServices.CallSite> M.<>o__4.<>p__0"" + IL_0043: ldsfld ""System.Runtime.CompilerServices.CallSite> M.<>o__4.<>p__0"" IL_0048: ldfld ""System.Func System.Runtime.CompilerServices.CallSite>.Target"" - IL_004d: ldsfld ""System.Runtime.CompilerServices.CallSite> M.<>o__3.<>p__0"" + IL_004d: ldsfld ""System.Runtime.CompilerServices.CallSite> M.<>o__4.<>p__0"" IL_0052: ldtoken ""M"" IL_0057: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)"" IL_005c: ldc.i4.2 @@ -15597,9 +15598,11 @@ class M { // inner call is dynamic parameter, static argument // outer call is dynamic parameter, dynamic argument - object a = Test(Test(2)); + object a = Test2(Test(2)); static dynamic Test(dynamic obj) => obj; + static dynamic Test2(int obj) => obj; + static dynamic Test2(long obj) => obj; static void Main() { @@ -15615,10 +15618,10 @@ static void Main() // Code size 120 (0x78) .maxstack 10 IL_0000: ldarg.0 - IL_0001: ldsfld ""System.Runtime.CompilerServices.CallSite> M.<>o__3.<>p__0"" + IL_0001: ldsfld ""System.Runtime.CompilerServices.CallSite> M.<>o__5.<>p__0"" IL_0006: brtrue.s IL_0043 IL_0008: ldc.i4.0 - IL_0009: ldstr ""Test"" + IL_0009: ldstr ""Test2"" IL_000e: ldnull IL_000f: ldtoken ""M"" IL_0014: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)"" @@ -15638,10 +15641,10 @@ .maxstack 10 IL_0033: stelem.ref IL_0034: call ""System.Runtime.CompilerServices.CallSiteBinder Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, string, System.Collections.Generic.IEnumerable, System.Type, System.Collections.Generic.IEnumerable)"" IL_0039: call ""System.Runtime.CompilerServices.CallSite> System.Runtime.CompilerServices.CallSite>.Create(System.Runtime.CompilerServices.CallSiteBinder)"" - IL_003e: stsfld ""System.Runtime.CompilerServices.CallSite> M.<>o__3.<>p__0"" - IL_0043: ldsfld ""System.Runtime.CompilerServices.CallSite> M.<>o__3.<>p__0"" + IL_003e: stsfld ""System.Runtime.CompilerServices.CallSite> M.<>o__5.<>p__0"" + IL_0043: ldsfld ""System.Runtime.CompilerServices.CallSite> M.<>o__5.<>p__0"" IL_0048: ldfld ""System.Func System.Runtime.CompilerServices.CallSite>.Target"" - IL_004d: ldsfld ""System.Runtime.CompilerServices.CallSite> M.<>o__3.<>p__0"" + IL_004d: ldsfld ""System.Runtime.CompilerServices.CallSite> M.<>o__5.<>p__0"" IL_0052: ldtoken ""M"" IL_0057: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)"" IL_005c: ldc.i4.2 @@ -15685,7 +15688,48 @@ static void Main() [WorkItem(10463, "https://github.com/dotnet/roslyn/issues/10463")] [Fact] - public void FieldInitializerDynamicBothStaticInstance() + public void FieldInitializerDynamicBothStaticInstance_01() + { + string source = @" +using System; + +class M +{ + object a = Test((dynamic)2L); + object b = Test((dynamic)2); + + static object Test(long obj) + { + Console.Write(""long.""); + return obj; + } + + object Test(int obj) + { + Console.Write(""int.""); + return obj; + } + + static void Main() + { + try + { + Console.Write(new M().a); + } + catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException ex) + { + Console.Write(""ex caught""); + } + } +} +"; + + var compilation = CompileAndVerifyWithMscorlib40(source, new[] { SystemCoreRef, CSharpRef }, expectedOutput: "long.long.2"); + } + + [WorkItem(10463, "https://github.com/dotnet/roslyn/issues/10463")] + [Fact] + public void FieldInitializerDynamicBothStaticInstance_02() { string source = @" using System; @@ -15707,6 +15751,11 @@ object Test(int obj) return obj; } + static object Test(byte obj) + { + return obj; + } + static void Main() { try diff --git a/src/Compilers/CSharp/Test/Emit/PDB/PDBDynamicLocalsTests.cs b/src/Compilers/CSharp/Test/Emit/PDB/PDBDynamicLocalsTests.cs index b7b1ae6cca98a..a1f47885298b6 100644 --- a/src/Compilers/CSharp/Test/Emit/PDB/PDBDynamicLocalsTests.cs +++ b/src/Compilers/CSharp/Test/Emit/PDB/PDBDynamicLocalsTests.cs @@ -17,7 +17,7 @@ public class PDBDynamicLocalsTests : CSharpTestBase public void EmitPDBDynamicObjectVariable1() { string source = WithWindowsLineBreaks(@" -class Helper +partial class Helper { int x; public void goo(int y){} @@ -40,7 +40,12 @@ public static void Main(string[] args) Helper d5 = new Helper(d1); } -}"); +} +partial class Helper +{ + public Helper(long y){} +} +"); var c = CreateCompilationWithMscorlib40AndSystemCore(source, references: new[] { CSharpRef }, options: TestOptions.DebugDll); c.VerifyPdb(@" @@ -79,6 +84,16 @@ public static void Main(string[] args) + + + + + + + + + + diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/ParamsCollectionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/ParamsCollectionTests.cs index 0d93fdc754b78..35f897aff2456 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/ParamsCollectionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/ParamsCollectionTests.cs @@ -1869,5 +1869,2115 @@ static void Test(int y, params long[] x) Diagnostic(ErrorCode.ERR_AmbigCall, "Test").WithArguments("Program.Test(long, params System.ReadOnlySpan)", "Program.Test(int, params long[])").WithLocation(5, 9) ); } + + [Fact] + public void GenericInference() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + long l = 1; + int i = 2; + byte b = 3; + Test(i, b, l); + } + + static void Test(params IEnumerable b) + { + System.Console.Write(typeof(T)); + } +} +"""; + var comp = CreateCompilation(src, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: ExpectedOutput(@"System.Int64")).VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_OrdinaryMethod_01() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + Test(d); + Test(d, 1); + Test(d, 2, 3); + Test(2, d, 3); + Test(2, 3, d); + Test(d, [3, 4]); + + Test2(d, d); + Test2(d, 1); + Test2(d, 2, 3); + Test2(2, d, 3); + Test2(2, 3, d); + + Test2(d); + Test2(d, d); + Test2(d, 1); + Test2(d, 2, 3); + Test2(2, d, 3); + Test2(2, 3, d); + Test2(d, [3, 4]); + } + + static void Test(int a, params IEnumerable b) + { + System.Console.Write("Called"); + } + + static void Test2(int a, params T[] b) + { + System.Console.Write("Called2"); + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"CalledCalledCalledCalledCalledCalledCalled2Called2Called2Called2Called2Called2Called2Called2Called2Called2Called2Called2").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_OrdinaryMethod_02_AmbiguousDynamicParamsArgument() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + Test(d); + } + + static void Test(params IEnumerable b) + { + System.Console.Write("Called"); + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); + + comp.VerifyDiagnostics( + // (8,14): error CS9502: Ambiguity between expanded and normal forms of non-array params collection parameter of 'Program.Test(params IEnumerable)', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + // Test(d); + Diagnostic(ErrorCode.ERR_ParamsCollectionAmbiguousDynamicArgument, "d").WithArguments("Program.Test(params System.Collections.Generic.IEnumerable)").WithLocation(8, 14) + ); + } + + [Fact] + public void DynamicInvocation_OrdinaryMethod_03_Warning() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d1 = System.DateTime.Now; + Test1(d1); // Called2 + + dynamic d2 = new[] { 1 }; + Test1(d2); // Called1 + Test2(1, d1); // Called3 + Test2(1, d2); // Called5 + + int x = 1; + Test2(x, d1); // Called3 + Test2(x, d2); // Called4 + + dynamic d3 = (byte)1; + Test3(d3, 1, 2); // Called7 + Test3(d3, x, x); // Called6 + + dynamic d4 = x; + Test4((byte)d3, x, x); // Called8 + Test4(d3, x, x); // Called9 + Test4(d3, d4, d4); // Called9 + } + + static void Test1(params IEnumerable b) => System.Console.Write("Called1"); + static void Test1(System.DateTime b) => System.Console.Write("Called2"); + + static void Test2(int x, System.DateTime b) => System.Console.Write("Called3"); + static void Test2(long x, IEnumerable b) => System.Console.Write("Called4"); + static void Test2(byte x, params IEnumerable b) => System.Console.Write("Called5"); + + static void Test3(byte x, params IEnumerable b) => System.Console.Write("Called6"); + static void Test3(byte x, byte y, byte z) => System.Console.Write("Called7"); + + static void Test4(byte x, params IEnumerable b) => System.Console.Write("Called8"); + static void Test4(byte x, long y, long z) => System.Console.Write("Called9"); +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"Called2Called1Called3Called5Called3Called4Called7Called6Called8Called9Called9"). + VerifyDiagnostics( + // (8,9): warning CS9503: One or more overloads of method 'Test1' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // Test1(d1); // Called2 + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionMethod, "Test1(d1)").WithArguments("Test1").WithLocation(8, 9), + // (11,9): warning CS9503: One or more overloads of method 'Test1' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // Test1(d2); // Called1 + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionMethod, "Test1(d2)").WithArguments("Test1").WithLocation(11, 9), + // (12,9): warning CS9503: One or more overloads of method 'Test2' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // Test2(1, d1); // Called3 + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionMethod, "Test2(1, d1)").WithArguments("Test2").WithLocation(12, 9), + // (13,9): warning CS9503: One or more overloads of method 'Test2' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // Test2(1, d2); // Called5 + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionMethod, "Test2(1, d2)").WithArguments("Test2").WithLocation(13, 9), + // (20,9): warning CS9503: One or more overloads of method 'Test3' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // Test3(d3, 1, 2); // Called7 + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionMethod, "Test3(d3, 1, 2)").WithArguments("Test3").WithLocation(20, 9), + // (25,9): warning CS9503: One or more overloads of method 'Test4' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // Test4(d3, x, x); // Called9 + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionMethod, "Test4(d3, x, x)").WithArguments("Test4").WithLocation(25, 9), + // (26,9): warning CS9503: One or more overloads of method 'Test4' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // Test4(d3, d4, d4); // Called9 + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionMethod, "Test4(d3, d4, d4)").WithArguments("Test4").WithLocation(26, 9) + ); + } + + [Fact] + public void DynamicInvocation_OrdinaryMethod_04() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + Test(d, 2); + } + + static void Test(int a, params IEnumerable b) + { + System.Console.Write("Called {0}", b is not null); + } + + static void Test(int a, System.DateTime b) + { + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"Called True").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_OrdinaryMethod_05() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + Test(d, 2, 3); + } + + static void Test(params IEnumerable b) + { + System.Console.Write("Called"); + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"Called").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_OrdinaryMethod_06_TypeArgumentInferenceError() + { + var src1 = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + Test(d, 2, 3); + } + + static void Test(params IEnumerable b) + { + System.Console.Write("Called"); + } +} +"""; + var comp1 = CreateCompilation(src1, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + comp1.VerifyDiagnostics( + // (8,9): error CS9501: The type arguments for method 'Program.Test(params IEnumerable)' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + // Test(d, 2, 3); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs_DynamicArgumentWithParamsCollections, "Test(d, 2, 3)").WithArguments("Program.Test(params System.Collections.Generic.IEnumerable)").WithLocation(8, 9) + ); + + var src2 = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + Test(d, 2, 3); + } + + static void Test(params IEnumerable b) + { + System.Console.Write("Called"); + } +} +"""; + var comp2 = CreateCompilation(src2, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp2, + expectedOutput: @"Called").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_OrdinaryMethod_07_TypeArgumentInferenceError() + { + var src1 = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + Test(0, d, 2, 3); + } + + static void Test(T a, params IEnumerable b) + { + System.Console.Write("Called"); + } +} +"""; + var comp1 = CreateCompilation(src1, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + comp1.VerifyDiagnostics( + // (8,9): error CS9501: The type arguments for method 'Program.Test(T, params IEnumerable)' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + // Test(0, d, 2, 3); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs_DynamicArgumentWithParamsCollections, "Test(0, d, 2, 3)").WithArguments("Program.Test(T, params System.Collections.Generic.IEnumerable)").WithLocation(8, 9) + ); + + var src2 = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + Test(0, d, 2, 3); + } + + static void Test(T a, params IEnumerable b) + { + System.Console.Write("Called"); + } +} +"""; + var comp2 = CreateCompilation(src2, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp2, + expectedOutput: @"Called").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_OrdinaryMethod_08_HideByOverride() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + new C2().Test(d, 2, 3); + } +} + +class C1 +{ + public virtual void Test(params IEnumerable b){} +} + +class C2 : C1 +{ + public override void Test(params IEnumerable b) + { + System.Console.Write("Called"); + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"Called").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_OrdinaryMethod_09_HideBySignature() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + new C2().Test(d, 2, 3); + } +} + +class C1 +{ + public void Test(params IEnumerable b){} +} + +class C2 : C1 +{ + new public void Test(params IEnumerable b) + { + System.Console.Write("Called"); + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"Called").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_OrdinaryMethod_10_HideBySignature() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + new C2().Test(d, 2, 3); + } +} + +class C0 +{ + public virtual void Test(params IEnumerable b){} +} + +class C1 : C0 +{ + public override void Test(params IEnumerable b){} +} + +class C2 : C1 +{ + new public void Test(params IEnumerable b) + { + System.Console.Write("Called"); + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"Called").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_OrdinaryMethod_11_HideBySignature() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + new C3().Test(d, 2, 3); + } +} + +class C1 +{ + public void Test(params IEnumerable b){} +} + +class C2 : C1 +{ + new public virtual void Test(params IEnumerable b) {} +} + +class C3 : C2 +{ + public override void Test(params IEnumerable b) + { + System.Console.Write("Called"); + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"Called").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_OrdinaryMethod_12_HideByName() + { + var src1 = """ +using System.Collections.Generic; + +public class C1 +{ + public void Test(params IEnumerable b){} +} +"""; + + var comp1 = CreateCompilation(src1, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseDll); + + var src2 = """ +Public Class C2 + Inherits C1 + + Public Shadows Sub Test(ParamArray b As Long()) + System.Console.Write("Called") + End Sub +End Class +"""; + + MetadataReference comp1Ref = comp1.EmitToImageReference(); + var comp2 = CreateVisualBasicCompilation(src2, referencedAssemblies: TargetFrameworkUtil.GetReferences(TargetFramework.Standard).Concat(comp1Ref)); + + var src = """ +class Program +{ + static void Main() + { + dynamic d = 1; + new C2().Test(d, 2, 3); + } +} +"""; + var comp = CreateCompilation(src, references: new[] { comp1Ref, comp2.EmitToImageReference() }, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"Called").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_OrdinaryMethod_13_DoNotHideByApplicability() + { + var src = """ +class Program +{ + static void Main() + { + dynamic d = 1L; + new C2().Test(d); + } +} + +class C1 +{ + public void Test(long a) + { + System.Console.Write("long"); + } +} + +class C2 : C1 +{ + public void Test(int b) + { + System.Console.Write("int"); + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"long").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_OrdinaryMethod_14_DoNotFilterBasedOnBetterFunctionMember() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1L; + new C1().Test(1, d, 2); + } +} + +class C1 +{ + public void Test(long a1, params IEnumerable a2) + { + System.Console.Write("long"); + } + + public void Test(int b1, int b2, int b3) + { + System.Console.Write("int"); + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + comp.VerifyDiagnostics( + // (8,9): warning CS9503: One or more overloads of method 'Test' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // new C1().Test(1, d, 2); + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionMethod, "new C1().Test(1, d, 2)").WithArguments("Test").WithLocation(8, 9) + ); + } + + [Fact] + public void DynamicInvocation_OrdinaryMethod_15_Warning() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d1 = 1; + Test1((int)d1); + try + { + Test1(d1); + } + catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) + { + System.Console.Write("Failed"); + } + } + + static void Test1(params IEnumerable b) => System.Console.Write("Called1"); + static void Test1(System.DateTime b) => System.Console.Write("Called2"); +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"Called1Failed"). + VerifyDiagnostics( + // (11,13): warning CS9503: One or more overloads of method 'Test1' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // Test1(d1); + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionMethod, "Test1(d1)").WithArguments("Test1").WithLocation(11, 13) + ); + } + + [Fact] + public void DynamicInvocation_LocalFunction_01() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + Test(d); + Test(d, 1); + Test(d, 2, 3); + Test(2, d, 3); + Test(2, 3, d); + Test(2, [3, d]); + + Test2(d); + Test2(d, 1); + Test2(d, 2, 3); + Test2(2, d, 3); + Test2(2, 3, d); + Test2(d, [3, 4]); + + void Test(int a, params IEnumerable b) + { + System.Console.Write("Called"); + } + + void Test2(int a, params int[] b) + { + System.Console.Write("Called2"); + } + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"CalledCalledCalledCalledCalledCalledCalled2Called2Called2Called2Called2Called2").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_LocalFunction_02_AmbiguousDynamicParamsArgument() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + Test(d); + + static void Test(params IEnumerable b) + { + System.Console.Write("Called"); + } + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); + + comp.VerifyDiagnostics( + // (8,14): error CS9502: Ambiguity between expanded and normal forms of non-array params collection parameter of 'Test(params IEnumerable)', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + // Test(d); + Diagnostic(ErrorCode.ERR_ParamsCollectionAmbiguousDynamicArgument, "d").WithArguments("Test(params System.Collections.Generic.IEnumerable)").WithLocation(8, 14) + ); + } + + [Fact] + public void DynamicInvocation_LocalFunction_06_TypeArgumentInferenceError() + { + var src1 = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + Test(d, 2, 3); + + void Test(params IEnumerable b) + { + System.Console.Write("Called"); + } + } +} +"""; + var comp1 = CreateCompilation(src1, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + comp1.VerifyDiagnostics( + // (8,9): error CS9501: The type arguments for method 'Test(params IEnumerable)' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + // Test(d, 2, 3); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs_DynamicArgumentWithParamsCollections, "Test(d, 2, 3)").WithArguments("Test(params System.Collections.Generic.IEnumerable)").WithLocation(8, 9) + ); + + var src2 = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + Test(d, 2, 3); + + void Test(params IEnumerable b) + { + System.Console.Write("Called"); + } + } +} +"""; + var comp2 = CreateCompilation(src2, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp2, + expectedOutput: @"Called").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_LocalFunction_07_TypeArgumentInferenceError() + { + var src1 = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + Test(0, d, 2, 3); + + void Test(T a, params IEnumerable b) + { + System.Console.Write("Called"); + } + } +} +"""; + var comp1 = CreateCompilation(src1, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + comp1.VerifyDiagnostics( + // (8,9): error CS9501: The type arguments for method 'Test(T, params IEnumerable)' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. + // Test(0, d, 2, 3); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs_DynamicArgumentWithParamsCollections, "Test(0, d, 2, 3)").WithArguments("Test(T, params System.Collections.Generic.IEnumerable)").WithLocation(8, 9) + ); + + var src2 = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + Test(0, d, 2, 3); + + void Test(T a, params IEnumerable b) + { + System.Console.Write("Called"); + } + } +} +"""; + var comp2 = CreateCompilation(src2, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp2, + expectedOutput: @"Called").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_Delegate_01() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + D test = Test; + dynamic d = 1; + test(d); + test(d, 1); + test(d, 2, 3); + test(2, d, 3); + test(2, 3, d); + test(2, [3, d]); + + D2 test2 = Test2; + test2(d); + test2(d, d); + test2(d, 1); + test2(d, 2, 3); + test2(2, d, 3); + test2(2, 3, d); + test2(d, [3, 4]); + + void Test(int a, IEnumerable b) + { + System.Console.Write("Called"); + } + void Test2(int a, int[] b) + { + System.Console.Write("Called2"); + } + } +} + +delegate void D(int a, params IEnumerable b); +delegate void D2(int a, params int[] b); +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"CalledCalledCalledCalledCalledCalledCalled2Called2Called2Called2Called2Called2Called2").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_Delegate_02_AmbiguousDynamicParamsArgument() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + D test = Test; + dynamic d = 1; + test(d); + + static void Test(IEnumerable b) + { + System.Console.Write("Called"); + } + } +} + +delegate void D(params IEnumerable b); +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); + + comp.VerifyDiagnostics( + // (9,14): error CS9502: Ambiguity between expanded and normal forms of non-array params collection parameter of 'D.Invoke(params IEnumerable)', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + // test(d); + Diagnostic(ErrorCode.ERR_ParamsCollectionAmbiguousDynamicArgument, "d").WithArguments("D.Invoke(params System.Collections.Generic.IEnumerable)").WithLocation(9, 14) + ); + } + + [Fact] + public void DynamicInvocation_Indexer_01() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + var c1 = new C1(); + dynamic d = 1; + _ = c1[d]; + _ = c1[d, 1]; + _ = c1[d, 2, 3]; + _ = c1[2, d, 3]; + _ = c1[2, 3, d]; + _ = c1[d, [3, 4]]; + + var c2 = new C2(); + + _ = c2[d]; + _ = c2[d, d]; + _ = c2[d, 1]; + _ = c2[d, 2, 3]; + _ = c2[2, d, 3]; + _ = c2[2, 3, d]; + _ = c2[d, [3, 4]]; + } +} + +class C1 +{ + public int this[int a, params IEnumerable b] + { + get + { + System.Console.Write("Called"); + return 0; + } + } +} +class C2 +{ + public int this[int a, params int[] b] + { + get + { + System.Console.Write("Called2"); + return 0; + } + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"CalledCalledCalledCalledCalledCalledCalled2Called2Called2Called2Called2Called2Called2").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_Indexer_02_AmbiguousDynamicParamsArgument() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + _ = new Program()[d]; + } + + int this[params IEnumerable b] + { + get + { + System.Console.Write("Called"); + return 0; + } + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); + + comp.VerifyDiagnostics( + // (8,27): error CS9502: Ambiguity between expanded and normal forms of non-array params collection parameter of 'Program.this[params IEnumerable]', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + // _ = new Program()[d]; + Diagnostic(ErrorCode.ERR_ParamsCollectionAmbiguousDynamicArgument, "d").WithArguments("Program.this[params System.Collections.Generic.IEnumerable]").WithLocation(8, 27) + ); + } + + [Fact] + public void DynamicInvocation_Indexer_03_Warning() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d1 = System.DateTime.Now; + _ = new Test1()[d1]; // Called2 + + dynamic d2 = new[] { 1 }; + _ = new Test1()[d2]; // Called1 + _ = new Test2()[1, d1]; // Called3 + _ = new Test2()[1, d2]; // Called5 + + int x = 1; + _ = new Test2()[x, d1]; // Called3 + _ = new Test2()[x, d2]; // Called4 + + dynamic d3 = (byte)1; + _ = new Test3()[d3, 1, 2]; // Called7 + _ = new Test3()[d3, x, x]; // Called6 + + dynamic d4 = x; + _ = new Test4()[(byte)d3, x, x]; // Called8 + _ = new Test4()[d3, x, x]; // Called9 + _ = new Test4()[d3, d4, d4]; // Called9 + } + + class Test1 + { + public int this[params IEnumerable b] { get { System.Console.Write("Called1"); return 0; } } + public int this[System.DateTime b] { get { System.Console.Write("Called2"); return 0; } } + } + class Test2 + { + public int this[int x, System.DateTime b] { get { System.Console.Write("Called3"); return 0; } } + public int this[long x, IEnumerable b] { get { System.Console.Write("Called4"); return 0; } } + public int this[byte x, params IEnumerable b] { get { System.Console.Write("Called5"); return 0; } } + } + class Test3 + { + public int this[byte x, params IEnumerable b] { get { System.Console.Write("Called6"); return 0; } } + public int this[byte x, byte y, byte z] { get { System.Console.Write("Called7"); return 0; } } + } + class Test4 + { + public int this[byte x, params IEnumerable b] { get { System.Console.Write("Called8"); return 0; } } + public int this[byte x, long y, long z] { get { System.Console.Write("Called9"); return 0; } } + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"Called2Called1Called3Called5Called3Called4Called7Called6Called8Called9Called9"). + VerifyDiagnostics( + // (8,13): warning CS9504: One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // _ = new Test1()[d1]; // Called2 + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionIndexer, "new Test1()[d1]").WithLocation(8, 13), + // (11,13): warning CS9504: One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // _ = new Test1()[d2]; // Called1 + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionIndexer, "new Test1()[d2]").WithLocation(11, 13), + // (12,13): warning CS9504: One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // _ = new Test2()[1, d1]; // Called3 + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionIndexer, "new Test2()[1, d1]").WithLocation(12, 13), + // (13,13): warning CS9504: One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // _ = new Test2()[1, d2]; // Called5 + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionIndexer, "new Test2()[1, d2]").WithLocation(13, 13), + // (20,13): warning CS9504: One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // _ = new Test3()[d3, 1, 2]; // Called7 + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionIndexer, "new Test3()[d3, 1, 2]").WithLocation(20, 13), + // (25,13): warning CS9504: One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // _ = new Test4()[d3, x, x]; // Called9 + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionIndexer, "new Test4()[d3, x, x]").WithLocation(25, 13), + // (26,13): warning CS9504: One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // _ = new Test4()[d3, d4, d4]; // Called9 + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionIndexer, "new Test4()[d3, d4, d4]").WithLocation(26, 13) + ); + } + + [Fact] + public void DynamicInvocation_Indexer_04() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + _ = new Program()[d, 2]; + } + + int this[int a, params IEnumerable b] + { + get + { + System.Console.Write("Called {0}", b is not null); + return 0; + } + } + + int this[int a, System.DateTime b] => 0; +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"Called True").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_Indexer_05() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + _ = new Program()[d, 2, 3]; + } + + int this[params IEnumerable b] + { + get + { + System.Console.Write("Called"); + return 0; + } + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"Called").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_Indexer_08_HideByOverride() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + _ = new C2()[d, 2, 3]; + } +} + +class C1 +{ + public virtual T this[params IEnumerable b] => default; +} + +class C2 : C1 +{ + public override T this[params IEnumerable b] + { + get + { + System.Console.Write("Called"); + return default; + } + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"Called").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_Indexer_09_HideBySignature() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + _ = new C2()[d, 2, 3]; + } +} + +class C1 +{ + public T this[params IEnumerable b] => default; +} + +class C2 : C1 +{ + new public T this[params IEnumerable b] + { + get + { + System.Console.Write("Called"); + return default; + } + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"Called").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_Indexer_10_HideBySignature() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + _ = new C2()[d, 2, 3]; + } +} + +class C0 +{ + public virtual T this[params IEnumerable b] => default; +} + +class C1 : C0 +{ + public override T this[params IEnumerable b] => default; +} + +class C2 : C1 +{ + new public T this[params IEnumerable b] + { + get + { + System.Console.Write("Called"); + return default; + } + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"Called").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_Indexer_11_HideBySignature() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + _ = new C3()[d, 2, 3]; + } +} + +class C1 +{ + public T this[params IEnumerable b] => default; +} + +class C2 : C1 +{ + new public virtual T this[params IEnumerable b] => default; +} + +class C3 : C2 +{ + public override T this[params IEnumerable b] + { + get + { + System.Console.Write("Called"); + return default; + } + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"Called").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_Indexer_12_HideByName() + { + var src1 = """ +using System.Collections.Generic; + +public class C1 +{ + public int this[int x, params IEnumerable b] => default; +} +"""; + + var comp1 = CreateCompilation(src1, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseDll); + + var src2 = """ +Public Class C2 + Inherits C1 + + Public Shadows Readonly Default Property Item(x as Integer, ParamArray b As Long()) As Integer + Get + System.Console.Write("Called") + Return 0 + End Get + End Property +End Class +"""; + + MetadataReference comp1Ref = comp1.EmitToImageReference(); + var comp2 = CreateVisualBasicCompilation(src2, referencedAssemblies: TargetFrameworkUtil.GetReferences(TargetFramework.Standard).Concat(comp1Ref)); + + var src = """ +class Program +{ + static void Main() + { + dynamic d = 1; + _ = new C2()[4, d, 2, 3]; + } +} +"""; + var comp = CreateCompilation(src, references: new[] { comp1Ref, comp2.EmitToImageReference() }, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"Called").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_Indexer_13_DoNotHideByApplicability() + { + var src = """ +class Program +{ + static void Main() + { + dynamic d = 1L; + _ = new C2()[d]; + } +} + +class C1 +{ + public long this[long a] + { + get + { + System.Console.Write("long"); + return a; + } + } +} + +class C2 : C1 +{ + public int this[int b] + { + get + { + System.Console.Write("int"); + return b; + } + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"long").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_Indexer_14_DoNotFilterBasedOnBetterFunctionMember() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1L; + _ = new C1()[1, d, 2]; + } +} + +class C1 +{ + public long this[long a1, params IEnumerable a2] + { + get + { + System.Console.Write("long"); + return a1; + } + } + + public int this[int b1, int b2, int b3] + { + get + { + System.Console.Write("int"); + return b1; + } + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + comp.VerifyDiagnostics( + // (8,13): warning CS9504: One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // _ = new C1()[1, d, 2]; + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionIndexer, "new C1()[1, d, 2]").WithLocation(8, 13) + ); + } + + [Fact] + public void DynamicInvocation_Constructor_01() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + new Test(d); + new Test(d, 1); + new Test(d, 2, 3); + new Test(2, d, 3); + new Test(2, 3, d); + new Test(d, [3, 4]); + + new Test2(d); + new Test2(d, d); + new Test2(d, 1); + new Test2(d, 2, 3); + new Test2(2, d, 3); + new Test2(2, 3, d); + new Test2(d, [3, 4]); + } + + class Test + { + public Test(int a, params IEnumerable b) + { + System.Console.Write("Called"); + } + } + + class Test2 + { + public Test2(int a, params int[] b) + { + System.Console.Write("Called2"); + } + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"CalledCalledCalledCalledCalledCalledCalled2Called2Called2Called2Called2Called2Called2").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_Constructor_02_AmbiguousDynamicParamsArgument() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + new Test(d); + } + + class Test + { + public Test(params IEnumerable b) + { + System.Console.Write("Called"); + } + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); + + comp.VerifyDiagnostics( + // (8,18): error CS9502: Ambiguity between expanded and normal forms of non-array params collection parameter of 'Program.Test.Test(params IEnumerable)', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + // new Test(d); + Diagnostic(ErrorCode.ERR_ParamsCollectionAmbiguousDynamicArgument, "d").WithArguments("Program.Test.Test(params System.Collections.Generic.IEnumerable)").WithLocation(8, 18) + ); + } + + [Fact] + public void DynamicInvocation_Constructor_03_Warning() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d1 = System.DateTime.Now; + new Test1(d1); // Called2 + + dynamic d2 = new[] { 1 }; + new Test1(d2); // Called1 + new Test2(1, d1); // Called3 + new Test2(1, d2); // Called5 + + int x = 1; + new Test2(x, d1); // Called3 + new Test2(x, d2); // Called4 + + dynamic d3 = (byte)1; + new Test3(d3, 1, 2); // Called7 + new Test3(d3, x, x); // Called6 + + dynamic d4 = x; + new Test4((byte)d3, x, x); // Called8 + new Test4(d3, x, x); // Called9 + new Test4(d3, d4, d4); // Called9 + } + + class Test1 + { + public Test1(params IEnumerable b) => System.Console.Write("Called1"); + public Test1(System.DateTime b) => System.Console.Write("Called2"); + } + + class Test2 + { + public Test2(int x, System.DateTime b) => System.Console.Write("Called3"); + public Test2(long x, IEnumerable b) => System.Console.Write("Called4"); + public Test2(byte x, params IEnumerable b) => System.Console.Write("Called5"); + } + + class Test3 + { + public Test3(byte x, params IEnumerable b) => System.Console.Write("Called6"); + public Test3(byte x, byte y, byte z) => System.Console.Write("Called7"); + } + + class Test4 + { + public Test4(byte x, params IEnumerable b) => System.Console.Write("Called8"); + public Test4(byte x, long y, long z) => System.Console.Write("Called9"); + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"Called2Called1Called3Called5Called3Called4Called7Called6Called8Called9Called9"). + VerifyDiagnostics( + // (8,9): warning CS9505: One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // new Test1(d1); // Called2 + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionConstructor, "new Test1(d1)").WithLocation(8, 9), + // (11,9): warning CS9505: One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // new Test1(d2); // Called1 + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionConstructor, "new Test1(d2)").WithLocation(11, 9), + // (12,9): warning CS9505: One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // new Test2(1, d1); // Called3 + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionConstructor, "new Test2(1, d1)").WithLocation(12, 9), + // (13,9): warning CS9505: One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // new Test2(1, d2); // Called5 + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionConstructor, "new Test2(1, d2)").WithLocation(13, 9), + // (20,9): warning CS9505: One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // new Test3(d3, 1, 2); // Called7 + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionConstructor, "new Test3(d3, 1, 2)").WithLocation(20, 9), + // (25,9): warning CS9505: One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // new Test4(d3, x, x); // Called9 + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionConstructor, "new Test4(d3, x, x)").WithLocation(25, 9), + // (26,9): warning CS9505: One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // new Test4(d3, d4, d4); // Called9 + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionConstructor, "new Test4(d3, d4, d4)").WithLocation(26, 9) + ); + } + + [Fact] + public void DynamicInvocation_Constructor_04() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + new Test(d, 2); + } + + class Test + { + public Test(int a, params IEnumerable b) + { + System.Console.Write("Called {0}", b is not null); + } + + public Test(int a, System.DateTime b) + { + } + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"Called True").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_Constructor_05() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + new Test(d, 2, 3); + } + + class Test + { + public Test(params IEnumerable b) + { + System.Console.Write("Called"); + } + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"Called").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_Constructor_14_DoNotFilterBasedOnBetterFunctionMember() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1L; + new Test(1, d, 2); + } +} + +class Test +{ + public Test(long a1, params IEnumerable a2) + { + System.Console.Write("long"); + } + + public Test(int b1, int b2, int b3) + { + System.Console.Write("int"); + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + comp.VerifyDiagnostics( + // (8,9): warning CS9505: One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // new Test(1, d, 2); + Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionConstructor, "new Test(1, d, 2)").WithLocation(8, 9) + ); + } + + [Fact] + public void DynamicInvocation_Constructor_16_Abstract() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + new Test(d); + } + + abstract class Test + { + public Test(int a, params IEnumerable b) + { + System.Console.Write("Called"); + } + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + comp.VerifyDiagnostics( + // (8,9): error CS0144: Cannot create an instance of the abstract type or interface 'Program.Test' + // new Test(d); + Diagnostic(ErrorCode.ERR_NoNewAbstract, "new Test(d)").WithArguments("Program.Test").WithLocation(8, 9) + ); + } + + [Fact] + public void DynamicInvocation_ConstructorInitializer_01() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + new C01(d); + new C02(d); + new C03(d); + new C04(d); + new C05(d); + new C06(d); + + new C07(d); + new C09(d); + new C10(d); + new C11(d); + new C12(d); + new C13(d); + } + + class C01(dynamic d) : Test(d); + class C02(dynamic d) : Test(d, 1); + class C03(dynamic d) : Test(d, 2, 3); + class C04(dynamic d) : Test(2, d, 3); + class C05(dynamic d) : Test(2, 3, d); + class C06(dynamic d) : Test(d, [3, 4]); + + class C07(dynamic d) : Test2(d); + class C09(dynamic d) : Test2(d, 1); + class C10(dynamic d) : Test2(d, 2, 3); + class C11(dynamic d) : Test2(2, d, 3); + class C12(dynamic d) : Test2(2, 3, d); + class C13(dynamic d) : Test2(d, [3, 4]); + + class Test + { + public Test(int a, params IEnumerable b) + { + System.Console.Write("Called"); + } + } + + class Test2 + { + public Test2(int a, params int[] b) + { + System.Console.Write("Called2"); + } + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + CompileAndVerify( + comp, + expectedOutput: @"CalledCalledCalledCalledCalledCalledCalled2Called2Called2Called2Called2Called2").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_ConstructorInitializer_02_AmbiguousDynamicParamsArgument() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + new C(d); + } + + class C(dynamic d) : Test(d); + + class Test + { + public Test(params IEnumerable b) + { + System.Console.Write("Called"); + } + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); + + comp.VerifyDiagnostics( + // (11,30): error CS1975: The constructor call needs to be dynamically dispatched, but cannot be because it is part of a constructor initializer. Consider casting the dynamic arguments. + // class C(dynamic d) : Test(d); + Diagnostic(ErrorCode.ERR_NoDynamicPhantomOnBaseCtor, "(d)").WithLocation(11, 30) + ); + } + + [Fact] + public void DynamicInvocation_ConstructorInitializer_03_MultipleCandidates() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d1 = System.DateTime.Now; + new C01(d1); + + dynamic d2 = new[] { 1 }; + new C02(d2); + new C03(d1); + new C04(d2); + + int x = 1; + new C05(x, d1); + new C06(x, d2); + + dynamic d3 = (byte)1; + new C07(d3); + new C08(d3, x); + + dynamic d4 = x; + new C09(d3, x); + new C10(d3, x); + new C11(d3, d4); + } + + class C01(dynamic d1) : Test1(d1); + + class C02(dynamic d2) : Test1(d2); + class C03(dynamic d1) : Test2(1, d1); + class C04(dynamic d2) : Test2(1, d2); + + class C05(int x, dynamic d1) : Test2(x, d1); + class C06(int x, dynamic d2) : Test2(x, d2); + + class C07(dynamic d3) : Test3(d3, 1, 2); + class C08(int x, dynamic d3) : Test3(d3, x, x); // Called6 + + class C09(dynamic d3, int x) : Test4((byte)d3, x, x); // Called8 + class C10(dynamic d3, int x) : Test4(d3, x, x); + class C11(dynamic d3, dynamic d4) : Test4(d3, d4, d4); + + class Test1 + { + public Test1(params IEnumerable b) => System.Console.Write("Called1"); + public Test1(System.DateTime b) => System.Console.Write("Called2"); + } + + class Test2 + { + public Test2(int x, System.DateTime b) => System.Console.Write("Called3"); + public Test2(long x, IEnumerable b) => System.Console.Write("Called4"); + public Test2(byte x, params IEnumerable b) => System.Console.Write("Called5"); + } + + class Test3 + { + public Test3(byte x, params IEnumerable b) => System.Console.Write("Called6"); + public Test3(byte x, byte y, byte z) => System.Console.Write("Called7"); + } + + class Test4 + { + public Test4(byte x, params IEnumerable b) => System.Console.Write("Called8"); + public Test4(byte x, long y, long z) => System.Console.Write("Called9"); + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + comp.VerifyDiagnostics( + // (29,34): error CS1975: The constructor call needs to be dynamically dispatched, but cannot be because it is part of a constructor initializer. Consider casting the dynamic arguments. + // class C01(dynamic d1) : Test1(d1); + Diagnostic(ErrorCode.ERR_NoDynamicPhantomOnBaseCtor, "(d1)").WithLocation(29, 34), + // (31,34): error CS1975: The constructor call needs to be dynamically dispatched, but cannot be because it is part of a constructor initializer. Consider casting the dynamic arguments. + // class C02(dynamic d2) : Test1(d2); + Diagnostic(ErrorCode.ERR_NoDynamicPhantomOnBaseCtor, "(d2)").WithLocation(31, 34), + // (32,34): error CS1975: The constructor call needs to be dynamically dispatched, but cannot be because it is part of a constructor initializer. Consider casting the dynamic arguments. + // class C03(dynamic d1) : Test2(1, d1); + Diagnostic(ErrorCode.ERR_NoDynamicPhantomOnBaseCtor, "(1, d1)").WithLocation(32, 34), + // (33,34): error CS1975: The constructor call needs to be dynamically dispatched, but cannot be because it is part of a constructor initializer. Consider casting the dynamic arguments. + // class C04(dynamic d2) : Test2(1, d2); + Diagnostic(ErrorCode.ERR_NoDynamicPhantomOnBaseCtor, "(1, d2)").WithLocation(33, 34), + // (35,41): error CS1975: The constructor call needs to be dynamically dispatched, but cannot be because it is part of a constructor initializer. Consider casting the dynamic arguments. + // class C05(int x, dynamic d1) : Test2(x, d1); + Diagnostic(ErrorCode.ERR_NoDynamicPhantomOnBaseCtor, "(x, d1)").WithLocation(35, 41), + // (36,41): error CS1975: The constructor call needs to be dynamically dispatched, but cannot be because it is part of a constructor initializer. Consider casting the dynamic arguments. + // class C06(int x, dynamic d2) : Test2(x, d2); + Diagnostic(ErrorCode.ERR_NoDynamicPhantomOnBaseCtor, "(x, d2)").WithLocation(36, 41), + // (38,34): error CS1975: The constructor call needs to be dynamically dispatched, but cannot be because it is part of a constructor initializer. Consider casting the dynamic arguments. + // class C07(dynamic d3) : Test3(d3, 1, 2); + Diagnostic(ErrorCode.ERR_NoDynamicPhantomOnBaseCtor, "(d3, 1, 2)").WithLocation(38, 34), + // (42,41): error CS1975: The constructor call needs to be dynamically dispatched, but cannot be because it is part of a constructor initializer. Consider casting the dynamic arguments. + // class C10(dynamic d3, int x) : Test4(d3, x, x); + Diagnostic(ErrorCode.ERR_NoDynamicPhantomOnBaseCtor, "(d3, x, x)").WithLocation(42, 41), + // (43,46): error CS1975: The constructor call needs to be dynamically dispatched, but cannot be because it is part of a constructor initializer. Consider casting the dynamic arguments. + // class C11(dynamic d3, dynamic d4) : Test4(d3, d4, d4); + Diagnostic(ErrorCode.ERR_NoDynamicPhantomOnBaseCtor, "(d3, d4, d4)").WithLocation(43, 46) + ); + } + + [Fact] + public void DynamicInvocation_ConstructorInitializer_04() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + new C(d); + } + + class C(dynamic d) : Test(d, 2); + + class Test + { + public Test(int a, params IEnumerable b) + { + System.Console.Write("Called {0}", b is not null); + } + + public Test(int a, System.DateTime b) + { + } + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"Called True").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_ConstructorInitializer_05() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1; + new C(d); + } + + class C(dynamic d) : Test(d, 2, 3); + + class Test + { + public Test(params IEnumerable b) + { + System.Console.Write("Called"); + } + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify( + comp, + expectedOutput: @"Called").VerifyDiagnostics(); + } + + [Fact] + public void DynamicInvocation_ConstructorInitializer_14_DoNotFilterBasedOnBetterFunctionMember() + { + var src = """ +using System.Collections.Generic; + +class Program +{ + static void Main() + { + dynamic d = 1L; + new C(d); + } +} + +class C(dynamic d) : Test(1, d, 2); + +class Test +{ + public Test(long a1, params IEnumerable a2) + { + System.Console.Write("long"); + } + + public Test(int b1, int b2, int b3) + { + System.Console.Write("int"); + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + comp.VerifyDiagnostics( + // (12,26): error CS1975: The constructor call needs to be dynamically dispatched, but cannot be because it is part of a constructor initializer. Consider casting the dynamic arguments. + // class C(dynamic d) : Test(1, d, 2); + Diagnostic(ErrorCode.ERR_NoDynamicPhantomOnBaseCtor, "(1, d, 2)").WithLocation(12, 26) + ); + } + + [Fact] + public void ExpressionTree() + { + var src = @" +using System.Linq.Expressions; + +class Program +{ + static void Main() + { + Expression e1 = () => Test(); + Expression e2 = () => Test(1); + Expression e3 = () => Test(2, 3); + Expression e4 = () => Test([]); + } + + static void Test(params System.Collections.Generic.IEnumerable a) + { + } +} +"; + var comp = CreateCompilation(src, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); + + // PROTOTYPE(ParamsCollections): report more specific error. + comp.VerifyDiagnostics( + // (8,46): error CS9175: An expression tree may not contain a collection expression. + // Expression e1 = () => Test(); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsCollectionExpression, "Test()").WithLocation(8, 46), + // (9,46): error CS9175: An expression tree may not contain a collection expression. + // Expression e2 = () => Test(1); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsCollectionExpression, "Test(1)").WithLocation(9, 46), + // (10,46): error CS9175: An expression tree may not contain a collection expression. + // Expression e3 = () => Test(2, 3); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsCollectionExpression, "Test(2, 3)").WithLocation(10, 46), + // (11,51): error CS9175: An expression tree may not contain a collection expression. + // Expression e4 = () => Test([]); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsCollectionExpression, "[]").WithLocation(11, 51) + ); + } } } diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/PrimaryConstructorTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/PrimaryConstructorTests.cs index abf0ed071c8ca..5349cae58d979 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/PrimaryConstructorTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/PrimaryConstructorTests.cs @@ -1728,9 +1728,9 @@ public void BaseArguments_10() var src = @" class Base { - public Base(int X) - { - } + public Base(int X) {} + + public Base(long X) {} public Base() {} } diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/RecordTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/RecordTests.cs index 5e66a660bacf0..eb15d1d1d28aa 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/RecordTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/RecordTests.cs @@ -21811,9 +21811,9 @@ public void BaseArguments_10() var src = @" record Base { - public Base(int X) - { - } + public Base(int X) {} + + public Base(long X) {} public Base() {} } diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/RefReadonlyParameterTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/RefReadonlyParameterTests.cs index 84cff75d7a786..777d721eb15a8 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/RefReadonlyParameterTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/RefReadonlyParameterTests.cs @@ -5608,7 +5608,7 @@ .locals init (int V_0) //x } [Fact] - public void Invocation_Dynamic() + public void Invocation_Dynamic_01() { var source = """ class C @@ -5632,6 +5632,8 @@ static void Main() cd.M(ref i); } void M2(dynamic p) => M(p); + + void M(ref readonly long p) => System.Console.Write(p); } """; var verifier = CompileAndVerify(source, targetFramework: TargetFramework.StandardAndCSharp, expectedOutput: "exception2"); @@ -5675,6 +5677,73 @@ .maxstack 9 """); } + [Fact] + public void Invocation_Dynamic_02() + { + var source = """ + class C + { + void M(ref readonly int p) => System.Console.Write(p); + static void Main() + { + dynamic d = 1; + var c = new C(); + try + { + c.M(d); + } + catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) + { + System.Console.Write("exception"); + } + + int i = 2; + dynamic cd = new C(); + cd.M(ref i); + } + void M2(dynamic p) => M(p); + } + """; + var verifier = CompileAndVerify(source, targetFramework: TargetFramework.StandardAndCSharp, expectedOutput: "12"); + + verifier.VerifyDiagnostics( + // (10,17): warning CS9192: Argument 1 should be passed with 'ref' or 'in' keyword + // c.M(d); + Diagnostic(ErrorCode.WRN_ArgExpectedRefOrIn, "d").WithArguments("1").WithLocation(10, 17), + // (21,29): warning CS9192: Argument 1 should be passed with 'ref' or 'in' keyword + // void M2(dynamic p) => M(p); + Diagnostic(ErrorCode.WRN_ArgExpectedRefOrIn, "p").WithArguments("1").WithLocation(21, 29) + ); + + verifier.VerifyIL("C.M2", """ + { + // Code size 74 (0x4a) + .maxstack 4 + .locals init (int V_0) + IL_0000: ldarg.0 + IL_0001: ldsfld "System.Runtime.CompilerServices.CallSite> C.<>o__2.<>p__0" + IL_0006: brtrue.s IL_002c + IL_0008: ldc.i4.0 + IL_0009: ldtoken "int" + IL_000e: call "System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)" + IL_0013: ldtoken "C" + IL_0018: call "System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)" + IL_001d: call "System.Runtime.CompilerServices.CallSiteBinder Microsoft.CSharp.RuntimeBinder.Binder.Convert(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, System.Type, System.Type)" + IL_0022: call "System.Runtime.CompilerServices.CallSite> System.Runtime.CompilerServices.CallSite>.Create(System.Runtime.CompilerServices.CallSiteBinder)" + IL_0027: stsfld "System.Runtime.CompilerServices.CallSite> C.<>o__2.<>p__0" + IL_002c: ldsfld "System.Runtime.CompilerServices.CallSite> C.<>o__2.<>p__0" + IL_0031: ldfld "System.Func System.Runtime.CompilerServices.CallSite>.Target" + IL_0036: ldsfld "System.Runtime.CompilerServices.CallSite> C.<>o__2.<>p__0" + IL_003b: ldarg.1 + IL_003c: callvirt "int System.Func.Invoke(System.Runtime.CompilerServices.CallSite, dynamic)" + IL_0041: stloc.0 + IL_0042: ldloca.s V_0 + IL_0044: call "void C.M(ref readonly int)" + IL_0049: ret + } + """); + } + [Fact] public void Invocation_Dynamic_In() { diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IDynamicIndexerAccessExpression.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IDynamicIndexerAccessExpression.cs index ed0381a8b77bc..dcbd0bcb58d69 100644 --- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IDynamicIndexerAccessExpression.cs +++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IDynamicIndexerAccessExpression.cs @@ -25,6 +25,7 @@ void M(C c, dynamic d) } public int this[int i] => 0; + public int this[long i] => 0; } "; string expectedOperationTree = @" @@ -152,6 +153,7 @@ void M(C c, dynamic d, dynamic e) } public int this[int i, ref dynamic ch] => 0; + public int this[long i, ref dynamic ch] => 0; } "; string expectedOperationTree = @" @@ -171,7 +173,10 @@ void M(C c, dynamic d, dynamic e) var expectedDiagnostics = new DiagnosticDescription[] { // CS0631: ref and out are not valid in this context // public int this[int i, ref dynamic ch] => 0; - Diagnostic(ErrorCode.ERR_IllegalRefParam, "ref").WithLocation(9, 28) + Diagnostic(ErrorCode.ERR_IllegalRefParam, "ref").WithLocation(9, 28), + // (10,29): error CS0631: ref and out are not valid in this context + // public int this[long i, ref dynamic ch] => 0; + Diagnostic(ErrorCode.ERR_IllegalRefParam, "ref").WithLocation(10, 29) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); @@ -324,6 +329,7 @@ public void M(C c) } public int this[Action a, Action y] => 0; + public int this[Action a, int y] => 0; } "; string expectedOperationTree = @" @@ -395,6 +401,7 @@ void M(C c, dynamic d, dynamic p) }/**/ public int this[int i] => 0; + public int this[long i] => 0; } "; string expectedFlowGraph = @" @@ -441,6 +448,7 @@ void M(dynamic d, dynamic p) }/**/ public static int this[int i] => 0; + public static int this[long i] => 0; } "; string expectedFlowGraph = @" @@ -476,6 +484,9 @@ void M(dynamic d, dynamic p) // file.cs(9,23): error CS0106: The modifier 'static' is not valid for this item // public static int this[int i] => 0; Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(9, 23), + // (10,23): error CS0106: The modifier 'static' is not valid for this item + // public static int this[long i] => 0; + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(10, 23), // file.cs(6,13): error CS0119: 'C' is a type, which is not valid in the given context // p = C[d]; Diagnostic(ErrorCode.ERR_BadSKunknown, "C").WithArguments("C", "type").WithLocation(6, 13) @@ -497,6 +508,7 @@ void M(C c1, C c2, dynamic d, dynamic p) }/**/ public int this[int i] => 0; + public int this[long i] => 0; } "; string expectedFlowGraph = @" @@ -597,6 +609,7 @@ void M(C c, dynamic d1, dynamic d2, dynamic p) }/**/ public int this[int i] => 0; + public int this[long i] => 0; } "; string expectedFlowGraph = @" @@ -701,6 +714,7 @@ void M(C c1, C c2, dynamic d1, dynamic d2, dynamic p) }/**/ public int this[int i] => 0; + public int this[long i] => 0; } "; string expectedFlowGraph = @" @@ -840,6 +854,7 @@ void M(C c, dynamic d1, dynamic d2, dynamic p, int j) }/**/ public int this[int i, int j] => 0; + public int this[long i, int j] => 0; } "; string expectedFlowGraph = @" @@ -945,6 +960,7 @@ void M(C c, dynamic d1, dynamic d2, dynamic p, int j) }/**/ public int this[int i, int j] => 0; + public int this[int i, long j] => 0; } "; string expectedFlowGraph = @" @@ -1054,6 +1070,7 @@ void M(C c, dynamic d1, dynamic d2, dynamic p, int? j1, int j2) }/**/ public int this[int i, int j] => 0; + public int this[int i, long j] => 0; } "; string expectedFlowGraph = @" diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IDynamicInvocationExpression.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IDynamicInvocationExpression.cs index b000db8196e33..d19b5fe1fe390 100644 --- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IDynamicInvocationExpression.cs +++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IDynamicInvocationExpression.cs @@ -28,6 +28,10 @@ void M(C c, dynamic d) public void M2(int i) { } + + public void M2(long i) + { + } } "; string expectedOperationTree = @" @@ -183,6 +187,10 @@ public void M2(ref object i, out int j, char c) { j = 0; } + public void M2(ref object i, out int j, int c) + { + j = 0; + } } "; string expectedOperationTree = @" @@ -216,17 +224,19 @@ public void DynamicInvocation_DelegateInvocation() class C { - public Action F; + public D F; void M(dynamic i) { var x = /**/F(i)/**/; } } + +delegate void D(params object[] x); "; string expectedOperationTree = @" IDynamicInvocationOperation (OperationKind.DynamicInvocation, Type: dynamic) (Syntax: 'F(i)') Expression: - IFieldReferenceOperation: System.Action C.F (OperationKind.FieldReference, Type: System.Action) (Syntax: 'F') + IFieldReferenceOperation: D C.F (OperationKind.FieldReference, Type: D) (Syntax: 'F') Instance Receiver: IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'F') Arguments(1): @@ -235,9 +245,9 @@ void M(dynamic i) ArgumentRefKinds(0) "; var expectedDiagnostics = new DiagnosticDescription[] { - // CS0649: Field 'C.F' is never assigned to, and will always have its default value null - // public Action F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("C.F", "null").WithLocation(6, 27) + // (6,14): warning CS0649: Field 'C.F' is never assigned to, and will always have its default value null + // public D F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("C.F", "null").WithLocation(6, 14) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); @@ -392,6 +402,10 @@ public void M(C c) public void M2(Action a, Action y) { } + + public void M2(Action a, Action y) + { + } } "; string expectedOperationTree = @" @@ -473,7 +487,11 @@ class C : B { C(dynamic x) : base((int)/**/Goo(x)/**/) { } - static object Goo(object x) + static object Goo(int x) + { + return x; + } + static object Goo(long x) { return x; } @@ -511,6 +529,9 @@ void M(C c, dynamic d) public void M2(int i) { } + public void M2(long i) + { + } } "; string expectedFlowGraph = @" @@ -559,6 +580,10 @@ void M(dynamic d1, dynamic d2) public static void M2(int i) { } + + public static void M2(long i) + { + } } "; string expectedFlowGraph = @" @@ -651,6 +676,9 @@ void M(C c1, C c2, dynamic d) public void M2(int i) { } + public void M2(long i) + { + } } "; string expectedFlowGraph = @" diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IDynamicObjectCreationExpression.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IDynamicObjectCreationExpression.cs index a0efe4487df33..e04a844188d06 100644 --- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IDynamicObjectCreationExpression.cs +++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IDynamicObjectCreationExpression.cs @@ -23,6 +23,9 @@ class C public C(int i) { } + public C(long i) + { + } void M(dynamic d) { @@ -165,6 +168,10 @@ public C(ref object i, out int j, char c) { j = 0; } + public C(ref object i, out int j, long c) + { + j = 0; + } void M(object d, dynamic e) { @@ -204,6 +211,9 @@ class C public C(char c) { } + public C(long c) + { + } void M(dynamic d) { @@ -299,7 +309,10 @@ static void Main() /**/new C(delegate { }, y)/**/; } - public C(Action a, Action y) + public C(Action a, int y) + { + } + public C(Action a, long y) { } } @@ -370,6 +383,7 @@ public void DynamicObjectCreationFlow_01() class C1 { C1(int i) { } + C1(long i) { } /**/void M(C1 c1, dynamic d) { c1 = new C1(d); @@ -415,6 +429,7 @@ public void DynamicObjectCreationFlow_02() class C1 { C1(int i) { } + C1(long i) { } /**/void M(C1 c1, dynamic d, bool b) { c1 = new C1(d) { I1 = 1, I2 = b ? 2 : 3 }; @@ -536,6 +551,7 @@ public void DynamicObjectCreationFlow_03() class C1 : IEnumerable { C1(int i) { } + C1(long i) { } /**/void M(C1 c1, dynamic d, bool b) { c1 = new C1(d) { 1, b ? 2 : 3 }; diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IInterpolatedStringOperation.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IInterpolatedStringOperation.cs index 1ba03c4d38252..6869a8bf5b412 100644 --- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IInterpolatedStringOperation.cs +++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IInterpolatedStringOperation.cs @@ -4392,10 +4392,13 @@ public void AppendLiteral(dynamic d) Console.WriteLine(""AppendLiteral""); } - public void AppendFormatted(dynamic d, int alignment, string format) + public void AppendFormatted(int d, int alignment, string format) { Console.WriteLine(""AppendFormatted""); } + public void AppendFormatted(long d, int alignment, string format) + { + } } "; @@ -4473,7 +4476,8 @@ void M(dynamic d, [InterpolatedStringHandlerArgument(""d"")]CustomHandler c) {} public partial struct CustomHandler { - public CustomHandler(int literalLength, int formattedCount, dynamic d) : this() {} + public CustomHandler(int literalLength, int formattedCount, int d) : this() {} + public CustomHandler(int literalLength, int formattedCount, long d) : this() {} } "; @@ -4570,7 +4574,8 @@ void M1(dynamic d, [InterpolatedStringHandlerArgument(""d"")]CustomHandler c) {} public partial struct CustomHandler { - public CustomHandler(int literalLength, int formattedCount, dynamic d) : this() {} + public CustomHandler(int literalLength, int formattedCount, int d) : this() {} + public CustomHandler(int literalLength, int formattedCount, long d) : this() {} } "; diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IObjectCreationExpression.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IObjectCreationExpression.cs index 625028f7c526e..ebde2d102e21d 100644 --- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IObjectCreationExpression.cs +++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IObjectCreationExpression.cs @@ -1811,6 +1811,7 @@ public static void M(C1 c, dynamic d1) public IEnumerator GetEnumerator() => throw null; IEnumerator IEnumerable.GetEnumerator() => throw null; public void Add(int c2) { } + public void Add(long c2) { } } "; var expectedDiagnostics = DiagnosticDescription.None; @@ -3327,6 +3328,7 @@ public static void M(C1 c, dynamic d1) public IEnumerator GetEnumerator() => throw null; IEnumerator IEnumerable.GetEnumerator() => throw null; public void Add(int c2) { } + public void Add(long c2) { } } "; var expectedDiagnostics = DiagnosticDescription.None; @@ -13276,6 +13278,7 @@ class C1 : IEnumerable public IEnumerator GetEnumerator() => throw null; IEnumerator IEnumerable.GetEnumerator() => throw null; public void Add(int c2) { } + public void Add(long c2) { } } "; var expectedDiagnostics = DiagnosticDescription.None; @@ -13361,6 +13364,7 @@ class C1 : IEnumerable public IEnumerator GetEnumerator() => throw null; IEnumerator IEnumerable.GetEnumerator() => throw null; public void Add(int c2) { } + public void Add(long c2) { } } "; var expectedDiagnostics = DiagnosticDescription.None; @@ -13490,6 +13494,7 @@ class C2 : IEnumerable public IEnumerator GetEnumerator() => throw null; IEnumerator IEnumerable.GetEnumerator() => throw null; public void Add(int c2) { } + public void Add(long c2) { } } "; var expectedDiagnostics = DiagnosticDescription.None; @@ -13658,6 +13663,7 @@ class C2 : IEnumerable public IEnumerator GetEnumerator() => throw null; IEnumerator IEnumerable.GetEnumerator() => throw null; public void Add(int c1, int c2) { } + public void Add(long c1, long c2) { } } "; var expectedDiagnostics = DiagnosticDescription.None; @@ -14310,6 +14316,13 @@ class A return new A(); } } + A this[long x, long y] + { + get + { + return new A(); + } + } int X, Y, Z; diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/DynamicTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/DynamicTests.cs index e79dc23b94fd1..a16d4f1501ada 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/DynamicTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/DynamicTests.cs @@ -1668,6 +1668,7 @@ struct S { public int X { get; private set; } public void M(int x) => X = x; + public void M(string x) => throw null; } """; var verifier = CompileAndVerify(source, new[] { CSharpRef }).VerifyDiagnostics(); @@ -2920,6 +2921,14 @@ public void Add(int a, int b, int c) { } + public void Add(long a, long b, long c) + { + } + + public void Add(long a) + { + } + static void M() { var z = new C() //-typeExpression: C @@ -2994,16 +3003,22 @@ static void Main() Expression> e21 = x => new dynamic(); Expression> e22 = x => from a in new[] { d } select a + 1; Expression> e23 = x => from a in new[] { d } select a; // ok - Expression> e24 = x => new string(x); + Expression> e24 = x => new C1(x); } } + +class C1 +{ + public C1(int x){} + public C1(long x){} +} "; CreateCompilationWithMscorlib40AndSystemCore(new[] { Parse(source, options: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp5)) }).VerifyDiagnostics( // (43,55): warning CS1981: Using 'is' to test compatibility with 'dynamic' is essentially identical to testing compatibility with 'Object' and will succeed for all non-null values // Expression> e18 = x => d is dynamic; // ok, warning Diagnostic(ErrorCode.WRN_IsDynamicIsConfusing, "d is dynamic").WithArguments("is", "dynamic", "Object").WithLocation(43, 55), - // (46,59): error CS8382: Invalid object creation + // (46,59): error CS8386: Invalid object creation // Expression> e21 = x => new dynamic(); Diagnostic(ErrorCode.ERR_InvalidObjectCreation, "dynamic").WithLocation(46, 59), // (25,52): error CS1963: An expression tree may not contain a dynamic operation @@ -3018,12 +3033,18 @@ static void Main() // (27,69): error CS1963: An expression tree may not contain a dynamic operation // Expression> e2 = () => new C { D = { X = { Y = 1 }, Z = 1 } }; Diagnostic(ErrorCode.ERR_ExpressionTreeContainsDynamicOperation, "Z").WithLocation(27, 69), - // (28,44): error CS1963: An expression tree may not contain a dynamic operation + // (28,46): error CS1963: An expression tree may not contain a dynamic operation + // Expression> e3 = () => new C() { { d }, { d, d, d } }; + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsDynamicOperation, "d").WithLocation(28, 46), + // (28,53): error CS1963: An expression tree may not contain a dynamic operation // Expression> e3 = () => new C() { { d }, { d, d, d } }; - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsDynamicOperation, "{ d }").WithLocation(28, 44), - // (28,51): error CS1963: An expression tree may not contain a dynamic operation + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsDynamicOperation, "d").WithLocation(28, 53), + // (28,56): error CS1963: An expression tree may not contain a dynamic operation // Expression> e3 = () => new C() { { d }, { d, d, d } }; - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsDynamicOperation, "{ d, d, d }").WithLocation(28, 51), + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsDynamicOperation, "d").WithLocation(28, 56), + // (28,59): error CS1963: An expression tree may not contain a dynamic operation + // Expression> e3 = () => new C() { { d }, { d, d, d } }; + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsDynamicOperation, "d").WithLocation(28, 59), // (29,54): error CS1963: An expression tree may not contain a dynamic operation // Expression> e4 = x => x.goo(); Diagnostic(ErrorCode.ERR_ExpressionTreeContainsDynamicOperation, "x.goo()").WithLocation(29, 54), @@ -3045,15 +3066,6 @@ static void Main() // (33,54): error CS1963: An expression tree may not contain a dynamic operation // Expression> e8 = x => -x; Diagnostic(ErrorCode.ERR_ExpressionTreeContainsDynamicOperation, "-x").WithLocation(33, 54), - // (34,54): error CS1963: An expression tree may not contain a dynamic operation - // Expression> e9 = x => f(d); - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsDynamicOperation, "f(d)").WithLocation(34, 54), - // (36,55): error CS1963: An expression tree may not contain a dynamic operation - // Expression> e11 = x => f((dynamic)1); - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsDynamicOperation, "f((dynamic)1)").WithLocation(36, 55), - // (37,55): error CS1963: An expression tree may not contain a dynamic operation - // Expression> e12 = x => f(d ?? null); - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsDynamicOperation, "f(d ?? null)").WithLocation(37, 55), // (38,55): error CS1963: An expression tree may not contain a dynamic operation // Expression> e13 = x => d ? 1 : 2; Diagnostic(ErrorCode.ERR_ExpressionTreeContainsDynamicOperation, "d").WithLocation(38, 55), @@ -3064,8 +3076,8 @@ static void Main() // Expression> e22 = x => from a in new[] { d } select a + 1; Diagnostic(ErrorCode.ERR_ExpressionTreeContainsDynamicOperation, "a + 1").WithLocation(47, 84), // (49,55): error CS1963: An expression tree may not contain a dynamic operation - // Expression> e24 = x => new string(x); - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsDynamicOperation, "new string(x)").WithLocation(49, 55) + // Expression> e24 = x => new C1(x); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsDynamicOperation, "new C1(x)").WithLocation(49, 55) ); } @@ -3319,14 +3331,14 @@ public void TestDynamicIndexers() class B { public int this[double x] { get { return 1; } set { } } + public int this[float x] { get { return 1; } set { } } } - class C : B { public int this[int x] { get { return 1; } set { } } public int this[string x] { get { return 1; } set { } } public int this[int a, System.Func b, object c] { get { return 1; } set { } } - + public int this[long a, System.Func b, object c] { get { return 1; } set { } } void M(C c, dynamic d) { // No overload takes two arguments: @@ -3345,9 +3357,9 @@ void M(C c, dynamic d) var comp = CreateCompilationWithMscorlib40AndSystemCore(source); comp.VerifyDiagnostics( - // (16,5): error CS7036: There is no argument given that corresponds to the required parameter 'c' of 'C.this[int, Func, object]' + // (16,5): error CS1501: No overload for method 'this' takes 2 arguments // c[d, d] = 1; - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "c[d, d]").WithArguments("c", "C.this[int, System.Func, object]").WithLocation(16, 5), + Diagnostic(ErrorCode.ERR_BadArgCount, "c[d, d]").WithArguments("this", "2").WithLocation(16, 5), // (22,10): error CS1977: Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type. // c[d, q=>q, null] = 3; Diagnostic(ErrorCode.ERR_BadDynamicMethodArgLambda, "q=>q"), @@ -4396,22 +4408,13 @@ static void Main() } "; - var comp = CreateCompilationWithMscorlib45AndCSharp(source, parseOptions: TestOptions.Regular7_2); + var comp = CreateCompilationWithMscorlib45AndCSharp(source, parseOptions: TestOptions.Regular7_2, options: TestOptions.DebugExe); - comp.VerifyEmitDiagnostics( - // (11,15): error CS8364: Arguments with 'in' modifier cannot be used in dynamically dispatched expressions. - // M1(in d, d = 2, in d); - Diagnostic(ErrorCode.ERR_InDynamicMethodArg, "d").WithLocation(11, 15), - // (11,28): error CS8364: Arguments with 'in' modifier cannot be used in dynamically dispatched expressions. - // M1(in d, d = 2, in d); - Diagnostic(ErrorCode.ERR_InDynamicMethodArg, "d").WithLocation(11, 28), - // (23,15): error CS8364: Arguments with 'in' modifier cannot be used in dynamically dispatched expressions. - // M2(in d, d = 3, in d); - Diagnostic(ErrorCode.ERR_InDynamicMethodArg, "d").WithLocation(23, 15), - // (23,28): error CS8364: Arguments with 'in' modifier cannot be used in dynamically dispatched expressions. - // M2(in d, d = 3, in d); - Diagnostic(ErrorCode.ERR_InDynamicMethodArg, "d").WithLocation(23, 28) - ); + CompileAndVerify(comp, expectedOutput: +@" +True +True +").VerifyDiagnostics(); } [WorkItem(22813, "https://github.com/dotnet/roslyn/issues/22813")] @@ -4431,7 +4434,7 @@ static void Main() class M2 { public M2(int a, in int d) => System.Console.Write(1); - public M2(int a, int d) => System.Console.Write(2); + public M2(long a, in int d) => System.Console.Write(2); } }"; @@ -4522,5 +4525,34 @@ public static bool operator false(C c) Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "new C()").WithArguments("C.implicit operator bool(C)").WithLocation(4, 5) ); } + + [Fact] + public void InapplicableMethodInDerived() + { + string source = @" +class C +{ + static void Main() + { + dynamic d = 1; + System.Console.WriteLine(new C2().Add(d)); + } +} + +class C1 +{ + public string Add(int x) => ""int""; +} + +class C2 : C1 +{ + public string Add(string x) => ""string""; +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe, targetFramework: TargetFramework.StandardAndCSharp); + + CompileAndVerify(comp, expectedOutput: "int").VerifyDiagnostics(); + } } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/InterpolationTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/InterpolationTests.cs index 1642a19841faf..5f2aba23088a9 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/InterpolationTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/InterpolationTests.cs @@ -13825,7 +13825,8 @@ void M(dynamic d, [InterpolatedStringHandlerArgument(""d"")]CustomHandler c) {} public partial struct CustomHandler { - public CustomHandler(int literalLength, int formattedCount, dynamic d) : this() {} + public CustomHandler(int literalLength, int formattedCount, int d) : this() {} + public CustomHandler(int literalLength, int formattedCount, long d) : this() {} } "; @@ -13853,7 +13854,8 @@ void M(dynamic d, [InterpolatedStringHandlerArgument(""d"")]CustomHandler c) {} public partial struct CustomHandler { - public CustomHandler(int literalLength, int formattedCount, dynamic d) : this() {} + public CustomHandler(int literalLength, int formattedCount, int d) : this() {} + public CustomHandler(int literalLength, int formattedCount, long d) : this() {} } "; @@ -14100,7 +14102,7 @@ .locals init (CustomHandler V_0) [Theory] [InlineData(@"$""literal{d}""")] [InlineData(@"$""literal"" + $""{d}""")] - public void DynamicConstruction_08(string expression) + public void DynamicConstruction_08_01(string expression) { var code = @" using System; @@ -14137,6 +14139,75 @@ public void AppendFormatted(dynamic d) verifier.VerifyIL("", @" { + // Code size 43 (0x2b) + .maxstack 3 + .locals init (object V_0, //d + CustomHandler V_1) + IL_0000: ldc.i4.1 + IL_0001: box ""int"" + IL_0006: stloc.0 + IL_0007: ldloca.s V_1 + IL_0009: ldc.i4.7 + IL_000a: ldc.i4.1 + IL_000b: call ""CustomHandler..ctor(int, int)"" + IL_0010: ldloca.s V_1 + IL_0012: ldstr ""literal"" + IL_0017: call ""void CustomHandler.AppendLiteral(dynamic)"" + IL_001c: ldloca.s V_1 + IL_001e: ldloc.0 + IL_001f: call ""void CustomHandler.AppendFormatted(dynamic)"" + IL_0024: ldloc.1 + IL_0025: call ""void Program.<
$>g__M|0_0(CustomHandler)"" + IL_002a: ret +} +"); + } + + [Theory] + [InlineData(@"$""literal{d}""")] + [InlineData(@"$""literal"" + $""{d}""")] + public void DynamicConstruction_08_02(string expression) + { + var code = @" +using System; +using System.Runtime.CompilerServices; +dynamic d = 1; +M(" + expression + @"); + +void M(CustomHandler c) {} + +[InterpolatedStringHandler] +public struct CustomHandler +{ + public CustomHandler(int literalLength, int formattedCount) + { + } + + public void AppendLiteral(dynamic d) + { + Console.WriteLine(""AppendLiteral""); + } + + public void AppendFormatted(dynamic d) + { + Console.WriteLine(""---""); + } + + public void AppendFormatted(int d) + { + Console.WriteLine(""AppendFormatted""); + } +} +"; + + var comp = CreateCompilation(new[] { code, InterpolatedStringHandlerAttribute }, targetFramework: TargetFramework.Mscorlib45AndCSharp); + var verifier = CompileAndVerify(comp, expectedOutput: @" +AppendLiteral +AppendFormatted"); + verifier.VerifyDiagnostics(); + + verifier.VerifyIL("", @" +{ // Code size 128 (0x80) .maxstack 9 .locals init (object V_0, //d @@ -14215,6 +14286,12 @@ public bool AppendLiteral(dynamic d) } public bool AppendFormatted(dynamic d) + { + Console.WriteLine(""---""); + return true; + } + + public bool AppendFormatted(long d) { Console.WriteLine(""AppendFormatted""); return true; diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs index 5ad93941c2fe0..295337aec3e42 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs @@ -2705,15 +2705,15 @@ static void Main() } }"; VerifyDiagnostics(src, - // (10,9): error CS8106: Cannot pass argument with dynamic type to params parameter 'ys' of local function 'L1'. + // (10,17): error CS8106: Cannot pass argument with dynamic type to params parameter 'ys' of local function 'L1'. // L1(val, val); - Diagnostic(ErrorCode.ERR_DynamicLocalFunctionParamsParameter, "L1(val, val)").WithArguments("ys", "L1").WithLocation(10, 9), - // (11,9): error CS8106: Cannot pass argument with dynamic type to params parameter 'ys' of local function 'L1'. + Diagnostic(ErrorCode.ERR_DynamicLocalFunctionParamsParameter, "val").WithArguments("ys", "L1").WithLocation(10, 17), + // (11,16): error CS8106: Cannot pass argument with dynamic type to params parameter 'ys' of local function 'L1'. // L1(ys: val, x: val); - Diagnostic(ErrorCode.ERR_DynamicLocalFunctionParamsParameter, "L1(ys: val, x: val)").WithArguments("ys", "L1").WithLocation(11, 9), - // (12,9): error CS8106: Cannot pass argument with dynamic type to params parameter 'ys' of local function 'L1'. + Diagnostic(ErrorCode.ERR_DynamicLocalFunctionParamsParameter, "val").WithArguments("ys", "L1").WithLocation(11, 16), + // (12,16): error CS8106: Cannot pass argument with dynamic type to params parameter 'ys' of local function 'L1'. // L1(ys: val); - Diagnostic(ErrorCode.ERR_DynamicLocalFunctionParamsParameter, "L1(ys: val)").WithArguments("ys", "L1").WithLocation(12, 9)); + Diagnostic(ErrorCode.ERR_DynamicLocalFunctionParamsParameter, "val").WithArguments("ys", "L1").WithLocation(12, 16)); } [Fact] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NonTrailingNamedArgumentsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NonTrailingNamedArgumentsTests.cs index daf809fec89cc..b9edc6addca35 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NonTrailingNamedArgumentsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NonTrailingNamedArgumentsTests.cs @@ -841,9 +841,9 @@ void local(int x, params object[] y) { } }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular7_2); comp.VerifyDiagnostics( - // (7,9): error CS8108: Cannot pass argument with dynamic type to params parameter 'y' of local function 'local'. + // (7,21): error CS8108: Cannot pass argument with dynamic type to params parameter 'y' of local function 'local'. // local(x: 1, d); - Diagnostic(ErrorCode.ERR_DynamicLocalFunctionParamsParameter, "local(x: 1, d)").WithArguments("y", "local").WithLocation(7, 9), + Diagnostic(ErrorCode.ERR_DynamicLocalFunctionParamsParameter, "d").WithArguments("y", "local").WithLocation(7, 21), // (7,21): error CS8323: Named argument specifications must appear after all fixed arguments have been specified in a dynamic invocation. // local(x: 1, d); Diagnostic(ErrorCode.ERR_NamedArgumentSpecificationBeforeFixedArgumentInDynamicInvocation, "d").WithLocation(7, 21) @@ -851,7 +851,7 @@ void local(int x, params object[] y) { } } [Fact] - public void TestDynamicWhenNotInvocation() + public void TestDynamicWhenNotInvocation_01() { var source = @" class C @@ -871,7 +871,43 @@ void M(C c) } }"; var comp = CreateCompilation(source); - comp.VerifyDiagnostics(); + comp.VerifyDiagnostics( + // (15,9): error CS0200: Property or indexer 'C.this[int, int]' cannot be assigned to -- it is read only + // c[a: 1, d] = d; + Diagnostic(ErrorCode.ERR_AssgReadonlyProp, "c[a: 1, d]").WithArguments("C.this[int, int]").WithLocation(15, 9) + ); + } + + [Fact] + public void TestDynamicWhenNotInvocation_02() + { + var source = @" +class C +{ + int this[int a, int b] + { + get + { + System.Console.Write($""{a} {b}.""); + return 0; + } + } + int this[int a, long b] + { + get + { + return 0; + } + } + void M(C c) + { + dynamic d = new object(); + c[a: 1, d] = d; + } +}"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + ); } [Fact] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs index d4d0369bc0b73..e999729cb2e53 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs @@ -63944,11 +63944,14 @@ public void DynamicObjectCreation_02() C(object x, object y) { } - static void G(object? x, dynamic y) + static void G(string? x, dynamic y) { var o = new C(x, y); if (x != null) o = new C(y, x); } + C(string x, string y) + { + } }"; var comp = CreateCompilationWithMscorlib40AndSystemCore(new[] { source }, options: WithNullableEnable()); // https://github.com/dotnet/roslyn/issues/29893: We should be able to report warnings @@ -64805,7 +64808,7 @@ public CL0(long x) } [Fact] - public void DynamicInvocation() + public void DynamicInvocation__01() { var source = @"class C @@ -64818,6 +64821,32 @@ static void G(object? x, dynamic y) F(x, y); if (x != null) F(y, x); } +}"; + var comp = CreateCompilationWithMscorlib40AndSystemCore(new[] { source }, options: WithNullableEnable()); + comp.VerifyDiagnostics( + // 0.cs(8,11): warning CS8604: Possible null reference argument for parameter 'x' in 'void C.F(object x, object y)'. + // F(x, y); + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("x", "void C.F(object x, object y)").WithLocation(8, 11) + ); + } + + [Fact] + public void DynamicInvocation__02() + { + var source = +@"class C +{ + static void F(object x, object y) + { + } + static void F(object x, int y) + { + } + static void G(object? x, dynamic y) + { + F(x, y); + if (x != null) F(y, x); + } }"; var comp = CreateCompilationWithMscorlib40AndSystemCore(new[] { source }, options: WithNullableEnable()); // https://github.com/dotnet/roslyn/issues/29893: We should be able to report warnings @@ -156032,6 +156061,7 @@ class C { public C(int x){F1 = default!;} public C(T t, int x){F1 = t;} + public C(T t, long x){F1 = t;} public T F1; public T? F2; @@ -156080,6 +156110,7 @@ class C { public C(int x){F1 = default!;} public C(T t, int x){F1 = t;} + public C(T t, long x){F1 = t;} public T F1; public T? F2; @@ -156135,6 +156166,7 @@ class C1 { public C1(int x){} public C1(C2 t, int x){} + public C1(C2 t, long x){} public C2? F1; public C2? F2; diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RawInterpolationTests_Handler.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RawInterpolationTests_Handler.cs index 7800e0741c064..08ff7b26dc486 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/RawInterpolationTests_Handler.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RawInterpolationTests_Handler.cs @@ -10464,7 +10464,8 @@ void M(dynamic d, [InterpolatedStringHandlerArgument(""d"")]CustomHandler c) {} public partial struct CustomHandler { - public CustomHandler(int literalLength, int formattedCount, dynamic d) : this() {} + public CustomHandler(int literalLength, int formattedCount, int d) : this() {} + public CustomHandler(int literalLength, int formattedCount, long d) : this() {} } "; @@ -10497,7 +10498,8 @@ void M(dynamic d, [InterpolatedStringHandlerArgument(""d"")]CustomHandler c) {} public partial struct CustomHandler { - public CustomHandler(int literalLength, int formattedCount, dynamic d) : this() {} + public CustomHandler(int literalLength, int formattedCount, int d) : this() {} + public CustomHandler(int literalLength, int formattedCount, long d) : this() {} } "; @@ -10788,6 +10790,11 @@ public void AppendLiteral(dynamic d) } public void AppendFormatted(dynamic d) + { + Console.WriteLine(""---""); + } + + public void AppendFormatted(int d) { Console.WriteLine(""AppendFormatted""); } @@ -10880,6 +10887,12 @@ public bool AppendLiteral(dynamic d) } public bool AppendFormatted(dynamic d) + { + Console.WriteLine(""---""); + return true; + } + + public bool AppendFormatted(int d) { Console.WriteLine(""AppendFormatted""); return true; diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs index 2ae9e4b1f2cb7..8d4e2a3ac683a 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs @@ -7091,6 +7091,9 @@ void Add(int value) { this.value += value; } + void Add(string value) + { + } } "; CreateCompilationWithMscorlib40AndSystemCore(source, parseOptions: TestOptions.Regular10).VerifyDiagnostics( @@ -7162,6 +7165,9 @@ void Add(int value) { this.value += value; } + void Add(string value) + { + } } "; CreateCompilationWithMscorlib40AndSystemCore(source, parseOptions: TestOptions.Regular10).VerifyDiagnostics( @@ -18360,12 +18366,40 @@ public static implicit operator A(dynamic a) // CS1970ERR_ExplicitDynamicAttr --> AttributeTests_Dynamic.ExplicitDynamicAttribute [Fact] - public void CS1971ERR_NoDynamicPhantomOnBase() + public void CS1971ERR_NoDynamicPhantomOnBase_01() + { + const string text = @" +public class B +{ + public virtual void M(object o) { System.Console.Write(""Called""); } +} +public class D : B +{ + public override void M(object o) {} + + void N(dynamic d) + { + base.M(d); + } + + static void Main() + { + new D().N(1); + } +} +"; + var comp = CreateCompilation(text, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.DebugExe); + CompileAndVerify(comp, expectedOutput: "Called").VerifyDiagnostics(); + } + + [Fact] + public void CS1971ERR_NoDynamicPhantomOnBase_02() { const string text = @" public class B { public virtual void M(object o) {} + public void M(int o) {} } public class D : B { @@ -18379,16 +18413,16 @@ void N(dynamic d) "; var comp = CreateCompilationWithMscorlib40AndSystemCore(text); comp.VerifyDiagnostics( - // (12,9): error CS1971: The call to method 'M' needs to be dynamically dispatched, but cannot be because it is part of a base access expression. Consider casting the dynamic arguments or eliminating the base access. + // (13,9): error CS1971: The call to method 'M' needs to be dynamically dispatched, but cannot be because it is part of a base access expression. Consider casting the dynamic arguments or eliminating the base access. // base.M(d); Diagnostic(ErrorCode.ERR_NoDynamicPhantomOnBase, "base.M(d)").WithArguments("M")); } [Fact] - public void CS1972ERR_NoDynamicPhantomOnBaseIndexer() + public void CS1972ERR_NoDynamicPhantomOnBaseIndexer_01() { const string text = @" -public class B +public partial class B { public string this[int index] { @@ -18403,6 +18437,13 @@ public void M(object o) int s = base[(dynamic)o]; } } +public partial class B +{ + public string this[long index] + { + get { return ""You passed "" + index; } + } +} "; var comp = CreateCompilationWithMscorlib40AndSystemCore(text); @@ -18413,7 +18454,92 @@ public void M(object o) } [Fact] - public void CS1973ERR_BadArgTypeDynamicExtension() + public void CS1972ERR_NoDynamicPhantomOnBaseIndexer_02() + { + const string text = @" +public class B +{ + public string this[int index] + { + get { return ""You passed "" + index; } + } +} +public class D : B +{ + static void Main() + { + D d = new D(); + System.Console.Write(d.M(1)); + } + + public string M(object o) + { + return base[(dynamic)o]; + } +} +"; + + var comp = CreateCompilation(text, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.DebugExe); + var verifier = CompileAndVerify(comp, expectedOutput: "You passed 1").VerifyDiagnostics(); + + verifier.VerifyIL("D.M", +@" +{ + // Code size 78 (0x4e) + .maxstack 4 + .locals init (string V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldsfld ""System.Runtime.CompilerServices.CallSite> D.<>o__1.<>p__0"" + IL_0007: brfalse.s IL_000b + IL_0009: br.s IL_002f + IL_000b: ldc.i4.0 + IL_000c: ldtoken ""int"" + IL_0011: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)"" + IL_0016: ldtoken ""D"" + IL_001b: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)"" + IL_0020: call ""System.Runtime.CompilerServices.CallSiteBinder Microsoft.CSharp.RuntimeBinder.Binder.Convert(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, System.Type, System.Type)"" + IL_0025: call ""System.Runtime.CompilerServices.CallSite> System.Runtime.CompilerServices.CallSite>.Create(System.Runtime.CompilerServices.CallSiteBinder)"" + IL_002a: stsfld ""System.Runtime.CompilerServices.CallSite> D.<>o__1.<>p__0"" + IL_002f: ldsfld ""System.Runtime.CompilerServices.CallSite> D.<>o__1.<>p__0"" + IL_0034: ldfld ""System.Func System.Runtime.CompilerServices.CallSite>.Target"" + IL_0039: ldsfld ""System.Runtime.CompilerServices.CallSite> D.<>o__1.<>p__0"" + IL_003e: ldarg.1 + IL_003f: callvirt ""int System.Func.Invoke(System.Runtime.CompilerServices.CallSite, dynamic)"" + IL_0044: call ""string B.this[int].get"" + IL_0049: stloc.0 + IL_004a: br.s IL_004c + IL_004c: ldloc.0 + IL_004d: ret +} +"); + } + + [Fact] + public void CS1973ERR_BadArgTypeDynamicExtension_01() + { + const string text = @" +class Program +{ + static void Main() + { + dynamic d = 1; + B b = new B(); + b.Goo(d); + } +} +public class B { } +static public class Extension +{ + public static void Goo(this B b, int x) { System.Console.Write(""Called""); } +}"; + + var comp = CreateCompilation(text, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.DebugExe); + CompileAndVerify(comp, expectedOutput: "Called").VerifyDiagnostics(); + } + + [Fact] + public void CS1973ERR_BadArgTypeDynamicExtension_02() { const string text = @" class Program @@ -18429,11 +18555,12 @@ public class B { } static public class Extension { public static void Goo(this B b, int x) { } + public static void Goo(this B b, long x) { } }"; var comp = CreateCompilationWithMscorlib40AndSystemCore(text); comp.VerifyDiagnostics( -// (8,9): error CS1973: 'B' has no applicable method named 'Goo' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax. +// (9,9): error CS1973: 'B' has no applicable method named 'Goo' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax. // b.Goo(d); Diagnostic(ErrorCode.ERR_BadArgTypeDynamicExtension, "b.Goo(d)").WithArguments("B", "Goo")); } @@ -18444,10 +18571,10 @@ public void CS1975ERR_NoDynamicPhantomOnBaseCtor_Base() var text = @" class A { - public A(int x) - { + public A(int x) {} + + public A(long x) {} - } } class B : A { @@ -18473,6 +18600,8 @@ public B(dynamic d) public B(int a, int b) { } + public B(long a, int b) + { } } "; CreateCompilationWithMscorlib40AndSystemCore(text).VerifyDiagnostics( @@ -18535,7 +18664,11 @@ static void Main() new C(delegate { }, y); } - public C(Action a, Action y) + public C(Action a, int y) + { + } + + public C(Action a, long y) { } }"; @@ -18573,15 +18706,27 @@ public static void M(__arglist) public static void SomeStaticMethod() {} - public void Add(dynamic d, int x, int* ptr) + public void Add(int d, int x, int* ptr) + { + } + + public void Add(long d, int x, int* ptr) + { + } + + public void Add(int d, RuntimeArgumentHandle x) + { + } + + public void Add(long d, RuntimeArgumentHandle x) { } - public void Add(dynamic d, RuntimeArgumentHandle x) + public void Add(int d, Action f) { } - public void Add(dynamic d, Action f) + public void Add(long d, Action f) { } @@ -18612,7 +18757,7 @@ IEnumerator IEnumerable.GetEnumerator() Diagnostic(ErrorCode.ERR_BadDynamicMethodArg, "__arglist").WithArguments("System.RuntimeArgumentHandle").WithLocation(18, 18), // (19,13): error CS1950: The best overloaded Add method 'C.Add(dynamic, RuntimeArgumentHandle)' for the collection initializer has some invalid arguments // { d, GetEnumerator }, - Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "{ d, GetEnumerator }").WithArguments("C.Add(dynamic, System.RuntimeArgumentHandle)").WithLocation(19, 13), + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "{ d, GetEnumerator }").WithArguments("C.Add(int, System.RuntimeArgumentHandle)").WithLocation(19, 13), // (19,18): error CS1503: Argument 2: cannot convert from 'method group' to 'RuntimeArgumentHandle' // { d, GetEnumerator }, Diagnostic(ErrorCode.ERR_BadArgType, "GetEnumerator").WithArguments("2", "method group", "System.RuntimeArgumentHandle").WithLocation(19, 18), @@ -22529,7 +22674,7 @@ public class List } [Fact] - public void CS1974WRN_DynamicDispatchToConditionalMethod() + public void CS1974WRN_DynamicDispatchToConditionalMethod_01() { var text = @" using System.Diagnostics; @@ -22546,7 +22691,7 @@ static void Main() [Conditional(""DEBUG"")] static void Goo(string d) {} - + static void Goo(long d) {} [Conditional(""DEBUG"")] static void Bar(int x, int y) {} @@ -22560,6 +22705,35 @@ static void Bar(string x) {} Diagnostic(ErrorCode.WRN_DynamicDispatchToConditionalMethod, "Goo(d)").WithArguments("Goo")); } + [Fact] + public void CS1974WRN_DynamicDispatchToConditionalMethod_02() + { + var text = @" +using System.Diagnostics; +class Myclass +{ + static void Main() + { + dynamic d = null; + // Warning because Goo might be conditional. + Goo(d); + // No warning; only the two-parameter Bar is conditional. + Bar(d); + } + + [Conditional(""DEBUG"")] + static void Goo(string d) {} + + [Conditional(""DEBUG"")] + static void Bar(int x, int y) {} + + static void Bar(string x) {} +}"; + + var comp = CreateCompilationWithMscorlib40AndSystemCore(text); + comp.VerifyDiagnostics(); + } + [Fact] public void CS1981WRN_IsDynamicIsConfusing() { diff --git a/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetSemanticInfoTests_LateBound.cs b/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetSemanticInfoTests_LateBound.cs index 8b1c205609bd0..882913c850da3 100644 --- a/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetSemanticInfoTests_LateBound.cs +++ b/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetSemanticInfoTests_LateBound.cs @@ -85,12 +85,43 @@ public void M(dynamic d) Assert.Equal("C", semanticInfo.Type.Name); Assert.Equal("C..ctor(out dynamic x, dynamic y)", semanticInfo.Symbol.ToTestDisplayString()); - Assert.Equal(CandidateReason.LateBound, semanticInfo.CandidateReason); + Assert.Equal(CandidateReason.None, semanticInfo.CandidateReason); Assert.Equal(0, semanticInfo.CandidateSymbols.Length); Assert.Equal(1, semanticInfo.MethodGroup.Length); Assert.False(semanticInfo.IsCompileTimeConstant); } + [Fact] + public void ObjectCreation_ByRefDynamicArgument3() + { + string sourceCode = @" +class C +{ + public C(out dynamic x, int y) {} + public C(out dynamic x, long y) {} + + public void M(dynamic d) + { + /**/new C(out d, d);/**/; + } +} +"; + var semanticInfo = GetSemanticInfoForTest(sourceCode); + + Assert.Equal("C", semanticInfo.Type.Name); + Assert.Null(semanticInfo.Symbol); + + Assert.Equal(CandidateReason.LateBound, semanticInfo.CandidateReason); + Assert.Equal(2, semanticInfo.CandidateSymbols.Length); + Assert.Equal("C..ctor(out dynamic x, System.Int32 y)", semanticInfo.CandidateSymbols[0].ToTestDisplayString()); + Assert.Equal("C..ctor(out dynamic x, System.Int64 y)", semanticInfo.CandidateSymbols[1].ToTestDisplayString()); + + Assert.Equal(2, semanticInfo.MethodGroup.Length); + Assert.Equal("C..ctor(out dynamic x, System.Int32 y)", semanticInfo.MethodGroup[0].ToTestDisplayString()); + Assert.Equal("C..ctor(out dynamic x, System.Int64 y)", semanticInfo.MethodGroup[1].ToTestDisplayString()); + Assert.False(semanticInfo.IsCompileTimeConstant); + } + [Fact] public void DelegateInvocation() { @@ -159,6 +190,9 @@ public void M() public void bar(int a) { } + public void bar(long a) + { + } } "; var semanticInfo = GetSemanticInfoForTest(sourceCode); @@ -168,20 +202,60 @@ public void bar(int a) Assert.True(semanticInfo.ConvertedType.IsDynamic()); Assert.Equal(ConversionKind.Identity, semanticInfo.ImplicitConversion.Kind); - Assert.Equal("void C.bar(System.Int32 a)", semanticInfo.Symbol.ToTestDisplayString()); + Assert.Null(semanticInfo.Symbol); + + Assert.Equal(2, semanticInfo.CandidateSymbols.Length); + Assert.Equal(2, semanticInfo.MethodGroup.Length); + Assert.False(semanticInfo.IsCompileTimeConstant); + } + [Fact] + public void MethodInvocation_TypeReceiver_01() + { + string sourceCode1 = @" +class C +{ + public static C Create(int arg) { return null; } + + public void M(dynamic d) + { + /**/C.Create(d);/**/; + } +} +"; + var semanticInfo = GetSemanticInfoForTest(sourceCode1); + + Assert.Equal("C", semanticInfo.Type.ToTestDisplayString()); + Assert.Equal("C C.Create(System.Int32 arg)", semanticInfo.Symbol.ToTestDisplayString()); + Assert.Equal(CandidateReason.None, semanticInfo.CandidateReason); Assert.Equal(0, semanticInfo.CandidateSymbols.Length); - Assert.Equal(1, semanticInfo.MethodGroup.Length); + Assert.Equal(0, semanticInfo.MethodGroup.Length); Assert.False(semanticInfo.IsCompileTimeConstant); + + string sourceCode2 = @" +class C +{ + public static C Create(int arg) { return null; } + + public void M(dynamic d) + { + /**/C.Create/**/(d); + } +} +"; + semanticInfo = GetSemanticInfoForTest(sourceCode2); + + Assert.Equal(1, semanticInfo.MethodGroup.Length); } [Fact] - public void MethodInvocation_TypeReceiver() + public void MethodInvocation_TypeReceiver_02() { string sourceCode = @" class C { public static C Create(int arg) { return null; } + public static C Create(long arg) { return null; } public void M(dynamic d) { @@ -192,10 +266,10 @@ public void M(dynamic d) var semanticInfo = GetSemanticInfoForTest(sourceCode); Assert.True(semanticInfo.Type.IsDynamic()); - Assert.Equal("C C.Create(System.Int32 arg)", semanticInfo.Symbol.ToTestDisplayString()); + Assert.Null(semanticInfo.Symbol); Assert.Equal(CandidateReason.LateBound, semanticInfo.CandidateReason); - Assert.Equal(0, semanticInfo.CandidateSymbols.Length); - Assert.Equal(1, semanticInfo.MethodGroup.Length); + Assert.Equal(2, semanticInfo.CandidateSymbols.Length); + Assert.Equal(2, semanticInfo.MethodGroup.Length); Assert.False(semanticInfo.IsCompileTimeConstant); } @@ -234,17 +308,20 @@ public void Add(dynamic x, string y) { /**/Add/**/(x); } + + public void Add(long y) + { + } }"; var semanticInfo = GetSemanticInfoForTest(source); Assert.Null(semanticInfo.Type); - // there is only one applicable candidate: - Assert.Equal("void System.Collections.Generic.List.Add(System.Int32 item)", semanticInfo.Symbol.ToTestDisplayString()); + Assert.Null(semanticInfo.Symbol); Assert.Equal(CandidateReason.LateBound, semanticInfo.CandidateReason); - Assert.Equal(0, semanticInfo.CandidateSymbols.Length); - Assert.Equal(2, semanticInfo.MethodGroup.Length); + Assert.Equal(2, semanticInfo.CandidateSymbols.Length); + Assert.Equal(3, semanticInfo.MethodGroup.Length); Assert.False(semanticInfo.IsCompileTimeConstant); } @@ -260,17 +337,20 @@ public void Add(dynamic x, string y) { /**/Add(x)/**/; } + + public void Add(long y) + { + } }"; var semanticInfo = GetSemanticInfoForTest(source); Assert.True(semanticInfo.Type.IsDynamic()); - // there is only one applicable candidate: - Assert.Equal("void System.Collections.Generic.List.Add(System.Int32 item)", semanticInfo.Symbol.ToTestDisplayString()); + Assert.Null(semanticInfo.Symbol); Assert.Equal(CandidateReason.LateBound, semanticInfo.CandidateReason); - Assert.Equal(0, semanticInfo.CandidateSymbols.Length); - Assert.Equal(1, semanticInfo.MethodGroup.Length); + Assert.Equal(2, semanticInfo.CandidateSymbols.Length); + Assert.Equal(2, semanticInfo.MethodGroup.Length); Assert.False(semanticInfo.IsCompileTimeConstant); } @@ -312,11 +392,15 @@ namespace Dynamic { class FunctionTestingWithOverloading { - public dynamic OverloadedFunction(dynamic d) + public dynamic OverloadedFunction(int d) { return d; } + public dynamic OverloadedFunction(long d) + { + return d; + } } class Program { @@ -337,11 +421,15 @@ static void Main(string[] args) Assert.Equal(CandidateReason.LateBound, semanticInfo.CandidateReason); - Assert.Equal(0, semanticInfo.CandidateSymbols.Length); - Assert.Equal("dynamic Dynamic.FunctionTestingWithOverloading.OverloadedFunction(dynamic d)", semanticInfo.Symbol.ToTestDisplayString()); + Assert.Equal(2, semanticInfo.CandidateSymbols.Length); + Assert.Equal("dynamic Dynamic.FunctionTestingWithOverloading.OverloadedFunction(System.Int32 d)", semanticInfo.CandidateSymbols[0].ToTestDisplayString()); + Assert.Equal("dynamic Dynamic.FunctionTestingWithOverloading.OverloadedFunction(System.Int64 d)", semanticInfo.CandidateSymbols[1].ToTestDisplayString()); - Assert.Equal(1, semanticInfo.MethodGroup.Length); - Assert.Equal("dynamic Dynamic.FunctionTestingWithOverloading.OverloadedFunction(dynamic d)", semanticInfo.MethodGroup.First().ToTestDisplayString()); + Assert.Null(semanticInfo.Symbol); + + Assert.Equal(2, semanticInfo.MethodGroup.Length); + Assert.Equal("dynamic Dynamic.FunctionTestingWithOverloading.OverloadedFunction(System.Int32 d)", semanticInfo.MethodGroup[0].ToTestDisplayString()); + Assert.Equal("dynamic Dynamic.FunctionTestingWithOverloading.OverloadedFunction(System.Int64 d)", semanticInfo.MethodGroup[1].ToTestDisplayString()); Assert.False(semanticInfo.IsCompileTimeConstant); } @@ -395,7 +483,7 @@ public void M() } [Fact] - public void Indexer_StaticReceiver() + public void Indexer_StaticReceiver_01() { string sourceCode = @" class C @@ -413,6 +501,12 @@ public int this[int a] get { return 0; } set { } } + + public int this[long a] + { + get { return 0; } + set { } + } } "; var semanticInfo = GetSemanticInfoForTest(sourceCode); @@ -422,6 +516,43 @@ public int this[int a] Assert.Equal(ConversionKind.Identity, semanticInfo.ImplicitConversion.Kind); Assert.Equal(CandidateReason.LateBound, semanticInfo.CandidateReason); + Assert.Equal(2, semanticInfo.CandidateSymbols.Length); + Assert.Equal("System.Int32 C.this[System.Int32 a] { get; set; }", semanticInfo.CandidateSymbols[0].ToTestDisplayString()); + Assert.Equal("System.Int32 C.this[System.Int64 a] { get; set; }", semanticInfo.CandidateSymbols[1].ToTestDisplayString()); + Assert.Null(semanticInfo.Symbol); + + Assert.Equal(0, semanticInfo.MethodGroup.Length); + Assert.False(semanticInfo.IsCompileTimeConstant); + } + + [Fact] + public void Indexer_StaticReceiver_02() + { + string sourceCode = @" +class C +{ + public void TestMeth() + { + dynamic d = null; + C c = null; + + var x = /**/c[d]/**/; + } + + public int this[int a] + { + get { return 0; } + set { } + } +} +"; + var semanticInfo = GetSemanticInfoForTest(sourceCode); + + Assert.False(semanticInfo.Type.IsDynamic()); + Assert.False(semanticInfo.ConvertedType.IsDynamic()); + Assert.Equal(ConversionKind.Identity, semanticInfo.ImplicitConversion.Kind); + + Assert.Equal(CandidateReason.None, semanticInfo.CandidateReason); Assert.Equal(0, semanticInfo.CandidateSymbols.Length); Assert.Equal("System.Int32 C.this[System.Int32 a] { get; set; }", semanticInfo.Symbol.ToTestDisplayString()); diff --git a/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs b/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs index 568b4af3f1ef7..590dd302c6017 100644 --- a/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs +++ b/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs @@ -429,6 +429,9 @@ public void WarningLevel_2() case ErrorCode.WRN_UseDefViolationRefField: case ErrorCode.WRN_CollectionExpressionRefStructMayAllocate: case ErrorCode.WRN_CollectionExpressionRefStructSpreadMayAllocate: + case ErrorCode.WRN_DynamicDispatchToParamsCollectionMethod: + case ErrorCode.WRN_DynamicDispatchToParamsCollectionIndexer: + case ErrorCode.WRN_DynamicDispatchToParamsCollectionConstructor: Assert.Equal(1, ErrorFacts.GetWarningLevel(errorCode)); break; case ErrorCode.WRN_InvalidVersionFormat: diff --git a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/DynamicTests.cs b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/DynamicTests.cs index cbb3dc038cedc..25922de0a50d2 100644 --- a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/DynamicTests.cs +++ b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/DynamicTests.cs @@ -1258,6 +1258,10 @@ static void Goo(dynamic y) { System.Action a = () => Goo(x); } + + static void Goo(int y) + { + } } "; var comp = CreateCompilation(source, new[] { CSharpRef }, TestOptions.DebugDll); @@ -1369,6 +1373,9 @@ static void Goo(int x) { M(x); } + static void Goo(string x) + { + } } "; var comp = CreateCompilation(source, new[] { CSharpRef }, TestOptions.DebugDll); diff --git a/src/Features/CSharpTest/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests_AsTests.cs b/src/Features/CSharpTest/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests_AsTests.cs index 44f89c8f4d145..4df0417d96928 100644 --- a/src/Features/CSharpTest/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests_AsTests.cs +++ b/src/Features/CSharpTest/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests_AsTests.cs @@ -2623,6 +2623,11 @@ static bool Goo(int x, object y, object z) { return true; } + + static bool Goo(long x, object y, object z) + { + return true; + } } """); } @@ -2657,7 +2662,19 @@ class C { } } - + + int this[long x, object s, string d] + { + get + { + return 0; + } + + set + { + } + } + void Goo(dynamic xx) { var y = this[x: xx, s: "", d: [|"" as object|]]; @@ -2760,6 +2777,11 @@ static bool Goo(object y, int x, object z) { return true; } + + static bool Goo(object y, long x, object z) + { + return true; + } } """); } diff --git a/src/Features/CSharpTest/SimplifyTypeNames/SimplifyTypeNamesTests.cs b/src/Features/CSharpTest/SimplifyTypeNames/SimplifyTypeNamesTests.cs index 723e912c8e658..62ea95b916a07 100644 --- a/src/Features/CSharpTest/SimplifyTypeNames/SimplifyTypeNamesTests.cs +++ b/src/Features/CSharpTest/SimplifyTypeNames/SimplifyTypeNamesTests.cs @@ -4118,9 +4118,11 @@ struct S S(dynamic y) { - [|object.Equals|](y, 0); + [|S.Equals|](y, 0); x = y; } + + static bool Equals(S s, object y) => false; } """); } @@ -4191,10 +4193,10 @@ await TestMissingInRegularAndScriptAsync( class B { - public static void Goo(int x, object y) - { - } + public static void Goo(int x, object y) {} + public static void Goo(long x, object y) {} + static void Main() { C.D.Goo(0); @@ -4273,10 +4275,10 @@ await TestMissingInRegularAndScriptAsync( class B { - static void Goo(int x, object y) - { - } - + static void Goo(int x, object y) {} + + static void Goo(long x, object y) {} + static void Goo(dynamic x) { Console.WriteLine([|C.Goo|](x, ")); From 4e11e24595821f99818a05d9d608e3b0b1294c3d Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Tue, 2 Jan 2024 18:21:04 -0800 Subject: [PATCH 2/4] PR feedback --- .../Portable/Binder/Binder_Expressions.cs | 4 +- .../OverloadResolution/OverloadResolution.cs | 10 ++--- .../CSharp/Portable/CSharpResources.resx | 10 ++--- .../Portable/xlf/CSharpResources.cs.xlf | 20 ++++----- .../Portable/xlf/CSharpResources.de.xlf | 20 ++++----- .../Portable/xlf/CSharpResources.es.xlf | 20 ++++----- .../Portable/xlf/CSharpResources.fr.xlf | 20 ++++----- .../Portable/xlf/CSharpResources.it.xlf | 20 ++++----- .../Portable/xlf/CSharpResources.ja.xlf | 20 ++++----- .../Portable/xlf/CSharpResources.ko.xlf | 20 ++++----- .../Portable/xlf/CSharpResources.pl.xlf | 20 ++++----- .../Portable/xlf/CSharpResources.pt-BR.xlf | 20 ++++----- .../Portable/xlf/CSharpResources.ru.xlf | 20 ++++----- .../Portable/xlf/CSharpResources.tr.xlf | 20 ++++----- .../Portable/xlf/CSharpResources.zh-Hans.xlf | 20 ++++----- .../Portable/xlf/CSharpResources.zh-Hant.xlf | 20 ++++----- .../Emit2/Semantics/ParamsCollectionTests.cs | 42 +++++++++---------- 17 files changed, 163 insertions(+), 163 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index 4929ca7a96b03..23b3e69f23aad 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -9259,8 +9259,8 @@ private BoundExpression BindIndexerOrIndexedPropertyAccess( bool allowRefOmittedArguments = !InParameterDefaultValue && !InAttributeArgument && receiver.IsExpressionOfComImportType(); CompoundUseSiteInfo useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics); this.OverloadResolution.PropertyOverloadResolution(propertyGroup, receiver, analyzedArguments, overloadResolutionResult, - options: (allowRefOmittedArguments ? OverloadResolution.Options.AllowRefOmittedArguments : OverloadResolution.Options.None) | - (analyzedArguments.HasDynamicArgument ? OverloadResolution.Options.DynamicResolution : OverloadResolution.Options.None), + allowRefOmittedArguments: allowRefOmittedArguments, + dynamicResolution: analyzedArguments.HasDynamicArgument, ref useSiteInfo); diagnostics.Add(syntax, useSiteInfo); diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs index 86744c389d7f7..1c45e33ac70c5 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs @@ -162,18 +162,18 @@ public void PropertyOverloadResolution( BoundExpression receiverOpt, AnalyzedArguments arguments, OverloadResolutionResult result, - Options options, + bool allowRefOmittedArguments, + bool dynamicResolution, ref CompoundUseSiteInfo useSiteInfo) { - Debug.Assert((options & Options.DynamicResolution) == 0 || arguments.HasDynamicArgument); - - options &= (Options.AllowRefOmittedArguments | Options.DynamicResolution); + Debug.Assert(!dynamicResolution || arguments.HasDynamicArgument); ArrayBuilder typeArguments = ArrayBuilder.GetInstance(); MethodOrPropertyOverloadResolution( indexers, typeArguments, receiverOpt, arguments, result, useSiteInfo: ref useSiteInfo, - options, + options: (allowRefOmittedArguments ? Options.AllowRefOmittedArguments : Options.None) | + (dynamicResolution ? Options.DynamicResolution : Options.None), callingConventionInfo: default); typeArguments.Free(); } diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 60e8b036a0c62..ce9b6170bd2ee 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -7843,7 +7843,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ The type arguments for method '{0}' cannot be inferred from the usage because an argument with dynamic type is used and the method has a non-array params collection parameter. Try specifying the type arguments explicitly. - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. One or more overloads of method '{0}' having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. @@ -7852,15 +7852,15 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 12b3ff41042a5..283bf08fa5cf1 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -1508,8 +1508,8 @@ - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. @@ -2598,23 +2598,23 @@ - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 55d0837b0a33c..6b1ddef1b0c84 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -1508,8 +1508,8 @@ - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. @@ -2598,23 +2598,23 @@ - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 5817b69a91897..a03ca6ccba54a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -1508,8 +1508,8 @@ - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. @@ -2598,23 +2598,23 @@ - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index f2d151f1268e5..6bf4443eca8aa 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -1508,8 +1508,8 @@ - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. @@ -2598,23 +2598,23 @@ - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index edc97a284c779..320c173aa607f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -1508,8 +1508,8 @@ - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. @@ -2598,23 +2598,23 @@ - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index badf6d95b2e48..0f3dfe307430f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -1508,8 +1508,8 @@ - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. @@ -2598,23 +2598,23 @@ - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index b77fa1dc8046f..f84ac158ecc00 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -1508,8 +1508,8 @@ - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. @@ -2598,23 +2598,23 @@ - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 9ff325c1166ad..e7fdff5fef460 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -1508,8 +1508,8 @@ - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. @@ -2598,23 +2598,23 @@ - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 75180b74bf9c2..84c3df334b3d6 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -1508,8 +1508,8 @@ - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. @@ -2598,23 +2598,23 @@ - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 57a9cfeb63622..1477dbd4c5394 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -1508,8 +1508,8 @@ - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. @@ -2598,23 +2598,23 @@ - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 3d38cc59646e8..b21866db0a806 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -1508,8 +1508,8 @@ - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. @@ -2598,23 +2598,23 @@ - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 09765f56109db..6669ea200230c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -1508,8 +1508,8 @@ - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. @@ -2598,23 +2598,23 @@ - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 1bac80eac638b..d2483486b3070 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -1508,8 +1508,8 @@ - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. - Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. + Ambiguity between expanded and normal forms of non-array params collection parameter of '{0}', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. @@ -2598,23 +2598,23 @@ - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. - One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/ParamsCollectionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/ParamsCollectionTests.cs index 35f897aff2456..a5964aac8f2e0 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/ParamsCollectionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/ParamsCollectionTests.cs @@ -1973,7 +1973,7 @@ static void Test(params IEnumerable b) var comp = CreateCompilation(src, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); comp.VerifyDiagnostics( - // (8,14): error CS9502: Ambiguity between expanded and normal forms of non-array params collection parameter of 'Program.Test(params IEnumerable)', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + // (8,14): error CS9502: Ambiguity between expanded and normal forms of non-array params collection parameter of 'Program.Test(params IEnumerable)', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. // Test(d); Diagnostic(ErrorCode.ERR_ParamsCollectionAmbiguousDynamicArgument, "d").WithArguments("Program.Test(params System.Collections.Generic.IEnumerable)").WithLocation(8, 14) ); @@ -2589,7 +2589,7 @@ static void Test(params IEnumerable b) var comp = CreateCompilation(src, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); comp.VerifyDiagnostics( - // (8,14): error CS9502: Ambiguity between expanded and normal forms of non-array params collection parameter of 'Test(params IEnumerable)', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + // (8,14): error CS9502: Ambiguity between expanded and normal forms of non-array params collection parameter of 'Test(params IEnumerable)', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. // Test(d); Diagnostic(ErrorCode.ERR_ParamsCollectionAmbiguousDynamicArgument, "d").WithArguments("Test(params System.Collections.Generic.IEnumerable)").WithLocation(8, 14) ); @@ -2774,7 +2774,7 @@ static void Test(IEnumerable b) var comp = CreateCompilation(src, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); comp.VerifyDiagnostics( - // (9,14): error CS9502: Ambiguity between expanded and normal forms of non-array params collection parameter of 'D.Invoke(params IEnumerable)', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + // (9,14): error CS9502: Ambiguity between expanded and normal forms of non-array params collection parameter of 'D.Invoke(params IEnumerable)', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. // test(d); Diagnostic(ErrorCode.ERR_ParamsCollectionAmbiguousDynamicArgument, "d").WithArguments("D.Invoke(params System.Collections.Generic.IEnumerable)").WithLocation(9, 14) ); @@ -2868,7 +2868,7 @@ int this[params IEnumerable b] var comp = CreateCompilation(src, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); comp.VerifyDiagnostics( - // (8,27): error CS9502: Ambiguity between expanded and normal forms of non-array params collection parameter of 'Program.this[params IEnumerable]', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + // (8,27): error CS9502: Ambiguity between expanded and normal forms of non-array params collection parameter of 'Program.this[params IEnumerable]', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. // _ = new Program()[d]; Diagnostic(ErrorCode.ERR_ParamsCollectionAmbiguousDynamicArgument, "d").WithArguments("Program.this[params System.Collections.Generic.IEnumerable]").WithLocation(8, 27) ); @@ -2935,25 +2935,25 @@ class Test4 comp, expectedOutput: @"Called2Called1Called3Called5Called3Called4Called7Called6Called8Called9Called9"). VerifyDiagnostics( - // (8,13): warning CS9504: One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // (8,13): warning CS9504: One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. // _ = new Test1()[d1]; // Called2 Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionIndexer, "new Test1()[d1]").WithLocation(8, 13), - // (11,13): warning CS9504: One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // (11,13): warning CS9504: One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. // _ = new Test1()[d2]; // Called1 Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionIndexer, "new Test1()[d2]").WithLocation(11, 13), - // (12,13): warning CS9504: One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // (12,13): warning CS9504: One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. // _ = new Test2()[1, d1]; // Called3 Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionIndexer, "new Test2()[1, d1]").WithLocation(12, 13), - // (13,13): warning CS9504: One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // (13,13): warning CS9504: One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. // _ = new Test2()[1, d2]; // Called5 Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionIndexer, "new Test2()[1, d2]").WithLocation(13, 13), - // (20,13): warning CS9504: One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // (20,13): warning CS9504: One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. // _ = new Test3()[d3, 1, 2]; // Called7 Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionIndexer, "new Test3()[d3, 1, 2]").WithLocation(20, 13), - // (25,13): warning CS9504: One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // (25,13): warning CS9504: One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. // _ = new Test4()[d3, x, x]; // Called9 Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionIndexer, "new Test4()[d3, x, x]").WithLocation(25, 13), - // (26,13): warning CS9504: One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // (26,13): warning CS9504: One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. // _ = new Test4()[d3, d4, d4]; // Called9 Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionIndexer, "new Test4()[d3, d4, d4]").WithLocation(26, 13) ); @@ -3319,7 +3319,7 @@ class C1 var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); comp.VerifyDiagnostics( - // (8,13): warning CS9504: One or more overloads of indexer having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // (8,13): warning CS9504: One or more indexer overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. // _ = new C1()[1, d, 2]; Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionIndexer, "new C1()[1, d, 2]").WithLocation(8, 13) ); @@ -3402,7 +3402,7 @@ public Test(params IEnumerable b) var comp = CreateCompilation(src, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); comp.VerifyDiagnostics( - // (8,18): error CS9502: Ambiguity between expanded and normal forms of non-array params collection parameter of 'Program.Test.Test(params IEnumerable)', the only corresponding argument has dynamic type. Consider casting the dynamic argument. + // (8,18): error CS9502: Ambiguity between expanded and normal forms of non-array params collection parameter of 'Program.Test.Test(params IEnumerable)', the only corresponding argument has the type 'dynamic'. Consider casting the dynamic argument. // new Test(d); Diagnostic(ErrorCode.ERR_ParamsCollectionAmbiguousDynamicArgument, "d").WithArguments("Program.Test.Test(params System.Collections.Generic.IEnumerable)").WithLocation(8, 18) ); @@ -3472,25 +3472,25 @@ class Test4 comp, expectedOutput: @"Called2Called1Called3Called5Called3Called4Called7Called6Called8Called9Called9"). VerifyDiagnostics( - // (8,9): warning CS9505: One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // (8,9): warning CS9505: One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. // new Test1(d1); // Called2 Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionConstructor, "new Test1(d1)").WithLocation(8, 9), - // (11,9): warning CS9505: One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // (11,9): warning CS9505: One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. // new Test1(d2); // Called1 Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionConstructor, "new Test1(d2)").WithLocation(11, 9), - // (12,9): warning CS9505: One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // (12,9): warning CS9505: One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. // new Test2(1, d1); // Called3 Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionConstructor, "new Test2(1, d1)").WithLocation(12, 9), - // (13,9): warning CS9505: One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // (13,9): warning CS9505: One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. // new Test2(1, d2); // Called5 Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionConstructor, "new Test2(1, d2)").WithLocation(13, 9), - // (20,9): warning CS9505: One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // (20,9): warning CS9505: One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. // new Test3(d3, 1, 2); // Called7 Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionConstructor, "new Test3(d3, 1, 2)").WithLocation(20, 9), - // (25,9): warning CS9505: One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // (25,9): warning CS9505: One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. // new Test4(d3, x, x); // Called9 Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionConstructor, "new Test4(d3, x, x)").WithLocation(25, 9), - // (26,9): warning CS9505: One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // (26,9): warning CS9505: One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. // new Test4(d3, d4, d4); // Called9 Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionConstructor, "new Test4(d3, d4, d4)").WithLocation(26, 9) ); @@ -3591,7 +3591,7 @@ public Test(int b1, int b2, int b3) var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); comp.VerifyDiagnostics( - // (8,9): warning CS9505: One or more overloads of constructor having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. + // (8,9): warning CS9505: One or more constructor overloads having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. // new Test(1, d, 2); Diagnostic(ErrorCode.WRN_DynamicDispatchToParamsCollectionConstructor, "new Test(1, d, 2)").WithLocation(8, 9) ); From 4ecbcdfa5e851b293202fa0ba456b1dddb099dc1 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Thu, 4 Jan 2024 16:03:03 -0800 Subject: [PATCH 3/4] Remove obsolete comments from test code --- .../CSharp/Test/Semantic/Semantics/DynamicTests.cs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/DynamicTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/DynamicTests.cs index a16d4f1501ada..c965d1742584e 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/DynamicTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/DynamicTests.cs @@ -4390,19 +4390,10 @@ static void Main() { dynamic d = 1; - // Produce an error. This cannot work correctly right now M1(in d, d = 2, in d); void M2(in dynamic x, int y, in dynamic z) => System.Console.WriteLine(x == y); - // NOTE: the following could work!!! - // - // Currently any kind of overloading that would require dynamic dispatch is not permitted - // for locals functions and dynamic dispatch is bypassed. - // - // We will still give an error for consistency with the case where the method is an ordinary private method. - // (and also in case if overloading restrictions are relaxed in the future and dispatch becomes necessary) - // M2(in d, d = 3, in d); } } From 9762f7ba2ff06a6730b744f9da24a3839bbb369d Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Mon, 8 Jan 2024 14:01:09 -0800 Subject: [PATCH 4/4] Update src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs --- .../CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs index 8d4e2a3ac683a..247759d6a5ceb 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs @@ -22715,7 +22715,7 @@ class Myclass static void Main() { dynamic d = null; - // Warning because Goo might be conditional. + // No warning because Goo is statically bound. Goo(d); // No warning; only the two-parameter Bar is conditional. Bar(d);