-
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
Remove NonNullTypes context and other unnecessary information stored in TypeSymbolWithAnnotations. #30913
Remove NonNullTypes context and other unnecessary information stored in TypeSymbolWithAnnotations. #30913
Conversation
…in TypeSymbolWithAnnotations. Fixes dotnet#30845.
Test windows_release_unit64_prtest please |
NotNullable, // For string, int, T | ||
Nullable, // For string?, T? where T : class; and for int?, T? where T : struct. | ||
NotNullableBasedOnAnalysis, // Explicitly set by flow analysis | ||
NullableBasedOnAnalysis, // Explicitly set by flow analysis |
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.
Could the Analysis
part be a separate bit?
[Flags]
enum NullableAnnotation
{
Unknown = 0,
NotNullable = 1,
Nullable = 2,
FromAnalysis = 4,
}
Or a separate bool
field on TypeSymbolWithAnnotations
?
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.
Could the Analysis part be a separate bit?
I thought about that, but for now decided against using flags to avoid the need to deal with "not meaningful"/impossible combinations. Also, I am hoping to get rid of NullableBasedOnAnalysis in the next change, making all values fit in two bits.
Or a separate bool field on TypeSymbolWithAnnotations?
I find it more convenient to deal with single value than with a pair of values. Going forward we should be able to get rid of Create methods that don't take NullableAnnotation.
In reply to: 230184941 [](ancestors = 230184941)
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.
I find it more convenient to deal with single value than with a pair of values.
Which callers are treating the pair as one value?
In reply to: 230193197 [](ancestors = 230193197,230184941)
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.
Which callers are treating the pair as one value?
I think every caller as it stands right now, the TypeSymbolWithAnnotations itself treats it as one value when merging transitioning between annotations. With pair of values it is not clear what combinations the code should be prepared to deal with.
In reply to: 230195433 [](ancestors = 230195433,230193197,230184941)
Nullable, // For string?, T? where T : class; and for int?, T? where T : struct. | ||
NotNullableBasedOnAnalysis, // Explicitly set by flow analysis | ||
NullableBasedOnAnalysis, // Explicitly set by flow analysis | ||
} |
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.
If the additional field (NotNullableBasedOnAnalysis
) is for marking unconstrained type parameter references that are not nullable, perhaps the Nullable
and NotNullable
values should be independent bits, with the nullability of unconstrained type parameter references initially set to Nullable | NotNullable
? Then flow analysis might infer the reference is NotNullable
only.
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.
With this structure, we should be able to accurately reflect what modifiers are in source code. Therefore, always pretending that there is a modifier when there isn't one in source, or always pretending that something is nullable when it isn't marked as nullable in source has a negative impact on checks we do on declarations. Checks on declarations should be performed specifically based on presence, or lack of '?' question mark in source code. Then, flow analysis can take that information coming from declarations and interpret it as it is appropriate for the purpose of flow analysis, however the structure itself shouldn't do this interpretation as it used to do before this change.
In reply to: 230214729 [](ancestors = 230214729)
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.
At some point I was thinking naming NotNullable as None (or something similar) to reflect exactly the fact that simply there was no annotation on the declaration, and then it is up to flow analysis to figure out what that means for a specific type.
In reply to: 230218492 [](ancestors = 230218492,230214729)
@@ -10,7 +10,7 @@ namespace Microsoft.CodeAnalysis | |||
[Flags] | |||
internal enum TypeCompareKind | |||
{ | |||
ConsiderEverything = 0, // Perhaps rename since this does not consider nullable modifiers. | |||
ConsiderEverything = 0, |
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.
ConsiderEverything [](start = 8, length = 18)
Consider leaving a comment or xml doc to indicate this option does not compare nullability. #Closed
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.
Consider leaving a comment or xml doc to indicate this option does not compare nullability.
But it does, the comment was obsolete.
In reply to: 230518210 [](ancestors = 230518210)
return true; | ||
|
||
case NullableAnnotation.NotNullableBasedOnAnalysis: | ||
return false; |
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.
return false; [](start = 24, length = 13)
nit: consider collapsing the two "not nullable" cases, as you did for the two "nullable" cases.
We could probably also assert in "not nullable" cases, as you did for the "unknown" case (Debug.Assert(!TypeSymbol.IsNullableType());
). #Closed
result.AsNotNullableReferenceType(); | ||
if (isAnnotated) | ||
{ | ||
result = result.AsNullableReferenceType(fromDeclaration: 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.
fromDeclaration: true [](start = 56, length = 21)
This is "from declaration" because we only use this method when loading from PE, correct?
If so, it may be good to comment.
Update: if you think "from declaration" will disappear in next iteration, then don't bother with comment. #Closed
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.
This is "from declaration" because we only use this method when loading from PE, correct?
No this is not correct. It is also used to manipulate symbols while binding declarations. It is never used by flow analysis. BTW, we are going to get rid of nonNullTypesContext
and change the ImmutableArray<bool> transforms
to be an array of NullableAnnotation. So we will not need to guess or assume what value to use.
In reply to: 230523652 [](ancestors = 230523652)
{ | ||
return CreateNonLazyType(type._defaultType, type.NonNullTypesContext, isAnnotated: true, | ||
type._treatPossiblyNullableReferenceTypeTypeParameterAsNullable, _customModifiers); | ||
return CreateNonLazyType(type._defaultType, fromDeclaration ? NullableAnnotation.Nullable : NullableAnnotation.NullableBasedOnAnalysis, _customModifiers); | ||
} | ||
|
||
internal override TypeSymbolWithAnnotations AsNotNullableReferenceType(TypeSymbolWithAnnotations type) |
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.
AsNotNullableReferenceType [](start = 56, length = 26)
Should we have a "from declaration" flag here too? It looks like AsNotNullableReferenceType
is used in method type inference, which is run during both binding and flow analysis. #Closed
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.
Should we have a "from declaration" flag here too? It looks like AsNotNullableReferenceType is used in method type inference, which is run during both binding and flow analysis.
At the moment there is no client that would use it. We'll add on as needed basis.
In reply to: 230525559 [](ancestors = 230525559)
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.
The client would be method type inference. Since it can be run during flow analysis, it feels like it should be passing a fromDeclaration: false
in that scenario.
In reply to: 230951976 [](ancestors = 230951976,230525559)
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.
The client would be method type inference. Since it can be run during flow analysis, it feels like it should be passing a fromDeclaration: false in that scenario.
Feel free to come up with a scenario that would indicate the need, so far we don't have any tests indicating that.
In reply to: 230958183 [](ancestors = 230958183,230951976,230525559)
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.
It seems that the distinction between NotNullable
and NotNullableBasedOnAnalysis
currently does nothing. So if we're incorrectly producing one rather than the other, there would be no way to observe that.
This makes me think one of those two flags should be removed. Then the question of whether we're producing the correct flag here becomes mute ;-)
In reply to: 230958960 [](ancestors = 230958960,230958183,230951976,230525559)
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.
This makes me think one of those two flags should be removed. Then the question of whether we're producing the correct flag here becomes mute ;-)
At the moment, NotNullableBasedOnAnalysis
affects behavior of SetPossiblyNullableReferenceTypeTypeParametersAsNullable in the way that we don't overwrite types that flow from earlier analysis. More real usage is coming in the next commit.
In reply to: 230959880 [](ancestors = 230959880,230958960,230958183,230951976,230525559)
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.
I'm sorry, I didn't follow. I looked at all the references to NotNullableBasedOnAnalysis
in this PR, and none of them behaves differently when encountering a NotNullableBasedOnAnalysis
or a NotNullable
.
In reply to: 230961770 [](ancestors = 230961770,230959880,230958960,230958183,230951976,230525559)
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.
I looked at all the references to NotNullableBasedOnAnalysis in this PR, and none of them behaves differently when encountering a NotNullableBasedOnAnalysis or a NotNullable.
The following method behaves differently:
internal bool IsPossiblyNullableReferenceTypeTypeParameter()
{
return NullableAnnotation == NullableAnnotation.NotNullable && TypeSymbol.IsPossiblyNullableReferenceTypeTypeParameter();
}
In reply to: 230962617 [](ancestors = 230962617,230961770,230959880,230958960,230958183,230951976,230525559)
@@ -181,7 +181,7 @@ internal static InferredLambdaReturnType InferReturnType(ArrayBuilder<(RefKind, | |||
// to the caller, and up through MethodTypeInferrer.Infer. | |||
bestResultType = hadNullabilityMismatch ? | |||
default : | |||
TypeSymbolWithAnnotations.Create(bestType, isNullableIfReferenceType: BestTypeInferrer.GetIsNullable(resultTypes)); | |||
TypeSymbolWithAnnotations.Create(bestType, isNullableIfReferenceType: BestTypeInferrer.GetIsNullable(resultTypes), fromDeclaration: 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.
fromDeclaration: true [](start = 139, length = 21)
The calculation of lambda return type is re-done during flow analysis, so it feels like we shouldn't always use "fromDeclaration: true".
public TypeSymbolWithAnnotations GetInferredReturnType(ConversionsBase conversions, NullableWalker.VariableState nullableState, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
...
if (nullableState == null)
{
return InferredReturnType.Type;
}
else
{
...
NullableWalker.Analyze(compilation, lambda: this, diagnostics, delegateInvokeMethod: delegateType?.DelegateInvokeMethod, returnTypes: returnTypes, initialState: nullableState);
var inferredReturnType = InferReturnType(returnTypes, compilation, conversions, delegateType, Symbol.IsAsync);
...
}
}
``` #Closed
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.
The calculation of lambda return type is re-done during flow analysis, so it feels like we shouldn't always use "fromDeclaration: true".
Some of the changes are simply preserving existing behavior, often relying on existing tests to verify that. The current plan is to remove all APIs that use "bool?" to create TypeSymbolWithAnnotations. Annotations from flow analysis will naturally flow through here after the change.
In reply to: 230530045 [](ancestors = 230530045)
} | ||
public bool Equals(VariableIdentifier other) | ||
{ | ||
return ((object)Symbol == null ? (object)other.Symbol == null : Symbol.Equals(other.Symbol)) && ContainingSlot == other.ContainingSlot; | ||
return ((object)Symbol == null ? (object)other.Symbol == null : Symbol.OriginalDefinition.Equals(other.Symbol.OriginalDefinition)) && ContainingSlot == other.ContainingSlot; |
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.
Symbol.OriginalDefinition.Equals(other.Symbol.OriginalDefinition)) [](start = 80, length = 66)
I didn't understand this part of the change. What was the impact? #Closed
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.
I didn't understand this part of the change. What was the impact?
The impact is that slight change in nested nullability of containing type (caused by SetPossiblyNullableReferenceTypeTypeParametersAsNullable, for example) won't have negative effect on allocating/finding slots. Container is already uniquely and accurately identified by ContainingSlot
, so we can safely rely on definition to match members
In reply to: 230530406 [](ancestors = 230530406)
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.
returnType; | ||
if (method.IsGenericTaskReturningAsync(compilation)) | ||
{ | ||
returnType = ((NamedTypeSymbol)returnType.TypeSymbol).TypeArgumentsNoUseSiteDiagnostics.Single().SetPossiblyNullableReferenceTypeTypeParametersAsNullable(); |
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.
SetPossiblyNullableReferenceTypeTypeParametersAsNullable [](start = 113, length = 56)
I'm not sure if we need this second call. returnType
should already have been "cleansed", including its type arguments. #Closed
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.
I'm not sure if we need this second call. returnType should already have been "cleansed", including its type arguments.
That is correct. I am planning to get rid of all the SetPossiblyNullableReferenceTypeTypeParametersAsNullable cleansing everywhere in my next commit regardless.
In reply to: 230531004 [](ancestors = 230531004)
The comment is out-of-date. Refers to: src/Compilers/CSharp/Portable/Symbols/TypeSymbolWithAnnotations.cs:314 in a2ffdaa. [](commit_id = a2ffdaa, deletion_comment = False) |
@@ -24461,7 +24501,7 @@ static void F<T>() | |||
var declarators = tree.GetRoot().DescendantNodes().OfType<VariableDeclaratorSyntax>().ToArray(); | |||
var symbol = (LocalSymbol)model.GetDeclaredSymbol(declarators[0]); | |||
Assert.Equal("T", symbol.Type.ToTestDisplayString(true)); | |||
Assert.Equal(true, symbol.Type.IsNullable); | |||
Assert.False(symbol.Type.IsNullable); |
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.
Assert.False(symbol.Type.IsNullable); [](start = 12, length = 37)
Is this the behavior we expect for public API as well, when asking about unconstrained type parameter?
It feels like the public and internal APIs should probably align for this question. #Closed
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 this the behavior we expect for public API as well, when asking about unconstrained type parameter?
It feels like the public and internal APIs should probably align for this question.
We are still figuring out whet the shape of public API should be.
I believe this internal API is misleading and I am planning to get rid of it internally.
In reply to: 230538988 [](ancestors = 230538988)
@@ -16,21 +16,22 @@ internal static class NullableTypeDecoder | |||
internal static TypeSymbolWithAnnotations TransformType( | |||
TypeSymbolWithAnnotations metadataType, | |||
EntityHandle targetSymbolToken, | |||
PEModuleSymbol containingModule) | |||
PEModuleSymbol containingModule, | |||
INonNullTypesContext nonNullTypesContext) |
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.
INonNullTypesContext nonNullTypesContext) [](start = 12, length = 41)
This seems a significant change/fix, but I didn't see test changes corresponding to it. Do we have adequate coverage? #Closed
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.
This seems a significant change/fix, but I didn't see test changes corresponding to it. Do we have adequate coverage?
Why do you see this as a significant change? Context, which was "inferred" from TypeSymbolWithAnnotations before is now passed explicitly. The final goal is to get rid of INonNullTypesContext completely, but we have to do it in steps to keep changes to a reasonable size.
In reply to: 230539140 [](ancestors = 230539140)
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.
Thanks for the clarification. Makes sense
In reply to: 230957799 [](ancestors = 230957799,230539140)
@@ -100,7 +100,7 @@ internal override ImmutableArray<TypeSymbolWithAnnotations> GetConstraintTypes(C | |||
{ | |||
var constraintTypes = ArrayBuilder<TypeSymbolWithAnnotations>.GetInstance(); | |||
_map.SubstituteTypesDistinctWithoutModifiers(_underlyingTypeParameter.GetConstraintTypes(inProgress, early), constraintTypes, null); | |||
return constraintTypes.ToImmutableAndFree().WhereAsArray(type => type.SpecialType != SpecialType.System_Object || !type.IsAnnotated); | |||
return constraintTypes.ToImmutableAndFree().WhereAsArray(type => type.SpecialType != SpecialType.System_Object || !type.NullableAnnotation.IsAnyNullable()); |
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.
type.SpecialType != SpecialType.System_Object || !type.NullableAnnotation.IsAnyNullable() [](start = 77, length = 89)
Would it make sense to extract this logic out to a helper function (maybe type => !type.IsNullableObject()
)? It also appears in PETypeParameterSymbol.GetDeclaredConstraintTypes
as part of this PR. #Closed
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.
Would it make sense to extract this logic out to a helper function (maybe type => !type.IsNullableObject())? It also appears in PETypeParameterSymbol.GetDeclaredConstraintTypes as part of this PR.
I personally do not see much value doing this at this point.
In reply to: 230539531 [](ancestors = 230539531)
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.
Done with review pass (iteration 1)
My plan is to get rid of this property completely. Whether a type should be considered nullable or not depends on the context. This type should be data only, no analysis. In reply to: 435545223 [](ancestors = 435545223) Refers to: src/Compilers/CSharp/Portable/Symbols/TypeSymbolWithAnnotations.cs:314 in a2ffdaa. [](commit_id = a2ffdaa, deletion_comment = False) |
I do not think so. The SetPossiblyNullableReferenceTypeTypeParametersAsNullable helper is a temporary solution to simply have existing tests passing. My next commit eliminates it everywhere. In reply to: 435547738 [](ancestors = 435547738) Refers to: src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs:115 in a2ffdaa. [](commit_id = a2ffdaa, deletion_comment = False) |
Looking at this more, I think we're ok because there is no way to use a lambda directly. In reply to: 436082310 [](ancestors = 436082310,435547738) Refers to: src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs:115 in a2ffdaa. [](commit_id = a2ffdaa, deletion_comment = False) |
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.
First iteration looks good to me. I'll wait for second commit to sign-off. Thanks
return NullableAnnotation == NullableAnnotation.NotNullable && TypeSymbol.IsPossiblyNullableReferenceTypeTypeParameter(); | ||
} | ||
|
||
internal NullableAnnotation GetValueNullableAnnotation() |
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.
GetValueNullableAnnotation [](start = 36, length = 26)
nit: I found this method name confusing. What does "Value" refer to?
Perhaps GetNullableAnnotationForAnalysis
would be clearer? #Closed
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.
I found this method name confusing. What does "Value" refer to?
It refers to the fact that we are talking about nullability of a value of this type. There is a distinction between a value and a target of an assignment. Both are involved into analysis, but handled differently even if they have the same type.
In reply to: 231236701 [](ancestors = 231236701)
Would it make sense to xml comment this method (and overload) to point out that it cares about insignificant nullability differences? I also wonder if we'll need the new comparison option in the long-term. As you pointed out, refactoring Refers to: src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs:4433 in f20e071. [](commit_id = f20e071, deletion_comment = False) |
I don't think it is necessary, they do what the flow analysis needs to do.
Refactoring ReportAssignmentWarnings would only help us with top level nullability, but we need to handle it as deep as it can go. So, I don't think this is a short term option. In reply to: 437169147 [](ancestors = 437169147) Refers to: src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs:4433 in f20e071. [](commit_id = f20e071, deletion_comment = False) |
|
||
internal static class NullableAnnotationExtensions | ||
{ | ||
public static bool IsAnyNullable(this NullableAnnotation annotation) |
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.
IsAny [](start = 27, length = 5)
I trip over IsAny
when I see these methods called since Any
is usually used for a collection. Consider naming these methods IsNullable()
and IsNotNullable()
. #Resolved
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.
I trip over IsAny when I see these methods called since Any is usually used for a collection. Consider naming these methods IsNullable() and IsNotNullable().
This is exactly the effect I want, I want people to think and understand what question these methods are answering. I think that the proposed names are going to be misleading, they would almost match specific enum values.
In reply to: 232112037 [](ancestors = 232112037)
_resultType = TypeSymbolWithAnnotations.Create(resultType, resultIsNullable); | ||
NullableAnnotation resultNullableAnnotation; | ||
|
||
if (getValueNullableAnnotation(leftOperand, leftResult).IsAnyNotNullable()) |
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.
getValueNullableAnnotation(leftOperand, leftResult) [](start = 16, length = 51)
I don't understand why we use getValueNulalbleAnnotation(left)
for the if
but then set the result type to getNullableAnnotation(left)
. Please consider adding a comment for which cases that distinction is important. #Resolved
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.
I don't understand why we use getValueNulalbleAnnotation(left) for the if but then set the result type to getNullableAnnotation(left). Please consider adding a comment for which cases that distinction is important.
We want to check if the value can be nullable based on annotations and getValueNullableAnnotation might adjust value that it returns to emphasize the fact. However, we want the original annotation to flow through the system. I will add a comment.
In reply to: 232115987 [](ancestors = 232115987)
// This code path is likely not reachable due to https://github.com/dotnet/roslyn/issues/30946. | ||
// See unit test NullabilityOfTypeParameters_080 for an attempt to get here. | ||
adjustedResultType = TypeSymbolWithAnnotations.Create(adjustedResultType.TypeSymbol, NullableAnnotation.NullableBasedOnAnalysis); | ||
} |
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.
This code snippet is used three times in this method. Consider extracting a local function. #Pending
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.
This code snippet is used three times in this method. Consider extracting a local function.
Will do
In reply to: 232116712 [](ancestors = 232116712)
(b == NullableAnnotation.NotNullable && a == NullableAnnotation.NotNullableBasedOnAnalysis)); | ||
return NullableAnnotation.NotNullable; // It is reasonable to settle on this value because the difference in annotations is either | ||
// not significant for the type, or candidate corresponding to this value is possibly a | ||
// nullable reference type type parameter and nullable should win. |
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.
nullable [](start = 62, length = 8)
not nullable? #Resolved
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.
not nullable?
No, candidate with NullableAnnotation.NotNullable could be a reference type parameter that can be substituted with a nullable reference type
In reply to: 232118018 [](ancestors = 232118018)
{ | ||
Debug.Assert(thisAnnotation.IsAnyNotNullable()); | ||
Debug.Assert(otherAnnotation.IsAnyNotNullable()); | ||
if (TypeSymbol.IsPossiblyNullableReferenceTypeTypeParameter()) |
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.
if (TypeSymbol.IsPossiblyNullableReferenceTypeTypeParameter()) [](start = 24, length = 62)
What if other.TypeSymbol.IsPossiblyNullableReferenceTypeTypeParameter()
instead? Do we return false
in that case? #Resolved
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.
What if other.TypeSymbol.IsPossiblyNullableReferenceTypeTypeParameter() instead? Do we return false in that case?
If we reach here types are the same, they are compared at the beginning of this function.
In reply to: 232119017 [](ancestors = 232119017)
@@ -836,7 +836,7 @@ private void CheckNewModifier(Symbol symbol, bool isNew, DiagnosticBag diagnosti | |||
{ | |||
var overridenParameterType = overriddenParameters[i].Type; | |||
if (!overridingParameters[i].Type.Equals(overridenParameterType, | |||
TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.IgnoreNullableModifiersForReferenceTypes) && | |||
TypeCompareKind.AllIgnoreOptions & ~(TypeCompareKind.IgnoreNullableModifiersForReferenceTypes | TypeCompareKind.IgnoreInsignificantNullableModifiersDifference)) && |
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.
TypeCompareKind.AllIgnoreOptions & ~(TypeCompareKind.IgnoreNullableModifiersForReferenceTypes | TypeCompareKind.IgnoreInsignificantNullableModifiersDifference) [](start = 73, length = 159)
Consider adding a TypeCompareKind.AllNonNullableIgnoreOptions
. #WontFix
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.
Consider adding a TypeCompareKind.AllNonNullableIgnoreOptions.
This and other similar places are still using UnknownNullableModifierMatchesAny, which is one of the nullable ignore options.
In reply to: 232119400 [](ancestors = 232119400)
4b7908f
to
77a0527
Compare
@jaredpar for approval for preview2. Thanks |
approved |
…out-if-error-message * origin/master: (174 commits) Add Compilers filter for Roslyn (dotnet#30880) Remove NonNullTypes context and other unnecessary information stored in TypeSymbolWithAnnotations. (dotnet#30913) Update BoundCall method based on receiver nullability (dotnet#31000) Make nullabiulity inference associative and commutative (dotnet#30990) Async-streams: minimal test for IOperation and CFG. Improve diagnostics (dotnet#30363) Add src. Add test. Remove dead code Update the build status table Script for generating our build status tables Add parsing tests to compiler benchmarks (dotnet#31033) Fix Edit and Continue in CPS projects Add comment Sorting. Save work Address PR feedback only produce optprof data on an official build Add bunch of exclusions to dead code analysis for special methods Disable WinRT tests on Linux (dotnet#31026) Change prerelease version to beta2 (dotnet#31017) ... # Conflicts: # src/Compilers/CSharp/Portable/CSharpResources.resx # src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
Fixes #30845.