Skip to content
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

Annotate ReferenceManager #42348

Merged
merged 8 commits into from
Mar 24, 2020
Merged

Annotate ReferenceManager #42348

merged 8 commits into from
Mar 24, 2020

Conversation

jaredpar
Copy link
Member

No description provided.

@jaredpar jaredpar added Area-Compilers Concept-Null Annotations The issue involves annotating an API for nullable reference types labels Mar 11, 2020
@@ -424,19 +424,20 @@ private bool CreateAndSetSourceAssemblyFullBind(CSharpCompilation compilation)

for (int i = 1; i < bindingResult.Length; i++)
{
if ((object)bindingResult[i].AssemblySymbol == null)
ref BoundInputAssembly bound = ref bindingResult[i];
Copy link
Member Author

Choose a reason for hiding this comment

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

The lack of member tracking in arrays was particularly problematic for this change. Then again this code is essentially paassing around large arrays of mutable struct values. It's the worst possible case for nullability. This doesn't make me want to push for array index tracking (that's really expensive) but it does make me think that if we were doing this again we would've chosen a different approach. Possibly wrapping this array in a simple struct wrapper that could've handled many of these assertions.

@@ -567,36 +568,41 @@ private bool CreateAndSetSourceAssemblyFullBind(CSharpCompilation compilation)

foreach (int i in newSymbols)
{
ref BoundInputAssembly currentBindingResult = ref bindingResult[i];
Copy link
Member Author

Choose a reason for hiding this comment

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

This is another theme in this PR: stop passing around an array an index. The lack of array index state tracking makes this hard to manage. Instead just pass around a ref to the array element. This also has the benefit of reducing the amount of times we dereference the array at runtime.

@jaredpar jaredpar marked this pull request as ready for review March 12, 2020 17:40
@jaredpar jaredpar requested a review from a team as a code owner March 12, 2020 17:40
@jaredpar
Copy link
Member Author

@dotnet/roslyn-compiler PTAL

{
private readonly AssemblyIdentity _referenceIdentity;
private readonly AssemblyIdentity? _referenceIdentity;
Copy link
Member

Choose a reason for hiding this comment

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

Both constructors use non-nullable referenceIdentity. I assume this field is marked as nullable because one might do default(AssemblyReferenceBinding). Is that the reason?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes. The runtime nullable annotation guide favors treating reference fields in structs as nullable since the use case default(T) must be considered. There are some exceptions considered but my reading is that it should be the rare case.

https://github.com/dotnet/runtime/blob/master/docs/coding-guidelines/api-guidelines/nullability.md


private string GetDebuggerDisplay()
private string? GetDebuggerDisplay()
Copy link
Member

Choose a reason for hiding this comment

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

Just curious, how does the debugger behave when the method given to DebuggerDisplay returns null?

Copy link
Member Author

Choose a reason for hiding this comment

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

For the way it's defined on this type, using the [DebuggerDisplay] attribute, it will display simply null.

@jcouv
Copy link
Member

jcouv commented Mar 13, 2020

#nullable enable

Can we remove these (also below)?


Refers to: src/Compilers/Core/Portable/ReferenceManager/CommonReferenceManager.Binding.cs:1017 in dbb8542. [](commit_id = dbb8542e5c9269794800d7dc0104515009801903, deletion_comment = False)

Copy link
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.

Done with review pass (iteration 4)

@jcouv jcouv self-assigned this Mar 18, 2020
@jcouv
Copy link
Member

jcouv commented Mar 19, 2020

@jaredpar This PR probably needs updating (possibly merging) to resolve build issues.

@jaredpar
Copy link
Member Author

@jcouv thanks, should be fixed now.

Copy link
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 Thanks (iteration 8)

@jaredpar
Copy link
Member Author

@dotnet/roslyn-compiler can I please get a second review? PR is two weeks old.

@@ -200,7 +201,7 @@ public ReferencedAssemblyIdentity(AssemblyIdentity identity, MetadataReference r
TCompilation compilation,
[Out] Dictionary<string, List<ReferencedAssemblyIdentity>> assemblyReferencesBySimpleName,
out ImmutableArray<MetadataReference> references,
out IDictionary<(string, string), MetadataReference> boundReferenceDirectiveMap,
[NotNull] out IDictionary<(string, string), MetadataReference>? boundReferenceDirectiveMap,
Copy link
Contributor

Choose a reason for hiding this comment

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

what does it do to put 'NotNull' on an 'out' parameter of a reference type?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's like [NotNullWhen] except that the "When" portion is always true. Basically this method will unconditionally assign a non-null value to the parameter.

Copy link
Contributor

@RikkiGibson RikkiGibson Mar 24, 2020

Choose a reason for hiding this comment

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

What I was trying to ask is: why can't this parameter be written as out IDictionary<(string, string), MetadataReference> boundReferenceDirectiveMap, instead of the way it is now? i.e. deleting the NotNullAttribute as well as the top-level nullable annotation.

Copy link
Member Author

Choose a reason for hiding this comment

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

Removing the ? annotation though would mean that I'd have to provide a non-null value at the call site correct? That would break the existing code.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is the scenario you are referring to. This doesn't produce a warning because we know the variable we pass using 'out' will only be written to.

public void M1(string? s1)
{
    M2(out s1); // no warning
    s1.ToString();
}

public void M2(out string s2)
{
    s2 = "a";
}

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah okay. Yeah then [NonNull] can be removed

@jaredpar jaredpar merged commit 9e78614 into dotnet:master Mar 24, 2020
@ghost ghost added this to the Next milestone Mar 24, 2020
@jaredpar jaredpar deleted the nullable-ref branch March 24, 2020 21:55
@sharwell sharwell modified the milestones: Next, temp, 16.6.P3 Apr 6, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compilers Concept-Null Annotations The issue involves annotating an API for nullable reference types
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants