Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/Binder/Binder_Crefs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,7 @@ private static ImmutableArray<Symbol> PerformCrefOverloadResolution(ArrayBuilder
name: null,
refKind: RefKind.None,
isInitOnly: false,
isStatic: false,
returnType: default,
refCustomModifiers: ImmutableArray<CustomModifier>.Empty,
explicitInterfaceImplementations: ImmutableArray<MethodSymbol>.Empty);
Expand Down
8 changes: 7 additions & 1 deletion src/Compilers/CSharp/Portable/CSharpResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -2151,7 +2151,7 @@ If such a class is used as a base class and if the deriving class defines a dest
<value>Invalid type specified as an argument for TypeForwardedTo attribute</value>
</data>
<data name="ERR_CloseUnimplementedInterfaceMemberStatic" xml:space="preserve">
<value>'{0}' does not implement interface member '{1}'. '{2}' cannot implement an interface member because it is static.</value>
<value>'{0}' does not implement instance interface member '{1}'. '{2}' cannot implement the interface member because it is static.</value>
</data>
<data name="ERR_CloseUnimplementedInterfaceMemberNotPublic" xml:space="preserve">
<value>'{0}' does not implement interface member '{1}'. '{2}' cannot implement an interface member because it is not public.</value>
Expand Down Expand Up @@ -6636,4 +6636,10 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="ERR_ExpressionTreeContainsAbstractStaticMemberAccess" xml:space="preserve">
<value>An expression tree may not contain an access of static abstract interface member</value>
</data>
<data name="ERR_CloseUnimplementedInterfaceMemberNotStatic" xml:space="preserve">
<value>'{0}' does not implement static interface member '{1}'. '{2}' cannot implement the interface member because it is not static.</value>
</data>
<data name="ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember" xml:space="preserve">
<value>'{0}' cannot implement interface member '{1}' in type '{2}' because the target runtime doesn't support static abstract members in interfaces.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ internal static BoundBlock ConstructSingleInvocationMethodBody(SyntheticBoundNod
argBuilder.Add(F.Parameter(param));
}

BoundExpression invocation = F.Call(useBaseReference ? (BoundExpression)F.Base(baseType: methodToInvoke.ContainingType) : F.This(),
BoundExpression invocation = F.Call(methodToInvoke.IsStatic ? null : (useBaseReference ? (BoundExpression)F.Base(baseType: methodToInvoke.ContainingType) : F.This()),
methodToInvoke,
argBuilder.ToImmutableAndFree());

Expand Down
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -811,7 +811,7 @@ private void CompileSynthesizedExplicitImplementations(SourceMemberContainerType
if (!_globalHasErrors)
{
var discardedDiagnostics = BindingDiagnosticBag.GetInstance(_diagnostics);
foreach (var synthesizedExplicitImpl in sourceTypeSymbol.GetSynthesizedExplicitImplementations(_cancellationToken))
foreach (var synthesizedExplicitImpl in sourceTypeSymbol.GetSynthesizedExplicitImplementations(_cancellationToken).ForwardingMethods)
{
Debug.Assert(synthesizedExplicitImpl.SynthesizesLoweredBoundBody);
synthesizedExplicitImpl.GenerateMethodBody(compilationState, discardedDiagnostics);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public override void VisitNamedType(NamedTypeSymbol symbol)
// base type from another assembly) it is necessary for the compiler to generate explicit implementations for
// some interface methods. They don't go in the symbol table, but if we are emitting metadata, then we should
// generate MethodDef entries for them.
foreach (var synthesizedExplicitImpl in sourceTypeSymbol.GetSynthesizedExplicitImplementations(_cancellationToken))
foreach (var synthesizedExplicitImpl in sourceTypeSymbol.GetSynthesizedExplicitImplementations(_cancellationToken).ForwardingMethods)
{
_moduleBeingBuilt.AddSynthesizedDefinition(symbol, synthesizedExplicitImpl.GetCciAdapter());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,15 @@ Cci.ITypeReference Cci.ITypeDefinition.GetBaseClass(EmitContext context)
yield break;
}

if (AdaptedNamedTypeSymbol is SourceMemberContainerTypeSymbol container)
{
foreach ((MethodSymbol body, MethodSymbol implemented) in container.GetSynthesizedExplicitImplementations(cancellationToken: default).MethodImpls)
{
Debug.Assert(body.ContainingType == (object)container);
yield return new Microsoft.Cci.MethodImplementation(body.GetCciAdapter(), moduleBeingBuilt.TranslateOverriddenMethodReference(implemented, (CSharpSyntaxNode)context.SyntaxNodeOpt, context.Diagnostics));
}
}

var syntheticMethods = moduleBeingBuilt.GetSynthesizedMethods(AdaptedNamedTypeSymbol);
if (syntheticMethods != null)
{
Expand Down
2 changes: 2 additions & 0 deletions src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1947,6 +1947,8 @@ internal enum ErrorCode
ERR_BadAbstractShiftOperatorSignature = 9106,
ERR_BadAbstractStaticMemberAccess = 9107,
ERR_ExpressionTreeContainsAbstractStaticMemberAccess = 9108,
ERR_CloseUnimplementedInterfaceMemberNotStatic = 9109,
ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember = 9110,

// Note: you will need to re-generate compiler code after adding warnings (eng\generate-compiler-code.cmd)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,11 @@ public override int GetHashCode()
}

internal override bool HasPossibleWellKnownCloneMethod() => false;

internal override IEnumerable<(MethodSymbol Body, MethodSymbol Implemented)> SynthesizedInterfaceMethodImpls()
{
return SpecializedCollections.EmptyEnumerable<(MethodSymbol Body, MethodSymbol Implemented)>();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,11 @@ private SynthesizedAttributeData TrySynthesizeDebuggerDisplayAttribute()
}

internal override bool HasPossibleWellKnownCloneMethod() => false;

internal override IEnumerable<(MethodSymbol Body, MethodSymbol Implemented)> SynthesizedInterfaceMethodImpls()
{
return SpecializedCollections.EmptyEnumerable<(MethodSymbol Body, MethodSymbol Implemented)>();
}
}
}
}
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/Symbols/ArrayTypeSymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,11 @@ protected sealed override ITypeSymbol CreateITypeSymbol(CodeAnalysis.NullableAnn

internal override bool IsRecord => false;

internal sealed override IEnumerable<(MethodSymbol Body, MethodSymbol Implemented)> SynthesizedInterfaceMethodImpls()
{
return SpecializedCollections.EmptyEnumerable<(MethodSymbol Body, MethodSymbol Implemented)>();
}

/// <summary>
/// Represents SZARRAY - zero-based one-dimensional array
/// </summary>
Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/Symbols/DynamicTypeSymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -246,5 +246,10 @@ protected sealed override ITypeSymbol CreateITypeSymbol(CodeAnalysis.NullableAnn
}

internal override bool IsRecord => false;

internal override IEnumerable<(MethodSymbol Body, MethodSymbol Implemented)> SynthesizedInterfaceMethodImpls()
{
return SpecializedCollections.EmptyEnumerable<(MethodSymbol Body, MethodSymbol Implemented)>();
}
}
}
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,11 @@ protected sealed override ITypeSymbol CreateITypeSymbol(CodeAnalysis.NullableAnn

internal sealed override bool IsRecord => false;
internal sealed override bool HasPossibleWellKnownCloneMethod() => false;

internal sealed override IEnumerable<(MethodSymbol Body, MethodSymbol Implemented)> SynthesizedInterfaceMethodImpls()
{
return SpecializedCollections.EmptyEnumerable<(MethodSymbol Body, MethodSymbol Implemented)>();
}
}

internal abstract class SubstitutedErrorTypeSymbol : ErrorTypeSymbol
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,5 +214,10 @@ internal static bool IsCallingConventionModifier(NamedTypeSymbol modifierType)
}

internal override bool IsRecord => false;

internal override IEnumerable<(MethodSymbol Body, MethodSymbol Implemented)> SynthesizedInterfaceMethodImpls()
{
return SpecializedCollections.EmptyEnumerable<(MethodSymbol Body, MethodSymbol Implemented)>();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,18 @@ internal class MemberSignatureComparer : IEqualityComparer<Symbol>
considerRefKindDifferences: false,
typeComparison: TypeCompareKind.IgnoreDynamicAndTupleNames | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes | TypeCompareKind.IgnoreNativeIntegers);

