Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
1de4314e
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,发现更多精彩内容 >>
未验证
提交
1de4314e
编写于
7月 03, 2018
作者:
C
Charles Stoner
提交者:
GitHub
7月 03, 2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Ignore nullability when checking for duplicate constraints (#28248)
上级
9df66a1f
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
154 addition
and
41 deletion
+154
-41
docs/features/nullable-reference-types.md
docs/features/nullable-reference-types.md
+13
-5
src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs
src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs
+3
-4
src/Compilers/CSharp/Test/Semantic/Semantics/StaticNullChecking.cs
...lers/CSharp/Test/Semantic/Semantics/StaticNullChecking.cs
+138
-32
未找到文件。
docs/features/nullable-reference-types.md
浏览文件 @
1de4314e
...
...
@@ -179,15 +179,23 @@ A warning is reported for inconsistent top-level nullability of constraint types
static
void
F4
<
T
>
where
T
:
class
,
Stream
?
{
}
// warning
static
void
F5
<
T
>
where
T
:
Stream
?,
IDisposable
{
}
// warning
```
An error is reported for duplicate constraints
. _Should the error be reported for duplicates that differ by top-level or nested nullability?_
An error is reported for duplicate constraints
where constraints are compared ignoring top-level and nested nullability.
```
c#
class
C
<
T
>
where
T
:
class
{
static
void
F1
<
U
>()
where
U
:
T
?,
T
?
{
}
// error: duplicate constraint
static
void
F2
<
U
>()
where
U
:
I
<
T
?>,
I
<
T
?>
{
}
// error: duplicate constraint
static
void
F3
<
U
>()
where
U
:
T
,
T
?
{
}
// error?
static
void
F4
<
U
>()
where
U
:
I
<
T
>,
I
<
T
?>
{
}
// error?
static
void
F1
<
U
>()
where
U
:
T
,
T
?
{
}
// error: duplicate constraint
static
void
F2
<
U
>()
where
U
:
I
<
T
>,
I
<
T
?>
{
}
// error: duplicate constraint
}
```
_What are the rules for annotated (unannotated) type arguments for generic type parameters from unannotated (annotated) types and methods?_
```
c#
[
NotNullTypes
(
false
)]
List
<
T
>
F1
<
T
>(
T
t
)
where
T
:
class
{
...
}
[
NotNullTypes
(
true
)]
List
<
T
>
F2
<
T
>(
T
t
)
where
T
:
class
{
...
}
[
NotNullTypes
(
true
)]
List
<
T
?>
F3
<
T
>(
T
?
t
)
where
T
:
class
{
...
}
var
x
=
F1
(
notNullString
);
// List<string!> or List<string~> ?
var
y
=
F1
(
maybeNullString
);
// List<string?> or List<string~> ?
var
z
=
F2
(
obliviousString
);
// List<string~>! or List<string!>! ?
var
w
=
F3
(
obliviousString
);
// List<string~>! or List<string?>! ?
```
## Compiler switch
_Describe behavior when feature is disabled._
src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs
浏览文件 @
1de4314e
...
...
@@ -209,12 +209,11 @@ internal partial class Binder
return
false
;
}
// PROTOTYPE(NullableReferenceTypes): Report ERR_DuplicateBound for
// duplicates that differ by top-level or nested nullability as well?
if
(
constraintTypes
.
Contains
(
c
=>
type
.
Equals
(
c
,
TypeCompareKind
.
AllAspects
)))
// Ignore nullability when comparing constraints.
if
(
constraintTypes
.
Contains
(
c
=>
type
.
Equals
(
c
,
TypeCompareKind
.
ConsiderEverything
)))
{
// "Duplicate constraint '{0}' for type parameter '{1}'"
Error
(
diagnostics
,
ErrorCode
.
ERR_DuplicateBound
,
syntax
,
type
,
typeParameterName
);
Error
(
diagnostics
,
ErrorCode
.
ERR_DuplicateBound
,
syntax
,
type
.
TypeSymbol
.
SetUnknownNullabilityForReferenceTypes
()
,
typeParameterName
);
return
false
;
}
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/StaticNullChecking.cs
浏览文件 @
1de4314e
...
...
@@ -34612,24 +34612,33 @@ class C<V> where V : V?, V? { }
where U3 : T3, T3?;";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8);
comp.VerifyDiagnostics(
// (3,26): error CS0405: Duplicate constraint 'V?' for type parameter 'V'
// class C<V> where V : V?, V? { }
Diagnostic(ErrorCode.ERR_DuplicateBound, "V?").WithArguments("V?", "V").WithLocation(3, 26),
// (3,9): error CS0454: Circular constraint dependency involving 'V' and 'V'
// class C<V> where V : V?, V? { }
Diagnostic(ErrorCode.ERR_CircularConstraint, "V").WithArguments("V", "V").WithLocation(3, 9),
// (1,9): error CS0454: Circular constraint dependency involving 'T' and 'T'
// (1,25): error CS0405: Duplicate constraint 'T' for type parameter 'T'
// class A<T> where T : T, T? { }
Diagnostic(ErrorCode.ERR_
CircularConstraint, "T").WithArguments("T", "T").WithLocation(1, 9
),
Diagnostic(ErrorCode.ERR_
DuplicateBound, "T?").WithArguments("T", "T").WithLocation(1, 25
),
// (1,9): error CS0454: Circular constraint dependency involving 'T' and 'T'
// class A<T> where T : T, T? { }
Diagnostic(ErrorCode.ERR_CircularConstraint, "T").WithArguments("T", "T").WithLocation(1, 9),
// (2,
9): error CS0454: Circular constraint dependency involving 'U' and
'U'
// (2,
26): error CS0405: Duplicate constraint 'U' for type parameter
'U'
// class B<U> where U : U?, U { }
Diagnostic(ErrorCode.ERR_
CircularConstraint, "U").WithArguments("U", "U").WithLocation(2, 9
),
Diagnostic(ErrorCode.ERR_
DuplicateBound, "U").WithArguments("U", "U").WithLocation(2, 26
),
// (2,9): error CS0454: Circular constraint dependency involving 'U' and 'U'
// class B<U> where U : U?, U { }
Diagnostic(ErrorCode.ERR_CircularConstraint, "U").WithArguments("U", "U").WithLocation(2, 9));
Diagnostic(ErrorCode.ERR_CircularConstraint, "U").WithArguments("U", "U").WithLocation(2, 9),
// (3,26): error CS0405: Duplicate constraint 'V' for type parameter 'V'
// class C<V> where V : V?, V? { }
Diagnostic(ErrorCode.ERR_DuplicateBound, "V?").WithArguments("V", "V").WithLocation(3, 26),
// (3,9): error CS0454: Circular constraint dependency involving 'V' and 'V'
// class C<V> where V : V?, V? { }
Diagnostic(ErrorCode.ERR_CircularConstraint, "V").WithArguments("V", "V").WithLocation(3, 9),
// (5,20): error CS0405: Duplicate constraint 'T1' for type parameter 'U1'
// where U1 : T1, T1?;
Diagnostic(ErrorCode.ERR_DuplicateBound, "T1?").WithArguments("T1", "U1").WithLocation(5, 20),
// (7,28): error CS0405: Duplicate constraint 'T2' for type parameter 'U2'
// where U2 : class, T2?, T2;
Diagnostic(ErrorCode.ERR_DuplicateBound, "T2").WithArguments("T2", "U2").WithLocation(7, 28),
// (10,20): error CS0405: Duplicate constraint 'T3' for type parameter 'U3'
// where U3 : T3, T3?;
Diagnostic(ErrorCode.ERR_DuplicateBound, "T3?").WithArguments("T3", "U3").WithLocation(10, 20));
}
[Fact]
...
...
@@ -34870,21 +34879,31 @@ class C<T> where T : class
static void F8<U>() where U : I<T?>, I<T?> { }
}";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8);
// PROTOTYPE(NullableReferenceTypes): Report ERR_DuplicateBound for
// duplicates that differ by top-level or nested nullability as well?
comp.VerifyDiagnostics(
// (4,38): error CS0405: Duplicate constraint 'T' for type parameter 'U'
// static void F1<U>() where U : T, T { }
Diagnostic(ErrorCode.ERR_DuplicateBound, "T").WithArguments("T", "U").WithLocation(4, 38),
// (7,39): error CS0405: Duplicate constraint 'T?' for type parameter 'U'
// (5,38): error CS0405: Duplicate constraint 'T' for type parameter 'U'
// static void F2<U>() where U : T, T? { }
Diagnostic(ErrorCode.ERR_DuplicateBound, "T?").WithArguments("T", "U").WithLocation(5, 38),
// (6,39): error CS0405: Duplicate constraint 'T' for type parameter 'U'
// static void F3<U>() where U : T?, T { }
Diagnostic(ErrorCode.ERR_DuplicateBound, "T").WithArguments("T", "U").WithLocation(6, 39),
// (7,39): error CS0405: Duplicate constraint 'T' for type parameter 'U'
// static void F4<U>() where U : T?, T? { }
Diagnostic(ErrorCode.ERR_DuplicateBound, "T?").WithArguments("T
?
", "U").WithLocation(7, 39),
Diagnostic(ErrorCode.ERR_DuplicateBound, "T?").WithArguments("T", "U").WithLocation(7, 39),
// (8,41): error CS0405: Duplicate constraint 'I<T>' for type parameter 'U'
// static void F5<U>() where U : I<T>, I<T> { }
Diagnostic(ErrorCode.ERR_DuplicateBound, "I<T>").WithArguments("I<T>", "U").WithLocation(8, 41),
// (11,42): error CS0405: Duplicate constraint 'I<T?>' for type parameter 'U'
// (9,41): error CS0405: Duplicate constraint 'I<T>' for type parameter 'U'
// static void F6<U>() where U : I<T>, I<T?> { }
Diagnostic(ErrorCode.ERR_DuplicateBound, "I<T?>").WithArguments("I<T>", "U").WithLocation(9, 41),
// (10,42): error CS0405: Duplicate constraint 'I<T>' for type parameter 'U'
// static void F7<U>() where U : I<T?>, I<T> { }
Diagnostic(ErrorCode.ERR_DuplicateBound, "I<T>").WithArguments("I<T>", "U").WithLocation(10, 42),
// (11,42): error CS0405: Duplicate constraint 'I<T>' for type parameter 'U'
// static void F8<U>() where U : I<T?>, I<T?> { }
Diagnostic(ErrorCode.ERR_DuplicateBound, "I<T?>").WithArguments("I<T
?
>", "U").WithLocation(11, 42));
Diagnostic(ErrorCode.ERR_DuplicateBound, "I<T?>").WithArguments("I<T>", "U").WithLocation(11, 42));
}
[Fact]
...
...
@@ -34908,7 +34927,7 @@ public void TypeUnification_01()
@"interface I<T> { }
class C1<T, U> : I<T>, I<U> { }
class C2<T, U> : I<T>, I<U?> { }
class C3<T, U> : I<T?>, I<U
?
> { }
class C3<T, U> : I<T?>, I<U> { }
class C4<T, U> : I<T?>, I<U?> { }";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8);
comp.VerifyDiagnostics(
...
...
@@ -34919,8 +34938,8 @@ class C4<T, U> : I<T?>, I<U?> { }";
// class C2<T, U> : I<T>, I<U?> { }
Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C2").WithArguments("C2<T, U>", "I<T>", "I<U?>").WithLocation(3, 7),
// (4,7): error CS0695: 'C3<T, U>' cannot implement both 'I<T?>' and 'I<U?>' because they may unify for some type parameter substitutions
// class C3<T, U> : I<T?>, I<U
?
> { }
Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C3").WithArguments("C3<T, U>", "I<T?>", "I<U
?
>").WithLocation(4, 7),
// class C3<T, U> : I<T?>, I<U> { }
Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C3").WithArguments("C3<T, U>", "I<T?>", "I<U>").WithLocation(4, 7),
// (5,7): error CS0695: 'C4<T, U>' cannot implement both 'I<T?>' and 'I<U?>' because they may unify for some type parameter substitutions
// class C4<T, U> : I<T?>, I<U?> { }
Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C4").WithArguments("C4<T, U>", "I<T?>", "I<U?>").WithLocation(5, 7));
...
...
@@ -34933,7 +34952,7 @@ public void TypeUnification_02()
@"interface I<T> { }
class C1<T, U> : I<T>, I<U> where T : struct { }
class C2<T, U> : I<T>, I<U?> where T : struct { }
class C3<T, U> : I<T?>, I<U
?
> where T : struct { }
class C3<T, U> : I<T?>, I<U> where T : struct { }
class C4<T, U> : I<T?>, I<U?> where T : struct { }";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8);
comp.VerifyDiagnostics(
...
...
@@ -34944,8 +34963,8 @@ class C4<T, U> : I<T?>, I<U?> where T : struct { }";
// class C2<T, U> : I<T>, I<U?> where T : struct { }
Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C2").WithArguments("C2<T, U>", "I<T>", "I<U?>").WithLocation(3, 7),
// (4,7): error CS0695: 'C3<T, U>' cannot implement both 'I<T?>' and 'I<U?>' because they may unify for some type parameter substitutions
// class C3<T, U> : I<T?>, I<U
?
> where T : struct { }
Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C3").WithArguments("C3<T, U>", "I<T?>", "I<U
?
>").WithLocation(4, 7),
// class C3<T, U> : I<T?>, I<U> where T : struct { }
Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C3").WithArguments("C3<T, U>", "I<T?>", "I<U>").WithLocation(4, 7),
// (5,7): error CS0695: 'C4<T, U>' cannot implement both 'I<T?>' and 'I<U?>' because they may unify for some type parameter substitutions
// class C4<T, U> : I<T?>, I<U?> where T : struct { }
Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C4").WithArguments("C4<T, U>", "I<T?>", "I<U?>").WithLocation(5, 7));
...
...
@@ -34958,7 +34977,7 @@ public void TypeUnification_03()
@"interface I<T> { }
class C1<T, U> : I<T>, I<U> where T : class { }
class C2<T, U> : I<T>, I<U?> where T : class { }
class C3<T, U> : I<T?>, I<U
?
> where T : class { }
class C3<T, U> : I<T?>, I<U> where T : class { }
class C4<T, U> : I<T?>, I<U?> where T : class { }";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8);
comp.VerifyDiagnostics(
...
...
@@ -34969,8 +34988,8 @@ class C4<T, U> : I<T?>, I<U?> where T : class { }";
// class C2<T, U> : I<T>, I<U?> where T : class { }
Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C2").WithArguments("C2<T, U>", "I<T>", "I<U?>").WithLocation(3, 7),
// (4,7): error CS0695: 'C3<T, U>' cannot implement both 'I<T?>' and 'I<U?>' because they may unify for some type parameter substitutions
// class C3<T, U> : I<T?>, I<U
?
> where T : class { }
Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C3").WithArguments("C3<T, U>", "I<T?>", "I<U
?
>").WithLocation(4, 7),
// class C3<T, U> : I<T?>, I<U> where T : class { }
Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C3").WithArguments("C3<T, U>", "I<T?>", "I<U>").WithLocation(4, 7),
// (5,7): error CS0695: 'C4<T, U>' cannot implement both 'I<T?>' and 'I<U?>' because they may unify for some type parameter substitutions
// class C4<T, U> : I<T?>, I<U?> where T : class { }
Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C4").WithArguments("C4<T, U>", "I<T?>", "I<U?>").WithLocation(5, 7));
...
...
@@ -34983,9 +35002,10 @@ public void TypeUnification_04()
@"interface I<T> { }
class C1<T, U> : I<T>, I<U> where T : struct where U : class { }
class C2<T, U> : I<T>, I<U?> where T : struct where U : class { }
class C3<T, U> : I<T?>, I<U
?
> where T : struct where U : class { }
class C3<T, U> : I<T?>, I<U> where T : struct where U : class { }
class C4<T, U> : I<T?>, I<U?> where T : struct where U : class { }";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8);
// Constraints are ignored when unifying types.
comp.VerifyDiagnostics(
// (2,7): error CS0695: 'C1<T, U>' cannot implement both 'I<T>' and 'I<U>' because they may unify for some type parameter substitutions
// class C1<T, U> : I<T>, I<U> where T : struct where U : class { }
...
...
@@ -34994,8 +35014,8 @@ class C4<T, U> : I<T?>, I<U?> where T : struct where U : class { }";
// class C2<T, U> : I<T>, I<U?> where T : struct where U : class { }
Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C2").WithArguments("C2<T, U>", "I<T>", "I<U?>").WithLocation(3, 7),
// (4,7): error CS0695: 'C3<T, U>' cannot implement both 'I<T?>' and 'I<U?>' because they may unify for some type parameter substitutions
// class C3<T, U> : I<T?>, I<U
?
> where T : struct where U : class { }
Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C3").WithArguments("C3<T, U>", "I<T?>", "I<U
?
>").WithLocation(4, 7),
// class C3<T, U> : I<T?>, I<U> where T : struct where U : class { }
Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C3").WithArguments("C3<T, U>", "I<T?>", "I<U>").WithLocation(4, 7),
// (5,7): error CS0695: 'C4<T, U>' cannot implement both 'I<T?>' and 'I<U?>' because they may unify for some type parameter substitutions
// class C4<T, U> : I<T?>, I<U?> where T : struct where U : class { }
Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C4").WithArguments("C4<T, U>", "I<T?>", "I<U?>").WithLocation(5, 7));
...
...
@@ -35008,7 +35028,7 @@ public void TypeUnification_05()
@"interface I<T> where T : class { }
class C1<T, U> : I<T>, I<U> where T : class where U : class { }
class C2<T, U> : I<T>, I<U?> where T : class where U : class { }
class C3<T, U> : I<T?>, I<U
?
> where T : class where U : class { }
class C3<T, U> : I<T?>, I<U> where T : class where U : class { }
class C4<T, U> : I<T?>, I<U?> where T : class where U : class { }";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8);
comp.VerifyDiagnostics(
...
...
@@ -35019,8 +35039,8 @@ class C4<T, U> : I<T?>, I<U?> where T : class where U : class { }";
// class C2<T, U> : I<T>, I<U?> where T : class where U : class { }
Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C2").WithArguments("C2<T, U>", "I<T>", "I<U?>").WithLocation(3, 7),
// (4,7): error CS0695: 'C3<T, U>' cannot implement both 'I<T?>' and 'I<U?>' because they may unify for some type parameter substitutions
// class C3<T, U> : I<T?>, I<U
?
> where T : class where U : class { }
Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C3").WithArguments("C3<T, U>", "I<T?>", "I<U
?
>").WithLocation(4, 7),
// class C3<T, U> : I<T?>, I<U> where T : class where U : class { }
Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C3").WithArguments("C3<T, U>", "I<T?>", "I<U>").WithLocation(4, 7),
// (5,7): error CS0695: 'C4<T, U>' cannot implement both 'I<T?>' and 'I<U?>' because they may unify for some type parameter substitutions
// class C4<T, U> : I<T?>, I<U?> where T : class where U : class { }
Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C4").WithArguments("C4<T, U>", "I<T?>", "I<U?>").WithLocation(5, 7));
...
...
@@ -35311,6 +35331,92 @@ static void Main()
Assert.Equal("A2<System.Object?>!", typeParameters[1].ConstraintTypesNoUseSiteDiagnostics[0].ToTestDisplayString(true));
}
[Fact]
public void UnannotatedConstraint_Override()
{
var source0 =
@"using System.Runtime.CompilerServices;
public interface I<T> { }
public abstract class A<T> where T : class
{
[NonNullTypes(false)] public abstract void F1<U>() where U : T, I<T>;
[NonNullTypes(false)] public abstract void F2<U>() where U : T?, I<T?>;
[NonNullTypes(true)] public abstract void F3<U>() where U : T, I<T>;
[NonNullTypes(true)] public abstract void F4<U>() where U : T?, I<T?>;
}";
var comp0 = CreateCompilation(new[] { source0, NonNullTypesAttributesDefinition }, parseOptions: TestOptions.Regular8);
comp0.VerifyDiagnostics();
var ref0 = comp0.EmitToImageReference();
var source =
@"using System.Runtime.CompilerServices;
[NonNullTypes(false)]
class B1 : A<string>
{
public override void F1<U>() { }
public override void F2<U>() { }
public override void F3<U>() { }
public override void F4<U>() { }
}
[NonNullTypes(false)]
class B2 : A<string?>
{
public override void F1<U>() { }
public override void F2<U>() { }
public override void F3<U>() { }
public override void F4<U>() { }
}
[NonNullTypes(true)]
class B3 : A<string>
{
public override void F1<U>() { }
public override void F2<U>() { }
public override void F3<U>() { }
public override void F4<U>() { }
}
[NonNullTypes(true)]
class B4 : A<string?>
{
public override void F1<U>() { }
public override void F2<U>() { }
public override void F3<U>() { }
public override void F4<U>() { }
}";
var comp = CreateCompilation(source, references: new[] { new CSharpCompilationReference(comp0) }, parseOptions: TestOptions.Regular8);
comp.VerifyDiagnostics();
verifyAllConstraintTypes();
comp = CreateCompilation(source, references: new[] { comp0.EmitToImageReference() }, parseOptions: TestOptions.Regular8);
comp.VerifyDiagnostics();
verifyAllConstraintTypes();
void verifyAllConstraintTypes()
{
verifyConstraintTypes("B1.F1", "System.String", "I<System.String>");
verifyConstraintTypes("B1.F2", "System.String?", "I<System.String?>");
verifyConstraintTypes("B1.F3", "System.String", "I<System.String>");
verifyConstraintTypes("B1.F4", "System.String?", "I<System.String?>");
verifyConstraintTypes("B2.F1", "System.String?", "I<System.String?>");
verifyConstraintTypes("B2.F2", "System.String?", "I<System.String?>");
verifyConstraintTypes("B2.F3", "System.String?", "I<System.String?>");
verifyConstraintTypes("B2.F4", "System.String?", "I<System.String?>");
verifyConstraintTypes("B3.F1", "System.String!", "I<System.String!>");
verifyConstraintTypes("B3.F2", "System.String?", "I<System.String?>");
verifyConstraintTypes("B3.F3", "System.String!", "I<System.String!>");
verifyConstraintTypes("B3.F4", "System.String?", "I<System.String?>");
verifyConstraintTypes("B4.F1", "System.String?", "I<System.String?>");
verifyConstraintTypes("B4.F2", "System.String?", "I<System.String?>");
verifyConstraintTypes("B4.F3", "System.String?", "I<System.String?>");
verifyConstraintTypes("B4.F4", "System.String?", "I<System.String?>");
}
void verifyConstraintTypes(string methodName, params string[] expectedTypes)
{
var constraintTypes = comp.GetMember<MethodSymbol>(methodName).TypeParameters[0].ConstraintTypesNoUseSiteDiagnostics;
AssertEx.Equal(expectedTypes, constraintTypes.SelectAsArray(t => t.ToTestDisplayString(true)));
}
}
[Fact]
public void Constraint_Oblivious_01()
{
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录