Move to the use site tracking for the purpose of recording used assemblies#40560
Conversation
- Merged extern aliases - Embeddable attributes - Usage of canonical definitions for NoPia embedded types - nameof of a method - Deconstruction - Collection initializers Related to dotnet#37768.
|
@dotnet/roslyn-compiler Please review. |
1 similar comment
|
@dotnet/roslyn-compiler Please review. |
Idiomatic English would be either "various pieces of information" or just "information" #Resolved Refers to: src/Compilers/Core/Portable/Binding/BindingDiagnosticBag.cs:15 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
|
It would be really nice to have a measure of the performance impact of this approach, if any. #Closed |
Is this a common pattern we have already? If not, I'd suggest Refers to: src/Compilers/Core/Portable/Binding/BindingDiagnosticBag.cs:99 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
We need a better name for this. Having a binding-diagnostic-bag (typically named diagnostic-bag) that contains a diagnostic-bag named diagnostic-bag is just too much. #Closed Refers to: src/Compilers/Core/Portable/Binding/BindingDiagnosticBag.cs:18 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
|
|
||
| namespace Microsoft.CodeAnalysis.CSharp | ||
| { | ||
| internal static class BindingDiagnosticBagExtensions |
There was a problem hiding this comment.
BindingDiagnosticBagExtensions [](start = 26, length = 30)
File is incorrectly named given this class name. #Closed
There was a problem hiding this comment.
File is incorrectly named given this class name.
The BindingDiagnosticBag class is below
In reply to: 361546561 [](ancestors = 361546561)
There was a problem hiding this comment.
Please place the class BindingDiagnosticBagExtensions in a file BindingDiagnosticBagExtensions.cs.
In reply to: 361549090 [](ancestors = 361549090,361546561)
Would this sound better: "This is base class for a bag used to accumulate various information while binding is performed"? In reply to: 569139255 [](ancestors = 569139255) Refers to: src/Compilers/Core/Portable/Binding/BindingDiagnosticBag.cs:15 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
I am open to suggestions. In reply to: 569146658 [](ancestors = 569146658) Refers to: src/Compilers/Core/Portable/Binding/BindingDiagnosticBag.cs:18 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
If this is only invoked in the method below, it should probably be changed to Refers to: src/Compilers/Core/Portable/Diagnostic/CommonMessageProvider.cs:244 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
Not necessary. We should free when it is appropriate to free. I.e. constituent pieces are either null or allocated from a pool. In reply to: 569141687 [](ancestors = 569141687) Refers to: src/Compilers/Core/Portable/Binding/BindingDiagnosticBag.cs:81 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
Even though it is safe to call this method any time. It is likely not the right thing to do when we are not collecting diagnostics. In other words, this assert is not about null-safety. In reply to: 569140729 [](ancestors = 569140729,569140668) Refers to: src/Compilers/Core/Portable/Binding/BindingDiagnosticBag.cs:45 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
Yes, this is a common pattern with DiagnosticBag, keeping the same name avoids significant amount of code changes. In reply to: 569142395 [](ancestors = 569142395) Refers to: src/Compilers/Core/Portable/Binding/BindingDiagnosticBag.cs:99 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
As far as I can tell, we have no methods named this currently. In reply to: 569147655 [](ancestors = 569147655,569142395) Refers to: src/Compilers/Core/Portable/Binding/BindingDiagnosticBag.cs:99 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
No. The problem is In reply to: 569146820 [](ancestors = 569146820,569139255) Refers to: src/Compilers/Core/Portable/Binding/BindingDiagnosticBag.cs:15 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
I see nothing wrong in calling these methods directly, now or in the future. Keeping original accessibility. In reply to: 569147070 [](ancestors = 569147070) Refers to: src/Compilers/Core/Portable/Diagnostic/CommonMessageProvider.cs:244 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
Specifically, various is an adjective that implies the noun it's modifying is countable, while information is not a countable noun. So it needs to either add a countable thing (pieces of) or be removed. In reply to: 569147835 [](ancestors = 569147835,569146820,569139255) Refers to: src/Compilers/Core/Portable/Binding/BindingDiagnosticBag.cs:15 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
This is a violation of good software engineering principles (e.g. principle of least privilege). Please restrict access. In reply to: 569147877 [](ancestors = 569147877,569147070) Refers to: src/Compilers/Core/Portable/Diagnostic/CommonMessageProvider.cs:244 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
|
Finished review pass (Iteration 4). The only issue remaining that concerns me is the access of |
| private static MethodSymbol GetEntryPoint(CSharpCompilation compilation, PEModuleBuilder moduleBeingBuilt, bool hasDeclarationErrors, bool emitMethodBodies, DiagnosticBag diagnostics, CancellationToken cancellationToken) | ||
| private static MethodSymbol GetEntryPoint(CSharpCompilation compilation, PEModuleBuilder moduleBeingBuilt, bool hasDeclarationErrors, bool emitMethodBodies, BindingDiagnosticBag diagnostics, CancellationToken cancellationToken) | ||
| { | ||
| Debug.Assert(diagnostics.DiagnosticBag != null); |
There was a problem hiding this comment.
Consider using either is object, or RoslynDebug.Assert. This is a pure null check in an unannotated method, and will cause warnings when nullable is eventually enabled. A simple change now makes it easier later. #WontFix
There was a problem hiding this comment.
Consider using either is object, or RoslynDebug.Assert. This is a pure null check in an unannotated method, and will cause warnings when nullable is eventually enabled. A simple change now makes it easier later.
This file has lots of asserts that will have to be changed when nullable is enabled here, for now I keep the same stile as used throughout the file.
In reply to: 362136392 [](ancestors = 362136392)
| private void CompileSynthesizedMethods(ImmutableArray<NamedTypeSymbol> additionalTypes, DiagnosticBag diagnostics) | ||
| private void CompileSynthesizedMethods(ImmutableArray<NamedTypeSymbol> additionalTypes, BindingDiagnosticBag diagnostics) | ||
| { | ||
| Debug.Assert(diagnostics.DiagnosticBag != null); |
| { | ||
| Debug.Assert(compilation != null); | ||
| Debug.Assert(diagnostics != null); | ||
| Debug.Assert(diagnostics.DiagnosticBag != null); |
There was a problem hiding this comment.
Consider using either is object or RoslynDebug.Assert #WontFix
| Debug.Assert(!discardedDiagnostics.HasAnyErrors()); | ||
| discardedDiagnostics.Free(); | ||
| discardedDiagnostics.DiagnosticBag.Clear(); | ||
| _diagnostics.AddRangeAndFree(discardedDiagnostics); |
There was a problem hiding this comment.
Consider using a method that is explicit about adding Dependencies only. Calling clear on the line before this is confusing at first read. #Resolved
| if (!hasErrors) | ||
| { | ||
| diagnostics.AddRange(bag); | ||
| bag.DiagnosticBag.Clear(); |
There was a problem hiding this comment.
Perhaps add a clarifying comment that we still want to record assembly usage in the presence of errors. #Resolved
There was a problem hiding this comment.
Perhaps add a clarifying comment that we still want to record assembly usage in the presence of errors.
Moving to using AddDependencies API instead
In reply to: 362137536 [](ancestors = 362137536)
| if (!hasErrors) | ||
| { | ||
| diagnostics.AddRange(bag); | ||
| bag.DiagnosticBag.Clear(); |
There was a problem hiding this comment.
Same clarifying comment would be useful. #Resolved
There was a problem hiding this comment.
Same clarifying comment would be useful.
Moving to using AddDependencies API instead
In reply to: 362137708 [](ancestors = 362137708)
I really do like the overall approach much better here. This is the type of code that was worrying me about needing to be spread everywhere, and now it just comes along for the ride. #Resolved Refers to: src/Compilers/CSharp/Portable/Symbols/AliasSymbol.cs:318 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = True) |
Should we consider saving this off to a temp? #Resolved Refers to: src/Compilers/CSharp/Portable/Symbols/Compilation_UsedAssemblies.cs:40 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
I do not agree with this “hardcore” application of the principle in this particular case. We are dealing with internal utility type, addition of the convenience wrappers doesn’t make the methods being wrapped less useful or safe. However, it feels like you are not open to having any discussion around the subject and are willing to block PR on this issue alone. For no other reason, but to get about a week worth of work moving forward, I will adjust accessibility. In reply to: 569825083 [](ancestors = 569825083,569147877,569147070) Refers to: src/Compilers/Core/Portable/Diagnostic/CommonMessageProvider.cs:244 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
Could you clarify please, which part? In reply to: 569854107 [](ancestors = 569854107) Refers to: src/Compilers/CSharp/Portable/Symbols/Compilation_UsedAssemblies.cs:40 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
Is this about MergedAssemblyReferencesMap? In reply to: 569854489 [](ancestors = 569854489,569854107) Refers to: src/Compilers/CSharp/Portable/Symbols/Compilation_UsedAssemblies.cs:40 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
It doesn't look like this return is being used. #Resolved Refers to: src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs:1015 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
Extracting MergedAssemblyReferencesMap into a local. Please reactivate if this will not address the suggestion. In reply to: 569854683 [](ancestors = 569854683,569854489,569854107) Refers to: src/Compilers/CSharp/Portable/Symbols/Compilation_UsedAssemblies.cs:40 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
I believe this doesn't violate formatting guidelines In reply to: 569854959 [](ancestors = 569854959) Refers to: src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs:988 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
Consider doing this part unconditionally, and returning the result of the above conditional (saving said conditional off to a temp). #WontFix Refers to: src/Compilers/CSharp/Portable/Symbols/MethodSymbol.cs:904 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
Consider doing this part unconditionally, and returning the result of the above conditional (saving said conditional off to a temp). #WontFix Refers to: src/Compilers/CSharp/Portable/Symbols/FieldSymbol.cs:354 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
Looks used to me: In reply to: 569855062 [](ancestors = 569855062) Refers to: src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs:1015 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
This is an argument for In reply to: 569855345 [](ancestors = 569855345,569854959) Refers to: src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs:988 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
This is addressed in #40640 In reply to: 569854263 [](ancestors = 569854263,569825083,569147877,569147070) Refers to: src/Compilers/Core/Portable/Diagnostic/CommonMessageProvider.cs:244 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
This is addressed in #40640 In reply to: 569855110 [](ancestors = 569855110,569854683,569854489,569854107) Refers to: src/Compilers/CSharp/Portable/Symbols/Compilation_UsedAssemblies.cs:40 in dce0ee8. [](commit_id = dce0ee8, deletion_comment = False) |
333fred
left a comment
There was a problem hiding this comment.
LGTM (commit 4) with followup PR
|
@gafter I believe the issue that you had indicated as blocking has been addressed. |
The basic idea is that dependencies should be tracked along with use-site diagnostics and should be collected together with regular diagnostic messages and bubble up to the top. The final consumer of the combined diagnostics and dependencies is responsible for “registering” dependencies with the compilation or ignore them (due to the context, etc.). I believe this is a very robust approach and would require little maintenance going forward, because every time a symbol is used, a use-site diagnostics should be reported. We just need to keep doing that for every new feature and dependencies will be tracked automatically. Also, the code performing binding no longer needs to be context aware (should dependencies be tracked at this moment or not), they should always be tracked and collected along with the regular diagnostics and it is up to the consumer to decide what to do with them, if anything. For example, when SemanticModel performs binding, dependencies are not registered, etc.