-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Implement definite assignment analysis for tuples #13107
Changes from 2 commits
56f7010
fc01769
2e0451a
9d18615
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -664,6 +664,28 @@ private void NoteWrite(BoundExpression n, BoundExpression value, bool read) | |
/// </summary> | ||
protected int VariableSlot(Symbol symbol, int containingSlot = 0) | ||
{ | ||
var fieldSymbol = symbol as TupleFieldSymbol; | ||
if ((object)fieldSymbol != null) | ||
{ | ||
TypeSymbol containingType = ((TupleTypeSymbol)symbol.ContainingType).UnderlyingNamedType; | ||
|
||
// for tuple fields the varible indentifier represents the underlying field | ||
symbol = fieldSymbol.TupleUnderlyingField; | ||
|
||
// descend through Rest fields | ||
// bail if corresponding slots do not exist | ||
while (containingType != symbol.ContainingType) | ||
{ | ||
var restField = containingType.GetMembers(TupleTypeSymbol.RestFieldName).FirstOrDefault() as FieldSymbol; | ||
if((object)restField == null || | ||
!_variableSlot.TryGetValue(new VariableIdentifier(restField, containingSlot), out containingSlot)) | ||
{ | ||
return -1; | ||
} | ||
containingType = restField.Type.TupleUnderlyingTypeOrSelf(); | ||
} | ||
} | ||
|
||
int slot; | ||
return (_variableSlot.TryGetValue(new VariableIdentifier(symbol, containingSlot), out slot)) ? slot : -1; | ||
} | ||
|
@@ -674,6 +696,29 @@ protected int VariableSlot(Symbol symbol, int containingSlot = 0) | |
protected int GetOrCreateSlot(Symbol symbol, int containingSlot = 0) | ||
{ | ||
if (symbol is RangeVariableSymbol) return -1; | ||
|
||
var fieldSymbol = symbol as TupleFieldSymbol; | ||
if ((object)fieldSymbol != null) | ||
{ | ||
TypeSymbol containingType = ((TupleTypeSymbol)symbol.ContainingType).UnderlyingNamedType; | ||
|
||
// for tuple fields the varible indentifier represents the underlying field | ||
symbol = fieldSymbol.TupleUnderlyingField; | ||
|
||
// descend through Rest fields | ||
// force corresponding slots if do not exist | ||
while (containingType != symbol.ContainingType) | ||
{ | ||
var restField = containingType.GetMembers(TupleTypeSymbol.RestFieldName).FirstOrDefault() as FieldSymbol; | ||
if (restField == null) | ||
{ | ||
return -1; | ||
} | ||
containingSlot = GetOrCreateSlot(restField, containingSlot); | ||
containingType = restField.Type.TupleUnderlyingTypeOrSelf(); | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it be worth extracting a helper method for use here and in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. extracted as In reply to: 74526518 [](ancestors = 74526518) |
||
|
||
VariableIdentifier identifier = new VariableIdentifier(symbol, containingSlot); | ||
int slot; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,6 +24,9 @@ internal class TupleFieldSymbol : WrappedFieldSymbol | |
public TupleFieldSymbol(TupleTypeSymbol container, FieldSymbol underlyingField, int tupleFieldId) | ||
: base(underlyingField) | ||
{ | ||
Debug.Assert(container.UnderlyingNamedType.Equals(underlyingField.ContainingType, TypeCompareKind.IgnoreDynamicAndTupleNames) || this is TupleVirtualElementFieldSymbol, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd prefer we avoid depending on the identity of particular internal implementation classes. Can There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The purpose of this assert is to actually check the internal implementation. I think it is ok to be strict about types here. |
||
"virtual fields should be represented by " + nameof(TupleVirtualElementFieldSymbol)); | ||
|
||
_containingTuple = container; | ||
_tupleFieldId = tupleFieldId; | ||
} | ||
|
@@ -185,18 +188,31 @@ public override Symbol AssociatedSymbol | |
} | ||
|
||
/// <summary> | ||
/// Represents an element field of a tuple type (such as (int a, byte b).a, or (int a, byte b).b) | ||
/// that is backed by a real field with a different name within the tuple underlying type. | ||
/// Represents an element field of a tuple type that is not backed by a real field | ||
/// with the same name within the tuple underlying type. | ||
/// | ||
/// Examples | ||
/// // alias to Item1 with a different name | ||
/// (int a, byte b).a | ||
/// | ||
/// // not backed directly by the underlying type | ||
/// (int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8).i8 | ||
/// | ||
/// NOTE: For any virtual element, there is a nonvirtual way to access the same underlying field. | ||
/// In scenarios where we need to enumerate actual fields of a struct, | ||
/// virtual fields should be ignored. | ||
/// </summary> | ||
internal sealed class TupleRenamedElementFieldSymbol : TupleElementFieldSymbol | ||
internal sealed class TupleVirtualElementFieldSymbol : TupleElementFieldSymbol | ||
{ | ||
private readonly string _name; | ||
|
||
public TupleRenamedElementFieldSymbol(TupleTypeSymbol container, FieldSymbol underlyingField, string name, int tupleElementOrdinal, Location location) | ||
public TupleVirtualElementFieldSymbol(TupleTypeSymbol container, FieldSymbol underlyingField, string name, int tupleElementOrdinal, Location location) | ||
: base(container, underlyingField, tupleElementOrdinal, location) | ||
{ | ||
Debug.Assert(name != null); | ||
Debug.Assert(name != underlyingField.Name); | ||
Debug.Assert(name != underlyingField.Name || !container.UnderlyingNamedType.Equals(underlyingField.ContainingType, TypeCompareKind.IgnoreDynamicAndTupleNames), | ||
"fields that map directly to underlying should not be represented by " + nameof(TupleVirtualElementFieldSymbol)); | ||
|
||
_name = name; | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo:
variable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed