提交 3ea086b8 编写于 作者: C Charles Stoner 提交者: Andy Gocke

Use NullableAnnotation.NotAnnotated for value types (#37431)

Use NullableAnnotation.NotAnnotated always for value type annotations in the public API.

Previously, the annotation was NotAnnotated if the type reference was from source and Disabled if the type reference was from metadata.

Fixes #34412
上级 8c047836
...@@ -300,8 +300,7 @@ private void SetAnalyzedNullability(BoundExpression expr, VisitResult result, bo ...@@ -300,8 +300,7 @@ private void SetAnalyzedNullability(BoundExpression expr, VisitResult result, bo
} }
} }
#endif #endif
_analyzedNullabilityMapOpt[expr] = (new NullabilityInfo(result.LValueType.NullableAnnotation.ToPublicAnnotation(), _analyzedNullabilityMapOpt[expr] = (new NullabilityInfo(result.LValueType.ToPublicAnnotation(), result.RValueType.State.ToPublicFlowState()),
result.RValueType.State.ToPublicFlowState()),
// https://github.com/dotnet/roslyn/issues/35046 We're dropping the result if the type doesn't match up completely // https://github.com/dotnet/roslyn/issues/35046 We're dropping the result if the type doesn't match up completely
// with the existing type // with the existing type
expr.Type?.Equals(result.RValueType.Type, TypeCompareKind.AllIgnoreOptions) == true ? result.RValueType.Type : expr.Type); expr.Type?.Equals(result.RValueType.Type, TypeCompareKind.AllIgnoreOptions) == true ? result.RValueType.Type : expr.Type);
......
...@@ -195,7 +195,7 @@ public static class SymbolDisplay ...@@ -195,7 +195,7 @@ public static class SymbolDisplay
bool minimal) bool minimal)
{ {
// https://github.com/dotnet/roslyn/issues/35035: Refactor this. We need to be able to handle non-TypeSymbol inputs // https://github.com/dotnet/roslyn/issues/35035: Refactor this. We need to be able to handle non-TypeSymbol inputs
var annotation = (CodeAnalysis.NullableAnnotation?)TypeWithState.Create((TypeSymbol)symbol, nullableFlowState.ToInternalFlowState()).ToTypeWithAnnotations().NullableAnnotation.ToPublicAnnotation(); var annotation = (CodeAnalysis.NullableAnnotation?)TypeWithState.Create((TypeSymbol)symbol, nullableFlowState.ToInternalFlowState()).ToTypeWithAnnotations().ToPublicAnnotation();
return ToDisplayParts(symbol, annotation, semanticModelOpt, positionOpt, format, minimal); return ToDisplayParts(symbol, annotation, semanticModelOpt, positionOpt, format, minimal);
} }
......
...@@ -477,7 +477,7 @@ ITypeSymbol IArrayTypeSymbol.ElementType ...@@ -477,7 +477,7 @@ ITypeSymbol IArrayTypeSymbol.ElementType
CodeAnalysis.NullableAnnotation IArrayTypeSymbol.ElementNullableAnnotation CodeAnalysis.NullableAnnotation IArrayTypeSymbol.ElementNullableAnnotation
{ {
get => ElementTypeWithAnnotations.NullableAnnotation.ToPublicAnnotation(); get => ElementTypeWithAnnotations.ToPublicAnnotation();
} }
ImmutableArray<CustomModifier> IArrayTypeSymbol.CustomModifiers ImmutableArray<CustomModifier> IArrayTypeSymbol.CustomModifiers
......
...@@ -351,7 +351,7 @@ ITypeSymbol IEventSymbol.Type ...@@ -351,7 +351,7 @@ ITypeSymbol IEventSymbol.Type
} }
} }
CodeAnalysis.NullableAnnotation IEventSymbol.NullableAnnotation => TypeWithAnnotations.NullableAnnotation.ToPublicAnnotation(); CodeAnalysis.NullableAnnotation IEventSymbol.NullableAnnotation => TypeWithAnnotations.ToPublicAnnotation();
IMethodSymbol IEventSymbol.AddMethod IMethodSymbol IEventSymbol.AddMethod
{ {
......
...@@ -467,7 +467,7 @@ ITypeSymbol IFieldSymbol.Type ...@@ -467,7 +467,7 @@ ITypeSymbol IFieldSymbol.Type
} }
} }
CodeAnalysis.NullableAnnotation IFieldSymbol.NullableAnnotation => TypeWithAnnotations.NullableAnnotation.ToPublicAnnotation(); CodeAnalysis.NullableAnnotation IFieldSymbol.NullableAnnotation => TypeWithAnnotations.ToPublicAnnotation();
ImmutableArray<CustomModifier> IFieldSymbol.CustomModifiers ImmutableArray<CustomModifier> IFieldSymbol.CustomModifiers
{ {
......
...@@ -372,7 +372,7 @@ ITypeSymbol ILocalSymbol.Type ...@@ -372,7 +372,7 @@ ITypeSymbol ILocalSymbol.Type
} }
} }
CodeAnalysis.NullableAnnotation ILocalSymbol.NullableAnnotation => TypeWithAnnotations.NullableAnnotation.ToPublicAnnotation(); CodeAnalysis.NullableAnnotation ILocalSymbol.NullableAnnotation => TypeWithAnnotations.ToPublicAnnotation();
bool ILocalSymbol.IsFunctionValue bool ILocalSymbol.IsFunctionValue
{ {
......
...@@ -1038,7 +1038,7 @@ ITypeSymbol IMethodSymbol.ReturnType ...@@ -1038,7 +1038,7 @@ ITypeSymbol IMethodSymbol.ReturnType
} }
} }
CodeAnalysis.NullableAnnotation IMethodSymbol.ReturnNullableAnnotation => ReturnTypeWithAnnotations.NullableAnnotation.ToPublicAnnotation(); CodeAnalysis.NullableAnnotation IMethodSymbol.ReturnNullableAnnotation => ReturnTypeWithAnnotations.ToPublicAnnotation();
ImmutableArray<ITypeSymbol> IMethodSymbol.TypeArguments ImmutableArray<ITypeSymbol> IMethodSymbol.TypeArguments
{ {
...@@ -1048,7 +1048,8 @@ ImmutableArray<ITypeSymbol> IMethodSymbol.TypeArguments ...@@ -1048,7 +1048,8 @@ ImmutableArray<ITypeSymbol> IMethodSymbol.TypeArguments
} }
} }
ImmutableArray<CodeAnalysis.NullableAnnotation> IMethodSymbol.TypeArgumentNullableAnnotations => TypeArgumentsWithAnnotations.SelectAsArray(arg => arg.NullableAnnotation.ToPublicAnnotation()); ImmutableArray<CodeAnalysis.NullableAnnotation> IMethodSymbol.TypeArgumentNullableAnnotations =>
TypeArgumentsWithAnnotations.SelectAsArray(arg => arg.ToPublicAnnotation());
ImmutableArray<ITypeParameterSymbol> IMethodSymbol.TypeParameters ImmutableArray<ITypeParameterSymbol> IMethodSymbol.TypeParameters
{ {
......
...@@ -1582,10 +1582,8 @@ ImmutableArray<ITypeSymbol> INamedTypeSymbol.TypeArguments ...@@ -1582,10 +1582,8 @@ ImmutableArray<ITypeSymbol> INamedTypeSymbol.TypeArguments
} }
} }
ImmutableArray<CodeAnalysis.NullableAnnotation> INamedTypeSymbol.TypeArgumentNullableAnnotations ImmutableArray<CodeAnalysis.NullableAnnotation> INamedTypeSymbol.TypeArgumentNullableAnnotations =>
{ this.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics.SelectAsArray(a => a.ToPublicAnnotation());
get => this.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics.SelectAsArray(a => a.NullableAnnotation.ToPublicAnnotation());
}
ImmutableArray<CustomModifier> INamedTypeSymbol.GetTypeArgumentCustomModifiers(int ordinal) ImmutableArray<CustomModifier> INamedTypeSymbol.GetTypeArgumentCustomModifiers(int ordinal)
{ {
......
...@@ -81,15 +81,21 @@ internal static NullabilityInfo ToNullabilityInfo(this CodeAnalysis.NullableAnno ...@@ -81,15 +81,21 @@ internal static NullabilityInfo ToNullabilityInfo(this CodeAnalysis.NullableAnno
internal static NullabilityInfo ToNullabilityInfo(this NullableAnnotation annotation, TypeSymbol type) internal static NullabilityInfo ToNullabilityInfo(this NullableAnnotation annotation, TypeSymbol type)
{ {
var flowState = TypeWithAnnotations.Create(type, annotation).ToTypeWithState().State; var flowState = TypeWithAnnotations.Create(type, annotation).ToTypeWithState().State;
return new NullabilityInfo(annotation.ToPublicAnnotation(), flowState.ToPublicFlowState()); return new NullabilityInfo(ToPublicAnnotation(type, annotation), flowState.ToPublicFlowState());
} }
internal static CodeAnalysis.NullableAnnotation ToPublicAnnotation(this CSharp.NullableAnnotation annotation) => internal static CodeAnalysis.NullableAnnotation ToPublicAnnotation(this TypeWithAnnotations type) =>
ToPublicAnnotation(type.Type, type.NullableAnnotation);
private static CodeAnalysis.NullableAnnotation ToPublicAnnotation(TypeSymbol type, NullableAnnotation annotation) =>
annotation switch annotation switch
{ {
CSharp.NullableAnnotation.Annotated => CodeAnalysis.NullableAnnotation.Annotated, CSharp.NullableAnnotation.Annotated => CodeAnalysis.NullableAnnotation.Annotated,
CSharp.NullableAnnotation.NotAnnotated => CodeAnalysis.NullableAnnotation.NotAnnotated, CSharp.NullableAnnotation.NotAnnotated => CodeAnalysis.NullableAnnotation.NotAnnotated,
CSharp.NullableAnnotation.Oblivious => CodeAnalysis.NullableAnnotation.Disabled, // A value type may be oblivious or not annotated depending on whether the type reference
// is from source or metadata. (Binding using the #nullable context only when setting the annotation
// to avoid checking IsValueType early.) The annotation is normalized here in the public API.
CSharp.NullableAnnotation.Oblivious => type.IsValueType ? CodeAnalysis.NullableAnnotation.NotAnnotated : CodeAnalysis.NullableAnnotation.Disabled,
_ => throw ExceptionUtilities.UnexpectedValue(annotation) _ => throw ExceptionUtilities.UnexpectedValue(annotation)
}; };
......
...@@ -412,7 +412,7 @@ ITypeSymbol IParameterSymbol.Type ...@@ -412,7 +412,7 @@ ITypeSymbol IParameterSymbol.Type
get { return this.Type; } get { return this.Type; }
} }
CodeAnalysis.NullableAnnotation IParameterSymbol.NullableAnnotation => TypeWithAnnotations.NullableAnnotation.ToPublicAnnotation(); CodeAnalysis.NullableAnnotation IParameterSymbol.NullableAnnotation => TypeWithAnnotations.ToPublicAnnotation();
ImmutableArray<CustomModifier> IParameterSymbol.CustomModifiers ImmutableArray<CustomModifier> IParameterSymbol.CustomModifiers
{ {
......
...@@ -433,7 +433,7 @@ ITypeSymbol IPropertySymbol.Type ...@@ -433,7 +433,7 @@ ITypeSymbol IPropertySymbol.Type
get { return this.Type; } get { return this.Type; }
} }
CodeAnalysis.NullableAnnotation IPropertySymbol.NullableAnnotation => TypeWithAnnotations.NullableAnnotation.ToPublicAnnotation(); CodeAnalysis.NullableAnnotation IPropertySymbol.NullableAnnotation => TypeWithAnnotations.ToPublicAnnotation();
ImmutableArray<IParameterSymbol> IPropertySymbol.Parameters ImmutableArray<IParameterSymbol> IPropertySymbol.Parameters
{ {
......
...@@ -183,7 +183,7 @@ public override TypeSymbol ReceiverType ...@@ -183,7 +183,7 @@ public override TypeSymbol ReceiverType
} }
protected override CodeAnalysis.NullableAnnotation ReceiverNullableAnnotation => protected override CodeAnalysis.NullableAnnotation ReceiverNullableAnnotation =>
_reducedFrom.Parameters[0].TypeWithAnnotations.NullableAnnotation.ToPublicAnnotation(); _reducedFrom.Parameters[0].TypeWithAnnotations.ToPublicAnnotation();
public override TypeSymbol GetTypeInferredDuringReduction(TypeParameterSymbol reducedFromTypeParameter) public override TypeSymbol GetTypeInferredDuringReduction(TypeParameterSymbol reducedFromTypeParameter)
{ {
......
...@@ -716,10 +716,8 @@ ImmutableArray<ITypeSymbol> ITypeParameterSymbol.ConstraintTypes ...@@ -716,10 +716,8 @@ ImmutableArray<ITypeSymbol> ITypeParameterSymbol.ConstraintTypes
} }
} }
ImmutableArray<CodeAnalysis.NullableAnnotation> ITypeParameterSymbol.ConstraintNullableAnnotations ImmutableArray<CodeAnalysis.NullableAnnotation> ITypeParameterSymbol.ConstraintNullableAnnotations =>
{ ConstraintTypesNoUseSiteDiagnostics.SelectAsArray(c => c.ToPublicAnnotation());
get => this.ConstraintTypesNoUseSiteDiagnostics.SelectAsArray(c => c.NullableAnnotation.ToPublicAnnotation());
}
ITypeParameterSymbol ITypeParameterSymbol.OriginalDefinition ITypeParameterSymbol ITypeParameterSymbol.OriginalDefinition
{ {
......
...@@ -43,7 +43,7 @@ internal Boxed(TypeWithAnnotations value) ...@@ -43,7 +43,7 @@ internal Boxed(TypeWithAnnotations value)
private TypeWithAnnotations(TypeSymbol defaultType, NullableAnnotation nullableAnnotation, Extensions extensions) private TypeWithAnnotations(TypeSymbol defaultType, NullableAnnotation nullableAnnotation, Extensions extensions)
{ {
Debug.Assert(defaultType?.IsNullableType() != true || (nullableAnnotation != NullableAnnotation.Oblivious && nullableAnnotation != NullableAnnotation.NotAnnotated)); Debug.Assert(defaultType?.IsNullableType() != true || nullableAnnotation == NullableAnnotation.Annotated);
Debug.Assert(extensions != null); Debug.Assert(extensions != null);
DefaultType = defaultType; DefaultType = defaultType;
...@@ -53,7 +53,7 @@ private TypeWithAnnotations(TypeSymbol defaultType, NullableAnnotation nullableA ...@@ -53,7 +53,7 @@ private TypeWithAnnotations(TypeSymbol defaultType, NullableAnnotation nullableA
public override string ToString() => Type.ToString(); public override string ToString() => Type.ToString();
internal static readonly SymbolDisplayFormat DebuggerDisplayFormat = new SymbolDisplayFormat( private static readonly SymbolDisplayFormat DebuggerDisplayFormat = new SymbolDisplayFormat(
typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces, typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters, genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters,
miscellaneousOptions: SymbolDisplayMiscellaneousOptions.UseSpecialTypes | SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier); miscellaneousOptions: SymbolDisplayMiscellaneousOptions.UseSpecialTypes | SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier);
...@@ -64,15 +64,14 @@ private TypeWithAnnotations(TypeSymbol defaultType, NullableAnnotation nullableA ...@@ -64,15 +64,14 @@ private TypeWithAnnotations(TypeSymbol defaultType, NullableAnnotation nullableA
miscellaneousOptions: SymbolDisplayMiscellaneousOptions.UseSpecialTypes | SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier, miscellaneousOptions: SymbolDisplayMiscellaneousOptions.UseSpecialTypes | SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier,
compilerInternalOptions: SymbolDisplayCompilerInternalOptions.IncludeNonNullableTypeModifier); compilerInternalOptions: SymbolDisplayCompilerInternalOptions.IncludeNonNullableTypeModifier);
internal static TypeWithAnnotations Create(bool isNullableEnabled, TypeSymbol typeSymbol, bool isAnnotated = false, ImmutableArray<CustomModifier> customModifiers = default) internal static TypeWithAnnotations Create(bool isNullableEnabled, TypeSymbol typeSymbol, bool isAnnotated = false)
{ {
if (typeSymbol is null) if (typeSymbol is null)
{ {
return default; return default;
} }
return Create(typeSymbol, nullableAnnotation: isAnnotated ? NullableAnnotation.Annotated : isNullableEnabled ? NullableAnnotation.NotAnnotated : NullableAnnotation.Oblivious, return Create(typeSymbol, nullableAnnotation: isAnnotated ? NullableAnnotation.Annotated : isNullableEnabled ? NullableAnnotation.NotAnnotated : NullableAnnotation.Oblivious);
customModifiers.NullToEmpty());
} }
internal static TypeWithAnnotations Create(TypeSymbol typeSymbol, NullableAnnotation nullableAnnotation = NullableAnnotation.Oblivious, ImmutableArray<CustomModifier> customModifiers = default) internal static TypeWithAnnotations Create(TypeSymbol typeSymbol, NullableAnnotation nullableAnnotation = NullableAnnotation.Oblivious, ImmutableArray<CustomModifier> customModifiers = default)
...@@ -580,7 +579,7 @@ public bool NeedsNullableAttribute() ...@@ -580,7 +579,7 @@ public bool NeedsNullableAttribute()
/// If the type is a non-generic value type or Nullable&lt;&gt;, and /// If the type is a non-generic value type or Nullable&lt;&gt;, and
/// is not a type parameter, the nullability is not included in the byte[]. /// is not a type parameter, the nullability is not included in the byte[].
/// </summary> /// </summary>
private static bool SkipNullableTransform(TypeSymbol type) private static bool IsNonGenericValueType(TypeSymbol type)
{ {
var namedType = type as NamedTypeSymbol; var namedType = type as NamedTypeSymbol;
if (namedType is null) if (namedType is null)
...@@ -605,7 +604,7 @@ private static void AddNullableTransforms(TypeWithAnnotations typeWithAnnotation ...@@ -605,7 +604,7 @@ private static void AddNullableTransforms(TypeWithAnnotations typeWithAnnotation
{ {
var type = typeWithAnnotations.Type; var type = typeWithAnnotations.Type;
if (!SkipNullableTransform(type)) if (!IsNonGenericValueType(type))
{ {
var annotation = typeWithAnnotations.NullableAnnotation; var annotation = typeWithAnnotations.NullableAnnotation;
byte flag; byte flag;
...@@ -642,9 +641,9 @@ public bool ApplyNullableTransforms(byte defaultTransformFlag, ImmutableArray<by ...@@ -642,9 +641,9 @@ public bool ApplyNullableTransforms(byte defaultTransformFlag, ImmutableArray<by
TypeSymbol oldTypeSymbol = Type; TypeSymbol oldTypeSymbol = Type;
byte transformFlag; byte transformFlag;
// Check SkipNullableTransform first to avoid // Check IsNonGenericValueType first to avoid
// applying transforms to simple value types. // applying transforms to simple value types.
if (SkipNullableTransform(oldTypeSymbol)) if (IsNonGenericValueType(oldTypeSymbol))
{ {
transformFlag = NullableAnnotationExtensions.ObliviousAttributeValue; transformFlag = NullableAnnotationExtensions.ObliviousAttributeValue;
} }
......
...@@ -933,6 +933,40 @@ public class C : IC< ...@@ -933,6 +933,40 @@ public class C : IC<
AssertNullableAttributes(comp, expected); AssertNullableAttributes(comp, expected);
} }
[Fact]
public void EmitAttribute_TypeParameters()
{
var source =
@"#nullable enable
public interface I<T, U, V>
where U : class
where V : struct
{
T F1();
U F2();
U? F3();
V F4();
V? F5();
#nullable disable
T F6();
U F7();
U? F8();
V F9();
V? F10();
}";
var comp = CreateCompilation(source);
var expected =
@"I<T, U, V> where U : class! where V : struct
[Nullable(2)] T
[Nullable(1)] U
[NullableContext(1)] T F1()
[NullableContext(1)] U! F2()
[NullableContext(2)] U? F3()
[NullableContext(2)] U? F8()
";
AssertNullableAttributes(comp, expected);
}
[Fact] [Fact]
public void EmitAttribute_Constraint_Nullable() public void EmitAttribute_Constraint_Nullable()
{ {
......
...@@ -319,14 +319,10 @@ internal static void VerifyTypes(this CSharpCompilation compilation, SyntaxTree ...@@ -319,14 +319,10 @@ internal static void VerifyTypes(this CSharpCompilation compilation, SyntaxTree
Assert.NotEqual(CodeAnalysis.NullableAnnotation.NotApplicable, typeInfo.Nullability.Annotation); Assert.NotEqual(CodeAnalysis.NullableAnnotation.NotApplicable, typeInfo.Nullability.Annotation);
Assert.NotEqual(CodeAnalysis.NullableFlowState.NotApplicable, typeInfo.Nullability.FlowState); Assert.NotEqual(CodeAnalysis.NullableFlowState.NotApplicable, typeInfo.Nullability.FlowState);
// https://github.com/dotnet/roslyn/issues/35035: After refactoring symboldisplay, we should be able to just call something like typeInfo.Type.ToDisplayString(typeInfo.Nullability.FlowState, TypeWithState.TestDisplayFormat) // https://github.com/dotnet/roslyn/issues/35035: After refactoring symboldisplay, we should be able to just call something like typeInfo.Type.ToDisplayString(typeInfo.Nullability.FlowState, TypeWithState.TestDisplayFormat)
if (annotation.IsConverted) var type = TypeWithState.Create(
{ (TypeSymbol)(annotation.IsConverted ? typeInfo.ConvertedType : typeInfo.Type),
return TypeWithState.Create((TypeSymbol)typeInfo.ConvertedType, typeInfo.ConvertedNullability.FlowState.ToInternalFlowState()).ToTypeWithAnnotations().ToDisplayString(TypeWithAnnotations.TestDisplayFormat); (annotation.IsConverted ? typeInfo.ConvertedNullability : typeInfo.Nullability).FlowState.ToInternalFlowState()).ToTypeWithAnnotations();
} return type.ToDisplayString(TypeWithAnnotations.TestDisplayFormat);
else
{
return TypeWithState.Create((TypeSymbol)typeInfo.Type, typeInfo.Nullability.FlowState.ToInternalFlowState()).ToTypeWithAnnotations().ToDisplayString(TypeWithAnnotations.TestDisplayFormat);
}
}); });
// Consider reporting the correct source with annotations on mismatch. // Consider reporting the correct source with annotations on mismatch.
AssertEx.Equal(expectedTypes, actualTypes, message: method.ToTestDisplayString()); AssertEx.Equal(expectedTypes, actualTypes, message: method.ToTestDisplayString());
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册