Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
2c6e8fa2
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,发现更多精彩内容 >>
提交
2c6e8fa2
编写于
1月 06, 2017
作者:
V
VSadov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Foreach deconstruction should mark iteration variables as assigned.
Fixes:#16106
上级
ea309794
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
118 addition
and
92 deletion
+118
-92
src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs
src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs
+12
-2
src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml
src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml
+1
-1
src/Compilers/CSharp/Portable/BoundTree/Statement.cs
src/Compilers/CSharp/Portable/BoundTree/Statement.cs
+3
-1
src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPass.cs
src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPass.cs
+17
-22
src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowsOutWalker.cs
...pilers/CSharp/Portable/FlowAnalysis/DataFlowsOutWalker.cs
+0
-5
src/Compilers/CSharp/Portable/FlowAnalysis/PreciseAbstractFlowPass.cs
...s/CSharp/Portable/FlowAnalysis/PreciseAbstractFlowPass.cs
+2
-2
src/Compilers/CSharp/Portable/FlowAnalysis/ReadWriteWalker.cs
...Compilers/CSharp/Portable/FlowAnalysis/ReadWriteWalker.cs
+0
-10
src/Compilers/CSharp/Portable/FlowAnalysis/VariablesDeclaredWalker.cs
...s/CSharp/Portable/FlowAnalysis/VariablesDeclaredWalker.cs
+11
-5
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_ForEachStatement.cs
.../Lowering/LocalRewriter/LocalRewriter_ForEachStatement.cs
+12
-25
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs
...ilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs
+41
-0
src/Compilers/CSharp/Test/Semantic/Semantics/ForEachTests.cs
src/Compilers/CSharp/Test/Semantic/Semantics/ForEachTests.cs
+19
-19
未找到文件。
src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs
浏览文件 @
2c6e8fa2
...
...
@@ -277,6 +277,16 @@ private BoundForEachStatement BindForEachPartsWorker(DiagnosticBag diagnostics,
BoundStatement
body
=
originalBinder
.
BindPossibleEmbeddedStatement
(
_syntax
.
Statement
,
diagnostics
);
// NOTE: in error cases, binder may collect all kind of variables, not just formally declared iteration variables.
// As a matter of error recovery, we will treat such variables the same as the iteration variables.
// I.E. - they will be considered declared and assigned in each iteration step.
ImmutableArray
<
LocalSymbol
>
iterationVariables
=
this
.
Locals
;
Debug
.
Assert
(
hasErrors
||
_syntax
.
HasErrors
||
iterationVariables
.
All
(
local
=>
local
.
DeclarationKind
==
LocalDeclarationKind
.
ForEachIterationVariable
),
"Should not have iteration variables that are not ForEachIterationVariable in valid code"
);
hasErrors
=
hasErrors
||
boundIterationVariableType
.
HasErrors
||
iterationVariableType
.
IsErrorType
();
// Skip the conversion checks and array/enumerator differentiation if we know we have an error (except local name conflicts).
...
...
@@ -287,7 +297,7 @@ private BoundForEachStatement BindForEachPartsWorker(DiagnosticBag diagnostics,
null
,
// can't be sure that it's complete
default
(
Conversion
),
boundIterationVariableType
,
this
.
IterationVariable
,
iterationVariables
,
collectionExpr
,
deconstructStep
,
body
,
...
...
@@ -379,7 +389,7 @@ private BoundForEachStatement BindForEachPartsWorker(DiagnosticBag diagnostics,
builder
.
Build
(
this
.
Flags
),
elementConversion
,
boundIterationVariableType
,
this
.
IterationVariable
,
iterationVariables
,
convertedCollectionExpression
,
deconstructStep
,
body
,
...
...
src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml
浏览文件 @
2c6e8fa2
...
...
@@ -875,7 +875,7 @@
<!-- This is so the binding API can find produce semantic info if the type is "var". -->
<!-- If there is a deconstruction, there will be no iteration variable (but we'll still have a type for it). -->
<Field
Name=
"IterationVariableType"
Type=
"BoundTypeExpression"
/>
<Field
Name=
"IterationVariable
Opt"
Type=
"LocalSymbol"
Null=
"allow
"
/>
<Field
Name=
"IterationVariable
s"
Type=
"ImmutableArray<LocalSymbol>
"
/>
<!-- If this node does not have errors, then this is the foreach expression wrapped
in a conversion to the collection type used by the foreach loop. The conversion
is here so that the binding API can return the correct ConvertedType in semantic
...
...
src/Compilers/CSharp/Portable/BoundTree/Statement.cs
浏览文件 @
2c6e8fa2
...
...
@@ -262,7 +262,9 @@ public override void Accept(OperationVisitor visitor)
internal
partial
class
BoundForEachStatement
:
IForEachLoopStatement
{
ILocalSymbol
IForEachLoopStatement
.
IterationVariable
=>
this
.
IterationVariableOpt
;
ILocalSymbol
IForEachLoopStatement
.
IterationVariable
=>
this
.
DeconstructionOpt
==
null
?
this
.
IterationVariables
.
FirstOrDefault
():
null
;
IOperation
IForEachLoopStatement
.
Collection
=>
this
.
Expression
;
...
...
src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPass.cs
浏览文件 @
2c6e8fa2
...
...
@@ -1222,16 +1222,6 @@ protected virtual void AssignImpl(BoundNode node, BoundExpression value, RefKind
AssignImpl
(((
BoundRangeVariable
)
node
).
Value
,
value
,
refKind
,
written
,
read
);
break
;
case
BoundKind
.
ForEachStatement
:
{
var
iterationVariable
=
((
BoundForEachStatement
)
node
).
IterationVariableOpt
;
Debug
.
Assert
((
object
)
iterationVariable
!=
null
);
int
slot
=
GetOrCreateSlot
(
iterationVariable
);
if
(
slot
>
0
)
SetSlotState
(
slot
,
written
);
if
(
written
)
NoteWrite
(
iterationVariable
,
value
,
read
);
break
;
}
case
BoundKind
.
BadExpression
:
{
// Sometimes a bad node is not so bad that we cannot analyze it at all.
...
...
@@ -1582,6 +1572,16 @@ public override BoundNode VisitForStatement(BoundForStatement node)
return
result
;
}
public
override
BoundNode
VisitForEachStatement
(
BoundForEachStatement
node
)
{
// NOTE: iteration variables are not declared or assigned
// before the collection expression is evaluated
var
result
=
base
.
VisitForEachStatement
(
node
);
// NOTE: do not report unused iteration variables. They are always considered used.
return
result
;
}
public
override
BoundNode
VisitDoStatement
(
BoundDoStatement
node
)
{
DeclareVariables
(
node
.
Locals
);
...
...
@@ -1598,12 +1598,6 @@ public override BoundNode VisitWhileStatement(BoundWhileStatement node)
return
result
;
}
public
override
BoundNode
VisitForEachStatement
(
BoundForEachStatement
node
)
{
var
result
=
base
.
VisitForEachStatement
(
node
);
return
result
;
}
public
override
BoundNode
VisitIfStatement
(
BoundIfStatement
node
)
{
var
result
=
base
.
VisitIfStatement
(
node
);
...
...
@@ -2186,14 +2180,15 @@ public override BoundNode VisitEventAccess(BoundEventAccess node)
return
result
;
}
public
override
void
VisitForEachIterationVariable
(
BoundForEachStatement
node
)
public
override
void
VisitForEachIterationVariable
s
(
BoundForEachStatement
node
)
{
var
local
=
node
.
IterationVariableOpt
;
if
((
object
)
local
!=
null
)
// declare and assign all iteration variables
foreach
(
var
iterationVariable
in
node
.
IterationVariables
)
{
GetOrCreateSlot
(
local
);
Assign
(
node
,
value
:
null
);
// TODO: node needed? NoteRead(local); // Never warn about unused foreach variables.
Debug
.
Assert
((
object
)
iterationVariable
!=
null
);
int
slot
=
GetOrCreateSlot
(
iterationVariable
);
if
(
slot
>
0
)
SetSlotAssigned
(
slot
);
NoteWrite
(
iterationVariable
,
null
,
read
:
true
);
}
}
...
...
src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowsOutWalker.cs
浏览文件 @
2c6e8fa2
...
...
@@ -147,11 +147,6 @@ private Symbol GetNodeSymbol(BoundNode node)
return
local
?.
DeclarationKind
==
LocalDeclarationKind
.
CatchVariable
?
local
:
null
;
}
case
BoundKind
.
ForEachStatement
:
{
return
((
BoundForEachStatement
)
node
).
IterationVariableOpt
;
}
case
BoundKind
.
RangeVariable
:
{
return
((
BoundRangeVariable
)
node
).
RangeVariableSymbol
;
...
...
src/Compilers/CSharp/Portable/FlowAnalysis/PreciseAbstractFlowPass.cs
浏览文件 @
2c6e8fa2
...
...
@@ -2118,7 +2118,7 @@ public override BoundNode VisitForEachStatement(BoundForEachStatement node)
VisitRvalue
(
node
.
Expression
);
var
breakState
=
this
.
State
.
Clone
();
LoopHead
(
node
);
VisitForEachIterationVariable
(
node
);
VisitForEachIterationVariable
s
(
node
);
VisitStatement
(
node
.
Body
);
ResolveContinues
(
node
.
ContinueLabel
);
LoopTail
(
node
);
...
...
@@ -2126,7 +2126,7 @@ public override BoundNode VisitForEachStatement(BoundForEachStatement node)
return
null
;
}
public
virtual
void
VisitForEachIterationVariable
(
BoundForEachStatement
node
)
public
virtual
void
VisitForEachIterationVariable
s
(
BoundForEachStatement
node
)
{
}
...
...
src/Compilers/CSharp/Portable/FlowAnalysis/ReadWriteWalker.cs
浏览文件 @
2c6e8fa2
...
...
@@ -213,16 +213,6 @@ public override BoundNode VisitUnboundLambda(UnboundLambda node)
return
VisitLambda
(
node
.
BindForErrorRecovery
());
}
public
override
void
VisitForEachIterationVariable
(
BoundForEachStatement
node
)
{
var
local
=
node
.
IterationVariableOpt
;
if
((
object
)
local
!=
null
)
{
GetOrCreateSlot
(
local
);
Assign
(
node
,
value
:
null
);
}
}
public
override
BoundNode
VisitRangeVariable
(
BoundRangeVariable
node
)
{
// Compute the "underlying symbol" for a read of the range variable
...
...
src/Compilers/CSharp/Portable/FlowAnalysis/VariablesDeclaredWalker.cs
浏览文件 @
2c6e8fa2
...
...
@@ -122,16 +122,22 @@ public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatemen
return
base
.
VisitLocalFunctionStatement
(
node
);
}
public
override
void
VisitForEachIterationVariable
(
BoundForEachStatement
node
)
public
override
void
VisitForEachIterationVariable
s
(
BoundForEachStatement
node
)
{
if
(
IsInside
)
{
if
(
node
.
IterationVariableOpt
!=
null
)
var
deconstructionAssignment
=
node
.
DeconstructionOpt
?.
DeconstructionAssignment
;
if
(
deconstructionAssignment
==
null
)
{
_variablesDeclared
.
Add
(
node
.
IterationVariableOpt
);
// regular, not deconstructing, foreach declares exactly one iteration variable
_variablesDeclared
.
Add
(
node
.
IterationVariables
.
Single
());
}
else
{
// deconstruction foreach declares multiple variables
deconstructionAssignment
.
Left
.
VisitAllElements
((
x
,
self
)
=>
self
.
Visit
(
x
),
this
);
}
node
.
DeconstructionOpt
?.
DeconstructionAssignment
.
Left
.
VisitAllElements
((
x
,
self
)
=>
self
.
Visit
(
x
),
this
);
}
}
...
...
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_ForEachStatement.cs
浏览文件 @
2c6e8fa2
...
...
@@ -96,9 +96,6 @@ private BoundStatement RewriteEnumeratorForEachStatement(BoundForEachStatement n
InstrumentForEachStatementCollectionVarDeclaration
(
node
,
ref
enumeratorVarDecl
);
// V v
LocalSymbol
iterationVar
=
node
.
IterationVariableOpt
;
//(V)(T)e.Current
BoundExpression
iterationVarAssignValue
=
MakeConversionNode
(
syntax
:
forEachSyntax
,
...
...
@@ -117,8 +114,8 @@ private BoundStatement RewriteEnumeratorForEachStatement(BoundForEachStatement n
// V v = (V)(T)e.Current; -OR- (D1 d1, ...) = (V)(T)e.Current;
ImmutableArray
<
LocalSymbol
>
iterationVariables
;
BoundStatement
iterationVarDecl
=
LocalOrDeconstructionDeclaration
(
node
,
iterationVar
,
iterationVarAssignValue
,
out
iterationVariables
);
ImmutableArray
<
LocalSymbol
>
iterationVariables
=
node
.
IterationVariables
;
BoundStatement
iterationVarDecl
=
LocalOrDeconstructionDeclaration
(
node
,
iterationVar
iables
,
iterationVarAssignValue
);
InstrumentForEachStatementIterationVarDeclaration
(
node
,
ref
iterationVarDecl
);
...
...
@@ -436,7 +433,6 @@ private BoundStatement RewriteStringForEachStatement(BoundForEachStatement node)
// p = p + 1;
BoundStatement
positionIncrement
=
MakePositionIncrement
(
forEachSyntax
,
boundPositionVar
,
intType
);
LocalSymbol
iterationVar
=
node
.
IterationVariableOpt
;
Debug
.
Assert
(
node
.
ElementConversion
.
IsValid
);
// (V)s.Chars[p]
...
...
@@ -453,8 +449,8 @@ private BoundStatement RewriteStringForEachStatement(BoundForEachStatement node)
@checked
:
node
.
Checked
);
// V v = (V)s.Chars[p]; /* OR */ (D1 d1, ...) = (V)s.Chars[p];
ImmutableArray
<
LocalSymbol
>
iterationVariables
;
BoundStatement
iterationVarDecl
=
LocalOrDeconstructionDeclaration
(
node
,
iterationVar
,
iterationVarInitValue
,
out
iterationVariables
);
ImmutableArray
<
LocalSymbol
>
iterationVariables
=
node
.
IterationVariables
;
BoundStatement
iterationVarDecl
=
LocalOrDeconstructionDeclaration
(
node
,
iterationVar
iables
,
iterationVarInitValue
);
InstrumentForEachStatementIterationVarDeclaration
(
node
,
ref
iterationVarDecl
);
...
...
@@ -494,9 +490,8 @@ private BoundStatement RewriteStringForEachStatement(BoundForEachStatement node)
/// </summary>
private
BoundStatement
LocalOrDeconstructionDeclaration
(
BoundForEachStatement
forEachBound
,
LocalSymbol
iterationVar
,
BoundExpression
iterationVarValue
,
out
ImmutableArray
<
LocalSymbol
>
iterationVariables
)
ImmutableArray
<
LocalSymbol
>
iterationVariables
,
BoundExpression
iterationVarValue
)
{
var
forEachSyntax
=
(
CommonForEachStatementSyntax
)
forEachBound
.
Syntax
;
...
...
@@ -506,8 +501,8 @@ private BoundStatement RewriteStringForEachStatement(BoundForEachStatement node)
if
(
deconstruction
==
null
)
{
// V v = /* expression */
iterationVarDecl
=
MakeLocalDeclaration
(
forEachSyntax
,
iterationVar
,
iterationVarValue
);
iterationVar
iables
=
ImmutableArray
.
Create
(
iterationVar
);
Debug
.
Assert
(
iterationVariables
.
Length
==
1
);
iterationVar
Decl
=
MakeLocalDeclaration
(
forEachSyntax
,
iterationVariables
[
0
],
iterationVarValue
);
}
else
{
...
...
@@ -518,8 +513,6 @@ private BoundStatement RewriteStringForEachStatement(BoundForEachStatement node)
BoundExpression
loweredAssignment
=
VisitExpression
(
assignment
);
iterationVarDecl
=
new
BoundExpressionStatement
(
assignment
.
Syntax
,
loweredAssignment
);
RemovePlaceholderReplacement
(
deconstruction
.
TargetPlaceholder
);
iterationVariables
=
GetLocalSymbols
(
assignment
.
Left
);
}
return
iterationVarDecl
;
...
...
@@ -613,9 +606,6 @@ private BoundStatement RewriteSingleDimensionalArrayForEachStatement(BoundForEac
BoundStatement
positionVarDecl
=
MakeLocalDeclaration
(
forEachSyntax
,
positionVar
,
MakeLiteral
(
forEachSyntax
,
ConstantValue
.
Default
(
SpecialType
.
System_Int32
),
intType
));
// V v
LocalSymbol
iterationVar
=
node
.
IterationVariableOpt
;
// (V)a[p]
BoundExpression
iterationVarInitValue
=
MakeConversionNode
(
syntax
:
forEachSyntax
,
...
...
@@ -629,8 +619,8 @@ private BoundStatement RewriteSingleDimensionalArrayForEachStatement(BoundForEac
@checked
:
node
.
Checked
);
// V v = (V)a[p]; /* OR */ (D1 d1, ...) = (V)a[p];
ImmutableArray
<
LocalSymbol
>
iterationVariables
;
BoundStatement
iterationVariableDecl
=
LocalOrDeconstructionDeclaration
(
node
,
iterationVar
,
iterationVarInitValue
,
out
iterationVariables
);
ImmutableArray
<
LocalSymbol
>
iterationVariables
=
node
.
IterationVariables
;
BoundStatement
iterationVariableDecl
=
LocalOrDeconstructionDeclaration
(
node
,
iterationVar
iables
,
iterationVarInitValue
);
InstrumentForEachStatementIterationVarDeclaration
(
node
,
ref
iterationVariableDecl
);
...
...
@@ -771,9 +761,6 @@ private BoundStatement RewriteMultiDimensionalArrayForEachStatement(BoundForEach
boundPositionVar
[
dimension
]
=
MakeBoundLocal
(
forEachSyntax
,
positionVar
[
dimension
],
intType
);
}
// V v
LocalSymbol
iterationVar
=
node
.
IterationVariableOpt
;
// (V)a[p_0, p_1, ...]
BoundExpression
iterationVarInitValue
=
MakeConversionNode
(
syntax
:
forEachSyntax
,
...
...
@@ -787,8 +774,8 @@ private BoundStatement RewriteMultiDimensionalArrayForEachStatement(BoundForEach
// V v = (V)a[p_0, p_1, ...]; /* OR */ (D1 d1, ...) = (V)a[p_0, p_1, ...];
ImmutableArray
<
LocalSymbol
>
iterationVariables
;
BoundStatement
iterationVarDecl
=
LocalOrDeconstructionDeclaration
(
node
,
iterationVar
,
iterationVarInitValue
,
out
iterationVariables
);
ImmutableArray
<
LocalSymbol
>
iterationVariables
=
node
.
IterationVariables
;
BoundStatement
iterationVarDecl
=
LocalOrDeconstructionDeclaration
(
node
,
iterationVar
iables
,
iterationVarInitValue
);
InstrumentForEachStatementIterationVarDeclaration
(
node
,
ref
iterationVarDecl
);
...
...
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs
浏览文件 @
2c6e8fa2
...
...
@@ -6151,5 +6151,46 @@ public static void Main()
compilation
.
VerifyDiagnostics
();
CompileAndVerify
(
compilation
,
expectedOutput
:
"10"
);
}
[
Fact
]
[
WorkItem
(
16106
,
"https://github.com/dotnet/roslyn/issues/16106"
)]
public
void
DefAssignmentsStruct001
()
{
string
source
=
@"
using System.Collections.Generic;
public class MyClass
{
public static void Main()
{
((int, int), string)[] arr = new((int, int), string)[1];
Test5(arr);
}
public static void Test4(IEnumerable<(KeyValuePair<int, int>, string)> en)
{
foreach ((KeyValuePair<int, int> kv, string s) in en)
{
var a = kv.Key; // false error CS0170: Use of possibly unassigned field
}
}
public static void Test5(IEnumerable<((int, int), string)> en)
{
foreach (((int, int k) t, string s) in en)
{
var a = t.k; // false error CS0170: Use of possibly unassigned field
System.Console.WriteLine(a);
}
}
}"
;
var
compilation
=
CreateCompilationWithMscorlib
(
source
,
references
:
new
[]
{
ValueTupleRef
,
SystemRuntimeFacadeRef
},
options
:
TestOptions
.
DebugExe
);
compilation
.
VerifyDiagnostics
();
CompileAndVerify
(
compilation
,
expectedOutput
:
"0"
);
}
}
}
src/Compilers/CSharp/Test/Semantic/Semantics/ForEachTests.cs
浏览文件 @
2c6e8fa2
...
...
@@ -1204,7 +1204,7 @@ void Foo(int[] a)
Assert
.
Equal
(
ConversionKind
.
ImplicitReference
,
info
.
EnumeratorConversion
.
Kind
);
Assert
.
Equal
(
ConversionKind
.
Identity
,
boundNode
.
ElementConversion
.
Kind
);
Assert
.
Equal
(
"System.Int32 x"
,
boundNode
.
IterationVariable
Opt
.
ToTestDisplayString
());
Assert
.
Equal
(
"System.Int32 x"
,
boundNode
.
IterationVariable
s
.
Single
()
.
ToTestDisplayString
());
Assert
.
Equal
(
SpecialType
.
System_Collections_IEnumerable
,
boundNode
.
Expression
.
Type
.
SpecialType
);
Assert
.
Equal
(
SymbolKind
.
ArrayType
,
((
BoundConversion
)
boundNode
.
Expression
).
Operand
.
Type
.
Kind
);
}
...
...
@@ -1236,7 +1236,7 @@ void Foo(string s)
Assert
.
Equal
(
ConversionKind
.
ImplicitReference
,
info
.
EnumeratorConversion
.
Kind
);
Assert
.
Equal
(
ConversionKind
.
Identity
,
boundNode
.
ElementConversion
.
Kind
);
Assert
.
Equal
(
"System.Char c"
,
boundNode
.
IterationVariable
Opt
.
ToTestDisplayString
());
Assert
.
Equal
(
"System.Char c"
,
boundNode
.
IterationVariable
s
.
Single
()
.
ToTestDisplayString
());
Assert
.
Equal
(
SpecialType
.
System_String
,
boundNode
.
Expression
.
Type
.
SpecialType
);
Assert
.
Equal
(
SpecialType
.
System_String
,
((
BoundConversion
)
boundNode
.
Expression
).
Operand
.
Type
.
SpecialType
);
}
...
...
@@ -1279,7 +1279,7 @@ class Enumerator
Assert
.
Equal
(
ConversionKind
.
ImplicitReference
,
info
.
EnumeratorConversion
.
Kind
);
Assert
.
Equal
(
ConversionKind
.
ImplicitNumeric
,
boundNode
.
ElementConversion
.
Kind
);
Assert
.
Equal
(
"System.Int64 x"
,
boundNode
.
IterationVariable
Opt
.
ToTestDisplayString
());
Assert
.
Equal
(
"System.Int64 x"
,
boundNode
.
IterationVariable
s
.
Single
()
.
ToTestDisplayString
());
Assert
.
Equal
(
"Enumerable"
,
boundNode
.
Expression
.
Type
.
ToTestDisplayString
());
Assert
.
Equal
(
"Enumerable"
,
((
BoundConversion
)
boundNode
.
Expression
).
Operand
.
Type
.
ToTestDisplayString
());
}
...
...
@@ -1322,7 +1322,7 @@ struct Enumerator
Assert
.
Equal
(
ConversionKind
.
Boxing
,
info
.
EnumeratorConversion
.
Kind
);
Assert
.
Equal
(
ConversionKind
.
ImplicitNumeric
,
boundNode
.
ElementConversion
.
Kind
);
Assert
.
Equal
(
"System.Int64 x"
,
boundNode
.
IterationVariable
Opt
.
ToTestDisplayString
());
Assert
.
Equal
(
"System.Int64 x"
,
boundNode
.
IterationVariable
s
.
Single
()
.
ToTestDisplayString
());
Assert
.
Equal
(
"Enumerable"
,
boundNode
.
Expression
.
Type
.
ToTestDisplayString
());
Assert
.
Equal
(
"Enumerable"
,
((
BoundConversion
)
boundNode
.
Expression
).
Operand
.
Type
.
ToTestDisplayString
());
}
...
...
@@ -1354,7 +1354,7 @@ void Foo(System.Collections.IEnumerable e)
Assert
.
Equal
(
ConversionKind
.
ImplicitReference
,
info
.
EnumeratorConversion
.
Kind
);
Assert
.
Equal
(
ConversionKind
.
Unboxing
,
boundNode
.
ElementConversion
.
Kind
);
Assert
.
Equal
(
"System.Int64 x"
,
boundNode
.
IterationVariable
Opt
.
ToTestDisplayString
());
Assert
.
Equal
(
"System.Int64 x"
,
boundNode
.
IterationVariable
s
.
Single
()
.
ToTestDisplayString
());
Assert
.
Equal
(
"System.Collections.IEnumerable"
,
boundNode
.
Expression
.
Type
.
ToTestDisplayString
());
Assert
.
Equal
(
"System.Collections.IEnumerable"
,
((
BoundConversion
)
boundNode
.
Expression
).
Operand
.
Type
.
ToTestDisplayString
());
}
...
...
@@ -1393,7 +1393,7 @@ class Enumerable : System.Collections.Generic.IEnumerable<int>
Assert
.
Equal
(
ConversionKind
.
ImplicitReference
,
info
.
EnumeratorConversion
.
Kind
);
Assert
.
Equal
(
ConversionKind
.
ImplicitNumeric
,
boundNode
.
ElementConversion
.
Kind
);
Assert
.
Equal
(
"System.Int64 x"
,
boundNode
.
IterationVariable
Opt
.
ToTestDisplayString
());
Assert
.
Equal
(
"System.Int64 x"
,
boundNode
.
IterationVariable
s
.
Single
()
.
ToTestDisplayString
());
Assert
.
Equal
(
"System.Collections.Generic.IEnumerable<System.Int32>"
,
boundNode
.
Expression
.
Type
.
ToTestDisplayString
());
Assert
.
Equal
(
"Enumerable"
,
((
BoundConversion
)
boundNode
.
Expression
).
Operand
.
Type
.
ToTestDisplayString
());
}
...
...
@@ -1434,7 +1434,7 @@ private class Hidden { }
Assert
.
Equal
(
ConversionKind
.
ImplicitReference
,
info
.
EnumeratorConversion
.
Kind
);
Assert
.
Equal
(
ConversionKind
.
Identity
,
boundNode
.
ElementConversion
.
Kind
);
Assert
.
Equal
(
"System.Object x"
,
boundNode
.
IterationVariable
Opt
.
ToTestDisplayString
());
Assert
.
Equal
(
"System.Object x"
,
boundNode
.
IterationVariable
s
.
Single
()
.
ToTestDisplayString
());
Assert
.
Equal
(
SpecialType
.
System_Collections_IEnumerable
,
boundNode
.
Expression
.
Type
.
SpecialType
);
Assert
.
Equal
(
"Enumerable"
,
((
BoundConversion
)
boundNode
.
Expression
).
Operand
.
Type
.
ToTestDisplayString
());
}
...
...
@@ -1472,7 +1472,7 @@ class Enumerable : System.Collections.IEnumerable
Assert
.
Equal
(
ConversionKind
.
ImplicitReference
,
info
.
EnumeratorConversion
.
Kind
);
Assert
.
Equal
(
ConversionKind
.
Unboxing
,
boundNode
.
ElementConversion
.
Kind
);
Assert
.
Equal
(
"System.Int64 x"
,
boundNode
.
IterationVariable
Opt
.
ToTestDisplayString
());
Assert
.
Equal
(
"System.Int64 x"
,
boundNode
.
IterationVariable
s
.
Single
()
.
ToTestDisplayString
());
Assert
.
Equal
(
SpecialType
.
System_Collections_IEnumerable
,
boundNode
.
Expression
.
Type
.
SpecialType
);
Assert
.
Equal
(
"Enumerable"
,
((
BoundConversion
)
boundNode
.
Expression
).
Operand
.
Type
.
ToTestDisplayString
());
}
...
...
@@ -1504,7 +1504,7 @@ void Foo(int[] a)
Assert
.
Equal
(
ConversionKind
.
ImplicitReference
,
info
.
EnumeratorConversion
.
Kind
);
Assert
.
Equal
(
ConversionKind
.
Identity
,
boundNode
.
ElementConversion
.
Kind
);
Assert
.
Equal
(
SpecialType
.
System_Int32
,
boundNode
.
IterationVariable
Opt
.
Type
.
SpecialType
);
Assert
.
Equal
(
SpecialType
.
System_Int32
,
boundNode
.
IterationVariable
s
.
Single
()
.
Type
.
SpecialType
);
}
[
Fact
]
...
...
@@ -1534,7 +1534,7 @@ void Foo(string s)
Assert
.
Equal
(
ConversionKind
.
ImplicitReference
,
info
.
EnumeratorConversion
.
Kind
);
Assert
.
Equal
(
ConversionKind
.
Identity
,
boundNode
.
ElementConversion
.
Kind
);
Assert
.
Equal
(
SpecialType
.
System_Char
,
boundNode
.
IterationVariable
Opt
.
Type
.
SpecialType
);
Assert
.
Equal
(
SpecialType
.
System_Char
,
boundNode
.
IterationVariable
s
.
Single
()
.
Type
.
SpecialType
);
}
[
Fact
]
...
...
@@ -1563,7 +1563,7 @@ class Enumerator
var
boundNode
=
GetBoundForEachStatement
(
text
);
Assert
.
NotNull
(
boundNode
.
EnumeratorInfoOpt
);
Assert
.
Equal
(
ConversionKind
.
Identity
,
boundNode
.
ElementConversion
.
Kind
);
Assert
.
Equal
(
SpecialType
.
System_Int32
,
boundNode
.
IterationVariable
Opt
.
Type
.
SpecialType
);
Assert
.
Equal
(
SpecialType
.
System_Int32
,
boundNode
.
IterationVariable
s
.
Single
()
.
Type
.
SpecialType
);
}
[
Fact
]
...
...
@@ -1587,7 +1587,7 @@ class Enumerable : System.Collections.IEnumerable
var
boundNode
=
GetBoundForEachStatement
(
text
);
Assert
.
NotNull
(
boundNode
.
EnumeratorInfoOpt
);
Assert
.
Equal
(
ConversionKind
.
Identity
,
boundNode
.
ElementConversion
.
Kind
);
Assert
.
Equal
(
SpecialType
.
System_Object
,
boundNode
.
IterationVariable
Opt
.
Type
.
SpecialType
);
Assert
.
Equal
(
SpecialType
.
System_Object
,
boundNode
.
IterationVariable
s
.
Single
()
.
Type
.
SpecialType
);
}
[
Fact
]
...
...
@@ -1619,7 +1619,7 @@ class var { }
Assert
.
Equal
(
ConversionKind
.
ImplicitReference
,
info
.
EnumeratorConversion
.
Kind
);
Assert
.
Equal
(
ConversionKind
.
Identity
,
boundNode
.
ElementConversion
.
Kind
);
Assert
.
Equal
(
"C.var"
,
boundNode
.
IterationVariable
Opt
.
Type
.
ToTestDisplayString
());
Assert
.
Equal
(
"C.var"
,
boundNode
.
IterationVariable
s
.
Single
()
.
Type
.
ToTestDisplayString
());
}
[
Fact
]
...
...
@@ -1649,7 +1649,7 @@ void Foo(dynamic d)
Assert
.
Equal
(
ConversionKind
.
ImplicitReference
,
info
.
EnumeratorConversion
.
Kind
);
Assert
.
Equal
(
ConversionKind
.
ExplicitDynamic
,
boundNode
.
ElementConversion
.
Kind
);
Assert
.
Equal
(
"System.Int32 x"
,
boundNode
.
IterationVariable
Opt
.
ToTestDisplayString
());
Assert
.
Equal
(
"System.Int32 x"
,
boundNode
.
IterationVariable
s
.
Single
()
.
ToTestDisplayString
());
Assert
.
Equal
(
SpecialType
.
System_Collections_IEnumerable
,
boundNode
.
Expression
.
Type
.
SpecialType
);
Assert
.
Equal
(
TypeKind
.
Dynamic
,
((
BoundConversion
)
boundNode
.
Expression
).
Operand
.
Type
.
TypeKind
);
}
...
...
@@ -1681,7 +1681,7 @@ void Foo(dynamic d)
Assert
.
Equal
(
ConversionKind
.
ImplicitReference
,
info
.
EnumeratorConversion
.
Kind
);
Assert
.
Equal
(
ConversionKind
.
Identity
,
boundNode
.
ElementConversion
.
Kind
);
//NB: differs from explicit case
Assert
.
Equal
(
"dynamic x"
,
boundNode
.
IterationVariable
Opt
.
ToTestDisplayString
());
Assert
.
Equal
(
"dynamic x"
,
boundNode
.
IterationVariable
s
.
Single
()
.
ToTestDisplayString
());
Assert
.
Equal
(
SpecialType
.
System_Collections_IEnumerable
,
boundNode
.
Expression
.
Type
.
SpecialType
);
Assert
.
Equal
(
SymbolKind
.
DynamicType
,
((
BoundConversion
)
boundNode
.
Expression
).
Operand
.
Type
.
Kind
);
}
...
...
@@ -1721,7 +1721,7 @@ public class Enumerable<T>
Assert
.
Equal
(
ConversionKind
.
Boxing
,
info
.
EnumeratorConversion
.
Kind
);
Assert
.
Equal
(
ConversionKind
.
Identity
,
boundNode
.
ElementConversion
.
Kind
);
Assert
.
Equal
(
"System.Object x"
,
boundNode
.
IterationVariable
Opt
.
ToTestDisplayString
());
Assert
.
Equal
(
"System.Object x"
,
boundNode
.
IterationVariable
s
.
Single
()
.
ToTestDisplayString
());
Assert
.
Equal
(
"Enumerable<T>"
,
boundNode
.
Expression
.
Type
.
ToTestDisplayString
());
Assert
.
Equal
(
"Enumerable<T>"
,
((
BoundConversion
)
boundNode
.
Expression
).
Operand
.
Type
.
ToTestDisplayString
());
}
...
...
@@ -1804,7 +1804,7 @@ interface MyEnumerator
Assert
.
Equal
(
ConversionKind
.
Boxing
,
info
.
EnumeratorConversion
.
Kind
);
Assert
.
Equal
(
ConversionKind
.
Identity
,
boundNode
.
ElementConversion
.
Kind
);
Assert
.
Equal
(
"System.Object x"
,
boundNode
.
IterationVariable
Opt
.
ToTestDisplayString
());
Assert
.
Equal
(
"System.Object x"
,
boundNode
.
IterationVariable
s
.
Single
()
.
ToTestDisplayString
());
Assert
.
Equal
(
"Enumerable<T>"
,
boundNode
.
Expression
.
Type
.
ToTestDisplayString
());
Assert
.
Equal
(
"Enumerable<T>"
,
((
BoundConversion
)
boundNode
.
Expression
).
Operand
.
Type
.
ToTestDisplayString
());
}
...
...
@@ -1850,7 +1850,7 @@ struct Enumerator
Assert
.
Equal
(
ConversionKind
.
Boxing
,
info
.
EnumeratorConversion
.
Kind
);
Assert
.
Equal
(
ConversionKind
.
ImplicitNumeric
,
boundNode
.
ElementConversion
.
Kind
);
Assert
.
Equal
(
"System.Int64 x"
,
boundNode
.
IterationVariable
Opt
.
ToTestDisplayString
());
Assert
.
Equal
(
"System.Int64 x"
,
boundNode
.
IterationVariable
s
.
Single
()
.
ToTestDisplayString
());
Assert
.
Equal
(
"Enumerable"
,
boundNode
.
Expression
.
Type
.
ToTestDisplayString
());
Assert
.
Equal
(
"Enumerable"
,
((
BoundConversion
)
boundNode
.
Expression
).
Operand
.
Type
.
ToTestDisplayString
());
}
...
...
@@ -3004,7 +3004,7 @@ .maxstack 2
Assert
.
Equal
(
ConversionKind
.
ImplicitReference
,
info
.
EnumeratorConversion
.
Kind
);
Assert
.
Equal
(
ConversionKind
.
Identity
,
boundNode
.
ElementConversion
.
Kind
);
Assert
.
Equal
(
SpecialType
.
System_Char
,
boundNode
.
IterationVariable
Opt
.
Type
.
SpecialType
);
Assert
.
Equal
(
SpecialType
.
System_Char
,
boundNode
.
IterationVariable
s
.
Single
()
.
Type
.
SpecialType
);
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录