Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Record structs: Bind type declaration #51494

Merged
merged 4 commits into from
Mar 6, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ private static void ComputeDeclarations(
return;
}

// PROTOTYPE(record-structs): update for record structs
case SyntaxKind.RecordDeclaration:
{
if (associatedSymbol is IMethodSymbol ctor)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,9 @@ public override Binder VisitInterfaceDeclaration(InterfaceDeclarationSyntax node
public override Binder VisitRecordDeclaration(RecordDeclarationSyntax node)
=> VisitTypeDeclarationCore(node);

public override Binder VisitRecordStructDeclaration(RecordStructDeclarationSyntax node)
=> VisitTypeDeclarationCore(node);

public override Binder VisitNamespaceDeclaration(NamespaceDeclarationSyntax parent)
{
if (!LookupPosition.IsInNamespaceDeclaration(_position, parent))
Expand Down Expand Up @@ -1139,6 +1142,7 @@ private Binder GetParameterNameAttributeValueBinder(MemberDeclarationSyntax memb
return new WithParametersBinder(method.Parameters, nextBinder);
}

// PROTOTYPE(record-structs): update for record structs
if (memberSyntax is RecordDeclarationSyntax { ParameterList: { ParameterCount: > 0 } } recordDeclSyntax)
{
Binder outerBinder = VisitCore(memberSyntax);
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/Binder/BinderFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ internal Binder GetBinder(SyntaxNode node, int position, CSharpSyntaxNode member

internal InMethodBinder GetRecordConstructorInMethodBinder(SynthesizedRecordConstructor constructor)
{
// PROTOTYPE(record-structs): update for record structs
RecordDeclarationSyntax typeDecl = constructor.GetSyntax();

var extraInfo = NodeUsage.ConstructorBodyOrInitializer;
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3286,6 +3286,7 @@ public virtual BoundNode BindMethodBody(CSharpSyntaxNode syntax, BindingDiagnost
{
switch (syntax)
{
// PROTOTYPE(record-structs): update for record structs
case RecordDeclarationSyntax recordDecl:
return BindRecordConstructorBody(recordDecl, diagnostics);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ protected void FindExpressionVariables(
Debug.Assert(node.Parent is ConstructorInitializerSyntax || node.Parent is PrimaryConstructorBaseTypeSyntax);
break;
case SyntaxKind.RecordDeclaration:
// PROTOTYPE(record-structs): update for record structs
Debug.Assert(((RecordDeclarationSyntax)node).ParameterList is object);
break;
default:
Expand Down Expand Up @@ -395,6 +396,7 @@ public override void VisitConstructorDeclaration(ConstructorDeclarationSyntax no
}
}

// PROTOTYPE(record-structs): update for record structs
public override void VisitRecordDeclaration(RecordDeclarationSyntax node)
{
Debug.Assert(node.ParameterList is object);
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ public override void VisitConstructorDeclaration(ConstructorDeclarationSyntax no
Visit(node.ExpressionBody, enclosing);
}

// PROTOTYPE(record-structs): update for record structs
public override void VisitRecordDeclaration(RecordDeclarationSyntax node)
{
Debug.Assert(node.ParameterList is object);
Expand Down
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/CSharpResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1132,7 +1132,7 @@
<value>Missing partial modifier on declaration of type '{0}'; another partial declaration of this type exists</value>
</data>
<data name="ERR_PartialTypeKindConflict" xml:space="preserve">
<value>Partial declarations of '{0}' must be all classes, all records, all structs, or all interfaces</value>
<value>Partial declarations of '{0}' must be all classes, all record classes, all structs, all record structs, or all interfaces</value>
</data>
<data name="ERR_PartialModifierConflict" xml:space="preserve">
<value>Partial declarations of '{0}' have conflicting accessibility modifiers</value>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ internal override IOperation GetOperationWorker(CSharpSyntaxNode node, Cancellat
case AccessorDeclarationSyntax accessor:
model = (accessor.Body != null || accessor.ExpressionBody != null) ? GetOrAddModel(node) : null;
break;
// PROTOTYPE(record-structs): update for record structs
case RecordDeclarationSyntax { ParameterList: { }, PrimaryConstructorBaseType: { } } recordDeclaration when TryGetSynthesizedRecordConstructor(recordDeclaration) is SynthesizedRecordConstructor:
model = GetOrAddModel(recordDeclaration);
break;
Expand Down Expand Up @@ -804,6 +805,7 @@ private MemberSemanticModel GetMemberModel(int position)
!LookupPosition.IsInConstructorParameterScope(position, constructorDecl) &&
!LookupPosition.IsInParameterList(position, constructorDecl);
break;
// PROTOTYPE(record-structs): update for record structs
case SyntaxKind.RecordDeclaration:
{
var recordDecl = (RecordDeclarationSyntax)memberDecl;
Expand Down Expand Up @@ -873,6 +875,7 @@ internal override MemberSemanticModel GetMemberModel(SyntaxNode node)
GetOrAddModel(constructorDecl) : null;
}

// PROTOTYPE(record-structs): update for record structs
case SyntaxKind.RecordDeclaration:
{
var recordDecl = (RecordDeclarationSyntax)memberDecl;
Expand Down Expand Up @@ -1091,6 +1094,7 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node)
return createMethodBodySemanticModel(memberDecl, symbol);
}

// PROTOTYPE(record-structs): update for record structs
case SyntaxKind.RecordDeclaration:
{
SynthesizedRecordConstructor symbol = TryGetSynthesizedRecordConstructor((RecordDeclarationSyntax)node);
Expand Down Expand Up @@ -2022,6 +2026,7 @@ private ParameterSymbol GetMethodParameterSymbol(

MethodSymbol method;

// PROTOTYPE(record-structs): update for record structs
if (memberDecl is RecordDeclarationSyntax recordDecl && recordDecl.ParameterList == paramList)
{
method = TryGetSynthesizedRecordConstructor(recordDecl);
Expand Down Expand Up @@ -2369,6 +2374,7 @@ internal override Symbol RemapSymbolIfNecessaryCore(Symbol symbol)

internal override Func<SyntaxNode, bool> GetSyntaxNodesToAnalyzeFilter(SyntaxNode declaredNode, ISymbol declaredSymbol)
{
// PROTOTYPE(record-structs): update for record structs
switch (declaredNode)
{
case CompilationUnitSyntax unit when SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(Compilation, unit, fallbackToMainEntryPoint: false) is SynthesizedSimpleProgramEntryPointSymbol entryPoint:
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1912,6 +1912,7 @@ internal static BoundExpression BindImplicitConstructorInitializer(
NamedTypeSymbol baseType = constructor.ContainingType.BaseTypeNoUseSiteDiagnostics;

SourceMemberMethodSymbol sourceConstructor = constructor as SourceMemberMethodSymbol;
// PROTOTYPE(record-structs): update for record structs
Debug.Assert(sourceConstructor?.SyntaxNode is RecordDeclarationSyntax || ((ConstructorDeclarationSyntax)sourceConstructor?.SyntaxNode)?.Initializer == null);

// The common case is that the type inherits directly from object.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ internal enum DeclarationKind : byte
Submission,
ImplicitClass,
SimpleProgram,
Record
// PROTOTYPE(record-structs): rename to RecordClass?
Record,
RecordStruct
}

internal static partial class EnumConversions
Expand All @@ -39,6 +41,7 @@ internal static DeclarationKind ToDeclarationKind(this SyntaxKind kind)
case SyntaxKind.EnumDeclaration: return DeclarationKind.Enum;
case SyntaxKind.DelegateDeclaration: return DeclarationKind.Delegate;
case SyntaxKind.RecordDeclaration: return DeclarationKind.Record;
case SyntaxKind.RecordStructDeclaration: return DeclarationKind.RecordStruct;
default:
throw ExceptionUtilities.UnexpectedValue(kind);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,9 @@ public override SingleNamespaceOrTypeDeclaration VisitInterfaceDeclaration(Inter
public override SingleNamespaceOrTypeDeclaration VisitRecordDeclaration(RecordDeclarationSyntax node)
=> VisitTypeDeclaration(node, DeclarationKind.Record);

public override SingleNamespaceOrTypeDeclaration VisitRecordStructDeclaration(RecordStructDeclarationSyntax node)
=> VisitTypeDeclaration(node, DeclarationKind.RecordStruct);

private SingleNamespaceOrTypeDeclaration VisitTypeDeclaration(TypeDeclarationSyntax node, DeclarationKind kind)
{
SingleTypeDeclaration.TypeDeclarationFlags declFlags = node.AttributeLists.Any() ?
Expand All @@ -402,6 +405,7 @@ private SingleNamespaceOrTypeDeclaration VisitTypeDeclaration(TypeDeclarationSyn
var memberNames = GetNonTypeMemberNames(((Syntax.InternalSyntax.TypeDeclarationSyntax)(node.Green)).Members,
ref declFlags);

// PROTOTYPE(record-structs): update for record structs
// A record with parameters at least has a primary constructor
if (((declFlags & SingleTypeDeclaration.TypeDeclarationFlags.HasAnyNontypeMembers) == 0) &&
node is RecordDeclarationSyntax { ParameterList: { } })
Expand Down Expand Up @@ -627,6 +631,7 @@ private static bool CheckMemberForAttributes(Syntax.InternalSyntax.CSharpSyntaxN
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.RecordDeclaration:
// PROTOTYPE(record-structs): update for record structs
return (((Syntax.InternalSyntax.BaseTypeDeclarationSyntax)member).AttributeLists).Any();

case SyntaxKind.DelegateDeclaration:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public ImmutableArray<SyntaxList<AttributeListSyntax>> GetAttributeDeclarations(
case SyntaxKind.StructDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.RecordDeclaration:
case SyntaxKind.RecordStructDeclaration:
attributesSyntaxList = ((TypeDeclarationSyntax)typeDecl).AttributeLists;
break;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ internal override MethodSymbol Constructor
}

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

internal override ImmutableArray<NamedTypeSymbol> InterfacesNoUseSiteDiagnostics(ConsList<TypeSymbol> basesBeingResolved)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ internal override IEnumerable<FieldSymbol> GetFieldsToEmit()
IMethodSymbolInternal ISynthesizedMethodBodyImplementationSymbol.Method => _topLevelMethod;

internal override bool IsRecord => false;
internal override bool IsRecordStruct => false;
internal override bool HasPossibleWellKnownCloneMethod() => false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ internal override ImmutableArray<NamedTypeSymbol> InterfacesNoUseSiteDiagnostics
internal override NamedTypeSymbol BaseTypeNoUseSiteDiagnostics => ContainingAssembly.GetSpecialType(SpecialType.System_Object);

internal override bool IsRecord => false;
internal override bool IsRecordStruct => false;
internal override bool HasPossibleWellKnownCloneMethod() => false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public sealed override bool AreLocalsZeroed
}

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

bool ISynthesizedMethodBodyImplementationSymbol.HasMethodBodyDependency
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ internal override ImmutableArray<NamedTypeSymbol> GetDeclaredInterfaces(ConsList
internal sealed override NamedTypeSymbol NativeIntegerUnderlyingType => null;

internal override bool IsRecord => false;
internal override bool IsRecordStruct => false;

internal override bool Equals(TypeSymbol t2, TypeCompareKind comparison)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,8 @@ internal override AttributeUsageInfo GetAttributeUsageInfo()

internal override bool IsRecord => false;

internal override bool IsRecordStruct => false;

internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder<SynthesizedAttributeData> attributes)
{
base.AddSynthesizedAttributes(moduleBuilder, ref attributes);
Expand Down
2 changes: 2 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,8 @@ protected sealed override ITypeSymbol CreateITypeSymbol(CodeAnalysis.NullableAnn

internal override bool IsRecord => false;

internal override bool IsRecordStruct => false;

/// <summary>
/// Represents SZARRAY - zero-based one-dimensional array
/// </summary>
Expand Down
2 changes: 2 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,7 @@ protected sealed override ITypeSymbol CreateITypeSymbol(CodeAnalysis.NullableAnn
}

internal override bool IsRecord => false;

internal override bool IsRecordStruct => false;
}
}
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/Symbols/EnumConversions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ internal static TypeKind ToTypeKind(this DeclarationKind kind)
return TypeKind.Interface;

case DeclarationKind.Struct:
case DeclarationKind.RecordStruct:
return TypeKind.Struct;

default:
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,7 @@ protected sealed override ITypeSymbol CreateITypeSymbol(CodeAnalysis.NullableAnn
}

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,5 +214,7 @@ internal static bool IsCallingConventionModifier(NamedTypeSymbol modifierType)
}

internal override bool IsRecord => false;

internal override bool IsRecordStruct => false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,9 @@ internal override bool IsRecord
}
}

// PROTOTYPE(record-structs): update for record structs (is there a way to recognize a record struct from PE?)
internal override bool IsRecordStruct => false;

public override Accessibility DeclaredAccessibility
{
get
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ internal override UseSiteInfo<AssemblySymbol> GetUseSiteInfo()
internal sealed override NamedTypeSymbol NativeIntegerUnderlyingType => _underlyingType;

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

internal override bool Equals(TypeSymbol? other, TypeCompareKind comparison)
Expand Down
2 changes: 2 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,7 @@ protected override ITypeSymbol CreateITypeSymbol(CodeAnalysis.NullableAnnotation
}

internal override bool IsRecord => false;

internal override bool IsRecordStruct => false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@ public sealed override bool AreLocalsZeroed
internal sealed override NamedTypeSymbol NativeIntegerUnderlyingType => null;

internal sealed override bool IsRecord => _underlyingType.IsRecord;
internal sealed override bool IsRecordStruct => _underlyingType.IsRecordStruct;
internal sealed override bool HasPossibleWellKnownCloneMethod() => _underlyingType.HasPossibleWellKnownCloneMethod();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ public sealed override bool AreLocalsZeroed
=> throw ExceptionUtilities.Unreachable;

internal override bool IsRecord => false;
internal override bool IsRecordStruct => false;
internal override bool HasPossibleWellKnownCloneMethod() => false;
}
}
Loading