Skip to content

Do not include value types in NullableAttribute byte[]#36519

Merged
cston merged 7 commits intodotnet:masterfrom
cston:skip-value-type
Jun 19, 2019
Merged

Do not include value types in NullableAttribute byte[]#36519
cston merged 7 commits intodotnet:masterfrom
cston:skip-value-type

Conversation

@cston
Copy link
Copy Markdown
Contributor

@cston cston commented Jun 17, 2019

Do not include a 0 entry in the byte[] for non-generic value types. The 0 is still included for generic value types, tuples, and type parameters constrained to value types.

@cston cston requested a review from a team as a code owner June 17, 2019 22:41
@jcouv jcouv self-assigned this Jun 18, 2019
@jcouv jcouv added this to the 16.2.P4 milestone Jun 18, 2019
@cston
Copy link
Copy Markdown
Contributor Author

cston commented Jun 18, 2019

@dotnet/roslyn-compiler please review.

private NamedTypeSymbol _lazyBaseType = ErrorTypeSymbol.UnknownResultType;
private ImmutableArray<NamedTypeSymbol> _lazyInterfaces = default(ImmutableArray<NamedTypeSymbol>);
private NamedTypeSymbol _lazyDeclaredBaseType = ErrorTypeSymbol.UnknownResultType;
private NamedTypeSymbol _lazyDeclaredBaseTypeWithoutNullability = ErrorTypeSymbol.UnknownResultType;
Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs Jun 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private NamedTypeSymbol _lazyDeclaredBaseTypeWithoutNullability = ErrorTypeSymbol.UnknownResultType; [](start = 8, length = 100)

It doesn't look like adding this cache is necessary. Inside TypeKind.get we could check if we already have _lazyDeclaredBaseType and use that, otherwise we could resolve the type from metadata without applying any transforms, including tuple and dynamic, and use that type without caching it. #Closed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even better might be to bundle resolution of base type with calculating type kind for non-interfaces. Before we apply any transforms to the base type, calculate and set the type kind, then proceed with transforms.


In reply to: 294935242 [](ancestors = 294935242)

- Nullable value type: the representation of the type argument only
- Value type: the representation of the type arguments in order including containing types
- Non-generic value type: skipped
- Generic value type: 0, followed by the representation of the type arguments in order including containing types
Copy link
Copy Markdown
Member

@jcouv jcouv Jun 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0, [](start = 21, length = 4)

just curious: why do we want to encode an annotation for a value type? Is this due to a concern for cycles when loading metadata? (if so, may be good to record rationale) #Resolved

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the reason that generic value types (and type parameters constrained to struct) include a 0 byte is to avoid cycles when loading types from metadata - in particular, when loading type parameters with constraint types. Simple (non-generic) value types are less of a concern.

I'll add a note to the document.


In reply to: 294943765 [](ancestors = 294943765)

if (!expectedPreviously.SequenceEqual(expectedNow))
{
position = 0;
Assert.True(underlyingType.ApplyNullableTransforms(0, ImmutableArray.Create(expectedPreviously), ref position, out updated) || position < expectedPreviously.Length);
Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs Jun 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

underlyingType.ApplyNullableTransforms(0, ImmutableArray.Create(expectedPreviously), ref position, out updated) [](start = 28, length = 111)

Should this condition be negated? #Closed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or perhaps removed?


In reply to: 294947325 [](ancestors = 294947325)

return type.IsNullableType();
}
else
return type.IsValueType && !type.IsTupleType;
Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs Jun 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type.IsValueType [](start = 19, length = 16)

Are we testing scenarios when concrete value type references within another type cannot be resolved from metadata (an assembly reference is missing, for example)? It looks like this might cause a confusion during ApplyNullableTransforms causing us to apply flags to wrong places.

@AlekseyTs
Copy link
Copy Markdown
Contributor

AlekseyTs commented Jun 18, 2019

Done with review pass (iteration 4) #Closed

VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F25").TypeWithAnnotations, new byte[] { 0, 1 }, new byte[] { 0, 1 }, "S<U!>");
VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F31").TypeWithAnnotations, new byte[] { 0 }, new byte[] { 0 }, "V");
VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F32").TypeWithAnnotations, new byte[] { 0, 0 }, new byte[] { 0 }, "V?");
VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F33").TypeWithAnnotations, new byte[] { 1, 0 }, new byte[] { 1, 0 }, "V[]!");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new byte[] { 1, 0 } [](start = 103, length = 19)

nit: consider using null for expectedPreviously when it is equals to expectedNow, as the actual value will be ignored.

Copy link
Copy Markdown
Member

@jcouv jcouv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM modulo Aleksey's feedback on removing cache. Thanks (iteration 4)

@jaredpar jaredpar mentioned this pull request Jun 18, 2019
23 tasks
{
// Decoding nullability might lead to a cycle calculating the base type.
// Instead, return early without updating the field.
return baseType;
Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs Jun 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return baseType; [](start = 24, length = 16)

No need to do dynamic and tuple transforms for this code path. #Closed

}

[Fact]
public void EmitAttribute_ValueTypes_08()
Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs Jun 19, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EmitAttribute_ValueTypes_08 [](start = 20, length = 27)

I don't think this test covers the error scenario that I was interested in. I was thinking about the tests that deals with types coming from metadata, this test verifies types coming from source. #Resolved

Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (iteration 7), the tests can be followed up on in a separate PR.

@cston cston merged commit 055ef1c into dotnet:master Jun 19, 2019
@cston cston deleted the skip-value-type branch June 19, 2019 17:06
333fred added a commit to 333fred/roslyn that referenced this pull request Jun 20, 2019
* dotnet/master: (85 commits)
  Don't complete statement when typing semicolon inside comments in an argument list (dotnet#36521)
  Set focus to editor before finding text
  Add a bunch of nullability support to some code generation helpers
  Add 'annotations' and 'warnings' support to nullable directive (dotnet#36464)
  Fixed IDE services touching `notnull` constraint (dotnet#36508)
  Update compiler toolset to arcade version (dotnet#36549)
  Fix for 923157
  Do not include value types in NullableAttribute byte[] (dotnet#36519)
  Fix a deadlock in InvokeOnUIThread
  Apply a hang mitigating timeout to UI thread operations
  Move to a different lowering from for nullable value types to work around a bug in TransformCompoundAssignmentLHS. Addressed PR feedback.
  Fix stack overflow in requesting syntax directives (dotnet#36347)
  crash on ClassifyUpdate for EventFields (dotnet#35962)
  fixing bad merge with refactoring that was checked in later
  added basic completion statement telemetry
  Remove duplication in AbstractSymbolCompletionProvider.CreateItems
  Disable move type when the options service isn't present (dotnet#36334)
  Fix crash where type inference doing method inference needs to drop nullability
  Revert "Use IVsSolution to look up IVsHierarchy by project GUID (dotnet#35746)"
  Fix parsing bug in invalid using statements (dotnet#36428)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants