Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
87f4c9df
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,发现更多精彩内容 >>
未验证
提交
87f4c9df
编写于
9月 16, 2020
作者:
J
Julien Couvreur
提交者:
GitHub
9月 16, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Typeless expressions should contribute nullability to lambda return (#47581)
上级
1d69a1dc
变更
7
展开全部
隐藏空白更改
内联
并排
Showing
7 changed file
with
564 addition
and
48 deletion
+564
-48
src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
+0
-2
src/Compilers/CSharp/Portable/Binder/Semantics/BestTypeInferrer.cs
...lers/CSharp/Portable/Binder/Semantics/BestTypeInferrer.cs
+9
-2
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
+9
-15
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker_Patterns.cs
...s/CSharp/Portable/FlowAnalysis/NullableWalker_Patterns.cs
+24
-17
src/Compilers/CSharp/Portable/Symbols/TypeWithAnnotations.cs
src/Compilers/CSharp/Portable/Symbols/TypeWithAnnotations.cs
+1
-1
src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
...rp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
+520
-10
src/Compilers/CSharp/Test/Symbol/Symbols/Source/NullablePublicAPITests.cs
...harp/Test/Symbol/Symbols/Source/NullablePublicAPITests.cs
+1
-1
未找到文件。
src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
浏览文件 @
87f4c9df
...
...
@@ -505,8 +505,6 @@ private BoundExpression CreateMethodGroupConversion(SyntaxNode syntax, BoundExpr
_
=>
throw
ExceptionUtilities
.
UnexpectedValue
(
source
),
};
BoundMethodGroup
group
=
FixMethodGroupWithTypeOrValue
(
originalGroup
,
conversion
,
diagnostics
);
BoundExpression
?
receiverOpt
=
group
.
ReceiverOpt
;
MethodSymbol
?
method
=
conversion
.
Method
;
bool
hasErrors
=
false
;
if
(
MethodGroupConversionHasErrors
(
syntax
,
conversion
,
group
.
ReceiverOpt
,
conversion
.
IsExtensionMethod
,
destination
,
diagnostics
))
...
...
src/Compilers/CSharp/Portable/Binder/Semantics/BestTypeInferrer.cs
浏览文件 @
87f4c9df
...
...
@@ -5,6 +5,7 @@
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Diagnostics
;
using
System.Linq
;
using
Microsoft.CodeAnalysis.CSharp.Symbols
;
using
Microsoft.CodeAnalysis.PooledObjects
;
...
...
@@ -14,11 +15,17 @@ internal static class BestTypeInferrer
{
public
static
NullableAnnotation
GetNullableAnnotation
(
ArrayBuilder
<
TypeWithAnnotations
>
types
)
{
#if DEBUG
var
example
=
types
.
FirstOrDefault
(
t
=>
t
.
HasType
);
#endif
var
result
=
NullableAnnotation
.
NotAnnotated
;
foreach
(
var
type
in
types
)
{
Debug
.
Assert
(
type
.
HasType
);
Debug
.
Assert
(
type
.
Equals
(
types
[
0
],
TypeCompareKind
.
AllIgnoreOptions
));
#if DEBUG
Debug
.
Assert
(!
type
.
HasType
||
type
.
Equals
(
example
,
TypeCompareKind
.
AllIgnoreOptions
));
#endif
// This uses the covariant merging rules.
result
=
result
.
Join
(
type
.
NullableAnnotation
);
}
...
...
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
浏览文件 @
87f4c9df
...
...
@@ -2842,11 +2842,9 @@ protected override void VisitStatement(BoundStatement statement)
public
override
BoundNode
?
VisitUnconvertedObjectCreationExpression
(
BoundUnconvertedObjectCreationExpression
node
)
{
var
discardedDiagnostics
=
new
DiagnosticBag
();
var
expr
=
_binder
!.
BindObjectCreationForErrorRecovery
(
node
,
discardedDiagnostics
);
discardedDiagnostics
.
Free
();
Visit
(
expr
);
SetResultType
(
node
,
TypeWithState
.
Create
(
expr
.
Type
,
NullableFlowState
.
NotNull
));
// This method is only involved in method inference with unbound lambdas.
// The diagnostics on arguments are reported by VisitObjectCreationExpression.
SetResultType
(
node
,
TypeWithState
.
Create
(
null
,
NullableFlowState
.
NotNull
));
return
null
;
}
...
...
@@ -4108,8 +4106,6 @@ private static TypeWithState GetNullCoalescingResultType(TypeWithState rightResu
BoundExpression
originalConsequence
,
BoundExpression
originalAlternative
)
{
Debug
.
Assert
(
node
.
Type
is
object
);
VisitCondition
(
condition
);
var
consequenceState
=
this
.
StateWhenTrue
;
var
alternativeState
=
this
.
StateWhenFalse
;
...
...
@@ -4127,7 +4123,7 @@ private static TypeWithState GetNullCoalescingResultType(TypeWithState rightResu
(
alternativeLValue
,
alternativeRValue
)
=
visitConditionalRefOperand
(
alternativeState
,
originalAlternative
);
Join
(
ref
this
.
State
,
ref
consequenceState
);
TypeSymbol
refResultType
=
node
.
Type
.
SetUnknownNullabilityForReferenceTypes
();
TypeSymbol
?
refResultType
=
node
.
Type
?
.
SetUnknownNullabilityForReferenceTypes
();
if
(
IsNullabilityMismatch
(
consequenceLValue
,
alternativeLValue
))
{
// l-value types must match
...
...
@@ -4204,8 +4200,8 @@ private static TypeWithState GetNullCoalescingResultType(TypeWithState rightResu
NullableFlowState
resultState
;
if
(
resultType
is
null
)
{
resultType
=
node
.
Type
.
SetUnknownNullabilityForReferenceTypes
();
resultState
=
NullableFlowState
.
NotNull
;
resultType
=
node
.
Type
?
.
SetUnknownNullabilityForReferenceTypes
();
resultState
=
consequenceRValue
.
State
.
Join
(
alternativeRValue
.
State
)
;
var
resultTypeWithState
=
TypeWithState
.
Create
(
resultType
,
resultState
);
...
...
@@ -6541,9 +6537,7 @@ private bool HasTopLevelNullabilityConversion(TypeWithAnnotations source, TypeWi
case
ConversionKind
.
ObjectCreation
:
case
ConversionKind
.
SwitchExpression
:
case
ConversionKind
.
ConditionalExpression
:
// These are not represented as a separate conversion in the bound tree.
// Instead they are folded into the operand.
throw
ExceptionUtilities
.
UnexpectedValue
(
conversion
.
Kind
);
return
operandType
;
case
ConversionKind
.
ExplicitUserDefined
:
case
ConversionKind
.
ImplicitUserDefined
:
...
...
@@ -8795,9 +8789,9 @@ private TypeWithState InferResultNullabilityOfBinaryLogicalOperator(BoundExpress
public
override
BoundNode
?
VisitDefaultLiteral
(
BoundDefaultLiteral
node
)
{
// Can occur in error scenarios
// Can occur in error scenarios
and lambda scenarios
var
result
=
base
.
VisitDefaultLiteral
(
node
);
Set
UnknownResultNullability
(
node
);
Set
ResultType
(
node
,
TypeWithState
.
Create
(
node
.
Type
,
NullableFlowState
.
MaybeDefault
)
);
return
result
;
}
...
...
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker_Patterns.cs
浏览文件 @
87f4c9df
...
...
@@ -566,6 +566,7 @@ public override BoundNode VisitConvertedSwitchExpression(BoundConvertedSwitchExp
public
override
BoundNode
VisitUnconvertedSwitchExpression
(
BoundUnconvertedSwitchExpression
node
)
{
// This method is only involved in method inference with unbound lambdas.
VisitSwitchExpressionCore
(
node
,
inferType
:
true
);
return
null
;
}
...
...
@@ -632,34 +633,40 @@ private void VisitSwitchExpressionCore(BoundSwitchExpression node, bool inferTyp
TypeSymbol
inferredType
=
(
inferType
?
BestTypeInferrer
.
InferBestType
(
placeholders
,
_conversions
,
ref
useSiteDiagnostics
)
:
null
)
??
node
.
Type
?.
SetUnknownNullabilityForReferenceTypes
()
??
new
ExtendedErrorTypeSymbol
(
this
.
compilation
,
""
,
arity
:
0
,
errorInfo
:
null
,
unreported
:
false
);
??
node
.
Type
?.
SetUnknownNullabilityForReferenceTypes
();
var
inferredTypeWithAnnotations
=
TypeWithAnnotations
.
Create
(
inferredType
);
// Convert elements to best type to determine element top-level nullability and to report nested nullability warnings
for
(
int
i
=
0
;
i
<
numSwitchArms
;
i
++
)
if
(
inferredType
is
not
null
)
{
var
expression
=
expressions
[
i
];
resultTypes
[
i
]
=
VisitConversion
(
conversionOpt
:
null
,
expression
,
conversions
[
i
],
inferredTypeWithAnnotations
,
resultTypes
[
i
],
checkConversion
:
true
,
fromExplicitCast
:
false
,
useLegacyWarnings
:
false
,
AssignmentKind
.
Assignment
,
reportRemainingWarnings
:
true
,
reportTopLevelWarnings
:
false
);
for
(
int
i
=
0
;
i
<
numSwitchArms
;
i
++)
{
var
expression
=
expressions
[
i
];
resultTypes
[
i
]
=
VisitConversion
(
conversionOpt
:
null
,
expression
,
conversions
[
i
],
inferredTypeWithAnnotations
,
resultTypes
[
i
],
checkConversion
:
true
,
fromExplicitCast
:
false
,
useLegacyWarnings
:
false
,
AssignmentKind
.
Assignment
,
reportRemainingWarnings
:
true
,
reportTopLevelWarnings
:
false
);
}
}
var
inferredState
=
BestTypeInferrer
.
GetNullableState
(
resultTypes
);
var
resultType
=
TypeWithState
.
Create
(
inferredType
,
inferredState
);
inferredTypeWithAnnotations
=
resultType
.
ToTypeWithAnnotations
(
compilation
);
if
(
resultType
.
State
==
NullableFlowState
.
MaybeDefault
)
{
inferredTypeWithAnnotations
=
inferredTypeWithAnnotations
.
AsAnnotated
();
}
for
(
int
i
=
0
;
i
<
numSwitchArms
;
i
++
)
if
(
inferredType
is
not
null
)
{
var
nodeForSyntax
=
expressions
[
i
];
var
conversionOpt
=
node
.
SwitchArms
[
i
].
Value
switch
{
BoundConversion
c
when
c
!=
nodeForSyntax
=>
c
,
_
=>
null
};
// Report top-level warnings
_
=
VisitConversion
(
conversionOpt
,
conversionOperand
:
nodeForSyntax
,
conversions
[
i
],
targetTypeWithNullability
:
inferredTypeWithAnnotations
,
operandType
:
resultTypes
[
i
],
checkConversion
:
true
,
fromExplicitCast
:
false
,
useLegacyWarnings
:
false
,
AssignmentKind
.
Assignment
,
reportRemainingWarnings
:
false
,
reportTopLevelWarnings
:
true
);
inferredTypeWithAnnotations
=
resultType
.
ToTypeWithAnnotations
(
compilation
);
if
(
resultType
.
State
==
NullableFlowState
.
MaybeDefault
)
{
inferredTypeWithAnnotations
=
inferredTypeWithAnnotations
.
AsAnnotated
();
}
for
(
int
i
=
0
;
i
<
numSwitchArms
;
i
++)
{
var
nodeForSyntax
=
expressions
[
i
];
var
conversionOpt
=
node
.
SwitchArms
[
i
].
Value
switch
{
BoundConversion
c
when
c
!=
nodeForSyntax
=>
c
,
_
=>
null
};
// Report top-level warnings
_
=
VisitConversion
(
conversionOpt
,
conversionOperand
:
nodeForSyntax
,
conversions
[
i
],
targetTypeWithNullability
:
inferredTypeWithAnnotations
,
operandType
:
resultTypes
[
i
],
checkConversion
:
true
,
fromExplicitCast
:
false
,
useLegacyWarnings
:
false
,
AssignmentKind
.
Assignment
,
reportRemainingWarnings
:
false
,
reportTopLevelWarnings
:
true
);
}
}
conversions
.
Free
();
...
...
src/Compilers/CSharp/Portable/Symbols/TypeWithAnnotations.cs
浏览文件 @
87f4c9df
...
...
@@ -782,7 +782,7 @@ static NullableFlowState getFlowState(TypeSymbol type, NullableAnnotation annota
{
if
(
type
is
null
)
{
return
annotation
.
IsAnnotated
()
?
NullableFlowState
.
Maybe
Null
:
NullableFlowState
.
NotNull
;
return
annotation
.
IsAnnotated
()
?
NullableFlowState
.
Maybe
Default
:
NullableFlowState
.
NotNull
;
}
if
(
type
.
IsPossiblyNullableReferenceTypeTypeParameter
())
{
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
浏览文件 @
87f4c9df
此差异已折叠。
点击以展开。
src/Compilers/CSharp/Test/Symbol/Symbols/Source/NullablePublicAPITests.cs
浏览文件 @
87f4c9df
...
...
@@ -1268,7 +1268,7 @@ void M()
Assert
.
Equal
(
notNull
,
leftInfo
.
Nullability
);
Assert
.
Equal
(
notNull
,
leftInfo
.
ConvertedNullability
);
Assert
.
Equal
(
@null
,
rightInfo
.
Nullability
);
Assert
.
Equal
(
notN
ull
,
rightInfo
.
ConvertedNullability
);
Assert
.
Equal
(
@n
ull
,
rightInfo
.
ConvertedNullability
);
}
[
Fact
]
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录