-
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 all 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 |
---|---|---|
|
@@ -15,7 +15,7 @@ internal class TupleFieldSymbol : WrappedFieldSymbol | |
protected readonly TupleTypeSymbol _containingTuple; | ||
|
||
/// <summary> | ||
/// If this field represents a tuple element (including the name match), | ||
/// If this field represents a tuple element, | ||
/// id is an index of the element (zero-based). | ||
/// Otherwise, (-1 - [index in members array]); | ||
/// </summary> | ||
|
@@ -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; | ||
} | ||
|
@@ -37,7 +40,7 @@ public override bool IsTupleField | |
} | ||
|
||
/// <summary> | ||
/// If this field represents a tuple element (including the name match), | ||
/// If this field represents a tuple element, | ||
/// id is an index of the element (zero-based). | ||
/// Otherwise, (-1 - [index in members array]); | ||
/// </summary>i | ||
|
@@ -100,22 +103,27 @@ internal override DiagnosticInfo GetUseSiteDiagnostic() | |
|
||
public override sealed int GetHashCode() | ||
{ | ||
return Hash.Combine(_containingTuple.GetHashCode(), _tupleFieldId.GetHashCode()); | ||
return Hash.Combine( | ||
Hash.Combine(_containingTuple.GetHashCode(), _tupleFieldId.GetHashCode()), | ||
this.Name.GetHashCode()); | ||
} | ||
|
||
public override sealed bool Equals(object obj) | ||
{ | ||
return Equals(obj as TupleFieldSymbol); | ||
} | ||
var other = obj as TupleFieldSymbol; | ||
|
||
public bool Equals(TupleFieldSymbol other) | ||
{ | ||
if ((object)other == this) | ||
{ | ||
return true; | ||
} | ||
|
||
return (object)other != null && _tupleFieldId == other._tupleFieldId && _containingTuple == other._containingTuple; | ||
// note we have to compare both index and name because | ||
// in nameless tuple there could be fields that differ only by index | ||
// and in named tupoles there could be fields that differ only by name | ||
return (object)other != null && | ||
_tupleFieldId == other.TupleElementIndex && | ||
_containingTuple == other._containingTuple && | ||
this.Name == other.Name; | ||
} | ||
} | ||
|
||
|
@@ -185,18 +193,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; | ||
} | ||
|
||
|
@@ -223,5 +244,13 @@ public override Symbol AssociatedSymbol | |
return null; | ||
} | ||
} | ||
|
||
internal override bool IsVirtualTupleField | ||
{ | ||
get | ||
{ | ||
return true; | ||
} | ||
} | ||
} | ||
} |
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.
Is it possible to hit this case?Nevermind, I was thinking about a field that is not a
FieldSymbol
, but really this is for missingRest
field. I see the test case for that.