提交 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
}
}
#endif
_analyzedNullabilityMapOpt[expr] = (new NullabilityInfo(result.LValueType.NullableAnnotation.ToPublicAnnotation(),
result.RValueType.State.ToPublicFlowState()),
_analyzedNullabilityMapOpt[expr] = (new NullabilityInfo(result.LValueType.ToPublicAnnotation(), result.RValueType.State.ToPublicFlowState()),
// https://github.com/dotnet/roslyn/issues/35046 We're dropping the result if the type doesn't match up completely
// with the existing type
expr.Type?.Equals(result.RValueType.Type, TypeCompareKind.AllIgnoreOptions) == true ? result.RValueType.Type : expr.Type);
......
......@@ -195,7 +195,7 @@ public static class SymbolDisplay
bool minimal)
{
// 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);
}
......
......@@ -477,7 +477,7 @@ ITypeSymbol IArrayTypeSymbol.ElementType
CodeAnalysis.NullableAnnotation IArrayTypeSymbol.ElementNullableAnnotation
{
get => ElementTypeWithAnnotations.NullableAnnotation.ToPublicAnnotation();
get => ElementTypeWithAnnotations.ToPublicAnnotation();
}
ImmutableArray<CustomModifier> IArrayTypeSymbol.CustomModifiers
......
......@@ -351,7 +351,7 @@ ITypeSymbol IEventSymbol.Type
}
}
CodeAnalysis.NullableAnnotation IEventSymbol.NullableAnnotation => TypeWithAnnotations.NullableAnnotation.ToPublicAnnotation();
CodeAnalysis.NullableAnnotation IEventSymbol.NullableAnnotation => TypeWithAnnotations.ToPublicAnnotation();
IMethodSymbol IEventSymbol.AddMethod
{
......
......@@ -467,7 +467,7 @@ ITypeSymbol IFieldSymbol.Type
}
}
CodeAnalysis.NullableAnnotation IFieldSymbol.NullableAnnotation => TypeWithAnnotations.NullableAnnotation.ToPublicAnnotation();
CodeAnalysis.NullableAnnotation IFieldSymbol.NullableAnnotation => TypeWithAnnotations.ToPublicAnnotation();
ImmutableArray<CustomModifier> IFieldSymbol.CustomModifiers
{
......
......@@ -372,7 +372,7 @@ ITypeSymbol ILocalSymbol.Type
}
}
CodeAnalysis.NullableAnnotation ILocalSymbol.NullableAnnotation => TypeWithAnnotations.NullableAnnotation.ToPublicAnnotation();
CodeAnalysis.NullableAnnotation ILocalSymbol.NullableAnnotation => TypeWithAnnotations.ToPublicAnnotation();
bool ILocalSymbol.IsFunctionValue
{
......
......@@ -1038,7 +1038,7 @@ ITypeSymbol IMethodSymbol.ReturnType
}
}
CodeAnalysis.NullableAnnotation IMethodSymbol.ReturnNullableAnnotation => ReturnTypeWithAnnotations.NullableAnnotation.ToPublicAnnotation();
CodeAnalysis.NullableAnnotation IMethodSymbol.ReturnNullableAnnotation => ReturnTypeWithAnnotations.ToPublicAnnotation();
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
{
......
......@@ -1582,10 +1582,8 @@ ImmutableArray<ITypeSymbol> INamedTypeSymbol.TypeArguments
}
}
ImmutableArray<CodeAnalysis.NullableAnnotation> INamedTypeSymbol.TypeArgumentNullableAnnotations
{
get => this.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics.SelectAsArray(a => a.NullableAnnotation.ToPublicAnnotation());
}
ImmutableArray<CodeAnalysis.NullableAnnotation> INamedTypeSymbol.TypeArgumentNullableAnnotations =>
this.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics.SelectAsArray(a => a.ToPublicAnnotation());
ImmutableArray<CustomModifier> INamedTypeSymbol.GetTypeArgumentCustomModifiers(int ordinal)
{
......
......@@ -81,15 +81,21 @@ internal static NullabilityInfo ToNullabilityInfo(this CodeAnalysis.NullableAnno
internal static NullabilityInfo ToNullabilityInfo(this NullableAnnotation annotation, TypeSymbol type)
{
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
{
CSharp.NullableAnnotation.Annotated => CodeAnalysis.NullableAnnotation.Annotated,
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)
};
......
......@@ -412,7 +412,7 @@ ITypeSymbol IParameterSymbol.Type
get { return this.Type; }
}
CodeAnalysis.NullableAnnotation IParameterSymbol.NullableAnnotation => TypeWithAnnotations.NullableAnnotation.ToPublicAnnotation();
CodeAnalysis.NullableAnnotation IParameterSymbol.NullableAnnotation => TypeWithAnnotations.ToPublicAnnotation();
ImmutableArray<CustomModifier> IParameterSymbol.CustomModifiers
{
......
......@@ -433,7 +433,7 @@ ITypeSymbol IPropertySymbol.Type
get { return this.Type; }
}
CodeAnalysis.NullableAnnotation IPropertySymbol.NullableAnnotation => TypeWithAnnotations.NullableAnnotation.ToPublicAnnotation();
CodeAnalysis.NullableAnnotation IPropertySymbol.NullableAnnotation => TypeWithAnnotations.ToPublicAnnotation();
ImmutableArray<IParameterSymbol> IPropertySymbol.Parameters
{
......
......@@ -183,7 +183,7 @@ public override TypeSymbol ReceiverType
}
protected override CodeAnalysis.NullableAnnotation ReceiverNullableAnnotation =>
_reducedFrom.Parameters[0].TypeWithAnnotations.NullableAnnotation.ToPublicAnnotation();
_reducedFrom.Parameters[0].TypeWithAnnotations.ToPublicAnnotation();
public override TypeSymbol GetTypeInferredDuringReduction(TypeParameterSymbol reducedFromTypeParameter)
{
......
......@@ -716,10 +716,8 @@ ImmutableArray<ITypeSymbol> ITypeParameterSymbol.ConstraintTypes
}
}
ImmutableArray<CodeAnalysis.NullableAnnotation> ITypeParameterSymbol.ConstraintNullableAnnotations
{
get => this.ConstraintTypesNoUseSiteDiagnostics.SelectAsArray(c => c.NullableAnnotation.ToPublicAnnotation());
}
ImmutableArray<CodeAnalysis.NullableAnnotation> ITypeParameterSymbol.ConstraintNullableAnnotations =>
ConstraintTypesNoUseSiteDiagnostics.SelectAsArray(c => c.ToPublicAnnotation());
ITypeParameterSymbol ITypeParameterSymbol.OriginalDefinition
{
......
......@@ -43,7 +43,7 @@ internal Boxed(TypeWithAnnotations value)
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);
DefaultType = defaultType;
......@@ -53,7 +53,7 @@ private TypeWithAnnotations(TypeSymbol defaultType, NullableAnnotation nullableA
public override string ToString() => Type.ToString();
internal static readonly SymbolDisplayFormat DebuggerDisplayFormat = new SymbolDisplayFormat(
private static readonly SymbolDisplayFormat DebuggerDisplayFormat = new SymbolDisplayFormat(
typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters,
miscellaneousOptions: SymbolDisplayMiscellaneousOptions.UseSpecialTypes | SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier);
......@@ -64,15 +64,14 @@ private TypeWithAnnotations(TypeSymbol defaultType, NullableAnnotation nullableA
miscellaneousOptions: SymbolDisplayMiscellaneousOptions.UseSpecialTypes | SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier,
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)
{
return default;
}
return Create(typeSymbol, nullableAnnotation: isAnnotated ? NullableAnnotation.Annotated : isNullableEnabled ? NullableAnnotation.NotAnnotated : NullableAnnotation.Oblivious,
customModifiers.NullToEmpty());
return Create(typeSymbol, nullableAnnotation: isAnnotated ? NullableAnnotation.Annotated : isNullableEnabled ? NullableAnnotation.NotAnnotated : NullableAnnotation.Oblivious);
}
internal static TypeWithAnnotations Create(TypeSymbol typeSymbol, NullableAnnotation nullableAnnotation = NullableAnnotation.Oblivious, ImmutableArray<CustomModifier> customModifiers = default)
......@@ -580,7 +579,7 @@ public bool NeedsNullableAttribute()
/// 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[].
/// </summary>
private static bool SkipNullableTransform(TypeSymbol type)
private static bool IsNonGenericValueType(TypeSymbol type)
{
var namedType = type as NamedTypeSymbol;
if (namedType is null)
......@@ -605,7 +604,7 @@ private static void AddNullableTransforms(TypeWithAnnotations typeWithAnnotation
{
var type = typeWithAnnotations.Type;
if (!SkipNullableTransform(type))
if (!IsNonGenericValueType(type))
{
var annotation = typeWithAnnotations.NullableAnnotation;
byte flag;
......@@ -642,9 +641,9 @@ public bool ApplyNullableTransforms(byte defaultTransformFlag, ImmutableArray<by
TypeSymbol oldTypeSymbol = Type;
byte transformFlag;
// Check SkipNullableTransform first to avoid
// Check IsNonGenericValueType first to avoid
// applying transforms to simple value types.
if (SkipNullableTransform(oldTypeSymbol))
if (IsNonGenericValueType(oldTypeSymbol))
{
transformFlag = NullableAnnotationExtensions.ObliviousAttributeValue;
}
......
......@@ -933,6 +933,40 @@ public class C : IC<
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]
public void EmitAttribute_Constraint_Nullable()
{
......
......@@ -319,14 +319,10 @@ internal static void VerifyTypes(this CSharpCompilation compilation, SyntaxTree
Assert.NotEqual(CodeAnalysis.NullableAnnotation.NotApplicable, typeInfo.Nullability.Annotation);
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)
if (annotation.IsConverted)
{
return TypeWithState.Create((TypeSymbol)typeInfo.ConvertedType, typeInfo.ConvertedNullability.FlowState.ToInternalFlowState()).ToTypeWithAnnotations().ToDisplayString(TypeWithAnnotations.TestDisplayFormat);
}
else
{
return TypeWithState.Create((TypeSymbol)typeInfo.Type, typeInfo.Nullability.FlowState.ToInternalFlowState()).ToTypeWithAnnotations().ToDisplayString(TypeWithAnnotations.TestDisplayFormat);
}
var type = TypeWithState.Create(
(TypeSymbol)(annotation.IsConverted ? typeInfo.ConvertedType : typeInfo.Type),
(annotation.IsConverted ? typeInfo.ConvertedNullability : typeInfo.Nullability).FlowState.ToInternalFlowState()).ToTypeWithAnnotations();
return type.ToDisplayString(TypeWithAnnotations.TestDisplayFormat);
});
// Consider reporting the correct source with annotations on mismatch.
AssertEx.Equal(expectedTypes, actualTypes, message: method.ToTestDisplayString());
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册