Inject NonNullTypesAttribute#29180
Inject NonNullTypesAttribute#29180jcouv merged 20 commits intodotnet:features/NullableReferenceTypesfrom
Conversation
There was a problem hiding this comment.
Just curious: Why pass a delegate to a local function rather than inlining the body of the local function as a lambda? #Resolved
There was a problem hiding this comment.
I can't see what code this comment was for, and I couldn't find injectNamespaceOpt: injectNamespace);.
Is this comment still alive?
In reply to: 208802151 [](ancestors = 208802151)
|
This is meant for design discussion, not for detailed review yet ;-) Thanks #Closed |
98eb2c4 to
07d7944
Compare
There was a problem hiding this comment.
ReportUseSiteDiagnostics [](start = 19, length = 24)
ReportUseSiteDiagnostics [](start = 19, length = 24)
📝 I wasn't able to find scenarios for use-site diagnostics on AttributeTargets or the constructor of AttributeUsage, but I'm including those checks anyways. #Closed
e4455c1 to
39614a0
Compare
b18dba6 to
6407e6d
Compare
| var obj2 = new TestReference.TestType2(); | ||
| var obj3 = new TestReference.TestType3(); | ||
| } | ||
| }"; |
There was a problem hiding this comment.
Remove if not needed. #Resolved
|
Consider splitting referenced assembly and added module cases. Will simply adding a module declaring the type cause an error, or it is reported only if the attribute is used? #Closed Refers to: docs/compilers/CSharp/Compiler Breaking Changes - VS2019.md:11 in f4a2147. [](commit_id = f4a2147, deletion_comment = False) |
|
Also, I think the term "referenced" is somewhat confusing in this context. Would it be clearer to say something like: "we allowed to refer to a In reply to: 419508939 [](ancestors = 419508939) Refers to: docs/compilers/CSharp/Compiler Breaking Changes - VS2019.md:11 in bba7cd2. [](commit_id = bba7cd293a3deacbf276165a0f93fae80ff9426a, deletion_comment = False) |
| *Breaks are formatted with a monotonically increasing numbered list to allow them to referenced via shorthand (i.e., "known break #1"). | ||
| Each entry should include a short description of the break, followed by either a link to the issue describing the full details of the break or the full details of the break inline.* | ||
|
|
||
| 1. Previously, we allowed the `Microsoft.CodeAnalysis.EmbeddedAttribute` to be referenced from a source module. |
There was a problem hiding this comment.
to be referenced from [](start = 73, length = 21)
declared in source? #Closed
There was a problem hiding this comment.
No, it can still be declared in source. The scenario that changed is with a module added that declares that type.
In reply to: 216033962 [](ancestors = 216033962)
There was a problem hiding this comment.
No, it can still be declared in source. The scenario that changed is with a module added that declares that type.
So this is not about a source module, this is a bout an added module. Also consider the other comment about using "referenced" term.
In reply to: 216041844 [](ancestors = 216041844,216033962)
| => new AttributeUsageInfo(validTargets: AttributeTargets.All, allowMultiple: false, inherited: false); | ||
|
|
||
| internal override DiagnosticBag GetDiagnostics() | ||
| => _diagnostics; |
There was a problem hiding this comment.
=> _diagnostics [](start = 12, length = 15)
Consider avoiding exposing "private" DiagnosticBag to external consumers. That can be achieved by adding a DiagnosticBag parameter where the diagnostics should be added. #Closed
|
|
||
| class InjectedNamespaceSymbol : NamespaceSymbol | ||
| { | ||
| private ModuleSymbol _module; |
There was a problem hiding this comment.
private ModuleSymbol _module; [](start = 16, length = 29)
I think this field is not necessary. It looks like it is used only for Extent and I think we can safely return extent for _containingNamespace #Closed
| class InjectedNamespaceSymbol : NamespaceSymbol | ||
| { | ||
| private ModuleSymbol _module; | ||
| private NamespaceSymbol _containingNamespace; |
There was a problem hiding this comment.
private NamespaceSymbol _containingNamespace; [](start = 16, length = 45)
readonly? #Closed
| internal sealed class InjectedNonNullTypesAttributeSymbol : InjectedAttributeSymbol | ||
| { | ||
| private ImmutableArray<CSharpAttributeData> _lazyCustomAttributes; | ||
| private SymbolCompletionState _state; |
There was a problem hiding this comment.
_state [](start = 38, length = 6)
I will remove the completion state (and left-over logic that relates to it) #Resolved
| public override string Name | ||
| => _name; | ||
|
|
||
| public override AssemblySymbol ContainingAssembly |
There was a problem hiding this comment.
public override AssemblySymbol ContainingAssembly [](start = 16, length = 49)
I think we can rely on implementation in base class. #Closed
There was a problem hiding this comment.
There is no implementation (just the abstract declaration).
In reply to: 216052712 [](ancestors = 216052712)
| : ImmutableArray<NamedTypeSymbol>.Empty; | ||
| } | ||
|
|
||
| internal override LexicalSortKey GetLexicalSortKey() |
There was a problem hiding this comment.
internal override LexicalSortKey GetLexicalSortKey() [](start = 16, length = 52)
I think we can rely on implementation in base class. #Closed
| internal override NamespaceExtent Extent | ||
| => new NamespaceExtent(_module); | ||
|
|
||
| internal override ImmutableArray<Symbol> GetMembersUnordered() |
There was a problem hiding this comment.
internal override ImmutableArray GetMembersUnordered() [](start = 16, length = 62)
I think we can rely on implementation in base class. #Closed
| return _nameToTypeMembersMap; | ||
| } | ||
|
|
||
| internal override ImmutableArray<NamedTypeSymbol> GetTypeMembersUnordered() |
There was a problem hiding this comment.
internal override ImmutableArray GetTypeMembersUnordered() [](start = 16, length = 75)
I think we can rely on implementation in base class. #Closed
| NamedTypeSymbolAll = NamedTypeSymbolWithLocationAll | MembersCompleted, | ||
|
|
||
| // For injected symbols | ||
| InjectedSymbolAll = Attributes, |
There was a problem hiding this comment.
InjectedSymbolAll = Attributes, [](start = 8, length = 31)
Is this still used? Consider reverting the file otherwise. #Closed
| _diagnostics = diagnostics; | ||
| } | ||
|
|
||
| public override ImmutableArray<Location> Locations |
There was a problem hiding this comment.
public override ImmutableArray Locations [](start = 7, length = 51)
Can we rely on implementation from base? #Closed
| #else | ||
| return result; | ||
| #endif | ||
| return GetMembers().ConditionallyDeOrder(); |
There was a problem hiding this comment.
return GetMembers().ConditionallyDeOrder(); [](start = 12, length = 43)
Is base implementation different? #Closed
| return ImmutableArray<CSharpAttributeData>.Empty; | ||
| } | ||
|
|
||
| Binder.ReportUseSiteDiagnostics(ctor, _diagnostics, Location.None); |
There was a problem hiding this comment.
Binder.ReportUseSiteDiagnostics(ctor, _diagnostics, Location.None); [](start = 12, length = 67)
Doesn't Binder.GetWellKnownTypeMember take care of this? #Closed
There was a problem hiding this comment.
I didn't manage to hit this with a test, but I fixed this anyways.
The few ways I know to generate use-site diagnostics didn't work:
- Obsolete is not reported for well-known types
- I couldn't create a missing type because we're dealing with corlib
In reply to: 216092257 [](ancestors = 216092257)
| { | ||
| if (_lazyCustomAttributes.IsDefault) | ||
| { | ||
| ImmutableInterlocked.InterlockedInitialize(ref _lazyCustomAttributes, MakeAttributes()); |
There was a problem hiding this comment.
ImmutableInterlocked.InterlockedInitialize(ref _lazyCustomAttributes, MakeAttributes()); [](start = 16, length = 88)
It looks like there is a chance of duplicating diagnostics when more than one thread is executing this line at the same time. #Closed
| internal override void GenerateMethodBody(TypeCompilationState compilationState, DiagnosticBag diagnostics) | ||
| { | ||
| var containingType = (InjectedNonNullTypesAttributeSymbol)ContainingType; | ||
| GenerateMethodBodyCore(compilationState, containingType._diagnostics); |
There was a problem hiding this comment.
GenerateMethodBodyCore(compilationState, containingType._diagnostics); [](start = 16, length = 70)
Let's assume this call produces diagnostics. Every time we try to emit, will we add it again? So, each subsequent attempt will have more and more duplicates? #Closed
|
|
||
| void addInjectedAttribute(WellKnownType wellKnownType, bool canUseFromSource) | ||
| { | ||
| NamedTypeSymbol attribute = Compilation.GetWellKnownType(wellKnownType); |
There was a problem hiding this comment.
Compilation.GetWellKnownType [](start = 44, length = 28)
Can this return a symbol from an added module? #Closed
| }"; | ||
|
|
||
| CreateCompilation(code, references: new[] { reference }, assemblyName: "Source").VerifyDiagnostics( | ||
| // error CS0101: The namespace 'Microsoft.CodeAnalysis' already contains a definition for 'EmbeddedAttribute' |
There was a problem hiding this comment.
// error CS0101: The namespace 'Microsoft.CodeAnalysis' already contains a definition for 'EmbeddedAttribute' [](start = 16, length = 109)
The breaking change description says:
"
- Previously, we allowed to refer to a
Microsoft.CodeAnalysis.EmbeddedAttributetype declared in an added module.
In Visual Studio 2019, this produces a collision with the injected declaration of that type.
"
However, it doesn't look like this scenario refers to the type, yet it is still an error. Consider adjusting description of the breaking change. It isn't really about referring, it is about having this type declared in an added module. #Closed
|
Done with review pass (iteration 19). Let's discuss offline what outstanding issues can be followed up separately. #Closed |
|
|
||
| // NonNullTypesAttribute from referenced assembly is used via extern alias | ||
| var comp = CreateCompilation(code, references: new[] { reference.ToMetadataReference(aliases: ImmutableArray.Create("Reference")) }); | ||
| comp.VerifyDiagnostics(); |
There was a problem hiding this comment.
VerifyDiagnostics [](start = 17, length = 17)
Let's also check that .NonNullTypes is true on the SourceModule #Closed
|
Awesome. Thanks a lot for the review! |
If no NonNullTypesAttribute type is available in source, we make one up.