Skip to content

Commit

Permalink
Merge pull request #35822 from YairHalberstadt/dont-suggest-this-in-s…
Browse files Browse the repository at this point in the history
…tatic-local-functions

Dont suggest this in static local functions
  • Loading branch information
jasonmalinowski authored Jun 26, 2019
2 parents 020f1a2 + c3d2d42 commit a571221
Show file tree
Hide file tree
Showing 35 changed files with 344 additions and 52 deletions.
14 changes: 7 additions & 7 deletions src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -246,9 +246,9 @@ private BoundExpression CheckValue(BoundExpression expr, BindValueKind valueKind

// Since we have a concrete member in hand, we can resolve the receiver.
var typeOrValue = (BoundTypeOrValueExpression)receiver;
receiver = otherSymbol.IsStatic
? null // no receiver required
: typeOrValue.Data.ValueExpression;
receiver = otherSymbol.RequiresInstanceReceiver()
? typeOrValue.Data.ValueExpression
: null; // no receiver required
}
return new BoundBadExpression(
expr.Syntax,
Expand Down Expand Up @@ -868,7 +868,7 @@ private bool CheckIsValidReceiverForVariable(SyntaxNode node, BoundExpression re
/// </remarks>
private static bool RequiresVariableReceiver(BoundExpression receiver, Symbol symbol)
{
return !symbol.IsStatic
return symbol.RequiresInstanceReceiver()
&& symbol.Kind != SymbolKind.Event
&& receiver?.Type?.IsValueType == true;
}
Expand Down Expand Up @@ -1114,7 +1114,7 @@ bool isRefEscape
//• the safe-to-escape of all argument expressions(including the receiver)
//

if (symbol.IsStatic)
if (!symbol.RequiresInstanceReceiver())
{
// ignore receiver when symbol is static
receiverOpt = null;
Expand Down Expand Up @@ -1221,7 +1221,7 @@ bool isRefEscape
// o no ref or out argument(excluding the receiver and arguments of ref-like types) may have a narrower ref-safe-to-escape than E1; and
// o no argument(including the receiver) may have a narrower safe-to-escape than E1.

if (symbol.IsStatic)
if (!symbol.RequiresInstanceReceiver())
{
// ignore receiver when symbol is static
receiverOpt = null;
Expand Down Expand Up @@ -1327,7 +1327,7 @@ private static bool CheckInvocationArgMixing(
// - If there is a ref or out argument of a ref struct type (including the receiver), with safe-to-escape E1, then
// - no argument (including the receiver) may have a narrower safe-to-escape than E1.

if (symbol.IsStatic)
if (!symbol.RequiresInstanceReceiver())
{
// ignore receiver when symbol is static
receiverOpt = null;
Expand Down
4 changes: 2 additions & 2 deletions src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ private BoundMethodGroup FixMethodGroupWithTypeOrValue(BoundMethodGroup group, C
BoundExpression receiverOpt = group.ReceiverOpt;
Debug.Assert(receiverOpt != null);
Debug.Assert((object)conversion.Method != null);
receiverOpt = ReplaceTypeOrValueReceiver(receiverOpt, conversion.Method.IsStatic && !conversion.IsExtensionMethod, diagnostics);
receiverOpt = ReplaceTypeOrValueReceiver(receiverOpt, !conversion.Method.RequiresInstanceReceiver && !conversion.IsExtensionMethod, diagnostics);
return group.Update(
group.TypeArgumentsOpt,
group.Name,
Expand Down Expand Up @@ -599,7 +599,7 @@ private bool MemberGroupFinalValidationAccessibilityChecks(BoundExpression recei
// None of the checks below apply if the receiver can't be classified as a type or value.
Debug.Assert(!invokedAsExtensionMethod);
}
else if (memberSymbol.IsStatic)
else if (!memberSymbol.RequiresInstanceReceiver())
{
Debug.Assert(!invokedAsExtensionMethod || (receiverOpt != null));

Expand Down
6 changes: 3 additions & 3 deletions src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1672,7 +1672,7 @@ private BoundExpression SynthesizeReceiver(SyntaxNode node, Symbol member, Diagn
// accessor, the result is the same as a member access of the form this.I. This can only
// happen when K is zero.

if (member.IsStatic)
if (!member.RequiresInstanceReceiver())
{
return null;
}
Expand Down Expand Up @@ -1737,7 +1737,7 @@ internal Symbol ContainingMember()

private BoundExpression TryBindInteractiveReceiver(SyntaxNode syntax, Symbol currentMember, NamedTypeSymbol currentType, NamedTypeSymbol memberDeclaringType)
{
if (currentType.TypeKind == TypeKind.Submission && !currentMember.IsStatic)
if (currentType.TypeKind == TypeKind.Submission && currentMember.RequiresInstanceReceiver())
{
if (memberDeclaringType.TypeKind == TypeKind.Submission)
{
Expand Down Expand Up @@ -6650,7 +6650,7 @@ private bool CheckInstanceOrStatic(
{
bool? instanceReceiver = IsInstanceReceiver(receiver);

if (symbol.IsStatic)
if (!symbol.RequiresInstanceReceiver())
{
if (instanceReceiver == true)
{
Expand Down
10 changes: 5 additions & 5 deletions src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1002,7 +1002,7 @@ private BoundCall BindInvocationExpressionContinued(
// instance methods. Therefore we must detect this scenario here, rather than in
// overload resolution.

var receiver = ReplaceTypeOrValueReceiver(methodGroup.Receiver, method.IsStatic && !invokedAsExtensionMethod, diagnostics);
var receiver = ReplaceTypeOrValueReceiver(methodGroup.Receiver, !method.RequiresInstanceReceiver && !invokedAsExtensionMethod, diagnostics);

// Note: we specifically want to do final validation (7.6.5.1) without checking delegate compatibility (15.2),
// so we're calling MethodGroupFinalValidation directly, rather than via MethodGroupConversionHasErrors.
Expand Down Expand Up @@ -1056,7 +1056,7 @@ private BoundCall BindInvocationExpressionContinued(
// For extension methods, there is no receiver because the receiver in source was actually the first argument.
// For instance methods, we may have synthesized an implicit this node. We'll keep it for the emitter.
// For static methods, we may have synthesized a type expression. It serves no purpose, so we'll drop it.
if (invokedAsExtensionMethod || (method.IsStatic && receiver != null && receiver.WasCompilerGenerated))
if (invokedAsExtensionMethod || (!method.RequiresInstanceReceiver && receiver != null && receiver.WasCompilerGenerated))
{
receiver = null;
}
Expand All @@ -1065,7 +1065,7 @@ private BoundCall BindInvocationExpressionContinued(
var argRefKinds = analyzedArguments.RefKinds.ToImmutableOrNull();
var args = analyzedArguments.Arguments.ToImmutable();

if (!gotError && !method.IsStatic && receiver != null && receiver.Kind == BoundKind.ThisReference && receiver.WasCompilerGenerated)
if (!gotError && method.RequiresInstanceReceiver && receiver != null && receiver.Kind == BoundKind.ThisReference && receiver.WasCompilerGenerated)
{
gotError = IsRefOrOutThisParameterCaptured(node, diagnostics);
}
Expand Down Expand Up @@ -1116,7 +1116,7 @@ private BoundCall BindInvocationExpressionContinued(
bool isDelegateCall = (object)delegateTypeOpt != null;
if (!isDelegateCall)
{
if (!method.IsStatic)
if (method.RequiresInstanceReceiver)
{
WarnOnAccessOfOffDefault(node.Kind() == SyntaxKind.InvocationExpression ?
((InvocationExpressionSyntax)node).Expression :
Expand Down Expand Up @@ -1145,7 +1145,7 @@ ContainingMemberOrLambda is MethodSymbol containingMethod &&
// Ignore calls to base members.
TypeSymbol.Equals(containingMethod.ContainingType, method.ContainingType, TypeCompareKind.ConsiderEverything) &&
!method.IsEffectivelyReadOnly &&
!method.IsStatic)
method.RequiresInstanceReceiver)
{
Error(diagnostics, ErrorCode.WRN_ImplicitCopyInReadOnlyMember, receiver.Syntax, method, ThisParameterSymbol.SymbolName);
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ private static bool IsSymbolAccessibleCore(
case SymbolKind.Property:
case SymbolKind.Event:
case SymbolKind.Field:
if (symbol.IsStatic)
if (!symbol.RequiresInstanceReceiver())
{
// static members aren't accessed "through" an "instance" of any type. So we
// null out the "through" instance here. This ensures that we'll understand
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ private static Conversion ToConversion(OverloadResolutionResult<MethodSymbol> re
}

//cannot capture stack-only types.
if (!method.IsStatic && methodGroup.Receiver?.Type?.IsRestrictedType() == true)
if (method.RequiresInstanceReceiver && methodGroup.Receiver?.Type?.IsRestrictedType() == true)
{
return Conversion.NoConversion;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ private void RemoveStaticInstanceMismatches<TMember>(
{
var result = results[f];
TMember member = result.Member;
if (result.Result.IsValid && member.IsStatic != keepStatic)
if (result.Result.IsValid && member.RequiresInstanceReceiver() == keepStatic)
{
results[f] = new MemberResolutionResult<TMember>(member, result.LeastOverriddenMember, MemberAnalysisResult.StaticInstanceMismatch());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -608,9 +608,11 @@ private bool HadStaticInstanceMismatch(
else
{
ErrorCode errorCode =
symbol.IsStatic ? ErrorCode.ERR_ObjectProhibited :
Binder.WasImplicitReceiver(receiverOpt) && binder.InFieldInitializer && !binder.BindingTopLevelScriptCode ? ErrorCode.ERR_FieldInitRefNonstatic :
ErrorCode.ERR_ObjectRequired;
symbol.RequiresInstanceReceiver()
? Binder.WasImplicitReceiver(receiverOpt) && binder.InFieldInitializer && !binder.BindingTopLevelScriptCode
? ErrorCode.ERR_FieldInitRefNonstatic
: ErrorCode.ERR_ObjectRequired
: ErrorCode.ERR_ObjectProhibited;
// error CS0176: Member 'Program.M(B)' cannot be accessed with an instance reference; qualify it with a type name instead
// -or-
// error CS0120: An object reference is required for the non-static field, method, or property 'Program.M(B)'
Expand Down
4 changes: 2 additions & 2 deletions src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1479,7 +1479,7 @@ private void EmitCallExpression(BoundCall call, UseKind useKind)

CallKind callKind;

if (method.IsStatic)
if (!method.RequiresInstanceReceiver)
{
callKind = CallKind.Call;
}
Expand Down Expand Up @@ -1748,7 +1748,7 @@ private static int GetCallStackBehavior(BoundCall call)
stack += 1;
}

if (!call.Method.IsStatic)
if (call.Method.RequiresInstanceReceiver)
{
// The call pops the receiver off the stack.
stack -= 1;
Expand Down
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/CodeGen/Optimizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1107,7 +1107,7 @@ public override BoundNode VisitCall(BoundCall node)
// matches or a bit stronger than EmitReceiverRef
// if there are any doubts that receiver is a ref type,
// assume we will need an address (that will prevent scheduling of receiver).
if (!node.Method.IsStatic)
if (node.Method.RequiresInstanceReceiver)
{
receiver = VisitCallReceiver(receiver);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1139,7 +1139,7 @@ private void VisitReceiverBeforeCall(BoundExpression receiverOpt, MethodSymbol m
private void VisitReceiverAfterCall(BoundExpression receiverOpt, MethodSymbol method)
{
NamedTypeSymbol containingType;
if (receiverOpt != null && ((object)method == null || method.MethodKind == MethodKind.Constructor || (object)(containingType = method.ContainingType) != null && !method.IsStatic && !containingType.IsReferenceType && !TypeIsImmutable(containingType)))
if (receiverOpt != null && ((object)method == null || method.MethodKind == MethodKind.Constructor || (object)(containingType = method.ContainingType) != null && method.RequiresInstanceReceiver && !containingType.IsReferenceType && !TypeIsImmutable(containingType)))
{
WriteArgument(receiverOpt, method?.MethodKind == MethodKind.Constructor ? RefKind.Out : RefKind.Ref, method);
}
Expand Down Expand Up @@ -1296,7 +1296,7 @@ public override BoundNode VisitDelegateCreationExpression(BoundDelegateCreationE
var methodGroup = node.Argument as BoundMethodGroup;
if (methodGroup != null)
{
if ((object)node.MethodOpt != null && !node.MethodOpt.IsStatic)
if ((object)node.MethodOpt != null && node.MethodOpt.RequiresInstanceReceiver)
{
if (_trackRegions)
{
Expand Down Expand Up @@ -1377,7 +1377,7 @@ public override BoundNode VisitConversion(BoundConversion node)
{
if (node.ConversionKind == ConversionKind.MethodGroup)
{
if (node.IsExtensionMethod || ((object)node.SymbolOpt != null && !node.SymbolOpt.IsStatic))
if (node.IsExtensionMethod || ((object)node.SymbolOpt != null && node.SymbolOpt.RequiresInstanceReceiver))
{
BoundExpression receiver = ((BoundMethodGroup)node.Operand).ReceiverOpt;
// A method group's "implicit this" is only used for instance methods.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ protected virtual int MakeSlot(BoundExpression node)
case BoundKind.PropertyAccess:
if (TryGetReceiverAndMember(node, out BoundExpression receiver, out Symbol member))
{
Debug.Assert((receiver is null) == member.IsStatic);
Debug.Assert((receiver is null) != member.RequiresInstanceReceiver());
return MakeMemberSlot(receiver, member);
}
break;
Expand All @@ -254,7 +254,7 @@ protected virtual int MakeSlot(BoundExpression node)
protected int MakeMemberSlot(BoundExpression receiverOpt, Symbol member)
{
int containingSlot = -1;
if (!member.IsStatic)
if (member.RequiresInstanceReceiver())
{
if (receiverOpt is null)
{
Expand Down
6 changes: 3 additions & 3 deletions src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,7 @@ protected override bool TryGetReceiverAndMember(BoundExpression expr, out BoundE
}
}

Debug.Assert(member?.IsStatic != true);
Debug.Assert(member?.RequiresInstanceReceiver() ?? true);

return (object)member != null &&
(object)receiver != null &&
Expand Down Expand Up @@ -2841,7 +2841,7 @@ private TypeWithState VisitCallReceiver(BoundCall node)

var type = receiverType.Type;
var method = node.Method;
if (!method.IsStatic &&
if (method.RequiresInstanceReceiver &&
type?.IsNullableType() == true &&
method.ContainingType.IsReferenceType)
{
Expand Down Expand Up @@ -5845,7 +5845,7 @@ private void VisitMemberAccess(BoundExpression node, BoundExpression receiverOpt
var receiverType = (receiverOpt != null) ? VisitRvalueWithState(receiverOpt) : default;

SpecialMember? nullableOfTMember = null;
if (!member.IsStatic)
if (member.RequiresInstanceReceiver())
{
member = AsMemberOfType(receiverType.Type, member);
nullableOfTMember = GetNullableOfTMember(member);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ protected override void VisitSwitchSection(BoundSwitchSection node, bool isLastS
// We may need to recompute the Deconstruct method for a deconstruction if
// the receiver type has changed (e.g. its nested nullability).
var method = e.DeconstructMethod;
int extensionExtra = method.IsStatic ? 1 : 0;
int extensionExtra = method.RequiresInstanceReceiver ? 0 : 1;
for (int i = 0; i < method.ParameterCount - extensionExtra; i++)
{
var parameterType = method.Parameters[i + extensionExtra].TypeWithAnnotations;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public override BoundNode VisitSizeOfOperator(BoundSizeOfOperator node)
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
{
var outerLocalFunction = _staticLocalFunction;
if (node.Symbol.IsStaticLocalFunction)
if (node.Symbol.IsStatic)
{
_staticLocalFunction = node.Symbol;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ private BoundExpression VisitCall(BoundCall node)
var method = node.Method;
return ExprFactory(
"Call",
method.IsStatic ? _bound.Null(ExpressionType) : Visit(node.ReceiverOpt),
method.RequiresInstanceReceiver ? Visit(node.ReceiverOpt) : _bound.Null(ExpressionType),
_bound.MethodInfo(method),
Expressions(node.Arguments));
}
Expand Down Expand Up @@ -608,7 +608,7 @@ private BoundExpression VisitConversion(BoundConversion node)
case ConversionKind.MethodGroup:
{
var mg = (BoundMethodGroup)node.Operand;
return DelegateCreation(mg.ReceiverOpt, node.SymbolOpt, node.Type, node.SymbolOpt.IsStatic && !node.IsExtensionMethod);
return DelegateCreation(mg.ReceiverOpt, node.SymbolOpt, node.Type, !node.SymbolOpt.RequiresInstanceReceiver && !node.IsExtensionMethod);
}
case ConversionKind.ExplicitUserDefined:
case ConversionKind.ImplicitUserDefined:
Expand Down Expand Up @@ -665,10 +665,10 @@ private BoundExpression Convert(BoundExpression expr, TypeSymbol type, bool isCh
return ExprFactory(isChecked ? "ConvertChecked" : "Convert", expr, _bound.Typeof(type));
}

private BoundExpression DelegateCreation(BoundExpression receiver, MethodSymbol method, TypeSymbol delegateType, bool staticMember)
private BoundExpression DelegateCreation(BoundExpression receiver, MethodSymbol method, TypeSymbol delegateType, bool requiresInstanceReciever)
{
var nullObject = _bound.Null(_objectType);
receiver = staticMember ? nullObject : receiver.Type.IsReferenceType ? receiver : _bound.Convert(_objectType, receiver);
receiver = requiresInstanceReciever ? nullObject : receiver.Type.IsReferenceType ? receiver : _bound.Convert(_objectType, receiver);

var createDelegate = _bound.WellKnownMethod(WellKnownMember.System_Reflection_MethodInfo__CreateDelegate, isOptional: true);
BoundExpression unquoted;
Expand Down Expand Up @@ -700,7 +700,7 @@ private BoundExpression VisitDelegateCreationExpression(BoundDelegateCreationExp

if ((object)node.MethodOpt != null)
{
bool staticMember = node.MethodOpt.IsStatic && !node.IsExtensionMethod;
bool staticMember = !node.MethodOpt.RequiresInstanceReceiver && !node.IsExtensionMethod;
return DelegateCreation(node.Argument, node.MethodOpt, node.Type, staticMember);
}

Expand Down
Loading

0 comments on commit a571221

Please sign in to comment.