diff --git a/src/Compilers/CSharp/Portable/Binder/Binder.cs b/src/Compilers/CSharp/Portable/Binder/Binder.cs
index 46c6af1a94164..732107a73a321 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder.cs
@@ -73,6 +73,8 @@ internal bool IsEarlyAttributeBinder
// Return the nearest enclosing node being bound as a nameof(...) argument, if any, or null if none.
protected virtual SyntaxNode EnclosingNameofArgument => null;
+ private bool IsInsideNameof => this.EnclosingNameofArgument != null;
+
///
/// Get the next binder in which to look up a name, if not found by this binder.
///
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
index b66cb01e0c6e9..b5e1aa262b05d 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
@@ -343,8 +343,7 @@ protected BoundExpression BindExpressionAllowArgList(ExpressionSyntax node, Diag
private void VerifyUnchecked(ExpressionSyntax node, DiagnosticBag diagnostics, BoundExpression expr)
{
- var isInsideNameof = this.EnclosingNameofArgument != null;
- if (!expr.HasAnyErrors && !isInsideNameof)
+ if (!expr.HasAnyErrors && !IsInsideNameof)
{
TypeSymbol exprType = expr.Type;
if ((object)exprType != null && exprType.IsUnsafe())
@@ -1191,7 +1190,7 @@ private BoundExpression BindDefaultExpression(DefaultExpressionSyntax node, Diag
options |= LookupOptions.MustBeInvocableIfMember;
}
- if (!IsInMethodBody && this.EnclosingNameofArgument == null)
+ if (!IsInMethodBody && !IsInsideNameof)
{
Debug.Assert((options & LookupOptions.NamespacesOrTypesOnly) == 0);
options |= LookupOptions.MustNotBeMethodTypeParameter;
@@ -1418,9 +1417,8 @@ private bool IsBadLocalOrParameterCapture(Symbol symbol, TypeSymbol type, RefKin
// Not expecting symbol from constructed method.
Debug.Assert(!symbol.ContainingSymbol.Equals(containingMethod));
- var isInsideNameof = this.EnclosingNameofArgument != null;
// Captured in a lambda.
- return (containingMethod.MethodKind == MethodKind.AnonymousFunction || containingMethod.MethodKind == MethodKind.LocalFunction) && !isInsideNameof; // false in EE evaluation method
+ return (containingMethod.MethodKind == MethodKind.AnonymousFunction || containingMethod.MethodKind == MethodKind.LocalFunction) && !IsInsideNameof; // false in EE evaluation method
}
}
return false;
@@ -1530,7 +1528,7 @@ private BoundExpression BindNonMethod(SimpleNameSyntax node, Symbol symbol, Diag
}
}
- var constantValueOpt = localSymbol.IsConst && this.EnclosingNameofArgument == null && !type.IsErrorType()
+ var constantValueOpt = localSymbol.IsConst && !IsInsideNameof && !type.IsErrorType()
? localSymbol.GetConstantValue(node, this.LocalInProgress, diagnostics) : null;
return new BoundLocal(node, localSymbol, constantValueOpt, type, hasErrors: isError);
}
@@ -5979,7 +5977,7 @@ private static void CombineExtensionMethodArguments(BoundExpression receiver, An
hasError = this.CheckInstanceOrStatic(node, receiver, fieldSymbol, ref resultKind, diagnostics);
}
- if (!hasError && fieldSymbol.IsFixed && EnclosingNameofArgument == null)
+ if (!hasError && fieldSymbol.IsFixed && !IsInsideNameof)
{
TypeSymbol receiverType = receiver.Type;
@@ -5989,9 +5987,8 @@ private static void CombineExtensionMethodArguments(BoundExpression receiver, An
if (!hasError)
{
var isFixedStatementExpression = SyntaxFacts.IsFixedStatementExpression(node);
- var isInsideNameof = this.EnclosingNameofArgument != null;
Symbol accessedLocalOrParameterOpt;
- if (IsNonMoveableVariable(receiver, out accessedLocalOrParameterOpt) == isFixedStatementExpression && !isInsideNameof)
+ if (IsNonMoveableVariable(receiver, out accessedLocalOrParameterOpt) == isFixedStatementExpression && !IsInsideNameof)
{
Error(diagnostics, isFixedStatementExpression ? ErrorCode.ERR_FixedNotNeeded : ErrorCode.ERR_FixedBufferNotFixed, node);
hasErrors = hasError = true;
@@ -6006,7 +6003,7 @@ private static void CombineExtensionMethodArguments(BoundExpression receiver, An
ConstantValue constantValueOpt = null;
- if (fieldSymbol.IsConst && this.EnclosingNameofArgument == null)
+ if (fieldSymbol.IsConst && !IsInsideNameof)
{
constantValueOpt = fieldSymbol.GetConstantValue(this.ConstantFieldsInProgress, this.IsEarlyAttributeBinder);
if (constantValueOpt == ConstantValue.Unset)
@@ -6163,7 +6160,7 @@ private bool InEnumMemberInitializer()
}
else
{
- if (instanceReceiver == false && EnclosingNameofArgument != node)
+ if (instanceReceiver == false && !IsInsideNameof)
{
Error(diagnostics, ErrorCode.ERR_ObjectRequired, node, symbol);
resultKind = LookupResultKind.StaticInstanceMismatch;
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs
index 7dc665458f55e..83753f350cf71 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs
@@ -1343,5 +1343,51 @@ private static void M(in string value)
}
}", expectedOutput: "Main");
}
+
+ [Fact, WorkItem(20600, "https://github.com/dotnet/roslyn/issues/20600")]
+ public void PermitInstanceQualifiedFromType()
+ {
+ CreateStandardCompilation(@"
+class C
+{
+ public string Instance1 = null;
+ public static string Static1 = null;
+ public string Instance2 => string.Empty;
+ public static string Static2 => string.Empty;
+
+ void M()
+ {
+ _ = nameof(C.Instance1);
+ _ = nameof(C.Instance1.Length);
+ _ = nameof(C.Static1);
+ _ = nameof(C.Static1.Length);
+ _ = nameof(C.Instance2);
+ _ = nameof(C.Instance2.Length);
+ _ = nameof(C.Static2);
+ _ = nameof(C.Static2.Length);
+ }
+}
+
+class C
+{
+ public string Instance1 = null;
+ public static string Static1 = null;
+ public string Instance2 => string.Empty;
+ public static string Static2 => string.Empty;
+
+ void M()
+ {
+ _ = nameof(C.Instance1);
+ _ = nameof(C.Instance1.Length);
+ _ = nameof(C.Static1);
+ _ = nameof(C.Static1.Length);
+ _ = nameof(C.Instance2);
+ _ = nameof(C.Instance2.Length);
+ _ = nameof(C.Static2);
+ _ = nameof(C.Static2.Length);
+ }
+}
+").VerifyDiagnostics();
+ }
}
}