Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
53c5ac5a
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,发现更多精彩内容 >>
未验证
提交
53c5ac5a
编写于
3月 08, 2018
作者:
C
Charles Stoner
提交者:
GitHub
3月 08, 2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add IncludeNullability option to Conversions (#24935)
上级
29905b3d
变更
22
展开全部
隐藏空白更改
内联
并排
Showing
22 changed file
with
1329 addition
and
471 deletion
+1329
-471
src/Compilers/CSharp/Portable/Binder/Binder.cs
src/Compilers/CSharp/Portable/Binder/Binder.cs
+2
-1
src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
+3
-3
src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
+1
-2
src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs
src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs
+0
-1
src/Compilers/CSharp/Portable/Binder/Semantics/BestTypeInferrer.cs
...lers/CSharp/Portable/Binder/Semantics/BestTypeInferrer.cs
+54
-38
src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs
...harp/Portable/Binder/Semantics/Conversions/Conversions.cs
+9
-4
src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs
.../Portable/Binder/Semantics/Conversions/ConversionsBase.cs
+152
-102
src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/TypeConversions.cs
.../Portable/Binder/Semantics/Conversions/TypeConversions.cs
+4
-4
src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs
...inder/Semantics/OverloadResolution/MethodTypeInference.cs
+16
-13
src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs
...Binder/Semantics/OverloadResolution/OverloadResolution.cs
+0
-1
src/Compilers/CSharp/Portable/BoundTree/BoundExpressionExtensions.cs
...rs/CSharp/Portable/BoundTree/BoundExpressionExtensions.cs
+17
-4
src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs
src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs
+2
-2
src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPass.cs
src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPass.cs
+1
-1
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
+198
-187
src/Compilers/CSharp/Portable/Symbols/MethodSymbolExtensions.cs
...mpilers/CSharp/Portable/Symbols/MethodSymbolExtensions.cs
+0
-1
src/Compilers/CSharp/Portable/Symbols/PropertySymbol.cs
src/Compilers/CSharp/Portable/Symbols/PropertySymbol.cs
+1
-1
src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol_Bases.cs
...rp/Portable/Symbols/Source/SourceNamedTypeSymbol_Bases.cs
+1
-1
src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs
...mpilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs
+51
-15
src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs
src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs
+8
-7
src/Compilers/CSharp/Test/Semantic/Semantics/StaticNullChecking.cs
...lers/CSharp/Test/Semantic/Semantics/StaticNullChecking.cs
+318
-60
src/Compilers/CSharp/Test/Semantic/Semantics/StaticNullChecking_FlowAnalysis.cs
...est/Semantic/Semantics/StaticNullChecking_FlowAnalysis.cs
+490
-21
src/Compilers/CSharp/Test/Semantic/Semantics/StaticNullChecking_TypeInference.cs
...st/Semantic/Semantics/StaticNullChecking_TypeInference.cs
+1
-2
未找到文件。
src/Compilers/CSharp/Portable/Binder/Binder.cs
浏览文件 @
53c5ac5a
...
...
@@ -33,12 +33,13 @@ internal Binder(CSharpCompilation compilation)
this
.
Compilation
=
compilation
;
}
internal
Binder
(
Binder
next
)
internal
Binder
(
Binder
next
,
Conversions
conversions
=
null
)
{
Debug
.
Assert
(
next
!=
null
);
_next
=
next
;
this
.
Flags
=
next
.
Flags
;
this
.
Compilation
=
next
.
Compilation
;
_lazyConversions
=
conversions
;
}
protected
Binder
(
Binder
next
,
BinderFlags
flags
)
...
...
src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
浏览文件 @
53c5ac5a
...
...
@@ -235,10 +235,10 @@ protected BoundExpression CreateUserDefinedConversion(SyntaxNode syntax, BoundEx
userDefinedConversion
=
CreateConversion
(
syntax
:
syntax
,
source
:
userDefinedConversion
,
conversion
:
Conversions
.
ClassifyStandardConversion
(
null
,
conversionReturnType
,
conversion
.
BestUserDefinedConversionAnalysis
.
ToType
,
ref
useSiteDiagnostics
),
conversion
:
Conversions
.
ClassifyStandardConversion
(
null
,
conversionReturnType
,
conversionToType
,
ref
useSiteDiagnostics
),
isCast
:
false
,
wasCompilerGenerated
:
true
,
destination
:
conversion
.
BestUserDefinedConversionAnalysis
.
ToType
,
destination
:
conversionToType
,
diagnostics
:
diagnostics
);
}
}
...
...
@@ -253,7 +253,7 @@ protected BoundExpression CreateUserDefinedConversion(SyntaxNode syntax, BoundEx
@checked
:
false
,
explicitCastInCode
:
isCast
,
constantValueOpt
:
ConstantValue
.
NotAvailable
,
type
:
conversion
.
BestUserDefinedConversionAnalysis
.
ToType
)
type
:
conversionToType
)
{
WasCompilerGenerated
=
true
};
}
...
...
src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
浏览文件 @
53c5ac5a
...
...
@@ -2100,7 +2100,7 @@ private static NameSyntax GetNameSyntax(SyntaxNode syntax)
/// </summary>
/// <param name="syntax">Syntax node</param>
/// <param name="nameString">Plain text name</param>
private
static
NameSyntax
GetNameSyntax
(
SyntaxNode
syntax
,
out
string
nameString
)
internal
static
NameSyntax
GetNameSyntax
(
SyntaxNode
syntax
,
out
string
nameString
)
{
nameString
=
string
.
Empty
;
while
(
true
)
...
...
@@ -2706,7 +2706,6 @@ private BoundExpression BindImplicitArrayCreationExpression(ImplicitArrayCreatio
var
bestType
=
BestTypeInferrer
.
InferBestType
(
boundInitializerExpressions
,
this
.
Conversions
,
includeNullability
:
false
,
hadMultipleCandidates
:
out
hadMultipleCandidates
,
useSiteDiagnostics
:
ref
useSiteDiagnostics
);
diagnostics
.
Add
(
node
,
useSiteDiagnostics
);
...
...
src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs
浏览文件 @
53c5ac5a
...
...
@@ -3586,7 +3586,6 @@ private BoundExpression BindConditionalOperator(ConditionalExpressionSyntax node
trueExpr
,
falseExpr
,
this
.
Conversions
,
includeNullability
:
false
,
hadMultipleCandidates
:
out
hadMultipleCandidates
,
useSiteDiagnostics
:
ref
useSiteDiagnostics
);
diagnostics
.
Add
(
node
,
useSiteDiagnostics
);
...
...
src/Compilers/CSharp/Portable/Binder/Semantics/BestTypeInferrer.cs
浏览文件 @
53c5ac5a
...
...
@@ -2,7 +2,6 @@
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Linq
;
using
Microsoft.CodeAnalysis.CSharp.Symbols
;
using
Microsoft.CodeAnalysis.PooledObjects
;
...
...
@@ -10,25 +9,49 @@ namespace Microsoft.CodeAnalysis.CSharp
{
internal
sealed
class
BestTypeInferrer
{
private
readonly
Conversions
_conversions
;
private
BestTypeInferrer
(
Conversions
conversions
)
public
static
TypeSymbolWithAnnotations
InferBestType
(
ImmutableArray
<
TypeSymbolWithAnnotations
>
types
,
Conversions
conversions
,
ref
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
)
{
_conversions
=
conversions
;
return
GetBestType
(
types
,
conversions
,
ref
useSiteDiagnostics
)
;
}
// PROTOTYPE(NullableReferenceTypes): Remove includeNullability parameter. Nullability should be calculated in flow analysis.
public
static
TypeSymbolWithAnnotations
InferBestType
(
ImmutableArray
<
TypeSymbolWithAnnotations
>
types
,
Conversions
conversions
,
bool
includeNullability
,
ref
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
)
private
static
bool
?
GetIsNullable
(
ImmutableArray
<
TypeSymbolWithAnnotations
>
types
)
{
var
inferrer
=
new
BestTypeInferrer
(
conversions
);
return
inferrer
.
GetBestType
(
types
,
includeNullability
,
ref
useSiteDiagnostics
);
bool
?
isNullable
=
false
;
foreach
(
var
type
in
types
)
{
if
(
type
is
null
)
{
// PROTOTYPE(NullableReferenceTypes): Should ignore untyped
// expressions such as unbound lambdas and typeless tuples.
// See StaticNullChecking.LocalVar_Array_02 test.
isNullable
=
true
;
continue
;
}
if
(!
type
.
IsReferenceType
)
{
return
null
;
}
switch
(
type
.
IsNullable
)
{
case
null
:
if
(
isNullable
==
false
)
{
isNullable
=
null
;
}
break
;
case
true
:
isNullable
=
true
;
break
;
}
}
return
isNullable
;
}
/// <remarks>
/// This method finds the best common type of a set of expressions as per section 7.5.2.14 of the specification.
/// NOTE: If some or all of the expressions have error types, we return error type as the inference result.
/// </remarks>
public
static
TypeSymbolWithAnnotations
InferBestType
(
ImmutableArray
<
BoundExpression
>
exprs
,
Conversions
conversions
,
bool
includeNullability
,
out
bool
hadMultipleCandidates
,
ref
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
)
public
static
TypeSymbolWithAnnotations
InferBestType
(
ImmutableArray
<
BoundExpression
>
exprs
,
Conversions
conversions
,
out
bool
hadMultipleCandidates
,
ref
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
)
{
// SPEC: 7.5.2.14 Finding the best common type of a set of expressions
// SPEC: In some cases, a common type needs to be inferred for a set of expressions. In particular, the element types of implicitly typed arrays and
...
...
@@ -41,6 +64,7 @@ public static TypeSymbolWithAnnotations InferBestType(ImmutableArray<BoundExpres
// SPEC: If no such S exists, the expressions have no best common type.
// All non-null types are candidates for best type inference.
bool
includeNullability
=
conversions
.
IncludeNullability
;
var
candidateTypes
=
new
HashSet
<
TypeSymbolWithAnnotations
>(
TypeSymbolWithAnnotations
.
EqualsComparer
.
Instance
);
foreach
(
BoundExpression
expr
in
exprs
)
{
...
...
@@ -61,14 +85,14 @@ public static TypeSymbolWithAnnotations InferBestType(ImmutableArray<BoundExpres
hadMultipleCandidates
=
candidateTypes
.
Count
>
1
;
// Perform best type inference on candidate types.
return
InferBestType
(
candidateTypes
.
AsImmutableOrEmpty
(),
conversions
,
includeNullability
,
ref
useSiteDiagnostics
);
return
InferBestType
(
candidateTypes
.
AsImmutableOrEmpty
(),
conversions
,
ref
useSiteDiagnostics
);
}
/// <remarks>
/// This method implements best type inference for the conditional operator ?:.
/// NOTE: If either expression is an error type, we return error type as the inference result.
/// </remarks>
public
static
TypeSymbolWithAnnotations
InferBestTypeForConditionalOperator
(
BoundExpression
expr1
,
BoundExpression
expr2
,
Conversions
conversions
,
bool
includeNullability
,
out
bool
hadMultipleCandidates
,
ref
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
)
public
static
TypeSymbolWithAnnotations
InferBestTypeForConditionalOperator
(
BoundExpression
expr1
,
BoundExpression
expr2
,
Conversions
conversions
,
out
bool
hadMultipleCandidates
,
ref
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
)
{
// SPEC: The second and third operands, x and y, of the ?: operator control the type of the conditional expression.
// SPEC: • If x has type X and y has type Y then
...
...
@@ -79,6 +103,7 @@ public static TypeSymbolWithAnnotations InferBestTypeForConditionalOperator(Boun
// SPEC: • Otherwise, no expression type can be determined, and a compile-time error occurs.
// A type is a candidate if all expressions are convertible to that type.
bool
includeNullability
=
conversions
.
IncludeNullability
;
var
candidateTypes
=
ArrayBuilder
<
TypeSymbolWithAnnotations
>.
GetInstance
();
var
type1
=
expr1
.
GetTypeAndNullability
(
includeNullability
);
...
...
@@ -92,7 +117,6 @@ public static TypeSymbolWithAnnotations InferBestTypeForConditionalOperator(Boun
return
type1
;
}
// PROTOTYPE(NullableReferenceTypes): Consider nullability in conversion.
if
(
conversions
.
ClassifyImplicitConversionFromExpression
(
expr2
,
type1
.
TypeSymbol
,
ref
useSiteDiagnostics
).
Exists
)
{
candidateTypes
.
Add
(
type1
);
...
...
@@ -101,7 +125,7 @@ public static TypeSymbolWithAnnotations InferBestTypeForConditionalOperator(Boun
var
type2
=
expr2
.
GetTypeAndNullability
(
includeNullability
);
if
((
object
)
type2
!=
null
&&
!
type2
.
Equals
(
type1
,
TypeCompareKind
.
ConsiderEverything
)
)
if
((
object
)
type2
!=
null
)
{
if
(
type2
.
IsErrorType
())
{
...
...
@@ -110,7 +134,6 @@ public static TypeSymbolWithAnnotations InferBestTypeForConditionalOperator(Boun
return
type2
;
}
// PROTOTYPE(NullableReferenceTypes): Consider nullability in conversion.
if
(
conversions
.
ClassifyImplicitConversionFromExpression
(
expr1
,
type2
.
TypeSymbol
,
ref
useSiteDiagnostics
).
Exists
)
{
candidateTypes
.
Add
(
type2
);
...
...
@@ -119,13 +142,10 @@ public static TypeSymbolWithAnnotations InferBestTypeForConditionalOperator(Boun
hadMultipleCandidates
=
candidateTypes
.
Count
>
1
;
return
InferBestType
(
candidateTypes
.
ToImmutableAndFree
(),
conversions
,
includeNullability
,
ref
useSiteDiagnostics
);
return
InferBestType
(
candidateTypes
.
ToImmutableAndFree
(),
conversions
,
ref
useSiteDiagnostics
);
}
// PROTOTYPE(NullableReferenceTypes): Should be a two-pass approach
// similar to MethodTypeInferrer which compares with nullability and
// without and prefers the result with nullability.
private
TypeSymbolWithAnnotations
GetBestType
(
ImmutableArray
<
TypeSymbolWithAnnotations
>
types
,
bool
includeNullability
,
ref
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
)
private
static
TypeSymbolWithAnnotations
GetBestType
(
ImmutableArray
<
TypeSymbolWithAnnotations
>
types
,
Conversions
conversions
,
ref
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
)
{
// This code assumes that the types in the list are unique.
...
...
@@ -155,7 +175,7 @@ private TypeSymbolWithAnnotations GetBestType(ImmutableArray<TypeSymbolWithAnnot
}
else
{
var
better
=
Better
(
best
,
type
,
ref
useSiteDiagnostics
);
var
better
=
Better
(
best
,
type
,
conversions
,
ref
useSiteDiagnostics
);
if
((
object
)
better
==
null
)
{
...
...
@@ -179,7 +199,7 @@ private TypeSymbolWithAnnotations GetBestType(ImmutableArray<TypeSymbolWithAnnot
for
(
int
i
=
0
;
i
<
bestIndex
;
i
++)
{
var
type
=
types
[
i
];
var
better
=
Better
(
best
,
type
,
ref
useSiteDiagnostics
);
var
better
=
Better
(
best
,
type
,
conversions
,
ref
useSiteDiagnostics
);
if
(!
best
.
Equals
(
better
,
TypeCompareKind
.
ConsiderEverything
))
{
...
...
@@ -187,25 +207,21 @@ private TypeSymbolWithAnnotations GetBestType(ImmutableArray<TypeSymbolWithAnnot
}
}
// If any of the types are null, the result should be nullable.
// PROTOTYPE(NullableReferenceTypes): Should ignore untyped
// expressions such as unbound lambdas and typeless tuples.
// See StaticNullChecking.LocalVar_Array_02 test.
if
(
includeNullability
&&
types
.
Any
(
t
=>
(
object
)
t
==
null
)
&&
best
.
IsReferenceType
&&
best
.
IsNullable
==
false
)
{
best
=
best
.
AsNullableReferenceType
();
}
// If any of the types are nullable, the result should be nullable.
return
conversions
.
IncludeNullability
?
UpdateNullability
(
best
,
types
)
:
best
;
}
return
best
;
private
static
TypeSymbolWithAnnotations
UpdateNullability
(
TypeSymbolWithAnnotations
bestType
,
ImmutableArray
<
TypeSymbolWithAnnotations
>
types
)
{
return
bestType
.
IsReferenceType
&&
bestType
.
IsNullable
==
false
?
TypeSymbolWithAnnotations
.
Create
(
bestType
.
TypeSymbol
,
GetIsNullable
(
types
))
:
bestType
;
}
/// <summary>
/// Returns the better type amongst the two, with some possible modifications (dynamic/object or tuple names).
/// </summary>
private
TypeSymbolWithAnnotations
Better
(
TypeSymbolWithAnnotations
type1
,
TypeSymbolWithAnnotations
type2
,
ref
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
)
private
static
TypeSymbolWithAnnotations
Better
(
TypeSymbolWithAnnotations
type1
,
TypeSymbolWithAnnotations
type2
,
Conversions
conversions
,
ref
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
)
{
// Anything is better than an error sym.
if
(
type1
.
IsErrorType
())
...
...
@@ -218,8 +234,8 @@ private TypeSymbolWithAnnotations Better(TypeSymbolWithAnnotations type1, TypeSy
return
type1
;
}
var
t1tot2
=
_
conversions
.
ClassifyImplicitConversionFromType
(
type1
.
TypeSymbol
,
type2
.
TypeSymbol
,
ref
useSiteDiagnostics
).
Exists
;
var
t2tot1
=
_
conversions
.
ClassifyImplicitConversionFromType
(
type2
.
TypeSymbol
,
type1
.
TypeSymbol
,
ref
useSiteDiagnostics
).
Exists
;
var
t1tot2
=
conversions
.
ClassifyImplicitConversionFromType
(
type1
.
TypeSymbol
,
type2
.
TypeSymbol
,
ref
useSiteDiagnostics
).
Exists
;
var
t2tot1
=
conversions
.
ClassifyImplicitConversionFromType
(
type2
.
TypeSymbol
,
type1
.
TypeSymbol
,
ref
useSiteDiagnostics
).
Exists
;
if
(
t1tot2
&&
t2tot1
)
{
...
...
@@ -235,7 +251,7 @@ private TypeSymbolWithAnnotations Better(TypeSymbolWithAnnotations type1, TypeSy
if
(
type1
.
Equals
(
type2
,
TypeCompareKind
.
IgnoreDynamicAndTupleNames
))
{
return
MethodTypeInferrer
.
Merge
(
type1
,
type2
,
_
conversions
.
CorLibrary
);
return
MethodTypeInferrer
.
Merge
(
type1
,
type2
,
conversions
.
CorLibrary
);
}
return
null
;
...
...
src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs
浏览文件 @
53c5ac5a
...
...
@@ -13,23 +13,28 @@ internal sealed class Conversions : ConversionsBase
private
readonly
Binder
_binder
;
public
Conversions
(
Binder
binder
)
:
this
(
binder
,
currentRecursionDepth
:
0
)
:
this
(
binder
,
currentRecursionDepth
:
0
,
includeNullability
:
false
)
{
}
private
Conversions
(
Binder
binder
,
int
currentRecursionDepth
)
:
base
(
binder
.
Compilation
.
Assembly
.
CorLibrary
,
currentRecursionDepth
)
private
Conversions
(
Binder
binder
,
int
currentRecursionDepth
,
bool
includeNullability
)
:
base
(
binder
.
Compilation
.
Assembly
.
CorLibrary
,
currentRecursionDepth
,
includeNullability
)
{
_binder
=
binder
;
}
protected
override
ConversionsBase
CreateInstance
(
int
currentRecursionDepth
)
{
return
new
Conversions
(
_binder
,
currentRecursionDepth
);
return
new
Conversions
(
_binder
,
currentRecursionDepth
,
IncludeNullability
);
}
private
CSharpCompilation
Compilation
{
get
{
return
_binder
.
Compilation
;
}
}
internal
Conversions
WithNullability
(
bool
includeNullability
)
{
return
(
IncludeNullability
==
includeNullability
)
?
this
:
new
Conversions
(
_binder
,
currentRecursionDepth
,
includeNullability
);
}
public
override
Conversion
GetMethodGroupConversion
(
BoundMethodGroup
source
,
TypeSymbol
destination
,
ref
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
)
{
// Must be a bona fide delegate type, not an expression tree type.
...
...
src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs
浏览文件 @
53c5ac5a
此差异已折叠。
点击以展开。
src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/TypeConversions.cs
浏览文件 @
53c5ac5a
...
...
@@ -10,18 +10,18 @@ namespace Microsoft.CodeAnalysis.CSharp
internal
sealed
class
TypeConversions
:
ConversionsBase
{
public
TypeConversions
(
AssemblySymbol
corLibrary
)
:
this
(
corLibrary
,
currentRecursionDepth
:
0
)
:
this
(
corLibrary
,
currentRecursionDepth
:
0
,
includeNullability
:
false
)
{
}
private
TypeConversions
(
AssemblySymbol
corLibrary
,
int
currentRecursionDepth
)
:
base
(
corLibrary
,
currentRecursionDepth
)
private
TypeConversions
(
AssemblySymbol
corLibrary
,
int
currentRecursionDepth
,
bool
includeNullability
)
:
base
(
corLibrary
,
currentRecursionDepth
,
includeNullability
)
{
}
protected
override
ConversionsBase
CreateInstance
(
int
currentRecursionDepth
)
{
return
new
TypeConversions
(
this
.
corLibrary
,
currentRecursionDepth
);
return
new
TypeConversions
(
this
.
corLibrary
,
currentRecursionDepth
,
IncludeNullability
);
}
public
override
Conversion
GetMethodGroupConversion
(
BoundMethodGroup
source
,
TypeSymbol
destination
,
ref
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
)
...
...
src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs
浏览文件 @
53c5ac5a
...
...
@@ -90,8 +90,6 @@ private enum Dependency
private
readonly
ImmutableArray
<
TypeSymbolWithAnnotations
>
_formalParameterTypes
;
private
readonly
ImmutableArray
<
RefKind
>
_formalParameterRefKinds
;
private
readonly
ImmutableArray
<
BoundExpression
>
_arguments
;
// PROTOTYPE(NullableReferenceTypes): Remove conditional and infer nullability always.
private
readonly
bool
_includeNullability
;
private
readonly
TypeSymbolWithAnnotations
[]
_fixedResults
;
private
readonly
HashSet
<
TypeSymbolWithAnnotations
>[]
_exactBounds
;
...
...
@@ -214,8 +212,7 @@ private enum Dependency
ImmutableArray
<
RefKind
>
formalParameterRefKinds
,
// Optional; assume all value if missing.
ImmutableArray
<
BoundExpression
>
arguments
,
// Required; in scenarios like method group conversions where there are
// no arguments per se we cons up some fake arguments.
ref
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
,
bool
includeNullability
=
false
)
ref
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
)
{
Debug
.
Assert
(!
methodTypeParameters
.
IsDefault
);
Debug
.
Assert
(
methodTypeParameters
.
Length
>
0
);
...
...
@@ -239,8 +236,7 @@ private enum Dependency
constructedContainingTypeOfMethod
,
formalParameterTypes
,
formalParameterRefKinds
,
arguments
,
includeNullability
);
arguments
);
return
inferrer
.
InferTypeArgs
(
binder
,
ref
useSiteDiagnostics
);
}
...
...
@@ -259,8 +255,7 @@ private enum Dependency
NamedTypeSymbol
constructedContainingTypeOfMethod
,
ImmutableArray
<
TypeSymbolWithAnnotations
>
formalParameterTypes
,
ImmutableArray
<
RefKind
>
formalParameterRefKinds
,
ImmutableArray
<
BoundExpression
>
arguments
,
bool
includeNullability
)
ImmutableArray
<
BoundExpression
>
arguments
)
{
_conversions
=
conversions
;
_methodTypeParameters
=
methodTypeParameters
;
...
...
@@ -268,7 +263,6 @@ private enum Dependency
_formalParameterTypes
=
formalParameterTypes
;
_formalParameterRefKinds
=
formalParameterRefKinds
;
_arguments
=
arguments
;
_includeNullability
=
includeNullability
;
_fixedResults
=
new
TypeSymbolWithAnnotations
[
methodTypeParameters
.
Length
];
_exactBounds
=
new
HashSet
<
TypeSymbolWithAnnotations
>[
methodTypeParameters
.
Length
];
_upperBounds
=
new
HashSet
<
TypeSymbolWithAnnotations
>[
methodTypeParameters
.
Length
];
...
...
@@ -2343,6 +2337,9 @@ private bool Fix(int iParam, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
// Fix considering nullability, if possible, otherwise fix ignoring nullability.
// PROTOTYPE(NullableReferenceTypes): Avoid calling Fix ignoring nullability if the nullability call succeeds.
// PROTOTYPE(NullableReferenceTypes): Avoid comparing with and without nullability here.
// Initial binding should use includeNullability: false, and NullableWalker should use
// includeNullability: true, and NullableWalker should compare the two.
HashSet
<
DiagnosticInfo
>
ignoredDiagnostics
=
null
;
var
withNullability
=
Fix
(
exact
,
lower
,
upper
,
ref
ignoredDiagnostics
,
_conversions
,
includeNullability
:
true
);
var
withoutNullability
=
Fix
(
exact
,
lower
,
upper
,
ref
useSiteDiagnostics
,
_conversions
,
includeNullability
:
false
);
...
...
@@ -2534,13 +2531,21 @@ private bool Fix(int iParam, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
private
bool
?
IsNullable
(
BoundExpression
expr
)
{
if
(!
_
i
ncludeNullability
)
if
(!
_
conversions
.
I
ncludeNullability
)
{
return
false
;
}
return
expr
.
IsNullable
();
}
internal
static
TypeSymbol
Merge
(
TypeSymbol
first
,
TypeSymbol
second
,
AssemblySymbol
corLibrary
)
{
var
firstWithAnnotations
=
TypeSymbolWithAnnotations
.
Create
(
first
);
var
secondWithAnnotations
=
TypeSymbolWithAnnotations
.
Create
(
second
);
return
MergeNullability
(
MergeTupleNames
(
MergeDynamic
(
firstWithAnnotations
,
secondWithAnnotations
,
corLibrary
),
secondWithAnnotations
),
secondWithAnnotations
).
TypeSymbol
;
}
// PROTOTYPE(NullableReferenceTypes): Remove this overload.
internal
static
TypeSymbolWithAnnotations
Merge
(
TypeSymbolWithAnnotations
first
,
TypeSymbolWithAnnotations
second
,
AssemblySymbol
corLibrary
)
{
return
MergeNullability
(
MergeTupleNames
(
MergeDynamic
(
first
,
second
,
corLibrary
),
second
),
second
);
...
...
@@ -2786,7 +2791,6 @@ private static NamedTypeSymbol GetInterfaceInferenceBound(ImmutableArray<NamedTy
ConversionsBase
conversions
,
MethodSymbol
method
,
ImmutableArray
<
BoundExpression
>
arguments
,
bool
includeNullability
,
ref
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
)
{
Debug
.
Assert
((
object
)
method
!=
null
);
...
...
@@ -2809,8 +2813,7 @@ private static NamedTypeSymbol GetInterfaceInferenceBound(ImmutableArray<NamedTy
constructedFromMethod
.
ContainingType
,
constructedFromMethod
.
GetParameterTypes
(),
constructedFromMethod
.
ParameterRefKinds
,
arguments
,
includeNullability
);
arguments
);
if
(!
inferrer
.
InferTypeArgumentsFromFirstArgument
(
ref
useSiteDiagnostics
))
{
...
...
src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs
浏览文件 @
53c5ac5a
...
...
@@ -3080,7 +3080,6 @@ internal EffectiveParameters(ImmutableArray<TypeSymbolWithAnnotations> types, Im
_binder
.
Conversions
,
method
,
args
,
includeNullability
:
Compilation
.
IsFeatureEnabled
(
MessageID
.
IDS_FeatureStaticNullChecking
),
useSiteDiagnostics
:
ref
useSiteDiagnostics
);
if
(
inferredFromFirstArgument
.
IsDefault
)
{
...
...
src/Compilers/CSharp/Portable/BoundTree/BoundExpressionExtensions.cs
浏览文件 @
53c5ac5a
...
...
@@ -222,7 +222,7 @@ internal static TypeSymbolWithAnnotations GetTypeAndNullability(this BoundExpres
switch
(
expr
.
Kind
)
{
case
BoundKind
.
SuppressNullableWarningExpression
:
return
false
;
return
null
;
case
BoundKind
.
Local
:
{
var
local
=
(
BoundLocal
)
expr
;
...
...
@@ -245,9 +245,15 @@ internal static TypeSymbolWithAnnotations GetTypeAndNullability(this BoundExpres
var
right
=
op
.
RightOperand
.
IsNullable
();
return
(
left
==
true
)
?
right
:
left
;
}
case
BoundKind
.
ThisReference
:
case
BoundKind
.
BaseReference
:
case
BoundKind
.
NewT
:
case
BoundKind
.
ObjectCreationExpression
:
case
BoundKind
.
DelegateCreationExpression
:
return
false
;
case
BoundKind
.
NoPiaObjectCreationExpression
:
case
BoundKind
.
InterpolatedString
:
case
BoundKind
.
TypeOfOperator
:
case
BoundKind
.
NameOfOperator
:
case
BoundKind
.
TupleLiteral
:
return
false
;
case
BoundKind
.
DefaultExpression
:
...
...
@@ -263,9 +269,16 @@ internal static TypeSymbolWithAnnotations GetTypeAndNullability(this BoundExpres
}
var
constant
=
expr
.
ConstantValue
;
if
(
constant
!=
null
&&
constant
.
IsNull
)
if
(
constant
!=
null
)
{
return
true
;
if
(
constant
.
IsNull
)
{
return
true
;
}
if
(
expr
.
Type
?.
IsReferenceType
==
true
)
{
return
false
;
}
}
return
null
;
...
...
src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs
浏览文件 @
53c5ac5a
...
...
@@ -140,8 +140,8 @@ public TypeSymbolWithAnnotations InferredReturnType(ref HashSet<DiagnosticInfo>
}
else
{
// PROTOTYPE(NullableReferenceTypes): Should pass includeNullability: false.
bestResultType
=
BestTypeInferrer
.
InferBestType
(
resultTypes
,
binder
.
Conversions
,
includeNullability
,
ref
useSiteDiagnostics
);
var
conversions
=
binder
.
Conversions
.
WithNullability
(
includeNullability
);
bestResultType
=
BestTypeInferrer
.
InferBestType
(
resultTypes
,
conversions
,
ref
useSiteDiagnostics
);
}
if
(!
isAsync
)
...
...
src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPass.cs
浏览文件 @
53c5ac5a
...
...
@@ -319,7 +319,7 @@ protected static bool HasInitializer(FieldSymbol field)
/// <summary>
/// Perform data flow analysis, reporting all necessary diagnostics.
/// </summary>
public
static
void
Analyze
(
CSharpCompilation
compilation
,
Symbol
member
,
BoundNode
node
,
DiagnosticBag
diagnostics
,
bool
requireOutParamsAssigned
=
true
)
public
static
void
Analyze
(
CSharpCompilation
compilation
,
Method
Symbol
member
,
BoundNode
node
,
DiagnosticBag
diagnostics
,
bool
requireOutParamsAssigned
=
true
)
{
Debug
.
Assert
(
diagnostics
!=
null
);
...
...
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
浏览文件 @
53c5ac5a
此差异已折叠。
点击以展开。
src/Compilers/CSharp/Portable/Symbols/MethodSymbolExtensions.cs
浏览文件 @
53c5ac5a
...
...
@@ -68,7 +68,6 @@ public static MethodSymbol InferExtensionMethodTypeArguments(this MethodSymbol m
conversions
,
method
,
arguments
.
AsImmutable
(),
includeNullability
:
false
,
// PROTOTYPE(NullableReferenceTypes): Support nullability if feature enabled.
useSiteDiagnostics
:
ref
useSiteDiagnostics
);
if
(
typeArgs
.
IsDefault
)
...
...
src/Compilers/CSharp/Portable/Symbols/PropertySymbol.cs
浏览文件 @
53c5ac5a
...
...
@@ -328,7 +328,7 @@ public override TResult Accept<TResult>(CSharpSymbolVisitor<TResult> visitor)
return
visitor
.
VisitProperty
(
this
);
}
internal
virtual
PropertySymbol
AsMember
(
NamedTypeSymbol
newOwner
)
internal
PropertySymbol
AsMember
(
NamedTypeSymbol
newOwner
)
{
Debug
.
Assert
(
this
.
IsDefinition
);
Debug
.
Assert
(
ReferenceEquals
(
newOwner
.
OriginalDefinition
,
this
.
ContainingSymbol
.
OriginalDefinition
));
...
...
src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol_Bases.cs
浏览文件 @
53c5ac5a
...
...
@@ -140,7 +140,7 @@ protected override void CheckInterfaces(DiagnosticBag diagnostics)
if
(
interfaces
.
Count
>
1
)
{
var
seenInterfaces
=
new
Dictionary
<
NamedTypeSymbol
,
NamedTypeSymbol
>(
EqualsIgnoring
Comparer
.
InstanceIgnoring
TupleNames
);
var
seenInterfaces
=
new
Dictionary
<
NamedTypeSymbol
,
NamedTypeSymbol
>(
EqualsIgnoringTupleNames
);
foreach
(
var
@interface
in
interfaces
)
{
NamedTypeSymbol
other
;
...
...
src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs
浏览文件 @
53c5ac5a
...
...
@@ -213,6 +213,36 @@ internal TupleTypeSymbol WithUnderlyingType(NamedTypeSymbol newUnderlyingType)
return
Create
(
_locations
,
newUnderlyingType
,
_elementLocations
,
_elementNames
,
_errorPositions
);
}
/// <summary>
/// Copy this tuple, but modify it to use the new element types.
/// </summary>
internal
TupleTypeSymbol
WithElementTypes
(
ImmutableArray
<
TypeSymbolWithAnnotations
>
newElementTypes
)
{
Debug
.
Assert
(
_elementTypes
.
Length
==
newElementTypes
.
Length
);
Debug
.
Assert
(
newElementTypes
.
All
(
t
=>
(
object
)
t
!=
null
));
NamedTypeSymbol
firstTupleType
;
NamedTypeSymbol
chainedTupleType
;
if
(
_underlyingType
.
Arity
<
TupleTypeSymbol
.
RestPosition
)
{
firstTupleType
=
_underlyingType
.
OriginalDefinition
;
chainedTupleType
=
null
;
}
else
{
chainedTupleType
=
_underlyingType
.
OriginalDefinition
;
var
underlyingType
=
_underlyingType
;
do
{
underlyingType
=
((
TupleTypeSymbol
)
underlyingType
.
TypeArgumentsNoUseSiteDiagnostics
[
TupleTypeSymbol
.
RestIndex
].
TypeSymbol
).
UnderlyingNamedType
;
}
while
(
underlyingType
.
Arity
>=
TupleTypeSymbol
.
RestPosition
);
firstTupleType
=
underlyingType
.
OriginalDefinition
;
}
return
Create
(
ConstructTupleUnderlyingType
(
firstTupleType
,
chainedTupleType
,
newElementTypes
),
elementNames
:
_elementNames
);
}
/// <summary>
/// Copy this tuple, but modify it to use the new element names.
/// Also applies new location of the whole tuple as well as each element.
...
...
@@ -319,34 +349,40 @@ private static NamedTypeSymbol GetTupleUnderlyingType(ImmutableArray<TypeSymbolW
int
remainder
;
int
chainLength
=
NumberOfValueTuples
(
numElements
,
out
remainder
);
NamedTypeSymbol
currentSymbol
=
default
(
NamedTypeSymbol
);
NamedTypeSymbol
firstTupleType
=
compilation
.
GetWellKnownType
(
GetTupleType
(
remainder
));
if
((
object
)
diagnostics
!=
null
&&
(
object
)
syntax
!=
null
)
{
ReportUseSiteAndObsoleteDiagnostics
(
syntax
,
diagnostics
,
firstTupleType
);
}
currentSymbol
=
firstTupleType
.
Construct
(
ImmutableArray
.
Create
(
elementTypes
,
(
chainLength
-
1
)
*
(
RestPosition
-
1
),
remainder
));
int
loop
=
chainLength
-
1
;
if
(
loop
>
0
)
NamedTypeSymbol
chainedTupleType
=
null
;
if
(
chainLength
>
1
)
{
NamedTypeSymbol
chainedTupleType
=
compilation
.
GetWellKnownType
(
GetTupleType
(
RestPosition
));
chainedTupleType
=
compilation
.
GetWellKnownType
(
GetTupleType
(
RestPosition
));
if
((
object
)
diagnostics
!=
null
&&
(
object
)
syntax
!=
null
)
{
ReportUseSiteAndObsoleteDiagnostics
(
syntax
,
diagnostics
,
chainedTupleType
);
}
}
do
{
var
chainedTypes
=
ImmutableArray
.
Create
(
elementTypes
,
(
loop
-
1
)
*
(
RestPosition
-
1
),
RestPosition
-
1
).
Add
(
TypeSymbolWithAnnotations
.
Create
(
currentSymbol
));
return
ConstructTupleUnderlyingType
(
firstTupleType
,
chainedTupleType
,
elementTypes
);
}
currentSymbol
=
chainedTupleType
.
Construct
(
chainedTypes
);
loop
--;
}
while
(
loop
>
0
);
internal
static
NamedTypeSymbol
ConstructTupleUnderlyingType
(
NamedTypeSymbol
firstTupleType
,
NamedTypeSymbol
chainedTupleTypeOpt
,
ImmutableArray
<
TypeSymbolWithAnnotations
>
elementTypes
)
{
Debug
.
Assert
(
chainedTupleTypeOpt
is
null
==
elementTypes
.
Length
<
RestPosition
);
int
numElements
=
elementTypes
.
Length
;
int
remainder
;
int
chainLength
=
NumberOfValueTuples
(
numElements
,
out
remainder
);
NamedTypeSymbol
currentSymbol
=
firstTupleType
.
Construct
(
ImmutableArray
.
Create
(
elementTypes
,
(
chainLength
-
1
)
*
(
RestPosition
-
1
),
remainder
));
int
loop
=
chainLength
-
1
;
while
(
loop
>
0
)
{
var
chainedTypes
=
ImmutableArray
.
Create
(
elementTypes
,
(
loop
-
1
)
*
(
RestPosition
-
1
),
RestPosition
-
1
).
Add
(
TypeSymbolWithAnnotations
.
Create
(
currentSymbol
));
currentSymbol
=
chainedTupleTypeOpt
.
Construct
(
chainedTypes
);
loop
--;
}
return
currentSymbol
;
...
...
src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs
浏览文件 @
53c5ac5a
...
...
@@ -104,16 +104,19 @@ private InterfaceInfo GetInterfaceInfo()
return
info
;
}
internal
static
readonly
EqualityComparer
<
TypeSymbol
>
EqualsConsiderEverything
=
new
TypeSymbolComparer
(
TypeCompareKind
.
ConsiderEverything
);
internal
static
readonly
EqualityComparer
<
TypeSymbol
>
EqualsIgnoringTupleNames
=
new
TypeSymbolComparer
(
TypeCompareKind
.
IgnoreTupleNames
);
/// <summary>
/// A comparer that treats dynamic and object as "the same" types, and also ignores tuple element names differences.
/// </summary>
internal
static
readonly
EqualityComparer
<
TypeSymbol
>
EqualsIgnoringDynamicAndTupleNamesComparer
=
new
EqualsIgnoring
Comparer
(
TypeCompareKind
.
IgnoreDynamicAndTupleNames
);
internal
static
readonly
EqualityComparer
<
TypeSymbol
>
EqualsIgnoringDynamicAndTupleNamesComparer
=
new
TypeSymbol
Comparer
(
TypeCompareKind
.
IgnoreDynamicAndTupleNames
);
/// <summary>
/// A comparator that pays attention to nullable modifiers in addition to default behavior.
/// </summary>
internal
static
readonly
EqualityComparer
<
TypeSymbol
>
EqualsIncludingNullableComparer
=
new
EqualsIgnoring
Comparer
(
TypeCompareKind
.
CompareNullableModifiersForReferenceTypes
);
internal
static
readonly
EqualityComparer
<
TypeSymbol
>
EqualsIncludingNullableComparer
=
new
TypeSymbol
Comparer
(
TypeCompareKind
.
CompareNullableModifiersForReferenceTypes
);
/// <summary>
/// The original definition of this symbol. If this symbol is constructed from another
...
...
@@ -307,13 +310,11 @@ public override int GetHashCode()
return
RuntimeHelpers
.
GetHashCode
(
this
);
}
internal
sealed
class
EqualsIgnoring
Comparer
:
EqualityComparer
<
TypeSymbol
>
internal
sealed
class
TypeSymbol
Comparer
:
EqualityComparer
<
TypeSymbol
>
{
public
static
EqualsIgnoringComparer
InstanceIgnoringTupleNames
{
get
;
}
=
new
EqualsIgnoringComparer
(
TypeCompareKind
.
IgnoreTupleNames
);
private
readonly
TypeCompareKind
_comparison
;
public
EqualsIgnoring
Comparer
(
TypeCompareKind
comparison
)
public
TypeSymbol
Comparer
(
TypeCompareKind
comparison
)
{
_comparison
=
comparison
;
}
...
...
@@ -354,7 +355,7 @@ protected virtual ImmutableArray<NamedTypeSymbol> GetAllInterfaces()
protected
virtual
ImmutableArray
<
NamedTypeSymbol
>
MakeAllInterfaces
()
{
var
result
=
ArrayBuilder
<
NamedTypeSymbol
>.
GetInstance
();
var
visited
=
new
HashSet
<
NamedTypeSymbol
>(
EqualsIgnoring
Comparer
.
InstanceIgnoring
TupleNames
);
var
visited
=
new
HashSet
<
NamedTypeSymbol
>(
EqualsIgnoringTupleNames
);
for
(
var
baseType
=
this
;
!
ReferenceEquals
(
baseType
,
null
);
baseType
=
baseType
.
BaseTypeNoUseSiteDiagnostics
)
{
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/StaticNullChecking.cs
浏览文件 @
53c5ac5a
此差异已折叠。
点击以展开。
src/Compilers/CSharp/Test/Semantic/Semantics/StaticNullChecking_FlowAnalysis.cs
浏览文件 @
53c5ac5a
此差异已折叠。
点击以展开。
src/Compilers/CSharp/Test/Semantic/Semantics/StaticNullChecking_TypeInference.cs
浏览文件 @
53c5ac5a
...
...
@@ -598,8 +598,7 @@ static void F(string? s)
var
declarator
=
tree
.
GetRoot
().
DescendantNodes
().
OfType
<
VariableDeclaratorSyntax
>().
First
();
var
symbol
=
(
LocalSymbol
)
model
.
GetDeclaredSymbol
(
declarator
);
Assert
.
Equal
(
"System.String"
,
symbol
.
Type
.
ToTestDisplayString
());
// PROTOTYPE(NullableReferenceTypes): IsNullable should be inferred nullable state: null.
Assert
.
Equal
(
false
,
symbol
.
Type
.
IsNullable
);
Assert
.
Equal
(
null
,
symbol
.
Type
.
IsNullable
);
}
[
Fact
]
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录