diff --git a/src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs b/src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs index bb8c6252f9b3b..d2b634fa18378 100644 --- a/src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs +++ b/src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs @@ -207,7 +207,7 @@ public override void VisitInvocationExpression(InvocationExpressionSyntax node) var oldEnclosing = _enclosing; WithTypeParametersBinder? withTypeParametersBinder; - WithParametersBinder? withParametersBinder; + Binder? withParametersBinder; // The LangVer check will be removed before shipping .NET 7. // Tracked by https://github.com/dotnet/roslyn/issues/60640 if (((_enclosing.Flags & BinderFlags.InContextualAttributeBinder) != 0) && _enclosing.Compilation.IsFeatureEnabled(MessageID.IDS_FeatureExtendedNameofScope)) @@ -249,8 +249,14 @@ static Symbol getAttributeTarget(Binder current) // We're bringing parameters in scope inside `nameof` in attributes on methods, their type parameters and parameters. // This also applies to local functions, lambdas, indexers and delegates. - static WithParametersBinder? getExtraWithParametersBinder(Binder enclosing, Symbol target) + static Binder? getExtraWithParametersBinder(Binder enclosing, Symbol target) { + if (target is LambdaSymbol lambda) + { + // lambda parameters have some special rules around parameters named `_` + return new WithLambdaParametersBinder(lambda, enclosing); + } + var parameters = target switch { SourcePropertyAccessorSymbol { MethodKind: MethodKind.PropertySet } setter => getSetterParameters(setter), diff --git a/src/Compilers/CSharp/Portable/Binder/NameofBinder.cs b/src/Compilers/CSharp/Portable/Binder/NameofBinder.cs index 9e24e3d374abf..668cad30a97f3 100644 --- a/src/Compilers/CSharp/Portable/Binder/NameofBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/NameofBinder.cs @@ -21,10 +21,10 @@ internal sealed class NameofBinder : Binder { private readonly SyntaxNode _nameofArgument; private readonly WithTypeParametersBinder? _withTypeParametersBinder; - private readonly WithParametersBinder? _withParametersBinder; + private readonly Binder? _withParametersBinder; private ThreeState _lazyIsNameofOperator; - internal NameofBinder(SyntaxNode nameofArgument, Binder next, WithTypeParametersBinder? withTypeParametersBinder, WithParametersBinder? withParametersBinder) + internal NameofBinder(SyntaxNode nameofArgument, Binder next, WithTypeParametersBinder? withTypeParametersBinder, Binder? withParametersBinder) : base(next) { _nameofArgument = nameofArgument; diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs index 26919900014f6..6c47e9e8716d5 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs @@ -6674,5 +6674,63 @@ void M() Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(9, 13) ); } + + [Fact, WorkItem(61143, "https://github.com/dotnet/roslyn/issues/61143")] + public void ParameterScope_LambdaDiscardParameter() + { + var comp = CreateCompilation(@" +class AAttribute : System.Attribute +{ + public AAttribute(string s) { } +} + +class C +{ + void M(int _) + { + System.Func a = [A(nameof(_))] (_, _) => 0; + } +} +"); + comp.VerifyDiagnostics(); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var discard = tree.GetRoot().DescendantNodes().OfType() + .Where(i => i.Identifier.ValueText == "_") + .Where(i => i.Ancestors().Any(a => a.IsKind(SyntaxKind.InvocationExpression))) + .Single(); + + Assert.Equal("System.Int32 _", model.GetSymbolInfo(discard).Symbol.ToTestDisplayString()); + } + + [Fact, WorkItem(61143, "https://github.com/dotnet/roslyn/issues/61143")] + public void ParameterScope_LambdaUnderscoreParameter() + { + var comp = CreateCompilation(@" +class AAttribute : System.Attribute +{ + public AAttribute(string s) { } +} + +class C +{ + void M(int _) + { + System.Func a = [A(nameof(_))] (_, x) => 0; + } +} +"); + comp.VerifyDiagnostics(); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var underscore = tree.GetRoot().DescendantNodes().OfType() + .Where(i => i.Identifier.ValueText == "_") + .Where(i => i.Ancestors().Any(a => a.IsKind(SyntaxKind.InvocationExpression))) + .Single(); + + Assert.Equal("System.String _", model.GetSymbolInfo(underscore).Symbol.ToTestDisplayString()); + } } }