Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
9d5bd878
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,发现更多精彩内容 >>
未验证
提交
9d5bd878
编写于
8月 17, 2018
作者:
N
Neal Gafter
提交者:
GitHub
8月 17, 2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Compute val escape for recursive pattern-matching (#29188)
Fixes #28633
上级
eee9bf96
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
282 addition
and
29 deletion
+282
-29
src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs
src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs
+40
-22
src/Compilers/CSharp/Portable/Binder/SwitchBinder.cs
src/Compilers/CSharp/Portable/Binder/SwitchBinder.cs
+3
-1
src/Compilers/CSharp/Portable/Binder/SwitchBinder_Patterns.cs
...Compilers/CSharp/Portable/Binder/SwitchBinder_Patterns.cs
+1
-1
src/Compilers/CSharp/Portable/Binder/SwitchExpressionArmBinder.cs
...ilers/CSharp/Portable/Binder/SwitchExpressionArmBinder.cs
+1
-1
src/Compilers/CSharp/Portable/Binder/SwitchExpressionBinder.cs
...ompilers/CSharp/Portable/Binder/SwitchExpressionBinder.cs
+2
-0
src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs
...ilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs
+1
-0
src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs
...rs/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs
+234
-4
未找到文件。
src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs
浏览文件 @
9d5bd878
...
...
@@ -30,7 +30,8 @@ private BoundExpression BindIsPatternExpression(IsPatternExpressionSyntax node,
expression
=
BadExpression
(
expression
.
Syntax
,
expression
);
}
BoundPattern
pattern
=
BindPattern
(
node
.
Pattern
,
expression
.
Type
,
hasErrors
,
diagnostics
);
uint
inputValEscape
=
GetValEscape
(
expression
,
LocalScopeDepth
);
BoundPattern
pattern
=
BindPattern
(
node
.
Pattern
,
expression
.
Type
,
inputValEscape
,
hasErrors
,
diagnostics
);
hasErrors
|=
pattern
.
HasErrors
;
return
MakeIsPatternExpression
(
node
,
expression
,
pattern
,
GetSpecialType
(
SpecialType
.
System_Boolean
,
diagnostics
,
node
),
...
...
@@ -84,6 +85,7 @@ internal virtual BoundExpression BindSwitchExpressionCore(SwitchExpressionSyntax
internal
BoundPattern
BindPattern
(
PatternSyntax
node
,
TypeSymbol
inputType
,
uint
inputValEscape
,
bool
hasErrors
,
DiagnosticBag
diagnostics
)
{
...
...
@@ -93,16 +95,16 @@ internal virtual BoundExpression BindSwitchExpressionCore(SwitchExpressionSyntax
return
BindDiscardPattern
((
DiscardPatternSyntax
)
node
,
inputType
,
hasErrors
,
diagnostics
);
case
SyntaxKind
.
DeclarationPattern
:
return
BindDeclarationPattern
((
DeclarationPatternSyntax
)
node
,
inputType
,
hasErrors
,
diagnostics
);
return
BindDeclarationPattern
((
DeclarationPatternSyntax
)
node
,
inputType
,
inputValEscape
,
hasErrors
,
diagnostics
);
case
SyntaxKind
.
ConstantPattern
:
return
BindConstantPattern
((
ConstantPatternSyntax
)
node
,
inputType
,
hasErrors
,
diagnostics
);
case
SyntaxKind
.
RecursivePattern
:
return
BindRecursivePattern
((
RecursivePatternSyntax
)
node
,
inputType
,
hasErrors
,
diagnostics
);
return
BindRecursivePattern
((
RecursivePatternSyntax
)
node
,
inputType
,
inputValEscape
,
hasErrors
,
diagnostics
);
case
SyntaxKind
.
VarPattern
:
return
BindVarPattern
((
VarPatternSyntax
)
node
,
inputType
,
hasErrors
,
diagnostics
);
return
BindVarPattern
((
VarPatternSyntax
)
node
,
inputType
,
inputValEscape
,
hasErrors
,
diagnostics
);
default
:
throw
ExceptionUtilities
.
UnexpectedValue
(
node
.
Kind
());
...
...
@@ -364,6 +366,7 @@ internal BoundExpression ConvertPatternExpression(TypeSymbol inputType, CSharpSy
private
BoundPattern
BindDeclarationPattern
(
DeclarationPatternSyntax
node
,
TypeSymbol
inputType
,
uint
inputValEscape
,
bool
hasErrors
,
DiagnosticBag
diagnostics
)
{
...
...
@@ -383,7 +386,8 @@ internal BoundExpression ConvertPatternExpression(TypeSymbol inputType, CSharpSy
}
TypeSymbol
declType
=
boundDeclType
.
Type
;
BindPatternDesignation
(
node
,
node
.
Designation
,
declType
,
typeSyntax
,
diagnostics
,
ref
hasErrors
,
out
Symbol
variableSymbol
,
out
BoundExpression
variableAccess
);
inputValEscape
=
GetValEscape
(
declType
,
inputValEscape
);
BindPatternDesignation
(
node
,
node
.
Designation
,
declType
,
inputValEscape
,
typeSyntax
,
diagnostics
,
ref
hasErrors
,
out
Symbol
variableSymbol
,
out
BoundExpression
variableAccess
);
return
new
BoundDeclarationPattern
(
node
,
variableSymbol
,
variableAccess
,
boundDeclType
,
isVar
,
inputType
,
hasErrors
);
}
...
...
@@ -419,6 +423,7 @@ internal BoundExpression ConvertPatternExpression(TypeSymbol inputType, CSharpSy
PatternSyntax
node
,
VariableDesignationSyntax
designation
,
TypeSymbol
declType
,
uint
inputValEscape
,
TypeSyntax
typeSyntax
,
DiagnosticBag
diagnostics
,
ref
bool
hasErrors
,
...
...
@@ -439,9 +444,7 @@ internal BoundExpression ConvertPatternExpression(TypeSymbol inputType, CSharpSy
}
localSymbol
.
SetType
(
declType
);
// https://github.com/dotnet/roslyn/issues/28633: need to preserve/compute the val escape. The following line
// from master does not work because we don't have a source expression at this point.
// localSymbol.SetValEscape(GetValEscape(sourceExpression, LocalScopeDepth));
localSymbol
.
SetValEscape
(
GetValEscape
(
declType
,
inputValEscape
));
// Check for variable declaration errors.
hasErrors
|=
localSymbol
.
ScopeBinder
.
ValidateDeclarationNameConflictsInScope
(
localSymbol
,
diagnostics
);
...
...
@@ -481,6 +484,16 @@ internal BoundExpression ConvertPatternExpression(TypeSymbol inputType, CSharpSy
}
}
/// <summary>
/// Compute the val escape of an expression of the given <paramref name="type"/>, which is known to be derived
/// from an expression whose escape scope is <paramref name="possibleValEscape"/>. By the language rules, the
/// result is either that same scope (if the type is a ref struct type) or <see cref="Binder.ExternalScope"/>.
/// </summary>
private
static
uint
GetValEscape
(
TypeSymbol
type
,
uint
possibleValEscape
)
{
return
type
.
IsByRefLikeType
?
possibleValEscape
:
Binder
.
ExternalScope
;
}
TypeSymbol
BindRecursivePatternType
(
TypeSyntax
typeSyntax
,
TypeSymbol
inputType
,
DiagnosticBag
diagnostics
,
ref
bool
hasErrors
,
out
BoundTypeExpression
boundDeclType
)
{
if
(
typeSyntax
!=
null
)
...
...
@@ -507,10 +520,11 @@ TypeSymbol BindRecursivePatternType(TypeSyntax typeSyntax, TypeSymbol inputType,
}
}
private
BoundPattern
BindRecursivePattern
(
RecursivePatternSyntax
node
,
TypeSymbol
inputType
,
bool
hasErrors
,
DiagnosticBag
diagnostics
)
private
BoundPattern
BindRecursivePattern
(
RecursivePatternSyntax
node
,
TypeSymbol
inputType
,
uint
inputValEscape
,
bool
hasErrors
,
DiagnosticBag
diagnostics
)
{
TypeSyntax
typeSyntax
=
node
.
Type
;
TypeSymbol
declType
=
BindRecursivePatternType
(
typeSyntax
,
inputType
,
diagnostics
,
ref
hasErrors
,
out
BoundTypeExpression
boundDeclType
);
inputValEscape
=
GetValEscape
(
declType
,
inputValEscape
);
if
(
ShouldUseITuple
(
node
,
declType
,
diagnostics
,
out
NamedTypeSymbol
iTupleType
,
out
MethodSymbol
iTupleGetLength
,
out
MethodSymbol
iTupleGetItem
))
{
...
...
@@ -521,16 +535,16 @@ private BoundPattern BindRecursivePattern(RecursivePatternSyntax node, TypeSymbo
ImmutableArray
<
BoundSubpattern
>
deconstructionSubpatterns
=
default
;
if
(
node
.
DeconstructionPatternClause
!=
null
)
{
deconstructionSubpatterns
=
BindDeconstructionPatternClause
(
node
.
DeconstructionPatternClause
,
declType
,
diagnostics
,
out
deconstructMethod
,
ref
hasErrors
);
deconstructionSubpatterns
=
BindDeconstructionPatternClause
(
node
.
DeconstructionPatternClause
,
declType
,
inputValEscape
,
diagnostics
,
out
deconstructMethod
,
ref
hasErrors
);
}
ImmutableArray
<
BoundSubpattern
>
properties
=
default
;
if
(
node
.
PropertyPatternClause
!=
null
)
{
properties
=
BindPropertyPatternClause
(
node
.
PropertyPatternClause
,
declType
,
diagnostics
,
ref
hasErrors
);
properties
=
BindPropertyPatternClause
(
node
.
PropertyPatternClause
,
declType
,
inputValEscape
,
diagnostics
,
ref
hasErrors
);
}
BindPatternDesignation
(
node
,
node
.
Designation
,
declType
,
typeSyntax
,
diagnostics
,
ref
hasErrors
,
out
Symbol
variableSymbol
,
out
BoundExpression
variableAccess
);
BindPatternDesignation
(
node
,
node
.
Designation
,
declType
,
inputValEscape
,
typeSyntax
,
diagnostics
,
ref
hasErrors
,
out
Symbol
variableSymbol
,
out
BoundExpression
variableAccess
);
return
new
BoundRecursivePattern
(
syntax
:
node
,
declaredType
:
boundDeclType
,
inputType
:
inputType
,
deconstructMethod
:
deconstructMethod
,
deconstruction
:
deconstructionSubpatterns
,
properties
:
properties
,
variable
:
variableSymbol
,
variableAccess
:
variableAccess
,
hasErrors
:
hasErrors
);
...
...
@@ -557,10 +571,12 @@ private BoundPattern BindRecursivePattern(RecursivePatternSyntax node, TypeSymbo
diagnostics
.
Add
(
ErrorCode
.
ERR_ArgumentNameInITuplePattern
,
subpatternSyntax
.
NameColon
.
Location
);
}
// Since the input has been cast to ITuple, it must be escapable.
const
uint
valEscape
=
Binder
.
ExternalScope
;
var
boundSubpattern
=
new
BoundSubpattern
(
subpatternSyntax
,
null
,
BindPattern
(
subpatternSyntax
.
Pattern
,
elementType
,
false
,
diagnostics
));
BindPattern
(
subpatternSyntax
.
Pattern
,
elementType
,
valEscape
,
false
,
diagnostics
));
patterns
.
Add
(
boundSubpattern
);
}
...
...
@@ -570,6 +586,7 @@ private BoundPattern BindRecursivePattern(RecursivePatternSyntax node, TypeSymbo
private
ImmutableArray
<
BoundSubpattern
>
BindDeconstructionPatternClause
(
DeconstructionPatternClauseSyntax
node
,
TypeSymbol
declType
,
uint
inputValEscape
,
DiagnosticBag
diagnostics
,
out
MethodSymbol
deconstructMethod
,
ref
bool
hasErrors
)
...
...
@@ -602,7 +619,7 @@ private BoundPattern BindRecursivePattern(RecursivePatternSyntax node, TypeSymbo
BoundSubpattern
boundSubpattern
=
new
BoundSubpattern
(
subpatternSyntax
,
foundField
,
BindPattern
(
subpatternSyntax
.
Pattern
,
elementType
,
isError
,
diagnostics
));
BindPattern
(
subpatternSyntax
.
Pattern
,
elementType
,
GetValEscape
(
elementType
,
inputValEscape
),
isError
,
diagnostics
));
patterns
.
Add
(
boundSubpattern
);
}
}
...
...
@@ -648,7 +665,7 @@ private BoundPattern BindRecursivePattern(RecursivePatternSyntax node, TypeSymbo
var
boundSubpattern
=
new
BoundSubpattern
(
subPattern
,
parameter
,
BindPattern
(
subPattern
.
Pattern
,
elementType
,
isError
,
diagnostics
)
BindPattern
(
subPattern
.
Pattern
,
elementType
,
GetValEscape
(
elementType
,
inputValEscape
),
isError
,
diagnostics
)
);
patterns
.
Add
(
boundSubpattern
);
}
...
...
@@ -786,7 +803,7 @@ private static FieldSymbol CheckIsTupleElement(SyntaxNode node, NamedTypeSymbol
return
foundElement
;
}
private
BoundPattern
BindVarPattern
(
VarPatternSyntax
node
,
TypeSymbol
inputType
,
bool
hasErrors
,
DiagnosticBag
diagnostics
)
private
BoundPattern
BindVarPattern
(
VarPatternSyntax
node
,
TypeSymbol
inputType
,
uint
inputValEscape
,
bool
hasErrors
,
DiagnosticBag
diagnostics
)
{
TypeSymbol
declType
=
inputType
;
Symbol
foundSymbol
=
BindTypeOrAliasOrKeyword
(
node
.
VarKeyword
,
node
,
diagnostics
,
out
bool
isVar
);
...
...
@@ -797,10 +814,10 @@ private BoundPattern BindVarPattern(VarPatternSyntax node, TypeSymbol inputType,
hasErrors
=
true
;
}
return
BindVarDesignation
(
node
,
node
.
Designation
,
inputType
,
hasErrors
,
diagnostics
);
return
BindVarDesignation
(
node
,
node
.
Designation
,
inputType
,
inputValEscape
,
hasErrors
,
diagnostics
);
}
private
BoundPattern
BindVarDesignation
(
VarPatternSyntax
node
,
VariableDesignationSyntax
designation
,
TypeSymbol
inputType
,
bool
hasErrors
,
DiagnosticBag
diagnostics
)
private
BoundPattern
BindVarDesignation
(
VarPatternSyntax
node
,
VariableDesignationSyntax
designation
,
TypeSymbol
inputType
,
uint
inputValEscape
,
bool
hasErrors
,
DiagnosticBag
diagnostics
)
{
switch
(
designation
.
Kind
())
{
...
...
@@ -811,7 +828,7 @@ private BoundPattern BindVarDesignation(VarPatternSyntax node, VariableDesignati
case
SyntaxKind
.
SingleVariableDesignation
:
{
BindPatternDesignation
(
node
:
node
,
designation
:
designation
,
declType
:
inputType
,
typeSyntax
:
null
,
diagnostics
:
diagnostics
,
node
:
node
,
designation
:
designation
,
declType
:
inputType
,
inputValEscape
:
inputValEscape
,
typeSyntax
:
null
,
diagnostics
:
diagnostics
,
hasErrors
:
ref
hasErrors
,
variableSymbol
:
out
Symbol
variableSymbol
,
variableAccess
:
out
BoundExpression
variableAccess
);
var
boundOperandType
=
new
BoundTypeExpression
(
syntax
:
node
,
aliasOpt
:
null
,
type
:
inputType
);
// fake a type expression for the variable's type
return
new
BoundDeclarationPattern
(
designation
,
variableSymbol
,
variableAccess
,
boundOperandType
,
isVar
:
true
,
inputType
:
inputType
,
hasErrors
:
hasErrors
);
...
...
@@ -837,7 +854,7 @@ private BoundPattern BindVarDesignation(VarPatternSyntax node, VariableDesignati
var
variable
=
tupleDesignation
.
Variables
[
i
];
bool
isError
=
i
>=
elementTypes
.
Length
;
TypeSymbol
elementType
=
isError
?
CreateErrorType
()
:
elementTypes
[
i
];
BoundPattern
pattern
=
BindVarDesignation
(
node
,
variable
,
elementType
,
isError
,
diagnostics
);
BoundPattern
pattern
=
BindVarDesignation
(
node
,
variable
,
elementType
,
GetValEscape
(
elementType
,
inputValEscape
),
isError
,
diagnostics
);
subPatterns
.
Add
(
new
BoundSubpattern
(
variable
,
symbol
:
null
,
pattern
));
}
}
...
...
@@ -853,7 +870,7 @@ private BoundPattern BindVarDesignation(VarPatternSyntax node, VariableDesignati
var
variable
=
tupleDesignation
.
Variables
[
i
];
bool
isError
=
outPlaceholders
.
IsDefaultOrEmpty
||
i
>=
outPlaceholders
.
Length
;
TypeSymbol
elementType
=
isError
?
CreateErrorType
()
:
outPlaceholders
[
i
].
Type
;
BoundPattern
pattern
=
BindVarDesignation
(
node
,
variable
,
elementType
,
isError
,
diagnostics
);
BoundPattern
pattern
=
BindVarDesignation
(
node
,
variable
,
elementType
,
GetValEscape
(
elementType
,
inputValEscape
),
isError
,
diagnostics
);
subPatterns
.
Add
(
new
BoundSubpattern
(
variable
,
symbol
:
null
,
pattern
));
}
}
...
...
@@ -872,6 +889,7 @@ private BoundPattern BindVarDesignation(VarPatternSyntax node, VariableDesignati
ImmutableArray
<
BoundSubpattern
>
BindPropertyPatternClause
(
PropertyPatternClauseSyntax
node
,
TypeSymbol
inputType
,
uint
inputValEscape
,
DiagnosticBag
diagnostics
,
ref
bool
hasErrors
)
{
...
...
@@ -897,7 +915,7 @@ private BoundPattern BindVarDesignation(VarPatternSyntax node, VariableDesignati
member
=
LookupMemberForPropertyPattern
(
inputType
,
name
,
diagnostics
,
ref
hasErrors
,
out
memberType
);
}
BoundPattern
boundPattern
=
BindPattern
(
pattern
,
memberType
,
hasErrors
,
diagnostics
);
BoundPattern
boundPattern
=
BindPattern
(
pattern
,
memberType
,
GetValEscape
(
memberType
,
inputValEscape
),
hasErrors
,
diagnostics
);
builder
.
Add
(
new
BoundSubpattern
(
p
,
member
,
boundPattern
));
}
...
...
src/Compilers/CSharp/Portable/Binder/SwitchBinder.cs
浏览文件 @
9d5bd878
...
...
@@ -43,6 +43,8 @@ protected BoundExpression SwitchGoverningExpression
protected
TypeSymbol
SwitchGoverningType
=>
SwitchGoverningExpression
.
Type
;
protected
uint
SwitchGoverningValEscape
=>
GetValEscape
(
SwitchGoverningExpression
,
LocalScopeDepth
);
protected
DiagnosticBag
SwitchGoverningDiagnostics
{
get
...
...
@@ -212,7 +214,7 @@ private void BuildSwitchLabels(SyntaxList<SwitchLabelSyntax> labelsSyntax, Binde
// bind the pattern, to cause its pattern variables to be inferred if necessary
var
matchLabel
=
(
CasePatternSwitchLabelSyntax
)
labelSyntax
;
var
pattern
=
sectionBinder
.
BindPattern
(
matchLabel
.
Pattern
,
SwitchGoverningType
,
labelSyntax
.
HasErrors
,
tempDiagnosticBag
);
matchLabel
.
Pattern
,
SwitchGoverningType
,
SwitchGoverningValEscape
,
labelSyntax
.
HasErrors
,
tempDiagnosticBag
);
break
;
default
:
...
...
src/Compilers/CSharp/Portable/Binder/SwitchBinder_Patterns.cs
浏览文件 @
9d5bd878
...
...
@@ -253,7 +253,7 @@ internal override void BindPatternSwitchLabelForInference(CasePatternSwitchLabel
{
var
matchLabelSyntax
=
(
CasePatternSwitchLabelSyntax
)
node
;
BoundPattern
pattern
=
sectionBinder
.
BindPattern
(
matchLabelSyntax
.
Pattern
,
SwitchGoverningType
,
node
.
HasErrors
,
diagnostics
);
matchLabelSyntax
.
Pattern
,
SwitchGoverningType
,
SwitchGoverningValEscape
,
node
.
HasErrors
,
diagnostics
);
return
new
BoundPatternSwitchLabel
(
node
,
label
,
pattern
,
matchLabelSyntax
.
WhenClause
!=
null
?
sectionBinder
.
BindBooleanExpression
(
matchLabelSyntax
.
WhenClause
.
Condition
,
diagnostics
)
:
null
,
node
.
HasErrors
);
...
...
src/Compilers/CSharp/Portable/Binder/SwitchExpressionArmBinder.cs
浏览文件 @
9d5bd878
...
...
@@ -36,7 +36,7 @@ internal override BoundSwitchExpressionArm BindSwitchExpressionArm(SwitchExpress
Binder
armBinder
=
this
.
GetBinder
(
node
);
bool
hasErrors
=
_switchExpressionBinder
.
SwitchGoverningType
.
IsErrorType
();
ImmutableArray
<
LocalSymbol
>
locals
=
_armScopeBinder
.
Locals
;
BoundPattern
pattern
=
armBinder
.
BindPattern
(
node
.
Pattern
,
_switchExpressionBinder
.
SwitchGoverningType
,
hasErrors
,
diagnostics
);
BoundPattern
pattern
=
armBinder
.
BindPattern
(
node
.
Pattern
,
_switchExpressionBinder
.
SwitchGoverningType
,
_switchExpressionBinder
.
SwitchGoverningValEscape
,
hasErrors
,
diagnostics
);
BoundExpression
whenClause
=
node
.
WhenClause
!=
null
?
armBinder
.
BindBooleanExpression
(
node
.
WhenClause
.
Condition
,
diagnostics
)
:
null
;
...
...
src/Compilers/CSharp/Portable/Binder/SwitchExpressionBinder.cs
浏览文件 @
9d5bd878
...
...
@@ -162,6 +162,8 @@ internal BoundExpression InputExpression
internal
TypeSymbol
SwitchGoverningType
=>
InputExpression
.
Type
;
internal
uint
SwitchGoverningValEscape
=>
GetValEscape
(
InputExpression
,
LocalScopeDepth
);
protected
DiagnosticBag
InputExpressionDiagnostics
{
get
...
...
src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs
浏览文件 @
9d5bd878
...
...
@@ -381,6 +381,7 @@ protected virtual TypeSymbol InferTypeOfVarVariable(DiagnosticBag diagnostics)
internal
void
SetType
(
TypeSymbol
newType
)
{
Debug
.
Assert
(!(
newType
is
null
));
TypeSymbol
originalType
=
_type
;
// In the event that we race to set the type of a local, we should
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs
浏览文件 @
9d5bd878
...
...
@@ -6558,9 +6558,9 @@ public static bool M2(bool e)
False"
);
}
[
Fact
(
Skip
=
"https://github.com/dotnet/roslyn/issues/28633"
)
]
[
Fact
]
[
WorkItem
(
27218
,
"https://github.com/dotnet/roslyn/issues/27218"
)]
public
void
IsPatternMatchingDoesNotCopyEscapeScopes
()
public
void
IsPatternMatchingDoesNotCopyEscapeScopes
_01
()
{
CreateCompilationWithMscorlibAndSpan
(
@"
using System;
...
...
@@ -6582,9 +6582,9 @@ public class C
Diagnostic
(
ErrorCode
.
ERR_EscapeLocal
,
"inner"
).
WithArguments
(
"inner"
).
WithLocation
(
10
,
24
));
}
[
Fact
(
Skip
=
"https://github.com/dotnet/roslyn/issues/28633"
)
]
[
Fact
]
[
WorkItem
(
27218
,
"https://github.com/dotnet/roslyn/issues/27218"
)]
public
void
CasePatternMatchingDoesNotCopyEscapeScopes
()
public
void
CasePatternMatchingDoesNotCopyEscapeScopes
_01
()
{
CreateCompilationWithMscorlibAndSpan
(
@"
using System;
...
...
@@ -6608,5 +6608,235 @@ public class C
// return ref inner[5];
Diagnostic
(
ErrorCode
.
ERR_EscapeLocal
,
"inner"
).
WithArguments
(
"inner"
).
WithLocation
(
12
,
28
));
}
[
Fact
]
[
WorkItem
(
28633
,
"https://github.com/dotnet/roslyn/issues/28633"
)]
public
void
CasePatternMatchingDoesNotCopyEscapeScopes_02
()
{
CreateCompilationWithMscorlibAndSpan
(
parseOptions
:
TestOptions
.
RegularWithRecursivePatterns
,
text
:
@"
using System;
public ref struct R
{
public R Prop => this;
public void Deconstruct(out R X, out R Y) => X = Y = this;
public static implicit operator R(Span<int> span) => new R();
}
public class C
{
public R M1()
{
R outer = stackalloc int[100];
switch (outer)
{
case { Prop: var x }: return x; // error 1
}
}
public R M2()
{
R outer = stackalloc int[100];
switch (outer)
{
case { Prop: R x }: return x; // error 2
}
}
public R M3()
{
R outer = stackalloc int[100];
switch (outer)
{
case (var x, var y): return x; // error 3
}
}
public R M4()
{
R outer = stackalloc int[100];
switch (outer)
{
case (R x, R y): return x; // error 4
}
}
public R M5()
{
R outer = stackalloc int[100];
switch (outer)
{
case var (x, y): return x; // error 5
}
}
public R M6()
{
R outer = stackalloc int[100];
switch (outer)
{
case { } x: return x; // error 6
}
}
public R M7()
{
R outer = stackalloc int[100];
switch (outer)
{
case (_, _) x: return x; // error 7
}
}
}
"
).
VerifyDiagnostics
(
// (16,42): error CS8352: Cannot use local 'x' in this context because it may expose referenced variables outside of their declaration scope
// case { Prop: var x }: return x; // error 1
Diagnostic
(
ErrorCode
.
ERR_EscapeLocal
,
"x"
).
WithArguments
(
"x"
).
WithLocation
(
16
,
42
),
// (24,40): error CS8352: Cannot use local 'x' in this context because it may expose referenced variables outside of their declaration scope
// case { Prop: R x }: return x; // error 2
Diagnostic
(
ErrorCode
.
ERR_EscapeLocal
,
"x"
).
WithArguments
(
"x"
).
WithLocation
(
24
,
40
),
// (32,41): error CS8352: Cannot use local 'x' in this context because it may expose referenced variables outside of their declaration scope
// case (var x, var y): return x; // error 3
Diagnostic
(
ErrorCode
.
ERR_EscapeLocal
,
"x"
).
WithArguments
(
"x"
).
WithLocation
(
32
,
41
),
// (40,37): error CS8352: Cannot use local 'x' in this context because it may expose referenced variables outside of their declaration scope
// case (R x, R y): return x; // error 4
Diagnostic
(
ErrorCode
.
ERR_EscapeLocal
,
"x"
).
WithArguments
(
"x"
).
WithLocation
(
40
,
37
),
// (48,37): error CS8352: Cannot use local 'x' in this context because it may expose referenced variables outside of their declaration scope
// case var (x, y): return x; // error 5
Diagnostic
(
ErrorCode
.
ERR_EscapeLocal
,
"x"
).
WithArguments
(
"x"
).
WithLocation
(
48
,
37
),
// (56,32): error CS8352: Cannot use local 'x' in this context because it may expose referenced variables outside of their declaration scope
// case { } x: return x; // error 6
Diagnostic
(
ErrorCode
.
ERR_EscapeLocal
,
"x"
).
WithArguments
(
"x"
).
WithLocation
(
56
,
32
),
// (64,35): error CS8352: Cannot use local 'x' in this context because it may expose referenced variables outside of their declaration scope
// case (_, _) x: return x; // error 7
Diagnostic
(
ErrorCode
.
ERR_EscapeLocal
,
"x"
).
WithArguments
(
"x"
).
WithLocation
(
64
,
35
)
);
}
[
Fact
]
[
WorkItem
(
28633
,
"https://github.com/dotnet/roslyn/issues/28633"
)]
public
void
IsPatternMatchingDoesNotCopyEscapeScopes_02
()
{
CreateCompilationWithMscorlibAndSpan
(
parseOptions
:
TestOptions
.
RegularWithRecursivePatterns
,
text
:
@"
using System;
public ref struct R
{
public R Prop => this;
public void Deconstruct(out R X, out R Y) => X = Y = this;
public static implicit operator R(Span<int> span) => new R();
}
public class C
{
public R M1()
{
R outer = stackalloc int[100];
if (outer is { Prop: var x }) return x; // error 1
throw null;
}
public R M2()
{
R outer = stackalloc int[100];
if (outer is { Prop: R x }) return x; // error 2
throw null;
}
public R M3()
{
R outer = stackalloc int[100];
if (outer is (var x, var y)) return x; // error 3
throw null;
}
public R M4()
{
R outer = stackalloc int[100];
if (outer is (R x, R y)) return x; // error 4
throw null;
}
public R M5()
{
R outer = stackalloc int[100];
if (outer is var (x, y)) return x; // error 5
throw null;
}
public R M6()
{
R outer = stackalloc int[100];
if (outer is { } x) return x; // error 6
throw null;
}
public R M7()
{
R outer = stackalloc int[100];
if (outer is (_, _) x) return x; // error 7
throw null;
}
}
"
).
VerifyDiagnostics
(
// (14,46): error CS8352: Cannot use local 'x' in this context because it may expose referenced variables outside of their declaration scope
// if (outer is { Prop: var x }) return x; // error 1
Diagnostic
(
ErrorCode
.
ERR_EscapeLocal
,
"x"
).
WithArguments
(
"x"
).
WithLocation
(
14
,
46
),
// (20,44): error CS8352: Cannot use local 'x' in this context because it may expose referenced variables outside of their declaration scope
// if (outer is { Prop: R x }) return x; // error 2
Diagnostic
(
ErrorCode
.
ERR_EscapeLocal
,
"x"
).
WithArguments
(
"x"
).
WithLocation
(
20
,
44
),
// (26,45): error CS8352: Cannot use local 'x' in this context because it may expose referenced variables outside of their declaration scope
// if (outer is (var x, var y)) return x; // error 3
Diagnostic
(
ErrorCode
.
ERR_EscapeLocal
,
"x"
).
WithArguments
(
"x"
).
WithLocation
(
26
,
45
),
// (32,41): error CS8352: Cannot use local 'x' in this context because it may expose referenced variables outside of their declaration scope
// if (outer is (R x, R y)) return x; // error 4
Diagnostic
(
ErrorCode
.
ERR_EscapeLocal
,
"x"
).
WithArguments
(
"x"
).
WithLocation
(
32
,
41
),
// (38,41): error CS8352: Cannot use local 'x' in this context because it may expose referenced variables outside of their declaration scope
// if (outer is var (x, y)) return x; // error 5
Diagnostic
(
ErrorCode
.
ERR_EscapeLocal
,
"x"
).
WithArguments
(
"x"
).
WithLocation
(
38
,
41
),
// (44,36): error CS8352: Cannot use local 'x' in this context because it may expose referenced variables outside of their declaration scope
// if (outer is { } x) return x; // error 6
Diagnostic
(
ErrorCode
.
ERR_EscapeLocal
,
"x"
).
WithArguments
(
"x"
).
WithLocation
(
44
,
36
),
// (50,39): error CS8352: Cannot use local 'x' in this context because it may expose referenced variables outside of their declaration scope
// if (outer is (_, _) x) return x; // error 7
Diagnostic
(
ErrorCode
.
ERR_EscapeLocal
,
"x"
).
WithArguments
(
"x"
).
WithLocation
(
50
,
39
)
);
}
[
Fact
]
[
WorkItem
(
28633
,
"https://github.com/dotnet/roslyn/issues/28633"
)]
public
void
EscapeScopeInSubpatternOfNonRefType
()
{
CreateCompilationWithMscorlibAndSpan
(
parseOptions
:
TestOptions
.
RegularWithRecursivePatterns
,
text
:
@"
using System;
public ref struct R
{
public R RProp => this;
public S SProp => new S();
public void Deconstruct(out S X, out S Y) => X = Y = new S();
public static implicit operator R(Span<int> span) => new R();
}
public struct S
{
public R RProp => new R();
}
public class C
{
public R M1()
{
R outer = stackalloc int[100];
if (outer is { SProp: { RProp: var x }}) return x; // OK
throw null;
}
public R M2()
{
R outer = stackalloc int[100];
switch (outer)
{
case { SProp: { RProp: var x }}: return x; // OK
}
}
public R M3()
{
R outer = stackalloc int[100];
if (outer is ({ RProp: var x }, _)) return x; // OK
throw null;
}
public R M4()
{
R outer = stackalloc int[100];
switch (outer)
{
case ({ RProp: var x }, _): return x; // OK
}
}
}
"
).
VerifyDiagnostics
(
);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录