/// <summary>
/// Same as <see cref="RuntimeSignatureComparer"/>, but in addition ignores name.
/// </summary>
public static readonly MemberSignatureComparer RuntimeExplicitImplementationSignatureComparer = new MemberSignatureComparer(
considerName: false,
considerExplicitlyImplementedInterfaces: false,
considerReturnType: true,
considerTypeConstraints: false,
considerCallingConvention: true,
considerRefKindDifferences: false,
typeComparison: TypeCompareKind.IgnoreDynamicAndTupleNames | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes | TypeCompareKind.IgnoreNativeIntegers);

/// <summary>
/// Same as <see cref="RuntimeSignatureComparer"/>, but distinguishes between <c>ref</c> and <c>out</c>. During override resolution,
/// if we find two methods that match except for <c>ref</c>/<c>out</c>, we want to prefer the one that matches, even
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1852,7 +1852,7 @@ private PooledDictionary<MethodDefinitionHandle, PEMethodSymbol> CreateMethods(A
{
foreach (var methodHandle in module.GetMethodsOfTypeOrThrow(_handle))
{
if (isOrdinaryEmbeddableStruct || module.ShouldImportMethod(methodHandle, moduleSymbol.ImportOptions))
if (isOrdinaryEmbeddableStruct || module.ShouldImportMethod(_handle, methodHandle, moduleSymbol.ImportOptions))
{
var method = new PEMethodSymbol(moduleSymbol, this, methodHandle);
members.Add(method);
Expand All @@ -1879,8 +1879,8 @@ private void CreateProperties(Dictionary<MethodDefinitionHandle, PEMethodSymbol>
{
var methods = module.GetPropertyMethodsOrThrow(propertyDef);

PEMethodSymbol getMethod = GetAccessorMethod(module, methodHandleToSymbol, methods.Getter);
PEMethodSymbol setMethod = GetAccessorMethod(module, methodHandleToSymbol, methods.Setter);
PEMethodSymbol getMethod = GetAccessorMethod(module, methodHandleToSymbol, _handle, methods.Getter);
PEMethodSymbol setMethod = GetAccessorMethod(module, methodHandleToSymbol, _handle, methods.Setter);

if (((object)getMethod != null) || ((object)setMethod != null))
{
Expand Down Expand Up @@ -1912,8 +1912,8 @@ private void CreateEvents(
var methods = module.GetEventMethodsOrThrow(eventRid);

// NOTE: C# ignores all other accessors (most notably, raise/fire).
PEMethodSymbol addMethod = GetAccessorMethod(module, methodHandleToSymbol, methods.Adder);
PEMethodSymbol removeMethod = GetAccessorMethod(module, methodHandleToSymbol, methods.Remover);
PEMethodSymbol addMethod = GetAccessorMethod(module, methodHandleToSymbol, _handle, methods.Adder);
PEMethodSymbol removeMethod = GetAccessorMethod(module, methodHandleToSymbol, _handle, methods.Remover);

// NOTE: both accessors are required, but that will be reported separately.
// Create the symbol unless both accessors are missing.
Expand All @@ -1930,7 +1930,7 @@ private void CreateEvents(
{ }
}

private PEMethodSymbol GetAccessorMethod(PEModule module, Dictionary<MethodDefinitionHandle, PEMethodSymbol> methodHandleToSymbol, MethodDefinitionHandle methodDef)
private PEMethodSymbol GetAccessorMethod(PEModule module, Dictionary<MethodDefinitionHandle, PEMethodSymbol> methodHandleToSymbol, TypeDefinitionHandle typeDef, MethodDefinitionHandle methodDef)
{
if (methodDef.IsNil)
{
Expand All @@ -1939,7 +1939,7 @@ private PEMethodSymbol GetAccessorMethod(PEModule module, Dictionary<MethodDefin

PEMethodSymbol method;
bool found = methodHandleToSymbol.TryGetValue(methodDef, out method);
Debug.Assert(found || !module.ShouldImportMethod(methodDef, this.ContainingPEModule.ImportOptions));
Debug.Assert(found || !module.ShouldImportMethod(typeDef, methodDef, this.ContainingPEModule.ImportOptions));
return method;
}

Expand Down Expand Up @@ -2297,6 +2297,11 @@ private static IEnumerable<TSymbol> GetMembers<TSymbol>(ImmutableArray<Symbol> m
}
}

internal sealed override IEnumerable<(MethodSymbol Body, MethodSymbol Implemented)> SynthesizedInterfaceMethodImpls()
{
return SpecializedCollections.EmptyEnumerable<(MethodSymbol Body, MethodSymbol Implemented)>();
}

/// <summary>
/// Specialized PENamedTypeSymbol for types with no type parameters in
/// metadata (no type parameters on this type and all containing types).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,11 @@ internal static void VerifyEquality(Symbol symbolA, Symbol symbolB)
Debug.Assert(symbolA.GetHashCode() == symbolB.GetHashCode());
}

internal override IEnumerable<(MethodSymbol Body, MethodSymbol Implemented)> SynthesizedInterfaceMethodImpls()
{
return SpecializedCollections.EmptyEnumerable<(MethodSymbol Body, MethodSymbol Implemented)>();
}

private sealed class NativeIntegerTypeMap : AbstractTypeMap
{
private readonly NativeIntegerTypeSymbol _type;
Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/Symbols/PointerTypeSymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -310,5 +310,10 @@ protected override ITypeSymbol CreateITypeSymbol(CodeAnalysis.NullableAnnotation
}

internal override bool IsRecord => false;

internal sealed override IEnumerable<(MethodSymbol Body, MethodSymbol Implemented)> SynthesizedInterfaceMethodImpls()
{
return SpecializedCollections.EmptyEnumerable<(MethodSymbol Body, MethodSymbol Implemented)>();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -393,5 +393,19 @@ public sealed override bool AreLocalsZeroed

internal sealed override bool IsRecord => _underlyingType.IsRecord;
internal sealed override bool HasPossibleWellKnownCloneMethod() => _underlyingType.HasPossibleWellKnownCloneMethod();

internal override IEnumerable<(MethodSymbol Body, MethodSymbol Implemented)> SynthesizedInterfaceMethodImpls()
{
foreach ((MethodSymbol body, MethodSymbol implemented) in _underlyingType.SynthesizedInterfaceMethodImpls())
{
var newBody = this.RetargetingTranslator.Retarget(body, MemberSignatureComparer.RetargetedExplicitImplementationComparer);
var newImplemented = this.RetargetingTranslator.Retarget(implemented, MemberSignatureComparer.RetargetedExplicitImplementationComparer);

if (newBody is object && newImplemented is object)
{
yield return (newBody, newImplemented);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,7 @@ IEqualityComparer<MethodSymbol> retargetedMethodComparer
targetParamsBuilder.ToImmutableAndFree(),
method.RefKind,
method.IsInitOnly,
method.IsStatic,
translator.Retarget(method.ReturnTypeWithAnnotations, RetargetOptions.RetargetPrimitiveTypesByTypeCode),
translator.RetargetModifiers(method.RefCustomModifiers, out modifiersHaveChanged_Ignored),
ImmutableArray<MethodSymbol>.Empty);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ internal sealed class SignatureOnlyMethodSymbol : MethodSymbol
private readonly ImmutableArray<ParameterSymbol> _parameters;
private readonly RefKind _refKind;
private readonly bool _isInitOnly;
private readonly bool _isStatic;
private readonly TypeWithAnnotations _returnType;
private readonly ImmutableArray<CustomModifier> _refCustomModifiers;
private readonly ImmutableArray<MethodSymbol> _explicitInterfaceImplementations;
Expand All @@ -39,6 +40,7 @@ public SignatureOnlyMethodSymbol(
ImmutableArray<ParameterSymbol> parameters,
RefKind refKind,
bool isInitOnly,
bool isStatic,
TypeWithAnnotations returnType,
ImmutableArray<CustomModifier> refCustomModifiers,
ImmutableArray<MethodSymbol> explicitInterfaceImplementations)
Expand All @@ -48,6 +50,7 @@ public SignatureOnlyMethodSymbol(
_typeParameters = typeParameters;
_refKind = refKind;
_isInitOnly = isInitOnly;
_isStatic = isStatic;
_returnType = returnType;
_refCustomModifiers = refCustomModifiers;
_parameters = parameters;
Expand Down Expand Up @@ -131,7 +134,7 @@ public SignatureOnlyMethodSymbol(

public override Accessibility DeclaredAccessibility { get { throw ExceptionUtilities.Unreachable; } }

public override bool IsStatic { get { throw ExceptionUtilities.Unreachable; } }
public override bool IsStatic { get { return _isStatic; } }

public override bool IsAsync { get { throw ExceptionUtilities.Unreachable; } }

Expand Down
Loading