diff --git a/src/Compilers/CSharp/Portable/Binder/Binder.QueryUnboundLambdaState.cs b/src/Compilers/CSharp/Portable/Binder/Binder.QueryUnboundLambdaState.cs index 4f5f4e34a4531..a7d1438a212c1 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder.QueryUnboundLambdaState.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder.QueryUnboundLambdaState.cs @@ -58,7 +58,7 @@ public override void GenerateAnonymousFunctionConversionError(BindingDiagnosticB base.GenerateAnonymousFunctionConversionError(diagnostics, targetType); } - public override Binder ParameterBinder(LambdaSymbol lambdaSymbol, Binder binder) + public override Binder GetWithParametersBinder(LambdaSymbol lambdaSymbol, Binder binder) { return new WithQueryLambdaParametersBinder(lambdaSymbol, _rangeVariableMap, binder); } diff --git a/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs b/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs index fce66b2e44abf..ec5232daa82c8 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs @@ -631,7 +631,7 @@ private static TypeWithAnnotations DelegateReturnTypeWithAnnotations(MethodSymbo parameterRefKinds, refKind: default, returnType: default); - var lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, ParameterBinder(lambdaSymbol, Binder)); + var lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, GetWithParametersBinder(lambdaSymbol, Binder)); var block = BindLambdaBody(lambdaSymbol, lambdaBodyBinder, BindingDiagnosticBag.Discarded); var returnTypes = ArrayBuilder<(BoundReturnStatement, TypeWithAnnotations)>.GetInstance(); BoundLambda.BlockReturns.GetReturnTypes(returnTypes, block); @@ -704,7 +704,7 @@ private BoundLambda ReallyBind(NamedTypeSymbol delegateType, bool inExpressionTr else { lambdaSymbol = CreateLambdaSymbol(Binder.ContainingMemberOrLambda, returnType, cacheKey.ParameterTypes, cacheKey.ParameterRefKinds, refKind); - lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, ParameterBinder(lambdaSymbol, Binder), inExpressionTree ? BinderFlags.InExpressionTree : BinderFlags.None); + lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, GetWithParametersBinder(lambdaSymbol, Binder), inExpressionTree ? BinderFlags.InExpressionTree : BinderFlags.None); block = BindLambdaBody(lambdaSymbol, lambdaBodyBinder, diagnostics); } @@ -890,7 +890,7 @@ private void ValidateUnsafeParameters(BindingDiagnosticBag diagnostics, Immutabl parameterTypes, parameterRefKinds, refKind); - var lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, ParameterBinder(lambdaSymbol, Binder)); + var lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, GetWithParametersBinder(lambdaSymbol, Binder)); var block = BindLambdaBody(lambdaSymbol, lambdaBodyBinder, diagnostics); lambdaSymbol.GetDeclarationDiagnostics(diagnostics); return (lambdaSymbol, block, lambdaBodyBinder, diagnostics); @@ -1024,7 +1024,7 @@ public static ReturnInferenceCacheKey Create(NamedTypeSymbol? delegateType, bool } } - public virtual Binder ParameterBinder(LambdaSymbol lambdaSymbol, Binder binder) + public virtual Binder GetWithParametersBinder(LambdaSymbol lambdaSymbol, Binder binder) { return new WithLambdaParametersBinder(lambdaSymbol, binder); } diff --git a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs index 8d106bcd64aa9..670764ca4d3f0 100644 --- a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs @@ -250,8 +250,7 @@ private static Binder GetEnclosingBinderInternalWithinRoot(SyntaxNode node, int { Debug.Assert(ownerOfTypeParametersInScope == null); var localFunction = (LocalFunctionStatementSyntax)stmt; - if (localFunction.TypeParameterList != null && - !LookupPosition.IsBetweenTokens(position, localFunction.Identifier, localFunction.TypeParameterList.LessThanToken)) // Scope does not include method name. + if (LookupPosition.IsInLocalFunctionTypeParameterScope(position, localFunction)) { ownerOfTypeParametersInScope = localFunction; } @@ -358,7 +357,7 @@ private static Binder GetEnclosingBinderInternalWithinRoot(SyntaxNode node, int LocalFunctionSymbol function = GetDeclaredLocalFunction(binder, ownerOfTypeParametersInScope.Identifier); if ((object)function != null) { - binder = function.SignatureBinder; + binder = function.WithTypeParametersBinder; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs index 3f4d5439a0f92..4851248e37bdc 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs @@ -314,7 +314,7 @@ internal static class ConstraintsHelper internal static ImmutableArray> MakeTypeParameterConstraintTypes( this MethodSymbol containingSymbol, - Binder binder, + Binder withTypeParametersBinder, ImmutableArray typeParameters, TypeParameterListSyntax typeParameterList, SyntaxList constraintClauses, @@ -327,11 +327,11 @@ internal static class ConstraintsHelper // Wrap binder from factory in a generic constraints specific binder // to avoid checking constraints when binding type names. - Debug.Assert(!binder.Flags.Includes(BinderFlags.GenericConstraintsClause)); - binder = binder.WithAdditionalFlags(BinderFlags.GenericConstraintsClause | BinderFlags.SuppressConstraintChecks); + Debug.Assert(!withTypeParametersBinder.Flags.Includes(BinderFlags.GenericConstraintsClause)); + withTypeParametersBinder = withTypeParametersBinder.WithAdditionalFlags(BinderFlags.GenericConstraintsClause | BinderFlags.SuppressConstraintChecks); ImmutableArray clauses; - clauses = binder.BindTypeParameterConstraintClauses(containingSymbol, typeParameters, typeParameterList, constraintClauses, + clauses = withTypeParametersBinder.BindTypeParameterConstraintClauses(containingSymbol, typeParameters, typeParameterList, constraintClauses, diagnostics, performOnlyCycleSafeValidation: false); if (clauses.All(clause => clause.ConstraintTypes.IsEmpty)) @@ -344,7 +344,7 @@ internal static class ConstraintsHelper internal static ImmutableArray MakeTypeParameterConstraintKinds( this MethodSymbol containingSymbol, - Binder binder, + Binder withTypeParametersBinder, ImmutableArray typeParameters, TypeParameterListSyntax typeParameterList, SyntaxList constraintClauses) @@ -358,18 +358,18 @@ internal static class ConstraintsHelper if (constraintClauses.Count == 0) { - clauses = binder.GetDefaultTypeParameterConstraintClauses(typeParameterList); + clauses = withTypeParametersBinder.GetDefaultTypeParameterConstraintClauses(typeParameterList); } else { // Wrap binder from factory in a generic constraints specific binder // Also, suppress type argument binding in constraint types, this helps to avoid cycles while we figure out constraint kinds. // to avoid checking constraints when binding type names. - Debug.Assert(!binder.Flags.Includes(BinderFlags.GenericConstraintsClause)); - binder = binder.WithAdditionalFlags(BinderFlags.GenericConstraintsClause | BinderFlags.SuppressConstraintChecks | BinderFlags.SuppressTypeArgumentBinding); + Debug.Assert(!withTypeParametersBinder.Flags.Includes(BinderFlags.GenericConstraintsClause)); + withTypeParametersBinder = withTypeParametersBinder.WithAdditionalFlags(BinderFlags.GenericConstraintsClause | BinderFlags.SuppressConstraintChecks | BinderFlags.SuppressTypeArgumentBinding); // We will recompute this diagnostics more accurately later, when binding without BinderFlags.SuppressTypeArgumentBinding - clauses = binder.BindTypeParameterConstraintClauses(containingSymbol, typeParameters, typeParameterList, constraintClauses, + clauses = withTypeParametersBinder.BindTypeParameterConstraintClauses(containingSymbol, typeParameters, typeParameterList, constraintClauses, BindingDiagnosticBag.Discarded, performOnlyCycleSafeValidation: true); clauses = AdjustConstraintKindsBasedOnConstraintTypes(containingSymbol, typeParameters, clauses); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/LambdaSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/LambdaSymbol.cs index e6f20510c98bb..381e7260aa726 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/LambdaSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/LambdaSymbol.cs @@ -267,9 +267,9 @@ public override bool IsExtensionMethod get { return false; } } - internal override Binder SignatureBinder => _binder; + internal override Binder OuterBinder => _binder; - internal override Binder ParameterBinder => new WithLambdaParametersBinder(this, _binder); + internal override Binder WithTypeParametersBinder => _binder; internal override OneOrMany> GetAttributeDeclarations() { diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs index ad93144d7fb9a..f48963065a891 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs @@ -61,7 +61,6 @@ internal sealed class LocalFunctionSymbol : SourceMethodSymbolWithAttributes if (syntax.TypeParameterList != null) { - binder = new WithMethodTypeParametersBinder(this, binder); _typeParameters = MakeTypeParameters(_declarationDiagnostics); } else @@ -106,7 +105,10 @@ internal sealed class LocalFunctionSymbol : SourceMethodSymbolWithAttributes /// internal Binder ScopeBinder { get; } - internal override Binder ParameterBinder => _binder; + internal override Binder OuterBinder => _binder; + + internal override Binder WithTypeParametersBinder + => _typeParameters.IsEmpty ? _binder : new WithMethodTypeParametersBinder(this, _binder); internal LocalFunctionStatementSyntax Syntax => (LocalFunctionStatementSyntax)syntaxReferenceOpt.GetSyntax(); @@ -181,7 +183,7 @@ private void ComputeParameters() var diagnostics = BindingDiagnosticBag.GetInstance(_declarationDiagnostics); var parameters = ParameterHelpers.MakeParameters( - _binder, + WithTypeParametersBinder, this, this.Syntax.ParameterList, arglistToken: out arglistToken, @@ -240,7 +242,7 @@ internal void ComputeReturnType() var diagnostics = BindingDiagnosticBag.GetInstance(_declarationDiagnostics); TypeSyntax returnTypeSyntax = Syntax.ReturnType; - TypeWithAnnotations returnType = _binder.BindType(returnTypeSyntax.SkipRef(), diagnostics); + TypeWithAnnotations returnType = WithTypeParametersBinder.BindType(returnTypeSyntax.SkipRef(), diagnostics); var compilation = DeclaringCompilation; @@ -335,8 +337,6 @@ internal override TypeWithAnnotations IteratorElementTypeWithAnnotations public SyntaxToken NameToken => Syntax.Identifier; - internal override Binder SignatureBinder => _binder; - public override ImmutableArray ExplicitInterfaceImplementations => ImmutableArray.Empty; public override ImmutableArray Locations => ImmutableArray.Create(Syntax.Identifier.GetLocation()); @@ -477,7 +477,7 @@ public override ImmutableArray> GetTypeParam var syntax = Syntax; var diagnostics = BindingDiagnosticBag.GetInstance(_declarationDiagnostics); var constraints = this.MakeTypeParameterConstraintTypes( - _binder, + WithTypeParametersBinder, TypeParameters, syntax.TypeParameterList, syntax.ConstraintClauses, @@ -502,7 +502,7 @@ public override ImmutableArray GetTypeParameterCons { var syntax = Syntax; var constraints = this.MakeTypeParameterConstraintKinds( - _binder, + WithTypeParametersBinder, TypeParameters, syntax.TypeParameterList, syntax.ConstraintClauses); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/ParameterHelpers.cs b/src/Compilers/CSharp/Portable/Symbols/Source/ParameterHelpers.cs index 49582f2d08eb2..dc3d227a6c807 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/ParameterHelpers.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/ParameterHelpers.cs @@ -17,7 +17,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols internal static class ParameterHelpers { public static ImmutableArray MakeParameters( - Binder binder, + Binder withTypeParametersBinder, Symbol owner, BaseParameterListSyntax syntax, out SyntaxToken arglistToken, @@ -27,7 +27,7 @@ internal static class ParameterHelpers bool addRefReadOnlyModifier) { return MakeParameters( - binder, + withTypeParametersBinder, owner, syntax.Parameters, out arglistToken, @@ -106,7 +106,7 @@ internal static class ParameterHelpers } private static ImmutableArray MakeParameters( - Binder binder, + Binder withTypeParametersBinder, TOwningSymbol owner, SeparatedSyntaxList parametersList, out SyntaxToken arglistToken, @@ -179,7 +179,7 @@ internal static class ParameterHelpers } Debug.Assert(parameterSyntax.Type != null); - var parameterType = binder.BindType(parameterSyntax.Type, diagnostics, suppressUseSiteDiagnostics: suppressUseSiteDiagnostics); + var parameterType = withTypeParametersBinder.BindType(parameterSyntax.Type, diagnostics, suppressUseSiteDiagnostics: suppressUseSiteDiagnostics); if (!allowRefOrOut && (refKind == RefKind.Ref || refKind == RefKind.Out)) { @@ -197,7 +197,7 @@ internal static class ParameterHelpers } } - TParameterSymbol parameter = parameterCreationFunc(binder, owner, parameterType, parameterSyntax, refKind, parameterIndex, paramsKeyword, thisKeyword, addRefReadOnlyModifier, diagnostics); + TParameterSymbol parameter = parameterCreationFunc(withTypeParametersBinder, owner, parameterType, parameterSyntax, refKind, parameterIndex, paramsKeyword, thisKeyword, addRefReadOnlyModifier, diagnostics); ReportParameterErrors(owner, parameterSyntax, parameter, thisKeyword, paramsKeyword, firstDefault, diagnostics); @@ -224,10 +224,10 @@ internal static class ParameterHelpers default(ImmutableArray); Debug.Assert(methodOwner?.MethodKind != MethodKind.LambdaMethod); - bool allowShadowingNames = binder.Compilation.IsFeatureEnabled(MessageID.IDS_FeatureNameShadowingInNestedFunctions) && + bool allowShadowingNames = withTypeParametersBinder.Compilation.IsFeatureEnabled(MessageID.IDS_FeatureNameShadowingInNestedFunctions) && methodOwner?.MethodKind == MethodKind.LocalFunction; - binder.ValidateParameterNameConflicts(typeParameters, parameters.Cast(), allowShadowingNames, diagnostics); + withTypeParametersBinder.ValidateParameterNameConflicts(typeParameters, parameters.Cast(), allowShadowingNames, diagnostics); } return parameters; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs index 832210b4ea495..a19dcff0d7038 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs @@ -73,7 +73,7 @@ private enum ParameterSyntaxKind : byte _lazyDefaultSyntaxValue = ConstantValue.Unset; } - private Binder ParameterBinderOpt => (ContainingSymbol as SourceMethodSymbolWithAttributes)?.ParameterBinder; + private Binder WithTypeParametersBinderOpt => (ContainingSymbol as SourceMethodSymbolWithAttributes)?.WithTypeParametersBinder; internal sealed override SyntaxReference SyntaxReference => _syntaxRef; @@ -246,9 +246,9 @@ private ConstantValue DefaultSyntaxValue } } - private Binder GetBinder(SyntaxNode syntax) + private Binder GetDefaultParameterValueBinder(SyntaxNode syntax) { - var binder = ParameterBinderOpt; + var binder = WithTypeParametersBinderOpt; // If binder is null, then get it from the compilation. Otherwise use the provided binder. // Don't always get it from the compilation because we might be in a speculative context (local function parameter), @@ -289,7 +289,7 @@ private void NullableAnalyzeParameterDefaultValueFromAttributes() return; } - var binder = GetBinder(parameterSyntax); + var binder = GetDefaultParameterValueBinder(parameterSyntax); // Nullable warnings *within* the attribute argument (such as a W-warning for `(string)null`) // are reported when we nullable-analyze attribute arguments separately from here. @@ -329,7 +329,7 @@ private ConstantValue MakeDefaultExpression(BindingDiagnosticBag diagnostics, ou return ConstantValue.NotAvailable; } - binder = GetBinder(defaultSyntax); + binder = GetDefaultParameterValueBinder(defaultSyntax); Binder binderForDefault = binder.CreateBinderForParameterDefaultValue(this, defaultSyntax); Debug.Assert(binderForDefault.InParameterDefaultValue); Debug.Assert(binderForDefault.ContainingMemberOrLambda == ContainingSymbol); @@ -551,7 +551,7 @@ internal sealed override CustomAttributesBag GetAttributesB else { var attributeSyntax = this.GetAttributeDeclarations(); - bagCreatedOnThisThread = LoadAndValidateAttributes(attributeSyntax, ref _lazyCustomAttributesBag, binderOpt: ParameterBinderOpt); + bagCreatedOnThisThread = LoadAndValidateAttributes(attributeSyntax, ref _lazyCustomAttributesBag, binderOpt: WithTypeParametersBinderOpt); } if (bagCreatedOnThisThread) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs index fb047ab0bfb2b..ae7179d9ef187 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs @@ -62,9 +62,9 @@ protected SourceMethodSymbolWithAttributes(SyntaxReference syntaxReferenceOpt) } } - internal virtual Binder? SignatureBinder => null; + internal virtual Binder? OuterBinder => null; - internal virtual Binder? ParameterBinder => null; + internal virtual Binder? WithTypeParametersBinder => null; #nullable disable @@ -283,7 +283,7 @@ private CustomAttributesBag GetAttributesBag(ref CustomAttr declarations, ref lazyCustomAttributesBag, symbolPart, - binderOpt: SignatureBinder); + binderOpt: OuterBinder); } if (bagCreatedOnThisThread) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs index 0364e5248e383..7ae3bfd1e8c50 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs @@ -185,7 +185,7 @@ internal virtual CustomAttributesBag GetAttributesBag() lazyAttributesStored = LoadAndValidateAttributes( OneOrMany.Create(this.MergedAttributeDeclarationSyntaxLists), ref _lazyCustomAttributesBag, - binderOpt: (ContainingSymbol as LocalFunctionSymbol)?.SignatureBinder); + binderOpt: (ContainingSymbol as LocalFunctionSymbol)?.WithTypeParametersBinder); } else { diff --git a/src/Compilers/CSharp/Portable/Syntax/LookupPosition.cs b/src/Compilers/CSharp/Portable/Syntax/LookupPosition.cs index e2ec607c57024..9015176b4b586 100644 --- a/src/Compilers/CSharp/Portable/Syntax/LookupPosition.cs +++ b/src/Compilers/CSharp/Portable/Syntax/LookupPosition.cs @@ -202,7 +202,7 @@ internal static bool IsInMethodTypeParameterScope(int position, MethodDeclaratio if (methodDecl.TypeParameterList == null) { - // no type parameters => nothing can be in their scope + // no type parameters => they are not in scope return false; } @@ -220,14 +220,41 @@ internal static bool IsInMethodTypeParameterScope(int position, MethodDeclaratio var explicitInterfaceSpecifier = methodDecl.ExplicitInterfaceSpecifier; var firstNameToken = explicitInterfaceSpecifier == null ? methodDecl.Identifier : explicitInterfaceSpecifier.GetFirstToken(); - - var typeParams = methodDecl.TypeParameterList; - var firstPostNameToken = typeParams == null ? methodDecl.ParameterList.OpenParenToken : typeParams.LessThanToken; + var firstPostNameToken = methodDecl.TypeParameterList.LessThanToken; // Scope does not include method name. return !IsBetweenTokens(position, firstNameToken, firstPostNameToken); } + internal static bool IsInLocalFunctionTypeParameterScope(int position, LocalFunctionStatementSyntax localFunction) + { + Debug.Assert(localFunction != null); + + if (localFunction.TypeParameterList == null) + { + // no type parameters => they are not in scope + return false; + } + + // optimization for a common case - when position is in the ReturnType, we can see type parameters + if (localFunction.ReturnType.FullSpan.Contains(position)) + { + return true; + } + + // Must be in the local function, but not in an attribute on the method. + if (IsInAttributeSpecification(position, localFunction.AttributeLists)) + { + return false; + } + + var firstNameToken = localFunction.Identifier; + var firstPostNameToken = localFunction.TypeParameterList.LessThanToken; + + // Scope does not include local function name. + return !IsBetweenTokens(position, firstNameToken, firstPostNameToken); + } + /// /// Used to determine whether it would be appropriate to use the binder for the statement (if any). /// Not used to determine whether the position is syntactically within the statement. diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs index 7fe132336e9b2..80e3ad4c285ec 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs @@ -6309,5 +6309,375 @@ class A : Attribute { } Diagnostic(ErrorCode.ERR_LambdaWithAttributesToExpressionTree, "[return: A] ([A] x) => x").WithLocation(5, 32) ); } + + [Fact] + public void ParameterScope_NotInMethodAttributeNameOf() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + + var _ = + [My(nameof(parameter))] // 1 + void(int parameter) => { }; + } + + [My(nameof(parameter))] // 2 + void M2(int parameter) { } +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics( + // (8,24): error CS0103: The name 'parameter' does not exist in the current context + // [My(nameof(parameter))] // 1 + Diagnostic(ErrorCode.ERR_NameNotInContext, "parameter").WithArguments("parameter").WithLocation(8, 24), + // (12,16): error CS0103: The name 'parameter' does not exist in the current context + // [My(nameof(parameter))] // 2 + Diagnostic(ErrorCode.ERR_NameNotInContext, "parameter").WithArguments("parameter").WithLocation(12, 16) + ); + + VerifyParameter(comp, 0); + VerifyParameter(comp, 1); + } + + /// + /// Look for usages of "parameter" and verify the index-th one. + /// + private void VerifyParameter(CSharpCompilation comp, int index) + { + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var parameterUsages = tree.GetRoot().DescendantNodes().OfType() + .Where(i => i.Identifier.ValueText == "parameter") + .Where(i => i.Ancestors().Any(a => a.IsKind(SyntaxKind.Attribute) || a.IsKind(SyntaxKind.DefaultExpression) || a.IsKind(SyntaxKind.InvocationExpression))) + .ToArray(); + + var parameterUsage = parameterUsages[index]; + + Assert.Null(model.GetSymbolInfo(parameterUsage).Symbol); + Assert.True(model.GetTypeInfo(parameterUsage).Type.IsErrorType()); + Assert.DoesNotContain("parameter", model.LookupSymbols(parameterUsage.Position).ToTestDisplayStrings()); + } + + [Fact] + public void ParameterScope_NotInMethodAttributeTypeOf() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + + var _ = + [My(typeof(parameter))] // 1 + void(int parameter) => { }; + } + + [My(typeof(parameter))] // 2 + void M2(int parameter) { } +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics( + // (8,24): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // [My(typeof(parameter))] // 1 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(8, 24), + // (12,16): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // [My(typeof(parameter))] // 2 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(12, 16) + ); + + VerifyParameter(comp, 0); + VerifyParameter(comp, 1); + } + + [Fact] + public void ParameterScope_NotInMethodAttribute() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + var _ = + [My(parameter)] // 1 + void (int parameter) => { }; + } + + [My(parameter)] // 2 + void M2(int parameter) { } +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(object o) { } +} +"); + comp.VerifyDiagnostics( + // (7,17): error CS0103: The name 'parameter' does not exist in the current context + // [My(parameter)] // 1 + Diagnostic(ErrorCode.ERR_NameNotInContext, "parameter").WithArguments("parameter").WithLocation(7, 17), + // (11,9): error CS0103: The name 'parameter' does not exist in the current context + // [My(parameter)] // 2 + Diagnostic(ErrorCode.ERR_NameNotInContext, "parameter").WithArguments("parameter").WithLocation(11, 9) + ); + + VerifyParameter(comp, 0); + VerifyParameter(comp, 1); + } + + [Fact] + public void ParameterScope_NotInMethodAttributeTypeArgument() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + var _ = + [My] // 1 + void (int parameter) => { }; + } + + [My] // 2 + void M2(int parameter) { } +} + +public class MyAttribute : System.Attribute +{ +} +"); + comp.VerifyDiagnostics( + // (7,17): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // [My] // 1 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(7, 17), + // (11,9): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // [My] // 2 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(11, 9) + ); + + VerifyParameter(comp, 0); + VerifyParameter(comp, 1); + } + + [Fact] + public void ParameterScope_NotAsMethodAttributeType() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + var _ = + [parameter] // 1 + void (System.Attribute parameter) => { }; + } + + [parameter] // 2 + void M2(System.Attribute parameter) { } +} +"); + comp.VerifyDiagnostics( + // (7,14): error CS0246: The type or namespace name 'parameterAttribute' could not be found (are you missing a using directive or an assembly reference?) + // [parameter] // 1 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameterAttribute").WithLocation(7, 14), + // (7,14): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // [parameter] // 1 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(7, 14), + // (11,6): error CS0246: The type or namespace name 'parameterAttribute' could not be found (are you missing a using directive or an assembly reference?) + // [parameter] // 2 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameterAttribute").WithLocation(11, 6), + // (11,6): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // [parameter] // 2 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(11, 6) + ); + + VerifyParameter(comp, 0); + VerifyParameter(comp, 1); + } + + [Fact] + public void ParameterScope_NotInParameterAttribute() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + var _ = void ([My(parameter)] int parameter) => throw null; + } + + void M2([My(parameter)] int parameter) => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics( + // (6,27): error CS0103: The name 'parameter' does not exist in the current context + // var _ = void ([My(parameter)] int parameter) => throw null; + Diagnostic(ErrorCode.ERR_NameNotInContext, "parameter").WithArguments("parameter").WithLocation(6, 27), + // (9,17): error CS0103: The name 'parameter' does not exist in the current context + // void M2([My(parameter)] int parameter) => throw null; + Diagnostic(ErrorCode.ERR_NameNotInContext, "parameter").WithArguments("parameter").WithLocation(9, 17) + ); + + VerifyParameter(comp, 0); + VerifyParameter(comp, 1); + } + + [Fact] + public void ParameterScope_NotInParameterAttributeNameOf() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + var _ = void ([My(nameof(parameter))] int parameter) => throw null; + } + + void M2([My(nameof(parameter))] int parameter) => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics( + // (6,34): error CS0103: The name 'parameter' does not exist in the current context + // var _ = void ([My(nameof(parameter))] int parameter) => throw null; + Diagnostic(ErrorCode.ERR_NameNotInContext, "parameter").WithArguments("parameter").WithLocation(6, 34), + // (9,24): error CS0103: The name 'parameter' does not exist in the current context + // void M2([My(nameof(parameter))] int parameter) => throw null; + Diagnostic(ErrorCode.ERR_NameNotInContext, "parameter").WithArguments("parameter").WithLocation(9, 24) + ); + + VerifyParameter(comp, 0); + VerifyParameter(comp, 1); + } + + [Fact] + public void ParameterScope_InParameterDefaultValueNameOf() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + var _ = void (string parameter = nameof(parameter)) => throw null; + } + + void M2(string parameter = nameof(parameter)) => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics( + // (6,40): error CS1065: Default values are not valid in this context. + // var _ = void (string parameter = nameof(parameter)) => throw null; + Diagnostic(ErrorCode.ERR_DefaultValueNotAllowed, "=").WithLocation(6, 40), + // (9,39): error CS0103: The name 'parameter' does not exist in the current context + // void M2(string parameter = nameof(parameter)) => throw null; + Diagnostic(ErrorCode.ERR_NameNotInContext, "parameter").WithArguments("parameter").WithLocation(9, 39) + ); + } + + [Fact] + public void ParameterScope_NotAsParameterAttributeType() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + var _ = void ([parameter] System.Attribute parameter) => throw null; + } + + void M2([parameter] System.Attribute parameter) => throw null; +} +"); + comp.VerifyDiagnostics( + // (6,24): error CS0246: The type or namespace name 'parameterAttribute' could not be found (are you missing a using directive or an assembly reference?) + // var _ = void ([parameter] System.Attribute parameter) => throw null; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameterAttribute").WithLocation(6, 24), + // (6,24): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // var _ = void ([parameter] System.Attribute parameter) => throw null; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(6, 24), + // (9,14): error CS0246: The type or namespace name 'parameterAttribute' could not be found (are you missing a using directive or an assembly reference?) + // void M2([parameter] System.Attribute parameter) => throw null; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameterAttribute").WithLocation(9, 14), + // (9,14): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // void M2([parameter] System.Attribute parameter) => throw null; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(9, 14) + ); + + VerifyParameter(comp, 0); + VerifyParameter(comp, 1); + } + + [Fact] + public void ParameterScope_NotInReturnType() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + var _ = parameter (int parameter) => throw null; + } + + parameter M2(int parameter) => throw null; +} +"); + comp.VerifyDiagnostics( + // (6,17): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // var _ = parameter (int parameter) => throw null; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(6, 17), + // (9,5): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // parameter M2(int parameter) => throw null; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(9, 5) + ); + } + + [Fact] + public void ParameterScope_NotInParameterType() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + var _ = void (parameter parameter) => throw null; + } + + void M2(parameter parameter) => throw null; +} +"); + comp.VerifyDiagnostics( + // (6,23): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // var _ = void (parameter parameter) => throw null; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(6, 23), + // (9,13): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // void M2(parameter parameter) => throw null; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(9, 13) + ); + } } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs index 1367310b17dfa..127d02f7d48c7 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs @@ -7117,5 +7117,1316 @@ async void F4() // async static void B4() { } Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "await").WithArguments("await").WithLocation(23, 30)); } + + [Fact, WorkItem(59775, "https://github.com/dotnet/roslyn/issues/59775")] + public void TypeParameterScope_NotInMethodAttributeNameOf() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(); + + [My(nameof(TParameter))] // 1 + void local() { } + } + + [My(nameof(TParameter))] // 2 + void M2() { } +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics( + // (8,20): error CS0103: The name 'TParameter' does not exist in the current context + // [My(nameof(TParameter))] // 1 + Diagnostic(ErrorCode.ERR_NameNotInContext, "TParameter").WithArguments("TParameter").WithLocation(8, 20), + // (12,16): error CS0103: The name 'TParameter' does not exist in the current context + // [My(nameof(TParameter))] // 2 + Diagnostic(ErrorCode.ERR_NameNotInContext, "TParameter").WithArguments("TParameter").WithLocation(12, 16) + ); + + VerifyTParameter(comp, 0, null); + VerifyTParameter(comp, 1, null); + } + + /// + /// Look for usages of "TParameter" and verify the index-th one. + /// + private void VerifyTParameter(CSharpCompilation comp, int index, string expectedMethod, bool findAnyways = false, bool lookupFailsAnyways = false) + { + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var tParameterUsages = tree.GetRoot().DescendantNodes().OfType() + .Where(i => i.Identifier.ValueText == "TParameter") + .Where(i => i.Ancestors().Any(a => a.IsKind(SyntaxKind.Attribute) || a.IsKind(SyntaxKind.TypeConstraint) || a.IsKind(SyntaxKind.DefaultExpression) || a.IsKind(SyntaxKind.InvocationExpression))) + .ToArray(); + + var tParameterUsage = tParameterUsages[index]; + + var symbol = model.GetSymbolInfo(tParameterUsage).Symbol; + if (expectedMethod is null) + { + Assert.Null(symbol); + + var typeInfo = model.GetTypeInfo(tParameterUsage); + if (findAnyways) + { + // In certain cases, like `[TParameter]`, we're able to bind the attribute, find the type but reject it. + // So GetTypeInfo does return a type. + Assert.Equal(SymbolKind.TypeParameter, typeInfo.Type.Kind); + } + else + { + Assert.True(typeInfo.Type.IsErrorType()); + } + + Assert.Equal(findAnyways, model.LookupSymbols(tParameterUsage.Position).ToTestDisplayStrings().Contains("TParameter")); + } + else + { + Assert.Equal(expectedMethod, symbol.ContainingSymbol.ToTestDisplayString()); + Assert.Equal(SymbolKind.TypeParameter, model.GetTypeInfo(tParameterUsage).Type.Kind); + Assert.Equal(!lookupFailsAnyways, model.LookupSymbols(tParameterUsage.Position).ToTestDisplayStrings().Contains("TParameter")); + } + } + + [Fact] + public void TypeParameterScope_NotInMethodAttribute() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(); + + [My(TParameter)] // 1 + void local() { } + } + + [My(TParameter)] // 2 + void M2() { } +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(object o) { } +} +"); + comp.VerifyDiagnostics( + // (8,13): error CS0103: The name 'TParameter' does not exist in the current context + // [My(TParameter)] // 1 + Diagnostic(ErrorCode.ERR_NameNotInContext, "TParameter").WithArguments("TParameter").WithLocation(8, 13), + // (12,9): error CS0103: The name 'TParameter' does not exist in the current context + // [My(TParameter)] // 2 + Diagnostic(ErrorCode.ERR_NameNotInContext, "TParameter").WithArguments("TParameter").WithLocation(12, 9) + ); + + VerifyTParameter(comp, 0, null); + VerifyTParameter(comp, 1, null); + } + + [Fact] + public void TypeParameterScope_NotInMethodAttributeTypeArgument() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(); + + [My] // 1 + void local() { } + } + + [My] // 2 + void M2() { } +} + +public class MyAttribute : System.Attribute +{ +} +"); + comp.VerifyDiagnostics( + // (8,13): error CS0246: The type or namespace name 'TParameter' could not be found (are you missing a using directive or an assembly reference?) + // [My] // 1 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "TParameter").WithArguments("TParameter").WithLocation(8, 13), + // (12,9): error CS0246: The type or namespace name 'TParameter' could not be found (are you missing a using directive or an assembly reference?) + // [My] // 2 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "TParameter").WithArguments("TParameter").WithLocation(12, 9) + ); + + VerifyTParameter(comp, 0, null); + VerifyTParameter(comp, 1, null); + } + + [Fact] + public void TypeParameterScope_NotAsMethodAttributeType() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(); + + [TParameter] // 1 + void local() where TParameter : System.Attribute { } + } + + [TParameter] // 2 + void M2() where TParameter : System.Attribute { } +} +"); + comp.VerifyDiagnostics( + // (8,10): error CS0246: The type or namespace name 'TParameterAttribute' could not be found (are you missing a using directive or an assembly reference?) + // [TParameter] // 1 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "TParameter").WithArguments("TParameterAttribute").WithLocation(8, 10), + // (8,10): error CS0246: The type or namespace name 'TParameter' could not be found (are you missing a using directive or an assembly reference?) + // [TParameter] // 1 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "TParameter").WithArguments("TParameter").WithLocation(8, 10), + // (12,6): error CS0246: The type or namespace name 'TParameterAttribute' could not be found (are you missing a using directive or an assembly reference?) + // [TParameter] // 2 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "TParameter").WithArguments("TParameterAttribute").WithLocation(12, 6), + // (12,6): error CS0246: The type or namespace name 'TParameter' could not be found (are you missing a using directive or an assembly reference?) + // [TParameter] // 2 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "TParameter").WithArguments("TParameter").WithLocation(12, 6) + ); + + VerifyTParameter(comp, 0, null); + VerifyTParameter(comp, 1, null); + } + + [Fact] + public void TypeParameterScope_NotInMethodAttributeDefault() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(); + + [My(default(TParameter))] + void local() where TParameter : class => throw null; + } + + [My(default(TParameter))] + void M2() where TParameter : class => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(object o) { } +} +"); + comp.VerifyDiagnostics( + // (8,21): error CS0246: The type or namespace name 'TParameter' could not be found (are you missing a using directive or an assembly reference?) + // [My(default(TParameter))] + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "TParameter").WithArguments("TParameter").WithLocation(8, 21), + // (12,17): error CS0246: The type or namespace name 'TParameter' could not be found (are you missing a using directive or an assembly reference?) + // [My(default(TParameter))] + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "TParameter").WithArguments("TParameter").WithLocation(12, 17) + ); + + VerifyTParameter(comp, 0, null); + VerifyTParameter(comp, 1, null); + } + + [Fact, WorkItem(60110, "https://github.com/dotnet/roslyn/issues/60110")] + public void TypeParameterScope_NotInParameterAttribute() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(0); + + void local([My(TParameter)] int i) => throw null; + } + + void M2([My(TParameter)] int i) => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + // TParameter unexpectedly was found in local function case because of IsInMethodBody logic + // Tracked by https://github.com/dotnet/roslyn/issues/60110 + comp.VerifyDiagnostics( + // (8,36): error CS0119: 'TParameter' is a type, which is not valid in the given context + // void local([My(TParameter)] int i) => throw null; + Diagnostic(ErrorCode.ERR_BadSKunknown, "TParameter").WithArguments("TParameter", "type").WithLocation(8, 36), + // (11,29): error CS0103: The name 'TParameter' does not exist in the current context + // void M2([My(TParameter)] int i) => throw null; + Diagnostic(ErrorCode.ERR_NameNotInContext, "TParameter").WithArguments("TParameter").WithLocation(11, 29) + ); + + //VerifyTParameter(comp, 0, null); + VerifyTParameter(comp, 1, null); + } + + [Fact] + public void TypeParameterScope_InParameterAttributeNameOf() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(0); + + void local([My(nameof(TParameter))] int i) => throw null; + } + + void M2([My(nameof(TParameter))] int i) => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics(); + + VerifyTParameter(comp, 0, "void local(System.Int32 i)"); + // LookupSymbols fails to find TParameter + // Tracked by https://github.com/dotnet/roslyn/issues/60194 + VerifyTParameter(comp, 1, "void C.M2(System.Int32 i)", lookupFailsAnyways: true); + } + + [Fact] + public void TypeParameterScope_InParameterAttributeTypeOf() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(0); + + void local([My(typeof(TParameter))] int i) => throw null; + } + + void M2([My(typeof(TParameter))] int i) => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics( + // (8,36): error CS1503: Argument 1: cannot convert from 'System.Type' to 'string' + // void local([My(typeof(TParameter))] int i) => throw null; + Diagnostic(ErrorCode.ERR_BadArgType, "typeof(TParameter)").WithArguments("1", "System.Type", "string").WithLocation(8, 36), + // (11,29): error CS1503: Argument 1: cannot convert from 'System.Type' to 'string' + // void M2([My(typeof(TParameter))] int i) => throw null; + Diagnostic(ErrorCode.ERR_BadArgType, "typeof(TParameter)").WithArguments("1", "System.Type", "string").WithLocation(11, 29) + ); + + VerifyTParameter(comp, 0, "void local(System.Int32 i)"); + VerifyTParameter(comp, 1, "void C.M2(System.Int32 i)"); + } + + [Fact] + public void TypeParameterScope_InParameterAttributeSizeOf() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(0); + + void local([My(sizeof(TParameter))] int i) => throw null; + } + + void M2([My(sizeof(TParameter))] int i) => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(int i) { } +} +"); + comp.VerifyDiagnostics( + // (8,36): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('TParameter') + // void local([My(sizeof(TParameter))] int i) => throw null; + Diagnostic(ErrorCode.ERR_ManagedAddr, "sizeof(TParameter)").WithArguments("TParameter").WithLocation(8, 36), + // (8,36): error CS0233: 'TParameter' does not have a predefined size, therefore sizeof can only be used in an unsafe context + // void local([My(sizeof(TParameter))] int i) => throw null; + Diagnostic(ErrorCode.ERR_SizeofUnsafe, "sizeof(TParameter)").WithArguments("TParameter").WithLocation(8, 36), + // (11,29): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('TParameter') + // void M2([My(sizeof(TParameter))] int i) => throw null; + Diagnostic(ErrorCode.ERR_ManagedAddr, "sizeof(TParameter)").WithArguments("TParameter").WithLocation(11, 29), + // (11,29): error CS0233: 'TParameter' does not have a predefined size, therefore sizeof can only be used in an unsafe context + // void M2([My(sizeof(TParameter))] int i) => throw null; + Diagnostic(ErrorCode.ERR_SizeofUnsafe, "sizeof(TParameter)").WithArguments("TParameter").WithLocation(11, 29) + ); + + VerifyTParameter(comp, 0, "void local(System.Int32 i)"); + VerifyTParameter(comp, 1, "void C.M2(System.Int32 i)"); + } + + [Fact] + public void TypeParameterScope_InParameterAttributeDefault() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(0); + + void local([My(default(TParameter))] int i) where TParameter : class => throw null; + } + + void M2([My(default(TParameter))] int i) where TParameter : class => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(object o) { } +} +"); + comp.VerifyDiagnostics(); + + VerifyTParameter(comp, 0, "void local(System.Int32 i)"); + VerifyTParameter(comp, 1, "void C.M2(System.Int32 i)"); + } + + [Fact] + public void TypeParameterScope_NotAsParameterAttributeType() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(0); + + void local([TParameter] int i) where TParameter : System.Attribute => throw null; + } + + void M2([TParameter] int i) where TParameter : System.Attribute => throw null; +} +"); + comp.VerifyDiagnostics( + // (8,33): error CS0616: 'TParameter' is not an attribute class + // void local([TParameter] int i) where TParameter : System.Attribute => throw null; + Diagnostic(ErrorCode.ERR_NotAnAttributeClass, "TParameter").WithArguments("TParameter").WithLocation(8, 33), + // (11,26): error CS0616: 'TParameter' is not an attribute class + // void M2([TParameter] int i) where TParameter : System.Attribute => throw null; + Diagnostic(ErrorCode.ERR_NotAnAttributeClass, "TParameter").WithArguments("TParameter").WithLocation(11, 26) + ); + + VerifyTParameter(comp, 0, null, findAnyways: true); + VerifyTParameter(comp, 1, null, findAnyways: true); + } + + [Fact] + public void TypeParameterScope_InReturnType() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(); + + TParameter local() => throw null; + } + + TParameter M2() => throw null; +} +"); + comp.VerifyDiagnostics(); + } + + [Fact] + public void TypeParameterScope_InParameterType() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(null); + + void local(TParameter p) => throw null; + } + + void M2(TParameter p) => throw null; +} +"); + comp.VerifyDiagnostics(); + } + + [Fact] + public void TypeParameterScope_InTypeConstraint() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(); + + void local() where TParameter2 : TParameter => throw null; + } + + void M2() where TParameter2 : TParameter => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics(); + + VerifyTParameter(comp, 0, "void local()"); + VerifyTParameter(comp, 1, "void C.M2()"); + } + + [Fact] + public void TypeParameterScope_NotInMethodAttributeTypeOf() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(); + + [My(typeof(TParameter))] + void local() => throw null; + } + + [My(typeof(TParameter))] + void M2() => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics( + // (8,20): error CS0246: The type or namespace name 'TParameter' could not be found (are you missing a using directive or an assembly reference?) + // [My(typeof(TParameter))] + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "TParameter").WithArguments("TParameter").WithLocation(8, 20), + // (12,16): error CS0246: The type or namespace name 'TParameter' could not be found (are you missing a using directive or an assembly reference?) + // [My(typeof(TParameter))] + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "TParameter").WithArguments("TParameter").WithLocation(12, 16) + ); + + VerifyTParameter(comp, 0, null); + VerifyTParameter(comp, 1, null); + } + + [Fact] + public void TypeParameterScope_NotInTypeParameterAttribute() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(); + + void local<[My(TParameter)] TParameter>() => throw null; + } + + void M2<[My(TParameter)] TParameter>() => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + // TParameter unexpectedly was found in local function case because of IsInMethodBody logic + // Tracked by https://github.com/dotnet/roslyn/issues/60110 + comp.VerifyDiagnostics( + // (8,24): error CS0119: 'TParameter' is a type, which is not valid in the given context + // void local<[My(TParameter)] TParameter>() => throw null; + Diagnostic(ErrorCode.ERR_BadSKunknown, "TParameter").WithArguments("TParameter", "type").WithLocation(8, 24), + // (11,17): error CS0103: The name 'TParameter' does not exist in the current context + // void M2<[My(TParameter)] TParameter>() => throw null; + Diagnostic(ErrorCode.ERR_NameNotInContext, "TParameter").WithArguments("TParameter").WithLocation(11, 17) + ); + + //VerifyTParameter(comp, 0, null); + VerifyTParameter(comp, 1, null); + } + + [Fact] + public void TypeParameterScope_InTypeParameterAttributeNameOf() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(); + + void local<[My(nameof(TParameter))] TParameter>() => throw null; + } + + void M2<[My(nameof(TParameter))] TParameter>() => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics(); + + VerifyTParameter(comp, 0, "void local()"); + // LookupSymbols fails to find TParameter + // Tracked by https://github.com/dotnet/roslyn/issues/60194 + VerifyTParameter(comp, 1, "void C.M2()", lookupFailsAnyways: true); + } + + [Fact] + public void TypeParameterScope_InTypeParameterAttributeDefault() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(); + + void local<[My(default(TParameter))] TParameter>() where TParameter : class => throw null; + } + + void M2<[My(default(TParameter))] TParameter>() where TParameter : class => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(object o) { } +} +"); + comp.VerifyDiagnostics(); + + VerifyTParameter(comp, 0, "void local()"); + VerifyTParameter(comp, 1, "void C.M2()"); + } + + [Fact] + public void TypeParameterScope_NotAsTypeParameterAttributeType() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(); + + void local<[TParameter] TParameter>() where TParameter : System.Attribute => throw null; + } + + void M2<[TParameter] TParameter>() where TParameter : System.Attribute => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics( + // (8,21): error CS0616: 'TParameter' is not an attribute class + // void local<[TParameter] TParameter>() where TParameter : System.Attribute => throw null; + Diagnostic(ErrorCode.ERR_NotAnAttributeClass, "TParameter").WithArguments("TParameter").WithLocation(8, 21), + // (11,14): error CS0616: 'TParameter' is not an attribute class + // void M2<[TParameter] TParameter>() where TParameter : System.Attribute => throw null; + Diagnostic(ErrorCode.ERR_NotAnAttributeClass, "TParameter").WithArguments("TParameter").WithLocation(11, 14) + ); + + VerifyTParameter(comp, 0, null, findAnyways: true); + VerifyTParameter(comp, 1, null, findAnyways: true); + } + + [Fact] + public void TypeParameterScope_AsParameterDefaultDefaultValue() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(); + + void local(TParameter s = default(TParameter)) => throw null; + } + + void M2(TParameter s = default(TParameter)) => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics(); + + VerifyTParameter(comp, 0, "void local([TParameter s = default(TParameter)])"); + VerifyTParameter(comp, 1, "void C.M2([TParameter s = default(TParameter)])"); + } + + [Fact] + public void TypeParameterScope_AsParameterNameOfDefaultValue() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(); + + void local(string s = nameof(TParameter)) => throw null; + } + + void M2(string s = nameof(TParameter)) => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics(); + + VerifyTParameter(comp, 0, @"void local([System.String s = ""TParameter""])"); + // LookupSymbols fails to find TParameter + // Tracked by https://github.com/dotnet/roslyn/issues/60194 + VerifyTParameter(comp, 1, @"void C.M2([System.String s = ""TParameter""])", lookupFailsAnyways: true); + } + + [Fact] + public void ParameterScope_NotInMethodAttributeNameOf() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(0); + + [My(nameof(parameter))] // 1 + void local(int parameter) { } + } + + [My(nameof(parameter))] // 2 + void M2(int parameter) { } +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics( + // (8,20): error CS0103: The name 'parameter' does not exist in the current context + // [My(nameof(parameter))] // 1 + Diagnostic(ErrorCode.ERR_NameNotInContext, "parameter").WithArguments("parameter").WithLocation(8, 20), + // (12,16): error CS0103: The name 'parameter' does not exist in the current context + // [My(nameof(parameter))] // 2 + Diagnostic(ErrorCode.ERR_NameNotInContext, "parameter").WithArguments("parameter").WithLocation(12, 16) + ); + + VerifyParameter(comp, 0, null); + VerifyParameter(comp, 1, null); + } + + /// + /// Look for usages of "parameter" and verify the index-th one. + /// + private void VerifyParameter(CSharpCompilation comp, int index, string expectedMethod) + { + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var parameterUsages = tree.GetRoot().DescendantNodes().OfType() + .Where(i => i.Identifier.ValueText == "parameter") + .Where(i => i.Ancestors().Any(a => a.IsKind(SyntaxKind.Attribute) || a.IsKind(SyntaxKind.TypeConstraint) || a.IsKind(SyntaxKind.DefaultExpression) || a.IsKind(SyntaxKind.InvocationExpression))) + .ToArray(); + + var parameterUsage = parameterUsages[index]; + + var symbol = model.GetSymbolInfo(parameterUsage).Symbol; + if (expectedMethod is null) + { + Assert.Null(symbol); + Assert.True(model.GetTypeInfo(parameterUsage).Type.IsErrorType()); + Assert.DoesNotContain("parameter", model.LookupSymbols(parameterUsage.Position).ToTestDisplayStrings()); + } + else + { + Assert.Equal(expectedMethod, symbol.ContainingSymbol.ToTestDisplayString()); + Assert.Equal(SymbolKind.Parameter, model.GetTypeInfo(parameterUsage).Type.Kind); + Assert.Contains(symbol, model.LookupSymbols(parameterUsage.Position)); + } + } + + [Fact] + public void ParameterScope_NotInMethodAttribute() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(0); + + [My(parameter)] // 1 + void local(int parameter) { } + } + + [My(parameter)] // 2 + void M2(int parameter) { } +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(object o) { } +} +"); + comp.VerifyDiagnostics( + // (8,13): error CS0103: The name 'parameter' does not exist in the current context + // [My(parameter)] // 1 + Diagnostic(ErrorCode.ERR_NameNotInContext, "parameter").WithArguments("parameter").WithLocation(8, 13), + // (12,9): error CS0103: The name 'parameter' does not exist in the current context + // [My(parameter)] // 2 + Diagnostic(ErrorCode.ERR_NameNotInContext, "parameter").WithArguments("parameter").WithLocation(12, 9) + ); + + VerifyParameter(comp, 0, null); + VerifyParameter(comp, 1, null); + } + + [Fact] + public void ParameterScope_NotInMethodAttributeTypeArgument() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(0); + + [My] // 1 + void local(int parameter) { } + } + + [My] // 2 + void M2(int parameter) { } +} + +public class MyAttribute : System.Attribute +{ +} +"); + comp.VerifyDiagnostics( + // (8,13): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // [My] // 1 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(8, 13), + // (12,9): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // [My] // 2 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(12, 9) + ); + + VerifyParameter(comp, 0, null); + VerifyParameter(comp, 1, null); + } + + [Fact] + public void ParameterScope_NotAsMethodAttributeType() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(null); + + [parameter] // 1 + void local(System.Attribute parameter) { } + } + + [parameter] // 2 + void M2(System.Attribute parameter) { } +} +"); + comp.VerifyDiagnostics( + // (8,10): error CS0246: The type or namespace name 'parameterAttribute' could not be found (are you missing a using directive or an assembly reference?) + // [parameter] // 1 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameterAttribute").WithLocation(8, 10), + // (8,10): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // [parameter] // 1 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(8, 10), + // (12,6): error CS0246: The type or namespace name 'parameterAttribute' could not be found (are you missing a using directive or an assembly reference?) + // [parameter] // 2 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameterAttribute").WithLocation(12, 6), + // (12,6): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // [parameter] // 2 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(12, 6) + ); + + VerifyParameter(comp, 0, null); + VerifyParameter(comp, 1, null); + } + + [Fact] + public void ParameterScope_NotInParameterAttribute() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(0); + + void local([My(parameter)] int parameter) => throw null; + } + + void M2([My(parameter)] int parameter) => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics( + // (8,24): error CS0103: The name 'parameter' does not exist in the current context + // void local([My(parameter)] int parameter) => throw null; + Diagnostic(ErrorCode.ERR_NameNotInContext, "parameter").WithArguments("parameter").WithLocation(8, 24), + // (11,17): error CS0103: The name 'parameter' does not exist in the current context + // void M2([My(parameter)] int parameter) => throw null; + Diagnostic(ErrorCode.ERR_NameNotInContext, "parameter").WithArguments("parameter").WithLocation(11, 17) + ); + + VerifyParameter(comp, 0, null); + VerifyParameter(comp, 1, null); + } + + [Fact] + public void ParameterScope_NotInParameterAttributeNameOf() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(0); + + void local([My(nameof(parameter))] int parameter) => throw null; + } + + void M2([My(nameof(parameter))] int parameter) => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics( + // (8,31): error CS0103: The name 'parameter' does not exist in the current context + // void local([My(nameof(parameter))] int parameter) => throw null; + Diagnostic(ErrorCode.ERR_NameNotInContext, "parameter").WithArguments("parameter").WithLocation(8, 31), + // (11,24): error CS0103: The name 'parameter' does not exist in the current context + // void M2([My(nameof(parameter))] int parameter) => throw null; + Diagnostic(ErrorCode.ERR_NameNotInContext, "parameter").WithArguments("parameter").WithLocation(11, 24) + ); + + VerifyParameter(comp, 0, null); + VerifyParameter(comp, 1, null); + } + + [Fact] + public void ParameterScope_NotAsParameterAttributeType() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(null); + + void local([parameter] System.Attribute parameter) => throw null; + } + + void M2([parameter] System.Attribute parameter) => throw null; +} +"); + comp.VerifyDiagnostics( + // (8,21): error CS0246: The type or namespace name 'parameterAttribute' could not be found (are you missing a using directive or an assembly reference?) + // void local([parameter] System.Attribute parameter) => throw null; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameterAttribute").WithLocation(8, 21), + // (8,21): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // void local([parameter] System.Attribute parameter) => throw null; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(8, 21), + // (11,14): error CS0246: The type or namespace name 'parameterAttribute' could not be found (are you missing a using directive or an assembly reference?) + // void M2([parameter] System.Attribute parameter) => throw null; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameterAttribute").WithLocation(11, 14), + // (11,14): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // void M2([parameter] System.Attribute parameter) => throw null; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(11, 14) + ); + + VerifyParameter(comp, 0, null); + VerifyParameter(comp, 1, null); + } + + [Fact] + public void ParameterScope_NotInReturnType() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(0); + + parameter local(int parameter) => throw null; + } + + parameter M2(int parameter) => throw null; +} +"); + comp.VerifyDiagnostics( + // (8,9): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // parameter local(int parameter) => throw null; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(8, 9), + // (11,5): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // parameter M2(int parameter) => throw null; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(11, 5) + ); + } + + [Fact] + public void ParameterScope_NotInParameterType() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(null); + + void local(parameter parameter) => throw null; + } + + void M2(parameter parameter) => throw null; +} +"); + comp.VerifyDiagnostics( + // (8,20): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // void local(parameter parameter) => throw null; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(8, 20), + // (11,25): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // void M2(parameter parameter) => throw null; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(11, 25) + ); + } + + [Fact] + public void ParameterScope_NotInTypeConstraint() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(0); + M2(0); + + void local(int parameter) where TParameter : parameter => throw null; + } + + void M2(int parameter) where TParameter : parameter => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics( + // (6,9): error CS0311: The type 'object' cannot be used as type parameter 'TParameter' in the generic type or method 'local(int)'. There is no implicit reference conversion from 'object' to 'parameter'. + // local(0); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "local").WithArguments("local(int)", "parameter", "TParameter", "object").WithLocation(6, 9), + // (7,9): error CS0311: The type 'object' cannot be used as type parameter 'TParameter' in the generic type or method 'C.M2(int)'. There is no implicit reference conversion from 'object' to 'parameter'. + // M2(0); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "M2").WithArguments("C.M2(int)", "parameter", "TParameter", "object").WithLocation(7, 9), + // (9,66): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // void local(int parameter) where TParameter : parameter => throw null; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(9, 66), + // (12,59): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // void M2(int parameter) where TParameter : parameter => throw null; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(12, 59) + ); + + VerifyParameter(comp, 0, null); + VerifyParameter(comp, 1, null); + } + + [Fact] + public void ParameterScope_NotAsParameterDefaultDefaultValue() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(); + + void local(string parameter = default(parameter)) => throw null; + } + + void M2(string parameter = default(parameter)) => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics( + // (8,27): error CS1750: A value of type 'parameter' cannot be used as a default parameter because there are no standard conversions to type 'string' + // void local(string parameter = default(parameter)) => throw null; + Diagnostic(ErrorCode.ERR_NoConversionForDefaultParam, "parameter").WithArguments("parameter", "string").WithLocation(8, 27), + // (8,47): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // void local(string parameter = default(parameter)) => throw null; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(8, 47), + // (11,20): error CS1750: A value of type 'parameter' cannot be used as a default parameter because there are no standard conversions to type 'string' + // void M2(string parameter = default(parameter)) => throw null; + Diagnostic(ErrorCode.ERR_NoConversionForDefaultParam, "parameter").WithArguments("parameter", "string").WithLocation(11, 20), + // (11,40): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // void M2(string parameter = default(parameter)) => throw null; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(11, 40) + ); + + VerifyParameter(comp, 0, null); + VerifyParameter(comp, 1, null); + } + + [Fact] + public void ParameterScope_NotAsParameterNameOfDefaultValue() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(); + + void local(string parameter = nameof(parameter)) => throw null; + } + + void M2(string parameter = nameof(parameter)) => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics( + // (8,46): error CS0103: The name 'parameter' does not exist in the current context + // void local(string parameter = nameof(parameter)) => throw null; + Diagnostic(ErrorCode.ERR_NameNotInContext, "parameter").WithArguments("parameter").WithLocation(8, 46), + // (11,39): error CS0103: The name 'parameter' does not exist in the current context + // void M2(string parameter = nameof(parameter)) => throw null; + Diagnostic(ErrorCode.ERR_NameNotInContext, "parameter").WithArguments("parameter").WithLocation(11, 39) + ); + + VerifyParameter(comp, 0, null); + VerifyParameter(comp, 1, null); + } + + [Fact] + public void MethodScope_InParameterAttribute() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(0); + + void local([My(local)] int i) => throw null; + } + + void M2([My(M2)] int i) => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics( + // (8,36): error CS1503: Argument 1: cannot convert from 'method group' to 'string' + // void local([My(local)] int i) => throw null; + Diagnostic(ErrorCode.ERR_BadArgType, "local").WithArguments("1", "method group", "string").WithLocation(8, 36), + // (11,29): error CS1503: Argument 1: cannot convert from 'method group' to 'string' + // void M2([My(M2)] int i) => throw null; + Diagnostic(ErrorCode.ERR_BadArgType, "M2").WithArguments("1", "method group", "string").WithLocation(11, 29) + ); + } + + [Fact] + public void MethodScope_InParameterAttributeNameOf() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(0); + + void local([My(nameof(local))] int i) => throw null; + } + + void M2([My(nameof(M2))] int i) => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics(); + } + + [Fact] + public void MethodScope_InTypeParameterAttribute() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(0); + + void local<[My(local)] TParameter>(int i) => throw null; + } + + void M2<[My(M2)] TParameter>(int i) => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics( + // (8,24): error CS1503: Argument 1: cannot convert from 'method group' to 'string' + // void local<[My(local)] TParameter>(int i) => throw null; + Diagnostic(ErrorCode.ERR_BadArgType, "local").WithArguments("1", "method group", "string").WithLocation(8, 24), + // (11,17): error CS1503: Argument 1: cannot convert from 'method group' to 'string' + // void M2<[My(M2)] TParameter>(int i) => throw null; + Diagnostic(ErrorCode.ERR_BadArgType, "M2").WithArguments("1", "method group", "string").WithLocation(11, 17) + ); + } + + [Fact] + public void MethodScope_InTypeParameterAttributeNameOf() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(0); + + void local<[My(nameof(local))] TParameter>(int i) => throw null; + } + + void M2<[My(nameof(M2))] TParameter>(int i) => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics(); + } + + [Fact] + public void MethodScope_InMethodAttribute() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(0); + + [My(local)] + void local(int i) => throw null; + } + + [My(M2)] + void M2(int i) => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics( + // (8,13): error CS1503: Argument 1: cannot convert from 'method group' to 'string' + // [My(local)] + Diagnostic(ErrorCode.ERR_BadArgType, "local").WithArguments("1", "method group", "string").WithLocation(8, 13), + // (12,9): error CS1503: Argument 1: cannot convert from 'method group' to 'string' + // [My(M2)] + Diagnostic(ErrorCode.ERR_BadArgType, "M2").WithArguments("1", "method group", "string").WithLocation(12, 9) + ); + } + + [Fact] + public void MethodScope_InMethodAttributeNameOf() + { + var comp = CreateCompilation(@" +class C +{ + void M() + { + local(0); + + [My(nameof(local))] + void local(int i) => throw null; + } + + [My(nameof(M2))] + void M2(int i) => throw null; +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} +"); + comp.VerifyDiagnostics(); + } } }