Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
4f64ad5f
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,发现更多精彩内容 >>
提交
4f64ad5f
编写于
2月 27, 2019
作者:
N
Neal Gafter
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Minor changes per code review.
上级
7e325b52
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
47 addition
and
47 deletion
+47
-47
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
+36
-36
src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
...rp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
+11
-11
未找到文件。
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
浏览文件 @
4f64ad5f
...
...
@@ -130,6 +130,14 @@ private TypeWithState ResultType
}
}
/// <summary>
/// Force the inference of the LValueResultType from ResultType.
/// </summary>
private
void
UseRvalueOnly
()
{
ResultType
=
ResultType
;
}
private
TypeSymbolWithAnnotations
LvalueResultType
{
get
=>
_visitResult
.
LValueType
;
...
...
@@ -139,6 +147,14 @@ private TypeSymbolWithAnnotations LvalueResultType
}
}
/// <summary>
/// Force the inference of the ResultType from LValueResultType.
/// </summary>
private
void
UseLvalueOnly
()
{
LvalueResultType
=
LvalueResultType
;
}
private
void
SetResult
(
TypeWithState
resultType
,
TypeSymbolWithAnnotations
lvalueType
)
{
_visitResult
=
new
VisitResult
(
resultType
,
lvalueType
);
...
...
@@ -455,7 +471,7 @@ private Symbol GetBackingFieldIfStructProperty(Symbol symbol)
protected
override
int
GetOrCreateSlot
(
Symbol
symbol
,
int
containingSlot
=
0
)
{
symbol
=
GetBackingFieldIfStructProperty
(
symbol
);
if
(
(
object
)
symbol
==
null
)
if
(
symbol
is
null
)
{
return
-
1
;
}
...
...
@@ -605,7 +621,7 @@ protected override void VisitRvalue(BoundExpression node)
{
Visit
(
node
);
Unsplit
();
ResultType
=
ResultType
;
// drop lvalue part
UseRvalueOnly
()
;
// drop lvalue part
}
private
TypeWithState
VisitRvalueWithState
(
BoundExpression
node
)
...
...
@@ -1434,7 +1450,7 @@ private int GetOrCreateObjectCreationPlaceholderSlot(BoundExpression node)
_placeholderLocalsOpt
.
TryGetValue
(
node
,
out
placeholder
);
}
if
(
(
object
)
placeholder
==
null
)
if
(
placeholder
is
null
)
{
placeholder
=
new
ObjectCreationPlaceholderLocal
(
_symbol
,
node
);
_placeholderLocalsOpt
.
Add
(
node
,
placeholder
);
...
...
@@ -2632,7 +2648,7 @@ private VisitResult VisitArgumentEvaluate(ImmutableArray<BoundExpression> argume
{
Visit
(
argument
);
// No Unsplit
ResultType
=
ResultType
;
// force use of flow result
UseRvalueOnly
()
;
// force use of flow result
}
else
{
...
...
@@ -2645,7 +2661,7 @@ private VisitResult VisitArgumentEvaluate(ImmutableArray<BoundExpression> argume
Visit
(
argument
);
// We'll want to use the l-value type, rather than the result type, for method re-inference
LvalueResultType
=
LvalueResultType
;
UseLvalueOnly
()
;
break
;
}
...
...
@@ -3241,7 +3257,7 @@ private static Symbol AsMemberOfType(TypeSymbol type, Symbol symbol)
Debug
.
Assert
((
object
)
symbol
!=
null
);
var
containingType
=
type
as
NamedTypeSymbol
;
if
(
(
object
)
containingType
==
null
||
containingType
.
IsErrorType
()
||
symbol
is
ErrorMethodSymbol
)
if
(
containingType
is
null
||
containingType
.
IsErrorType
()
||
symbol
is
ErrorMethodSymbol
)
{
return
symbol
;
}
...
...
@@ -3281,7 +3297,7 @@ private static Symbol AsMemberOfType(TypeSymbol type, Symbol symbol)
return
result
;
}
containingType
=
containingType
.
BaseTypeNoUseSiteDiagnostics
;
if
(
(
object
)
containingType
==
null
)
if
(
containingType
is
null
)
{
break
;
}
...
...
@@ -3430,7 +3446,7 @@ private void VisitTupleExpression(BoundTupleExpression node)
{
var
arguments
=
node
.
Arguments
;
ImmutableArray
<
TypeWithState
>
elementTypes
=
arguments
.
SelectAsArray
((
a
,
w
)
=>
w
.
VisitRvalueWithState
(
a
),
this
);
ImmutableArray
<
TypeSymbolWithAnnotations
>
elementTypesWithAnnotations
=
elementTypes
.
SelectAsArray
(
(
a
,
w
)
=>
a
.
ToTypeSymbolWithAnnotations
(),
this
);
ImmutableArray
<
TypeSymbolWithAnnotations
>
elementTypesWithAnnotations
=
elementTypes
.
SelectAsArray
(
a
=>
a
.
ToTypeSymbolWithAnnotations
()
);
var
tupleOpt
=
(
TupleTypeSymbol
)
node
.
Type
;
if
(
tupleOpt
is
null
)
{
...
...
@@ -4401,7 +4417,7 @@ public override BoundNode VisitIncrementOperator(BoundIncrementOperator node)
}
TypeWithState
resultOfIncrementType
;
if
(
(
object
)
incrementOperator
==
null
)
if
(
incrementOperator
is
null
)
{
resultOfIncrementType
=
resultOfOperandConversionType
;
}
...
...
@@ -4918,7 +4934,7 @@ protected override void AfterLeftChildOfBinaryLogicalOperatorHasBeenVisited(Boun
throw
ExceptionUtilities
.
UnexpectedValue
(
node
.
Kind
);
}
Debug
.
Assert
(
(
object
)
trueFalseOperator
==
null
||
((
object
)
logicalOperator
!=
null
&&
left
!=
null
));
Debug
.
Assert
(
trueFalseOperator
is
null
||
((
object
)
logicalOperator
!=
null
&&
left
!=
null
));
if
((
object
)
trueFalseOperator
!=
null
)
{
...
...
@@ -4961,7 +4977,7 @@ public override BoundNode VisitAwaitExpression(BoundAwaitExpression node)
{
var
result
=
base
.
VisitAwaitExpression
(
node
);
CheckPossibleNullReceiver
(
node
.
Expression
);
if
(
node
.
Type
.
IsValueType
||
node
.
HasErrors
||
(
object
)
node
.
AwaitableInfo
.
GetResult
==
null
)
if
(
node
.
Type
.
IsValueType
||
node
.
HasErrors
||
node
.
AwaitableInfo
.
GetResult
is
null
)
{
SetNotNullResult
(
node
);
}
...
...
@@ -5058,28 +5074,13 @@ public override BoundNode VisitAsOperator(BoundAsOperator node)
if
(
type
.
CanContainNull
())
{
var
operandType
=
argumentType
;
switch
(
node
.
Conversion
.
Kind
)
{
case
ConversionKind
.
Identity
:
// Inherit nullability from the operand
resultState
=
operandType
.
State
;
break
;
case
ConversionKind
.
ImplicitReference
:
// Inherit nullability from the operand
resultState
=
operandType
.
State
;
break
;
case
ConversionKind
.
Boxing
:
// Inherit nullability from the operand
resultState
=
operandType
.
State
;
break
;
case
ConversionKind
.
ImplicitNullable
:
// conversion of a value of type `X` to the type `Nullable<X>`
// conversion of a value of type `int?` to the type `long?`
resultState
=
operandType
.
State
;
resultState
=
argumentType
.
State
;
break
;
default
:
...
...
@@ -5114,7 +5115,7 @@ public override BoundNode VisitArgList(BoundArgList node)
public
override
BoundNode
VisitArgListOperator
(
BoundArgListOperator
node
)
{
VisitArgumentsEvaluate
(
node
.
Arguments
,
node
.
ArgumentRefKindsOpt
);
Debug
.
Assert
(
(
object
)
node
.
Type
==
null
);
Debug
.
Assert
(
node
.
Type
is
null
);
SetNotNullResult
(
node
);
return
null
;
}
...
...
@@ -5293,7 +5294,7 @@ private void SetUnknownResultNullability()
public
override
BoundNode
VisitStackAllocArrayCreation
(
BoundStackAllocArrayCreation
node
)
{
var
result
=
base
.
VisitStackAllocArrayCreation
(
node
);
Debug
.
Assert
(
(
object
)
node
.
Type
==
null
||
node
.
Type
.
IsPointerType
()
||
node
.
Type
.
IsRefLikeType
);
Debug
.
Assert
(
node
.
Type
is
null
||
node
.
Type
.
IsPointerType
()
||
node
.
Type
.
IsRefLikeType
);
SetNotNullResult
(
node
);
return
result
;
}
...
...
@@ -5313,8 +5314,7 @@ public override BoundNode VisitDynamicIndexerAccess(BoundDynamicIndexerAccess no
NullableAnnotation
nullableAnnotation
=
(
object
)
node
.
Type
!=
null
&&
!
node
.
Type
.
IsValueType
?
InferResultNullabilityFromApplicableCandidates
(
StaticCast
<
Symbol
>.
From
(
node
.
ApplicableIndexers
))
:
NullableAnnotation
.
Unknown
;
var
result
=
TypeSymbolWithAnnotations
.
Create
(
node
.
Type
,
nullableAnnotation
);
LvalueResultType
=
result
;
LvalueResultType
=
TypeSymbolWithAnnotations
.
Create
(
node
.
Type
,
nullableAnnotation
);
return
null
;
}
...
...
@@ -5323,18 +5323,18 @@ private void CheckPossibleNullReceiver(BoundExpression receiverOpt, bool checkNu
Debug
.
Assert
(!
this
.
IsConditionalState
);
if
(
receiverOpt
!=
null
&&
this
.
State
.
Reachable
)
{
var
resultType
=
ResultType
.
Type
;
if
(
resultType
is
null
)
var
resultType
Symbol
=
ResultType
.
Type
;
if
(
resultType
Symbol
is
null
)
{
return
;
}
#if DEBUG
Debug
.
Assert
(
receiverOpt
.
Type
is
null
||
AreCloseEnough
(
receiverOpt
.
Type
,
resultType
));
Debug
.
Assert
(
receiverOpt
.
Type
is
null
||
AreCloseEnough
(
receiverOpt
.
Type
,
resultType
Symbol
));
#endif
if
(
ResultType
.
MaybeNull
)
{
bool
isValueType
=
resultType
.
IsValueType
;
if
(
isValueType
&&
(!
checkNullableValueType
||
!
resultType
.
IsNullableTypeOrTypeParameter
()
||
resultType
.
GetNullableUnderlyingType
().
IsErrorType
()))
bool
isValueType
=
resultType
Symbol
.
IsValueType
;
if
(
isValueType
&&
(!
checkNullableValueType
||
!
resultType
Symbol
.
IsNullableTypeOrTypeParameter
()
||
resultTypeSymbol
.
GetNullableUnderlyingType
().
IsErrorType
()))
{
return
;
}
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
浏览文件 @
4f64ad5f
...
...
@@ -38351,6 +38351,9 @@ static void F1<T1>(T1 t1)
}";
var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue());
comp.VerifyDiagnostics(
// (5,9): warning CS8653: A default expression introduces a null value when 'T1' is a non-nullable reference type.
// default(T1).ToString(); // 1
Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T1)").WithArguments("T1").WithLocation(5, 9),
// (5,9): warning CS8602: Possible dereference of a null reference.
// default(T1).ToString(); // 1
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "default(T1)").WithLocation(5, 9),
...
...
@@ -65919,7 +65922,7 @@ class Outer
void M0<T>(T x0, T y0)
{
if (y0 == null) return;
(x0 ?? y0)
?
.ToString();
(x0 ?? y0).ToString();
}
}
";
...
...
@@ -77949,8 +77952,9 @@ public void BestType_DifferentTupleNullability_10()
comp.VerifyTypes();
}
[Fact
(Skip = "https://github.com/dotnet/roslyn/issues/33344")
]
[Fact]
[WorkItem(32575, "https://github.com/dotnet/roslyn/issues/32575")]
[WorkItem(33344, "https://github.com/dotnet/roslyn/issues/33344")]
public void BestType_DifferentTupleNullability_11()
{
var source =
...
...
@@ -77959,23 +77963,19 @@ public void BestType_DifferentTupleNullability_11()
static void F<T, U>(T t, U u)
where U : class
{
var x = new[] { (t, u), default }[0]/*T:(T t, U
? u)*/;
var x = new[] { (t, u), default }[0]/*T:(T t, U
u)*/; // should be (T t, U? u)
x.Item1.ToString(); // 1
x.Item2.ToString(); // 2
var y = new[] { default, (t, u) }[0]/*T:(T t, U
? u)*/;
var y = new[] { default, (t, u) }[0]/*T:(T t, U
u)*/; // should be (T t, U? u)
y.Item1.ToString(); // 3
y.Item2.ToString(); // 4
}
}";
var comp = CreateCompilation(source, options: WithNonNullTypesTrue());
// https://github.com/dotnet/roslyn/issues/32575: Not handling default for U.
comp.VerifyDiagnostics(
// (7,9): warning CS8602: Possible dereference of a null reference.
// x.Item1.ToString(); // 1
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Item1").WithLocation(7, 9),
// (10,9): warning CS8602: Possible dereference of a null reference.
// y.Item1.ToString(); // 3
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Item1").WithLocation(10, 9));
// https://github.com/dotnet/roslyn/issues/32575: Not handling default for U.
// SHOULD BE 4 diagnostics.
);
comp.VerifyTypes();
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录