Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
52444741
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,发现更多精彩内容 >>
未验证
提交
52444741
编写于
4月 22, 2020
作者:
N
Neal Gafter
提交者:
GitHub
4月 22, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Update `or` combinator narrowed type per LDM (#43419)
Fixes #43377
上级
324e9a79
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
165 addition
and
16 deletion
+165
-16
src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs
src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs
+76
-15
src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs
.../Portable/Binder/Semantics/Conversions/ConversionsBase.cs
+1
-1
src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests3.cs
...s/CSharp/Test/Semantic/Semantics/PatternMatchingTests3.cs
+88
-0
未找到文件。
src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs
浏览文件 @
52444741
...
...
@@ -1337,8 +1337,83 @@ void addSubpatternsForTuple(ImmutableArray<TypeWithAnnotations> elementTypes)
permitDesignations
=
false
;
// prevent designators under 'or'
var
left
=
BindPattern
(
node
.
LeftPattern
,
inputType
,
inputValEscape
,
permitDesignations
,
hasErrors
,
diagnostics
);
var
right
=
BindPattern
(
node
.
RightPattern
,
inputType
,
inputValEscape
,
permitDesignations
,
hasErrors
,
diagnostics
);
var
convertedType
=
commonType
(
node
,
left
.
ConvertedType
,
right
.
ConvertedType
,
diagnostics
)
??
inputType
;
// Compute the common type. This algorithm is quadratic, but disjunctive patterns are unlikely to be huge
var
narrowedTypeCandidates
=
ArrayBuilder
<
TypeSymbol
>.
GetInstance
(
2
);
collectCandidates
(
left
,
narrowedTypeCandidates
);
collectCandidates
(
right
,
narrowedTypeCandidates
);
var
convertedType
=
leastSpecificType
(
node
,
narrowedTypeCandidates
,
diagnostics
)
??
inputType
;
narrowedTypeCandidates
.
Free
();
return
new
BoundBinaryPattern
(
node
,
disjunction
:
isDisjunction
,
left
,
right
,
inputType
:
inputType
,
convertedType
:
convertedType
,
hasErrors
);
static
void
collectCandidates
(
BoundPattern
pat
,
ArrayBuilder
<
TypeSymbol
>
candidates
)
{
if
(
pat
is
BoundBinaryPattern
{
Disjunction
:
true
}
p
)
{
collectCandidates
(
p
.
Left
,
candidates
);
collectCandidates
(
p
.
Right
,
candidates
);
}
else
{
candidates
.
Add
(
pat
.
ConvertedType
);
}
}
TypeSymbol
?
leastSpecificType
(
SyntaxNode
node
,
ArrayBuilder
<
TypeSymbol
>
candidates
,
DiagnosticBag
diagnostics
)
{
Debug
.
Assert
(
candidates
.
Count
>=
2
);
HashSet
<
DiagnosticInfo
>?
useSiteDiagnostics
=
null
;
TypeSymbol
?
bestSoFar
=
candidates
[
0
];
// first pass: select a candidate for which no other has been shown to be an improvement.
for
(
int
i
=
1
,
n
=
candidates
.
Count
;
i
<
n
;
i
++)
{
TypeSymbol
candidate
=
candidates
[
i
];
bestSoFar
=
lessSpecificCandidate
(
bestSoFar
,
candidate
,
ref
useSiteDiagnostics
)
??
bestSoFar
;
}
// second pass: check that it is no more specific than any candidate.
for
(
int
i
=
0
,
n
=
candidates
.
Count
;
i
<
n
;
i
++)
{
TypeSymbol
candidate
=
candidates
[
i
];
TypeSymbol
?
spoiler
=
lessSpecificCandidate
(
candidate
,
bestSoFar
,
ref
useSiteDiagnostics
);
if
(
spoiler
is
null
)
{
bestSoFar
=
null
;
break
;
}
// Our specificity criteria are transitive
Debug
.
Assert
(
spoiler
.
Equals
(
bestSoFar
,
TypeCompareKind
.
ConsiderEverything
));
}
diagnostics
.
Add
(
node
.
Location
,
useSiteDiagnostics
);
return
bestSoFar
;
}
// Given a candidate least specific type so far, attempt to refine it with a possibly less specific candidate.
TypeSymbol
?
lessSpecificCandidate
(
TypeSymbol
bestSoFar
,
TypeSymbol
possiblyLessSpecificCandidate
,
ref
HashSet
<
DiagnosticInfo
>?
useSiteDiagnostics
)
{
if
(
bestSoFar
.
Equals
(
possiblyLessSpecificCandidate
,
TypeCompareKind
.
AllIgnoreOptions
))
{
// When the types are equivalent, merge them.
return
bestSoFar
.
MergeEquivalentTypes
(
possiblyLessSpecificCandidate
,
VarianceKind
.
Out
);
}
else
if
(
Conversions
.
HasImplicitReferenceConversion
(
bestSoFar
,
possiblyLessSpecificCandidate
,
ref
useSiteDiagnostics
))
{
// When there is an implicit reference conversion from T to U, U is less specific
return
possiblyLessSpecificCandidate
;
}
else
if
(
Conversions
.
HasBoxingConversion
(
bestSoFar
,
possiblyLessSpecificCandidate
,
ref
useSiteDiagnostics
))
{
// when there is a boxing conversion from T to U, U is less specific.
return
possiblyLessSpecificCandidate
;
}
else
{
// We have no improved candidate to offer.
return
null
;
}
}
}
else
{
...
...
@@ -1347,20 +1422,6 @@ void addSubpatternsForTuple(ImmutableArray<TypeWithAnnotations> elementTypes)
var
right
=
BindPattern
(
node
.
RightPattern
,
left
.
ConvertedType
,
leftOutputValEscape
,
permitDesignations
,
hasErrors
,
diagnostics
);
return
new
BoundBinaryPattern
(
node
,
disjunction
:
isDisjunction
,
left
,
right
,
inputType
:
inputType
,
convertedType
:
right
.
ConvertedType
,
hasErrors
);
}
TypeSymbol
commonType
(
SyntaxNode
node
,
TypeSymbol
t1
,
TypeSymbol
t2
,
DiagnosticBag
diagnostics
)
{
if
(
t1
.
Equals
(
t2
,
TypeCompareKind
.
AllIgnoreOptions
))
return
t2
;
HashSet
<
DiagnosticInfo
>?
useSiteDiagnostics
=
null
;
TypeSymbol
result
=
(
ExpressionOfTypeMatchesPatternType
(
Conversions
,
expressionType
:
t1
,
patternType
:
t2
,
ref
useSiteDiagnostics
,
out
_
)
==
true
)
?
t2
:
(
ExpressionOfTypeMatchesPatternType
(
Conversions
,
expressionType
:
t2
,
patternType
:
t1
,
ref
useSiteDiagnostics
,
out
_
)
==
true
)
?
t1
:
inputType
;
diagnostics
.
Add
(
node
.
Location
,
useSiteDiagnostics
);
return
result
;
}
}
}
}
src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs
浏览文件 @
52444741
...
...
@@ -2308,7 +2308,7 @@ private bool HasImplicitReferenceConversion(TypeWithAnnotations source, TypeWith
return
HasImplicitReferenceConversion
(
source
.
Type
,
destination
.
Type
,
ref
useSiteDiagnostics
);
}
private
bool
HasImplicitReferenceConversion
(
TypeSymbol
source
,
TypeSymbol
destination
,
ref
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
)
internal
bool
HasImplicitReferenceConversion
(
TypeSymbol
source
,
TypeSymbol
destination
,
ref
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
)
{
Debug
.
Assert
((
object
)
source
!=
null
);
Debug
.
Assert
((
object
)
destination
!=
null
);
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests3.cs
浏览文件 @
52444741
...
...
@@ -3241,6 +3241,94 @@ class Q: System.Runtime.CompilerServices.ITuple
var
compVerifier
=
CompileAndVerify
(
compilation
,
expectedOutput
:
expectedOutput
);
}
[
Fact
,
WorkItem
(
43377
,
"https://github.com/dotnet/roslyn/issues/43377"
)]
public
void
OutputType_02
()
{
var
source
=
@"#nullable enable
using System;
using System.Collections.Generic;
class C
{
static void Main()
{
// The narrowed type of an or pattern combines the narrowed type of all subpatterns
// beneath all of the or combinators.
// Identity conversions
object o = new Dictionary<object, object>();
{ if (o is (Dictionary<object, dynamic> or Dictionary<dynamic?, object?>) and var i) M(i); } // System.Collections.Generic.Dictionary<object, object>
// Boxing conversions
o = 1;
{ if (o is (long or IComparable) and var i) M(i); } // System.IComparable
{ if (o is (IComparable or long) and var i) M(i); } // System.IComparable
// Incomparable types
o = 1L;
{ if (o is (IEquatable<string> or long) and var i) M(i); } // System.Object
{ if (o is (long or IEquatable<string>) and var i) M(i); } // System.Object
o = new Derived1();
{ if (o is (Derived1 or Derived2) and var i) M(i); } // System.Object
// Implicit reference conversions
o = new Derived1();
{ if (o is (Derived1 or Base) and var i) M(i); } // Base
{ if (o is (Base or Derived1) and var i) M(i); } // Base
// Implicit reference conversions involving variance
o = new X();
{ if (o is (IIn<Derived1> or IIn<Base>) and var i) M(i); } // IIn<Derived1>
{ if (o is (IIn<Base> or IIn<Derived1>) and var i) M(i); } // IIn<Derived1>
{ if (o is (IOut<Derived1> or IOut<Base>) and var i) M(i); } // IOut<Base>
{ if (o is (IOut<Base> or IOut<Derived1>) and var i) M(i); } // IOut<Base>
// Multiple layers of or patterns
o = new Derived1();
{ if (o is (Derived1 or Derived2 or Base) and var i) M(i); } // Base
{ if (o is ((Derived1 or Derived2) or Base) and var i) M(i); } // Base
{ if (o is (Base or (Derived1 or Derived2)) and var i) M(i); } // Base
{ if (o is (Derived1 or Base or Derived2) and var i) M(i); } // Base
{ if (o is ((Derived1 or Derived2) or (Derived1 or Derived2) or Base or (Derived1 or Derived2)) and var i) M(i); } // Base
}
static void M<T>(T t)
{
Console.WriteLine(typeof(T));
}
}
class Base { }
class Derived1 : Base { }
class Derived2 : Base { }
interface IIn<in T> { }
interface IOut<out T> { }
class X : IIn<Base>, IOut<Base> { }
"
;
var
expectedOutput
=
@"System.Collections.Generic.Dictionary`2[System.Object,System.Object]
System.IComparable
System.IComparable
System.Object
System.Object
System.Object
Base
Base
IIn`1[Derived1]
IIn`1[Derived1]
IOut`1[Base]
IOut`1[Base]
Base
Base
Base
Base
Base
"
;
var
compilation
=
CreateCompilation
(
source
+
_iTupleSource
,
options
:
TestOptions
.
DebugExe
,
parseOptions
:
TestOptions
.
Regular
.
WithLanguageVersion
(
LanguageVersion
.
Preview
));
compilation
.
VerifyDiagnostics
(
);
var
compVerifier
=
CompileAndVerify
(
compilation
,
expectedOutput
:
expectedOutput
);
}
[
Fact
]
public
void
DoNotShareTempMutatedThroughReceiver_01
()
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录