Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
21ca4569
R
roslyn
项目概览
lwm1986
/
roslyn
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
roslyn
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
21ca4569
编写于
10月 22, 2020
作者:
J
Julien Couvreur
提交者:
GitHub
10月 22, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Only enforce Member/NotNullWhen on analyzable returned expressions (#48425)
上级
e2e303ac
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
488 addition
and
62 deletion
+488
-62
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
+106
-32
src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
...rp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
+382
-30
未找到文件。
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
浏览文件 @
21ca4569
...
...
@@ -611,18 +611,50 @@ void enforceMemberNotNullWhenForPendingReturn(PendingBranch pendingReturn, Bound
{
if
(
pendingReturn
.
IsConditionalState
)
{
enforceMemberNotNullWhen
(
returnStatement
.
Syntax
,
sense
:
true
,
pendingReturn
.
StateWhenTrue
);
enforceMemberNotNullWhen
(
returnStatement
.
Syntax
,
sense
:
false
,
pendingReturn
.
StateWhenFalse
);
if
(
returnStatement
.
ExpressionOpt
is
{
ConstantValue
:
{
IsBoolean
:
true
,
BooleanValue
:
bool
value
}
})
{
enforceMemberNotNullWhen
(
returnStatement
.
Syntax
,
sense
:
value
,
pendingReturn
.
State
);
return
;
}
if
(!
pendingReturn
.
StateWhenTrue
.
Reachable
||
!
pendingReturn
.
StateWhenFalse
.
Reachable
)
{
return
;
}
if
(
_symbol
is
MethodSymbol
method
)
{
foreach
(
var
memberName
in
method
.
NotNullWhenTrueMembers
)
{
enforceMemberNotNullWhenIfAffected
(
returnStatement
.
Syntax
,
sense
:
true
,
method
.
ContainingType
.
GetMembers
(
memberName
),
pendingReturn
.
StateWhenTrue
,
pendingReturn
.
StateWhenFalse
);
}
foreach
(
var
memberName
in
method
.
NotNullWhenFalseMembers
)
{
enforceMemberNotNullWhenIfAffected
(
returnStatement
.
Syntax
,
sense
:
false
,
method
.
ContainingType
.
GetMembers
(
memberName
),
pendingReturn
.
StateWhenFalse
,
pendingReturn
.
StateWhenTrue
);
}
}
}
else
if
(
returnStatement
.
ExpressionOpt
is
{
ConstantValue
:
{
IsBoolean
:
true
,
BooleanValue
:
bool
value
}
})
{
enforceMemberNotNullWhen
(
returnStatement
.
Syntax
,
sense
:
value
,
pendingReturn
.
State
);
}
}
void
enforceMemberNotNullWhen
(
SyntaxNode
?
syntaxOpt
,
bool
sense
,
LocalState
s
tate
)
void
enforceMemberNotNullWhen
IfAffected
(
SyntaxNode
?
syntaxOpt
,
bool
sense
,
ImmutableArray
<
Symbol
>
members
,
LocalState
state
,
LocalState
otherS
tate
)
{
if
(!
state
.
Reachable
)
foreach
(
var
member
in
members
)
{
return
;
// For non-constant values, only complain if we were able to analyze a difference for this member between two branches
if
(
memberHasBadState
(
member
,
state
)
!=
memberHasBadState
(
member
,
otherState
))
{
reportMemberIfBadConditionalState
(
syntaxOpt
,
sense
,
member
,
state
);
}
}
}
void
enforceMemberNotNullWhen
(
SyntaxNode
?
syntaxOpt
,
bool
sense
,
LocalState
state
)
{
if
(
_symbol
is
MethodSymbol
method
)
{
var
notNullMembers
=
sense
?
method
.
NotNullWhenTrueMembers
:
method
.
NotNullWhenFalseMembers
;
...
...
@@ -630,16 +662,21 @@ void enforceMemberNotNullWhen(SyntaxNode? syntaxOpt, bool sense, LocalState stat
{
foreach
(
var
member
in
method
.
ContainingType
.
GetMembers
(
memberName
))
{
if
(
memberHasBadState
(
member
,
state
))
{
// Member '{name}' must have a non-null value when exiting with '{sense}'.
Diagnostics
.
Add
(
ErrorCode
.
WRN_MemberNotNullWhen
,
syntaxOpt
?.
GetLocation
()
??
methodMainNode
.
Syntax
.
GetLastToken
().
GetLocation
(),
member
.
Name
,
sense
?
"true"
:
"false"
);
}
reportMemberIfBadConditionalState
(
syntaxOpt
,
sense
,
member
,
state
);
}
}
}
}
void
reportMemberIfBadConditionalState
(
SyntaxNode
?
syntaxOpt
,
bool
sense
,
Symbol
member
,
LocalState
state
)
{
if
(
memberHasBadState
(
member
,
state
))
{
// Member '{name}' must have a non-null value when exiting with '{sense}'.
Diagnostics
.
Add
(
ErrorCode
.
WRN_MemberNotNullWhen
,
syntaxOpt
?.
GetLocation
()
??
methodMainNode
.
Syntax
.
GetLastToken
().
GetLocation
(),
member
.
Name
,
sense
?
"true"
:
"false"
);
}
}
bool
memberHasBadState
(
Symbol
member
,
LocalState
state
)
{
switch
(
member
.
Kind
)
...
...
@@ -767,12 +804,45 @@ void enforceNotNullWhenForPendingReturn(PendingBranch pendingReturn, BoundReturn
{
if
(
pendingReturn
.
IsConditionalState
)
{
enforceParameterNotNullWhen
(
returnStatement
.
Syntax
,
parameters
,
sense
:
true
,
stateWhen
:
pendingReturn
.
StateWhenTrue
);
enforceParameterNotNullWhen
(
returnStatement
.
Syntax
,
parameters
,
sense
:
false
,
stateWhen
:
pendingReturn
.
StateWhenFalse
);
if
(
returnStatement
.
ExpressionOpt
is
{
ConstantValue
:
{
IsBoolean
:
true
,
BooleanValue
:
bool
value
}
})
{
enforceParameterNotNullWhen
(
returnStatement
.
Syntax
,
parameters
,
sense
:
value
,
stateWhen
:
pendingReturn
.
State
);
return
;
}
if
(!
pendingReturn
.
StateWhenTrue
.
Reachable
||
!
pendingReturn
.
StateWhenFalse
.
Reachable
)
{
return
;
}
foreach
(
var
parameter
in
parameters
)
{
// For non-constant values, only complain if we were able to analyze a difference for this parameter between two branches
if
(
GetOrCreateSlot
(
parameter
)
is
>
0
and
var
slot
&&
pendingReturn
.
StateWhenTrue
[
slot
]
!=
pendingReturn
.
StateWhenFalse
[
slot
])
{
reportParameterIfBadConditionalState
(
returnStatement
.
Syntax
,
parameter
,
sense
:
true
,
stateWhen
:
pendingReturn
.
StateWhenTrue
);
reportParameterIfBadConditionalState
(
returnStatement
.
Syntax
,
parameter
,
sense
:
false
,
stateWhen
:
pendingReturn
.
StateWhenFalse
);
}
}
}
else
if
(
returnStatement
.
ExpressionOpt
is
{
ConstantValue
:
{
IsBoolean
:
true
,
BooleanValue
:
bool
value
}
})
{
// example: return (bool)true;
enforceParameterNotNullWhen
(
returnStatement
.
Syntax
,
parameters
,
sense
:
value
,
stateWhen
:
pendingReturn
.
State
);
return
;
}
}
}
void
reportParameterIfBadConditionalState
(
SyntaxNode
syntax
,
ParameterSymbol
parameter
,
bool
sense
,
LocalState
stateWhen
)
{
if
(
parameterHasBadConditionalState
(
parameter
,
sense
,
stateWhen
))
{
// Parameter '{name}' must have a non-null value when exiting with '{sense}'.
Diagnostics
.
Add
(
ErrorCode
.
WRN_ParameterConditionallyDisallowsNull
,
syntax
.
Location
,
parameter
.
Name
,
sense
?
"true"
:
"false"
);
}
}
void
enforceNotNull
(
SyntaxNode
?
syntaxOpt
,
LocalState
state
)
{
if
(!
state
.
Reachable
)
...
...
@@ -812,11 +882,7 @@ void enforceParameterNotNullWhen(SyntaxNode syntax, ImmutableArray<ParameterSymb
foreach
(
var
parameter
in
parameters
)
{
if
(
parameterHasBadConditionalState
(
parameter
,
sense
,
stateWhen
))
{
// Parameter '{name}' must have a non-null value when exiting with '{sense}'.
Diagnostics
.
Add
(
ErrorCode
.
WRN_ParameterConditionallyDisallowsNull
,
syntax
.
Location
,
parameter
.
Name
,
sense
?
"true"
:
"false"
);
}
reportParameterIfBadConditionalState
(
syntax
,
parameter
,
sense
,
stateWhen
);
}
}
...
...
@@ -2428,6 +2494,7 @@ private bool TryGetReturnType(out TypeWithAnnotations type, out FlowAnalysisAnno
}
SetResult
(
node
,
GetAdjustedResult
(
type
.
ToTypeWithState
(),
slot
),
type
);
SplitIfBooleanConstant
(
node
);
return
null
;
}
...
...
@@ -8152,9 +8219,27 @@ private TypeWithAnnotations GetDeclaredParameterResult(ParameterSymbol parameter
return
null
;
}
private
void
SplitIfBooleanConstant
(
BoundExpression
node
)
{
if
(
node
.
ConstantValue
is
{
IsBoolean
:
true
,
BooleanValue
:
bool
booleanValue
})
{
Split
();
if
(
booleanValue
)
{
StateWhenFalse
=
UnreachableState
();
}
else
{
StateWhenTrue
=
UnreachableState
();
}
}
}
public
override
BoundNode
?
VisitFieldAccess
(
BoundFieldAccess
node
)
{
var
updatedSymbol
=
VisitMemberAccess
(
node
,
node
.
ReceiverOpt
,
node
.
FieldSymbol
);
SplitIfBooleanConstant
(
node
);
SetUpdatedSymbol
(
node
,
node
.
FieldSymbol
,
updatedSymbol
);
return
null
;
}
...
...
@@ -8614,8 +8699,9 @@ public override void VisitForEachIterationVariables(BoundForEachStatement node)
switch
(
node
.
OperatorKind
)
{
case
UnaryOperatorKind
.
BoolLogicalNegation
:
VisitCondition
(
node
.
Operand
);
SetConditionalState
(
StateWhenFalse
,
StateWhenTrue
);
Visit
(
node
.
Operand
);
if
(
IsConditionalState
)
SetConditionalState
(
StateWhenFalse
,
StateWhenTrue
);
resultType
=
adjustForLifting
(
ResultType
);
break
;
case
UnaryOperatorKind
.
DynamicTrue
:
...
...
@@ -8968,19 +9054,7 @@ private TypeWithState InferResultNullabilityOfBinaryLogicalOperator(BoundExpress
Debug
.
Assert
(!
IsConditionalState
);
SetResultType
(
node
,
TypeWithState
.
Create
(
node
.
Type
,
node
.
Type
?.
CanContainNull
()
!=
false
&&
node
.
ConstantValue
?.
IsNull
==
true
?
NullableFlowState
.
MaybeDefault
:
NullableFlowState
.
NotNull
));
if
(
node
.
ConstantValue
?.
IsBoolean
==
true
)
{
Split
();
if
(
node
.
ConstantValue
.
BooleanValue
)
{
StateWhenFalse
=
UnreachableState
();
}
else
{
StateWhenTrue
=
UnreachableState
();
}
}
SplitIfBooleanConstant
(
node
);
return
result
;
}
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
浏览文件 @
21ca4569
...
...
@@ -24076,6 +24076,149 @@ bool Init()
);
}
[Fact]
public void MemberNotNullWhenTrue_EnforcedInMethodBody_NonConstant()
{
var c = CreateNullableCompilation(new[] { @"
using System.Diagnostics.CodeAnalysis;
public class C
{
public string field1;
public string? field2;
public string field3;
public string? field4;
C() // 1
{
if (!Init()) throw null!;
}
[MemberNotNullWhen(true, nameof(field1), nameof(field2))]
bool Init()
{
bool b = true;
if (b)
{
return b;
}
if (b)
{
return !b;
}
return M(out _);
}
bool M([MaybeNullWhen(true)]out string s) => throw null!;
}
", MemberNotNullWhenAttributeDefinition, MaybeNullWhenAttributeDefinition });
c.VerifyDiagnostics(
// (10,5): warning CS8618: Non-nullable field 'field3' is uninitialized. Consider declaring the field as nullable.
// C() // 1
Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "C").WithArguments("field", "field3").WithLocation(10, 5)
);
}
[Fact]
public void MemberNotNullWhenTrue_EnforcedInMethodBody_NonConstant_ButAnalyzable()
{
var c = CreateNullableCompilation(new[] { @"
using System.Diagnostics.CodeAnalysis;
public class C
{
public string field1;
public string field3;
C()
{
if (!Init()) throw null!;
}
[MemberNotNullWhen(true, nameof(field1), nameof(field3))]
bool Init()
{
bool b = true;
if (b)
{
return field1 == null; // 1
}
if (b)
{
return field1 != null;
}
if (b)
{
return Init();
}
return !Init(); // 2, 3
}
}
", MemberNotNullWhenAttributeDefinition, MaybeNullWhenAttributeDefinition });
c.VerifyDiagnostics(
// (19,13): warning CS8775: Member 'field1' must have a non-null value when exiting with 'true'.
// return field1 == null; // 1
Diagnostic(ErrorCode.WRN_MemberNotNullWhen, "return field1 == null;").WithArguments("field1", "true").WithLocation(19, 13),
// (29,9): warning CS8775: Member 'field1' must have a non-null value when exiting with 'true'.
// return !Init(); // 2, 3
Diagnostic(ErrorCode.WRN_MemberNotNullWhen, "return !Init();").WithArguments("field1", "true").WithLocation(29, 9),
// (29,9): warning CS8775: Member 'field3' must have a non-null value when exiting with 'true'.
// return !Init(); // 2, 3
Diagnostic(ErrorCode.WRN_MemberNotNullWhen, "return !Init();").WithArguments("field3", "true").WithLocation(29, 9)
);
}
[Fact]
public void MemberNotNullWhenFalse_EnforcedInMethodBody_NonConstant_ButAnalyzable()
{
var c = CreateNullableCompilation(new[] { @"
using System.Diagnostics.CodeAnalysis;
public class C
{
public string field1;
public string field3;
C()
{
if (Init()) throw null!;
}
[MemberNotNullWhen(false, nameof(field1), nameof(field3))]
bool Init()
{
bool b = true;
if (b)
{
return field1 == null;
}
if (b)
{
return field1 != null; // 1
}
if (b)
{
return Init();
}
return !Init(); // 2, 3
}
bool M([MaybeNullWhen(true)]out string s) => throw null!;
}
", MemberNotNullWhenAttributeDefinition, MaybeNullWhenAttributeDefinition });
c.VerifyDiagnostics(
// (23,13): warning CS8775: Member 'field1' must have a non-null value when exiting with 'false'.
// return field1 != null; // 1
Diagnostic(ErrorCode.WRN_MemberNotNullWhen, "return field1 != null;").WithArguments("field1", "false").WithLocation(23, 13),
// (29,9): warning CS8775: Member 'field1' must have a non-null value when exiting with 'false'.
// return !Init(); // 2, 3
Diagnostic(ErrorCode.WRN_MemberNotNullWhen, "return !Init();").WithArguments("field1", "false").WithLocation(29, 9),
// (29,9): warning CS8775: Member 'field3' must have a non-null value when exiting with 'false'.
// return !Init(); // 2, 3
Diagnostic(ErrorCode.WRN_MemberNotNullWhen, "return !Init();").WithArguments("field3", "false").WithLocation(29, 9)
);
}
[Fact]
public void MemberNotNullWhenTrue_WithMemberNotNull()
{
...
...
@@ -24315,7 +24458,7 @@ bool IsInit2
", MemberNotNullWhenAttributeDefinition }, parseOptions: TestOptions.Regular9);
c.VerifyDiagnostics(
// (21,13):
error CS876
5: Member 'field2' must have a non-null value when exiting with 'true'.
// (21,13):
warning CS877
5: Member 'field2' must have a non-null value when exiting with 'true'.
// return field2 == null; // 1
Diagnostic(ErrorCode.WRN_MemberNotNullWhen, "return field2 == null;").WithArguments("field2", "true").WithLocation(21, 13)
);
...
...
@@ -25084,6 +25227,23 @@ public static bool TryGetValue([NotNullWhen(true)] out string? s)
comp.VerifyDiagnostics();
}
[Fact]
public void NotNullWhenTrue_EnforceInMethodBody_ConditionalWithThrow()
{
var source = @"
using System.Diagnostics.CodeAnalysis;
public class C
{
static bool M([NotNullWhen(true)] object? o)
{
return o == null ? true : throw null!;
}
}
";
var comp = CreateNullableCompilation(new[] { source, NotNullWhenAttributeDefinition });
comp.VerifyDiagnostics();
}
[Fact]
public void NotNullWhenTrue_EnforceInMethodBody_WithMaybeNull_CallingObliviousAPI()
{
...
...
@@ -25489,35 +25649,39 @@ public void NotNullWhenTrue_EnforceInMethodBody_OnConversionToBool()
using System.Diagnostics.CodeAnalysis;
public class C
{
public static implicit operator bool(C? c) => throw null!;
public static bool TryGetValue(C? c, [NotNullWhen(true)] out string? s)
{
s = null;
return c;
// 1
return c;
}
public static bool TryGetValue2(C c, [NotNullWhen(false)] out string? s)
{
s = null;
return c;
// 2
return c;
}
public static implicit operator bool(C? c) => throw null!;
static bool TryGetValue3([MaybeNullWhen(false)]out string s)
{
s = null;
return (bool)true; //
3
return (bool)true; //
1
}
static bool TryGetValue4([MaybeNullWhen(false)]out string s)
{
s = null;
return (bool)false;
// 4
return (bool)false;
}
}
";
var comp = CreateNullableCompilation(new[] { source, NotNullWhenAttributeDefinition, MaybeNullWhenAttributeDefinition });
comp.VerifyDiagnostics();
comp.VerifyDiagnostics(
// (22,9): warning CS8762: Parameter 's' must have a non-null value when exiting with 'true'.
// return (bool)true;
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return (bool)true;").WithArguments("s", "true").WithLocation(22, 9)
);
}
[Fact]
...
...
@@ -37294,10 +37458,10 @@ static bool TryGetValue4([AllowNull] TYPE x, [MaybeNullWhen(false)] out TYPE y)
";
var comp = CreateNullableCompilation(new[] { AllowNullAttributeDefinition, MaybeNullAttributeDefinition, MaybeNullWhenAttributeDefinition, source.Replace("TYPE", type) });
comp.VerifyDiagnostics(
// (24,9):
error
CS8762: Parameter 'y' must have a non-null value when exiting with 'false'.
// (24,9):
warning
CS8762: Parameter 'y' must have a non-null value when exiting with 'false'.
// return y != null; // 1
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return y != null;").WithArguments("y", "false").WithLocation(24, 9),
// (30,9):
error
CS8762: Parameter 'y' must have a non-null value when exiting with 'true'.
// (30,9):
warning
CS8762: Parameter 'y' must have a non-null value when exiting with 'true'.
// return y == null; // 2
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return y == null;").WithArguments("y", "true").WithLocation(30, 9)
);
...
...
@@ -37387,7 +37551,7 @@ static bool TryGetValue<T>([AllowNull]T x, [MaybeNullWhen(true)]out T y, [MaybeN
{
y = x;
z = x;
return y != null || z != null;
// 1, 2
return y != null || z != null;
}
static bool TryGetValue2<T>([AllowNull]T x, [MaybeNullWhen(false)]out T y, [MaybeNullWhen(false)]out T z)
...
...
@@ -37399,14 +37563,7 @@ static bool TryGetValue2<T>([AllowNull]T x, [MaybeNullWhen(false)]out T y, [Mayb
}
";
var comp = CreateNullableCompilation(new[] { AllowNullAttributeDefinition, MaybeNullWhenAttributeDefinition, source });
comp.VerifyDiagnostics(
// (12,9): warning CS8762: Parameter 'y' must have a non-null value when exiting with 'false'.
// return y != null || z != null; // 1, 2
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return y != null || z != null;").WithArguments("y", "false").WithLocation(12, 9),
// (12,9): warning CS8762: Parameter 'z' must have a non-null value when exiting with 'false'.
// return y != null || z != null; // 1, 2
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return y != null || z != null;").WithArguments("z", "false").WithLocation(12, 9)
);
comp.VerifyDiagnostics();
}
[Theory]
...
...
@@ -37440,20 +37597,32 @@ static bool TryGetValue2([NotNullWhen(true)] out TYPE y)
return y != null;
}
static bool TryGetValue2B([NotNullWhen(true)] out TYPE y)
{
y = null;
return y == null; // 2
}
static bool TryGetValue3([NotNullWhen(false)] out TYPE y)
{
y = null;
return y == null;
}
static bool TryGetValue3B([NotNullWhen(false)] out TYPE y)
{
y = null;
return y != null; // 3
}
static bool TryGetValue4([NotNull] TYPE x, [NotNullWhen(false)] out TYPE y)
{
y = null;
if (y != null)
{
return true; //
2
return true; //
4
}
return false; //
3, 4
return false; //
5, 6
}
}
";
...
...
@@ -37462,15 +37631,21 @@ static bool TryGetValue4([NotNull] TYPE x, [NotNullWhen(false)] out TYPE y)
// (15,13): warning CS8762: Parameter 'y' must have a non-null value when exiting with 'true'.
// return true; // 1
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return true;").WithArguments("y", "true").WithLocation(15, 13),
// (37,13): warning CS8777: Parameter 'x' must have a non-null value when exiting.
// return true; // 2
Diagnostic(ErrorCode.WRN_ParameterDisallowsNull, "return true;").WithArguments("x").WithLocation(37, 13),
// (39,9): warning CS8777: Parameter 'x' must have a non-null value when exiting.
// return false; // 3, 4
Diagnostic(ErrorCode.WRN_ParameterDisallowsNull, "return false;").WithArguments("x").WithLocation(39, 9),
// (39,9): warning CS8762: Parameter 'y' must have a non-null value when exiting with 'false'.
// return false; // 3, 4
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return false;").WithArguments("y", "false").WithLocation(39, 9)
// (29,9): warning CS8762: Parameter 'y' must have a non-null value when exiting with 'true'.
// return y == null; // 2
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return y == null;").WithArguments("y", "true").WithLocation(29, 9),
// (41,9): warning CS8762: Parameter 'y' must have a non-null value when exiting with 'false'.
// return y != null; // 3
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return y != null;").WithArguments("y", "false").WithLocation(41, 9),
// (49,13): warning CS8777: Parameter 'x' must have a non-null value when exiting.
// return true; // 4
Diagnostic(ErrorCode.WRN_ParameterDisallowsNull, "return true;").WithArguments("x").WithLocation(49, 13),
// (51,9): warning CS8777: Parameter 'x' must have a non-null value when exiting.
// return false; // 5, 6
Diagnostic(ErrorCode.WRN_ParameterDisallowsNull, "return false;").WithArguments("x").WithLocation(51, 9),
// (51,9): warning CS8762: Parameter 'y' must have a non-null value when exiting with 'false'.
// return false; // 5, 6
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return false;").WithArguments("y", "false").WithLocation(51, 9)
);
}
...
...
@@ -140237,6 +140412,183 @@ void M()
Diagnostic(ErrorCode.ERR_DiscardTypeInferenceFailed, "_").WithLocation(10, 13));
}
[Fact, WorkItem(48126, "https://github.com/dotnet/roslyn/issues/48126")]
public void EnforcedInMethodBody_MaybeNullWhen_Issue_48126()
{
var source = @"
using System.Diagnostics.CodeAnalysis;
#nullable enable
class C
{
static bool NullWhenFalseA(bool a, [MaybeNullWhen(false)] out string s1)
{
s1 = null;
return a;
}
static bool NullWhenFalseNotA(bool a, [MaybeNullWhen(false)] out string s1)
{
s1 = null;
return !a;
}
static bool NullWhenTrueA(bool a, [MaybeNullWhen(true)] out string s1)
{
s1 = null;
return a;
}
static bool NullWhenTrueNotA(bool a, [MaybeNullWhen(true)] out string s1)
{
s1 = null;
return !a;
}
}";
var comp = CreateCompilation(new[] { source, MaybeNullWhenAttributeDefinition });
comp.VerifyEmitDiagnostics();
}
[Fact, WorkItem(48126, "https://github.com/dotnet/roslyn/issues/48126")]
public void EnforcedInMethodBody_MaybeNullWhen_Issue_48126_2()
{
var source = @"
using System.Diagnostics.CodeAnalysis;
#nullable enable
class C
{
static bool M1([MaybeNullWhen(false)] out string s1)
{
const bool b = true;
s1 = null;
return b; // 1
}
static bool M2([MaybeNullWhen(false)] out string s1)
{
s1 = null;
return (bool)true; // 2
}
}";
var comp = CreateCompilation(new[] { source, MaybeNullWhenAttributeDefinition });
comp.VerifyEmitDiagnostics(
// (12,9): warning CS8762: Parameter 's1' must have a non-null value when exiting with 'true'.
// return b; // 1
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return b;").WithArguments("s1", "true").WithLocation(12, 9),
// (18,9): warning CS8762: Parameter 's1' must have a non-null value when exiting with 'true'.
// return (bool)true; // 2
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return (bool)true;").WithArguments("s1", "true").WithLocation(18, 9)
);
}
[Fact, WorkItem(48126, "https://github.com/dotnet/roslyn/issues/48126")]
public void EnforcedInMethodBody_MaybeNullWhen_Issue_48126_3()
{
var source = @"
using System.Diagnostics.CodeAnalysis;
#nullable enable
class C
{
static bool M1([MaybeNullWhen(false)] out string s1)
{
const bool b = true;
s1 = null;
return b; // 1
}
static bool M2([MaybeNullWhen(false)] out string s1)
{
const bool b = true;
s1 = null;
return b && true; // 2
}
static bool M3([MaybeNullWhen(false)] out string s1)
{
const bool b = false;
s1 = null;
return b;
}
}";
var comp = CreateCompilation(new[] { source, MaybeNullWhenAttributeDefinition });
comp.VerifyEmitDiagnostics(
// (12,9): warning CS8762: Parameter 's1' must have a non-null value when exiting with 'true'.
// return b; // 1
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return b;").WithArguments("s1", "true").WithLocation(12, 9),
// (19,9): warning CS8762: Parameter 's1' must have a non-null value when exiting with 'true'.
// return b && true; // 2
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return b && true;").WithArguments("s1", "true").WithLocation(19, 9)
);
}
[Fact, WorkItem(48126, "https://github.com/dotnet/roslyn/issues/48126")]
public void EnforcedInMethodBody_MaybeNullWhen_Issue_48126_4()
{
var source = @"
using System.Diagnostics.CodeAnalysis;
#nullable enable
class C
{
static bool M1([MaybeNullWhen(false)] out string s1)
{
return M1(out s1);
}
static bool M2([MaybeNullWhen(false)] out string s1)
{
return !M1(out s1); // 1
}
static bool M3([MaybeNullWhen(true)] out string s1)
{
return !M1(out s1);
}
}";
var comp = CreateCompilation(new[] { source, MaybeNullWhenAttributeDefinition });
comp.VerifyEmitDiagnostics(
// (15,9): warning CS8762: Parameter 's1' must have a non-null value when exiting with 'true'.
// return !M1(out s1); // 1
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return !M1(out s1);").WithArguments("s1", "true").WithLocation(15, 9)
);
}
[Fact, WorkItem(48126, "https://github.com/dotnet/roslyn/issues/48126")]
public void EnforcedInMethodBody_MaybeNullWhen_Issue_48126_5()
{
var source = @"
using System.Diagnostics.CodeAnalysis;
#nullable enable
internal static class Program
{
public static bool M1([MaybeNullWhen(true)] out string s)
{
s = null;
return HasAnnotation(out _);
}
public static bool M2([MaybeNullWhen(true)] out string s)
{
s = null;
return NoAnnotations();
}
private static bool HasAnnotation([MaybeNullWhen(true)] out string s) { s = null; return true; }
private static bool NoAnnotations() => true;
}";
var comp = CreateCompilation(new[] { source, MaybeNullWhenAttributeDefinition });
comp.VerifyEmitDiagnostics();
}
[Fact]
[WorkItem(47221, "https://github.com/dotnet/roslyn/issues/47221")]
public void PropertyAccessorWithNullableContextAttribute_01()
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录