提交 393f18b6 编写于 作者: Y yair halberstadt

Distinguish between RequiresInstanceReciever and IsStatic

上级 9d7a2525
......@@ -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.RequiresInstanceReciever
? typeOrValue.Data.ValueExpression
: null; // no receiver required
}
return new BoundBadExpression(
expr.Syntax,
......@@ -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.RequiresInstanceReciever
&& symbol.Kind != SymbolKind.Event
&& receiver?.Type?.IsValueType == true;
}
......@@ -1114,7 +1114,7 @@ bool isRefEscape
//• the safe-to-escape of all argument expressions(including the receiver)
//
if (symbol.IsStatic)
if (!symbol.RequiresInstanceReciever)
{
// ignore receiver when symbol is static
receiverOpt = null;
......@@ -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.RequiresInstanceReciever)
{
// ignore receiver when symbol is static
receiverOpt = null;
......@@ -1322,7 +1322,7 @@ bool isRefEscape
uint scopeOfTheContainingExpression,
DiagnosticBag diagnostics)
{
if (symbol.IsStatic)
if (!symbol.RequiresInstanceReciever)
{
// ignore receiver when symbol is static
receiverOpt = null;
......
......@@ -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.RequiresInstanceReciever && !conversion.IsExtensionMethod, diagnostics);
return group.Update(
group.TypeArgumentsOpt,
group.Name,
......@@ -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.RequiresInstanceReciever)
{
Debug.Assert(!invokedAsExtensionMethod || (receiverOpt != null));
......
......@@ -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.RequiresInstanceReciever)
{
return null;
}
......@@ -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.RequiresInstanceReciever)
{
if (memberDeclaringType.TypeKind == TypeKind.Submission)
{
......@@ -6650,7 +6650,7 @@ private void CheckRuntimeSupportForSymbolAccess(SyntaxNode node, BoundExpression
{
bool? instanceReceiver = IsInstanceReceiver(receiver);
if (symbol.IsStatic)
if (!symbol.RequiresInstanceReciever)
{
if (instanceReceiver == true)
{
......
......@@ -1002,7 +1002,7 @@ private void CheckRestrictedTypeReceiver(BoundExpression expression, Compilation
// 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.RequiresInstanceReciever && !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.
......@@ -1056,7 +1056,7 @@ private void CheckRestrictedTypeReceiver(BoundExpression expression, Compilation
// 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.RequiresInstanceReciever && receiver != null && receiver.WasCompilerGenerated))
{
receiver = null;
}
......@@ -1065,7 +1065,7 @@ private void CheckRestrictedTypeReceiver(BoundExpression expression, Compilation
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.RequiresInstanceReciever && receiver != null && receiver.Kind == BoundKind.ThisReference && receiver.WasCompilerGenerated)
{
gotError = IsRefOrOutThisParameterCaptured(node, diagnostics);
}
......@@ -1116,7 +1116,7 @@ private void CheckRestrictedTypeReceiver(BoundExpression expression, Compilation
bool isDelegateCall = (object)delegateTypeOpt != null;
if (!isDelegateCall)
{
if (!method.IsStatic)
if (method.RequiresInstanceReciever)
{
WarnOnAccessOfOffDefault(node.Kind() == SyntaxKind.InvocationExpression ?
((InvocationExpressionSyntax)node).Expression :
......
......@@ -130,7 +130,7 @@ internal static class AccessCheck
case SymbolKind.Property:
case SymbolKind.Event:
case SymbolKind.Field:
if (symbol.IsStatic)
if (!symbol.RequiresInstanceReciever)
{
// 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
......
......@@ -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.RequiresInstanceReciever && methodGroup.Receiver?.Type?.IsRestrictedType() == true)
{
return Conversion.NoConversion;
}
......
......@@ -337,7 +337,7 @@ private static bool OverloadResolutionResultIsValid<TMember>(ArrayBuilder<Member
{
var result = results[f];
TMember member = result.Member;
if (result.Result.IsValid && member.IsStatic != keepStatic)
if (result.Result.IsValid && member.RequiresInstanceReciever == keepStatic)
{
results[f] = new MemberResolutionResult<TMember>(member, result.LeastOverriddenMember, MemberAnalysisResult.StaticInstanceMismatch());
}
......
......@@ -608,9 +608,11 @@ private bool UseSiteError()
else
{
ErrorCode errorCode =
symbol.IsStatic ? ErrorCode.ERR_ObjectProhibited :
Binder.WasImplicitReceiver(receiverOpt) && binder.InFieldInitializer && !binder.BindingTopLevelScriptCode ? ErrorCode.ERR_FieldInitRefNonstatic :
ErrorCode.ERR_ObjectRequired;
symbol.RequiresInstanceReciever
? 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)'
......
......@@ -1479,7 +1479,7 @@ private void EmitCallExpression(BoundCall call, UseKind useKind)
CallKind callKind;
if (method.IsStatic)
if (!method.RequiresInstanceReciever)
{
callKind = CallKind.Call;
}
......@@ -1748,7 +1748,7 @@ private static int GetCallStackBehavior(BoundCall call)
stack += 1;
}
if (!call.Method.IsStatic)
if (call.Method.RequiresInstanceReciever)
{
// The call pops the receiver off the stack.
stack -= 1;
......
......@@ -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.RequiresInstanceReciever)
{
receiver = VisitCallReceiver(receiver);
}
......
......@@ -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.RequiresInstanceReciever && !containingType.IsReferenceType && !TypeIsImmutable(containingType)))
{
WriteArgument(receiverOpt, method?.MethodKind == MethodKind.Constructor ? RefKind.Out : RefKind.Ref, method);
}
......@@ -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.RequiresInstanceReciever)
{
if (_trackRegions)
{
......@@ -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.RequiresInstanceReciever))
{
BoundExpression receiver = ((BoundMethodGroup)node.Operand).ReceiverOpt;
// A method group's "implicit this" is only used for instance methods.
......
......@@ -217,7 +217,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.RequiresInstanceReciever);
return MakeMemberSlot(receiver, member);
}
break;
......@@ -230,7 +230,7 @@ protected virtual int MakeSlot(BoundExpression node)
protected int MakeMemberSlot(BoundExpression receiverOpt, Symbol member)
{
int containingSlot = -1;
if (!member.IsStatic)
if (member.RequiresInstanceReciever)
{
if (receiverOpt is null)
{
......
......@@ -621,7 +621,7 @@ protected override bool TryGetReceiverAndMember(BoundExpression expr, out BoundE
}
}
Debug.Assert(member?.IsStatic != true);
Debug.Assert(member?.RequiresInstanceReciever ?? true);
return (object)member != null &&
(object)receiver != null &&
......@@ -2737,7 +2737,7 @@ private TypeWithState VisitCallReceiver(BoundCall node)
var type = receiverType.Type;
var method = node.Method;
if (!method.IsStatic &&
if (method.RequiresInstanceReciever &&
type?.IsNullableType() == true &&
method.ContainingType.IsReferenceType)
{
......@@ -5371,7 +5371,7 @@ private void VisitMemberAccess(BoundExpression node, BoundExpression receiverOpt
var receiverType = (receiverOpt != null) ? VisitRvalueWithState(receiverOpt) : default;
SpecialMember? nullableOfTMember = null;
if (!member.IsStatic)
if (member.RequiresInstanceReciever)
{
member = AsMemberOfType(receiverType.Type, member);
nullableOfTMember = GetNullableOfTMember(member);
......
......@@ -229,7 +229,7 @@ protected override LocalState VisitSwitchStatementDispatch(BoundSwitchStatement
// 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.RequiresInstanceReciever ? 0 : 1;
for (int i = 0; i < method.ParameterCount - extensionExtra; i++)
{
var parameterType = method.Parameters[i + extensionExtra].TypeWithAnnotations;
......
......@@ -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;
}
......
......@@ -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.RequiresInstanceReciever? Visit(node.ReceiverOpt) : _bound.Null(ExpressionType),
_bound.MethodInfo(method),
Expressions(node.Arguments));
}
......@@ -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.RequiresInstanceReciever && !node.IsExtensionMethod);
}
case ConversionKind.ExplicitUserDefined:
case ConversionKind.ImplicitUserDefined:
......@@ -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;
......@@ -700,7 +700,7 @@ private BoundExpression VisitDelegateCreationExpression(BoundDelegateCreationExp
if ((object)node.MethodOpt != null)
{
bool staticMember = node.MethodOpt.IsStatic && !node.IsExtensionMethod;
bool staticMember = !node.MethodOpt.RequiresInstanceReciever && !node.IsExtensionMethod;
return DelegateCreation(node.Argument, node.MethodOpt, node.Type, staticMember);
}
......
......@@ -44,11 +44,11 @@ public BoundExpression VisitDynamicInvocation(BoundDynamicInvocation node, bool
{
// Calling a static method defined on an outer class via its simple name.
NamedTypeSymbol firstContainer = node.ApplicableMethods.First().ContainingType;
Debug.Assert(node.ApplicableMethods.All(m => m.IsStatic && TypeSymbol.Equals(m.ContainingType, firstContainer, TypeCompareKind.ConsiderEverything2)));
Debug.Assert(node.ApplicableMethods.All(m => !m.RequiresInstanceReciever && TypeSymbol.Equals(m.ContainingType, firstContainer, TypeCompareKind.ConsiderEverything2)));
loweredReceiver = new BoundTypeExpression(node.Syntax, null, firstContainer);
}
else if (hasImplicitReceiver && _factory.TopLevelMethod.IsStatic)
else if (hasImplicitReceiver && !_factory.TopLevelMethod.RequiresInstanceReciever)
{
// Calling a static method defined on the current class via its simple name.
loweredReceiver = new BoundTypeExpression(node.Syntax, null, _factory.CurrentType);
......
......@@ -351,7 +351,7 @@ private static bool IsFloatingPointExpressionOfUnknownPrecision(BoundExpression
Debug.Assert((object)method != null);
var oldSyntax = _factory.Syntax;
_factory.Syntax = (mg.ReceiverOpt ?? mg).Syntax;
var receiver = (method.IsStatic && !oldNode.IsExtensionMethod) ? _factory.Type(method.ContainingType) : mg.ReceiverOpt;
var receiver = (!method.RequiresInstanceReciever && !oldNode.IsExtensionMethod) ? _factory.Type(method.ContainingType) : mg.ReceiverOpt;
_factory.Syntax = oldSyntax;
return new BoundDelegateCreationExpression(syntax, argument: receiver, methodOpt: method,
isExtensionMethod: oldNode.IsExtensionMethod, type: rewrittenType);
......
......@@ -27,7 +27,7 @@ public override BoundNode VisitDelegateCreationExpression(BoundDelegateCreationE
var method = node.MethodOpt;
var oldSyntax = _factory.Syntax;
_factory.Syntax = (mg.ReceiverOpt ?? mg).Syntax;
var receiver = (method.IsStatic && !node.IsExtensionMethod) ? _factory.Type(method.ContainingType) : VisitExpression(mg.ReceiverOpt);
var receiver = (!method.RequiresInstanceReciever && !node.IsExtensionMethod) ? _factory.Type(method.ContainingType) : VisitExpression(mg.ReceiverOpt);
_factory.Syntax = oldSyntax;
return node.Update(receiver, method, node.IsExtensionMethod, node.Type);
}
......
......@@ -197,7 +197,7 @@ private enum CSharpArgumentInfoFlags
_factory.Syntax = loweredReceiver.Syntax;
CSharpBinderFlags binderFlags = 0;
if (hasImplicitReceiver && !_factory.TopLevelMethod.IsStatic)
if (hasImplicitReceiver && _factory.TopLevelMethod.RequiresInstanceReciever)
{
binderFlags |= CSharpBinderFlags.InvokeSimpleName;
}
......
......@@ -764,7 +764,7 @@ public override BoundNode VisitCall(BoundCall node)
{
receiver = VisitExpression(ref builder, node.ReceiverOpt);
}
else if (!node.Method.IsStatic)
else if (node.Method.RequiresInstanceReciever)
{
// spill the receiver if there were await expressions in the arguments
var receiverBuilder = new BoundSpillSequenceBuilder();
......
......@@ -1100,7 +1100,7 @@ ITypeSymbol IMethodSymbol.ReceiverType
CodeAnalysis.NullableAnnotation IMethodSymbol.ReceiverNullableAnnotation => ReceiverNullableAnnotation;
protected virtual CodeAnalysis.NullableAnnotation ReceiverNullableAnnotation =>
IsStatic ? CodeAnalysis.NullableAnnotation.NotApplicable : CodeAnalysis.NullableAnnotation.NotAnnotated;
RequiresInstanceReciever ? CodeAnalysis.NullableAnnotation.NotAnnotated : CodeAnalysis.NullableAnnotation.NotApplicable;
IMethodSymbol IMethodSymbol.ReducedFrom
{
......
......@@ -45,7 +45,6 @@ internal sealed class LocalFunctionSymbol : SourceMethodSymbol
_declarationModifiers =
DeclarationModifiers.Private |
DeclarationModifiers.Static |
syntax.Modifiers.ToDeclarationModifiers(diagnostics: _declarationDiagnostics);
this.CheckUnsafeModifier(_declarationModifiers, _declarationDiagnostics);
......@@ -128,6 +127,8 @@ internal void GetDeclarationDiagnostics(DiagnosticBag addTo)
internal override void AddDeclarationDiagnostics(DiagnosticBag diagnostics)
=> _declarationDiagnostics.AddRange(diagnostics);
public override bool RequiresInstanceReciever => false;
public override bool IsVararg
{
get
......@@ -286,9 +287,6 @@ public override bool IsExtensionMethod
}
}
// Replace with IsStatic after fixing https://github.com/dotnet/roslyn/issues/27719.
internal bool IsStaticLocalFunction => _syntax.Modifiers.Any(SyntaxKind.StaticKeyword);
internal override TypeWithAnnotations IteratorElementTypeWithAnnotations
{
get
......
......@@ -346,6 +346,11 @@ internal static ImmutableArray<SyntaxReference> GetDeclaringSyntaxReferenceHelpe
/// </summary>
public abstract bool IsStatic { get; }
/// <summary>
/// Returns true if this symbol requires an instance reference as the implicit reciever. This is false if the symbol is static, or a <see cref="LocalFunctionSymbol"/>
/// </summary>
public virtual bool RequiresInstanceReciever => !IsStatic;
/// <summary>
/// Returns true if this symbol is "virtual", has an implementation, and does not override a
/// base class member; i.e., declared with the <c>virtual</c> modifier. Does not return true for
......
......@@ -110,6 +110,14 @@ public override bool IsStatic
}
}
public override bool RequiresInstanceReciever
{
get
{
return UnderlyingMethod.RequiresInstanceReciever;
}
}
public override bool IsVirtual
{
get
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册