未验证 提交 32c9dc06 编写于 作者: C Chris Sienkiewicz 提交者: GitHub

Report nullability for attribute arguments: (#33816)

* Report nullability for attribute arguments:
- Add an entry point to nullable walker for attribute analysis
- Implement analyze attribute in the walker
- Update MethodThisParameter to not throw
- Add extra fields to BoundAttribute that are needed for nullable analysis
- Add tests



* PR Feedback:
- Analyse attributes even when we don't bind a constructor

- Add tests for when we don't bind constructor but still want to analyze what we have

* PR Feedback:
- fix typos
- make no matching constructors use implicit constructors

* Replace tabs with spaces

* Fix failing test
...@@ -147,21 +147,33 @@ private BoundAttribute BindAttributeCore(AttributeSyntax node, NamedTypeSymbol a ...@@ -147,21 +147,33 @@ private BoundAttribute BindAttributeCore(AttributeSyntax node, NamedTypeSymbol a
AnalyzedAttributeArguments analyzedArguments = attributeArgumentBinder.BindAttributeArguments(argumentListOpt, attributeTypeForBinding, diagnostics); AnalyzedAttributeArguments analyzedArguments = attributeArgumentBinder.BindAttributeArguments(argumentListOpt, attributeTypeForBinding, diagnostics);
HashSet<DiagnosticInfo> useSiteDiagnostics = null; HashSet<DiagnosticInfo> useSiteDiagnostics = null;
ImmutableArray<int> argsToParamsOpt = default;
bool expanded = false;
MethodSymbol attributeConstructor = null;
// Bind attributeType's constructor based on the bound constructor arguments // Bind attributeType's constructor based on the bound constructor arguments
MethodSymbol attributeConstructor = attributeTypeForBinding.IsErrorType() ? if (!attributeTypeForBinding.IsErrorType())
null : {
BindAttributeConstructor(node, attributeTypeForBinding, analyzedArguments.ConstructorArguments, diagnostics, ref resultKind, suppressErrors: attributeType.IsErrorType(), useSiteDiagnostics: ref useSiteDiagnostics); attributeConstructor = BindAttributeConstructor(node,
attributeTypeForBinding,
analyzedArguments.ConstructorArguments,
diagnostics,
ref resultKind,
suppressErrors: attributeType.IsErrorType(),
ref argsToParamsOpt,
ref expanded,
ref useSiteDiagnostics);
}
diagnostics.Add(node, useSiteDiagnostics); diagnostics.Add(node, useSiteDiagnostics);
if ((object)attributeConstructor != null) if (!(attributeConstructor is null))
{ {
ReportDiagnosticsIfObsolete(diagnostics, attributeConstructor, node, hasBaseReceiver: false); ReportDiagnosticsIfObsolete(diagnostics, attributeConstructor, node, hasBaseReceiver: false);
}
if (attributeConstructor?.Parameters.Any(p => p.RefKind == RefKind.In) == true) if (attributeConstructor.Parameters.Any(p => p.RefKind == RefKind.In))
{ {
Error(diagnostics, ErrorCode.ERR_AttributeCtorInParameter, node, attributeConstructor.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat)); Error(diagnostics, ErrorCode.ERR_AttributeCtorInParameter, node, attributeConstructor.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat));
}
} }
var constructorArguments = analyzedArguments.ConstructorArguments; var constructorArguments = analyzedArguments.ConstructorArguments;
...@@ -170,10 +182,9 @@ private BoundAttribute BindAttributeCore(AttributeSyntax node, NamedTypeSymbol a ...@@ -170,10 +182,9 @@ private BoundAttribute BindAttributeCore(AttributeSyntax node, NamedTypeSymbol a
ImmutableArray<BoundExpression> boundNamedArguments = analyzedArguments.NamedArguments; ImmutableArray<BoundExpression> boundNamedArguments = analyzedArguments.NamedArguments;
constructorArguments.Free(); constructorArguments.Free();
return new BoundAttribute(node, attributeConstructor, boundConstructorArguments, boundConstructorArgumentNamesOpt, return new BoundAttribute(node, attributeConstructor, boundConstructorArguments, boundConstructorArgumentNamesOpt, argsToParamsOpt, expanded,
boundNamedArguments, resultKind, attributeType, hasErrors: resultKind != LookupResultKind.Viable); boundNamedArguments, resultKind, attributeType, hasErrors: resultKind != LookupResultKind.Viable);
} }
private CSharpAttributeData GetAttribute(BoundAttribute boundAttribute, DiagnosticBag diagnostics) private CSharpAttributeData GetAttribute(BoundAttribute boundAttribute, DiagnosticBag diagnostics)
{ {
var attributeType = (NamedTypeSymbol)boundAttribute.Type; var attributeType = (NamedTypeSymbol)boundAttribute.Type;
...@@ -181,6 +192,8 @@ private CSharpAttributeData GetAttribute(BoundAttribute boundAttribute, Diagnost ...@@ -181,6 +192,8 @@ private CSharpAttributeData GetAttribute(BoundAttribute boundAttribute, Diagnost
Debug.Assert((object)attributeType != null); Debug.Assert((object)attributeType != null);
NullableWalker.AnalyzeIfNeeded(Compilation, boundAttribute, diagnostics);
bool hasErrors = boundAttribute.HasAnyErrors; bool hasErrors = boundAttribute.HasAnyErrors;
if (attributeType.IsErrorType() || attributeType.IsAbstract || (object)attributeConstructor == null) if (attributeType.IsErrorType() || attributeType.IsAbstract || (object)attributeConstructor == null)
...@@ -484,13 +497,15 @@ private TypeSymbol BindNamedAttributeArgumentType(AttributeArgumentSyntax namedA ...@@ -484,13 +497,15 @@ private TypeSymbol BindNamedAttributeArgumentType(AttributeArgumentSyntax namedA
return namedArgumentType; return namedArgumentType;
} }
protected virtual MethodSymbol BindAttributeConstructor( protected MethodSymbol BindAttributeConstructor(
AttributeSyntax node, AttributeSyntax node,
NamedTypeSymbol attributeType, NamedTypeSymbol attributeType,
AnalyzedArguments boundConstructorArguments, AnalyzedArguments boundConstructorArguments,
DiagnosticBag diagnostics, DiagnosticBag diagnostics,
ref LookupResultKind resultKind, ref LookupResultKind resultKind,
bool suppressErrors, bool suppressErrors,
ref ImmutableArray<int> argsToParamsOpt,
ref bool expanded,
ref HashSet<DiagnosticInfo> useSiteDiagnostics) ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{ {
MemberResolutionResult<MethodSymbol> memberResolutionResult; MemberResolutionResult<MethodSymbol> memberResolutionResult;
...@@ -511,7 +526,8 @@ private TypeSymbol BindNamedAttributeArgumentType(AttributeArgumentSyntax namedA ...@@ -511,7 +526,8 @@ private TypeSymbol BindNamedAttributeArgumentType(AttributeArgumentSyntax namedA
LookupResultKind.Inaccessible : LookupResultKind.Inaccessible :
LookupResultKind.OverloadResolutionFailure); LookupResultKind.OverloadResolutionFailure);
} }
argsToParamsOpt = memberResolutionResult.Result.ArgsToParamsOpt;
expanded = memberResolutionResult.Result.Kind == MemberResolutionKind.ApplicableInExpandedForm;
return memberResolutionResult.Member; return memberResolutionResult.Member;
} }
......
...@@ -1438,6 +1438,8 @@ ...@@ -1438,6 +1438,8 @@
<Field Name="Constructor" Type="MethodSymbol" Null="allow"/> <Field Name="Constructor" Type="MethodSymbol" Null="allow"/>
<Field Name="ConstructorArguments" Type="ImmutableArray&lt;BoundExpression&gt;"/> <Field Name="ConstructorArguments" Type="ImmutableArray&lt;BoundExpression&gt;"/>
<Field Name="ConstructorArgumentNamesOpt" Type="ImmutableArray&lt;string&gt;" Null="allow"/> <Field Name="ConstructorArgumentNamesOpt" Type="ImmutableArray&lt;string&gt;" Null="allow"/>
<Field Name="ConstructorArgumentsToParamsOpt" Type="ImmutableArray&lt;int&gt;" Null="allow"/>
<Field Name="ConstructorExpanded" Type="bool" />
<Field Name="NamedArguments" Type ="ImmutableArray&lt;BoundExpression&gt;"/> <Field Name="NamedArguments" Type ="ImmutableArray&lt;BoundExpression&gt;"/>
<Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind"/> <Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind"/>
</Node> </Node>
......
...@@ -423,8 +423,9 @@ protected ParameterSymbol MethodThisParameter ...@@ -423,8 +423,9 @@ protected ParameterSymbol MethodThisParameter
{ {
get get
{ {
var method = _symbol as MethodSymbol; ParameterSymbol thisParameter = null;
return (object)method == null ? null : method.ThisParameter; (_symbol as MethodSymbol)?.TryGetThisParameter(out thisParameter);
return thisParameter;
} }
} }
......
...@@ -265,7 +265,7 @@ protected override ImmutableArray<PendingBranch> Scan(ref bool badRegion) ...@@ -265,7 +265,7 @@ protected override ImmutableArray<PendingBranch> Scan(ref bool badRegion)
this.State = TopState(); // entry point is reachable this.State = TopState(); // entry point is reachable
this.regionPlace = RegionPlace.Before; this.regionPlace = RegionPlace.Before;
EnterParameters(); // with parameters assigned EnterParameters(); // with parameters assigned
if ((object)methodThisParameter != null) if (!(methodThisParameter is null))
{ {
EnterParameter(methodThisParameter, methodThisParameter.Type); EnterParameter(methodThisParameter, methodThisParameter.Type);
} }
...@@ -288,6 +288,19 @@ protected override ImmutableArray<PendingBranch> Scan(ref bool badRegion) ...@@ -288,6 +288,19 @@ protected override ImmutableArray<PendingBranch> Scan(ref bool badRegion)
Analyze(compilation, method, node, diagnostics, useMethodSignatureReturnType: false, useMethodSignatureParameterTypes: false, methodSignatureOpt: null, returnTypes: null, initialState: null, callbackOpt); Analyze(compilation, method, node, diagnostics, useMethodSignatureReturnType: false, useMethodSignatureParameterTypes: false, methodSignatureOpt: null, returnTypes: null, initialState: null, callbackOpt);
} }
internal static void AnalyzeIfNeeded(
CSharpCompilation compilation,
BoundAttribute attribute,
DiagnosticBag diagnostics)
{
if (compilation.LanguageVersion < MessageID.IDS_FeatureNullableReferenceTypes.RequiredVersion())
{
return;
}
Analyze(compilation, null, attribute, diagnostics, useMethodSignatureReturnType: false, useMethodSignatureParameterTypes: false, methodSignatureOpt: null, returnTypes: null, initialState: null, callbackOpt: null);
}
internal static void Analyze( internal static void Analyze(
CSharpCompilation compilation, CSharpCompilation compilation,
BoundLambda lambda, BoundLambda lambda,
...@@ -1097,7 +1110,13 @@ protected override LocalState ReachableBottomState() ...@@ -1097,7 +1110,13 @@ protected override LocalState ReachableBottomState()
private void EnterParameters() private void EnterParameters()
{ {
var methodParameters = ((MethodSymbol)_symbol).Parameters; var methodSymbol = _symbol as MethodSymbol;
if (methodSymbol is null)
{
return;
}
var methodParameters = methodSymbol.Parameters;
var signatureParameters = _useMethodSignatureParameterTypes ? _methodSignatureOpt.Parameters : methodParameters; var signatureParameters = _useMethodSignatureParameterTypes ? _methodSignatureOpt.Parameters : methodParameters;
Debug.Assert(signatureParameters.Length == methodParameters.Length); Debug.Assert(signatureParameters.Length == methodParameters.Length);
int n = methodParameters.Length; int n = methodParameters.Length;
...@@ -5726,6 +5745,18 @@ public override BoundNode VisitLockStatement(BoundLockStatement node) ...@@ -5726,6 +5745,18 @@ public override BoundNode VisitLockStatement(BoundLockStatement node)
return null; return null;
} }
public override BoundNode VisitAttribute(BoundAttribute node)
{
VisitArguments(node, node.ConstructorArguments, ImmutableArray<RefKind>.Empty, node.Constructor, argsToParamsOpt: node.ConstructorArgumentsToParamsOpt, expanded: node.ConstructorExpanded);
foreach (var assignment in node.NamedArguments)
{
Visit(assignment);
}
SetNotNullResult(node);
return null;
}
protected override string Dump(LocalState state) protected override string Dump(LocalState state)
{ {
if (!state.Reachable) if (!state.Reachable)
......
...@@ -6015,7 +6015,7 @@ protected override BoundExpression ShallowClone() ...@@ -6015,7 +6015,7 @@ protected override BoundExpression ShallowClone()
internal sealed partial class BoundAttribute : BoundExpression internal sealed partial class BoundAttribute : BoundExpression
{ {
public BoundAttribute(SyntaxNode syntax, MethodSymbol constructor, ImmutableArray<BoundExpression> constructorArguments, ImmutableArray<string> constructorArgumentNamesOpt, ImmutableArray<BoundExpression> namedArguments, LookupResultKind resultKind, TypeSymbol type, bool hasErrors = false) public BoundAttribute(SyntaxNode syntax, MethodSymbol constructor, ImmutableArray<BoundExpression> constructorArguments, ImmutableArray<string> constructorArgumentNamesOpt, ImmutableArray<int> constructorArgumentsToParamsOpt, bool constructorExpanded, ImmutableArray<BoundExpression> namedArguments, LookupResultKind resultKind, TypeSymbol type, bool hasErrors = false)
: base(BoundKind.Attribute, syntax, type, hasErrors || constructorArguments.HasErrors() || namedArguments.HasErrors()) : base(BoundKind.Attribute, syntax, type, hasErrors || constructorArguments.HasErrors() || namedArguments.HasErrors())
{ {
...@@ -6026,6 +6026,8 @@ public BoundAttribute(SyntaxNode syntax, MethodSymbol constructor, ImmutableArra ...@@ -6026,6 +6026,8 @@ public BoundAttribute(SyntaxNode syntax, MethodSymbol constructor, ImmutableArra
this.Constructor = constructor; this.Constructor = constructor;
this.ConstructorArguments = constructorArguments; this.ConstructorArguments = constructorArguments;
this.ConstructorArgumentNamesOpt = constructorArgumentNamesOpt; this.ConstructorArgumentNamesOpt = constructorArgumentNamesOpt;
this.ConstructorArgumentsToParamsOpt = constructorArgumentsToParamsOpt;
this.ConstructorExpanded = constructorExpanded;
this.NamedArguments = namedArguments; this.NamedArguments = namedArguments;
this._ResultKind = resultKind; this._ResultKind = resultKind;
} }
...@@ -6037,6 +6039,10 @@ public BoundAttribute(SyntaxNode syntax, MethodSymbol constructor, ImmutableArra ...@@ -6037,6 +6039,10 @@ public BoundAttribute(SyntaxNode syntax, MethodSymbol constructor, ImmutableArra
public ImmutableArray<string> ConstructorArgumentNamesOpt { get; } public ImmutableArray<string> ConstructorArgumentNamesOpt { get; }
public ImmutableArray<int> ConstructorArgumentsToParamsOpt { get; }
public bool ConstructorExpanded { get; }
public ImmutableArray<BoundExpression> NamedArguments { get; } public ImmutableArray<BoundExpression> NamedArguments { get; }
private readonly LookupResultKind _ResultKind; private readonly LookupResultKind _ResultKind;
...@@ -6047,11 +6053,11 @@ public override BoundNode Accept(BoundTreeVisitor visitor) ...@@ -6047,11 +6053,11 @@ public override BoundNode Accept(BoundTreeVisitor visitor)
return visitor.VisitAttribute(this); return visitor.VisitAttribute(this);
} }
public BoundAttribute Update(MethodSymbol constructor, ImmutableArray<BoundExpression> constructorArguments, ImmutableArray<string> constructorArgumentNamesOpt, ImmutableArray<BoundExpression> namedArguments, LookupResultKind resultKind, TypeSymbol type) public BoundAttribute Update(MethodSymbol constructor, ImmutableArray<BoundExpression> constructorArguments, ImmutableArray<string> constructorArgumentNamesOpt, ImmutableArray<int> constructorArgumentsToParamsOpt, bool constructorExpanded, ImmutableArray<BoundExpression> namedArguments, LookupResultKind resultKind, TypeSymbol type)
{ {
if (constructor != this.Constructor || constructorArguments != this.ConstructorArguments || constructorArgumentNamesOpt != this.ConstructorArgumentNamesOpt || namedArguments != this.NamedArguments || resultKind != this.ResultKind || !TypeSymbol.Equals(type, this.Type, TypeCompareKind.ConsiderEverything)) if (constructor != this.Constructor || constructorArguments != this.ConstructorArguments || constructorArgumentNamesOpt != this.ConstructorArgumentNamesOpt || constructorArgumentsToParamsOpt != this.ConstructorArgumentsToParamsOpt || constructorExpanded != this.ConstructorExpanded || namedArguments != this.NamedArguments || resultKind != this.ResultKind || !TypeSymbol.Equals(type, this.Type, TypeCompareKind.ConsiderEverything))
{ {
var result = new BoundAttribute(this.Syntax, constructor, constructorArguments, constructorArgumentNamesOpt, namedArguments, resultKind, type, this.HasErrors); var result = new BoundAttribute(this.Syntax, constructor, constructorArguments, constructorArgumentNamesOpt, constructorArgumentsToParamsOpt, constructorExpanded, namedArguments, resultKind, type, this.HasErrors);
result.CopyAttributes(this); result.CopyAttributes(this);
return result; return result;
} }
...@@ -6060,7 +6066,7 @@ public BoundAttribute Update(MethodSymbol constructor, ImmutableArray<BoundExpre ...@@ -6060,7 +6066,7 @@ public BoundAttribute Update(MethodSymbol constructor, ImmutableArray<BoundExpre
protected override BoundExpression ShallowClone() protected override BoundExpression ShallowClone()
{ {
var result = new BoundAttribute(this.Syntax, this.Constructor, this.ConstructorArguments, this.ConstructorArgumentNamesOpt, this.NamedArguments, this.ResultKind, this.Type, this.HasErrors); var result = new BoundAttribute(this.Syntax, this.Constructor, this.ConstructorArguments, this.ConstructorArgumentNamesOpt, this.ConstructorArgumentsToParamsOpt, this.ConstructorExpanded, this.NamedArguments, this.ResultKind, this.Type, this.HasErrors);
result.CopyAttributes(this); result.CopyAttributes(this);
return result; return result;
} }
...@@ -11801,7 +11807,7 @@ public override BoundNode VisitAttribute(BoundAttribute node) ...@@ -11801,7 +11807,7 @@ public override BoundNode VisitAttribute(BoundAttribute node)
ImmutableArray<BoundExpression> constructorArguments = (ImmutableArray<BoundExpression>)this.VisitList(node.ConstructorArguments); ImmutableArray<BoundExpression> constructorArguments = (ImmutableArray<BoundExpression>)this.VisitList(node.ConstructorArguments);
ImmutableArray<BoundExpression> namedArguments = (ImmutableArray<BoundExpression>)this.VisitList(node.NamedArguments); ImmutableArray<BoundExpression> namedArguments = (ImmutableArray<BoundExpression>)this.VisitList(node.NamedArguments);
TypeSymbol type = this.VisitType(node.Type); TypeSymbol type = this.VisitType(node.Type);
return node.Update(node.Constructor, constructorArguments, node.ConstructorArgumentNamesOpt, namedArguments, node.ResultKind, type); return node.Update(node.Constructor, constructorArguments, node.ConstructorArgumentNamesOpt, node.ConstructorArgumentsToParamsOpt, node.ConstructorExpanded, namedArguments, node.ResultKind, type);
} }
public override BoundNode VisitObjectCreationExpression(BoundObjectCreationExpression node) public override BoundNode VisitObjectCreationExpression(BoundObjectCreationExpression node)
{ {
...@@ -13541,6 +13547,8 @@ public override TreeDumperNode VisitAttribute(BoundAttribute node, object arg) ...@@ -13541,6 +13547,8 @@ public override TreeDumperNode VisitAttribute(BoundAttribute node, object arg)
new TreeDumperNode("constructor", node.Constructor, null), new TreeDumperNode("constructor", node.Constructor, null),
new TreeDumperNode("constructorArguments", null, from x in node.ConstructorArguments select Visit(x, null)), new TreeDumperNode("constructorArguments", null, from x in node.ConstructorArguments select Visit(x, null)),
new TreeDumperNode("constructorArgumentNamesOpt", node.ConstructorArgumentNamesOpt, null), new TreeDumperNode("constructorArgumentNamesOpt", node.ConstructorArgumentNamesOpt, null),
new TreeDumperNode("constructorArgumentsToParamsOpt", node.ConstructorArgumentsToParamsOpt, null),
new TreeDumperNode("constructorExpanded", node.ConstructorExpanded, null),
new TreeDumperNode("namedArguments", null, from x in node.NamedArguments select Visit(x, null)), new TreeDumperNode("namedArguments", null, from x in node.NamedArguments select Visit(x, null)),
new TreeDumperNode("resultKind", node.ResultKind, null), new TreeDumperNode("resultKind", node.ResultKind, null),
new TreeDumperNode("type", node.Type, null), new TreeDumperNode("type", node.Type, null),
......
...@@ -4578,8 +4578,11 @@ public class MyAttribute : System.Attribute ...@@ -4578,8 +4578,11 @@ public class MyAttribute : System.Attribute
class C { } class C { }
"; ";
var comp = CreateCompilation(source, options: TestOptions.DebugDll); var comp = CreateCompilation(source, options: TestOptions.DebugDll);
comp.VerifyDiagnostics(); comp.VerifyDiagnostics(
// Expecting a warning. Issue tracked by https://github.com/dotnet/roslyn/issues/23697 // (7,20): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [My(new string[] { null })]
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(7, 20)
);
} }
[Fact, WorkItem(31740, "https://github.com/dotnet/roslyn/issues/31740")] [Fact, WorkItem(31740, "https://github.com/dotnet/roslyn/issues/31740")]
...@@ -4626,6 +4629,893 @@ class C { } ...@@ -4626,6 +4629,893 @@ class C { }
); );
} }
[Fact]
public void AttributeArgument_Constructor_NullLiteral()
{
var source =
@"
#nullable enable
class MyAttribute : System.Attribute
{
public MyAttribute(string s) { }
}
[MyAttribute(null)] //1
class C { }
[MyAttribute(""str"")]
class D { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (8,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute(null)] //1
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(8, 14)
);
}
[Fact]
public void AttributeArgument_Constructor_NullLiteral_Suppressed()
{
var source =
@"
#nullable enable
class MyAttribute : System.Attribute
{
public MyAttribute(string s) { }
}
[MyAttribute(null!)]
class C { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
}
[Fact]
public void AttributeArgument_Constructor_NullLiteral_CSharp7_3()
{
var source =
@"
class MyAttribute : System.Attribute
{
public MyAttribute(string s) { }
}
[MyAttribute(null)]
class C { }
[MyAttribute(""str"")]
class D { }
";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular7_3);
comp.VerifyDiagnostics();
}
[Fact]
public void AttributeArgument_Constructor_NullLiteral_WithDefaultArgument()
{
var source =
@"#nullable enable
class MyAttribute : System.Attribute
{
public MyAttribute(string s, string s2 = ""str"") { }
}
[MyAttribute(null)] //1
class C { }
[MyAttribute(null, null)] // 2, 3
class D { }
[MyAttribute(null, ""str"")] // 4
class E { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (7,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute(null)] //1
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(7, 14),
// (10,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute(null, null)] // 2, 3
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 14),
// (10,20): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute(null, null)] // 2, 3
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 20),
// (13,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute(null, "str")] // 4
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(13, 14)
);
}
[Fact]
public void AttributeArgument_Constructor_NullLiteral_WithNullDefaultArgument()
{
var source =
@"#nullable enable
class MyAttribute : System.Attribute
{
public MyAttribute(string s, string s2 = null) { } //1
}
[MyAttribute(""str"")]
class C { }
[MyAttribute(""str"", null)] // 2
class D { }
[MyAttribute(""str"", ""str"")]
class E { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (4,46): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// public MyAttribute(string s, string s2 = null) { } //1
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(4, 46),
// (10,21): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute("str", null)] // 2
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 21)
);
}
[Fact]
public void AttributeArgument_Constructor_NullLiteral_WithNamedArguments()
{
var source =
@"#nullable enable
class MyAttribute : System.Attribute
{
public MyAttribute(string s, string s2 = ""str"", string? s3 = ""str"") { }
}
[MyAttribute(""str"", s2: null, s3: null)] //1
class C { }
[MyAttribute(s3: null, s2: null, s: ""str"")] // 2
class D { }
[MyAttribute(s3: null, s2: ""str"", s: ""str"")]
class E { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (7,25): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute("str", s2: null, s3: null)] //1
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(7, 25),
// (10,28): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute(s3: null, s2: null, s: "str")] // 2
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 28)
);
}
[Fact]
public void AttributeArgument_Constructor_NullLiteral_DisabledEnabled()
{
var source =
@"
#nullable enable
class MyAttribute : System.Attribute
{
public MyAttribute(string s, string s2) { }
}
[MyAttribute(null, //1
#nullable disable
null
#nullable enable
)]
class C { }
[MyAttribute(
#nullable disable
null,
#nullable enable
null //2
)]
class D { }
[MyAttribute(null, //3
s2:
#nullable disable
null
#nullable enable
)]
class E { }
[MyAttribute(
#nullable disable
null,
s2:
#nullable enable
null //4
)]
class F { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (8,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute(null, //1
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(8, 14),
// (19,1): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// null //2
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(19, 1),
// (23,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute(null, //3
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(23, 14),
// (36,1): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// null //4
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(36, 1)
);
}
[Fact]
public void AttributeArgument_Constructor_NullLiteral_WarningDisabledEnabled()
{
var source =
@"
#nullable enable
class MyAttribute : System.Attribute
{
public MyAttribute(string s, string s2) { }
}
#nullable disable
#pragma warning enable nullable
[MyAttribute(null, //1
#pragma warning disable nullable
null
#pragma warning enable nullable
)]
class C { }
[MyAttribute(
#pragma warning disable nullable
null,
#pragma warning enable nullable
null //2
)]
class D { }
[MyAttribute(null, //3
s2:
#pragma warning disable nullable
null
#pragma warning enable nullable
)]
class E { }
[MyAttribute(
#pragma warning disable nullable
null,
s2:
#pragma warning enable nullable
null //4
)]
class F { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (10,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute(null, //1
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 14),
// (21,1): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// null //2
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(21, 1),
// (25,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute(null, //3
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(25, 14),
// (38,1): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// null //4
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(38, 1)
);
}
[Fact]
public void AttributeArgument_Constructor_Array_LiteralNull()
{
var source =
@"
#nullable enable
class MyAttribute : System.Attribute
{
public MyAttribute(string[] s) { }
}
[MyAttribute(null)] //1
class C { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (8,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute(null)] //1
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(8, 14)
);
}
[Fact]
public void AttributeArgument_Constructor_Array_LiteralNull_Suppressed()
{
var source =
@"
#nullable enable
class MyAttribute : System.Attribute
{
public MyAttribute(string[] s) { }
}
[MyAttribute(null!)]
class C { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
}
[Fact]
public void AttributeArgument_Constructor_Array_ArrayOfNullable()
{
var source =
@"
#nullable enable
class MyAttribute : System.Attribute
{
public MyAttribute(string[] s) { }
}
[MyAttribute(new string?[]{ null })] //1
class C { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (8,14): warning CS8620: Argument of type 'string?[]' cannot be used as an input of type 'string[]' for parameter 's' in 'MyAttribute.MyAttribute(string[] s)' due to differences in the nullability of reference types.
// [MyAttribute(new string?[]{ null })] //1
Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new string?[]{ null }").WithArguments("string?[]", "string[]", "s", "MyAttribute.MyAttribute(string[] s)").WithLocation(8, 14)
);
}
[Fact]
public void AttributeArgument_Constructor_Array_ArrayOfNullable_Suppressed()
{
var source =
@"
#nullable enable
class MyAttribute : System.Attribute
{
public MyAttribute(string[] s) { }
}
[MyAttribute(new string?[]{ null }!)]
class C { }
[MyAttribute(new string[]{ null! })]
class D { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
}
[Fact]
public void AttributeArgument_Constructor_Array_ArrayOfNullable_ImplicitType()
{
var source =
@"
#nullable enable
class MyAttribute : System.Attribute
{
public MyAttribute(string[] s) { }
}
[MyAttribute(new []{ ""str"", null })] //1
class C { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (8,14): warning CS8620: Argument of type 'string?[]' cannot be used as an input of type 'string[]' for parameter 's' in 'MyAttribute.MyAttribute(string[] s)' due to differences in the nullability of reference types.
// [MyAttribute(new []{ "str", null })] //1
Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, @"new []{ ""str"", null }").WithArguments("string?[]", "string[]", "s", "MyAttribute.MyAttribute(string[] s)").WithLocation(8, 14)
);
}
[Fact]
public void AttributeArgument_Constructor_Array_NullValueInInitializer()
{
var source =
@"
#nullable enable
class MyAttribute : System.Attribute
{
public MyAttribute(string[] s) { }
}
[MyAttribute(new string[]{ ""str"", null, ""str"" })] //1
class C { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (8,35): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute(new string[]{ "str", null, "str" })] //1
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(8, 35)
);
}
[Fact]
public void AttributeArgument_Constructor_Array_NullValueInNestedInitializer()
{
var source =
@"
#nullable enable
class MyAttribute : System.Attribute
{
public MyAttribute(object[] s) { }
}
[MyAttribute(new object[]
{
new string[] { ""str"", null }, //1
new string[] { null }, //2
new string?[] { null }
})]
class C { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (10,27): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// new string[] { "str", null }, //1
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 27),
// (11,20): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// new string[] { null }, //2
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(11, 20)
);
}
[Fact]
public void AttributeArgument_Constructor_ParamsArrayOfNullable_NullLiteral()
{
var source =
@"
#nullable enable
class MyAttribute : System.Attribute
{
public MyAttribute(params object?[] s) { }
}
[MyAttribute(null)] //1
class C { }
[MyAttribute(null, null)]
class D { }
[MyAttribute((object?)null)]
class E { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (8,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute(null)] //1
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(8, 14)
);
}
[Fact]
public void AttributeArgument_Constructor_ParamsArray_NullItem()
{
var source =
@"
#nullable enable
class MyAttribute : System.Attribute
{
public MyAttribute(string s1, params object[] s) { }
}
[MyAttribute(""str"", null, ""str"", ""str"")] //1
class C { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (8,21): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute("str", null, "str", "str")] //1
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(8, 21)
);
}
[Fact]
public void AttributeArgument_PropertyAssignment_NullLiteral()
{
var source =
@"
#nullable enable
class MyAttribute : System.Attribute
{
public MyAttribute() { }
public string MyValue { get; set; } = ""str"";
}
[MyAttribute(MyValue = null)] //1
class C { }
[MyAttribute(MyValue = ""str"")]
class D { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (10,24): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute(MyValue = null)] //1
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 24)
);
}
[Fact]
public void AttributeArgument_PropertyAssignment_Array_NullLiteral()
{
var source =
@"
#nullable enable
class MyAttribute : System.Attribute
{
public MyAttribute() { }
public string[] PropertyArray { get; set; } = new string[] { };
public string[]? NullablePropertyArray { get; set; } = null;
}
[MyAttribute(PropertyArray = null)] //1
class C { }
[MyAttribute(NullablePropertyArray = null)]
class D { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (13,30): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute(PropertyArray = null)] //1
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(13, 30)
);
}
[Fact]
public void AttributeArgument_PropertyAssignment_Array_ArrayOfNullable()
{
var source =
@"
#nullable enable
class MyAttribute : System.Attribute
{
public MyAttribute() { }
public string[] PropertyArray { get; set; } = new string[] { ""str"" };
public string[]? PropertyNullableArray { get; set; } = new string[] { ""str"" };
}
[MyAttribute(PropertyArray = new string?[]{ null })] //1
class C { }
[MyAttribute(PropertyNullableArray = null)]
class D { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (12,30): warning CS8619: Nullability of reference types in value of type 'string?[]' doesn't match target type 'string[]'.
// [MyAttribute(PropertyArray = new string?[]{ null })] //1
Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new string?[]{ null }").WithArguments("string?[]", "string[]").WithLocation(12, 30)
);
}
[Fact]
public void AttributeArgument_FieldAssignment_NullLiteral()
{
var source =
@"
#nullable enable
class MyAttribute : System.Attribute
{
public MyAttribute() { }
public string myValue = ""str"";
}
[MyAttribute(myValue = null)] //1
class C { }
[MyAttribute(myValue = ""str"")]
class D { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (10,24): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute(myValue = null)] //1
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 24)
);
}
[Fact]
public void AttributeArgument_FieldAssignment_Array_NullLiteral()
{
var source =
@"
#nullable enable
class MyAttribute : System.Attribute
{
public MyAttribute() { }
public string[] fieldArray = new string[] { };
public string[]? nullableFieldArray = null;
}
[MyAttribute(fieldArray = null)] //1
class C { }
[MyAttribute(nullableFieldArray = null)]
class D { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (12,27): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute(fieldArray = null)] //1
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(12, 27)
);
}
[Fact]
public void AttributeArgument_FieldAssignment_Array_ArrayOfNullable()
{
var source =
@"
#nullable enable
class MyAttribute : System.Attribute
{
public MyAttribute() { }
public string[] fieldArray = new string[] { };
public string?[] fieldArrayOfNullable = new string?[] { };
}
[MyAttribute(fieldArray = new string?[]{ null })] //1
class C { }
[MyAttribute(fieldArrayOfNullable = new string?[]{ null })]
class D { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (12,27): warning CS8619: Nullability of reference types in value of type 'string?[]' doesn't match target type 'string[]'.
// [MyAttribute(fieldArray = new string?[]{ null })] //1
Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new string?[]{ null }").WithArguments("string?[]", "string[]").WithLocation(12, 27)
);
}
[Fact]
public void AttributeArgument_NoMatchingConstructor_NullLiteral()
{
var source =
@"
#nullable enable
class MyAttribute : System.Attribute
{
}
[MyAttribute(null)] //1
class C { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (7,2): error CS1729: 'MyAttribute' does not contain a constructor that takes 1 arguments
// [MyAttribute(null)] //1
Diagnostic(ErrorCode.ERR_BadCtorArgCount, "MyAttribute(null)").WithArguments("MyAttribute", "1").WithLocation(7, 2)
);
}
[Fact]
public void AttributeArgument_NoMatchingConstructor_Array_NullValueInInitializer()
{
var source =
@"
#nullable enable
class MyAttribute : System.Attribute
{
}
[MyAttribute(new string[] { null })] //1
class C { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (7,2): error CS1729: 'MyAttribute' does not contain a constructor that takes 1 arguments
// [MyAttribute(new string[] { null })] //1
Diagnostic(ErrorCode.ERR_BadCtorArgCount, "MyAttribute(new string[] { null })").WithArguments("MyAttribute", "1").WithLocation(7, 2),
// (7,29): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute(new string[] { null })] //1
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(7, 29)
);
}
[Fact]
public void AttributeArgument_NoMatchingConstructor_PropertyAssignment_NullLiteral()
{
var source =
@"
#nullable enable
class MyAttribute : System.Attribute
{
public string[] PropertyArray { get; set; } = new string[] { ""str"" };
public string[]? PropertyNullableArray { get; set; } = new string[] { ""str"" };
}
[MyAttribute( // 1
new string[] { null }, // 2
PropertyArray = null, // 3
PropertyNullableArray = new string[] { null } // 4
)]
class C { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (10,2): error CS1729: 'MyAttribute' does not contain a constructor that takes 1 arguments
// [MyAttribute( // 1
Diagnostic(ErrorCode.ERR_BadCtorArgCount, @"MyAttribute( // 1
new string[] { null }, // 2
PropertyArray = null, // 3
PropertyNullableArray = new string[] { null } // 4
)").WithArguments("MyAttribute", "1").WithLocation(10, 2),
// (11,20): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// new string[] { null }, // 2
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(11, 20),
// (12,21): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// PropertyArray = null, // 3
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(12, 21),
// (13,44): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// PropertyNullableArray = new string[] { null } // 4
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(13, 44)
);
}
[Fact]
public void AttributeArgument_NoMatchingConstructor_FieldAssignment_NullLiteral()
{
var source =
@"
#nullable enable
class MyAttribute : System.Attribute
{
public string[] fieldArray = new string[] { };
public string?[] fieldArrayOfNullable = new string?[] { };
}
[MyAttribute( // 1
new string[] { null }, // 2
fieldArray = null, // 3
fieldArrayOfNullable = new string[] { null } // 4
)]
class C { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (10,2): error CS1729: 'MyAttribute' does not contain a constructor that takes 1 arguments
// [MyAttribute( // 1
Diagnostic(ErrorCode.ERR_BadCtorArgCount, @"MyAttribute( // 1
new string[] { null }, // 2
fieldArray = null, // 3
fieldArrayOfNullable = new string[] { null } // 4
)").WithArguments("MyAttribute", "1").WithLocation(10, 2),
// (11,20): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// new string[] { null }, // 2
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(11, 20),
// (12,18): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// fieldArray = null, // 3
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(12, 18),
// (13,43): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// fieldArrayOfNullable = new string[] { null } // 4
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(13, 43)
);
}
[Fact]
public void AttributeArgument_ComplexAssignment()
{
var source =
@"
#nullable enable
[System.AttributeUsage(System.AttributeTargets.All, AllowMultiple = true)]
class MyAttribute : System.Attribute
{
public MyAttribute(string s, string s2 = ""str"", string s3 = ""str"") { }
public string[] fieldArray = new string[] { };
public string?[] fieldArrayOfNullable = new string[] { };
public string[]? nullableFieldArray = null;
public string[] PropertyArray { get; set; } = new string[] { };
public string?[] PropertyArrayOfNullable { get; set; } = new string[] { };
public string[]? NullablePropertyArray { get; set; } = null;
}
[MyAttribute(""s1"")]
[MyAttribute(""s1"", s3: ""s3"", fieldArray = new string[]{})]
[MyAttribute(""s1"", s2: ""s2"", fieldArray = new string[]{}, PropertyArray = new string[]{})]
[MyAttribute(""s1"", fieldArrayOfNullable = new string?[]{ null }, NullablePropertyArray = null)]
[MyAttribute(null)] // 1
[MyAttribute(""s1"", s3: null, fieldArray = new string[]{})] // 2
[MyAttribute(""s1"", s2: ""s2"", fieldArray = new string?[]{ null }, PropertyArray = new string[]{})] // 3
[MyAttribute(""s1"", PropertyArrayOfNullable = null)] // 4
[MyAttribute(""s1"", NullablePropertyArray = new string?[]{ null })] // 5
[MyAttribute(""s1"", fieldArrayOfNullable = null)] // 6
[MyAttribute(""s1"", nullableFieldArray = new string[]{ null })] // 7
[MyAttribute(null, //8
s2: null, //9
fieldArrayOfNullable = null, //10
NullablePropertyArray = new string?[]{ null })] // 11
[MyAttribute(null, // 12
#nullable disable
s2: null,
#nullable enable
fieldArrayOfNullable = null, //13
#pragma warning disable nullable
NullablePropertyArray = new string?[]{ null },
#pragma warning enable nullable
nullableFieldArray = new string?[]{ null })] //14
class C { }
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (26,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute(null)] // 1
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(26, 14),
// (27,24): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute("s1", s3: null, fieldArray = new string[]{})] // 2
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(27, 24),
// (28,43): warning CS8619: Nullability of reference types in value of type 'string?[]' doesn't match target type 'string[]'.
// [MyAttribute("s1", s2: "s2", fieldArray = new string?[]{ null }, PropertyArray = new string[]{})] // 3
Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new string?[]{ null }").WithArguments("string?[]", "string[]").WithLocation(28, 43),
// (29,46): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute("s1", PropertyArrayOfNullable = null)] // 4
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(29, 46),
// (30,44): warning CS8619: Nullability of reference types in value of type 'string?[]' doesn't match target type 'string[]'.
// [MyAttribute("s1", NullablePropertyArray = new string?[]{ null })] // 5
Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new string?[]{ null }").WithArguments("string?[]", "string[]").WithLocation(30, 44),
// (31,43): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute("s1", fieldArrayOfNullable = null)] // 6
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(31, 43),
// (32,55): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute("s1", nullableFieldArray = new string[]{ null })] // 7
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(32, 55),
// (33,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute(null, //8
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(33, 14),
// (34,17): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// s2: null, //9
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(34, 17),
// (35,36): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// fieldArrayOfNullable = null, //10
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(35, 36),
// (36,37): warning CS8619: Nullability of reference types in value of type 'string?[]' doesn't match target type 'string[]'.
// NullablePropertyArray = new string?[]{ null })] // 11
Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new string?[]{ null }").WithArguments("string?[]", "string[]").WithLocation(36, 37),
// (37,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// [MyAttribute(null, // 12
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(37, 14),
// (41,36): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// fieldArrayOfNullable = null, //13
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(41, 36),
// (45,34): warning CS8619: Nullability of reference types in value of type 'string?[]' doesn't match target type 'string[]'.
// nullableFieldArray = new string?[]{ null })] //14
Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new string?[]{ null }").WithArguments("string?[]", "string[]").WithLocation(45, 34)
);
}
[Fact] [Fact]
public void NullableAndConditionalOperators() public void NullableAndConditionalOperators()
{ {
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册