Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
ba91070c
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,发现更多精彩内容 >>
未验证
提交
ba91070c
编写于
4月 02, 2019
作者:
C
Charles Stoner
提交者:
GitHub
4月 02, 2019
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Assert MaybeNull is not used for value types other than Nullable<T> (#34630)
上级
ed576ba3
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
74 addition
and
44 deletion
+74
-44
src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs
src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs
+1
-1
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
+37
-33
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker_Patterns.cs
...s/CSharp/Portable/FlowAnalysis/NullableWalker_Patterns.cs
+2
-2
src/Compilers/CSharp/Portable/Symbols/TypeWithAnnotations.cs
src/Compilers/CSharp/Portable/Symbols/TypeWithAnnotations.cs
+1
-1
src/Compilers/CSharp/Portable/Symbols/TypeWithState.cs
src/Compilers/CSharp/Portable/Symbols/TypeWithState.cs
+29
-2
src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
...rp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
+4
-5
未找到文件。
src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs
浏览文件 @
ba91070c
...
...
@@ -841,7 +841,7 @@ private BoundPattern BindVarPattern(VarPatternSyntax node, TypeSymbol inputType,
}
case
SyntaxKind
.
SingleVariableDesignation
:
{
var
declType
=
new
TypeWithState
(
inputType
,
NullableFlowState
.
MaybeNull
).
ToTypeWithAnnotations
();
var
declType
=
TypeWithState
.
ForType
(
inputType
).
ToTypeWithAnnotations
();
BindPatternDesignation
(
designation
:
node
,
declType
:
declType
,
inputValEscape
:
inputValEscape
,
typeSyntax
:
null
,
diagnostics
:
diagnostics
,
hasErrors
:
ref
hasErrors
,
variableSymbol
:
out
Symbol
variableSymbol
,
variableAccess
:
out
BoundExpression
variableAccess
);
...
...
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
浏览文件 @
ba91070c
...
...
@@ -141,7 +141,7 @@ public VisitArgumentResult(VisitResult visitResult, Optional<LocalState> stateFo
/// Invalid type, used only to catch Visit methods that do not set
/// _result.Type. See VisitExpressionWithoutStackGuard.
/// </summary>
private
static
readonly
TypeWithState
_invalidType
=
new
TypeWithSt
ate
(
ErrorTypeSymbol
.
UnknownResultType
,
NullableFlowState
.
NotNull
);
private
static
readonly
TypeWithState
_invalidType
=
TypeWithState
.
Cre
ate
(
ErrorTypeSymbol
.
UnknownResultType
,
NullableFlowState
.
NotNull
);
/// <summary>
/// The result and l-value type of the last visited expression.
...
...
@@ -1409,7 +1409,7 @@ public override BoundNode VisitObjectCreationExpression(BoundObjectCreationExpre
VisitObjectCreationInitializer
(
null
,
slot
,
initializerOpt
);
}
ResultType
=
new
TypeWithSt
ate
(
type
,
resultState
);
ResultType
=
TypeWithState
.
Cre
ate
(
type
,
resultState
);
}
private
void
VisitObjectCreationInitializer
(
Symbol
containingSymbol
,
int
containingSlot
,
BoundExpression
node
)
...
...
@@ -1502,7 +1502,7 @@ private new void VisitCollectionElementInitializer(BoundCollectionElementInitial
private
void
SetNotNullResult
(
BoundExpression
node
)
{
ResultType
=
new
TypeWithSt
ate
(
node
.
Type
,
NullableFlowState
.
NotNull
);
ResultType
=
TypeWithState
.
Cre
ate
(
node
.
Type
,
NullableFlowState
.
NotNull
);
}
private
int
GetOrCreatePlaceholderSlot
(
BoundExpression
node
)
...
...
@@ -1552,7 +1552,7 @@ public override BoundNode VisitAnonymousObjectCreationExpression(BoundAnonymousO
}
}
ResultType
=
new
TypeWithSt
ate
(
anonymousType
,
NullableFlowState
.
NotNull
);
ResultType
=
TypeWithState
.
Cre
ate
(
anonymousType
,
NullableFlowState
.
NotNull
);
return
null
;
}
...
...
@@ -1563,7 +1563,7 @@ public override BoundNode VisitArrayCreation(BoundArrayCreation node)
VisitRvalue
(
expr
);
}
TypeSymbol
resultType
=
(
node
.
InitializerOpt
==
null
)
?
node
.
Type
:
VisitArrayInitializer
(
node
);
ResultType
=
new
TypeWithSt
ate
(
resultType
,
NullableFlowState
.
NotNull
);
ResultType
=
TypeWithState
.
Cre
ate
(
resultType
,
NullableFlowState
.
NotNull
);
return
null
;
}
...
...
@@ -1797,12 +1797,12 @@ private TypeWithState InferResultNullability(BinaryOperatorKind operatorKind, Me
}
}
if
(
operatorKind
.
IsLifted
())
if
(
operatorKind
.
IsLifted
()
&&
!
operatorKind
.
IsComparison
()
)
{
resultState
=
leftType
.
State
.
Join
(
rightType
.
State
);
}
return
new
TypeWithSt
ate
(
resultType
,
resultState
);
return
TypeWithState
.
Cre
ate
(
resultType
,
resultState
);
}
protected
override
void
AfterLeftChildHasBeenVisited
(
BoundBinaryOperator
binary
)
...
...
@@ -2104,7 +2104,7 @@ public override BoundNode VisitNullCoalescingOperator(BoundNullCoalescingOperato
rightResult
=
VisitRvalueWithState
(
rightOperand
);
// Should be able to use rightResult for the result of the operator but
// binding may have generated a different result type in the case of errors.
ResultType
=
new
TypeWithSt
ate
(
node
.
Type
,
rightResult
.
State
);
ResultType
=
TypeWithState
.
Cre
ate
(
node
.
Type
,
rightResult
.
State
);
return
null
;
}
...
...
@@ -2202,7 +2202,7 @@ private static NullableAnnotation GetNullableAnnotation(BoundExpression expr)
private
static
TypeWithState
GetNullCoalescingResultType
(
TypeWithState
rightResult
,
TypeSymbol
resultType
)
{
NullableFlowState
resultState
=
rightResult
.
State
;
return
new
TypeWithSt
ate
(
resultType
,
resultState
);
return
TypeWithState
.
Cre
ate
(
resultType
,
resultState
);
}
public
override
BoundNode
VisitConditionalAccess
(
BoundConditionalAccess
node
)
...
...
@@ -2230,6 +2230,7 @@ public override BoundNode VisitConditionalAccess(BoundConditionalAccess node)
var
accessExpressionType
=
VisitRvalueWithState
(
node
.
AccessExpression
);
Join
(
ref
this
.
State
,
ref
receiverState
);
// Per LDM 2019-02-13 decision, the result of a conditional access might be null even if
// both the receiver and right-hand-side are believed not to be null.
NullableFlowState
resultState
=
NullableFlowState
.
MaybeNull
;
...
...
@@ -2247,7 +2248,7 @@ public override BoundNode VisitConditionalAccess(BoundConditionalAccess node)
_currentConditionalReceiverVisitResult
=
default
;
_lastConditionalAccessSlot
=
previousConditionalAccessSlot
;
ResultType
=
new
TypeWithSt
ate
(
type
,
resultState
);
ResultType
=
TypeWithState
.
Cre
ate
(
type
,
resultState
);
return
null
;
}
...
...
@@ -2284,7 +2285,7 @@ public override BoundNode VisitConditionalOperator(BoundConditionalOperator node
var
lValueAnnotation
=
consequenceLValue
.
NullableAnnotation
.
EnsureCompatible
(
alternativeLValue
.
NullableAnnotation
);
var
rValueState
=
consequenceRValue
.
State
.
Join
(
alternativeRValue
.
State
);
SetResult
(
new
TypeWithSt
ate
(
refResultType
,
rValueState
),
TypeWithAnnotations
.
Create
(
refResultType
,
lValueAnnotation
));
SetResult
(
TypeWithState
.
Cre
ate
(
refResultType
,
rValueState
),
TypeWithAnnotations
.
Create
(
refResultType
,
lValueAnnotation
));
return
null
;
}
...
...
@@ -2379,7 +2380,7 @@ public override BoundNode VisitConditionalOperator(BoundConditionalOperator node
resultState
=
convertedConsequenceResult
.
State
.
Join
(
convertedAlternativeResult
.
State
);
}
ResultType
=
new
TypeWithSt
ate
(
resultType
,
resultState
);
ResultType
=
TypeWithState
.
Cre
ate
(
resultType
,
resultState
);
return
null
;
(
BoundExpression
,
Conversion
,
TypeWithState
)
visitConditionalOperand
(
LocalState
state
,
BoundExpression
operand
)
...
...
@@ -2444,7 +2445,7 @@ public override BoundNode VisitConditionalReceiver(BoundConditionalReceiver node
{
rvalueType
=
rvalueType
.
GetNullableUnderlyingType
();
}
ResultType
=
new
TypeWithSt
ate
(
rvalueType
,
NullableFlowState
.
NotNull
);
ResultType
=
TypeWithState
.
Cre
ate
(
rvalueType
,
NullableFlowState
.
NotNull
);
return
null
;
}
...
...
@@ -3373,7 +3374,7 @@ private TypeWithState GetAdjustedResult(TypeWithState type, int slot)
if
(
slot
>
0
&&
slot
<
this
.
State
.
Capacity
)
{
NullableFlowState
state
=
this
.
State
[
slot
];
return
new
TypeWithSt
ate
(
type
.
Type
,
state
);
return
TypeWithState
.
Cre
ate
(
type
.
Type
,
state
);
}
return
type
;
...
...
@@ -3608,7 +3609,7 @@ private void VisitTupleExpression(BoundTupleExpression node)
tupleOpt
=
tupleOpt
.
WithElementTypes
(
elementTypesWithAnnotations
);
var
locations
=
tupleOpt
.
TupleElements
.
SelectAsArray
((
element
,
location
)
=>
element
.
Locations
.
FirstOrDefault
()
??
location
,
node
.
Syntax
.
Location
);
tupleOpt
.
CheckConstraints
(
_conversions
,
includeNullability
:
true
,
node
.
Syntax
,
locations
,
compilation
,
diagnosticsOpt
:
null
,
nullabilityDiagnosticsOpt
:
Diagnostics
);
ResultType
=
new
TypeWithSt
ate
(
tupleOpt
,
NullableFlowState
.
NotNull
);
ResultType
=
TypeWithState
.
Cre
ate
(
tupleOpt
,
NullableFlowState
.
NotNull
);
}
}
...
...
@@ -3939,7 +3940,7 @@ private bool HasTopLevelNullabilityConversion(TypeWithAnnotations source, TypeWi
ReportNullabilityMismatchWithTargetDelegate
(
node
.
Syntax
,
delegateType
,
unboundLambda
);
}
return
new
TypeWithSt
ate
(
targetType
,
NullableFlowState
.
NotNull
);
return
TypeWithState
.
Cre
ate
(
targetType
,
NullableFlowState
.
NotNull
);
}
break
;
...
...
@@ -3962,6 +3963,9 @@ private bool HasTopLevelNullabilityConversion(TypeWithAnnotations source, TypeWi
break
;
case
ConversionKind
.
NoConversion
:
resultState
=
operandType
.
State
;
break
;
case
ConversionKind
.
DefaultOrNullLiteral
:
checkConversion
=
false
;
goto
case
ConversionKind
.
Identity
;
...
...
@@ -4117,7 +4121,7 @@ private bool HasTopLevelNullabilityConversion(TypeWithAnnotations source, TypeWi
resultState
=
NullableFlowState
.
MaybeNull
;
}
var
resultType
=
new
TypeWithSt
ate
(
targetType
,
resultState
);
var
resultType
=
TypeWithState
.
Cre
ate
(
targetType
,
resultState
);
if
(
operandType
.
Type
?.
IsErrorType
()
!=
true
&&
!
targetType
.
IsErrorType
())
{
...
...
@@ -4175,7 +4179,7 @@ private bool HasTopLevelNullabilityConversion(TypeWithAnnotations source, TypeWi
// cf. Binder.CreateUserDefinedConversion
if
(!
conversion
.
IsValid
)
{
return
new
TypeWithSt
ate
(
targetType
,
NullableFlowState
.
NotNull
);
return
TypeWithState
.
Cre
ate
(
targetType
,
NullableFlowState
.
NotNull
);
}
// operand -> conversion "from" type
...
...
@@ -4254,7 +4258,7 @@ private TypeWithState LiftedReturnType(TypeWithAnnotations returnType, NullableF
?
compilation
.
GetSpecialType
(
SpecialType
.
System_Nullable_T
).
Construct
(
ImmutableArray
.
Create
(
returnType
))
:
returnType
.
Type
;
NullableFlowState
state
=
returnType
.
ToTypeWithState
().
State
.
Join
(
operandState
);
return
new
TypeWithSt
ate
(
type
,
state
);
return
TypeWithState
.
Cre
ate
(
type
,
state
);
}
private
TypeWithState
ClassifyAndApplyConversion
(
...
...
@@ -4374,7 +4378,7 @@ public override BoundNode VisitThisReference(BoundThisReference node)
private
void
VisitThisOrBaseReference
(
BoundExpression
node
)
{
var
rvalueResult
=
new
TypeWithSt
ate
(
node
.
Type
,
NullableFlowState
.
NotNull
);
var
rvalueResult
=
TypeWithState
.
Cre
ate
(
node
.
Type
,
NullableFlowState
.
NotNull
);
var
lvalueResult
=
TypeWithAnnotations
.
Create
(
node
.
Type
,
NullableAnnotation
.
NotAnnotated
);
SetResult
(
rvalueResult
,
lvalueResult
);
}
...
...
@@ -4418,7 +4422,7 @@ public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node)
}
TrackNullableStateForAssignment
(
right
,
leftLValueType
,
MakeSlot
(
left
),
rightType
,
MakeSlot
(
right
));
SetResult
(
new
TypeWithSt
ate
(
leftLValueType
.
Type
,
rightType
.
State
),
leftLValueType
);
SetResult
(
TypeWithState
.
Cre
ate
(
leftLValueType
.
Type
,
rightType
.
State
),
leftLValueType
);
}
return
null
;
...
...
@@ -4578,7 +4582,7 @@ private void VisitDeconstructionArguments(ArrayBuilder<DeconstructionVariable> v
valueSlot
=
MakeSlot
(
rightPart
);
if
(
valueSlot
>
0
)
{
var
valueBeforeNullableWrapping
=
new
TypeWithSt
ate
(
underlyingType
.
Type
,
NullableFlowState
.
NotNull
);
var
valueBeforeNullableWrapping
=
TypeWithState
.
Cre
ate
(
underlyingType
.
Type
,
NullableFlowState
.
NotNull
);
TrackNullableStateOfNullableValue
(
targetSlot
,
targetType
.
Type
,
rightPart
,
valueBeforeNullableWrapping
,
valueSlot
);
}
}
...
...
@@ -4823,7 +4827,7 @@ public override BoundNode VisitCompoundAssignmentOperator(BoundCompoundAssignmen
}
else
{
resultType
=
new
TypeWithSt
ate
(
node
.
Type
,
NullableFlowState
.
NotNull
);
resultType
=
TypeWithState
.
Cre
ate
(
node
.
Type
,
NullableFlowState
.
NotNull
);
}
TrackNullableStateForAssignment
(
node
,
leftLValueType
,
MakeSlot
(
node
.
Left
),
resultType
);
...
...
@@ -4968,7 +4972,7 @@ private void VisitMemberAccess(BoundExpression node, BoundExpression receiverOpt
if
(
slot
>
0
&&
slot
<
this
.
State
.
Capacity
)
{
var
state
=
this
.
State
[
slot
];
resultType
=
new
TypeWithSt
ate
(
resultType
.
Type
,
state
);
resultType
=
TypeWithState
.
Cre
ate
(
resultType
.
Type
,
state
);
}
}
...
...
@@ -5147,7 +5151,7 @@ public override BoundNode VisitUnaryOperator(BoundUnaryOperator node)
}
else
{
resultType
=
new
TypeWithSt
ate
(
node
.
Type
,
node
.
OperatorKind
.
IsLifted
()
?
argumentResult
.
State
:
NullableFlowState
.
NotNull
);
resultType
=
TypeWithState
.
Cre
ate
(
node
.
Type
,
node
.
OperatorKind
.
IsLifted
()
?
argumentResult
.
State
:
NullableFlowState
.
NotNull
);
}
ResultType
=
resultType
;
...
...
@@ -5198,7 +5202,7 @@ private TypeWithState InferResultNullability(BoundUserDefinedConditionalLogicalO
{
// https://github.com/dotnet/roslyn/issues/33879 Conversions: Lifted operator
// Should this use the updated flow type and state? How should it compute nullability?
return
new
TypeWithSt
ate
(
node
.
Type
,
NullableFlowState
.
NotNull
);
return
TypeWithState
.
Cre
ate
(
node
.
Type
,
NullableFlowState
.
NotNull
);
}
// Update method based on inferred operand types: see https://github.com/dotnet/roslyn/issues/29605.
...
...
@@ -5302,7 +5306,7 @@ public override BoundNode VisitAwaitExpression(BoundAwaitExpression node)
public
override
BoundNode
VisitTypeOfOperator
(
BoundTypeOfOperator
node
)
{
var
result
=
base
.
VisitTypeOfOperator
(
node
);
ResultType
=
new
TypeWithSt
ate
(
node
.
Type
,
NullableFlowState
.
NotNull
);
ResultType
=
TypeWithState
.
Cre
ate
(
node
.
Type
,
NullableFlowState
.
NotNull
);
return
result
;
}
...
...
@@ -5402,7 +5406,7 @@ public override BoundNode VisitAsOperator(BoundAsOperator node)
}
}
ResultType
=
new
TypeWithSt
ate
(
type
,
resultState
);
ResultType
=
TypeWithState
.
Cre
ate
(
type
,
resultState
);
return
null
;
}
...
...
@@ -5434,7 +5438,7 @@ public override BoundNode VisitLiteral(BoundLiteral node)
var
result
=
base
.
VisitLiteral
(
node
);
Debug
.
Assert
(!
IsConditionalState
);
ResultType
=
new
TypeWithSt
ate
(
node
.
Type
,
node
.
Type
?.
CanContainNull
()
!=
false
&&
node
.
ConstantValue
?.
IsNull
==
true
?
NullableFlowState
.
MaybeNull
:
NullableFlowState
.
NotNull
);
ResultType
=
TypeWithState
.
Cre
ate
(
node
.
Type
,
node
.
Type
?.
CanContainNull
()
!=
false
&&
node
.
ConstantValue
?.
IsNull
==
true
?
NullableFlowState
.
MaybeNull
:
NullableFlowState
.
NotNull
);
return
result
;
}
...
...
@@ -5570,7 +5574,7 @@ public override BoundNode VisitAnonymousPropertyDeclaration(BoundAnonymousProper
public
override
BoundNode
VisitNoPiaObjectCreationExpression
(
BoundNoPiaObjectCreationExpression
node
)
{
var
result
=
base
.
VisitNoPiaObjectCreationExpression
(
node
);
ResultType
=
new
TypeWithSt
ate
(
node
.
Type
,
NullableFlowState
.
NotNull
);
ResultType
=
TypeWithState
.
Cre
ate
(
node
.
Type
,
NullableFlowState
.
NotNull
);
return
result
;
}
...
...
@@ -5679,7 +5683,7 @@ public override BoundNode VisitQueryClause(BoundQueryClause node)
public
override
BoundNode
VisitNameOfOperator
(
BoundNameOfOperator
node
)
{
var
result
=
base
.
VisitNameOfOperator
(
node
);
ResultType
=
new
TypeWithSt
ate
(
node
.
Type
,
NullableFlowState
.
NotNull
);
ResultType
=
TypeWithState
.
Cre
ate
(
node
.
Type
,
NullableFlowState
.
NotNull
);
return
result
;
}
...
...
@@ -5693,7 +5697,7 @@ public override BoundNode VisitNamespaceExpression(BoundNamespaceExpression node
public
override
BoundNode
VisitInterpolatedString
(
BoundInterpolatedString
node
)
{
var
result
=
base
.
VisitInterpolatedString
(
node
);
ResultType
=
new
TypeWithSt
ate
(
node
.
Type
,
NullableFlowState
.
NotNull
);
ResultType
=
TypeWithState
.
Cre
ate
(
node
.
Type
,
NullableFlowState
.
NotNull
);
return
result
;
}
...
...
@@ -5714,7 +5718,7 @@ public override BoundNode VisitConvertedStackAllocExpression(BoundConvertedStack
public
override
BoundNode
VisitDiscardExpression
(
BoundDiscardExpression
node
)
{
var
result
=
TypeWithAnnotations
.
Create
(
node
.
Type
);
var
rValueType
=
new
TypeWithState
(
node
.
Type
,
NullableFlowState
.
MaybeNull
);
var
rValueType
=
TypeWithState
.
ForType
(
node
.
Type
);
SetResult
(
rValueType
,
result
);
return
null
;
}
...
...
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker_Patterns.cs
浏览文件 @
ba91070c
...
...
@@ -211,7 +211,7 @@ protected override LocalState VisitSwitchStatementDispatch(BoundSwitchStatement
break
;
}
State
[
outputSlot
]
=
NullableFlowState
.
NotNull
;
var
outputType
=
new
TypeWithSt
ate
(
e
.
Type
,
inputState
);
var
outputType
=
TypeWithState
.
Cre
ate
(
e
.
Type
,
inputState
);
addToTempMap
(
output
,
outputSlot
,
outputType
.
Type
);
break
;
}
...
...
@@ -323,7 +323,7 @@ protected override LocalState VisitSwitchStatementDispatch(BoundSwitchStatement
var
tempState
=
this
.
State
[
tempSlot
];
if
(
variableAccess
is
BoundLocal
{
LocalSymbol
:
SourceLocalSymbol
{
IsVar
:
true
}
local
})
{
var
inferredType
=
new
TypeWithSt
ate
(
tempType
,
tempState
).
ToTypeWithAnnotations
();
var
inferredType
=
TypeWithState
.
Cre
ate
(
tempType
,
tempState
).
ToTypeWithAnnotations
();
if
(
_variableTypes
.
TryGetValue
(
local
,
out
var
existingType
))
{
// merge inferred nullable annotation from different branches of the decision tree
...
...
src/Compilers/CSharp/Portable/Symbols/TypeWithAnnotations.cs
浏览文件 @
ba91070c
...
...
@@ -711,7 +711,7 @@ internal TypeWithState ToTypeWithState()
// Reading from a variable of a type parameter (that could be substituted with a nullable type), but which
// cannot itself be annotated (because it isn't known to be a reference type), may yield a null value
// even though the type parameter isn't annotated.
return
new
TypeWithSt
ate
(
return
TypeWithState
.
Cre
ate
(
Type
,
IsPossiblyNullableTypeTypeParameter
()
||
NullableAnnotation
.
IsAnnotated
()
?
NullableFlowState
.
MaybeNull
:
NullableFlowState
.
NotNull
);
}
...
...
src/Compilers/CSharp/Portable/Symbols/TypeWithState.cs
浏览文件 @
ba91070c
...
...
@@ -15,12 +15,39 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols
public
bool
HasNullType
=>
Type
is
null
;
public
bool
MayBeNull
=>
State
==
NullableFlowState
.
MaybeNull
;
public
bool
IsNotNull
=>
State
==
NullableFlowState
.
NotNull
;
public
static
TypeWithState
ForType
(
TypeSymbol
type
)
=>
new
TypeWithState
(
type
,
type
?.
CanContainNull
()
==
true
?
NullableFlowState
.
MaybeNull
:
NullableFlowState
.
NotNull
);
public
TypeWithState
(
TypeSymbol
type
,
NullableFlowState
state
)
=>
(
Type
,
State
)
=
(
type
,
state
);
private
static
bool
CanContainNull
(
TypeSymbol
type
)
{
return
type
is
null
||
!
type
.
IsValueType
||
type
.
IsNullableTypeOrTypeParameter
();
}
public
static
TypeWithState
ForType
(
TypeSymbol
type
)
{
var
state
=
CanContainNull
(
type
)
?
NullableFlowState
.
MaybeNull
:
NullableFlowState
.
NotNull
;
return
new
TypeWithState
(
type
,
state
);
}
public
static
TypeWithState
Create
(
TypeSymbol
type
,
NullableFlowState
defaultState
)
{
var
state
=
defaultState
==
NullableFlowState
.
MaybeNull
&&
CanContainNull
(
type
)
?
NullableFlowState
.
MaybeNull
:
NullableFlowState
.
NotNull
;
return
new
TypeWithState
(
type
,
state
);
}
private
TypeWithState
(
TypeSymbol
type
,
NullableFlowState
state
)
{
Debug
.
Assert
(
state
==
NullableFlowState
.
NotNull
||
CanContainNull
(
type
));
Type
=
type
;
State
=
state
;
}
public
void
Deconstruct
(
out
TypeSymbol
type
,
out
NullableFlowState
state
)
=>
(
type
,
state
)
=
(
Type
,
State
);
public
string
GetDebuggerDisplay
()
=>
$"
{{
Type
:{
Type
?.
GetDebuggerDisplay
()},
State
:{
State
}{
"}"
}
";
public
override
string
ToString
()
=>
GetDebuggerDisplay
();
public
TypeWithState
WithNotNullState
()
=>
new
TypeWithState
(
Type
,
NullableFlowState
.
NotNull
);
public
TypeWithAnnotations
ToTypeWithAnnotations
()
{
NullableAnnotation
annotation
=
this
.
State
.
IsNotNull
()
||
Type
?.
CanContainNull
()
==
false
||
Type
?.
IsTypeParameterDisallowingAnnotation
()
==
true
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
浏览文件 @
ba91070c
...
...
@@ -79998,7 +79998,7 @@ static void F3(int? ni)
}
else
{
_ = (S)ni; //
1
_ = (S)ni; //
3
}
}
}";
...
...
@@ -80011,7 +80011,7 @@ static void F3(int? ni)
// _ = s4.Value; // 2
Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4").WithLocation(33, 17),
// (45,20): warning CS8629: Nullable value type may be null.
// _ = (S)ni; //
1
// _ = (S)ni; //
3
Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ni").WithLocation(45, 20)
);
}
...
...
@@ -81721,9 +81721,8 @@ internal override void F<U>(int? t)
// o.ToString(); // 1
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o").WithLocation(11, 9),
// (21,9): warning CS8602: Dereference of a possibly null reference.
// o.ToString();
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o").WithLocation(21, 9)
);
// o.ToString(); // 2
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o").WithLocation(21, 9));
}
[Fact]
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录