diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs index 06a853b99f712..36f16a496685c 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs @@ -683,7 +683,7 @@ private BoundExpression MakeDeconstructInvocationExpression( // This prevents, for example, an unused params parameter after the out parameters. var deconstructMethod = ((BoundCall)result).Method; var parameters = deconstructMethod.Parameters; - for (int i = (deconstructMethod.IsExtensionMethod ? 1 : 0); i < parameters.Length; i++) // Tracked by https://github.com/dotnet/roslyn/issues/76130: Test this code path with new extensions + for (int i = (deconstructMethod.IsExtensionMethod ? 1 : 0); i < parameters.Length; i++) { if (parameters[i].RefKind != RefKind.Out) { diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_InterpolatedString.cs b/src/Compilers/CSharp/Portable/Binder/Binder_InterpolatedString.cs index 2fe795e8b504f..fb21a3e6ba53a 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_InterpolatedString.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_InterpolatedString.cs @@ -339,7 +339,7 @@ private BoundInterpolatedString BindUnconvertedInterpolatedExpressionToFactory( SyntaxNode syntax = unconvertedSource.Syntax; ImmutableArray expressions = makeInterpolatedStringFactoryArguments(syntax, parts, diagnostics); - BoundExpression construction = MakeInvocationExpression( + BoundExpression construction = MakeInvocationExpression( // Tracked by https://github.com/dotnet/roslyn/issues/76130 : test this scenario with a delegate-returning property (should be blocked by virtue of allowFieldsAndProperties: false) syntax, new BoundTypeExpression(syntax, null, factoryType) { WasCompilerGenerated = true }, factoryMethod, diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs index c434edd5229eb..ef11a6d9fb00e 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs @@ -137,11 +137,11 @@ internal BoundExpression MakeInvocationExpression( } BoundExpression result = BindInvocationExpression( - node, node, methodName, boundExpression, analyzedArguments, diagnostics, queryClause, - ignoreNormalFormIfHasValidParamsParameter: ignoreNormalFormIfHasValidParamsParameter, + node, node, methodName, boundExpression, analyzedArguments, diagnostics, acceptOnlyMethods: !allowFieldsAndProperties, + queryClause, ignoreNormalFormIfHasValidParamsParameter: ignoreNormalFormIfHasValidParamsParameter, disallowExpandedNonArrayParams: disallowExpandedNonArrayParams); - // Query operator can't be called dynamically. + // Query operator can't be called dynamically. if (queryClause != null && result.Kind == BoundKind.DynamicInvocation) { // the error has already been reported by BindInvocationExpression @@ -245,7 +245,7 @@ BoundExpression bindArgumentsAndInvocation(InvocationExpressionSyntax node, Boun boundExpression = CheckValue(boundExpression, BindValueKind.RValueOrMethodGroup, diagnostics); string name = boundExpression.Kind == BoundKind.MethodGroup ? GetName(node.Expression) : null; BindArgumentsAndNames(node.ArgumentList, diagnostics, analyzedArguments, allowArglist: true); - return BindInvocationExpression(node, node.Expression, name, boundExpression, analyzedArguments, diagnostics); + return BindInvocationExpression(node, node.Expression, name, boundExpression, analyzedArguments, diagnostics, acceptOnlyMethods: false); } static bool receiverIsInvocation(InvocationExpressionSyntax node, out InvocationExpressionSyntax nested) @@ -324,6 +324,7 @@ private BoundExpression BindInvocationExpression( BoundExpression boundExpression, AnalyzedArguments analyzedArguments, BindingDiagnosticBag diagnostics, + bool acceptOnlyMethods, CSharpSyntaxNode queryClause = null, bool ignoreNormalFormIfHasValidParamsParameter = false, bool disallowExpandedNonArrayParams = false) @@ -356,7 +357,7 @@ private BoundExpression BindInvocationExpression( ignoreNormalFormIfHasValidParamsParameter: ignoreNormalFormIfHasValidParamsParameter, disallowExpandedNonArrayParams: disallowExpandedNonArrayParams, anyApplicableCandidates: out _, - acceptOnlyMethods: false); + acceptOnlyMethods: acceptOnlyMethods); } else if ((object)(delegateType = GetDelegateType(boundExpression)) != null) { @@ -727,7 +728,7 @@ private BoundExpression BindMethodGroupInvocation( Debug.Assert(extensionMemberAccess.Kind != BoundKind.MethodGroup); extensionMemberAccess = CheckValue(extensionMemberAccess, BindValueKind.RValue, diagnostics); - BoundExpression extensionMemberInvocation = BindInvocationExpression(syntax, expression, methodName: null, extensionMemberAccess, analyzedArguments, diagnostics); + BoundExpression extensionMemberInvocation = BindInvocationExpression(syntax, expression, methodName: null, extensionMemberAccess, analyzedArguments, diagnostics, acceptOnlyMethods: false); anyApplicableCandidates = !extensionMemberInvocation.HasAnyErrors; return extensionMemberInvocation; } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs index ce3304eef8da0..860fbe3e56536 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs @@ -1058,7 +1058,7 @@ deconstructMethod is null && if (deconstructMethod is null) hasErrors = true; - int skippedExtensionParameters = deconstructMethod?.IsExtensionMethod == true ? 1 : 0; // Tracked by https://github.com/dotnet/roslyn/issues/76130: Test this code path with new extensions + int skippedExtensionParameters = deconstructMethod?.IsExtensionMethod == true ? 1 : 0; for (int i = 0; i < node.Subpatterns.Count; i++) { var subPattern = node.Subpatterns[i]; diff --git a/src/Compilers/CSharp/Portable/Binder/RefSafetyAnalysis.cs b/src/Compilers/CSharp/Portable/Binder/RefSafetyAnalysis.cs index 91747ec2bbc09..019efd40e184b 100644 --- a/src/Compilers/CSharp/Portable/Binder/RefSafetyAnalysis.cs +++ b/src/Compilers/CSharp/Portable/Binder/RefSafetyAnalysis.cs @@ -627,7 +627,7 @@ static SafeContext getDeclarationValEscape(BoundTypeExpression typeExpression, S // and so the ref safety of the pattern is equivalent to a `Deconstruct(out var ...)` invocation // where "safe-context inference of declaration expressions" would have the same effect. if (node.DeconstructMethod is { } m && - tryGetThisParameter(m)?.EffectiveScope == ScopedKind.None) + tryGetReceiverParameter(m)?.EffectiveScope == ScopedKind.None) { using (new PatternInput(this, _localScopeDepth)) { @@ -637,12 +637,16 @@ static SafeContext getDeclarationValEscape(BoundTypeExpression typeExpression, S return base.VisitRecursivePattern(node); - static ParameterSymbol? tryGetThisParameter(MethodSymbol method) + static ParameterSymbol? tryGetReceiverParameter(MethodSymbol method) { - if (method.IsExtensionMethod) // Tracked by https://github.com/dotnet/roslyn/issues/76130: Test this code path with new extensions + if (method.IsExtensionMethod) { return method.Parameters is [{ } firstParameter, ..] ? firstParameter : null; } + else if (method.GetIsNewExtensionMember()) + { + return method.ContainingType.ExtensionParameter; + } return method.TryGetThisParameter(out var thisParameter) ? thisParameter : null; } diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs index 6739e439ee5ad..e6c1bb9edd37f 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs @@ -652,7 +652,7 @@ private void MakeExplicitParameterTypeInferences(Binder binder, BoundExpression } else if (IsUnfixedTypeParameter(target) && !target.NullableAnnotation.IsAnnotated() && kind is ExactOrBoundsKind.LowerBound) { - var ordinal = GetOrdinal((TypeParameterSymbol)target.Type); // Tracked by https://github.com/dotnet/roslyn/issues/76130 : test nullability scenario where the override of ordinals matters + var ordinal = GetOrdinal((TypeParameterSymbol)target.Type); _nullableAnnotationLowerBounds[ordinal] = _nullableAnnotationLowerBounds[ordinal].Join(argumentType.NullableAnnotation); } } diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 61cb849a9e4d7..b3f569a40c14f 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -547,7 +547,7 @@ Inconsistent accessibility: indexer return type '{1}' is less accessible than indexer '{0}' - Inconsistent accessibility: parameter type '{1}' is less accessible than indexer '{0}' + Inconsistent accessibility: parameter type '{1}' is less accessible than indexer or property '{0}' Inconsistent accessibility: return type '{1}' is less accessible than operator '{0}' diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.PatternLocalRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.PatternLocalRewriter.cs index 56b944a4888b2..ac58ea84b9d5a 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.PatternLocalRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.PatternLocalRewriter.cs @@ -152,6 +152,7 @@ protected BoundExpression LowerEvaluation(BoundDagEvaluation evaluation) PropertySymbol property = p.Property; var outputTemp = new BoundDagTemp(p.Syntax, property.Type, p); BoundExpression output = _tempAllocator.GetTemp(outputTemp); + input = _factory.ConvertReceiverForExtensionMemberIfNeeded(property, input); return _factory.AssignmentExpression(output, _localRewriter.MakePropertyAccess(_factory.Syntax, input, property, LookupResultKind.Viable, property.Type, isLeftOfAssignment: false)); } @@ -169,7 +170,7 @@ void addArg(RefKind refKind, BoundExpression expression) Debug.Assert(method.Name == WellKnownMemberNames.DeconstructMethodName); int extensionExtra; - if (method.IsStatic) // Tracked by https://github.com/dotnet/roslyn/issues/76130: Test this code path with new extensions + if (method.IsStatic) { Debug.Assert(method.IsExtensionMethod); receiver = _factory.Type(method.ContainingType); @@ -190,6 +191,7 @@ void addArg(RefKind refKind, BoundExpression expression) addArg(RefKind.Out, _tempAllocator.GetTemp(outputTemp)); } + receiver = _factory.ConvertReceiverForExtensionMemberIfNeeded(method, receiver); return _factory.Call(receiver, method, refKindBuilder.ToImmutableAndFree(), argBuilder.ToImmutableAndFree()); } diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_FixedStatement.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_FixedStatement.cs index 892a1ba24ef29..718c3fda82af6 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_FixedStatement.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_FixedStatement.cs @@ -355,6 +355,7 @@ private BoundStatement InitializeFixedStatementGetPinnable( } // .GetPinnable() + callReceiver = factory.ConvertReceiverForExtensionMemberIfNeeded(getPinnableMethod, callReceiver); var getPinnableCall = getPinnableMethod.IsStatic ? factory.Call(null, getPinnableMethod, callReceiver) : factory.Call(callReceiver, getPinnableMethod); diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_ObjectOrCollectionInitializerExpression.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_ObjectOrCollectionInitializerExpression.cs index ec0cd11e141fe..da2b10c2df251 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_ObjectOrCollectionInitializerExpression.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_ObjectOrCollectionInitializerExpression.cs @@ -698,9 +698,11 @@ private BoundExpression MakeObjectInitializerMemberAccess( #if DEBUG var discardedUseSiteInfo = CompoundUseSiteInfo.Discarded; Debug.Assert(_compilation.Conversions.ClassifyConversionFromType(rewrittenReceiver.Type, memberSymbol.ContainingType, isChecked: false, ref discardedUseSiteInfo).IsImplicit || + (memberSymbol.GetIsNewExtensionMember() && !memberSymbol.IsStatic && ConversionsBase.IsValidExtensionMethodThisArgConversion(_compilation.Conversions.ClassifyConversionFromType(rewrittenReceiver.Type, memberSymbol.ContainingType.ExtensionParameter!.Type, isChecked: false, ref discardedUseSiteInfo))) || _compilation.Conversions.HasImplicitConversionToOrImplementsVarianceCompatibleInterface(rewrittenReceiver.Type, memberSymbol.ContainingType, ref discardedUseSiteInfo, out _)); // It is possible there are use site diagnostics from the above, but none that we need report as we aren't generating code for the conversion #endif + rewrittenReceiver = _factory.ConvertReceiverForExtensionMemberIfNeeded(memberSymbol, rewrittenReceiver); switch (memberSymbol.Kind) { diff --git a/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs b/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs index 15748f836eb9c..72e2a86bf7c93 100644 --- a/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs +++ b/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs @@ -431,6 +431,24 @@ public BoundExpression AssignmentExpression(BoundExpression left, BoundExpressio return AssignmentExpression(Syntax, left, right, isRef: isRef, wasCompilerGenerated: true); } + public BoundExpression ConvertReceiverForExtensionMemberIfNeeded(Symbol member, BoundExpression receiver) + { + if (member.GetIsNewExtensionMember()) + { + Debug.Assert(!member.IsStatic); + ParameterSymbol? extensionParameter = member.ContainingType.ExtensionParameter; + Debug.Assert(extensionParameter is not null); +#if DEBUG + var discardedUseSiteInfo = CompoundUseSiteInfo.Discarded; + Debug.Assert(Conversions.IsValidExtensionMethodThisArgConversion(this.Compilation.Conversions.ClassifyConversionFromType(receiver.Type, extensionParameter.Type, isChecked: false, ref discardedUseSiteInfo))); +#endif + + return this.Convert(extensionParameter.Type, receiver); + } + + return receiver; + } + /// /// Creates a general assignment that might be instrumented. /// diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 37ae8bfc426e4..164941bfe1cf5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -6009,8 +6009,8 @@ - Inconsistent accessibility: parameter type '{1}' is less accessible than indexer '{0}' - Nekonzistentní dostupnost: Typ parametru {1} je míň dostupný než indexer {0}. + Inconsistent accessibility: parameter type '{1}' is less accessible than indexer or property '{0}' + Nekonzistentní dostupnost: Typ parametru {1} je míň dostupný než indexer {0}. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index e481e2a789344..2cfd37350a1fa 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -6009,8 +6009,8 @@ - Inconsistent accessibility: parameter type '{1}' is less accessible than indexer '{0}' - Inkonsistenter Zugriff: Parametertyp "{1}" ist weniger zugreifbar als Indexer "{0}". + Inconsistent accessibility: parameter type '{1}' is less accessible than indexer or property '{0}' + Inkonsistenter Zugriff: Parametertyp "{1}" ist weniger zugreifbar als Indexer "{0}". diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 3dcae73e93f47..5b904b8347d5e 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -6009,8 +6009,8 @@ - Inconsistent accessibility: parameter type '{1}' is less accessible than indexer '{0}' - Incoherencia de accesibilidad: el tipo de parámetro '{1}' es menos accesible que el indizador '{0}' + Inconsistent accessibility: parameter type '{1}' is less accessible than indexer or property '{0}' + Incoherencia de accesibilidad: el tipo de parámetro '{1}' es menos accesible que el indizador '{0}' diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 73299c0f6772f..3643165b3ae3c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -6009,8 +6009,8 @@ - Inconsistent accessibility: parameter type '{1}' is less accessible than indexer '{0}' - Accessibilité incohérente : le type de paramètre '{1}' est moins accessible que l'indexeur '{0}' + Inconsistent accessibility: parameter type '{1}' is less accessible than indexer or property '{0}' + Accessibilité incohérente : le type de paramètre '{1}' est moins accessible que l'indexeur '{0}' diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index ca9c6d183269e..8f62ff52a10f7 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -6009,8 +6009,8 @@ target:module Compila un modulo che può essere aggiunto ad altro - Inconsistent accessibility: parameter type '{1}' is less accessible than indexer '{0}' - Accessibilità incoerente: il tipo parametro '{1}' è meno accessibile dell'indicizzatore '{0}' + Inconsistent accessibility: parameter type '{1}' is less accessible than indexer or property '{0}' + Accessibilità incoerente: il tipo parametro '{1}' è meno accessibile dell'indicizzatore '{0}' diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 64ffd6274eeff..af9147be02882 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -6009,8 +6009,8 @@ - Inconsistent accessibility: parameter type '{1}' is less accessible than indexer '{0}' - アクセシビリティに一貫性がありません。パラメーター型 '{1}' のアクセシビリティはインデクサー '{0}' よりも低く設定されています + Inconsistent accessibility: parameter type '{1}' is less accessible than indexer or property '{0}' + アクセシビリティに一貫性がありません。パラメーター型 '{1}' のアクセシビリティはインデクサー '{0}' よりも低く設定されています diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 7c16a674e240b..8f1588fb75407 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -6009,8 +6009,8 @@ - Inconsistent accessibility: parameter type '{1}' is less accessible than indexer '{0}' - 일관성 없는 액세스 가능성: '{1}' 매개 변수 형식이 '{0}' 인덱서보다 액세스하기 어렵습니다. + Inconsistent accessibility: parameter type '{1}' is less accessible than indexer or property '{0}' + 일관성 없는 액세스 가능성: '{1}' 매개 변수 형식이 '{0}' 인덱서보다 액세스하기 어렵습니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 40a51a9d7aba7..8a892cfd63dc2 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -6009,8 +6009,8 @@ - Inconsistent accessibility: parameter type '{1}' is less accessible than indexer '{0}' - Niespójność dostępności: typ parametru „{1}” jest mniej dostępny niż indeksator „{0}” + Inconsistent accessibility: parameter type '{1}' is less accessible than indexer or property '{0}' + Niespójność dostępności: typ parametru „{1}” jest mniej dostępny niż indeksator „{0}” diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 133576185f638..827cc499e6797 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -6009,8 +6009,8 @@ - Inconsistent accessibility: parameter type '{1}' is less accessible than indexer '{0}' - Acessibilidade inconsistente: tipo de parâmetro "{1}" é menos acessível do que o indexador "{0}" + Inconsistent accessibility: parameter type '{1}' is less accessible than indexer or property '{0}' + Acessibilidade inconsistente: tipo de parâmetro "{1}" é menos acessível do que o indexador "{0}" diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 30b7d953160bf..7488a8c4a28a1 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -6010,8 +6010,8 @@ - Inconsistent accessibility: parameter type '{1}' is less accessible than indexer '{0}' - Несогласованность по доступности: доступность типа параметра "{1}" ниже доступности индексатора "{0}" + Inconsistent accessibility: parameter type '{1}' is less accessible than indexer or property '{0}' + Несогласованность по доступности: доступность типа параметра "{1}" ниже доступности индексатора "{0}" diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 2c46ca1dae051..1e55e37679f67 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -6009,8 +6009,8 @@ - Inconsistent accessibility: parameter type '{1}' is less accessible than indexer '{0}' - Tutarsız erişilebilirlik: '{1}' parametre türü, '{0}' dizin oluşturucusundan daha az erişilebilir + Inconsistent accessibility: parameter type '{1}' is less accessible than indexer or property '{0}' + Tutarsız erişilebilirlik: '{1}' parametre türü, '{0}' dizin oluşturucusundan daha az erişilebilir diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 8ca0b9a047b72..d205367c9b87f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -6009,8 +6009,8 @@ - Inconsistent accessibility: parameter type '{1}' is less accessible than indexer '{0}' - 可访问性不一致: 参数类型“{1}”的可访问性低于索引器“{0}” + Inconsistent accessibility: parameter type '{1}' is less accessible than indexer or property '{0}' + 可访问性不一致: 参数类型“{1}”的可访问性低于索引器“{0}” diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 04b102802f385..fa2ad94a2450f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -6009,8 +6009,8 @@ strument:TestCoverage 產生檢測要收集 - Inconsistent accessibility: parameter type '{1}' is less accessible than indexer '{0}' - 不一致的存取範圍: 參數類型 '{1}' 比索引子 '{0}' 的存取範圍小 + Inconsistent accessibility: parameter type '{1}' is less accessible than indexer or property '{0}' + 不一致的存取範圍: 參數類型 '{1}' 比索引子 '{0}' 的存取範圍小 diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs index a79f04945d6b0..0e748539c83b7 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs @@ -30,362 +30,6 @@ protected CompilationVerifier CompileAndVerifyUtil( /// protected static MetadataReference ExpressionAssemblyRef => SystemCoreRef_v46; - #region A string containing expression-tree dumping utilities - private const string ExpressionTestLibrary = @" -using System; -using System.Globalization; -using System.Linq.Expressions; -using System.Text; - -public class TestBase -{ - protected static void DCheck(Expression e, string expected) { Check(e.Dump(), expected); } - protected static void Check(Expression> e, string expected) { Check(e.Dump(), expected); } - protected static void Check(Expression> e, string expected) { Check(e.Dump(), expected); } - protected static void Check(Expression> e, string expected) { Check(e.Dump(), expected); } - protected static void Check(Expression> e, string expected) { Check(e.Dump(), expected); } - protected static string ToString(Expression> e) { return e.Dump(); } - protected static string ToString(Expression> e) { return e.Dump(); } - protected static string ToString(Expression> e) { return e.Dump(); } - private static void Check(string actual, string expected) - { - if (expected != actual) - { - Console.WriteLine(""FAIL""); - Console.WriteLine(""expected: "" + expected); - Console.WriteLine(""actual: "" + actual); -// throw new Exception(""expected='"" + expected + ""'; actual='"" + actual + ""'""); - } - } -} - -public static class ExpressionExtensions -{ - public static string Dump(this Expression self) - { - return ExpressionPrinter.Print(self.Body); - } -} - -class ExpressionPrinter : System.Linq.Expressions.ExpressionVisitor -{ - private StringBuilder s = new StringBuilder(); - - public static string Print(Expression e) - { - var p = new ExpressionPrinter(); - p.Visit(e); - return p.s.ToString(); - } - - public override Expression Visit(Expression node) - { - if (node == null) { s.Append(""null""); return null; } - s.Append(node.NodeType.ToString()); - s.Append(""(""); - base.Visit(node); - s.Append("" Type:"" + node.Type); - s.Append("")""); - return null; - } - - protected override MemberBinding VisitMemberBinding(MemberBinding node) - { - if (node == null) { s.Append(""null""); return null; } - return base.VisitMemberBinding(node); - } - - protected override MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding node) - { - s.Append(""MemberMemberBinding(Member=""); - s.Append(node.Member.ToString()); - foreach (var b in node.Bindings) - { - s.Append("" ""); - VisitMemberBinding(b); - } - s.Append("")""); - return null; - } - - protected override MemberListBinding VisitMemberListBinding(MemberListBinding node) - { - s.Append(""MemberListBinding(Member=""); - s.Append(node.Member.ToString()); - foreach (var i in node.Initializers) - { - s.Append("" ""); - VisitElementInit(i); - } - s.Append("")""); - return null; - } - - protected override MemberAssignment VisitMemberAssignment(MemberAssignment node) - { - s.Append(""MemberAssignment(Member=""); - s.Append(node.Member.ToString()); - s.Append("" Expression=""); - Visit(node.Expression); - s.Append("")""); - return null; - } - - protected override Expression VisitMemberInit(MemberInitExpression node) - { - s.Append(""NewExpression: ""); - Visit(node.NewExpression); - s.Append("" Bindings:[""); - bool first = true; - foreach (var b in node.Bindings) - { - if (!first) s.Append("" ""); - VisitMemberBinding(b); - first = false; - } - s.Append(""]""); - return null; - } - - protected override Expression VisitBinary(BinaryExpression node) - { - Visit(node.Left); - s.Append("" ""); - Visit(node.Right); - if (node.Conversion != null) - { - s.Append("" Conversion:""); - Visit(node.Conversion); - } - if (node.IsLifted) s.Append("" Lifted""); - if (node.IsLiftedToNull) s.Append("" LiftedToNull""); - if (node.Method != null) s.Append("" Method:["" + node.Method + ""]""); - return null; - } - - protected override Expression VisitConditional(ConditionalExpression node) - { - Visit(node.Test); - s.Append("" ? ""); - Visit(node.IfTrue); - s.Append("" : ""); - Visit(node.IfFalse); - return null; - } - - protected override Expression VisitConstant(ConstantExpression node) - { - // s.Append(node.Value == null ? ""null"" : node.Value.ToString()); - s.Append(node.Value == null ? ""null"" : GetCultureInvariantString(node.Value)); - return null; - } - - protected override Expression VisitDefault(DefaultExpression node) - { - return null; - } - - protected override Expression VisitIndex(IndexExpression node) - { - Visit(node.Object); - s.Append(""[""); - int n = node.Arguments.Count; - for (int i = 0; i < n; i++) - { - if (i != 0) s.Append("" ""); - Visit(node.Arguments[i]); - } - s.Append(""]""); - if (node.Indexer != null) s.Append("" Indexer:"" + node.Indexer); - return null; - } - - protected override Expression VisitInvocation(InvocationExpression node) - { - Visit(node.Expression); - s.Append(""(""); - int n = node.Arguments.Count; - for (int i = 0; i < n; i++) - { - if (i != 0) s.Append("" ""); - Visit(node.Arguments[i]); - } - s.Append("")""); - return null; - } - - protected override Expression VisitLambda(Expression node) - { - s.Append(""(""); - int n = node.Parameters.Count; - for (int i = 0; i < n; i++) - { - if (i != 0) s.Append("" ""); - Visit(node.Parameters[i]); - } - s.Append("") => ""); - if (node.Name != null) s.Append(node.Name); - Visit(node.Body); - if (node.ReturnType != null) s.Append("" ReturnType:"" + node.ReturnType); - if (node.TailCall) s.Append("" TailCall""); - return null; - } - - protected override Expression VisitListInit(ListInitExpression node) - { - Visit(node.NewExpression); - s.Append(""{""); - int n = node.Initializers.Count; - for (int i = 0; i < n; i++) - { - if (i != 0) s.Append("" ""); - Visit(node.Initializers[i]); - } - s.Append(""}""); - return null; - } - - protected override ElementInit VisitElementInit(ElementInit node) - { - Visit(node); - return null; - } - - private void Visit(ElementInit node) - { - s.Append(""ElementInit(""); - s.Append(node.AddMethod); - int n = node.Arguments.Count; - for (int i = 0; i < n; i++) - { - s.Append("" ""); - Visit(node.Arguments[i]); - } - s.Append("")""); - } - - protected override Expression VisitMember(MemberExpression node) - { - Visit(node.Expression); - s.Append("".""); - s.Append(node.Member.Name); - return null; - } - - protected override Expression VisitMethodCall(MethodCallExpression node) - { - Visit(node.Object); - s.Append("".["" + node.Method + ""]""); - s.Append(""(""); - int n = node.Arguments.Count; - for (int i = 0; i < n; i++) - { - if (i != 0) s.Append("", ""); - Visit(node.Arguments[i]); - } - s.Append("")""); - return null; - } - - protected override Expression VisitNew(NewExpression node) - { - s.Append((node.Constructor != null) ? ""["" + node.Constructor + ""]"" : ""<.ctor>""); - s.Append(""(""); - int n = node.Arguments.Count; - for (int i = 0; i < n; i++) - { - if (i != 0) s.Append("", ""); - Visit(node.Arguments[i]); - } - s.Append("")""); - if (node.Members != null) - { - n = node.Members.Count; - if (n != 0) - { - s.Append(""{""); - for (int i = 0; i < n; i++) - { - var info = node.Members[i]; - if (i != 0) s.Append("" ""); - s.Append(info); - } - s.Append(""}""); - } - } - return null; - } - - protected override Expression VisitNewArray(NewArrayExpression node) - { - s.Append(""[""); - int n = node.Expressions.Count; - for (int i = 0; i < n; i++) - { - if (i != 0) s.Append("" ""); - Visit(node.Expressions[i]); - } - s.Append(""]""); - return null; - } - - protected override Expression VisitParameter(ParameterExpression node) - { - s.Append(node.Name); - if (node.IsByRef) s.Append("" ByRef""); - return null; - } - - protected override Expression VisitTypeBinary(TypeBinaryExpression node) - { - Visit(node.Expression); - s.Append("" TypeOperand:"" + node.TypeOperand); - return null; - } - - protected override Expression VisitUnary(UnaryExpression node) - { - Visit(node.Operand); - if (node.IsLifted) s.Append("" Lifted""); - if (node.IsLiftedToNull) s.Append("" LiftedToNull""); - if (node.Method != null) s.Append("" Method:["" + node.Method + ""]""); - return null; - } - - public static string GetCultureInvariantString(object value) - { - var valueType = value.GetType(); - if (valueType == typeof(string)) - { - return value as string; - } - - if (valueType == typeof(DateTime)) - { - return ((DateTime)value).ToString(""M/d/yyyy h:mm:ss tt"", CultureInfo.InvariantCulture); - } - - if (valueType == typeof(float)) - { - return ((float)value).ToString(CultureInfo.InvariantCulture); - } - - if (valueType == typeof(double)) - { - return ((double)value).ToString(CultureInfo.InvariantCulture); - } - - if (valueType == typeof(decimal)) - { - return ((decimal)value).ToString(CultureInfo.InvariantCulture); - } - - return value.ToString(); - } -} -"; - #endregion A string containing expression-tree dumping utilities - [Fact] public void ExprLambdaReordering() { diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs index 17f3ef8e322cb..b0656529312c0 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs @@ -24,7 +24,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics; [CompilerTrait(CompilerFeature.Extensions)] -public class ExtensionTests : CompilingTestBase +public partial class ExtensionTests : CompilingTestBase { private static string ExpectedOutput(string output) { @@ -126,10 +126,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [netstandard]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object '' - ) cil managed + ) cil managed { .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -296,10 +296,10 @@ 01 00 00 00 extends [netstandard]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( !T '' - ) cil managed + ) cil managed { .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -585,10 +585,10 @@ extends [netstandard]System.Object 01 00 01 00 00 ) // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( !T '' - ) cil managed + ) cil managed { .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -829,10 +829,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [netstandard]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object '' - ) cil managed + ) cil managed { .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -1125,10 +1125,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [netstandard]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( class [netstandard]System.Text.StringBuilder '' - ) cil managed + ) cil managed { .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -1138,10 +1138,10 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method public hidebysig static + .method public hidebysig static class [netstandard]System.Text.StringBuilder Inspect ( class [netstandard]System.Text.StringBuilder sb - ) cil managed + ) cil managed { // Method begins at RVA 0x20a7 // Code size 2 (0x2) @@ -1159,8 +1159,8 @@ 01 00 00 00 // Fields .field public class [netstandard]System.Text.StringBuilder sb // Methods - .method public hidebysig specialname rtspecialname - instance void .ctor () cil managed + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed { // Method begins at RVA 0x2079 // Code size 7 (0x7) @@ -1169,8 +1169,8 @@ .maxstack 8 IL_0001: call instance void [netstandard]System.Object::.ctor() IL_0006: ret } // end of method '<>c__DisplayClass1_0'::.ctor - .method assembly hidebysig - instance void 'b__0' () cil managed + .method assembly hidebysig + instance void 'b__0' () cil managed { // Method begins at RVA 0x20ac // Code size 42 (0x2a) @@ -1204,10 +1204,10 @@ [1] int32 } // end of method '<>c__DisplayClass1_0'::'b__0' } // end of class <>c__DisplayClass1_0 // Methods - .method public hidebysig static + .method public hidebysig static class [netstandard]System.Text.StringBuilder Inspect ( class [netstandard]System.Text.StringBuilder sb - ) cil managed + ) cil managed { // Method begins at RVA 0x2081 // Code size 35 (0x23) @@ -1289,10 +1289,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [netstandard]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( int32 '' - ) cil managed + ) cil managed { .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -1302,8 +1302,8 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method public hidebysig static - class [netstandard]System.Action DoSomething () cil managed + .method public hidebysig static + class [netstandard]System.Action DoSomething () cil managed { // Method begins at RVA 0x20be // Code size 2 (0x2) @@ -1321,8 +1321,8 @@ 01 00 00 00 // Fields .field public int32 b // Methods - .method public hidebysig specialname rtspecialname - instance void .ctor () cil managed + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed { // Method begins at RVA 0x2073 // Code size 7 (0x7) @@ -1331,8 +1331,8 @@ .maxstack 8 IL_0001: call instance void [netstandard]System.Object::.ctor() IL_0006: ret } // end of method '<>c__DisplayClass1_0'::.ctor - .method assembly hidebysig - instance void 'b__0' () cil managed + .method assembly hidebysig + instance void 'b__0' () cil managed { // Method begins at RVA 0x20c4 // Code size 35 (0x23) @@ -1357,8 +1357,8 @@ [0] int32 } // end of method '<>c__DisplayClass1_0'::'b__0' } // end of class <>c__DisplayClass1_0 // Methods - .method public hidebysig static - class [netstandard]System.Action DoSomething () cil managed + .method public hidebysig static + class [netstandard]System.Action DoSomething () cil managed { // Method begins at RVA 0x207c // Code size 52 (0x34) @@ -1454,10 +1454,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [netstandard]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( int32 '' - ) cil managed + ) cil managed { .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -1467,8 +1467,8 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method public hidebysig static - class [netstandard]System.Action DoSomething () cil managed + .method public hidebysig static + class [netstandard]System.Action DoSomething () cil managed { // Method begins at RVA 0x20bc // Code size 2 (0x2) @@ -1486,8 +1486,8 @@ 01 00 00 00 // Fields .field public int32 b // Methods - .method public hidebysig specialname rtspecialname - instance void .ctor () cil managed + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed { // Method begins at RVA 0x2073 // Code size 7 (0x7) @@ -1496,8 +1496,8 @@ .maxstack 8 IL_0001: call instance void [netstandard]System.Object::.ctor() IL_0006: ret } // end of method '<>c__DisplayClass1_0'::.ctor - .method assembly hidebysig - instance void 'b__0' () cil managed + .method assembly hidebysig + instance void 'b__0' () cil managed { // Method begins at RVA 0x20c0 // Code size 35 (0x23) @@ -1522,8 +1522,8 @@ [0] int32 } // end of method '<>c__DisplayClass1_0'::'b__0' } // end of class <>c__DisplayClass1_0 // Methods - .method public hidebysig static - class [netstandard]System.Action DoSomething () cil managed + .method public hidebysig static + class [netstandard]System.Action DoSomething () cil managed { // Method begins at RVA 0x207c // Code size 50 (0x32) @@ -1744,10 +1744,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [netstandard]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o - ) cil managed + ) cil managed { .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -1757,8 +1757,8 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method private hidebysig - instance void M () cil managed + .method private hidebysig + instance void M () cil managed { // Method begins at RVA 0x2069 // Code size 2 (0x2) @@ -1768,10 +1768,10 @@ .maxstack 8 } // end of method '<>E__0'::M } // end of class <>E__0 // Methods - .method private hidebysig static + .method private hidebysig static void M ( object o - ) cil managed + ) cil managed { .custom instance void [netstandard]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 @@ -1850,10 +1850,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [netstandard]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object '' - ) cil managed + ) cil managed { .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -1863,8 +1863,8 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method private hidebysig static - void M () cil managed + .method private hidebysig static + void M () cil managed { // Method begins at RVA 0x2069 // Code size 2 (0x2) @@ -1874,8 +1874,8 @@ .maxstack 8 } // end of method '<>E__0'::M } // end of class <>E__0 // Methods - .method private hidebysig static - void M () cil managed + .method private hidebysig static + void M () cil managed { // Method begins at RVA 0x2067 // Code size 1 (0x1) @@ -1971,10 +1971,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [netstandard]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o - ) cil managed + ) cil managed { .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -1984,8 +1984,8 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method private hidebysig specialname - instance int32 get_Property () cil managed + .method private hidebysig specialname + instance int32 get_Property () cil managed { // Method begins at RVA 0x206d // Code size 2 (0x2) @@ -1993,10 +1993,10 @@ .maxstack 8 IL_0000: ldnull IL_0001: throw } // end of method '<>E__0'::get_Property - .method private hidebysig specialname + .method private hidebysig specialname instance void set_Property ( int32 'value' - ) cil managed + ) cil managed { // Method begins at RVA 0x206d // Code size 2 (0x2) @@ -2012,10 +2012,10 @@ .property instance int32 Property() } } // end of class <>E__0 // Methods - .method private hidebysig static + .method private hidebysig static int32 get_Property ( object o - ) cil managed + ) cil managed { // Method begins at RVA 0x2067 // Code size 3 (0x3) @@ -2023,11 +2023,11 @@ .maxstack 8 IL_0000: ldc.i4.s 42 IL_0002: ret } // end of method Extensions::get_Property - .method private hidebysig static + .method private hidebysig static void set_Property ( object o, int32 'value' - ) cil managed + ) cil managed { // Method begins at RVA 0x206b // Code size 1 (0x1) @@ -2140,10 +2140,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [netstandard]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object '' - ) cil managed + ) cil managed { .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -2153,8 +2153,8 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method private hidebysig specialname static - int32 get_Property () cil managed + .method private hidebysig specialname static + int32 get_Property () cil managed { // Method begins at RVA 0x206d // Code size 2 (0x2) @@ -2162,10 +2162,10 @@ .maxstack 8 IL_0000: ldnull IL_0001: throw } // end of method '<>E__0'::get_Property - .method private hidebysig specialname static + .method private hidebysig specialname static void set_Property ( int32 'value' - ) cil managed + ) cil managed { // Method begins at RVA 0x206d // Code size 2 (0x2) @@ -2181,8 +2181,8 @@ .property int32 Property() } } // end of class <>E__0 // Methods - .method private hidebysig static - int32 get_Property () cil managed + .method private hidebysig static + int32 get_Property () cil managed { // Method begins at RVA 0x2067 // Code size 3 (0x3) @@ -2190,10 +2190,10 @@ .maxstack 8 IL_0000: ldc.i4.s 42 IL_0002: ret } // end of method Extensions::get_Property - .method private hidebysig static + .method private hidebysig static void set_Property ( int32 'value' - ) cil managed + ) cil managed { // Method begins at RVA 0x206b // Code size 1 (0x1) @@ -2279,10 +2279,10 @@ extends [netstandard]System.Object 01 00 04 49 74 65 6d 00 00 ) // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o - ) cil managed + ) cil managed { .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -2292,10 +2292,10 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method private hidebysig specialname + .method private hidebysig specialname instance int32 get_Item ( int32 i - ) cil managed + ) cil managed { // Method begins at RVA 0x206d // Code size 2 (0x2) @@ -2303,11 +2303,11 @@ .maxstack 8 IL_0000: ldnull IL_0001: throw } // end of method '<>E__0'::get_Item - .method private hidebysig specialname + .method private hidebysig specialname instance void set_Item ( int32 i, int32 'value' - ) cil managed + ) cil managed { // Method begins at RVA 0x206d // Code size 2 (0x2) @@ -2325,11 +2325,11 @@ int32 i } } // end of class <>E__0 // Methods - .method private hidebysig static + .method private hidebysig static int32 get_Item ( object o, int32 i - ) cil managed + ) cil managed { // Method begins at RVA 0x2067 // Code size 3 (0x3) @@ -2337,12 +2337,12 @@ .maxstack 8 IL_0000: ldc.i4.s 42 IL_0002: ret } // end of method Extensions::get_Item - .method private hidebysig static + .method private hidebysig static void set_Item ( object o, int32 i, int32 'value' - ) cil managed + ) cil managed { // Method begins at RVA 0x206b // Code size 1 (0x1) @@ -2731,7 +2731,7 @@ public void ReceiverParameter_WithIdentifier() var src = """ public static class Extensions { - extension(object o) + extension(object o) { public object M() { return o; } } @@ -2884,7 +2884,7 @@ public void ReceiverParameter_TypeParameter_Unreferenced_01() public static class Extensions { - extension(int) + extension(int) { public static void M() { } } @@ -2896,7 +2896,7 @@ public static void M() { } // int.M(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "M").WithArguments("int", "M").WithLocation(1, 5), // (5,18): error CS9295: The extended type 'int' must reference all the type parameters declared by the extension, but type parameter 'T' is not referenced. - // extension(int) + // extension(int) Diagnostic(ErrorCode.ERR_UnderspecifiedExtension, "int").WithArguments("int", "T").WithLocation(5, 18)); } @@ -2908,7 +2908,7 @@ public void ReceiverParameter_TypeParameter_Unreferenced_02() public static class Extensions { - extension(T1) + extension(T1) { public static void M() { } } @@ -2920,7 +2920,7 @@ public static void M() { } // int.M(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "M").WithArguments("int", "M").WithLocation(1, 5), // (5,23): error CS9295: The extended type 'T1' must reference all the type parameters declared by the extension, but type parameter 'T2' is not referenced. - // extension(T1) + // extension(T1) Diagnostic(ErrorCode.ERR_UnderspecifiedExtension, "T1").WithArguments("T1", "T2").WithLocation(5, 23)); } @@ -3302,7 +3302,7 @@ public void ReceiverParameter_Ref_01() public static class Extensions { - extension(ref int i) + extension(ref int i) { public void M() { System.Console.Write(i); i = 43; } } @@ -3519,7 +3519,7 @@ public void ReceiverParameter_RefReadonly_01() public static class Extensions { - extension(ref readonly int i) + extension(ref readonly int i) { public void M() { System.Console.Write(i); } } @@ -3941,25 +3941,51 @@ static class Extensions ); } - [Fact] - public void ReceiverParameter_RefScope() + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/78491")] + public void ReceiverParameter_RefScope_01() { var src = """ +int i = 42; +i.M(); + static class Extensions { extension(scoped ref int receiver) { + public void M() => System.Console.Write(receiver); } } """; var comp = CreateCompilation(src); - CompileAndVerify(comp, symbolValidator: (m) => + CompileAndVerify(comp, expectedOutput: "42", symbolValidator: (m) => { AssertEx.Equal(ScopedKind.ScopedRef, m.GlobalNamespace.GetMember("Extensions.<>E__0.$").Parameters[0].EffectiveScope); }).VerifyDiagnostics(); } + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/78491")] + public void ReceiverParameter_RefScope_02() + { + var src = """ +int i = 42; +i.M(); + +static class Extensions +{ + extension(scoped ref int receiver) + { + public ref int M() => ref receiver; + } +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (8,35): error CS9075: Cannot return a parameter by reference 'receiver' because it is scoped to the current method + // public ref int M() => ref receiver; + Diagnostic(ErrorCode.ERR_RefReturnScopedParameter, "receiver").WithArguments("receiver").WithLocation(8, 35)); + } + [Fact] public void ReceiverParameter_Nullability() { @@ -3985,7 +4011,11 @@ static class Extensions AssertEx.Equal("System.String?", m.GlobalNamespace.GetMember("Extensions.<>E__1.$").Parameters[0].TypeWithAnnotations.ToTestDisplayString()); }).VerifyDiagnostics(); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : verify nullability in GetDeclaredSymbol and GetSymbolInfo + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var parameters = tree.GetRoot().DescendantNodes().OfType().ToArray(); + Assert.Equal("System.String? receiver", model.GetDeclaredSymbol(parameters[0]).ToTestDisplayString(includeNonNullable: true)); + Assert.Equal("System.String?", model.GetDeclaredSymbol(parameters[1]).ToTestDisplayString(includeNonNullable: true)); } [Fact] @@ -4044,12 +4074,10 @@ class C {} // (5,21): error CS0051: Inconsistent accessibility: parameter type 'C' is less accessible than method 'Extensions.extension(C).M()' // public void M() {} Diagnostic(ErrorCode.ERR_BadVisParamType, "M").WithArguments("Extensions.extension(C).M()", "C").WithLocation(5, 21), - - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : Error wording, this isn't an indexer - // (6,20): error CS0055: Inconsistent accessibility: parameter type 'C' is less accessible than indexer 'Extensions.extension(C).P' + // (6,20): error CS0055: Inconsistent accessibility: parameter type 'C' is less accessible than indexer or property 'Extensions.extension(C).P' // public int P { get => 0; set {}} Diagnostic(ErrorCode.ERR_BadVisIndexerParam, "P").WithArguments("Extensions.extension(C).P", "C").WithLocation(6, 20), - // (7,20): error CS0055: Inconsistent accessibility: parameter type 'C' is less accessible than indexer 'Extensions.extension(C).this[int]' + // (7,20): error CS0055: Inconsistent accessibility: parameter type 'C' is less accessible than indexer or property 'Extensions.extension(C).this[int]' // public int this[int i] { get => 0; set {}} Diagnostic(ErrorCode.ERR_BadVisIndexerParam, "this").WithArguments("Extensions.extension(C).this[int]", "C").WithLocation(7, 20) ); @@ -4103,22 +4131,19 @@ private class C {} // (5,21): error CS0051: Inconsistent accessibility: parameter type 'Extensions.C' is less accessible than method 'Extensions.extension(Extensions.C).M()' // public void M() {} Diagnostic(ErrorCode.ERR_BadVisParamType, "M").WithArguments("Extensions.extension(Extensions.C).M()", "Extensions.C").WithLocation(5, 21), - - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : Error wording, this isn't an indexer - - // (6,20): error CS0055: Inconsistent accessibility: parameter type 'Extensions.C' is less accessible than indexer 'Extensions.extension(Extensions.C).P' + // (6,20): error CS0055: Inconsistent accessibility: parameter type 'Extensions.C' is less accessible than indexer or property 'Extensions.extension(Extensions.C).P' // public int P { get => 0; set {}} Diagnostic(ErrorCode.ERR_BadVisIndexerParam, "P").WithArguments("Extensions.extension(Extensions.C).P", "Extensions.C").WithLocation(6, 20), - // (7,20): error CS0055: Inconsistent accessibility: parameter type 'Extensions.C' is less accessible than indexer 'Extensions.extension(Extensions.C).this[int]' + // (7,20): error CS0055: Inconsistent accessibility: parameter type 'Extensions.C' is less accessible than indexer or property 'Extensions.extension(Extensions.C).this[int]' // public int this[int i] { get => 0; set {}} Diagnostic(ErrorCode.ERR_BadVisIndexerParam, "this").WithArguments("Extensions.extension(Extensions.C).this[int]", "Extensions.C").WithLocation(7, 20), // (13,23): error CS0051: Inconsistent accessibility: parameter type 'Extensions.C' is less accessible than method 'Extensions.extension(Extensions.C).M2()' // internal void M2() {} Diagnostic(ErrorCode.ERR_BadVisParamType, "M2").WithArguments("Extensions.extension(Extensions.C).M2()", "Extensions.C").WithLocation(13, 23), - // (14,22): error CS0055: Inconsistent accessibility: parameter type 'Extensions.C' is less accessible than indexer 'Extensions.extension(Extensions.C).P2' + // (14,22): error CS0055: Inconsistent accessibility: parameter type 'Extensions.C' is less accessible than indexer or property 'Extensions.extension(Extensions.C).P2' // internal int P2 { get => 0; set {}} Diagnostic(ErrorCode.ERR_BadVisIndexerParam, "P2").WithArguments("Extensions.extension(Extensions.C).P2", "Extensions.C").WithLocation(14, 22), - // (15,22): error CS0055: Inconsistent accessibility: parameter type 'Extensions.C' is less accessible than indexer 'Extensions.extension(Extensions.C).this[byte]' + // (15,22): error CS0055: Inconsistent accessibility: parameter type 'Extensions.C' is less accessible than indexer or property 'Extensions.extension(Extensions.C).this[byte]' // internal int this[byte i] { get => 0; set {}} Diagnostic(ErrorCode.ERR_BadVisIndexerParam, "this").WithArguments("Extensions.extension(Extensions.C).this[byte]", "Extensions.C").WithLocation(15, 22) ); @@ -4538,7 +4563,7 @@ static void Main() _ = GetInt().P; } - static int GetInt() => 0; + static int GetInt() => 0; } static class Extensions @@ -4582,23 +4607,24 @@ static void Main() _ = GetInt().P; } - static int GetInt() => 0; + static int GetInt() => 0; } static class Extensions { extension(ref readonly int receiver) { - public void M1() {} - public int P => 0; + public void M1() { System.Console.Write("ranM1 "); } + public int P { get { System.Console.Write("ranP"); return 0; } } } public static void M2 (this ref readonly int receiver) { + System.Console.Write("ranM2 "); } } """; - var comp = CreateCompilation(src); + var comp = CreateCompilation(src, options: TestOptions.DebugExe); comp.VerifyEmitDiagnostics( // (5,9): warning CS9193: Argument 0 should be a variable because it is passed to a 'ref readonly' parameter @@ -4612,7 +4638,7 @@ public static void M2 (this ref readonly int receiver) Diagnostic(ErrorCode.WRN_RefReadonlyNotVariable, "GetInt()").WithArguments("0").WithLocation(7, 13) ); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : Test emit and execution for a scenario like this + CompileAndVerify(comp, expectedOutput: "ranM1 ranM2 ranP"); } [Fact] @@ -4628,25 +4654,25 @@ static void Main() _ = GetInt().P; } - static int GetInt() => 0; + static int GetInt() => 0; } static class Extensions { extension(in int receiver) { - public void M1() {} - public int P => 0; + public void M1() { System.Console.Write("ranM1 "); } + public int P { get { System.Console.Write("ranP"); return 0; } } } - public static void M2 (this in int receiver) + public static void M2(this in int receiver) { + System.Console.Write("ranM2 "); } } """; - var comp = CreateCompilation(src); - - comp.VerifyEmitDiagnostics(); // Tracked by https://github.com/dotnet/roslyn/issues/76130 : Test emit and execution for a scenario like this + var comp = CreateCompilation(src, options: TestOptions.DebugExe); + CompileAndVerify(comp, expectedOutput: "ranM1 ranM2 ranP").VerifyDiagnostics(); } [Fact] @@ -4680,10 +4706,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -4693,10 +4719,10 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method private hidebysig + .method private hidebysig instance void M ( string s - ) cil managed + ) cil managed { // Method begins at RVA 0x2079 // Code size 2 (0x2) @@ -4706,11 +4732,11 @@ .maxstack 8 } // end of method '<>E__0'::M } // end of class <>E__0 // Methods - .method private hidebysig static + .method private hidebysig static void M ( object o, string s - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 @@ -4799,10 +4825,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -4812,10 +4838,10 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method public hidebysig + .method public hidebysig instance string M ( string s - ) cil managed + ) cil managed { // Method begins at RVA 0x207d // Code size 2 (0x2) @@ -4825,11 +4851,11 @@ .maxstack 8 } // end of method '<>E__0'::M } // end of class <>E__0 // Methods - .method public hidebysig static + .method public hidebysig static string M ( object o, string s - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 @@ -5168,10 +5194,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -5181,10 +5207,10 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method public hidebysig + .method public hidebysig instance string M ( string s - ) cil managed + ) cil managed { // Method begins at RVA 0x20ad // Code size 2 (0x2) @@ -5204,11 +5230,11 @@ .field public object o .field public string s } // end of class <>c__DisplayClass1_0 // Methods - .method public hidebysig static + .method public hidebysig static string M ( object o, string s - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 @@ -5229,10 +5255,10 @@ [0] valuetype Extensions/'<>c__DisplayClass1_0' IL_0012: call string Extensions::'b__1_0'(valuetype Extensions/'<>c__DisplayClass1_0'&) IL_0017: ret } // end of method Extensions::M - .method assembly hidebysig static + .method assembly hidebysig static string 'b__1_0' ( valuetype Extensions/'<>c__DisplayClass1_0'& '' - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -5348,10 +5374,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -5361,10 +5387,10 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method public hidebysig + .method public hidebysig instance string M ( string s - ) cil managed + ) cil managed { // Method begins at RVA 0x208e // Code size 2 (0x2) @@ -5383,8 +5409,8 @@ 01 00 00 00 .field public object o .field public string s // Methods - .method public hidebysig specialname rtspecialname - instance void .ctor () cil managed + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed { // Method begins at RVA 0x2091 // Code size 7 (0x7) @@ -5393,8 +5419,8 @@ .maxstack 8 IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0006: ret } // end of method '<>c__DisplayClass1_0'::.ctor - .method assembly hidebysig - instance string 'b__0' () cil managed + .method assembly hidebysig + instance string 'b__0' () cil managed { // Method begins at RVA 0x2099 // Code size 30 (0x1e) @@ -5414,11 +5440,11 @@ .maxstack 8 } // end of method '<>c__DisplayClass1_0'::'b__0' } // end of class <>c__DisplayClass1_0 // Methods - .method public hidebysig static + .method public hidebysig static string M ( object o, string s - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 @@ -5536,10 +5562,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -5549,10 +5575,10 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method public hidebysig + .method public hidebysig instance class [mscorlib]System.Collections.Generic.IEnumerable`1 M ( string s - ) cil managed + ) cil managed { // Method begins at RVA 0x2080 // Code size 2 (0x2) @@ -5593,10 +5619,10 @@ .field public object '<>3__o' .field private string s .field public string '<>3__s' // Methods - .method public hidebysig specialname rtspecialname + .method public hidebysig specialname rtspecialname instance void .ctor ( int32 '<>1__state' - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -5614,8 +5640,8 @@ .maxstack 8 IL_0013: stfld int32 Extensions/'d__1'::'<>l__initialThreadId' IL_0018: ret } // end of method 'd__1'::.ctor - .method private final hidebysig newslot virtual - instance void System.IDisposable.Dispose () cil managed + .method private final hidebysig newslot virtual + instance void System.IDisposable.Dispose () cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -5629,8 +5655,8 @@ .maxstack 8 IL_0003: stfld int32 Extensions/'d__1'::'<>1__state' IL_0008: ret } // end of method 'd__1'::System.IDisposable.Dispose - .method private final hidebysig newslot virtual - instance bool MoveNext () cil managed + .method private final hidebysig newslot virtual + instance bool MoveNext () cil managed { .override method instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() // Method begins at RVA 0x20a8 @@ -5676,8 +5702,8 @@ [0] int32 IL_004a: ldc.i4.0 IL_004b: ret } // end of method 'd__1'::MoveNext - .method private final hidebysig specialname newslot virtual - instance string 'System.Collections.Generic.IEnumerator.get_Current' () cil managed + .method private final hidebysig specialname newslot virtual + instance string 'System.Collections.Generic.IEnumerator.get_Current' () cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -5690,8 +5716,8 @@ .maxstack 8 IL_0001: ldfld string Extensions/'d__1'::'<>2__current' IL_0006: ret } // end of method 'd__1'::'System.Collections.Generic.IEnumerator.get_Current' - .method private final hidebysig newslot virtual - instance void System.Collections.IEnumerator.Reset () cil managed + .method private final hidebysig newslot virtual + instance void System.Collections.IEnumerator.Reset () cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -5703,8 +5729,8 @@ .maxstack 8 IL_0000: newobj instance void [mscorlib]System.NotSupportedException::.ctor() IL_0005: throw } // end of method 'd__1'::System.Collections.IEnumerator.Reset - .method private final hidebysig specialname newslot virtual - instance object System.Collections.IEnumerator.get_Current () cil managed + .method private final hidebysig specialname newslot virtual + instance object System.Collections.IEnumerator.get_Current () cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -5717,8 +5743,8 @@ .maxstack 8 IL_0001: ldfld string Extensions/'d__1'::'<>2__current' IL_0006: ret } // end of method 'd__1'::System.Collections.IEnumerator.get_Current - .method private final hidebysig newslot virtual - instance class [mscorlib]System.Collections.Generic.IEnumerator`1 'System.Collections.Generic.IEnumerable.GetEnumerator' () cil managed + .method private final hidebysig newslot virtual + instance class [mscorlib]System.Collections.Generic.IEnumerator`1 'System.Collections.Generic.IEnumerable.GetEnumerator' () cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -5758,8 +5784,8 @@ [0] class Extensions/'d__1' IL_0041: ldloc.0 IL_0042: ret } // end of method 'd__1'::'System.Collections.Generic.IEnumerable.GetEnumerator' - .method private final hidebysig newslot virtual - instance class [mscorlib]System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () cil managed + .method private final hidebysig newslot virtual + instance class [mscorlib]System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -5783,11 +5809,11 @@ .property instance object System.Collections.IEnumerator.Current() } } // end of class d__1 // Methods - .method public hidebysig static + .method public hidebysig static class [mscorlib]System.Collections.Generic.IEnumerable`1 M ( object o, string s - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.IteratorStateMachineAttribute::.ctor(class [mscorlib]System.Type) = ( 01 00 12 45 78 74 65 6e 73 69 6f 6e 73 2b 3c 4d @@ -5937,10 +5963,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -5950,10 +5976,10 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method public hidebysig + .method public hidebysig instance class [mscorlib]System.Threading.Tasks.Task`1 M ( string s - ) cil managed + ) cil managed { // Method begins at RVA 0x20b5 // Code size 2 (0x2) @@ -5976,8 +6002,8 @@ .field public object o .field public string s .field private valuetype [mscorlib]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter '<>u__1' // Methods - .method private final hidebysig newslot virtual - instance void MoveNext () cil managed + .method private final hidebysig newslot virtual + instance void MoveNext () cil managed { .override method instance void [mscorlib]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext() // Method begins at RVA 0x20b8 @@ -6067,10 +6093,10 @@ [4] class [mscorlib]System.Exception IL_00ac: call instance void valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetResult(!0) IL_00b1: ret } // end of method 'd__1'::MoveNext - .method private final hidebysig newslot virtual + .method private final hidebysig newslot virtual instance void SetStateMachine ( class [mscorlib]System.Runtime.CompilerServices.IAsyncStateMachine stateMachine - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -6087,11 +6113,11 @@ .maxstack 8 } // end of method 'd__1'::SetStateMachine } // end of class d__1 // Methods - .method public hidebysig static + .method public hidebysig static class [mscorlib]System.Threading.Tasks.Task`1 M ( object o, string s - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.AsyncStateMachineAttribute::.ctor(class [mscorlib]System.Type) = ( 01 00 12 45 78 74 65 6e 73 69 6f 6e 73 2b 3c 4d @@ -6237,10 +6263,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0`1' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( class C`1 o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -6250,11 +6276,11 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0`1'::'$' - .method public hidebysig + .method public hidebysig instance string M ( !T t, !!U u - ) cil managed + ) cil managed { // Method begins at RVA 0x20a7 // Code size 2 (0x2) @@ -6264,12 +6290,12 @@ .maxstack 8 } // end of method '<>E__0`1'::M } // end of class <>E__0`1 // Methods - .method public hidebysig static + .method public hidebysig static string M ( class C`1 o, !!T t, !!U u - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 @@ -6478,10 +6504,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0`1' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( class C`1 o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -6491,11 +6517,11 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0`1'::'$' - .method public hidebysig + .method public hidebysig instance class C`1 M ( !T t1, !!U u1 - ) cil managed + ) cil managed { // Method begins at RVA 0x216f // Code size 2 (0x2) @@ -6516,12 +6542,12 @@ .field public !U u1 .field public !T t1 } // end of class <>c__DisplayClass1_0`2 // Methods - .method public hidebysig static + .method public hidebysig static class C`1 M ( class C`1 o, !!T t1, !!U u1 - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 @@ -6554,7 +6580,7 @@ .locals init ( IL_0033: call class C`1 Extensions::'b__1_0'(!!0, !!1, !!2, !!3, !!4, valuetype Extensions/'<>c__DisplayClass1_0`2'&) IL_0038: ret } // end of method Extensions::M - .method assembly hidebysig static + .method assembly hidebysig static class C`1 'b__1_0' ( !!T t2, !!U u2, @@ -6562,7 +6588,7 @@ class C`1 'b__1_0' ( !!Y y2, !!Z z2, valuetype Extensions/'<>c__DisplayClass1_0`2'& '' - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -6753,10 +6779,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0`1' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( class C`1 o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -6766,11 +6792,11 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0`1'::'$' - .method public hidebysig + .method public hidebysig instance class C`1 M ( !T t1, !!U u1 - ) cil managed + ) cil managed { // Method begins at RVA 0x20c6 // Code size 2 (0x2) @@ -6790,8 +6816,8 @@ .field public class C`1 o .field public !U u1 .field public !T t1 // Methods - .method public hidebysig specialname rtspecialname - instance void .ctor () cil managed + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed { // Method begins at RVA 0x20c9 // Code size 7 (0x7) @@ -6800,11 +6826,11 @@ .maxstack 8 IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0006: ret } // end of method '<>c__DisplayClass1_0`2'::.ctor - .method assembly hidebysig + .method assembly hidebysig instance class C`1 'b__0' ( !T t2, !U u2 - ) cil managed + ) cil managed { // Method begins at RVA 0x20d4 // Code size 103 (0x67) @@ -6849,12 +6875,12 @@ .maxstack 4 } // end of method '<>c__DisplayClass1_0`2'::'b__0' } // end of class <>c__DisplayClass1_0`2 // Methods - .method public hidebysig static + .method public hidebysig static class C`1 M ( class C`1 o, !!T t1, !!U u1 - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 @@ -7012,10 +7038,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0`1' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( class C`1 o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -7025,11 +7051,11 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0`1'::'$' - .method public hidebysig + .method public hidebysig instance class [mscorlib]System.Collections.Generic.IEnumerable`1 M ( !T t1, !!U u1 - ) cil managed + ) cil managed { // Method begins at RVA 0x209e // Code size 2 (0x2) @@ -7072,10 +7098,10 @@ .field public !U '<>3__u1' .field private !T t1 .field public !T '<>3__t1' // Methods - .method public hidebysig specialname rtspecialname + .method public hidebysig specialname rtspecialname instance void .ctor ( int32 '<>1__state' - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -7093,8 +7119,8 @@ .maxstack 8 IL_0013: stfld int32 class Extensions/'d__1`2'::'<>l__initialThreadId' IL_0018: ret } // end of method 'd__1`2'::.ctor - .method private final hidebysig newslot virtual - instance void System.IDisposable.Dispose () cil managed + .method private final hidebysig newslot virtual + instance void System.IDisposable.Dispose () cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -7108,8 +7134,8 @@ .maxstack 8 IL_0003: stfld int32 class Extensions/'d__1`2'::'<>1__state' IL_0008: ret } // end of method 'd__1`2'::System.IDisposable.Dispose - .method private final hidebysig newslot virtual - instance bool MoveNext () cil managed + .method private final hidebysig newslot virtual + instance bool MoveNext () cil managed { .override method instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() // Method begins at RVA 0x20c8 @@ -7156,8 +7182,8 @@ [0] int32 IL_005f: ldc.i4.0 IL_0060: ret } // end of method 'd__1`2'::MoveNext - .method private final hidebysig specialname newslot virtual - instance string 'System.Collections.Generic.IEnumerator.get_Current' () cil managed + .method private final hidebysig specialname newslot virtual + instance string 'System.Collections.Generic.IEnumerator.get_Current' () cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -7170,8 +7196,8 @@ .maxstack 8 IL_0001: ldfld string class Extensions/'d__1`2'::'<>2__current' IL_0006: ret } // end of method 'd__1`2'::'System.Collections.Generic.IEnumerator.get_Current' - .method private final hidebysig newslot virtual - instance void System.Collections.IEnumerator.Reset () cil managed + .method private final hidebysig newslot virtual + instance void System.Collections.IEnumerator.Reset () cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -7183,8 +7209,8 @@ .maxstack 8 IL_0000: newobj instance void [mscorlib]System.NotSupportedException::.ctor() IL_0005: throw } // end of method 'd__1`2'::System.Collections.IEnumerator.Reset - .method private final hidebysig specialname newslot virtual - instance object System.Collections.IEnumerator.get_Current () cil managed + .method private final hidebysig specialname newslot virtual + instance object System.Collections.IEnumerator.get_Current () cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -7197,8 +7223,8 @@ .maxstack 8 IL_0001: ldfld string class Extensions/'d__1`2'::'<>2__current' IL_0006: ret } // end of method 'd__1`2'::System.Collections.IEnumerator.get_Current - .method private final hidebysig newslot virtual - instance class [mscorlib]System.Collections.Generic.IEnumerator`1 'System.Collections.Generic.IEnumerable.GetEnumerator' () cil managed + .method private final hidebysig newslot virtual + instance class [mscorlib]System.Collections.Generic.IEnumerator`1 'System.Collections.Generic.IEnumerable.GetEnumerator' () cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -7242,8 +7268,8 @@ .locals init ( IL_004d: ldloc.0 IL_004e: ret } // end of method 'd__1`2'::'System.Collections.Generic.IEnumerable.GetEnumerator' - .method private final hidebysig newslot virtual - instance class [mscorlib]System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () cil managed + .method private final hidebysig newslot virtual + instance class [mscorlib]System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -7267,12 +7293,12 @@ .property instance object System.Collections.IEnumerator.Current() } } // end of class d__1`2 // Methods - .method public hidebysig static + .method public hidebysig static class [mscorlib]System.Collections.Generic.IEnumerable`1 M ( class C`1 o, !!T t1, !!U u1 - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.IteratorStateMachineAttribute::.ctor(class [mscorlib]System.Type) = ( 01 00 14 45 78 74 65 6e 73 69 6f 6e 73 2b 3c 4d @@ -7401,10 +7427,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0`1' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( class C`1 o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -7414,11 +7440,11 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0`1'::'$' - .method public hidebysig + .method public hidebysig instance class [mscorlib]System.Threading.Tasks.Task`1 M ( !T t1, !!U u1 - ) cil managed + ) cil managed { // Method begins at RVA 0x20d4 // Code size 2 (0x2) @@ -7442,8 +7468,8 @@ .field public !U u1 .field public !T t1 .field private valuetype [mscorlib]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter '<>u__1' // Methods - .method private final hidebysig newslot virtual - instance void MoveNext () cil managed + .method private final hidebysig newslot virtual + instance void MoveNext () cil managed { .override method instance void [mscorlib]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext() // Method begins at RVA 0x20d8 @@ -7534,10 +7560,10 @@ [4] class [mscorlib]System.Exception IL_00c4: call instance void valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetResult(!0) IL_00c9: ret } // end of method 'd__1`2'::MoveNext - .method private final hidebysig newslot virtual + .method private final hidebysig newslot virtual instance void SetStateMachine ( class [mscorlib]System.Runtime.CompilerServices.IAsyncStateMachine stateMachine - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -7554,12 +7580,12 @@ .maxstack 8 } // end of method 'd__1`2'::SetStateMachine } // end of class d__1`2 // Methods - .method public hidebysig static + .method public hidebysig static class [mscorlib]System.Threading.Tasks.Task`1 M ( class C`1 o, !!T t1, !!U u1 - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.AsyncStateMachineAttribute::.ctor(class [mscorlib]System.Type) = ( 01 00 14 45 78 74 65 6e 73 69 6f 6e 73 2b 3c 4d @@ -7718,10 +7744,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object _ - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -7731,11 +7757,11 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method public hidebysig static + .method public hidebysig static string M ( object o, string s - ) cil managed + ) cil managed { // Method begins at RVA 0x207d // Code size 2 (0x2) @@ -7745,11 +7771,11 @@ .maxstack 8 } // end of method '<>E__0'::M } // end of class <>E__0 // Methods - .method public hidebysig static + .method public hidebysig static string M ( object o, string s - ) cil managed + ) cil managed { // Method begins at RVA 0x2067 // Code size 19 (0x13) @@ -8199,10 +8225,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object _ - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -8212,11 +8238,11 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method public hidebysig static + .method public hidebysig static string M ( object o, string s - ) cil managed + ) cil managed { // Method begins at RVA 0x20ad // Code size 2 (0x2) @@ -8236,11 +8262,11 @@ .field public object o .field public string s } // end of class <>c__DisplayClass1_0 // Methods - .method public hidebysig static + .method public hidebysig static string M ( object o, string s - ) cil managed + ) cil managed { // Method begins at RVA 0x2068 // Code size 24 (0x18) @@ -8258,10 +8284,10 @@ [0] valuetype Extensions/'<>c__DisplayClass1_0' IL_0012: call string Extensions::'b__1_0'(valuetype Extensions/'<>c__DisplayClass1_0'&) IL_0017: ret } // end of method Extensions::M - .method assembly hidebysig static + .method assembly hidebysig static string 'b__1_0' ( valuetype Extensions/'<>c__DisplayClass1_0'& '' - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -8377,10 +8403,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object _ - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -8390,11 +8416,11 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method public hidebysig static + .method public hidebysig static string M ( object o, string s - ) cil managed + ) cil managed { // Method begins at RVA 0x208e // Code size 2 (0x2) @@ -8413,8 +8439,8 @@ 01 00 00 00 .field public object o .field public string s // Methods - .method public hidebysig specialname rtspecialname - instance void .ctor () cil managed + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed { // Method begins at RVA 0x2091 // Code size 7 (0x7) @@ -8423,8 +8449,8 @@ .maxstack 8 IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0006: ret } // end of method '<>c__DisplayClass1_0'::.ctor - .method assembly hidebysig - instance string 'b__0' () cil managed + .method assembly hidebysig + instance string 'b__0' () cil managed { // Method begins at RVA 0x2099 // Code size 30 (0x1e) @@ -8444,11 +8470,11 @@ .maxstack 8 } // end of method '<>c__DisplayClass1_0'::'b__0' } // end of class <>c__DisplayClass1_0 // Methods - .method public hidebysig static + .method public hidebysig static string M ( object o, string s - ) cil managed + ) cil managed { // Method begins at RVA 0x2067 // Code size 36 (0x24) @@ -8563,10 +8589,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object _ - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -8576,11 +8602,11 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method public hidebysig static + .method public hidebysig static class [mscorlib]System.Collections.Generic.IEnumerable`1 M ( object o, string s - ) cil managed + ) cil managed { // Method begins at RVA 0x2080 // Code size 2 (0x2) @@ -8621,10 +8647,10 @@ .field public object '<>3__o' .field private string s .field public string '<>3__s' // Methods - .method public hidebysig specialname rtspecialname + .method public hidebysig specialname rtspecialname instance void .ctor ( int32 '<>1__state' - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -8642,8 +8668,8 @@ .maxstack 8 IL_0013: stfld int32 Extensions/'d__1'::'<>l__initialThreadId' IL_0018: ret } // end of method 'd__1'::.ctor - .method private final hidebysig newslot virtual - instance void System.IDisposable.Dispose () cil managed + .method private final hidebysig newslot virtual + instance void System.IDisposable.Dispose () cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -8657,8 +8683,8 @@ .maxstack 8 IL_0003: stfld int32 Extensions/'d__1'::'<>1__state' IL_0008: ret } // end of method 'd__1'::System.IDisposable.Dispose - .method private final hidebysig newslot virtual - instance bool MoveNext () cil managed + .method private final hidebysig newslot virtual + instance bool MoveNext () cil managed { .override method instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() // Method begins at RVA 0x20a8 @@ -8704,8 +8730,8 @@ [0] int32 IL_004a: ldc.i4.0 IL_004b: ret } // end of method 'd__1'::MoveNext - .method private final hidebysig specialname newslot virtual - instance string 'System.Collections.Generic.IEnumerator.get_Current' () cil managed + .method private final hidebysig specialname newslot virtual + instance string 'System.Collections.Generic.IEnumerator.get_Current' () cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -8718,8 +8744,8 @@ .maxstack 8 IL_0001: ldfld string Extensions/'d__1'::'<>2__current' IL_0006: ret } // end of method 'd__1'::'System.Collections.Generic.IEnumerator.get_Current' - .method private final hidebysig newslot virtual - instance void System.Collections.IEnumerator.Reset () cil managed + .method private final hidebysig newslot virtual + instance void System.Collections.IEnumerator.Reset () cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -8731,8 +8757,8 @@ .maxstack 8 IL_0000: newobj instance void [mscorlib]System.NotSupportedException::.ctor() IL_0005: throw } // end of method 'd__1'::System.Collections.IEnumerator.Reset - .method private final hidebysig specialname newslot virtual - instance object System.Collections.IEnumerator.get_Current () cil managed + .method private final hidebysig specialname newslot virtual + instance object System.Collections.IEnumerator.get_Current () cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -8745,8 +8771,8 @@ .maxstack 8 IL_0001: ldfld string Extensions/'d__1'::'<>2__current' IL_0006: ret } // end of method 'd__1'::System.Collections.IEnumerator.get_Current - .method private final hidebysig newslot virtual - instance class [mscorlib]System.Collections.Generic.IEnumerator`1 'System.Collections.Generic.IEnumerable.GetEnumerator' () cil managed + .method private final hidebysig newslot virtual + instance class [mscorlib]System.Collections.Generic.IEnumerator`1 'System.Collections.Generic.IEnumerable.GetEnumerator' () cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -8786,8 +8812,8 @@ [0] class Extensions/'d__1' IL_0041: ldloc.0 IL_0042: ret } // end of method 'd__1'::'System.Collections.Generic.IEnumerable.GetEnumerator' - .method private final hidebysig newslot virtual - instance class [mscorlib]System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () cil managed + .method private final hidebysig newslot virtual + instance class [mscorlib]System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -8811,11 +8837,11 @@ .property instance object System.Collections.IEnumerator.Current() } } // end of class d__1 // Methods - .method public hidebysig static + .method public hidebysig static class [mscorlib]System.Collections.Generic.IEnumerable`1 M ( object o, string s - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.IteratorStateMachineAttribute::.ctor(class [mscorlib]System.Type) = ( 01 00 12 45 78 74 65 6e 73 69 6f 6e 73 2b 3c 4d @@ -8928,10 +8954,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object _ - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -8941,11 +8967,11 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method public hidebysig static + .method public hidebysig static class [mscorlib]System.Threading.Tasks.Task`1 M ( object o, string s - ) cil managed + ) cil managed { // Method begins at RVA 0x20b5 // Code size 2 (0x2) @@ -8968,8 +8994,8 @@ .field public object o .field public string s .field private valuetype [mscorlib]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter '<>u__1' // Methods - .method private final hidebysig newslot virtual - instance void MoveNext () cil managed + .method private final hidebysig newslot virtual + instance void MoveNext () cil managed { .override method instance void [mscorlib]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext() // Method begins at RVA 0x20b8 @@ -9059,10 +9085,10 @@ [4] class [mscorlib]System.Exception IL_00ac: call instance void valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetResult(!0) IL_00b1: ret } // end of method 'd__1'::MoveNext - .method private final hidebysig newslot virtual + .method private final hidebysig newslot virtual instance void SetStateMachine ( class [mscorlib]System.Runtime.CompilerServices.IAsyncStateMachine stateMachine - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 @@ -9079,11 +9105,11 @@ .maxstack 8 } // end of method 'd__1'::SetStateMachine } // end of class d__1 // Methods - .method public hidebysig static + .method public hidebysig static class [mscorlib]System.Threading.Tasks.Task`1 M ( object o, string s - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.AsyncStateMachineAttribute::.ctor(class [mscorlib]System.Type) = ( 01 00 12 45 78 74 65 6e 73 69 6f 6e 73 2b 3c 4d @@ -9218,10 +9244,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -9231,8 +9257,8 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method public hidebysig specialname - instance string get_P () cil managed + .method public hidebysig specialname + instance string get_P () cil managed { // Method begins at RVA 0x2071 // Code size 2 (0x2) @@ -9247,10 +9273,10 @@ .property instance string P() } } // end of class <>E__0 // Methods - .method public hidebysig static + .method public hidebysig static string get_P ( object o - ) cil managed + ) cil managed { // Method begins at RVA 0x2067 // Code size 7 (0x7) @@ -9507,10 +9533,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object '' - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -9520,8 +9546,8 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method public hidebysig specialname static - string get_P () cil managed + .method public hidebysig specialname static + string get_P () cil managed { // Method begins at RVA 0x2070 // Code size 2 (0x2) @@ -9536,8 +9562,8 @@ .property string P() } } // end of class <>E__0 // Methods - .method public hidebysig static - string get_P () cil managed + .method public hidebysig static + string get_P () cil managed { // Method begins at RVA 0x2067 // Code size 6 (0x6) @@ -9718,10 +9744,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -9731,8 +9757,8 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method public hidebysig specialname - instance string get_P () cil managed + .method public hidebysig specialname + instance string get_P () cil managed { // Method begins at RVA 0x2071 // Code size 2 (0x2) @@ -9747,10 +9773,10 @@ .property instance string P() } } // end of class <>E__0 // Methods - .method public hidebysig static + .method public hidebysig static string get_P ( object o - ) cil managed + ) cil managed { // Method begins at RVA 0x2067 // Code size 7 (0x7) @@ -9829,13 +9855,16 @@ .maxstack 1 public void Implementation_DelegateCaching_01() { var src = """ +42.M2(); + public static class Extensions { extension(T o) { - void M2() + public void M2() { - #pragma warning disable CS8321 // The local function 'local' is declared but never used + local()(); + System.Func local() { return C1.M1; @@ -9846,11 +9875,11 @@ System.Func local() class C1 { - static public V M1() => default; + static public V M1() { System.Console.Write((typeof(T), typeof(U), typeof(V))); return default; } } """; var comp = CreateCompilation(src); - var verifier = CompileAndVerify(comp).VerifyDiagnostics(); // Tracked by https://github.com/dotnet/roslyn/issues/76130 : Consider executing and verifying behavior + var verifier = CompileAndVerify(comp, expectedOutput: "(System.Int32, System.String, System.Int64)").VerifyDiagnostics(); verifier.VerifyTypeIL("Extensions", """ .class public auto ansi abstract sealed beforefieldinit Extensions @@ -9864,23 +9893,23 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0`1' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( !T o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - // Method begins at RVA 0x2067 + // Method begins at RVA 0x20e7 // Code size 1 (0x1) .maxstack 8 IL_0000: ret } // end of method '<>E__0`1'::'$' - .method private hidebysig - instance void M2 () cil managed + .method public hidebysig + instance void M2 () cil managed { - // Method begins at RVA 0x20a6 + // Method begins at RVA 0x20e9 // Code size 2 (0x2) .maxstack 8 IL_0000: ldnull @@ -9897,26 +9926,29 @@ 01 00 00 00 .field public static class [mscorlib]System.Func`1 '<0>__M1' } // end of class O__1_0`3 // Methods - .method private hidebysig static + .method public hidebysig static void M2 ( !!T o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) - // Method begins at RVA 0x2067 - // Code size 1 (0x1) + // Method begins at RVA 0x2078 + // Code size 12 (0xc) .maxstack 8 - IL_0000: ret + IL_0000: call class [mscorlib]System.Func`1 Extensions::'b__1_0'() + IL_0005: callvirt instance !0 class [mscorlib]System.Func`1::Invoke() + IL_000a: pop + IL_000b: ret } // end of method Extensions::M2 - .method assembly hidebysig static - class [mscorlib]System.Func`1 'b__1_0' () cil managed + .method assembly hidebysig static + class [mscorlib]System.Func`1 'b__1_0' () cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - // Method begins at RVA 0x2069 + // Method begins at RVA 0x2085 // Code size 28 (0x1c) .maxstack 8 IL_0000: ldsfld class [mscorlib]System.Func`1 class Extensions/'O__1_0`3'::'<0>__M1' @@ -9973,13 +10005,17 @@ class C1 public void Implementation_DelegateCaching_02() { var src = """ + +42.M2(); + public static class Extensions { extension(T o) { - void M2() + public void M2() { - #pragma warning disable CS8321 // The local function 'local' is declared but never used + local()(); + System.Action local() { return C1.M1; @@ -9990,11 +10026,11 @@ System.Action local() class C1 { - static public void M1() {} + static public void M1() { System.Console.Write(typeof(T)); } } """; var comp = CreateCompilation(src); - var verifier = CompileAndVerify(comp).VerifyDiagnostics(); // Tracked by https://github.com/dotnet/roslyn/issues/76130 : Consider executing and verifying behavior + var verifier = CompileAndVerify(comp, expectedOutput: "System.Int32").VerifyDiagnostics(); verifier.VerifyTypeIL("Extensions", """ .class public auto ansi abstract sealed beforefieldinit Extensions @@ -10008,23 +10044,23 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0`1' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( !T o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - // Method begins at RVA 0x2067 + // Method begins at RVA 0x20b2 // Code size 1 (0x1) .maxstack 8 IL_0000: ret } // end of method '<>E__0`1'::'$' - .method private hidebysig - instance void M2 () cil managed + .method public hidebysig + instance void M2 () cil managed { - // Method begins at RVA 0x208e + // Method begins at RVA 0x20b4 // Code size 2 (0x2) .maxstack 8 IL_0000: ldnull @@ -10041,26 +10077,28 @@ 01 00 00 00 .field public static class [mscorlib]System.Action '<0>__M1' } // end of class <>O__1_0`1 // Methods - .method private hidebysig static + .method public hidebysig static void M2 ( !!T o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) - // Method begins at RVA 0x2067 - // Code size 1 (0x1) + // Method begins at RVA 0x2078 + // Code size 11 (0xb) .maxstack 8 - IL_0000: ret + IL_0000: call class [mscorlib]System.Action Extensions::'b__1_0'() + IL_0005: callvirt instance void [mscorlib]System.Action::Invoke() + IL_000a: ret } // end of method Extensions::M2 - .method assembly hidebysig static - class [mscorlib]System.Action 'b__1_0' () cil managed + .method assembly hidebysig static + class [mscorlib]System.Action 'b__1_0' () cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - // Method begins at RVA 0x2069 + // Method begins at RVA 0x2084 // Code size 28 (0x1c) .maxstack 8 IL_0000: ldsfld class [mscorlib]System.Action class Extensions/'<>O__1_0`1'::'<0>__M1' @@ -10139,7 +10177,7 @@ static public void M1() {} } """; var comp = CreateCompilation(src); - var verifier = CompileAndVerify(comp).VerifyDiagnostics(); // Tracked by https://github.com/dotnet/roslyn/issues/76130 : Consider executing and verifying behavior + var verifier = CompileAndVerify(comp).VerifyDiagnostics(); verifier.VerifyTypeIL("Extensions", """ .class public auto ansi abstract sealed beforefieldinit Extensions @@ -10153,10 +10191,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -10166,8 +10204,8 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method private hidebysig - instance void M2 () cil managed + .method private hidebysig + instance void M2 () cil managed { // Method begins at RVA 0x208e // Code size 2 (0x2) @@ -10186,10 +10224,10 @@ 01 00 00 00 .field public static class [mscorlib]System.Action '<0>__M1' } // end of class <>O // Methods - .method private hidebysig static + .method private hidebysig static void M2 ( object o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 @@ -10199,8 +10237,8 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method Extensions::M2 - .method assembly hidebysig static - class [mscorlib]System.Action 'b__1_0' () cil managed + .method assembly hidebysig static + class [mscorlib]System.Action 'b__1_0' () cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -10279,7 +10317,7 @@ static void local() } """; var comp = CreateCompilation(src); - var verifier = CompileAndVerify(comp).VerifyDiagnostics(); // Tracked by https://github.com/dotnet/roslyn/issues/76130 : Consider executing and verifying behavior + var verifier = CompileAndVerify(comp).VerifyDiagnostics(); verifier.VerifyTypeIL("Extensions", """ .class public auto ansi abstract sealed beforefieldinit Extensions @@ -10293,10 +10331,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0`1' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( !T o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -10306,8 +10344,8 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0`1'::'$' - .method private hidebysig - instance class [mscorlib]System.Action M2 () cil managed + .method private hidebysig + instance class [mscorlib]System.Action M2 () cil managed { // Method begins at RVA 0x2098 // Code size 2 (0x2) @@ -10326,10 +10364,10 @@ 01 00 00 00 .field public static class [mscorlib]System.Action '<0>__local' } // end of class <>O__1_0`1 // Methods - .method private hidebysig static + .method private hidebysig static class [mscorlib]System.Action M2 ( !!T o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 @@ -10348,8 +10386,8 @@ .maxstack 8 IL_0016: stsfld class [mscorlib]System.Action class Extensions/'<>O__1_0`1'::'<0>__local' IL_001b: ret } // end of method Extensions::M2 - .method assembly hidebysig static - void 'b__1_0' () cil managed + .method assembly hidebysig static + void 'b__1_0' () cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -10421,7 +10459,7 @@ static void local() } """; var comp = CreateCompilation(src); - var verifier = CompileAndVerify(comp).VerifyDiagnostics(); // Tracked by https://github.com/dotnet/roslyn/issues/76130 : Consider executing and verifying behavior + var verifier = CompileAndVerify(comp).VerifyDiagnostics(); verifier.VerifyTypeIL("Extensions", """ .class public auto ansi abstract sealed beforefieldinit Extensions @@ -10435,10 +10473,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -10448,8 +10486,8 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method private hidebysig - instance class [mscorlib]System.Action M2 () cil managed + .method private hidebysig + instance class [mscorlib]System.Action M2 () cil managed { // Method begins at RVA 0x2098 // Code size 2 (0x2) @@ -10468,10 +10506,10 @@ 01 00 00 00 .field public static class [mscorlib]System.Action '<0>__local' } // end of class <>O // Methods - .method private hidebysig static + .method private hidebysig static class [mscorlib]System.Action M2 ( object o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 @@ -10490,8 +10528,8 @@ .maxstack 8 IL_0016: stsfld class [mscorlib]System.Action Extensions/'<>O'::'<0>__local' IL_001b: ret } // end of method Extensions::M2 - .method assembly hidebysig static - void 'b__1_0' () cil managed + .method assembly hidebysig static + void 'b__1_0' () cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -10546,13 +10584,21 @@ static void local() public void Implementation_DynamicCallSite_01() { var src = """ +42.M2(); + +class D +{ + public void M1(T t, U u, V v) { System.Console.Write((typeof(T), typeof(U), typeof(V))); } +} + public static class Extensions { extension(T o) { - void M2() + public void M2() { - #pragma warning disable CS8321 // The local function 'local' is declared but never used + local(new D(), default(T), default(U), 42L); + void local(dynamic d, T t, U u, V v) { d.M1(t, u, v); @@ -10562,7 +10608,7 @@ void local(dynamic d, T t, U u, V v) } """; var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp); - var verifier = CompileAndVerify(comp).VerifyDiagnostics(); // Tracked by https://github.com/dotnet/roslyn/issues/76130 : Consider executing and verifying behavior + var verifier = CompileAndVerify(comp, expectedOutput: "(System.Int32, System.String, System.Int64)").VerifyDiagnostics(); verifier.VerifyTypeIL("Extensions", """ .class public auto ansi abstract sealed beforefieldinit Extensions @@ -10576,23 +10622,23 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0`1' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( !T o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - // Method begins at RVA 0x2067 + // Method begins at RVA 0x2152 // Code size 1 (0x1) .maxstack 8 IL_0000: ret } // end of method '<>E__0`1'::'$' - .method private hidebysig - instance void M2 () cil managed + .method public hidebysig + instance void M2 () cil managed { - // Method begins at RVA 0x20ea + // Method begins at RVA 0x2154 // Code size 2 (0x2) .maxstack 8 IL_0000: ldnull @@ -10609,26 +10655,40 @@ 01 00 00 00 .field public static class [System.Core]System.Runtime.CompilerServices.CallSite`1> '<>p__0' } // end of class <>o__0|1`3 // Methods - .method private hidebysig static + .method public hidebysig static void M2 ( !!T o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) - // Method begins at RVA 0x2067 - // Code size 1 (0x1) - .maxstack 8 - IL_0000: ret + // Method begins at RVA 0x20a8 + // Code size 32 (0x20) + .maxstack 4 + .locals init ( + [0] !!T, + [1] !!U + ) + IL_0000: newobj instance void D::.ctor() + IL_0005: ldloca.s 0 + IL_0007: initobj !!T + IL_000d: ldloc.0 + IL_000e: ldloca.s 1 + IL_0010: initobj !!U + IL_0016: ldloc.1 + IL_0017: ldc.i4.s 42 + IL_0019: conv.i8 + IL_001a: call void Extensions::'b__1_0'(object, !!0, !!1, !!2) + IL_001f: ret } // end of method Extensions::M2 - .method assembly hidebysig static + .method assembly hidebysig static void 'b__1_0' ( object d, !!T t, !!U u, !!V v - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -10637,7 +10697,7 @@ .param [1] .custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = ( 01 00 00 00 ) - // Method begins at RVA 0x206c + // Method begins at RVA 0x20d4 // Code size 114 (0x72) .maxstack 9 IL_0000: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1> class Extensions/'<>o__0|1`3'::'<>p__0' @@ -10741,7 +10801,7 @@ void local(dynamic d, T t) } """; var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp); - var verifier = CompileAndVerify(comp).VerifyDiagnostics(); // Tracked by https://github.com/dotnet/roslyn/issues/76130 : Consider executing and verifying behavior + var verifier = CompileAndVerify(comp).VerifyDiagnostics(); verifier.VerifyTypeIL("Extensions", """ .class public auto ansi abstract sealed beforefieldinit Extensions @@ -10755,10 +10815,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0`1' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( !T o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -10768,8 +10828,8 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0`1'::'$' - .method private hidebysig - instance void M2 () cil managed + .method private hidebysig + instance void M2 () cil managed { // Method begins at RVA 0x20d4 // Code size 2 (0x2) @@ -10788,10 +10848,10 @@ 01 00 00 00 .field public static class [System.Core]System.Runtime.CompilerServices.CallSite`1> '<>p__0' } // end of class <>o__1`1 // Methods - .method private hidebysig static + .method private hidebysig static void M2 ( !!T o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 @@ -10801,11 +10861,11 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method Extensions::M2 - .method assembly hidebysig static + .method assembly hidebysig static void 'b__1_0' ( object d, !!T t - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -10904,7 +10964,7 @@ void local(dynamic d) } """; var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp); - var verifier = CompileAndVerify(comp).VerifyDiagnostics(); // Tracked by https://github.com/dotnet/roslyn/issues/76130 : Consider executing and verifying behavior + var verifier = CompileAndVerify(comp).VerifyDiagnostics(); verifier.VerifyTypeIL("Extensions", """ .class public auto ansi abstract sealed beforefieldinit Extensions @@ -10918,10 +10978,10 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method private hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -10931,8 +10991,8 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method '<>E__0'::'$' - .method private hidebysig - instance void M2 () cil managed + .method private hidebysig + instance void M2 () cil managed { // Method begins at RVA 0x20c9 // Code size 2 (0x2) @@ -10951,10 +11011,10 @@ 01 00 00 00 .field public static class [System.Core]System.Runtime.CompilerServices.CallSite`1> '<>p__0' } // end of class <>o__1 // Methods - .method private hidebysig static + .method private hidebysig static void M2 ( object o - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 @@ -10964,10 +11024,10 @@ 01 00 00 00 .maxstack 8 IL_0000: ret } // end of method Extensions::M2 - .method assembly hidebysig static + .method assembly hidebysig static void 'b__1_0' ( object d - ) cil managed + ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 @@ -11299,7 +11359,7 @@ static class Extensions extension(C) { } } -class C1 +class C1 { void M(UseSiteError x) { } void M(C x) { } @@ -11439,7 +11499,7 @@ static class E { extension(object o) { - public void Method() => throw null; + public void Method() { System.Console.Write("ran"); } } } } @@ -11489,9 +11549,7 @@ namespace N4 void verify(string src, string extensionName) { var comp = CreateCompilation(src, options: TestOptions.DebugExe); - comp.VerifyEmitDiagnostics(); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : metadata is undone - //CompileAndVerify(comp, expectedOutput: "").VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "ran").VerifyDiagnostics(); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); @@ -11531,10 +11589,7 @@ public static class E """; var comp = CreateCompilation([src, eSrc], options: TestOptions.DebugExe); - comp.VerifyEmitDiagnostics(); - - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : metadata is undone - //CompileAndVerify(comp, expectedOutput: "method"); + CompileAndVerify(comp, expectedOutput: "method").VerifyDiagnostics(); var tree = comp.SyntaxTrees.First(); var model = comp.GetSemanticModel(tree); @@ -11640,9 +11695,7 @@ static class E2 } """; var comp = CreateCompilation(src); - comp.VerifyEmitDiagnostics(); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : metadata is undone - //CompileAndVerify(comp, expectedOutput: "E1.Method(42) E2.Method(hello)").VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "E1.Method(42) E2.Method(hello)").VerifyDiagnostics(); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); @@ -11698,9 +11751,7 @@ public static void Main() } """; var comp = CreateCompilation(src, options: TestOptions.DebugExe); - comp.VerifyEmitDiagnostics(); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : metadata is undone - //CompileAndVerify(comp, expectedOutput: "E1.Method(42) E2.Method(hello)").VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "E1.Method(42) E2.Method(hello)").VerifyDiagnostics(); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); @@ -11750,9 +11801,7 @@ static class E2 } """; var comp = CreateCompilation(src); - comp.VerifyEmitDiagnostics(); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : metadata is undone - //CompileAndVerify(comp, expectedOutput: "E1.Method E2.Method E1.Method").VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "E1.Method E2.Method E1.Method").VerifyDiagnostics(); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); @@ -11939,12 +11988,14 @@ static class E [Fact] public void InstanceMethodInvocation_MatchingExtendedType_TypeParameterWithBaseClass() { - var src = $$""" + var src = """ +D.M(new D()); + class C { } -class D +class D : C { - void M(T t) where T : C + public static void M(T t) where T : C { t.M2(); } @@ -11954,13 +12005,12 @@ static class E { extension(C c) { - public void M2() { } + public void M2() { System.Console.Write(typeof(C)); } } } """; var comp = CreateCompilation(src); - comp.VerifyEmitDiagnostics(); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : metadata is undone + CompileAndVerify(comp, expectedOutput: "C`1[D]").VerifyDiagnostics(); var tree = comp.SyntaxTrees.First(); var model = comp.GetSemanticModel(tree); @@ -12737,17 +12787,18 @@ static class E } [Fact] - public void InstanceMethodInvocation_PatternBased_ForEach_NoMethod() + public void InstanceMethodInvocation_PatternBased_ForEach_MoveNext() { var src = """ foreach (var x in new C()) { - System.Console.Write(x); - break; } class C { } -class D { } +class D +{ + public int Current => 42; +} static class E { @@ -12759,6 +12810,50 @@ static class E extension(D d) { public bool MoveNext() => true; + } +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (1,19): error CS0117: 'D' does not contain a definition for 'MoveNext' + // foreach (var x in new C()) + Diagnostic(ErrorCode.ERR_NoSuchMember, "new C()").WithArguments("D", "MoveNext").WithLocation(1, 19), + // (1,19): error CS0202: foreach requires that the return type 'D' of 'E.extension(C).GetEnumerator()' must have a suitable public 'MoveNext' method and public 'Current' property + // foreach (var x in new C()) + Diagnostic(ErrorCode.ERR_BadGetEnumerator, "new C()").WithArguments("D", "E.extension(C).GetEnumerator()").WithLocation(1, 19) + ); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var loop = tree.GetRoot().DescendantNodes().OfType().Single(); + Assert.Null(model.GetForEachStatementInfo(loop).GetEnumeratorMethod); + Assert.Null(model.GetForEachStatementInfo(loop).MoveNextMethod); + Assert.Null(model.GetForEachStatementInfo(loop).CurrentProperty); + } + + [Fact] + public void InstanceMethodInvocation_PatternBased_ForEach_Current() + { + var src = """ +foreach (var x in new C()) +{ +} + +class C { } +class D +{ + public bool MoveNext() => true; +} + +static class E +{ + extension(C c) + { + public D GetEnumerator() => new D(); + } + + extension(D d) + { public int Current => 42; } } @@ -12781,6 +12876,42 @@ static class E Assert.Null(model.GetForEachStatementInfo(loop).CurrentProperty); } + [Fact] + public void InstanceMethodInvocation_PatternBased_ForEach_GetEnumerator_Conversion() + { + var src = """ +foreach (var x in new C()) +{ + System.Console.Write(x); + break; +} + +class C { } +class D +{ + public bool MoveNext() => true; + public int Current => 42; +} + +static class E +{ + extension(object o) + { + public D GetEnumerator() => new D(); + } +} +"""; + try + { + // Tracked by https://github.com/dotnet/roslyn/issues/76130 : assertion in NullableWalker + var comp = CreateCompilation(src); + CompileAndVerify(comp, expectedOutput: "42").VerifyDiagnostics(); + } + catch (InvalidOperationException) + { + } + } + [Fact] public void InstanceMethodInvocation_NameOf_SingleParameter() { @@ -12811,10 +12942,10 @@ static class E [Fact] public void InstanceMethodInvocation_Simple_ExpressionTree() { - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : Verify shape of the tree if we decide to allow var source = """ using System.Linq.Expressions; Expression x = () => new C().M(42); +System.Console.Write(x.Dump()); System.Action a = x.Compile(); a(); @@ -12827,13 +12958,12 @@ static class E { extension(C c) { - public void M(int i) { System.Console.Write("ran"); } + public void M(int i) { System.Console.Write(" ran"); } } } """; - var comp = CreateCompilation(source); - comp.VerifyEmitDiagnostics(); - CompileAndVerify(comp, expectedOutput: "ran").VerifyDiagnostics(); + var comp = CreateCompilation([source, ExpressionTestLibrary]); + CompileAndVerify(comp, expectedOutput: "Call(null.[Void M(C, Int32)](New([Void .ctor()]() Type:C), Constant(42 Type:System.Int32)) Type:System.Void) ran").VerifyDiagnostics(); var tree = comp.SyntaxTrees.First(); var model = comp.GetSemanticModel(tree); @@ -15711,7 +15841,7 @@ public class MyCollection : IEnumerable } [Fact] - public void ResolveAll_CollectionExpression_ExtensionAddDelegateTypeProperty() + public void ResolveAll_CollectionExpression_ExtensionAdd_DelegateTypeProperty() { var source = """ using System.Collections; @@ -15739,6 +15869,74 @@ public class MyCollection : IEnumerable // MyCollection c = [42]; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[42]").WithArguments("MyCollection", "Add").WithLocation(4, 18) ); + + source = """ +using System.Collections; +using System.Collections.Generic; + +MyCollection c = [42]; + +public class MyCollection : IEnumerable +{ + IEnumerator IEnumerable.GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; + public System.Action Add => (int i) => { }; +} +"""; + comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (4,18): error CS0118: 'Add' is a property but is used like a method + // MyCollection c = [42]; + Diagnostic(ErrorCode.ERR_BadSKknown, "[42]").WithArguments("Add", "property", "method").WithLocation(4, 18)); + } + + [Fact] + public void ResolveAll_CollectionExpression_ExtensionAdd_DynamicTypeProperty() + { + var source = """ +using System.Collections; +using System.Collections.Generic; + +MyCollection c = [42]; + +static class E +{ + extension(MyCollection c) + { + public dynamic Add => throw null; + } +} + +public class MyCollection : IEnumerable +{ + IEnumerator IEnumerable.GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; +} +"""; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (4,18): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) + // MyCollection c = [42]; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[42]").WithArguments("MyCollection", "Add").WithLocation(4, 18)); + + source = """ +using System.Collections; +using System.Collections.Generic; + +MyCollection c = [42]; + +public class MyCollection : IEnumerable +{ + IEnumerator IEnumerable.GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; + public dynamic Add => throw null; +} +"""; + comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (4,18): error CS0118: 'Add' is a property but is used like a method + // MyCollection c = [42]; + Diagnostic(ErrorCode.ERR_BadSKknown, "[42]").WithArguments("Add", "property", "method").WithLocation(4, 18)); } [Fact] @@ -16155,6 +16353,86 @@ static class E Assert.Equal("System.String E.<>E__0.M { get; }", model.GetSymbolInfo(memberAccess).Symbol.ToTestDisplayString()); } + [Fact] + public void ResolveAll_Query_Where_DelegateTypeProperty() + { + var src = """ +var x = from i in new C() + where i is not null + select i; + +System.Console.Write(x); + +public class C { } + +public static class E +{ + extension(C c) + { + public System.Func, C> Where => (System.Func f) => { System.Console.Write(f(c)); return c; }; + } +} +"""; + var comp = CreateCompilation(src); + CompileAndVerify(comp, expectedOutput: "TrueC").VerifyDiagnostics(); + + src = """ +var x = from i in new C() + where i is not null + select i; + +System.Console.Write(x); + +public class C +{ + public System.Func, C> Where => (System.Func f) => { System.Console.Write(f(this)); return this; }; +} +"""; + comp = CreateCompilation(src); + CompileAndVerify(comp, expectedOutput: "TrueC").VerifyDiagnostics(); + } + + [Fact] + public void ResolveAll_Query_Where_DynamicTypeProperty() + { + var src = """ +var x = from i in new C() + where i is not null + select i; + +public class C { } + +public static class E +{ + extension(C c) + { + public dynamic Where => throw null; + } +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (2,15): 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. + // where i is not null + Diagnostic(ErrorCode.ERR_BadDynamicMethodArgLambda, "i is not null").WithLocation(2, 15)); + + src = """ +var x = from i in new C() + where i is not null + select i; + +public class C +{ + public dynamic Where => throw null; +} +"""; + comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (2,9): error CS1979: Query expressions over source type 'dynamic' or with a join sequence of type 'dynamic' are not allowed + // where i is not null + Diagnostic(ErrorCode.ERR_BadDynamicQuery, "where i is not null").WithLocation(2, 9)); + } + [Fact(Skip = "Tracked by https://github.com/dotnet/roslyn/issues/76130 : WasPropertyBackingFieldAccessChecked asserts that we're setting twice")] public void ResolveAll_Query_Cast() { @@ -18268,7 +18546,7 @@ static class E """; // Note: we apply the same conversion requirements even though no conversion on the receiver - // is needed in a static scenario. + // is needed in a static scenario. var comp = CreateCompilation(source, targetFramework: TargetFramework.Net90); comp.VerifyEmitDiagnostics( // (1,36): error CS0117: 'Span' does not contain a definition for 'M' @@ -18496,20 +18774,21 @@ public void StaticPropertyAccess_RefProperty_02() { var src = """ localFuncRef(ref object.Property); +System.Console.Write(E.field); -void localFuncRef(ref int i) => throw null; +void localFuncRef(ref int i) { i++; } static class E { + public static int field = 42; extension(object) { - public static ref int Property { get => throw null; } + public static ref int Property { get => ref E.field; } } } """; var comp = CreateCompilation(src); - comp.VerifyEmitDiagnostics(); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : metadata is undone + CompileAndVerify(comp, expectedOutput: "43").VerifyDiagnostics(); } [Fact] @@ -19951,11 +20230,12 @@ static class E } [Fact] - public void ExtensionMemberLookup_PatternBased_Deconstruct_NoMethod() + public void ExtensionMemberLookup_PatternBased_ForEach_DelegateTypeProperty() { var src = """ -var (x, y) = new C(); -System.Console.Write((x, y)); +using System.Collections; + +foreach (var x in new C()) { } class C { } @@ -19963,171 +20243,159 @@ static class E { extension(C c) { - public void Deconstruct(out int i, out int j) { i = 42; j = 43; } + public System.Func GetEnumerator => throw null; } } """; var comp = CreateCompilation(src); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : confirm when spec'ing pattern-based deconstruction - CompileAndVerify(comp, expectedOutput: "(42, 43)").VerifyDiagnostics(); + comp.VerifyEmitDiagnostics( + // (3,19): error CS1579: foreach statement cannot operate on variables of type 'C' because 'C' does not contain a public instance or extension definition for 'GetEnumerator' + // foreach (var x in new C()) { } + Diagnostic(ErrorCode.ERR_ForEachMissingMember, "new C()").WithArguments("C", "GetEnumerator").WithLocation(3, 19)); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); - var deconstruction = tree.GetRoot().DescendantNodes().OfType().First(); + var loop = tree.GetRoot().DescendantNodes().OfType().Single(); + Assert.Null(model.GetForEachStatementInfo(loop).GetEnumeratorMethod); - Assert.Equal("void E.<>E__0.Deconstruct(out System.Int32 i, out System.Int32 j)", - model.GetDeconstructionInfo(deconstruction).Method.ToTestDisplayString()); + src = """ +using System.Collections; + +foreach (var x in new C()) { } + +class C +{ + public System.Func GetEnumerator => throw null; +} +"""; + comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (3,19): warning CS0280: 'C' does not implement the 'collection' pattern. 'C.GetEnumerator' has the wrong signature. + // foreach (var x in new C()) { } + Diagnostic(ErrorCode.WRN_PatternBadSignature, "new C()").WithArguments("C", "collection", "C.GetEnumerator").WithLocation(3, 19), + // (3,19): error CS1579: foreach statement cannot operate on variables of type 'C' because 'C' does not contain a public instance or extension definition for 'GetEnumerator' + // foreach (var x in new C()) { } + Diagnostic(ErrorCode.ERR_ForEachMissingMember, "new C()").WithArguments("C", "GetEnumerator").WithLocation(3, 19)); } [Fact] - public void ExtensionMemberLookup_PatternBased_Deconstruct_FallbackToExtensionMethod() + public void ExtensionMemberLookup_PatternBased_ForEach_GetEnumerator_DynamicTypeProperty() { - // If the method from the extension type is not applicable, we fall back - // to a Deconstruct extension method var src = """ -var (x, y) = new C(); -System.Console.Write((x, y)); +using System.Collections; -public class C { } +foreach (var x in new C()) { } + +class C { } static class E { extension(C c) { - public void Deconstruct(int inapplicable) => throw null; + public dynamic GetEnumerator => throw null; } } - -public static class E2 -{ - public static void Deconstruct(this C c, out int i, out int j) { i = 42; j = 43; } -} """; var comp = CreateCompilation(src); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : confirm when spec'ing pattern-based deconstruction - CompileAndVerify(comp, expectedOutput: "(42, 43)").VerifyDiagnostics(); + comp.VerifyEmitDiagnostics( + // (3,19): error CS1579: foreach statement cannot operate on variables of type 'C' because 'C' does not contain a public instance or extension definition for 'GetEnumerator' + // foreach (var x in new C()) { } + Diagnostic(ErrorCode.ERR_ForEachMissingMember, "new C()").WithArguments("C", "GetEnumerator").WithLocation(3, 19)); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); - var deconstruction = tree.GetRoot().DescendantNodes().OfType().First(); + var loop = tree.GetRoot().DescendantNodes().OfType().Single(); + Assert.Null(model.GetForEachStatementInfo(loop).GetEnumeratorMethod); - Assert.Equal("void E2.Deconstruct(this C c, out System.Int32 i, out System.Int32 j)", - model.GetDeconstructionInfo(deconstruction).Method.ToTestDisplayString()); + src = """ +foreach (var x in new C()) { } + +class C +{ + public dynamic GetEnumerator => throw null; +} +"""; + comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (1,19): warning CS0280: 'C' does not implement the 'collection' pattern. 'C.GetEnumerator' has the wrong signature. + // foreach (var x in new C()) { } + Diagnostic(ErrorCode.WRN_PatternBadSignature, "new C()").WithArguments("C", "collection", "C.GetEnumerator").WithLocation(1, 19), + // (1,19): error CS1579: foreach statement cannot operate on variables of type 'C' because 'C' does not contain a public instance or extension definition for 'GetEnumerator' + // foreach (var x in new C()) { } + Diagnostic(ErrorCode.ERR_ForEachMissingMember, "new C()").WithArguments("C", "GetEnumerator").WithLocation(1, 19)); } [Fact] - public void ExtensionMemberLookup_PatternBased_Deconstruct_DelegateTypeProperty() + public void ExtensionMemberLookup_PatternBased_ForEach_GetEnumerator_Generic() { var src = """ -var (x1, y1) = new C1(); - -var (x2, y2) = new C2(); - -class C1 { } +using System.Collections.Generic; -class C2 -{ - public D Deconstruct => (out int i, out int j) => { i = 42; j = 43; }; -} +foreach (var x in new C()) { System.Console.Write(x); } -delegate void D(out int i, out int j); +class C { } static class E { - extension(C1 c) + extension(T t) { - public D Deconstruct => (out int i, out int j) => { i = 42; j = 43; }; + public IEnumerator GetEnumerator() + { + yield return t; + } } } """; var comp = CreateCompilation(src); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : revisit pattern-based deconstruction - comp.VerifyDiagnostics( - // (1,6): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x1'. - // var (x1, y1) = new C1(); - Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x1").WithArguments("x1").WithLocation(1, 6), - // (1,10): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'y1'. - // var (x1, y1) = new C1(); - Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "y1").WithArguments("y1").WithLocation(1, 10), - - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : It looks like the following error is not reported for instance scenario. Noise? - - // (1,16): error CS1061: 'C1' does not contain a definition for 'Deconstruct' and no accessible extension method 'Deconstruct' accepting a first argument of type 'C1' could be found (are you missing a using directive or an assembly reference?) - // var (x1, y1) = new C1(); - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "new C1()").WithArguments("C1", "Deconstruct").WithLocation(1, 16), - - // (1,16): error CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'C1', with 2 out parameters and a void return type. - // var (x1, y1) = new C1(); - Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C1()").WithArguments("C1", "2").WithLocation(1, 16), - // (3,6): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x2'. - // var (x2, y2) = new C2(); - Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x2").WithArguments("x2").WithLocation(3, 6), - // (3,10): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'y2'. - // var (x2, y2) = new C2(); - Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "y2").WithArguments("y2").WithLocation(3, 10), - // (3,16): error CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'C2', with 2 out parameters and a void return type. - // var (x2, y2) = new C2(); - Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C2()").WithArguments("C2", "2").WithLocation(3, 16) - ); + CompileAndVerify(comp, expectedOutput: "C").VerifyDiagnostics(); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); - var deconstruction = tree.GetRoot().DescendantNodes().OfType().First(); - - Assert.Null(model.GetDeconstructionInfo(deconstruction).Method); + var loop = tree.GetRoot().DescendantNodes().OfType().Single(); + Assert.Equal("System.Collections.Generic.IEnumerator E.<>E__0.GetEnumerator()", + model.GetForEachStatementInfo(loop).GetEnumeratorMethod.ToTestDisplayString()); } [Fact] - public void ExtensionMemberLookup_PatternBased_Deconstruct_DynamicProperty() + public void ExtensionMemberLookup_PatternBased_AwaitForEach_GetAsyncEnumerator() { var src = """ -var (x, y) = new C(); +using System.Collections.Generic; + +await foreach (var x in new C()) { System.Console.Write(x); } class C { } static class E { - extension(C c) + extension(T t) { - public dynamic Deconstruct => throw null; + public async IAsyncEnumerator GetAsyncEnumerator() + { + await System.Threading.Tasks.Task.Yield(); + yield return t; + } } } """; - var comp = CreateCompilation(src); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : revisit pattern-based deconstruction - comp.VerifyEmitDiagnostics( - // (1,6): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x'. - // var (x, y) = new C(); - Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x").WithArguments("x").WithLocation(1, 6), - // (1,9): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'y'. - // var (x, y) = new C(); - Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "y").WithArguments("y").WithLocation(1, 9), - // (1,14): error CS1061: 'C' does not contain a definition for 'Deconstruct' and no accessible extension method 'Deconstruct' accepting a first argument of type 'C' could be found (are you missing a using directive or an assembly reference?) - // var (x, y) = new C(); - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "new C()").WithArguments("C", "Deconstruct").WithLocation(1, 14), - // (1,14): error CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'C', with 2 out parameters and a void return type. - // var (x, y) = new C(); - Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C()").WithArguments("C", "2").WithLocation(1, 14) - ); + var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90); + CompileAndVerify(comp, expectedOutput: ExpectedOutput("C"), verify: Verification.FailsPEVerify).VerifyDiagnostics(); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); - var deconstruction = tree.GetRoot().DescendantNodes().OfType().First(); - - Assert.Null(model.GetDeconstructionInfo(deconstruction).Method); + var loop = tree.GetRoot().DescendantNodes().OfType().Single(); + Assert.Equal("System.Collections.Generic.IAsyncEnumerator E.<>E__0.GetAsyncEnumerator()", + model.GetForEachStatementInfo(loop).GetEnumeratorMethod.ToTestDisplayString()); } [Fact] - public void ExtensionMemberLookup_PatternBased_Deconstruct_NoApplicableMethod() + public void ExtensionMemberLookup_PatternBased_Deconstruct_NoMethod() { var src = """ var (x, y) = new C(); System.Console.Write((x, y)); -class C -{ - public void Deconstruct() { } // not applicable -} +class C { } static class E { @@ -20137,7 +20405,6 @@ static class E } } """; - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : confirm when spec'ing pattern-based deconstruction var comp = CreateCompilation(src); CompileAndVerify(comp, expectedOutput: "(42, 43)").VerifyDiagnostics(); @@ -20150,7 +20417,245 @@ static class E } [Fact] - public void ExtensionMemberLookup_PatternBased_Dispose_Async_NoMethod() + public void ExtensionMemberLookup_PatternBased_Deconstruct_Conversion() + { + var src = """ +var (x, y) = new C(); +System.Console.Write((x, y)); + +class C { } + +static class E +{ + extension(object o) + { + public void Deconstruct(out int i, out int j) { i = 42; j = 43; } + } +} +"""; + var comp = CreateCompilation(src); + CompileAndVerify(comp, expectedOutput: "(42, 43)").VerifyDiagnostics(); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_Deconstruct_Generic() + { + var src = """ +var (x, y) = new C(); +System.Console.Write((x, y)); + +class C { } + +static class E +{ + extension(T t) + { + public void Deconstruct(out int i, out int j) { i = 42; j = 43; } + } +} +"""; + var comp = CreateCompilation(src); + CompileAndVerify(comp, expectedOutput: "(42, 43)").VerifyDiagnostics(); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var deconstruction = tree.GetRoot().DescendantNodes().OfType().First(); + + Assert.Equal("void E.<>E__0.Deconstruct(out System.Int32 i, out System.Int32 j)", + model.GetDeconstructionInfo(deconstruction).Method.ToTestDisplayString()); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_Deconstruct_FallbackToExtensionMethod() + { + // If the method from the extension type is not applicable, we fall back + // to a Deconstruct extension method + var src = """ +var (x, y) = new C(); +System.Console.Write((x, y)); + +public class C { } + +static class E +{ + extension(C c) + { + public void Deconstruct(int inapplicable) => throw null; + } +} + +public static class E2 +{ + public static void Deconstruct(this C c, out int i, out int j) { i = 42; j = 43; } +} +"""; + var comp = CreateCompilation(src); + CompileAndVerify(comp, expectedOutput: "(42, 43)").VerifyDiagnostics(); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var deconstruction = tree.GetRoot().DescendantNodes().OfType().First(); + + Assert.Equal("void E2.Deconstruct(this C c, out System.Int32 i, out System.Int32 j)", + model.GetDeconstructionInfo(deconstruction).Method.ToTestDisplayString()); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_Deconstruct_DelegateTypeProperty() + { + var src = """ +var (x1, y1) = new C1(); + +var (x2, y2) = new C2(); + +class C1 { } + +class C2 +{ + public D Deconstruct => (out int i, out int j) => { i = 42; j = 43; }; +} + +delegate void D(out int i, out int j); + +static class E +{ + extension(C1 c) + { + public D Deconstruct => (out int i, out int j) => { i = 42; j = 43; }; + } +} +"""; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (1,6): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x1'. + // var (x1, y1) = new C1(); + Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x1").WithArguments("x1").WithLocation(1, 6), + // (1,10): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'y1'. + // var (x1, y1) = new C1(); + Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "y1").WithArguments("y1").WithLocation(1, 10), + + // Tracked by https://github.com/dotnet/roslyn/issues/76130 : It looks like the following error is not reported for instance scenario. Noise? + + // (1,16): error CS1061: 'C1' does not contain a definition for 'Deconstruct' and no accessible extension method 'Deconstruct' accepting a first argument of type 'C1' could be found (are you missing a using directive or an assembly reference?) + // var (x1, y1) = new C1(); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "new C1()").WithArguments("C1", "Deconstruct").WithLocation(1, 16), + + // (1,16): error CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'C1', with 2 out parameters and a void return type. + // var (x1, y1) = new C1(); + Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C1()").WithArguments("C1", "2").WithLocation(1, 16), + // (3,6): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x2'. + // var (x2, y2) = new C2(); + Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x2").WithArguments("x2").WithLocation(3, 6), + // (3,10): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'y2'. + // var (x2, y2) = new C2(); + Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "y2").WithArguments("y2").WithLocation(3, 10), + // (3,16): error CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'C2', with 2 out parameters and a void return type. + // var (x2, y2) = new C2(); + Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C2()").WithArguments("C2", "2").WithLocation(3, 16) + ); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var deconstruction = tree.GetRoot().DescendantNodes().OfType().First(); + + Assert.Null(model.GetDeconstructionInfo(deconstruction).Method); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_Deconstruct_DynamicProperty() + { + var src = """ +var (x, y) = new C(); + +class C { } + +static class E +{ + extension(C c) + { + public dynamic Deconstruct => throw null; + } +} +"""; + var comp = CreateCompilation(src); + // Tracked by https://github.com/dotnet/roslyn/issues/76130 : revisit pattern-based deconstruction + comp.VerifyEmitDiagnostics( + // (1,6): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x'. + // var (x, y) = new C(); + Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x").WithArguments("x").WithLocation(1, 6), + // (1,9): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'y'. + // var (x, y) = new C(); + Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "y").WithArguments("y").WithLocation(1, 9), + // (1,14): error CS1061: 'C' does not contain a definition for 'Deconstruct' and no accessible extension method 'Deconstruct' accepting a first argument of type 'C' could be found (are you missing a using directive or an assembly reference?) + // var (x, y) = new C(); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "new C()").WithArguments("C", "Deconstruct").WithLocation(1, 14), + // (1,14): error CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'C', with 2 out parameters and a void return type. + // var (x, y) = new C(); + Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C()").WithArguments("C", "2").WithLocation(1, 14) + ); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var deconstruction = tree.GetRoot().DescendantNodes().OfType().First(); + + Assert.Null(model.GetDeconstructionInfo(deconstruction).Method); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_Deconstruct_NoApplicableMethod() + { + var src = """ +var (x, y) = new C(); +System.Console.Write((x, y)); + +class C +{ + public void Deconstruct() { } // not applicable +} + +static class E +{ + extension(C c) + { + public void Deconstruct(out int i, out int j) { i = 42; j = 43; } + } +} +"""; + var comp = CreateCompilation(src); + CompileAndVerify(comp, expectedOutput: "(42, 43)").VerifyDiagnostics(); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var deconstruction = tree.GetRoot().DescendantNodes().OfType().First(); + + Assert.Equal("void E.<>E__0.Deconstruct(out System.Int32 i, out System.Int32 j)", + model.GetDeconstructionInfo(deconstruction).Method.ToTestDisplayString()); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_PositionalPattern() + { + var src = """ +var c = new C(); +if (c is var (x, y)) + System.Console.Write((x, y)); + +class C { } + +static class E +{ + extension(T t) + { + public void Deconstruct(out int i, out int j) { i = 42; j = 43; } + } +} +"""; + var comp = CreateCompilation(src); + CompileAndVerify(comp, expectedOutput: "(42, 43)").VerifyDiagnostics(); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_DisposeAsync_NoMethod() { var src = """ using System.Threading.Tasks; @@ -20168,22 +20673,13 @@ static class E { extension(C1 c) { - public async Task DisposeAsync() - { - System.Console.Write("RAN"); - await Task.Yield(); - } + public Task DisposeAsync() => throw null; } - public static async Task DisposeAsync(this C2 c) - { - System.Console.Write("RAN"); - await Task.Yield(); - } + public static Task DisposeAsync(this C2 c) => throw null; } """; var comp = CreateCompilation(src); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : confirm when spec'ing pattern-based disposal var expectedDiagnostics = new[] { // (4,1): error CS8410: 'C1': type used in an asynchronous using statement must implement 'System.IAsyncDisposable' or implement a suitable 'DisposeAsync' method. @@ -20284,12 +20780,11 @@ static class E { extension(C c) { - public System.Func DisposeAsync => async () => { System.Console.Write("ran2"); await Task.Yield(); }; + public System.Func DisposeAsync => async () => { await Task.Yield(); }; } } """; var comp = CreateCompilation(src); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 :(instance) confirm when spec'ing pattern-based disposal comp.VerifyEmitDiagnostics( // (3,1): error CS8410: 'C': type used in an asynchronous using statement must implement 'System.IAsyncDisposable' or implement a suitable 'DisposeAsync' method. // await using var x = new C(); @@ -20324,7 +20819,6 @@ public async Task DisposeAsync() } } """; - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : confirm when spec'ing pattern-based disposal var comp = CreateCompilation(src); comp.VerifyDiagnostics( // (4,1): error CS8410: 'C': type used in an asynchronous using statement must implement 'System.IAsyncDisposable' or implement a suitable 'DisposeAsync' method. @@ -20370,7 +20864,44 @@ public static void Dispose(this S2 s) { } } [Fact] - public void ExtensionMemberLookup_PatternBased_Fixed_NoMethod() + public void ExtensionMemberLookup_PatternBased_Dispose_RefStruct_DelegateTypeProperty() + { + var src = """ +using var x1 = new S1(); + +ref struct S1 { } + +static class E +{ + extension(S1 s) + { + public System.Action Dispose => throw null; + } +} +"""; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (1,1): error CS1674: 'S1': type used in a using statement must implement 'System.IDisposable'. + // using var x1 = new S1(); + Diagnostic(ErrorCode.ERR_NoConvToIDisp, "using var x1 = new S1();").WithArguments("S1").WithLocation(1, 1)); + + src = """ +using var x1 = new S1(); + +ref struct S1 +{ + public System.Action Dispose => throw null; +} +"""; + comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (1,1): error CS1674: 'S1': type used in a using statement must implement 'System.IDisposable'. + // using var x1 = new S1(); + Diagnostic(ErrorCode.ERR_NoConvToIDisp, "using var x1 = new S1();").WithArguments("S1").WithLocation(1, 1)); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_Fixed_01() { var text = """ unsafe class C @@ -20395,13 +20926,40 @@ static class E } """; var comp = CreateCompilation(text, options: TestOptions.UnsafeReleaseExe); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : confirm when spec'ing pattern-based fixed - comp.VerifyEmitDiagnostics(); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : metadata is undone + CompileAndVerify(comp, expectedOutput: "pin 2", verify: Verification.Skipped).VerifyDiagnostics(); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_Fixed_02_Conversion() + { + var text = """ +unsafe class C +{ + public static void Main() + { + fixed (int* p = new Fixable()) + { + System.Console.WriteLine(p[1]); + } + } +} + +class Fixable { } + +static class E +{ + extension(object o) + { + public ref int GetPinnableReference() { System.Console.Write("pin "); return ref (new int[] { 1, 2, 3 })[0]; } + } +} +"""; + var comp = CreateCompilation(text, options: TestOptions.UnsafeReleaseExe); + CompileAndVerify(comp, expectedOutput: "pin 2", verify: Verification.Skipped).VerifyDiagnostics(); } [Fact] - public void ExtensionMemberLookup_PatternBased_Fixed_NoMethod_DelegateTypeProperty() + public void ExtensionMemberLookup_PatternBased_Fixed_03_DelegateTypeProperty() { var text = @" unsafe class C @@ -20422,389 +20980,1217 @@ public static void Main() class Fixable1 { } -class Fixable2 +class Fixable2 +{ + public MyDelegate GetPinnableReference => throw null; +} + +delegate ref int MyDelegate(); + +static class E +{ + extension(Fixable1 f) + { + public MyDelegate GetPinnableReference => throw null; + } +} +"; + var comp = CreateCompilation(text, options: TestOptions.UnsafeReleaseExe); + comp.VerifyEmitDiagnostics( + // (6,25): error CS8385: The given expression cannot be used in a fixed statement + // fixed (int* p = new Fixable1()) + Diagnostic(ErrorCode.ERR_ExprCannotBeFixed, "new Fixable1()").WithLocation(6, 25), + // (11,25): error CS8385: The given expression cannot be used in a fixed statement + // fixed (int* p = new Fixable2()) + Diagnostic(ErrorCode.ERR_ExprCannotBeFixed, "new Fixable2()").WithLocation(11, 25) + ); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_Fixed_04_DynamicTypeProperty() + { + var text = @" +unsafe class C +{ + public static void Main() + { + fixed (int* p = new Fixable1()) + { + } + } +} + +class Fixable1 { } + +delegate ref int MyDelegate(); + +static class E +{ + extension(Fixable1 f) + { + public dynamic GetPinnableReference => throw null; + } +} +"; + var comp = CreateCompilation(text, options: TestOptions.UnsafeReleaseExe); + comp.VerifyEmitDiagnostics( + // (6,25): error CS8385: The given expression cannot be used in a fixed statement + // fixed (int* p = new Fixable1()) + Diagnostic(ErrorCode.ERR_ExprCannotBeFixed, "new Fixable1()").WithLocation(6, 25)); + + text = @" +unsafe class C +{ + public static void Main() + { + fixed (int* p = new Fixable1()) + { + } + } +} + +class Fixable1 +{ + public dynamic GetPinnableReference => throw null; +} + +delegate ref int MyDelegate(); +"; + comp = CreateCompilation(text, options: TestOptions.UnsafeReleaseExe); + comp.VerifyEmitDiagnostics( + // (6,25): error CS8385: The given expression cannot be used in a fixed statement + // fixed (int* p = new Fixable1()) + Diagnostic(ErrorCode.ERR_ExprCannotBeFixed, "new Fixable1()").WithLocation(6, 25)); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_Fixed_05() + { + var src = """ +unsafe class C +{ + public static void Main() + { + /**/ + fixed (int* p = new Fixable()) + { + System.Console.WriteLine(p[1]); + } + /**/ + } +} + +class Fixable +{ + public ref int GetPinnableReference(int notApplicable) => throw null; // not applicable +} + +static class E +{ + extension(Fixable f) + { + public ref int GetPinnableReference() { return ref (new int[] { 1, 2, 3 })[0]; } + } +} +"""; + + var comp = CreateCompilation(src, options: TestOptions.UnsafeReleaseExe); + CompileAndVerify(comp, expectedOutput: "2", verify: Verification.Skipped).VerifyDiagnostics(); + + string expectedOperationTree = """ +IFixedOperation (OperationKind.None, Type: null) (Syntax: 'fixed (int* ... }') + Locals: Local_1: System.Int32* p + Declaration: + IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null, IsImplicit) (Syntax: 'int* p = new Fixable()') + IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'int* p = new Fixable()') + Declarators: + IVariableDeclaratorOperation (Symbol: System.Int32* p) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'p = new Fixable()') + Initializer: + IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= new Fixable()') + IOperation: (OperationKind.None, Type: System.Int32*, IsImplicit) (Syntax: 'new Fixable()') + Children(1): + IObjectCreationOperation (Constructor: Fixable..ctor()) (OperationKind.ObjectCreation, Type: Fixable) (Syntax: 'new Fixable()') + Arguments(0) + Initializer: + null + Initializer: + null + Body: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'System.Cons ... Line(p[1]);') + Expression: + IInvocationOperation (void System.Console.WriteLine(System.Int32 value)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'System.Cons ... eLine(p[1])') + Instance Receiver: + null + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: 'p[1]') + IOperation: (OperationKind.None, Type: System.Int32) (Syntax: 'p[1]') + Children(2): + ILocalReferenceOperation: p (OperationKind.LocalReference, Type: System.Int32*) (Syntax: 'p') + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) +"""; + + VerifyOperationTreeAndDiagnosticsForTest(src, expectedOperationTree, [], targetFramework: TargetFramework.Net70, compilationOptions: TestOptions.UnsafeReleaseExe); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_Fixed_06() + { + var text = @" +unsafe class C +{ + public static void Main() + { + fixed (int* p = new Fixable()) + { + } + } +} + +class Fixable { } + +static class E +{ + extension(Fixable f) + { + public static ref int GetPinnableReference() => throw null; + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.UnsafeReleaseExe); + comp.VerifyEmitDiagnostics( + // (6,25): error CS0176: Member 'E.extension(Fixable).GetPinnableReference()' cannot be accessed with an instance reference; qualify it with a type name instead + // fixed (int* p = new Fixable()) + Diagnostic(ErrorCode.ERR_ObjectProhibited, "new Fixable()").WithArguments("E.extension(Fixable).GetPinnableReference()").WithLocation(6, 25), + // (6,25): error CS8385: The given expression cannot be used in a fixed statement + // fixed (int* p = new Fixable()) + Diagnostic(ErrorCode.ERR_ExprCannotBeFixed, "new Fixable()").WithLocation(6, 25)); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_Await_ExtensionIsCompleted() + { + var text = @" +using System; +using System.Runtime.CompilerServices; + +int i = await new C(); +System.Console.Write(i); + +class C +{ + public D GetAwaiter() => new D(); +} + +class D : INotifyCompletion +{ + public int GetResult() => 42; + public void OnCompleted(Action continuation) => throw null; +} + +static class E +{ + extension(D d) + { + public bool IsCompleted => true; + } +} +"; + + var comp = CreateCompilation(text); + comp.VerifyEmitDiagnostics( + // (5,9): error CS0117: 'D' does not contain a definition for 'IsCompleted' + // int i = await new C(); + Diagnostic(ErrorCode.ERR_NoSuchMember, "await new C()").WithArguments("D", "IsCompleted").WithLocation(5, 9) + ); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_Await_ExtensionGetAwaiter() + { + var text = @" +using System; +using System.Runtime.CompilerServices; + +/**/ +int i = await new C(); +/**/ +System.Console.Write(i); + +class C +{ +} + +class D : INotifyCompletion +{ + public int GetResult() => 42; + public void OnCompleted(Action continuation) => throw null; + public bool IsCompleted => true; +} + +static class E +{ + extension(C c) + { + public D GetAwaiter() => new D(); + } +} +"; + + var comp = CreateCompilation(text); + CompileAndVerify(comp, expectedOutput: "42").VerifyDiagnostics(); + + string expectedOperationTree = """ +IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null) (Syntax: 'int i = await new C();') +IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'int i = await new C()') + Declarators: + IVariableDeclaratorOperation (Symbol: System.Int32 i) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'i = await new C()') + Initializer: + IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= await new C()') + IAwaitOperation (OperationKind.Await, Type: System.Int32) (Syntax: 'await new C()') + Expression: + IObjectCreationOperation (Constructor: C..ctor()) (OperationKind.ObjectCreation, Type: C) (Syntax: 'new C()') + Arguments(0) + Initializer: + null + Initializer: + null +"""; + + VerifyOperationTreeAndDiagnosticsForTest(text, expectedOperationTree, [], targetFramework: TargetFramework.Net70); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_Await_ExtensionGetAwaiter_Conversion() + { + var text = @" +using System; +using System.Runtime.CompilerServices; + +int i = await new C(); +System.Console.Write(i); + +class C +{ +} + +class D : INotifyCompletion +{ + public int GetResult() => 42; + public void OnCompleted(Action continuation) => throw null; + public bool IsCompleted => true; +} + +static class E +{ + extension(object o) + { + public D GetAwaiter() => new D(); + } +} +"; + + var comp = CreateCompilation(text); + CompileAndVerify(comp, expectedOutput: "42").VerifyDiagnostics(); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_Await_ExtensionGetAwaiter_DelegateTypeProperty() + { + var text = @" +using System; +using System.Runtime.CompilerServices; + +int i = await new C(); +System.Console.Write(i); + +class C +{ +} + +class D : INotifyCompletion +{ + public int GetResult() => 42; + public void OnCompleted(Action continuation) => throw null; + public bool IsCompleted => true; +} + +static class E +{ + extension(C c) + { + public System.Func GetAwaiter => () => new D(); + } +} +"; + + var comp = CreateCompilation(text); + comp.VerifyEmitDiagnostics( + // (5,9): error CS1061: 'C' does not contain a definition for 'GetAwaiter' and no accessible extension method 'GetAwaiter' accepting a first argument of type 'C' could be found (are you missing a using directive or an assembly reference?) + // int i = await new C(); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "await new C()").WithArguments("C", "GetAwaiter").WithLocation(5, 9)); + + text = @" +using System; +using System.Runtime.CompilerServices; + +int i = await new C(); +System.Console.Write(i); + +class C +{ + public System.Func GetAwaiter => () => new D(); +} + +class D : INotifyCompletion +{ + public int GetResult() => 42; + public void OnCompleted(Action continuation) => throw null; + public bool IsCompleted => true; +} +"; + + comp = CreateCompilation(text); + comp.VerifyEmitDiagnostics( + // (5,9): error CS0118: 'GetAwaiter' is a property but is used like a method + // int i = await new C(); + Diagnostic(ErrorCode.ERR_BadSKknown, "await new C()").WithArguments("GetAwaiter", "property", "method").WithLocation(5, 9)); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_Await_ExtensionGetAwaiter_DynamicTypeProperty() + { + var text = @" +using System; +using System.Runtime.CompilerServices; + +int i = await new C(); +System.Console.Write(i); + +class C +{ +} + +class D : INotifyCompletion +{ + public int GetResult() => 42; + public void OnCompleted(Action continuation) => throw null; + public bool IsCompleted => true; +} + +static class E +{ + extension(C c) + { + public dynamic GetAwaiter => throw null; + } +} +"; + + var comp = CreateCompilation(text); + comp.VerifyEmitDiagnostics( + // (5,9): error CS1061: 'C' does not contain a definition for 'GetAwaiter' and no accessible extension method 'GetAwaiter' accepting a first argument of type 'C' could be found (are you missing a using directive or an assembly reference?) + // int i = await new C(); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "await new C()").WithArguments("C", "GetAwaiter").WithLocation(5, 9)); + + text = @" +using System; +using System.Runtime.CompilerServices; + +int i = await new C(); +System.Console.Write(i); + +class C +{ + public dynamic GetAwaiter => throw null; +} + +class D : INotifyCompletion +{ + public int GetResult() => 42; + public void OnCompleted(Action continuation) => throw null; + public bool IsCompleted => true; +} +"; + + comp = CreateCompilation(text); + comp.VerifyEmitDiagnostics( + // (5,9): error CS0118: 'GetAwaiter' is a property but is used like a method + // int i = await new C(); + Diagnostic(ErrorCode.ERR_BadSKknown, "await new C()").WithArguments("GetAwaiter", "property", "method").WithLocation(5, 9)); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_Await_ExtensionGetResult() + { + var text = @" +using System; +using System.Runtime.CompilerServices; + +int i = await new C(); +System.Console.Write(i); + +class C +{ + public D GetAwaiter() => new D(); +} + +class D : INotifyCompletion +{ + public void OnCompleted(Action continuation) => throw null; + public bool IsCompleted => true; +} + +static class E +{ + extension(D d) + { + public int GetResult() => 42; + } +} +"; + + var comp = CreateCompilation(text); + + // The error is consistent with classic extension methods + comp.VerifyEmitDiagnostics( + // (5,9): error CS0117: 'D' does not contain a definition for 'GetResult' + // int i = await new C(); + Diagnostic(ErrorCode.ERR_NoSuchMember, "await new C()").WithArguments("D", "GetResult").WithLocation(5, 9) + ); + + text = """ +using System; +using System.Runtime.CompilerServices; + +int i = await new C(); +System.Console.Write(i); + +class C +{ + public D GetAwaiter() => new D(); +} + +class D : INotifyCompletion +{ + public void OnCompleted(Action continuation) => throw null; + public bool IsCompleted => true; +} + +static class E +{ + public static int GetResult(this D d) => 42; +} +"""; + + comp = CreateCompilation(text); + comp.VerifyEmitDiagnostics( + // (4,9): error CS0117: 'D' does not contain a definition for 'GetResult' + // int i = await new C(); + Diagnostic(ErrorCode.ERR_NoSuchMember, "await new C()").WithArguments("D", "GetResult").WithLocation(4, 9) + ); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_Await_ExtensionGetResult_DelegateTypeProperty() + { + var text = @" +using System; +using System.Runtime.CompilerServices; + +int i = await new C(); +System.Console.Write(i); + +class C +{ + public D GetAwaiter() => new D(); +} + +class D : INotifyCompletion +{ + public void OnCompleted(Action continuation) => throw null; + public bool IsCompleted => true; +} + +static class E +{ + extension(D d) + { + public System.Func GetResult => () => 42; + } +} +"; + var comp = CreateCompilation(text); + comp.VerifyEmitDiagnostics( + // (5,9): error CS0117: 'D' does not contain a definition for 'GetResult' + // int i = await new C(); + Diagnostic(ErrorCode.ERR_NoSuchMember, "await new C()").WithArguments("D", "GetResult").WithLocation(5, 9)); + + text = """ +using System; +using System.Runtime.CompilerServices; + +int i = await new C(); +System.Console.Write(i); + +class C +{ + public D GetAwaiter() => new D(); +} + +class D : INotifyCompletion +{ + public void OnCompleted(Action continuation) => throw null; + public bool IsCompleted => true; + public System.Func GetResult => () => 42; +} +"""; + + comp = CreateCompilation(text); + comp.VerifyEmitDiagnostics( + // (4,9): error CS0118: 'GetResult' is a property but is used like a method + // int i = await new C(); + Diagnostic(ErrorCode.ERR_BadSKknown, "await new C()").WithArguments("GetResult", "property", "method").WithLocation(4, 9)); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_Await_ExtensionGetResult_DynamicTypeProperty() + { + var text = @" +using System; +using System.Runtime.CompilerServices; + +int i = await new C(); +System.Console.Write(i); + +class C +{ + public D GetAwaiter() => new D(); +} + +class D : INotifyCompletion +{ + public void OnCompleted(Action continuation) => throw null; + public bool IsCompleted => true; +} + +static class E +{ + extension(D d) + { + public dynamic GetResult => throw null; + } +} +"; + + var comp = CreateCompilation(text); + comp.VerifyEmitDiagnostics( + // (5,9): error CS0117: 'D' does not contain a definition for 'GetResult' + // int i = await new C(); + Diagnostic(ErrorCode.ERR_NoSuchMember, "await new C()").WithArguments("D", "GetResult").WithLocation(5, 9)); + + text = """ +using System; +using System.Runtime.CompilerServices; + +int i = await new C(); +System.Console.Write(i); + +class C +{ + public D GetAwaiter() => new D(); +} + +class D : INotifyCompletion +{ + public void OnCompleted(Action continuation) => throw null; + public bool IsCompleted => true; + public dynamic GetResult => throw null; +} +"""; + + comp = CreateCompilation(text); + comp.VerifyEmitDiagnostics( + // (4,9): error CS0118: 'GetResult' is a property but is used like a method + // int i = await new C(); + Diagnostic(ErrorCode.ERR_BadSKknown, "await new C()").WithArguments("GetResult", "property", "method").WithLocation(4, 9)); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_IndexIndexer_Length() + { + var src = """ +var c = new C(); + +/**/ +_ = c[^1]; +/**/ + +class C +{ + public int this[int i] => throw null; +} + +static class E +{ + extension(C c) + { + public int Length => throw null; + } +} +"""; + DiagnosticDescription[] expectedDiagnostics = [ + // (4,7): error CS1503: Argument 1: cannot convert from 'System.Index' to 'int' + // _ = c[^1]; + Diagnostic(ErrorCode.ERR_BadArgType, "^1").WithArguments("1", "System.Index", "int").WithLocation(4, 7)]; + + var comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); + comp.VerifyEmitDiagnostics(expectedDiagnostics); + + string expectedOperationTree = """ +ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32, IsInvalid) (Syntax: '_ = c[^1]') +Left: + IDiscardOperation (Symbol: System.Int32 _) (OperationKind.Discard, Type: System.Int32) (Syntax: '_') +Right: + IInvalidOperation (OperationKind.Invalid, Type: System.Int32, IsInvalid) (Syntax: 'c[^1]') + Children(2): + ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C) (Syntax: 'c') + IUnaryOperation (UnaryOperatorKind.Hat) (OperationKind.Unary, Type: System.Index, IsInvalid) (Syntax: '^1') + Operand: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1') +"""; + + VerifyOperationTreeAndDiagnosticsForTest(src, expectedOperationTree, expectedDiagnostics, targetFramework: TargetFramework.Net70); + + src = """ +var c = new C(); +_ = c[^1]; + +class C +{ + public int this[int i] => throw null; + public int Length => throw null; +} +"""; + comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); + comp.VerifyEmitDiagnostics(); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_IndexIndexer_Count() + { + var src = """ +var c = new C(); +_ = c[^1]; + +class C +{ + public int this[int i] => throw null; +} + +static class E +{ + extension(C c) + { + public int Count => throw null; + } +} +"""; + + var comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); + comp.VerifyEmitDiagnostics( + // (2,7): error CS1503: Argument 1: cannot convert from 'System.Index' to 'int' + // _ = c[^1]; + Diagnostic(ErrorCode.ERR_BadArgType, "^1").WithArguments("1", "System.Index", "int").WithLocation(2, 7)); + + src = """ +var c = new C(); +_ = c[^1]; + +class C +{ + public int this[int i] => throw null; + public int Count => throw null; +} +"""; + comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); + comp.VerifyEmitDiagnostics(); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_IndexIndexer_IntIndexer() + { + var src = """ +var c = new C(); +_ = c[^1]; + +class C +{ + public int Length => throw null; +} + +static class E +{ + extension(C c) + { + public int this[int i] => throw null; + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); + comp.VerifyEmitDiagnostics( + // (2,5): error CS0021: Cannot apply indexing with [] to an expression of type 'C' + // _ = c[^1]; + Diagnostic(ErrorCode.ERR_BadIndexLHS, "c[^1]").WithArguments("C").WithLocation(2, 5)); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_IndexIndexer_RegularIndexer() + { + var src = """ +var c = new C(); +_ = c[^1]; + +class C +{ + public int Length => throw null; +} + +static class E +{ + extension(C c) + { + public int this[System.Index i] => throw null; + } +} +"""; + // Tracked by https://github.com/dotnet/roslyn/issues/76130 : revisit when implementing extension indexers + var comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); + comp.VerifyEmitDiagnostics( + // (2,5): error CS0021: Cannot apply indexing with [] to an expression of type 'C' + // _ = c[^1]; + Diagnostic(ErrorCode.ERR_BadIndexLHS, "c[^1]").WithArguments("C").WithLocation(2, 5)); + + src = """ +var c = new C(); +_ = c[^1]; + +class C +{ + public int Length => throw null; + public int this[System.Index i] => throw null; +} +"""; + comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); + comp.VerifyEmitDiagnostics(); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_RangeIndexer_Slice() + { + var src = """ +var c = new C(); + +/**/ +_ = c[1..^1]; +/**/ + +class C +{ + public int Length => throw null; +} + +static class E +{ + extension(C c) + { + public int Slice(int i, int j) => throw null; + } +} +"""; + + DiagnosticDescription[] expectedDiagnostics = [ + // (4,5): error CS0021: Cannot apply indexing with [] to an expression of type 'C' + // _ = c[1..^1]; + Diagnostic(ErrorCode.ERR_BadIndexLHS, "c[1..^1]").WithArguments("C").WithLocation(4, 5)]; + + var comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); + comp.VerifyEmitDiagnostics(expectedDiagnostics); + + string expectedOperationTree = """ +ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: ?, IsInvalid) (Syntax: '_ = c[1..^1]') +Left: + IDiscardOperation (Symbol: ? _) (OperationKind.Discard, Type: ?) (Syntax: '_') +Right: + IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'c[1..^1]') + Children(2): + IRangeOperation (OperationKind.Range, Type: System.Range, IsInvalid) (Syntax: '1..^1') + LeftOperand: + IConversionOperation (TryCast: False, Unchecked) (OperatorMethod: System.Index System.Index.op_Implicit(System.Int32 value)) (OperationKind.Conversion, Type: System.Index, IsInvalid, IsImplicit) (Syntax: '1') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: System.Index System.Index.op_Implicit(System.Int32 value)) + Operand: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1') + RightOperand: + IUnaryOperation (UnaryOperatorKind.Hat) (OperationKind.Unary, Type: System.Index, IsInvalid) (Syntax: '^1') + Operand: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1') + ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C, IsInvalid) (Syntax: 'c') +"""; + + VerifyOperationTreeAndDiagnosticsForTest(src, expectedOperationTree, expectedDiagnostics, targetFramework: TargetFramework.Net70); + + src = """ +var c = new C(); +_ = c[1..^1]; + +class C +{ + public int Length => throw null; + public int Slice(int i, int j) => throw null; +} +"""; + + comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); + comp.VerifyEmitDiagnostics(); + } + + [Fact] + public void ExtensionMemberLookup_PatternBased_RangeIndexer_Length() + { + var src = """ +var c = new C(); +_ = c[1..^1]; + +class C { - public MyDelegate GetPinnableReference => throw null; + public int Slice(int i, int j) => throw null; } -delegate ref int MyDelegate(); - static class E { - extension(Fixable1 f) + extension(C c) { - public MyDelegate GetPinnableReference => throw null; + public int Length => throw null; } } -"; - var comp = CreateCompilation(text, options: TestOptions.UnsafeReleaseExe); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : confirm when spec'ing pattern-based fixed +"""; + + var comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (6,25): error CS8385: The given expression cannot be used in a fixed statement - // fixed (int* p = new Fixable1()) - Diagnostic(ErrorCode.ERR_ExprCannotBeFixed, "new Fixable1()").WithLocation(6, 25), - // (11,25): error CS8385: The given expression cannot be used in a fixed statement - // fixed (int* p = new Fixable2()) - Diagnostic(ErrorCode.ERR_ExprCannotBeFixed, "new Fixable2()").WithLocation(11, 25) - ); + // (2,5): error CS0021: Cannot apply indexing with [] to an expression of type 'C' + // _ = c[1..^1]; + Diagnostic(ErrorCode.ERR_BadIndexLHS, "c[1..^1]").WithArguments("C").WithLocation(2, 5)); } [Fact] - public void ExtensionMemberLookup_PatternBased_Fixed_NoApplicableMethod() + public void ExtensionMemberLookup_PatternBased_RangeIndexer_RegularIndexer() { var src = """ -unsafe class C -{ - public static void Main() - { - fixed (int* p = new Fixable()) - { - System.Console.WriteLine(p[1]); - } - } -} +var c = new C(); +_ = c[1..^1]; -class Fixable +class C { - public ref int GetPinnableReference(int notApplicable) => throw null; // not applicable + public int Length => throw null; } static class E { - extension(Fixable f) + extension(C c) { - public ref int GetPinnableReference() { return ref (new int[] { 1, 2, 3 })[0]; } + public int this[System.Range r] => throw null; } } """; - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : confirm when spec'ing pattern-based fixed - var comp = CreateCompilation(src, options: TestOptions.UnsafeReleaseExe); - comp.VerifyEmitDiagnostics(); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : metadata is undone + // Tracked by https://github.com/dotnet/roslyn/issues/76130 : revisit when implementing extension indexers + var comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); + comp.VerifyEmitDiagnostics( + // (2,5): error CS0021: Cannot apply indexing with [] to an expression of type 'C' + // _ = c[1..^1]; + Diagnostic(ErrorCode.ERR_BadIndexLHS, "c[1..^1]").WithArguments("C").WithLocation(2, 5)); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : verify IOperation + src = """ +var c = new C(); +_ = c[1..^1]; + +class C +{ + public int Length => throw null; + public int this[System.Range r] => throw null; +} +"""; + + comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); + comp.VerifyEmitDiagnostics(); } [Fact] - public void ExtensionMemberLookup_PatternBased_Fixed_Static() + public void ExtensionMemberLookup_PatternBased_ListPattern_Length() { - var text = @" -unsafe class C + var src = """ +_ = new C() is [1]; + +class C { - public static void Main() - { - fixed (int* p = new Fixable()) - { - } - } + public int this[int i] => throw null; } -class Fixable { } - static class E { - extension(Fixable f) + extension(C c) { - public static ref int GetPinnableReference() => throw null; + public int Length => throw null; } } -"; +"""; - var comp = CreateCompilation(text, options: TestOptions.UnsafeReleaseExe); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : confirm when spec'ing pattern-based fixed + var comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (6,25): error CS0176: Member 'E.extension(Fixable).GetPinnableReference()' cannot be accessed with an instance reference; qualify it with a type name instead - // fixed (int* p = new Fixable()) - Diagnostic(ErrorCode.ERR_ObjectProhibited, "new Fixable()").WithArguments("E.extension(Fixable).GetPinnableReference()").WithLocation(6, 25), - // (6,25): error CS8385: The given expression cannot be used in a fixed statement - // fixed (int* p = new Fixable()) - Diagnostic(ErrorCode.ERR_ExprCannotBeFixed, "new Fixable()").WithLocation(6, 25)); - } - - [Fact] - public void ExtensionMemberLookup_PatternBased_Await_ExtensionIsCompleted() - { - var text = @" -using System; -using System.Runtime.CompilerServices; + // (1,16): error CS8985: List patterns may not be used for a value of type 'C'. No suitable 'Length' or 'Count' property was found. + // _ = new C() is [1]; + Diagnostic(ErrorCode.ERR_ListPatternRequiresLength, "[1]").WithArguments("C").WithLocation(1, 16), + // (1,16): error CS1503: Argument 1: cannot convert from 'System.Index' to 'int' + // _ = new C() is [1]; + Diagnostic(ErrorCode.ERR_BadArgType, "[1]").WithArguments("1", "System.Index", "int").WithLocation(1, 16)); -int i = await new C(); -System.Console.Write(i); + src = """ +_ = new C() is [1]; class C { - public D GetAwaiter() => new D(); + public int this[int i] => throw null; + public int Length => throw null; } +"""; + comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); + comp.VerifyEmitDiagnostics(); + } -class D : INotifyCompletion + [Fact] + public void ExtensionMemberLookup_PatternBased_ListPattern_IntIndexer() + { + var src = """ +_ = new C() is [1]; + +class C { - public int GetResult() => 42; - public void OnCompleted(Action continuation) => throw null; + public int Length => throw null; } static class E { - extension(D d) + extension(C c) { - public bool IsCompleted => true; + public int this[int i] => throw null; } } -"; - - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : confirm when spec'ing pattern-based await - var comp = CreateCompilation(text); +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (5,9): error CS0117: 'D' does not contain a definition for 'IsCompleted' - // int i = await new C(); - Diagnostic(ErrorCode.ERR_NoSuchMember, "await new C()").WithArguments("D", "IsCompleted").WithLocation(5, 9) - ); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : metadata is undone + // (1,16): error CS0021: Cannot apply indexing with [] to an expression of type 'C' + // _ = new C() is [1]; + Diagnostic(ErrorCode.ERR_BadIndexLHS, "[1]").WithArguments("C").WithLocation(1, 16)); } [Fact] - public void ExtensionMemberLookup_PatternBased_Await_ExtensionGetAwaiter() + public void ExtensionMemberLookup_PatternBased_ListPattern_RegularIndexer() { - var text = @" -using System; -using System.Runtime.CompilerServices; - -int i = await new C(); -System.Console.Write(i); + var src = """ +_ = new C() is [1]; class C { -} - -class D : INotifyCompletion -{ - public int GetResult() => 42; - public void OnCompleted(Action continuation) => throw null; - public bool IsCompleted => true; + public int Length => throw null; } static class E { extension(C c) { - public D GetAwaiter() => new D(); + public int this[System.Index i] => throw null; } } -"; +"""; - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : confirm when spec'ing pattern-based await - var comp = CreateCompilation(text); + // Tracked by https://github.com/dotnet/roslyn/issues/76130 : revisit when implementing extension indexers + var comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); + comp.VerifyEmitDiagnostics( + // (1,16): error CS0021: Cannot apply indexing with [] to an expression of type 'C' + // _ = new C() is [1]; + Diagnostic(ErrorCode.ERR_BadIndexLHS, "[1]").WithArguments("C").WithLocation(1, 16)); + + src = """ +_ = new C() is [1]; + +class C +{ + public int Length => throw null; + public int this[System.Index i] => throw null; +} +"""; + + comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics(); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : metadata is undone } [Fact] - public void ExtensionMemberLookup_PatternBased_Await_ExtensionGetResult() + public void ExtensionMemberLookup_PatternBased_SpreadPattern_Length() { - var text = @" -using System; -using System.Runtime.CompilerServices; - -int i = await new C(); -System.Console.Write(i); + var src = """ +_ = new C() is [_, .. var x]; class C { - public D GetAwaiter() => new D(); -} - -class D : INotifyCompletion -{ - public void OnCompleted(Action continuation) => throw null; - public bool IsCompleted => true; + public int this[System.Index i] => throw null; + public int Slice(int i, int j) => throw null; } static class E { - extension(D d) + extension(C c) { - public int GetResult() => 42; + public int Length => throw null; } } -"; - - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : confirm when spec'ing pattern-based await - var comp = CreateCompilation(text); +"""; - // The error is consistent with classic extension methods + var comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (5,9): error CS0117: 'D' does not contain a definition for 'GetResult' - // int i = await new C(); - Diagnostic(ErrorCode.ERR_NoSuchMember, "await new C()").WithArguments("D", "GetResult").WithLocation(5, 9) - ); + // (1,16): error CS8985: List patterns may not be used for a value of type 'C'. No suitable 'Length' or 'Count' property was found. + // _ = new C() is [_, .. var x]; + Diagnostic(ErrorCode.ERR_ListPatternRequiresLength, "[_, .. var x]").WithArguments("C").WithLocation(1, 16), + // (1,20): error CS1503: Argument 1: cannot convert from 'System.Range' to 'System.Index' + // _ = new C() is [_, .. var x]; + Diagnostic(ErrorCode.ERR_BadArgType, ".. var x").WithArguments("1", "System.Range", "System.Index").WithLocation(1, 20)); + + src = """ +_ = new C() is [_, .. var x]; + +class C +{ + public int this[System.Index i] => throw null; + public int Slice(int i, int j) => throw null; + public int Length => throw null; +} +"""; + comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); + comp.VerifyEmitDiagnostics(); } [Fact] - public void ExtensionMemberLookup_PatternBased_IndexIndexer_NoLength() + public void ExtensionMemberLookup_PatternBased_SpreadPattern_Slice() { var src = """ -var c = new C(); - -/**/ -_ = c[^1]; -/**/ +_ = new C() is [_, .. var x]; class C { - public int this[int i] - { - get { System.Console.Write("indexer "); return 0; } - } + public int this[System.Index i] => throw null; + public int Length => throw null; } static class E { extension(C c) { - public int Length - { - get { System.Console.Write("length "); return 42; } - } + public int Slice(int i, int j) => throw null; } } """; - DiagnosticDescription[] expectedDiagnostics = [ - // (4,7): error CS1503: Argument 1: cannot convert from 'System.Index' to 'int' - // _ = c[^1]; - Diagnostic(ErrorCode.ERR_BadArgType, "^1").WithArguments("1", "System.Index", "int").WithLocation(4, 7)]; var comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : revisit as part of "implicit indexer access" section - comp.VerifyEmitDiagnostics(expectedDiagnostics); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : metadata is undone - //CompileAndVerify(comp, expectedOutput: "length indexer"); - - string expectedOperationTree = """ -ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32, IsInvalid) (Syntax: '_ = c[^1]') -Left: - IDiscardOperation (Symbol: System.Int32 _) (OperationKind.Discard, Type: System.Int32) (Syntax: '_') -Right: - IInvalidOperation (OperationKind.Invalid, Type: System.Int32, IsInvalid) (Syntax: 'c[^1]') - Children(2): - ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C) (Syntax: 'c') - IUnaryOperation (UnaryOperatorKind.Hat) (OperationKind.Unary, Type: System.Index, IsInvalid) (Syntax: '^1') - Operand: - ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1') -"""; - - VerifyOperationTreeAndDiagnosticsForTest(src, expectedOperationTree, expectedDiagnostics, targetFramework: TargetFramework.Net70); + comp.VerifyEmitDiagnostics( + // (1,20): error CS1503: Argument 1: cannot convert from 'System.Range' to 'System.Index' + // _ = new C() is [_, .. var x]; + Diagnostic(ErrorCode.ERR_BadArgType, ".. var x").WithArguments("1", "System.Range", "System.Index").WithLocation(1, 20)); } [Fact] - public void ExtensionMemberLookup_PatternBased_RangeIndexer_NoMethod() + public void ExtensionMemberLookup_PatternBased_SpreadPattern_RegularIndexer() { var src = """ -var c = new C(); - -/**/ -_ = c[1..^1]; -/**/ +_ = new C() is [_, .. var x]; -class C { } +class C +{ + public int this[System.Index i] => throw null; + public int Length => throw null; +} static class E { extension(C c) { - public int Slice(int i, int j) { System.Console.Write("slice "); return 0; } - - public int Length - { - get { System.Console.Write("length "); return 42; } - } + public int this[System.Range r] => throw null; } } """; - DiagnosticDescription[] expectedDiagnostics = [ - // (4,5): error CS0021: Cannot apply indexing with [] to an expression of type 'C' - // _ = c[1..^1]; - Diagnostic(ErrorCode.ERR_BadIndexLHS, "c[1..^1]").WithArguments("C").WithLocation(4, 5)]; - var comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : revisit as part of "implicit indexer access" section - comp.VerifyEmitDiagnostics(expectedDiagnostics); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : metadata is undone - //CompileAndVerify(comp, expectedOutput: "length slice"); + comp.VerifyEmitDiagnostics( + // (1,20): error CS1503: Argument 1: cannot convert from 'System.Range' to 'System.Index' + // _ = new C() is [_, .. var x]; + Diagnostic(ErrorCode.ERR_BadArgType, ".. var x").WithArguments("1", "System.Range", "System.Index").WithLocation(1, 20)); - string expectedOperationTree = """ -ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: ?, IsInvalid) (Syntax: '_ = c[1..^1]') -Left: - IDiscardOperation (Symbol: ? _) (OperationKind.Discard, Type: ?) (Syntax: '_') -Right: - IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'c[1..^1]') - Children(2): - IRangeOperation (OperationKind.Range, Type: System.Range, IsInvalid) (Syntax: '1..^1') - LeftOperand: - IConversionOperation (TryCast: False, Unchecked) (OperatorMethod: System.Index System.Index.op_Implicit(System.Int32 value)) (OperationKind.Conversion, Type: System.Index, IsInvalid, IsImplicit) (Syntax: '1') - Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: System.Index System.Index.op_Implicit(System.Int32 value)) - Operand: - ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1') - RightOperand: - IUnaryOperation (UnaryOperatorKind.Hat) (OperationKind.Unary, Type: System.Index, IsInvalid) (Syntax: '^1') - Operand: - ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1') - ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C, IsInvalid) (Syntax: 'c') -"""; + src = """ +_ = new C() is [_, .. var x]; - VerifyOperationTreeAndDiagnosticsForTest(src, expectedOperationTree, expectedDiagnostics, targetFramework: TargetFramework.Net70); +class C +{ + public int this[System.Index i] => throw null; + public int this[System.Range r] => throw null; + public int Length => throw null; +} +"""; + comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); + comp.VerifyEmitDiagnostics(); } [Fact] - public void ExtensionMemberLookup_PatternBased_RangeIndexer_NoApplicableMethod() + public void ExtensionMemberLookup_Patterns() { var src = """ var c = new C(); +_ = c is { Property: 42 }; -/**/ -_ = c[1..^1]; -/**/ - -class C -{ - public int Slice(int notApplicable) => throw null; // not applicable -} +class C { } static class E { extension(C c) { - public int Slice(int i, int j) { System.Console.Write("slice "); return 0; } - - public int Length + public int Property { - get { System.Console.Write("length "); return 42; } + get { System.Console.Write("property"); return 42; } } } } """; + var comp = CreateCompilation(src); + CompileAndVerify(comp, expectedOutput: "property").VerifyDiagnostics(); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : revisit as part of "implicit indexer access" section - var comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); - comp.VerifyEmitDiagnostics( - // (4,5): error CS0021: Cannot apply indexing with [] to an expression of type 'C' - // _ = c[1..^1]; - Diagnostic(ErrorCode.ERR_BadIndexLHS, "c[1..^1]").WithArguments("C").WithLocation(4, 5)); + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + var nameColon = GetSyntax(tree, "Property:"); + Assert.Equal("System.Int32 E.<>E__0.Property { get; }", model.GetSymbolInfo(nameColon.Name).Symbol.ToTestDisplayString()); } [Fact] - public void ExtensionMemberLookup_Patterns() + public void ExtensionMemberLookup_Patterns_Conversion() { var src = """ var c = new C(); - _ = c is { Property: 42 }; class C { } static class E { - extension(C c) + extension(object o) { public int Property { @@ -20815,11 +22201,6 @@ public int Property """; var comp = CreateCompilation(src); CompileAndVerify(comp, expectedOutput: "property").VerifyDiagnostics(); - - var tree = comp.SyntaxTrees.First(); - var model = comp.GetSemanticModel(tree); - var nameColon = GetSyntax(tree, "Property:"); - Assert.Equal("System.Int32 E.<>E__0.Property { get; }", model.GetSymbolInfo(nameColon.Name).Symbol.ToTestDisplayString()); } [Fact] @@ -20857,6 +22238,66 @@ static class E2 Assert.Equal("System.Int32 E2.<>E__0.Property2 { get; }", model.GetSymbolInfo(expressionColon.Expression).Symbol.ToTestDisplayString()); } + [Fact] + public void ExtensionMemberLookup_Patterns_ExtendedPropertyPattern_Conversion() + { + var src = """ +var c = new C(); + +_ = c is { Property.Property2: 43 }; + +class C { } + +static class E1 +{ + extension(object o) + { + public int Property { get { System.Console.Write("property "); return 42; } } + } +} + +static class E2 +{ + extension(int i) + { + public int Property2 { get { System.Console.Write("property2"); return 43; } } + } +} +"""; + var comp = CreateCompilation(src); + CompileAndVerify(comp, expectedOutput: "property property2").VerifyDiagnostics(); + } + + [Fact] + public void ExtensionMemberLookup_Patterns_ExtendedPropertyPattern_Conversion_02() + { + var src = """ +var c = new C(); + +_ = c is { Property.Property2: 43 }; + +class C { } + +static class E1 +{ + extension(C c) + { + public C Property { get { System.Console.Write("property "); return c; } } + } +} + +static class E2 +{ + extension(object o) + { + public int Property2 { get { System.Console.Write("property2"); return 43; } } + } +} +"""; + var comp = CreateCompilation(src); + CompileAndVerify(comp, expectedOutput: "property property2").VerifyDiagnostics(); + } + [Fact] public void ExtensionMemberLookup_Patterns_ListPattern_NoInstanceLength() { @@ -20884,23 +22325,19 @@ public int Length """; var comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : confirm that we want extensions to contribute to list-patterns + // Tracked by https://github.com/dotnet/roslyn/issues/76130 : confirm whether we want extension Length/Count to contribute to list-patterns comp.VerifyEmitDiagnostics( // (1,33): error CS8985: List patterns may not be used for a value of type 'C'. No suitable 'Length' or 'Count' property was found. // System.Console.Write(new C() is ["hi"]); Diagnostic(ErrorCode.ERR_ListPatternRequiresLength, @"[""hi""]").WithArguments("C").WithLocation(1, 33) ); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : metadata is undone - //CompileAndVerify(comp, expectedOutput: "length indexer"); } - [ConditionalFact(typeof(NoUsedAssembliesValidation))] // Tracked by https://github.com/dotnet/roslyn/issues/76130 : metadata is undone + [Fact] public void ExtensionMemberLookup_ObjectInitializer() { var src = """ -/**/ _ = new C() { Property = 42 }; -/**/ class C { } @@ -20914,9 +22351,7 @@ static class E """; var comp = CreateCompilation(src); - comp.VerifyDiagnostics(); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : metadata is undone - //CompileAndVerify(comp, expectedOutput: "property"); + CompileAndVerify(comp, expectedOutput: "property").VerifyDiagnostics(); var tree = comp.SyntaxTrees.First(); var model = comp.GetSemanticModel(tree); @@ -20924,7 +22359,28 @@ static class E Assert.Equal("System.Int32 E.<>E__0.Property { set; }", model.GetSymbolInfo(assignment.Left).Symbol.ToTestDisplayString()); } - [ConditionalFact(typeof(NoUsedAssembliesValidation))] // Tracked by https://github.com/dotnet/roslyn/issues/76130 : metadata is undone + [Fact] + public void ExtensionMemberLookup_ObjectInitializer_Conversion() + { + var src = """ +_ = new C() { Property = 42 }; + +class C { } + +static class E +{ + extension(object o) + { + public int Property { set { System.Console.Write("property"); } } + } +} +"""; + + var comp = CreateCompilation(src); + CompileAndVerify(comp, expectedOutput: "property").VerifyDiagnostics(); + } + + [Fact] public void ExtensionMemberLookup_With() { var src = """ @@ -20944,10 +22400,7 @@ static class E """; var comp = CreateCompilation(src); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : need to decide whether extensions apply here - comp.VerifyDiagnostics(); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : metadata is undone - //CompileAndVerify(comp, expectedOutput: "property"); + CompileAndVerify(comp, expectedOutput: "property").VerifyDiagnostics(); var tree = comp.SyntaxTrees.First(); var model = comp.GetSemanticModel(tree); @@ -20956,7 +22409,7 @@ static class E } [Fact] - public void ExtensionMemberLookup_CollectionInitializer_NoMethod() + public void ExtensionMemberLookup_CollectionInitializer() { var src = """ using System.Collections; @@ -20982,7 +22435,6 @@ static class E """; var comp = CreateCompilation(src); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : confirm when spec'ing pattern-based collection initializer CompileAndVerify(comp, expectedOutput: "add").VerifyDiagnostics(); string expectedOperationTree = """ @@ -21009,6 +22461,62 @@ static class E VerifyOperationTreeAndDiagnosticsForTest(src, expectedOperationTree, expectedDiagnostics); } + [Fact] + public void ExtensionMemberLookup_CollectionInitializer_Conversion() + { + var src = """ +using System.Collections; +using System.Collections.Generic; + +/**/ +_ = new C() { 42 }; +/**/ + +class C : IEnumerable, IEnumerable +{ + IEnumerator IEnumerable.GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; +} + +static class E +{ + extension(object o) + { + public void Add(int i) { System.Console.Write("add"); } + } +} +"""; + + var comp = CreateCompilation(src); + CompileAndVerify(comp, expectedOutput: "add").VerifyDiagnostics(); + + string expectedOperationTree = """ +ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: C) (Syntax: '_ = new C() { 42 }') +Left: + IDiscardOperation (Symbol: C _) (OperationKind.Discard, Type: C) (Syntax: '_') +Right: + IObjectCreationOperation (Constructor: C..ctor()) (OperationKind.ObjectCreation, Type: C) (Syntax: 'new C() { 42 }') + Arguments(0) + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: C) (Syntax: '{ 42 }') + Initializers(1): + IInvocationOperation ( void E.<>E__0.Add(System.Int32 i)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: '42') + Instance Receiver: + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Object, IsImplicit) (Syntax: 'C') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) + Operand: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'C') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: i) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: '42') + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 42) (Syntax: '42') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) +"""; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(src, expectedOperationTree, expectedDiagnostics); + } + [Fact] public void ExtensionMemberLookup_CollectionInitializer_NoApplicableMethod() { @@ -21042,7 +22550,6 @@ static class E } """; - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : confirm when spec'ing pattern-based collection initializer var comp = CreateCompilation(src, options: TestOptions.DebugExe); CompileAndVerify(comp, expectedOutput: "add").VerifyDiagnostics(); @@ -21150,7 +22657,6 @@ static class E } """; - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : confirm when spec'ing pattern-based collection initializer // Tracked by https://github.com/dotnet/roslyn/issues/76130 : expression trees var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90); comp.VerifyEmitDiagnostics( @@ -21160,6 +22666,104 @@ static class E ); } + [Fact] + public void ResolveAll_CollectionInitializer_DelegateTypeProperty() + { + var source = """ +using System.Collections; +using System.Collections.Generic; + +MyCollection c = new MyCollection() { 42 }; + +static class E +{ + extension(MyCollection c) + { + public System.Action Add => (int i) => { }; + } +} + +public class MyCollection : IEnumerable +{ + IEnumerator IEnumerable.GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; +} +"""; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (4,39): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) + // MyCollection c = new MyCollection() { 42 }; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "42").WithArguments("MyCollection", "Add").WithLocation(4, 39)); + + source = """ +using System.Collections; +using System.Collections.Generic; + +MyCollection c = new MyCollection() { 42 }; + +public class MyCollection : IEnumerable +{ + IEnumerator IEnumerable.GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; + public System.Action Add => (int i) => { }; +} +"""; + comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (4,39): error CS0118: 'Add' is a property but is used like a method + // MyCollection c = new MyCollection() { 42 }; + Diagnostic(ErrorCode.ERR_BadSKknown, "42").WithArguments("Add", "property", "method").WithLocation(4, 39)); + } + + [Fact] + public void ResolveAll_CollectionInitializer_DynamicTypeProperty() + { + var source = """ +using System.Collections; +using System.Collections.Generic; + +MyCollection c = new MyCollection() { 42 }; + +static class E +{ + extension(MyCollection c) + { + public dynamic Add => throw null; + } +} + +public class MyCollection : IEnumerable +{ + IEnumerator IEnumerable.GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; +} +"""; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (4,39): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) + // MyCollection c = new MyCollection() { 42 }; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "42").WithArguments("MyCollection", "Add").WithLocation(4, 39)); + + source = """ +using System.Collections; +using System.Collections.Generic; + +MyCollection c = new MyCollection() { 42 }; + +public class MyCollection : IEnumerable +{ + IEnumerator IEnumerable.GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; + public dynamic Add => throw null; +} +"""; + comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (4,39): error CS0118: 'Add' is a property but is used like a method + // MyCollection c = new MyCollection() { 42 }; + Diagnostic(ErrorCode.ERR_BadSKknown, "42").WithArguments("Add", "property", "method").WithLocation(4, 39)); + } + [Fact] public void ExtensionMemberLookup_Query_NoMethod() { @@ -21414,7 +23018,7 @@ .locals init (delegate* V_0, //ptr IL_0011: calli "delegate*" IL_0016: nop IL_0017: ret -} +} """); var tree = comp.SyntaxTrees.First(); @@ -21724,7 +23328,6 @@ static class E } } """; - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : should we get an error as with methods? var comp = CreateCompilation(src); CompileAndVerify(comp, expectedOutput: "Property").VerifyDiagnostics(); @@ -21734,6 +23337,32 @@ static class E Assert.Equal("System.String E.<>E__0.Property { get; }", model.GetSymbolInfo(memberAccess).Symbol.ToTestDisplayString()); } + [Fact(Skip = "Assertion in NullableWalker.AsMemberOfType")] // Tracked by https://github.com/dotnet/roslyn/issues/76130 : Nullability analysis of properties + public void Nameof_Instance_Property_Generic_01() + { + var src = """ +I i = null; +System.Console.Write(nameof(i.Property)); + +interface I { } + +static class E +{ + extension(I i) + { + public string Property => throw null; + } +} +"""; + var comp = CreateCompilation(src); + CompileAndVerify(comp, expectedOutput: "Property").VerifyDiagnostics(); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var memberAccess = GetSyntax(tree, "i.Property"); + Assert.Equal("System.String E.<>E__0.Property { get; }", model.GetSymbolInfo(memberAccess).Symbol.ToTestDisplayString()); + } + [Fact] public void Nameof_Static_Property_Generic_01() { @@ -21789,6 +23418,31 @@ static class E Assert.Equal("System.String E.<>E__0.Property { get; }", model.GetSymbolInfo(memberAccess).Symbol.ToTestDisplayString()); } + [Fact] + public void Nameof_Static_Property_Generic_03() + { + var src = """ +System.Console.Write(nameof(I.Property)); + +interface I { } + +static class E +{ + extension(I i) + { + public static string Property => throw null; + } +} +"""; + var comp = CreateCompilation(src); + CompileAndVerify(comp, expectedOutput: "Property").VerifyDiagnostics(); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var memberAccess = GetSyntax(tree, "I.Property"); + Assert.Equal("System.String E.<>E__0.Property { get; }", model.GetSymbolInfo(memberAccess).Symbol.ToTestDisplayString()); + } + [Fact] public void Nameof_Overloads_01() { @@ -22782,14 +24436,14 @@ static int T() } } -class C1 {} -class C2 {} -class C3 {} -class C4 {} -class C5 {} -class C6 {} -class C7 {} -class C8 {} +class C1 {} +class C2 {} +class C3 {} +class C4 {} +class C5 {} +class C6 {} +class C7 {} +class C8 {} """; var comp = CreateCompilation(src); comp.VerifyEmitDiagnostics( @@ -23381,7 +25035,7 @@ static int M(T[] ts) { return T(ts); } - + static int T(U[] ts) => 0; } "; @@ -23419,7 +25073,7 @@ static int M(int P) { return P(P); } - + static int P(int P) => 0; } "; @@ -26574,8 +28228,8 @@ public void MethodInvocation_RemoveStaticInstanceMismatches_ColorColor_01() Color.M2(null); -class Color -{ +class Color +{ public static void M2(Color Color) { Color.M(); @@ -26624,8 +28278,8 @@ public void MethodInvocation_RemoveStaticInstanceMismatches_ColorColor_02() Color.M2(new Color()); -class Color -{ +class Color +{ public static void M2(Color Color) { Color.M(); @@ -27314,7 +28968,7 @@ public void MethodInvocation_ReceiverConversion_ColorColor() Color.M2(new Color(42)); class Color(int i) : Base(i) -{ +{ public static void M2(Color Color) { Color.M(); @@ -27372,7 +29026,7 @@ public void PropertyAccess_ReceiverConversion_ColorColor() Color.M2(new Color(42)); class Color(int i) : Base(i) -{ +{ public static void M2(Color Color) { _ = Color.P; @@ -27477,7 +29131,7 @@ static void Main() { dynamic d = 1; var result = new C().Test("name", d); - System.Console.Write(result); + System.Console.Write(result); } } @@ -27880,8 +29534,8 @@ .locals init (short V_0, //x C.M(x.ToString()); [ComImport, Guid("1234C65D-1234-447A-B786-64682CBEF136")] -class C -{ +class C +{ public extern static void M(ref string p); } """; @@ -27997,6 +29651,65 @@ static class E Assert.Equal("void E.<>E__0.M(System.String? t2)", model.GetSymbolInfo(memberAccess).Symbol.ToTestDisplayString()); } + [Fact] + public void Nullability_Method_03() + { + var src = """ +#nullable enable + +object oNotNull = new object(); + +oNotNull.M(out object x1, null).ToString(); // 1 +oNotNull.M(out object x2, oNotNull).ToString(); + +x1.ToString(); +x2.ToString(); + +static class E +{ + extension(T t1) + { + public T M(out U u, T t2) => throw null!; + } +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (5,1): warning CS8602: Dereference of a possibly null reference. + // oNotNull.M(out object x1, null).ToString(); // 1 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "oNotNull.M(out object x1, null)").WithLocation(5, 1)); + } + + [Fact] + public void Nullability_Method_04() + { + var src = """ +#nullable enable + +object oNotNull = new object(); + +"".M(oNotNull, null).ToString(); // 1 +"".M(null, oNotNull).ToString(); // 2 +"".M(oNotNull, oNotNull).ToString(); + +static class E +{ + extension(T t) + { + public U M(U u1, U u2) => throw null!; + } +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (5,1): warning CS8602: Dereference of a possibly null reference. + // "".M(oNotNull, null).ToString(); // 1 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, @""""".M(oNotNull, null)").WithLocation(5, 1), + // (6,1): warning CS8602: Dereference of a possibly null reference. + // "".M(null, oNotNull).ToString(); // 2 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, @""""".M(null, oNotNull)").WithLocation(6, 1)); + } + [Fact] public void PropertyAccess_RemoveWorseMembers_01() { @@ -28822,20 +30535,20 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends System.Object { // Methods - .method private hidebysig specialname static void '$' ( int32[] i ) cil managed + .method private hidebysig specialname static void '$' ( int32[] i ) cil managed { .param [1] .custom instance void [mscorlib]System.ParamArrayAttribute::.ctor() = ( 01 00 00 00) IL_0000: ret } - .method public hidebysig instance void M () cil managed + .method public hidebysig instance void M () cil managed { IL_0000: ldnull IL_0001: throw } } - .method public hidebysig static void 'M' ( int32[] i ) cil managed + .method public hidebysig static void 'M' ( int32[] i ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 @@ -28892,14 +30605,14 @@ 01 00 00 00 .class nested public auto ansi sealed beforefieldinit '<>E__0' extends System.Object { - .method private hidebysig specialname static void '$' ( int32[] i ) cil managed + .method private hidebysig specialname static void '$' ( int32[] i ) cil managed { .param [1] .custom instance void [mscorlib]System.ParamArrayAttribute::.ctor() = ( 01 00 00 00) IL_0000: ret } - .method public hidebysig specialname instance int32 get_P () cil managed + .method public hidebysig specialname instance int32 get_P () cil managed { IL_0000: ldnull IL_0001: throw @@ -28909,7 +30622,7 @@ .property instance int32 P() .get instance int32 E/'<>E__0'::get_P() } } - .method public hidebysig static int32 'get_P' ( int32[] i ) cil managed + .method public hidebysig static int32 'get_P' ( int32[] i ) cil managed { .param [1] .custom instance void [mscorlib]System.ParamArrayAttribute::.ctor() = ( 01 00 00 00) @@ -31905,7 +33618,7 @@ public static class Extensions public C.Enumerator GetEnumerator(int x = 1) => new C.Enumerator(x); } }"; - var verifier = CompileAndVerify(source, expectedOutput: "23", parseOptions: TestOptions.RegularPreview.WithFeature("run-nullable-analysis", "never")); // Tracked by https://github.com/dotnet/roslyn/issues/76130: Nullable analysis asserts + var verifier = CompileAndVerify(source, expectedOutput: "23", parseOptions: TestOptions.RegularPreview.WithFeature("run-nullable-analysis", "never")); // Tracked by https://github.com/dotnet/roslyn/issues/76130: Nullable analysis asserts VerifyFlowGraphAndDiagnosticsForTest((CSharpCompilation)verifier.Compilation, @" @@ -32018,6 +33731,248 @@ public static class Extensions // foreach (var i in new C()) Diagnostic(ErrorCode.ERR_BadGetEnumerator, "new C()").WithArguments("C.Enumerator", "C.GetEnumerator()").WithLocation(7, 27) ); + + source = """ +using System; +public class C +{ + public static void Main() + { + foreach (var i in new C()) + { + Console.Write(i); + } + } + public sealed class Enumerator + { + public int Current { get; private set; } + } + + public C.Enumerator GetEnumerator() => new C.Enumerator(); +} +public static class Extensions +{ + public static bool MoveNext(this C.Enumerator e) => false; +} +"""; + CreateCompilation(source) + .VerifyDiagnostics( + // (6,27): error CS0117: 'C.Enumerator' does not contain a definition for 'MoveNext' + // foreach (var i in new C()) + Diagnostic(ErrorCode.ERR_NoSuchMember, "new C()").WithArguments("C.Enumerator", "MoveNext").WithLocation(6, 27), + // (6,27): error CS0202: foreach requires that the return type 'C.Enumerator' of 'C.GetEnumerator()' must have a suitable public 'MoveNext' method and public 'Current' property + // foreach (var i in new C()) + Diagnostic(ErrorCode.ERR_BadGetEnumerator, "new C()").WithArguments("C.Enumerator", "C.GetEnumerator()").WithLocation(6, 27) + ); + } + + [Fact] + public void TestMoveNextPatternViaExtensions_DelegateTypeProperty() + { + var src = """ +using System; + +foreach (var i in new C()) +{ + Console.Write(i); +} + +public class C +{ + public sealed class Enumerator + { + public int Current { get; private set; } + } + + public C.Enumerator GetEnumerator() => new C.Enumerator(); +} + +public static class Extensions +{ + extension(C.Enumerator e) + { + public System.Func MoveNext => throw null; + } +} +"""; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (3,19): error CS0117: 'C.Enumerator' does not contain a definition for 'MoveNext' + // foreach (var i in new C()) + Diagnostic(ErrorCode.ERR_NoSuchMember, "new C()").WithArguments("C.Enumerator", "MoveNext").WithLocation(3, 19), + // (3,19): error CS0202: foreach requires that the return type 'C.Enumerator' of 'C.GetEnumerator()' must have a suitable public 'MoveNext' method and public 'Current' property + // foreach (var i in new C()) + Diagnostic(ErrorCode.ERR_BadGetEnumerator, "new C()").WithArguments("C.Enumerator", "C.GetEnumerator()").WithLocation(3, 19)); + + src = """ +using System; + +foreach (var i in new C()) +{ + Console.Write(i); +} + +public class C +{ + public sealed class Enumerator + { + public int Current { get; private set; } + public System.Func MoveNext => throw null; + } + + public C.Enumerator GetEnumerator() => new C.Enumerator(); +} +"""; + comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (3,19): error CS0202: foreach requires that the return type 'C.Enumerator' of 'C.GetEnumerator()' must have a suitable public 'MoveNext' method and public 'Current' property + // foreach (var i in new C()) + Diagnostic(ErrorCode.ERR_BadGetEnumerator, "new C()").WithArguments("C.Enumerator", "C.GetEnumerator()").WithLocation(3, 19)); + } + + [Fact] + public void TestMoveNextPatternViaExtensions_DynamicTypeProperty() + { + var src = """ +using System; + +foreach (var i in new C()) +{ + Console.Write(i); +} + +public class C +{ + public sealed class Enumerator + { + public int Current { get; private set; } + } + + public C.Enumerator GetEnumerator() => new C.Enumerator(); +} + +public static class Extensions +{ + extension(C.Enumerator e) + { + public System.Func MoveNext => throw null; + } +} +"""; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (3,19): error CS0117: 'C.Enumerator' does not contain a definition for 'MoveNext' + // foreach (var i in new C()) + Diagnostic(ErrorCode.ERR_NoSuchMember, "new C()").WithArguments("C.Enumerator", "MoveNext").WithLocation(3, 19), + // (3,19): error CS0202: foreach requires that the return type 'C.Enumerator' of 'C.GetEnumerator()' must have a suitable public 'MoveNext' method and public 'Current' property + // foreach (var i in new C()) + Diagnostic(ErrorCode.ERR_BadGetEnumerator, "new C()").WithArguments("C.Enumerator", "C.GetEnumerator()").WithLocation(3, 19)); + + src = """ +using System; + +foreach (var i in new C()) +{ + Console.Write(i); +} + +public class C +{ + public sealed class Enumerator + { + public int Current { get; private set; } + public System.Func MoveNext => throw null; + } + + public C.Enumerator GetEnumerator() => new C.Enumerator(); +} +"""; + comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (3,19): error CS0202: foreach requires that the return type 'C.Enumerator' of 'C.GetEnumerator()' must have a suitable public 'MoveNext' method and public 'Current' property + // foreach (var i in new C()) + Diagnostic(ErrorCode.ERR_BadGetEnumerator, "new C()").WithArguments("C.Enumerator", "C.GetEnumerator()").WithLocation(3, 19)); + } + + [Fact] + public void TestMoveNextAsyncPatternViaExtensions_01() + { + var src = """ +await foreach (var i in new C()) +{ +} + +public class C +{ + public sealed class Enumerator + { + public int Current { get; private set; } + } + + public C.Enumerator GetAsyncEnumerator() => new C.Enumerator(); +} + +public static class E +{ + extension(C.Enumerator e) + { + public System.Threading.Tasks.Task MoveNextAsync() => throw null; + } +} +"""; + CreateCompilation(src).VerifyEmitDiagnostics( + // (1,25): error CS0117: 'C.Enumerator' does not contain a definition for 'MoveNextAsync' + // await foreach (var i in new C()) + Diagnostic(ErrorCode.ERR_NoSuchMember, "new C()").WithArguments("C.Enumerator", "MoveNextAsync").WithLocation(1, 25), + // (1,25): error CS8412: Asynchronous foreach requires that the return type 'C.Enumerator' of 'C.GetAsyncEnumerator()' must have a suitable public 'MoveNextAsync' method and public 'Current' property + // await foreach (var i in new C()) + Diagnostic(ErrorCode.ERR_BadGetAsyncEnumerator, "new C()").WithArguments("C.Enumerator", "C.GetAsyncEnumerator()").WithLocation(1, 25)); + + src = """ +await foreach (var i in new C()) +{ +} + +public class C +{ + public sealed class Enumerator + { + public int Current { get; private set; } + } + + public C.Enumerator GetAsyncEnumerator() => new C.Enumerator(); +} + +public static class E +{ + public static System.Threading.Tasks.Task MoveNextAsync(this C.Enumerator e) => throw null; +} +"""; + CreateCompilation(src).VerifyEmitDiagnostics( + // (1,25): error CS0117: 'C.Enumerator' does not contain a definition for 'MoveNextAsync' + // await foreach (var i in new C()) + Diagnostic(ErrorCode.ERR_NoSuchMember, "new C()").WithArguments("C.Enumerator", "MoveNextAsync").WithLocation(1, 25), + // (1,25): error CS8412: Asynchronous foreach requires that the return type 'C.Enumerator' of 'C.GetAsyncEnumerator()' must have a suitable public 'MoveNextAsync' method and public 'Current' property + // await foreach (var i in new C()) + Diagnostic(ErrorCode.ERR_BadGetAsyncEnumerator, "new C()").WithArguments("C.Enumerator", "C.GetAsyncEnumerator()").WithLocation(1, 25)); + + src = """ +await foreach (var i in new C()) +{ +} + +public class C +{ + public sealed class Enumerator + { + public int Current { get; private set; } + public System.Threading.Tasks.Task MoveNextAsync() => throw null; + } + + public C.Enumerator GetAsyncEnumerator() => new C.Enumerator(); +} +"""; + CreateCompilation(src).VerifyEmitDiagnostics(); } [Fact] @@ -33053,27 +35008,27 @@ extends [mscorlib]System.Object .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { - .method private hidebysig specialname static void '$' ( int32 '' ) cil managed + .method private hidebysig specialname static void '$' ( int32 '' ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) IL_0000: ret } - .method public hidebysig instance void M3 () cil managed + .method public hidebysig instance void M3 () cil managed { IL_0000: ldnull IL_0001: throw } - .method public hidebysig static void M4 () cil managed + .method public hidebysig static void M4 () cil managed { IL_0000: ldnull IL_0001: throw } - .method public hidebysig specialname instance int32 get_P3 () cil managed + .method public hidebysig specialname instance int32 get_P3 () cil managed { IL_0000: ldnull IL_0001: throw } - .method public hidebysig specialname static int32 get_P4 () cil managed + .method public hidebysig specialname static int32 get_P4 () cil managed { IL_0000: ldnull IL_0001: throw @@ -33087,21 +35042,21 @@ .property int32 P4() .get int32 E/'<>E__0'::get_P4() } } - .method public hidebysig static void M3 ( int32 '' ) cil managed + .method public hidebysig static void M3 ( int32 '' ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) IL_0000: ret } - .method public hidebysig static void M4 () cil managed + .method public hidebysig static void M4 () cil managed { IL_0000: ret } - .method public hidebysig static int32 get_P3 ( int32 '' ) cil managed + .method public hidebysig static int32 get_P3 ( int32 '' ) cil managed { IL_0000: ldc.i4.0 IL_0001: ret } - .method public hidebysig static int32 get_P4 () cil managed + .method public hidebysig static int32 get_P4 () cil managed { IL_0000: ldc.i4.0 IL_0001: ret @@ -35139,6 +37094,243 @@ static class E Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "oNull").WithArguments("E.extension(T)", "T", "object?").WithLocation(4, 16)); } + [Fact] + public void Nullability_Deconstruct_05() + { + var src = """ +#nullable enable + +object o = new object(); +var (x1, x2) = o; +x1.ToString(); // 1 +x2.ToString(); + +var (y1, y2, y3) = o; +y1.ToString(); // 2 +y2.ToString(); + +static class E +{ + extension(object o) + { + public void Deconstruct(out object? o1, out object o2) => throw null!; + } + + public static void Deconstruct(this object o, out object? o1, out object o2, out int i3) => throw null!; +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (5,1): warning CS8602: Dereference of a possibly null reference. + // x1.ToString(); // 1 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(5, 1), + // (9,1): warning CS8602: Dereference of a possibly null reference. + // y1.ToString(); // 2 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y1").WithLocation(9, 1)); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/78022")] + public void Nullability_PositionalPattern_01() + { + var src = """ +#nullable enable + +object? oNull = null; +if (oNull is var (x1, x2)) +{ + x1.ToString(); +} + +object oNotNull = new object(); +if (oNotNull is var (y1, y2)) +{ + y1.ToString(); +} + +if (oNull is var (z1, z2, z3)) +{ + z1.ToString(); +} + +static class E +{ + extension(T t) + { + public void Deconstruct(out T t1, out T t2) => throw null!; + } + + public static void Deconstruct(this T t, out T t1, out T t2, out T t3) => throw null!; +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics(); + + // Tracked by https://github.com/dotnet/roslyn/issues/78022 : verify nullability in the semantic model, possibly in IOperation + } + + [Fact] + public void Nullability_PositionalPattern_02() + { + var src = """ +#nullable enable + +object? oNull = null; +if (oNull is var (x1, x2)) +{ +} + +object oNotNull = new object(); +if (oNotNull is var (y1, y2)) +{ +} + +object? oNull2 = null; +if (oNull2 is var (z1, z2, z3)) +{ +} + +if (oNotNull is var (t1, t2, t3)) +{ +} + + +static class E +{ + extension(object o) + { + public void Deconstruct(out int i1, out int i2) => throw null!; + } + + public static void Deconstruct(this object o, out int i1, out int i2, out int i3) => throw null!; +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics(); + // Tracked by https://github.com/dotnet/roslyn/issues/78022 : verify nullability in the semantic model, possibly in IOperation + } + + [Fact] + public void Nullability_PositionalPattern_03() + { + var src = """ +#nullable enable + +(object?, object?) oNull = default; +if (oNull is var ((x1, x2), _)) +{ +} + +(object, object) oNotNull = (new object(), new object()); +if (oNotNull is var ((y1, y2), _)) +{ +} + +(object?, object?) oNull2 = default; +if (oNull2 is var ((z1, z2, z3), _)) +{ +} + +if (oNotNull is var ((t1, t2, t3), _)) +{ +} + +static class E +{ + extension(object o) + { + public void Deconstruct(out int i1, out int i2) => throw null!; + } + public static void Deconstruct(this object o, out int i1, out int i2, out int i3) => throw null!; +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics(); + } + + [Fact] + public void Nullability_PositionalPattern_04() + { + var src = """ +#nullable enable + +object? oNull = default; +if (oNull is var (x1, x2)) +{ +} +else +{ + System.Console.Write("skipped "); +} + +object oNotNull = new object(); +if (oNotNull is var (y1, y2)) +{ +} + +object? oNull2 = default; +if (oNull2 is var (z1, z2, z3)) +{ +} +else +{ + System.Console.Write(" skipped "); +} + +if (oNotNull is var (t1, t2, t3)) +{ +} + +static class E +{ + extension(T t) where T : notnull + { + public void Deconstruct(out int i1, out int i2) { System.Console.Write(t is not null); i1 = i2 = 0; } + } + public static void Deconstruct(this T t, out int i1, out int i2, out int i3) where T : notnull { System.Console.Write(t is not null); i1 = i2 = i3 = 0; } +} +"""; + var comp = CreateCompilation(src); + CompileAndVerify(comp, expectedOutput: "skipped True skipped True").VerifyDiagnostics(); + } + + [Fact] + public void Nullability_PositionalPattern_05() + { + var src = """ +#nullable enable + +object o = new object(); +if (o is var (x1, x2)) +{ + x1.ToString(); // 1 + x2.ToString(); +} + +if (o is var (y1, y2, y3)) +{ + y1.ToString(); // 2 + y2.ToString(); +} + +static class E +{ + extension(object o) + { + public void Deconstruct(out object? o1, out object o2) => throw null!; + } + public static void Deconstruct(this object o, out object? o1, out object o2, out int i3) => throw null!; +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (6,5): warning CS8602: Dereference of a possibly null reference. + // x1.ToString(); // 1 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(6, 5), + // (12,5): warning CS8602: Dereference of a possibly null reference. + // y1.ToString(); // 2 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y1").WithLocation(12, 5)); + } + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/78022")] public void Nullability_ForeachDeconstruct_01() { @@ -35279,6 +37471,45 @@ static class E Diagnostic(ErrorCode.WRN_NullReferenceArgument, "oNull").WithArguments("o", "extension(object)").WithLocation(5, 23)); } + [Fact] + public void Nullability_ForeachDeconstruct_05() + { + var src = """ +#nullable enable + +object[] o = new object[] { }; +foreach (var (x1, x2) in o) +{ + x1.ToString(); // 1 + x2.ToString(); +} + +foreach (var (y1, y2, y3) in o) +{ + y1.ToString(); // 2 + y2.ToString(); +} + +static class E +{ + extension(object o) + { + public void Deconstruct(out object? o1, out object o2) => throw null!; + } + + public static void Deconstruct(this object o, out object? o1, out object o2, out int i3) => throw null!; +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (6,5): warning CS8602: Dereference of a possibly null reference. + // x1.ToString(); // 1 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(6, 5), + // (12,5): warning CS8602: Dereference of a possibly null reference. + // y1.ToString(); // 2 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y1").WithLocation(12, 5)); + } + [Fact] public void Nullability_Parameter_01() { @@ -35451,7 +37682,7 @@ static class E { extension([System.Diagnostics.CodeAnalysis.DisallowNull] object? o) { - public void M() + public void M() { o.ToString(); } @@ -35481,7 +37712,7 @@ static class E { extension([System.Diagnostics.CodeAnalysis.DisallowNull] int? i) { - public void M() + public void M() { i.Value.ToString(); } @@ -35511,7 +37742,7 @@ static class E { extension([System.Diagnostics.CodeAnalysis.AllowNull] object o) { - public void M() + public void M() { o.ToString(); } @@ -35543,7 +37774,7 @@ static class E { extension([System.Diagnostics.CodeAnalysis.NotNull] object? o) { - public void M() + public void M() { } // 1 } @@ -35581,11 +37812,11 @@ static class E { extension([System.Diagnostics.CodeAnalysis.NotNull] ref int? o) { - public void M() + public void M() { } // 1 - public void M3() + public void M3() { o = 42; } @@ -35624,7 +37855,7 @@ static class E { extension([System.Diagnostics.CodeAnalysis.NotNull] ref int? o) { - public void M(bool b = false) + public void M(bool b = false) { if (b) return; // 1 @@ -36005,6 +38236,70 @@ static class E // (13,73): error CS0103: The name 'P' does not exist in the current context // [System.Diagnostics.CodeAnalysis.MemberNotNullWhen(true, nameof(P))] Diagnostic(ErrorCode.ERR_NameNotInContext, "P").WithArguments("P").WithLocation(13, 73)); + + src = """ +#nullable enable + +object o = new object(); +if (o.M()) + o.P.ToString(); // 1 +else + o.P.ToString(); // 2 + +static class E +{ + extension(object o) + { + [System.Diagnostics.CodeAnalysis.MemberNotNullWhen(true, nameof(object.P))] + public bool M() => throw null!; + + public object? P => null; + } +} +"""; + comp = CreateCompilation(src, targetFramework: TargetFramework.Net90); + comp.VerifyEmitDiagnostics( + // (5,5): warning CS8602: Dereference of a possibly null reference. + // o.P.ToString(); // 1 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o.P").WithLocation(5, 5), + // (7,5): warning CS8602: Dereference of a possibly null reference. + // o.P.ToString(); // 2 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o.P").WithLocation(7, 5), + // (13,73): error CS9286: 'object' does not contain a definition for 'P' and no accessible extension member 'P' for receiver of type 'object' could be found (are you missing a using directive or an assembly reference?) + // [System.Diagnostics.CodeAnalysis.MemberNotNullWhen(true, nameof(object.P))] + Diagnostic(ErrorCode.ERR_ExtensionResolutionFailed, "object.P").WithArguments("object", "P").WithLocation(13, 73)); + + src = """ +#nullable enable + +object o = new object(); +if (o.M()) + o.P.ToString(); // 1 +else + o.P.ToString(); // 2 + +static class E +{ + extension(object o) + { + [System.Diagnostics.CodeAnalysis.MemberNotNullWhen(true, nameof(new object().P))] + public bool M() => throw null!; + + public object? P => null; + } +} +"""; + comp = CreateCompilation(src, targetFramework: TargetFramework.Net90); + comp.VerifyEmitDiagnostics( + // (5,5): warning CS8602: Dereference of a possibly null reference. + // o.P.ToString(); // 1 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o.P").WithLocation(5, 5), + // (7,5): warning CS8602: Dereference of a possibly null reference. + // o.P.ToString(); // 2 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o.P").WithLocation(7, 5), + // (13,73): error CS8082: Sub-expression cannot be used in an argument to nameof. + // [System.Diagnostics.CodeAnalysis.MemberNotNullWhen(true, nameof(new object().P))] + Diagnostic(ErrorCode.ERR_SubexpressionNotInNameof, "new object()").WithLocation(13, 73)); } [Fact] @@ -36233,6 +38528,470 @@ static class E Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("o", "void C.M(object o)").WithLocation(4, 34)); } + [Fact] + public void Nullability_ForEach_01() + { + var src = """ +#nullable enable +using System.Collections.Generic; + +object? oNull = null; +foreach (var x in oNull) { x.ToString(); } + +object? oNotNull = new object(); +foreach (var y in oNotNull) { y.ToString(); } + +static class E +{ + extension(T t) + { + public IEnumerator GetEnumerator() + { + yield return t; + } + } +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (5,19): warning CS8602: Dereference of a possibly null reference. + // foreach (var x in oNull) { x.ToString(); } + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "oNull").WithLocation(5, 19)); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var loop = tree.GetRoot().DescendantNodes().OfType().First(); + // Tracked by https://github.com/dotnet/roslyn/issues/78022 : incorrect nullability + Assert.Equal("System.Collections.Generic.IEnumerator! E.extension(System.Object).GetEnumerator()", + model.GetForEachStatementInfo(loop).GetEnumeratorMethod.ToTestDisplayString(includeNonNullable: true)); + + src = """ +#nullable enable +using System.Collections.Generic; + +object? oNull = null; +foreach (var x in oNull) { x.ToString(); } + +object? oNotNull = new object(); +foreach (var y in oNotNull) { y.ToString(); } + +static class E +{ + public static IEnumerator GetEnumerator(this T t) + { + yield return t; + } +} +"""; + comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (5,28): warning CS8602: Dereference of a possibly null reference. + // foreach (var x in oNull) { x.ToString(); } + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(5, 28)); + + // Tracked by https://github.com/dotnet/roslyn/issues/78022 : incorrect nullability + tree = comp.SyntaxTrees.Single(); + model = comp.GetSemanticModel(tree); + loop = tree.GetRoot().DescendantNodes().OfType().First(); + Assert.Equal("System.Collections.Generic.IEnumerator! E.GetEnumerator(this System.Object t)", + model.GetForEachStatementInfo(loop).GetEnumeratorMethod.ToTestDisplayString(includeNonNullable: true)); + } + + [Fact] + public void Nullability_CollectionInitializer_01() + { + var src = """ +#nullable enable +using System.Collections; +using System.Collections.Generic; + +object? oNull = null; +object oNotNull = new object(); +MyCollection c = new MyCollection() { oNull, oNotNull }; + +static class E +{ + extension(MyCollection c) + { + public void Add(object o) { } + } +} + +public class MyCollection : IEnumerable +{ + IEnumerator IEnumerable.GetEnumerator() => throw null!; + IEnumerator IEnumerable.GetEnumerator() => throw null!; +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (7,39): warning CS8604: Possible null reference argument for parameter 'o' in 'void extension(MyCollection).Add(object o)'. + // MyCollection c = new MyCollection() { oNull, oNotNull }; + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "oNull").WithArguments("o", "void extension(MyCollection).Add(object o)").WithLocation(7, 39)); + } + + [Fact] + public void Nullability_CollectionExpression_Add_01() + { + var src = """ +#nullable enable +using System.Collections; +using System.Collections.Generic; + +object? oNull = null; +object oNotNull = new object(); +MyCollection c = [oNull, oNotNull]; + +static class E +{ + extension(MyCollection c) + { + public void Add(object o) { } + } +} + +public class MyCollection : IEnumerable +{ + IEnumerator IEnumerable.GetEnumerator() => throw null!; + IEnumerator IEnumerable.GetEnumerator() => throw null!; +} +"""; + // Tracked by https://github.com/dotnet/roslyn/issues/76130 : missing nullability diagnostic + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics(); + + src = """ +#nullable enable +using System.Collections; +using System.Collections.Generic; + +object? oNull = null; +object oNotNull = new object(); +MyCollection c = [oNull, oNotNull]; + +static class E +{ + public static void Add(this MyCollection c, object o) { } +} + +public class MyCollection : IEnumerable +{ + IEnumerator IEnumerable.GetEnumerator() => throw null!; + IEnumerator IEnumerable.GetEnumerator() => throw null!; +} +"""; + // Tracked by https://github.com/dotnet/roslyn/issues/78452 : assertion hit during nullability analysis + try + { + comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics(); + } + catch (InvalidOperationException) + { + } + } + + [Fact] + public void Nullability_ObjectInitializer_01() + { + var src = """ +#nullable enable + +object? oNull = null; +_ = new object() { Property = oNull }; + +object oNotNull = new object(); +_ = new object() { Property = oNotNull }; + +static class E +{ + extension(object o) + { + public object Property { set { } } + } +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (4,31): warning CS8601: Possible null reference assignment. + // _ = new object() { Property = oNull }; + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "oNull").WithLocation(4, 31)); + } + + [Fact] + public void Nullability_ObjectInitializer_02() + { + var src = """ +#nullable enable + +_ = new object() { Property = 42 }; + +static class E +{ + extension(T t) + { + public int Property { set { } } + } +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics(); + + // Tracked by https://github.com/dotnet/roslyn/issues/76130 : incorrect nullability + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var assignment = GetSyntax(tree, "Property = 42"); + Assert.Equal("System.Int32 E.extension(System.Object).Property { set; }", + model.GetSymbolInfo(assignment.Left).Symbol.ToTestDisplayString(includeNonNullable: true)); + } + + [Fact] + public void Nullability_With_01() + { + var src = """ +#nullable enable + +object? oNull = null; +_ = new S() with { Property = oNull }; + +object oNotNull = new object(); +_ = new S() with { Property = oNotNull }; + +struct S { } + +static class E +{ + extension(object o) + { + public object Property { set { } } + } +} +"""; + + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (4,31): warning CS8601: Possible null reference assignment. + // _ = new S() with { Property = oNull }; + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "oNull").WithLocation(4, 31)); + } + + [Fact] + public void Nullability_With_02() + { + var src = """ +#nullable enable + +C? cNull = null; +_ = cNull with { Property = 42 }; + +C cNotNull = new C(); +_ = cNotNull with { Property = 42 }; + +record C { } + +static class E +{ + extension(object o) + { + public int Property { set { } } + } +} +"""; + + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (4,5): warning CS8602: Dereference of a possibly null reference. + // _ = cNull with { Property = 42 }; + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "cNull").WithLocation(4, 5)); + } + + [Fact] + public void Nullability_With_03() + { + var src = """ +#nullable enable + +C? cNull = null; +_ = cNull with { Property = 42 }; + +C cNotNull = new C(); +_ = cNotNull with { Property = 42 }; + +record C { } + +static class E +{ + extension(object? o) + { + public int Property { set { } } + } +} +"""; + + // Tracked by https://github.com/dotnet/roslyn/issues/76130 : unexpected nullability warning + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (4,5): warning CS8602: Dereference of a possibly null reference. + // _ = cNull with { Property = 42 }; + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "cNull").WithLocation(4, 5)); + } + + [Fact] + public void Nullability_With_04() + { + var src = """ +#nullable enable + +C? cNull = null; +_ = cNull with { Property = 42 }; + +C cNotNull = new C(); +_ = cNotNull with { Property = 42 }; + +record C { } + +static class E +{ + extension(T t) + { + public int Property { set { } } + } +} +"""; + // Tracked by https://github.com/dotnet/roslyn/issues/76130 : unexpected nullability warning + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (4,5): warning CS8602: Dereference of a possibly null reference. + // _ = cNull with { Property = 42 }; + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "cNull").WithLocation(4, 5)); + } + + [Fact] + public void Nullability_With_05() + { + var src = """ +#nullable enable + +C? cNull = null; +_ = cNull with { Property = 42 }; + +C cNotNull = new C(); +_ = cNotNull with { Property = 42 }; + +record C { } + +static class E +{ + extension(T t) where T : notnull + { + public int Property { set { } } + } +} +"""; + + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (4,5): warning CS8602: Dereference of a possibly null reference. + // _ = cNull with { Property = 42 }; + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "cNull").WithLocation(4, 5)); + } + + [Fact] + public void Nullability_Fixed_01() + { + var src = """ +#nullable enable + +unsafe class C +{ + public static void M() + { + fixed (S* p = new Fixable()) { } // 1 + fixed (S* p = new Fixable()) { } + } +} + +class Fixable { } + +struct S { } + +static class E +{ + extension(Fixable f) + { + public ref S GetPinnableReference() => throw null!; + } +} +"""; + // We don't yet analyze the nullability of `fixed` statements for extension methods + var comp = CreateCompilation(src, options: TestOptions.UnsafeDebugDll); + comp.VerifyEmitDiagnostics(); + + src = """ +#nullable enable + +unsafe class C +{ + public static void M() + { + fixed (S* p = new Fixable()) { } // 1 + fixed (S* p = new Fixable()) { } + } +} + +class Fixable { } + +struct S { } + +static class E +{ + public static ref S GetPinnableReference(this Fixable f) => throw null!; +} +"""; + comp = CreateCompilation(src, options: TestOptions.UnsafeDebugDll); + comp.VerifyEmitDiagnostics(); + } + + [Fact] + public void Nullability_Await_GetAwaiter_01() + { + var src = """ +#nullable enable + +using System; +using System.Runtime.CompilerServices; + +C? cNull = null; +_ = await cNull; + +C cNotNull = new C(); +_ = await cNotNull; + +class C { } + +class D : INotifyCompletion +{ + public int GetResult() => 42; + public void OnCompleted(Action continuation) => throw null!; + public bool IsCompleted => true; +} + +static class E +{ + extension(C c) + { + public D GetAwaiter() => new D(); + } +} +"""; + + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (7,11): warning CS8604: Possible null reference argument for parameter 'c' in 'extension(C)'. + // _ = await cNull; + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "cNull").WithArguments("c", "extension(C)").WithLocation(7, 11)); + } + [Fact] public void BuildArgumentsForErrorRecovery_01() { @@ -36389,17 +39148,17 @@ extends [mscorlib]System.Object .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { - .method private hidebysig static void '$' ( int32 '' ) cil managed + .method private hidebysig static void '$' ( int32 '' ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) IL_0000: ret } - .method public hidebysig instance void M () cil managed + .method public hidebysig instance void M () cil managed { IL_0000: ldnull IL_0001: throw } - .method public hidebysig specialname instance int32 get_P () cil managed + .method public hidebysig specialname instance int32 get_P () cil managed { IL_0000: ldnull IL_0001: throw @@ -36409,12 +39168,12 @@ .property instance int32 P() .get instance int32 E/'<>E__0'::get_P() } } - .method public hidebysig static void M ( int32 '' ) cil managed + .method public hidebysig static void M ( int32 '' ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) IL_0000: ret } - .method public hidebysig static int32 get_P ( int32 '' ) cil managed + .method public hidebysig static int32 get_P ( int32 '' ) cil managed { IL_0000: ldc.i4.0 IL_0001: ret @@ -36452,27 +39211,27 @@ extends [mscorlib]System.Object .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { - .method private hidebysig specialname static void '$' ( int32 '' ) cil managed + .method private hidebysig specialname static void '$' ( int32 '' ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) IL_0000: ret } - .method public hidebysig instance void M () cil managed + .method public hidebysig instance void M () cil managed { IL_0000: ldnull IL_0001: throw } - .method public hidebysig specialname instance void M2 () cil managed + .method public hidebysig specialname instance void M2 () cil managed { IL_0000: ldnull IL_0001: throw } - .method public hidebysig specialname instance int32 get_P () cil managed + .method public hidebysig specialname instance int32 get_P () cil managed { IL_0000: ldnull IL_0001: throw } - .method public hidebysig instance int32 get_P2 () cil managed + .method public hidebysig instance int32 get_P2 () cil managed { IL_0000: ldnull IL_0001: throw @@ -36486,22 +39245,22 @@ .property instance int32 P2() .get instance int32 E/'<>E__0'::get_P2() } } - .method public hidebysig specialname static void M ( int32 '' ) cil managed + .method public hidebysig specialname static void M ( int32 '' ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) IL_0000: ret } - .method public hidebysig static void M2 ( int32 '' ) cil managed + .method public hidebysig static void M2 ( int32 '' ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) IL_0000: ret } - .method public hidebysig static int32 get_P ( int32 '' ) cil managed + .method public hidebysig static int32 get_P ( int32 '' ) cil managed { IL_0000: ldc.i4.0 IL_0001: ret } - .method public hidebysig specialname static int32 get_P2 ( int32 '' ) cil managed + .method public hidebysig specialname static int32 get_P2 ( int32 '' ) cil managed { IL_0000: ldc.i4.0 IL_0001: ret @@ -37523,4 +40282,33 @@ void handleEnd(SymbolAnalysisContext context) } } } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/78487")] + public void Async_01() + { + string source = """ +await System.Threading.Tasks.Task.FromResult(true).M(); +await System.Threading.Tasks.Task.M2(); + +static class E +{ + extension(System.Threading.Tasks.Task source) + { + public async System.Threading.Tasks.Task M() + { + System.Console.Write(await source); + System.Console.Write(" ran "); + } + + public static async System.Threading.Tasks.Task M2() + { + await System.Threading.Tasks.Task.FromResult(default(T)); + System.Console.Write("ran2"); + } + } +} +"""; + var comp = CreateCompilation(source); + CompileAndVerify(comp, expectedOutput: "True ran ran2").VerifyDiagnostics(); + } } diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests2.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests2.cs new file mode 100644 index 0000000000000..764c7a9e8c10e --- /dev/null +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests2.cs @@ -0,0 +1,636 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +#nullable disable + +using System; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics; + +[CompilerTrait(CompilerFeature.Extensions)] +public partial class ExtensionTests : CompilingTestBase +{ + [Fact] + public void Deconstruct_01() + { + var src = """ +var (x, y) = ""; + +static class E +{ + extension(object o) + { + public void Deconstruct(out int i, out int j, params int[] k) => throw null; + } +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (1,6): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x'. + // var (x, y) = ""; + Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x").WithArguments("x").WithLocation(1, 6), + // (1,9): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'y'. + // var (x, y) = ""; + Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "y").WithArguments("y").WithLocation(1, 9), + // (1,14): error CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'string', with 2 out parameters and a void return type. + // var (x, y) = ""; + Diagnostic(ErrorCode.ERR_MissingDeconstruct, @"""""").WithArguments("string", "2").WithLocation(1, 14)); + } + + [Fact] + public void Deconstruct_02() + { + var src = """ +var (x, y) = ""; + +static class E +{ + extension(object o) + { + public void Deconstruct(out int i, out int j, int k = 0) => throw null; + } +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (1,6): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x'. + // var (x, y) = ""; + Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x").WithArguments("x").WithLocation(1, 6), + // (1,9): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'y'. + // var (x, y) = ""; + Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "y").WithArguments("y").WithLocation(1, 9), + // (1,14): error CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'string', with 2 out parameters and a void return type. + // var (x, y) = ""; + Diagnostic(ErrorCode.ERR_MissingDeconstruct, @"""""").WithArguments("string", "2").WithLocation(1, 14)); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75484")] + public void Deconstruction_UnscopedRef_ExtensionMethod() + { + var source = """ +class C +{ + R M1() + { + new S().Deconstruct(out var x, out _); + return x; // 1 + } + R M2() + { + (var x, _) = new S(); + return x; // 2 + } + R M3() + { + if (new S() is (var x, _)) + return x; // 3 + return default; + } +} +struct S; +ref struct R; +static class E +{ + extension(in S s) + { + public void Deconstruct(out R x, out int y) => throw null; + } +} +"""; + CreateCompilation(source).VerifyDiagnostics( + // (6,16): error CS8352: Cannot use variable 'x' in this context because it may expose referenced variables outside of their declaration scope + // return x; // 1 + Diagnostic(ErrorCode.ERR_EscapeVariable, "x").WithArguments("x").WithLocation(6, 16), + // (11,16): error CS8352: Cannot use variable 'x' in this context because it may expose referenced variables outside of their declaration scope + // return x; // 2 + Diagnostic(ErrorCode.ERR_EscapeVariable, "x").WithArguments("x").WithLocation(11, 16), + // (16,20): error CS8352: Cannot use variable 'x' in this context because it may expose referenced variables outside of their declaration scope + // return x; // 3 + Diagnostic(ErrorCode.ERR_EscapeVariable, "x").WithArguments("x").WithLocation(16, 20)); + } + + [Fact] + public void Deconstruction_ScopedRef_ExtensionMethod() + { + var source = """ +class C +{ + R M1() + { + new S().Deconstruct(out var x, out _); + return x; + } + R M2() + { + (var x, _) = new S(); + return x; + } + R M3() + { + if (new S() is (var x, _)) + return x; + return default; + } +} +struct S; +ref struct R; +static class E +{ + extension(scoped in S s) + { + public void Deconstruct(out R x, out int y) => throw null; + } +} +"""; + CreateCompilation(source).VerifyDiagnostics(); + } + + [Fact] + public void ForeachDeconstruct_Conversion() + { + var src = """ +C[] c = new C[] { new C() }; +foreach (var (x1, x2) in c) +{ + System.Console.Write(x1.ToString()); +} + +class C { } + +static class E +{ + extension(object o) + { + public void Deconstruct(out int i1, out int i2) { i1 = i2 = 42; } + } +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics(); + CompileAndVerify(comp, expectedOutput: "42").VerifyDiagnostics(); + } + + [Fact] + public void PositionalPattern_01() + { + var src = """ +_ = "" is (i: 42, other: 43); + +static class E +{ + extension(object o) + { + public void Deconstruct(out int i, out int j) => throw null; + } +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (1,19): error CS8517: The name 'other' does not match the corresponding 'Deconstruct' parameter 'j'. + // _ = "" is (i: 42, other: 43); + Diagnostic(ErrorCode.ERR_DeconstructParameterNameMismatch, "other").WithArguments("other", "j").WithLocation(1, 19)); + } + + [Fact] + public void PositionalPattern_02() + { + var src = """ +_ = new C() is var (x, y); + +class C { } + +static class E +{ + extension(object o) + { + public void Deconstruct(out int i, out int j) => throw null; + } +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics(); + } + + [Fact] + public void InvocationOnNull() + { + var src = """ +null.M1(""); +null.M2(""); + +static class E +{ + extension(T t1) + { + public void M1(T t2) => throw null!; + } + + public static void M2(this T t1, T t2) => throw null!; +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (1,1): error CS0023: Operator '.' cannot be applied to operand of type '' + // null.M1(""); + Diagnostic(ErrorCode.ERR_BadUnaryOp, "null.M1").WithArguments(".", "").WithLocation(1, 1), + // (2,1): error CS0023: Operator '.' cannot be applied to operand of type '' + // null.M2(""); + Diagnostic(ErrorCode.ERR_BadUnaryOp, "null.M2").WithArguments(".", "").WithLocation(2, 1)); + } + + [Fact] + public void RemoveLowerPriorityMembers_Deconstruct() + { + var src = """ +var (x, y) = ""; + +public static class E +{ + extension(object o) + { + [System.Runtime.CompilerServices.OverloadResolutionPriority(1)] + public void Deconstruct(out int i2, out int i3) { System.Console.Write("ran"); i2 = i3 = 43; } + } + extension(string s) + { + public void Deconstruct(out int i2, out int i3) => throw null; + } +} +"""; + var comp = CreateCompilation([src, OverloadResolutionPriorityAttributeDefinition]); + CompileAndVerify(comp, expectedOutput: "ran").VerifyDiagnostics(); + + src = """ +var (x, y) = ""; + +public static class E +{ + extension(object o) + { + public void Deconstruct(out int i2, out int i3) => throw null; + } + extension(string s) + { + public void Deconstruct(out int i2, out int i3) { System.Console.Write("ran"); i2 = i3 = 43; } + } +} +"""; + comp = CreateCompilation([src, OverloadResolutionPriorityAttributeDefinition]); + CompileAndVerify(comp, expectedOutput: "ran").VerifyDiagnostics(); + } + + [Fact] + public void RemoveLowerPriorityMembers_Foreach_GetEnumerator() + { + var src = """ +using System.Collections.Generic; + +foreach (var x in new C()) { System.Console.Write(x); } + +public class C { } + +public static class E +{ + extension(object o) + { + [System.Runtime.CompilerServices.OverloadResolutionPriority(1)] + public IEnumerator GetEnumerator() { yield return 42; } + } + + extension(C c) + { + public IEnumerator GetEnumerator() => throw null; + } +} +"""; + try + { + var comp = CreateCompilation([src, OverloadResolutionPriorityAttributeDefinition]); + // Tracked by https://github.com/dotnet/roslyn/issues/76130 : assertion in NullableWalker + CompileAndVerify(comp, expectedOutput: "42").VerifyDiagnostics(); + } + catch (InvalidOperationException) + { + } + } + + [Fact] + public void RemoveLowerPriorityMembers_CollectionInitializer() + { + var src = """ +using System.Collections; +using System.Collections.Generic; + +_ = new C() { 42 }; + +public class C : IEnumerable, IEnumerable +{ + IEnumerator IEnumerable.GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; +} + +public static class E +{ + extension(object o) + { + [System.Runtime.CompilerServices.OverloadResolutionPriority(1)] + public void Add(int i) { System.Console.Write("add"); } + } + + extension(C c) + { + public void Add(int i) => throw null; + } +} +"""; + var comp = CreateCompilation([src, OverloadResolutionPriorityAttributeDefinition]); + CompileAndVerify(comp, expectedOutput: "add").VerifyDiagnostics(); + } + + [Fact] + public void RemoveLowerPriorityMembers_Fixed() + { + var src = """ +unsafe class C +{ + public static void Main() + { + fixed (int* p = new Fixable()) { } + } +} + +public class Fixable { } + +public static class E +{ + extension(object o) + { + [System.Runtime.CompilerServices.OverloadResolutionPriority(1)] + public ref int GetPinnableReference() { System.Console.Write("ran"); return ref (new int[] { 1, 2, 3 })[0]; } + } + + extension(Fixable f) + { + public ref int GetPinnableReference() => throw null; + } +} +"""; + var comp = CreateCompilation([src, OverloadResolutionPriorityAttributeDefinition], options: TestOptions.UnsafeDebugExe); + CompileAndVerify(comp, expectedOutput: "ran", verify: Verification.Skipped).VerifyDiagnostics(); + } + + [Fact] + public void RemoveLowerPriorityMembers_Await() + { + var src = """ +using System; +using System.Runtime.CompilerServices; + +int i = await new C(); +System.Console.Write(i); + +public class C { } + +public class D : INotifyCompletion +{ + public int GetResult() => 42; + public void OnCompleted(Action continuation) => throw null; + public bool IsCompleted => true; +} + +public static class E +{ + extension(object o) + { + [System.Runtime.CompilerServices.OverloadResolutionPriority(1)] + public D GetAwaiter() => new D(); + } + + extension(C c) + { + public D GetAwaiter() => throw null; + } +} +"""; + var comp = CreateCompilation([src, OverloadResolutionPriorityAttributeDefinition]); + CompileAndVerify(comp, expectedOutput: "42").VerifyDiagnostics(); + } + + [Fact] + public void RemoveLowerPriorityMembers_ObjectInitializer() + { + var src = """ +_ = new C() { Property = 42 }; + +public class C { } + +public static class E +{ + extension(object o) + { + [System.Runtime.CompilerServices.OverloadResolutionPriority(1)] + public int Property { set { System.Console.Write("property"); } } + } + + extension(C c) + { + public int Property => throw null; + } +} +"""; + var comp = CreateCompilation([src, OverloadResolutionPriorityAttributeDefinition]); + CompileAndVerify(comp, expectedOutput: "property").VerifyDiagnostics(); + } + + [Fact] + public void RemoveLowerPriorityMembers_With() + { + var src = """ +_ = new S() with { Property = 42 }; + +public struct S { } + +public static class E +{ + extension(object o) + { + [System.Runtime.CompilerServices.OverloadResolutionPriority(1)] + public int Property { set { System.Console.Write("property"); } } + } + + extension(S s) + { + public int Property { set => throw null; } + } +} +"""; + var comp = CreateCompilation([src, OverloadResolutionPriorityAttributeDefinition]); + CompileAndVerify(comp, expectedOutput: "property").VerifyDiagnostics(); + } + + [Fact] + public void RemoveLowerPriorityMembers_PropertyPattern() + { + var src = """ +_ = new C() is { Property: 42 }; + +public class C{ } + +public static class E +{ + extension(object o) + { + [System.Runtime.CompilerServices.OverloadResolutionPriority(1)] + public int Property { get { System.Console.Write("property"); return 42; } } + } + + extension(C c) + { + public int Property => throw null; + } +} +"""; + var comp = CreateCompilation([src, OverloadResolutionPriorityAttributeDefinition]); + CompileAndVerify(comp, expectedOutput: "property").VerifyDiagnostics(); + } + + [Fact] + public void AnonymousType_01() + { + var src = """ +var person = new { Name = "John", Age = 30 }; +person.M(); +person.M2(); +_ = person.P; + +public static class E +{ + extension(T t) + { + public void M() { System.Console.Write("method "); } + public int Property { get { System.Console.Write("property"); return 42; } } + } + + public static void M2(this T t) { System.Console.Write("method2 "); } +} +"""; + // Tracked by https://github.com/dotnet/roslyn/issues/76130 : should work + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (4,12): error CS1061: '' does not contain a definition for 'P' and no accessible extension method 'P' accepting a first argument of type '' could be found (are you missing a using directive or an assembly reference?) + // _ = person.P; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "P").WithArguments("", "P").WithLocation(4, 12)); + } + + [Fact] + public void Attribute_01() + { + var src = """ +[My(Property = 42)] +class C { } + +public class MyAttribute : System.Attribute { } + +public static class E +{ + extension(MyAttribute a) + { + public int Property { get => throw null; set => throw null; } + } +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (1,5): error CS0246: The type or namespace name 'Property' could not be found (are you missing a using directive or an assembly reference?) + // [My(Property = 42)] + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Property").WithArguments("Property").WithLocation(1, 5)); + } + + [Fact] + public void Lock_01() + { + var src = """ +System.Threading.Lock x = new System.Threading.Lock(); +lock (x) { } + +namespace System.Threading +{ + public sealed class Lock + { + public Scope EnterScope() { System.Console.Write("ran "); return new Scope(); } + + public ref struct Scope + { + public void Dispose() { System.Console.Write("disposed"); } + } + } +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics(); + CompileAndVerify(comp, expectedOutput: "ran disposed", verify: Verification.Skipped).VerifyDiagnostics(); + + src = """ +System.Threading.Lock x = new System.Threading.Lock(); +lock (x) { } + +namespace System.Threading +{ + public sealed class Lock + { + public ref struct Scope + { + public void Dispose() => throw null; + } + } +} + +public static class E +{ + extension(System.Threading.Lock x) + { + public System.Threading.Lock.Scope EnterScope() => throw null; + } +} +"""; + comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (2,7): error CS0656: Missing compiler required member 'System.Threading.Lock.EnterScope' + // lock (x) { } + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "x").WithArguments("System.Threading.Lock", "EnterScope").WithLocation(2, 7)); + + src = """ +System.Threading.Lock x = new System.Threading.Lock(); +lock (x) { } + +namespace System.Threading +{ + public sealed class Lock + { + public Scope EnterScope() => throw null; + public ref struct Scope + { + } + } +} + +public static class E +{ + extension(System.Threading.Lock.Scope x) + { + public void Dispose() => throw null; + } +} +"""; + comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (2,7): error CS0656: Missing compiler required member 'System.Threading.Lock+Scope.Dispose' + // lock (x) { } + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "x").WithArguments("System.Threading.Lock+Scope", "Dispose").WithLocation(2, 7)); + } +} + diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ExtensionsParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ExtensionsParsingTests.cs index dbd2ceed5f107..ddd91722878ca 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/ExtensionsParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ExtensionsParsingTests.cs @@ -752,7 +752,6 @@ class extension } EOF(); - // Tracked by https://github.com/dotnet/roslyn/issues/76130 : report error for declaring type named "extension" // Note: break from C# 13 UsingTree(""" class extension diff --git a/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs b/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs index 0611918d426a0..0402daf5a450e 100644 --- a/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs +++ b/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs @@ -725,7 +725,7 @@ public CompilerFeatureRequiredAttribute(string featureName) #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member """; - internal const string CompilerFeatureRequiredAttributeIL = @" + internal static readonly string CompilerFeatureRequiredAttributeIL = @" .class public auto ansi sealed beforefieldinit System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute extends [mscorlib]System.Attribute { @@ -813,7 +813,7 @@ public CollectionBuilderAttribute(Type builderType, string methodName) { } } """; - internal const string OverloadResolutionPriorityAttributeDefinition = """ + internal static readonly string OverloadResolutionPriorityAttributeDefinition = """ namespace System.Runtime.CompilerServices; [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] @@ -823,7 +823,7 @@ public sealed class OverloadResolutionPriorityAttribute(int priority) : Attribut } """; - internal const string OverloadResolutionPriorityAttributeILDefinition = """ + internal static readonly string OverloadResolutionPriorityAttributeILDefinition = """ .class public auto ansi sealed beforefieldinit System.Runtime.CompilerServices.OverloadResolutionPriorityAttribute extends [mscorlib]System.Attribute { @@ -865,7 +865,7 @@ .property instance int32 Priority() /// /// The shape of the attribute comes from https://github.com/dotnet/runtime/issues/103430 /// - internal const string CompilerLoweringPreserveAttributeDefinition = """ + internal static readonly string CompilerLoweringPreserveAttributeDefinition = """ namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Class, Inherited = false)] @@ -876,6 +876,360 @@ public CompilerLoweringPreserveAttribute() { } } """; + #region A string containing expression-tree dumping utilities + protected static readonly string ExpressionTestLibrary = """ +using System; +using System.Globalization; +using System.Linq.Expressions; +using System.Text; + +public class TestBase +{ + protected static void DCheck(Expression e, string expected) { Check(e.Dump(), expected); } + protected static void Check(Expression> e, string expected) { Check(e.Dump(), expected); } + protected static void Check(Expression> e, string expected) { Check(e.Dump(), expected); } + protected static void Check(Expression> e, string expected) { Check(e.Dump(), expected); } + protected static void Check(Expression> e, string expected) { Check(e.Dump(), expected); } + protected static string ToString(Expression> e) { return e.Dump(); } + protected static string ToString(Expression> e) { return e.Dump(); } + protected static string ToString(Expression> e) { return e.Dump(); } + private static void Check(string actual, string expected) + { + if (expected != actual) + { + Console.WriteLine("FAIL"); + Console.WriteLine("expected: " + expected); + Console.WriteLine("actual: " + actual); + } + } +} + +public static class ExpressionExtensions +{ + public static string Dump(this Expression self) + { + return ExpressionPrinter.Print(self.Body); + } +} + +class ExpressionPrinter : System.Linq.Expressions.ExpressionVisitor +{ + private StringBuilder s = new StringBuilder(); + + public static string Print(Expression e) + { + var p = new ExpressionPrinter(); + p.Visit(e); + return p.s.ToString(); + } + + public override Expression Visit(Expression node) + { + if (node == null) { s.Append("null"); return null; } + s.Append(node.NodeType.ToString()); + s.Append("("); + base.Visit(node); + s.Append(" Type:" + node.Type); + s.Append(")"); + return null; + } + + protected override MemberBinding VisitMemberBinding(MemberBinding node) + { + if (node == null) { s.Append("null"); return null; } + return base.VisitMemberBinding(node); + } + + protected override MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding node) + { + s.Append("MemberMemberBinding(Member="); + s.Append(node.Member.ToString()); + foreach (var b in node.Bindings) + { + s.Append(" "); + VisitMemberBinding(b); + } + s.Append(")"); + return null; + } + + protected override MemberListBinding VisitMemberListBinding(MemberListBinding node) + { + s.Append("MemberListBinding(Member="); + s.Append(node.Member.ToString()); + foreach (var i in node.Initializers) + { + s.Append(" "); + VisitElementInit(i); + } + s.Append(")"); + return null; + } + + protected override MemberAssignment VisitMemberAssignment(MemberAssignment node) + { + s.Append("MemberAssignment(Member="); + s.Append(node.Member.ToString()); + s.Append(" Expression="); + Visit(node.Expression); + s.Append(")"); + return null; + } + + protected override Expression VisitMemberInit(MemberInitExpression node) + { + s.Append("NewExpression: "); + Visit(node.NewExpression); + s.Append(" Bindings:["); + bool first = true; + foreach (var b in node.Bindings) + { + if (!first) s.Append(" "); + VisitMemberBinding(b); + first = false; + } + s.Append("]"); + return null; + } + + protected override Expression VisitBinary(BinaryExpression node) + { + Visit(node.Left); + s.Append(" "); + Visit(node.Right); + if (node.Conversion != null) + { + s.Append(" Conversion:"); + Visit(node.Conversion); + } + if (node.IsLifted) s.Append(" Lifted"); + if (node.IsLiftedToNull) s.Append(" LiftedToNull"); + if (node.Method != null) s.Append(" Method:[" + node.Method + "]"); + return null; + } + + protected override Expression VisitConditional(ConditionalExpression node) + { + Visit(node.Test); + s.Append(" ? "); + Visit(node.IfTrue); + s.Append(" : "); + Visit(node.IfFalse); + return null; + } + + protected override Expression VisitConstant(ConstantExpression node) + { + s.Append(node.Value == null ? "null" : GetCultureInvariantString(node.Value)); + return null; + } + + protected override Expression VisitDefault(DefaultExpression node) + { + return null; + } + + protected override Expression VisitIndex(IndexExpression node) + { + Visit(node.Object); + s.Append("["); + int n = node.Arguments.Count; + for (int i = 0; i < n; i++) + { + if (i != 0) s.Append(" "); + Visit(node.Arguments[i]); + } + s.Append("]"); + if (node.Indexer != null) s.Append(" Indexer:" + node.Indexer); + return null; + } + + protected override Expression VisitInvocation(InvocationExpression node) + { + Visit(node.Expression); + s.Append("("); + int n = node.Arguments.Count; + for (int i = 0; i < n; i++) + { + if (i != 0) s.Append(" "); + Visit(node.Arguments[i]); + } + s.Append(")"); + return null; + } + + protected override Expression VisitLambda(Expression node) + { + s.Append("("); + int n = node.Parameters.Count; + for (int i = 0; i < n; i++) + { + if (i != 0) s.Append(" "); + Visit(node.Parameters[i]); + } + s.Append(") => "); + if (node.Name != null) s.Append(node.Name); + Visit(node.Body); + if (node.ReturnType != null) s.Append(" ReturnType:" + node.ReturnType); + if (node.TailCall) s.Append(" TailCall"); + return null; + } + + protected override Expression VisitListInit(ListInitExpression node) + { + Visit(node.NewExpression); + s.Append("{"); + int n = node.Initializers.Count; + for (int i = 0; i < n; i++) + { + if (i != 0) s.Append(" "); + Visit(node.Initializers[i]); + } + s.Append("}"); + return null; + } + + protected override ElementInit VisitElementInit(ElementInit node) + { + Visit(node); + return null; + } + + private void Visit(ElementInit node) + { + s.Append("ElementInit("); + s.Append(node.AddMethod); + int n = node.Arguments.Count; + for (int i = 0; i < n; i++) + { + s.Append(" "); + Visit(node.Arguments[i]); + } + s.Append(")"); + } + + protected override Expression VisitMember(MemberExpression node) + { + Visit(node.Expression); + s.Append("."); + s.Append(node.Member.Name); + return null; + } + + protected override Expression VisitMethodCall(MethodCallExpression node) + { + Visit(node.Object); + s.Append(".[" + node.Method + "]"); + s.Append("("); + int n = node.Arguments.Count; + for (int i = 0; i < n; i++) + { + if (i != 0) s.Append(", "); + Visit(node.Arguments[i]); + } + s.Append(")"); + return null; + } + + protected override Expression VisitNew(NewExpression node) + { + s.Append((node.Constructor != null) ? "[" + node.Constructor + "]" : "<.ctor>"); + s.Append("("); + int n = node.Arguments.Count; + for (int i = 0; i < n; i++) + { + if (i != 0) s.Append(", "); + Visit(node.Arguments[i]); + } + s.Append(")"); + if (node.Members != null) + { + n = node.Members.Count; + if (n != 0) + { + s.Append("{"); + for (int i = 0; i < n; i++) + { + var info = node.Members[i]; + if (i != 0) s.Append(" "); + s.Append(info); + } + s.Append("}"); + } + } + return null; + } + + protected override Expression VisitNewArray(NewArrayExpression node) + { + s.Append("["); + int n = node.Expressions.Count; + for (int i = 0; i < n; i++) + { + if (i != 0) s.Append(" "); + Visit(node.Expressions[i]); + } + s.Append("]"); + return null; + } + + protected override Expression VisitParameter(ParameterExpression node) + { + s.Append(node.Name); + if (node.IsByRef) s.Append(" ByRef"); + return null; + } + + protected override Expression VisitTypeBinary(TypeBinaryExpression node) + { + Visit(node.Expression); + s.Append(" TypeOperand:" + node.TypeOperand); + return null; + } + + protected override Expression VisitUnary(UnaryExpression node) + { + Visit(node.Operand); + if (node.IsLifted) s.Append(" Lifted"); + if (node.IsLiftedToNull) s.Append(" LiftedToNull"); + if (node.Method != null) s.Append(" Method:[" + node.Method + "]"); + return null; + } + + public static string GetCultureInvariantString(object value) + { + var valueType = value.GetType(); + if (valueType == typeof(string)) + { + return value as string; + } + + if (valueType == typeof(DateTime)) + { + return ((DateTime)value).ToString("M/d/yyyy h:mm:ss tt", CultureInfo.InvariantCulture); + } + + if (valueType == typeof(float)) + { + return ((float)value).ToString(CultureInfo.InvariantCulture); + } + + if (valueType == typeof(double)) + { + return ((double)value).ToString(CultureInfo.InvariantCulture); + } + + if (valueType == typeof(decimal)) + { + return ((decimal)value).ToString(CultureInfo.InvariantCulture); + } + + return value.ToString(); + } +} +"""; + #endregion A string containing expression-tree dumping utilities + protected static T GetSyntax(SyntaxTree tree, string text) where T : notnull {