Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
46c71ef2
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,发现更多精彩内容 >>
未验证
提交
46c71ef2
编写于
8月 06, 2018
作者:
F
Fredric Silberberg
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Addressed pr feedback.
上级
962daf5e
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
133 addition
and
13 deletion
+133
-13
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
+17
-10
src/Compilers/CSharp/Portable/Symbols/SymbolWithAnnotations.cs
...ompilers/CSharp/Portable/Symbols/SymbolWithAnnotations.cs
+7
-1
src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
...rp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
+109
-2
未找到文件。
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
浏览文件 @
46c71ef2
...
...
@@ -163,6 +163,8 @@ protected override void Free()
}
}
// PROTOTYPE(NullableReferenceTypes): Investigate remaining IsReferenceType usage for replacement by !IsValueType if necessary.
protected
override
bool
ConvertInsufficientExecutionStackExceptionToCancelledByStackGuardException
()
{
return
true
;
...
...
@@ -319,10 +321,12 @@ private void Populate(ref LocalState state, int start)
}
// PROTOTYPE(NullableReferenceTypes): Consider setting treatUnconstrainedTypeParameterAsNullable during initial binding, and removing this method.
private
static
TypeSymbolWithAnnotations
GetAdjustedType
(
TypeSymbolWithAnnotations
?
initialType
)
/// <summary>
/// Adjust the given type, treating unconstrained type parameters as nullable if in the appropriate context. This overrides the current state
/// of type parameter.
/// </summary>
private
static
TypeSymbolWithAnnotations
UnconstrainedTypeParametersAsNullable
(
TypeSymbolWithAnnotations
?
initialType
)
{
// If the initial type was an unconstrained type parameter, we want to treat it as nullable, overriding
// the annotated state.
if
(
initialType
is
null
||
initialType
.
Value
.
IsNull
)
{
return
default
;
...
...
@@ -776,15 +780,16 @@ private void EnterParameters()
for
(
int
i
=
0
;
i
<
n
;
i
++)
{
var
parameter
=
methodParameters
[
i
];
var
parameterType
=
signatureParameters
[
i
].
Type
;
_variableTypes
[
parameter
]
=
GetAdjustedType
(
parameterType
);
var
parameterType
=
UnconstrainedTypeParametersAsNullable
(
signatureParameters
[
i
].
Type
);
EnterParameter
(
parameter
,
parameterType
);
}
}
private
void
EnterParameter
(
ParameterSymbol
parameter
,
TypeSymbolWithAnnotations
parameterType
)
{
_variableTypes
[
parameter
]
=
parameterType
;
int
slot
=
GetOrCreateSlot
(
parameter
);
Debug
.
Assert
(!
IsConditionalState
);
if
(
slot
>
0
&&
parameter
.
RefKind
!=
RefKind
.
Out
)
{
...
...
@@ -928,13 +933,14 @@ private TypeSymbolWithAnnotations GetReturnType()
{
var
method
=
(
MethodSymbol
)
_member
;
var
returnType
=
(
_useMethodSignatureReturnType
?
_methodSignatureOpt
:
method
).
ReturnType
;
returnType
=
GetAdjustedTyp
e
(
returnType
);
returnType
=
UnconstrainedTypeParametersAsNullabl
e
(
returnType
);
Debug
.
Assert
((
object
)
returnType
!=
LambdaSymbol
.
ReturnTypeIsBeingInferred
);
return
method
.
IsGenericTaskReturningAsync
(
compilation
)
?
((
NamedTypeSymbol
)
returnType
.
TypeSymbol
).
TypeArgumentsNoUseSiteDiagnostics
.
Single
()
:
returnType
;
}
// Consider making these local functions.
private
static
bool
IsNullable
(
TypeSymbolWithAnnotations
typeOpt
)
{
return
!
typeOpt
.
IsNull
&&
typeOpt
.
IsNullable
==
true
;
...
...
@@ -986,7 +992,7 @@ public override BoundNode VisitLocalDeclaration(BoundLocalDeclaration node)
(
initializer
,
conversion
)
=
RemoveConversion
(
initializer
,
includeExplicitConversions
:
false
);
TypeSymbolWithAnnotations
valueType
=
VisitRvalueWithResult
(
initializer
);
TypeSymbolWithAnnotations
type
=
GetAdjustedTyp
e
(
local
.
Type
);
TypeSymbolWithAnnotations
type
=
UnconstrainedTypeParametersAsNullabl
e
(
local
.
Type
);
if
(
node
.
DeclaredType
.
InferredType
)
{
...
...
@@ -1895,7 +1901,7 @@ public override BoundNode VisitCall(BoundCall node)
//if (this.State.Reachable) // PROTOTYPE(NullableReferenceTypes): Consider reachability?
{
_resultType
=
GetAdjustedTyp
e
(
method
.
ReturnType
);
_resultType
=
UnconstrainedTypeParametersAsNullabl
e
(
method
.
ReturnType
);
}
return
null
;
...
...
@@ -2777,7 +2783,7 @@ public override BoundNode VisitConversion(BoundConversion node)
Visit
(
operand
);
TypeSymbolWithAnnotations
operandType
=
_resultType
;
TypeSymbolWithAnnotations
explicitType
=
GetAdjustedTyp
e
(
node
.
ConversionGroupOpt
?.
ExplicitType
);
TypeSymbolWithAnnotations
explicitType
=
UnconstrainedTypeParametersAsNullabl
e
(
node
.
ConversionGroupOpt
?.
ExplicitType
);
bool
fromExplicitCast
=
!
explicitType
.
IsNull
;
TypeSymbolWithAnnotations
resultType
=
ApplyConversion
(
node
,
operand
,
conversion
,
explicitType
.
TypeSymbol
??
node
.
Type
,
operandType
,
checkConversion
:
!
fromExplicitCast
,
fromExplicitCast
:
fromExplicitCast
,
out
bool
_
);
...
...
@@ -3480,13 +3486,14 @@ private TypeSymbolWithAnnotations GetDeclaredLocalResult(LocalSymbol local)
return
_variableTypes
.
TryGetValue
(
local
,
out
TypeSymbolWithAnnotations
type
)
?
type
:
local
.
Type
;
//UnconstrainedTypeParametersAsNullable(local.Type);
}
private
TypeSymbolWithAnnotations
GetDeclaredParameterResult
(
ParameterSymbol
parameter
)
{
return
_variableTypes
.
TryGetValue
(
parameter
,
out
TypeSymbolWithAnnotations
type
)
?
type
:
GetAdjustedTyp
e
(
parameter
.
Type
);
UnconstrainedTypeParametersAsNullabl
e
(
parameter
.
Type
);
}
public
override
BoundNode
VisitBaseReference
(
BoundBaseReference
node
)
...
...
src/Compilers/CSharp/Portable/Symbols/SymbolWithAnnotations.cs
浏览文件 @
46c71ef2
...
...
@@ -209,12 +209,18 @@ public static TypeSymbolWithAnnotations Create(TypeSymbol typeSymbol, INonNullTy
if
((!
isAnnotated
&&
typeSymbol
is
TypeParameterSymbol
)
||
(
isAnnotated
&&
typeSymbol
.
IsReferenceType
&&
!
typeSymbol
.
IsNullableType
()))
{
// T (leave unannotated)
// string? (leave annotated)
Debug
.
Assert
(!
typeSymbol
.
IsNullableType
());
}
else
{
// PROTOTYPE(NullableReferenceTypes): Investigate whether we can bind unconstrained type
// parameters as annotated during initial binding without causing cycles.
// Initial binding leaves unconstrained type parameters unannotated, NullableWalker will
// set treatUnconstrainedTypeParametersAsNullable where appropriate
// T (leave unannotated when treatUnconstrainedTypeParamersAsNullable is false)
// T (add annotation when treatUnconstrainedTypeParameterAsNullable is true)
// T? where T : class (leave annotated)
// string, int (leave unannotated)
// int?, T? where T : struct (add annotation)
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
浏览文件 @
46c71ef2
...
...
@@ -21123,6 +21123,7 @@ static void F<T>()
var comp = CreateCompilation(
new[] { source, NonNullTypesTrue, NonNullTypesAttributesDefinition },
parseOptions: TestOptions.Regular8);
// PROTOTYPE(NullableReferenceTypes): Improve this diagnostic. default is the cause of the error, but is not mentioned in the diagnostic.
comp.VerifyDiagnostics(
// (5,15): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// T s = default;
...
...
@@ -35863,7 +35864,7 @@ class C3<T3> where T3 : new()
static T3 F3() => new T3();
static void F4()
{
T3 t = (T3)NullableObject(); // warn:
return type T4
may be non-null
T3 t = (T3)NullableObject(); // warn:
T3
may be non-null
}
}
class C4<T4> where T4 : I
...
...
@@ -35873,7 +35874,7 @@ class C4<T4> where T4 : I
static T4 F2() => default(T4); // warn: return type T4 may be non-null
static void F4()
{
T4 t4 = (T4)NullableObject(); // warn:
return type
T4 may be non-null
T4 t4 = (T4)NullableObject(); // warn: T4 may be non-null
}
}
class C5<T5> where T5 : A
...
...
@@ -36204,6 +36205,112 @@ public void UnconstrainedTypeParameter_Return_03()
);
}
[Fact]
public void UnconstrainedTypeParameter_Uninitialized()
{
var source =
@"
class C
{
static void F1<T>()
{
T t;
t.ToString(); // 1
}
}
";
var comp = CreateCompilation(new[] { source, NonNullTypesAttributesDefinition, NonNullTypesTrue }, parseOptions: TestOptions.Regular8);
comp.VerifyDiagnostics(
// (7,9): error CS0165: Use of unassigned local variable 't'
// t.ToString(); // 1
Diagnostic(ErrorCode.ERR_UseDefViolation, "t").WithArguments("t").WithLocation(7, 9)
);
}
[Fact]
public void UnconstrainedTypeParameter_OutVariable()
{
var source =
@"
class C
{
static void F1<T>(out T t) => t = default; // 1
static void F2<T>(out T t) => t = default(T); // 2
static void F3<T>(T t1, out T t2) => t2 = t1;
static void F4<T, U>(U u, out T t) where U : T => t = u;
static void F5<T, U>(U u, out T t) where T : U => t = (T)u; // 3
static void F6<T, U>(U u, out T t) => t = (T)(object)u; // 4
}
";
// PROTOTYPE(NullableReferenceTypes): there should be a warning for F5
var comp = CreateCompilation(new[] { source, NonNullTypesAttributesDefinition, NonNullTypesTrue }, parseOptions: TestOptions.Regular8);
comp.VerifyDiagnostics(
// (4,39): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// static void F1<T>(out T t) => t = default; // 1
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(4, 39),
// (5,39): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// static void F2<T>(out T t) => t = default(T); // 2
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default(T)").WithLocation(5, 39),
// (9,50): warning CS8600: Converting null literal or possible null value to non-nullable type.
// static void F6<T, U>(U u, out T t) => t = (T)(object)u; // 4
Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)u").WithLocation(9, 50)
);
}
[Fact]
public void UnconstrainedTypeParameter_PatternMatching()
{
var source =
@"
class C
{
static void F1<T>(object o, T tin)
{
if (o is T t1)
{
t1.ToString();
}
else
{
t1 = default; // 1
}
t1.ToString(); // 2
if (!(o is T t2))
{
t2 = tin;
}
else
{
t2.ToString();
}
t2.ToString(); // 3
if (!(o is T t3)) return;
t3.ToString();
}
}
";
var comp = CreateCompilation(new[] { source, NonNullTypesAttributesDefinition, NonNullTypesTrue }, parseOptions: TestOptions.Regular8);
comp.VerifyDiagnostics(
// (12,18): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// t1 = default; // 1
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(12, 18),
// (15,9): warning CS8602: Possible dereference of a null reference.
// t1.ToString(); // 2
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1").WithLocation(15, 9),
// (25,9): warning CS8602: Possible dereference of a null reference.
// t2.ToString(); // 3
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t2").WithLocation(25, 9)
);
}
// PROTOTYPE(NullableReferenceTypes): Add tests for unconstrained T in foreach and using
[Fact]
public void TypeParameter_Return_01()
{
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录