Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
ef76ee11
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,发现更多精彩内容 >>
提交
ef76ee11
编写于
6月 10, 2015
作者:
E
Evan Hauck
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Allow generic local functions
上级
f507de44
变更
13
隐藏空白更改
内联
并排
Showing
13 changed file
with
775 addition
and
105 deletion
+775
-105
src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs
src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs
+13
-4
src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaFrame.cs
...rs/CSharp/Portable/Lowering/LambdaRewriter/LambdaFrame.cs
+2
-2
src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.Analysis.cs
...rtable/Lowering/LambdaRewriter/LambdaRewriter.Analysis.cs
+9
-0
src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.cs
...CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.cs
+67
-53
src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/SynthesizedLambdaMethod.cs
...rtable/Lowering/LambdaRewriter/SynthesizedLambdaMethod.cs
+18
-13
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LoweredDynamicOperationFactory.cs
.../Lowering/LocalRewriter/LoweredDynamicOperationFactory.cs
+1
-0
src/Compilers/CSharp/Portable/Lowering/SynthesizedMethodBaseSymbol.cs
...s/CSharp/Portable/Lowering/SynthesizedMethodBaseSymbol.cs
+1
-1
src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs
...ers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs
+0
-2
src/Compilers/CSharp/Portable/Symbols/SubstitutedTypeParameterSymbol.cs
...CSharp/Portable/Symbols/SubstitutedTypeParameterSymbol.cs
+4
-2
src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs
...harp/Portable/Symbols/Synthesized/SynthesizedContainer.cs
+10
-4
src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedSubstitutedTypeParameterSymbol.cs
.../Synthesized/SynthesizedSubstitutedTypeParameterSymbol.cs
+2
-2
src/Compilers/CSharp/Portable/Symbols/TypeMap.cs
src/Compilers/CSharp/Portable/Symbols/TypeMap.cs
+41
-3
src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs
...lers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs
+607
-19
未找到文件。
src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs
浏览文件 @
ef76ee11
...
...
@@ -131,7 +131,7 @@ public override void VisitParenthesizedLambdaExpression(ParenthesizedLambdaExpre
public
override
void
VisitLocalFunctionStatement
(
LocalFunctionStatementSyntax
node
)
{
var
body
=
(
CSharpSyntaxNode
)
node
.
Body
??
node
.
ExpressionBody
;
Method
Symbol
match
=
null
;
LocalFunction
Symbol
match
=
null
;
// Don't use LookupLocalFunction because it recurses up the tree, as it
// should be defined in the directly enclosing block (see note below)
foreach
(
var
candidate
in
_enclosing
.
LocalFunctions
)
...
...
@@ -149,11 +149,20 @@ public override void VisitLocalFunctionStatement(LocalFunctionStatementSyntax no
{
var
oldMethod
=
_method
;
_method
=
match
;
var
inMethod
=
new
InMethodBinder
(
match
,
_enclosing
);
AddToMap
(
node
,
inMethod
);
Binder
addToMap
;
if
(
match
.
IsGenericMethod
)
{
addToMap
=
new
WithMethodTypeParametersBinder
(
match
,
_enclosing
);
}
else
{
addToMap
=
_enclosing
;
}
addToMap
=
new
InMethodBinder
(
match
,
addToMap
);
AddToMap
(
node
,
addToMap
);
if
(
body
!=
null
)
{
Visit
(
body
,
inMethod
);
Visit
(
body
,
addToMap
);
}
_method
=
oldMethod
;
}
...
...
src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaFrame.cs
浏览文件 @
ef76ee11
...
...
@@ -22,8 +22,8 @@ internal sealed class LambdaFrame : SynthesizedContainer, ISynthesizedMethodBody
internal
readonly
CSharpSyntaxNode
ScopeSyntaxOpt
;
internal
readonly
int
ClosureOrdinal
;
internal
LambdaFrame
(
MethodSymbol
topLevelMethod
,
CSharpSyntaxNode
scopeSyntaxOpt
,
DebugId
methodId
,
DebugId
closureId
)
:
base
(
MakeName
(
scopeSyntaxOpt
,
methodId
,
closureId
),
topLevel
Method
)
internal
LambdaFrame
(
MethodSymbol
topLevelMethod
,
MethodSymbol
containingMethod
,
CSharpSyntaxNode
scopeSyntaxOpt
,
DebugId
methodId
,
DebugId
closureId
)
:
base
(
MakeName
(
scopeSyntaxOpt
,
methodId
,
closureId
),
containing
Method
)
{
_topLevelMethod
=
topLevelMethod
;
_constructor
=
new
LambdaFrameConstructor
(
this
);
...
...
src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.Analysis.cs
浏览文件 @
ef76ee11
...
...
@@ -50,6 +50,11 @@ internal sealed class Analysis : BoundTreeWalker
/// </summary>
public
readonly
Dictionary
<
Symbol
,
BoundNode
>
variableScope
=
new
Dictionary
<
Symbol
,
BoundNode
>();
/// <summary>
/// For each value in variableScope, identifies the closest owning method, lambda, or local function.
/// </summary>
public
readonly
Dictionary
<
BoundNode
,
MethodSymbol
>
scopeOwner
=
new
Dictionary
<
BoundNode
,
MethodSymbol
>();
/// <summary>
/// The syntax nodes associated with each captured variable.
/// </summary>
...
...
@@ -102,6 +107,7 @@ public static Analysis Analyze(BoundNode node, MethodSymbol method)
private
void
Analyze
(
BoundNode
node
)
{
_currentScope
=
FindNodeToAnalyze
(
node
);
scopeOwner
[
_currentScope
]
=
_currentParent
;
Debug
.
Assert
(!
_inExpressionLambda
);
Debug
.
Assert
((
object
)
_topLevelMethod
!=
null
);
...
...
@@ -267,6 +273,8 @@ private BoundNode PushBlock(BoundNode node, ImmutableArray<LocalSymbol> locals)
variableScope
[
local
]
=
_currentScope
;
}
scopeOwner
[
_currentScope
]
=
_currentParent
;
return
previousBlock
;
}
...
...
@@ -362,6 +370,7 @@ private BoundNode VisitLambdaOrFunction(IBoundLambdaOrFunction node)
_currentParent
=
node
.
Symbol
;
_currentScope
=
node
.
Body
;
scopeParent
[
_currentScope
]
=
oldBlock
;
scopeOwner
[
_currentScope
]
=
_currentParent
;
var
wasInExpressionLambda
=
_inExpressionLambda
;
_inExpressionLambda
=
_inExpressionLambda
||
((
node
as
BoundLambda
)?.
Type
.
IsExpressionTree
()
??
false
);
...
...
src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.cs
浏览文件 @
ef76ee11
...
...
@@ -323,7 +323,8 @@ private LambdaFrame GetFrameForScope(BoundNode scope, ArrayBuilder<ClosureDebugI
DebugId
methodId
=
GetTopLevelMethodId
();
DebugId
closureId
=
GetClosureId
(
syntax
,
closureDebugInfo
);
frame
=
new
LambdaFrame
(
_topLevelMethod
,
syntax
,
methodId
,
closureId
);
var
containingMethod
=
_analysis
.
scopeOwner
[
scope
];
frame
=
new
LambdaFrame
(
_topLevelMethod
,
containingMethod
,
syntax
,
methodId
,
closureId
);
_frames
.
Add
(
scope
,
frame
);
CompilationState
.
ModuleBuilderOpt
.
AddSynthesizedDefinition
(
this
.
ContainingType
,
frame
);
...
...
@@ -359,7 +360,8 @@ private LambdaFrame GetStaticFrame(DiagnosticBag diagnostics, IBoundLambdaOrFunc
}
DebugId
closureId
=
default
(
DebugId
);
_lazyStaticLambdaFrame
=
new
LambdaFrame
(
_topLevelMethod
,
scopeSyntaxOpt
:
null
,
methodId
:
methodId
,
closureId
:
closureId
);
// using _topLevelMethod as containing member because the static frame does not have generic parameters, except for the top level method's
_lazyStaticLambdaFrame
=
new
LambdaFrame
(
_topLevelMethod
,
_topLevelMethod
,
scopeSyntaxOpt
:
null
,
methodId
:
methodId
,
closureId
:
closureId
);
// nongeneric static lambdas can share the frame
if
(
isNonGeneric
)
...
...
@@ -465,7 +467,8 @@ private static void InsertAndFreePrologue(ArrayBuilder<BoundStatement> result, A
/// <returns>The translated statement, as returned from F</returns>
private
T
IntroduceFrame
<
T
>(
BoundNode
node
,
LambdaFrame
frame
,
Func
<
ArrayBuilder
<
BoundExpression
>,
ArrayBuilder
<
LocalSymbol
>,
T
>
F
)
{
NamedTypeSymbol
frameType
=
frame
.
ConstructIfGeneric
(
StaticCast
<
TypeSymbol
>.
From
(
_currentTypeParameters
));
var
frameTypeParameters
=
ImmutableArray
.
Create
(
StaticCast
<
TypeSymbol
>.
From
(
_currentTypeParameters
),
0
,
frame
.
Arity
);
NamedTypeSymbol
frameType
=
frame
.
ConstructIfGeneric
(
frameTypeParameters
);
Debug
.
Assert
(
frame
.
ScopeSyntaxOpt
!=
null
);
LocalSymbol
framePointer
=
new
SynthesizedLocal
(
_topLevelMethod
,
frameType
,
SynthesizedLocalKind
.
LambdaDisplayClass
,
frame
.
ScopeSyntaxOpt
);
...
...
@@ -644,30 +647,41 @@ public override BoundNode VisitBaseReference(BoundBaseReference node)
:
FramePointer
(
node
.
Syntax
,
_topLevelMethod
.
ContainingType
);
// technically, not the correct static type
}
private
void
RemapLocalFunction
(
CSharpSyntaxNode
syntax
,
MethodSymbol
symbol
,
out
BoundExpression
receiver
,
out
MethodSymbol
method
)
private
void
RemapLambdaOrLocalFunction
(
CSharpSyntaxNode
syntax
,
MethodSymbol
originalMethod
,
ImmutableArray
<
TypeSymbol
>
typeArgumentsOpt
,
ClosureKind
closureKind
,
ref
MethodSymbol
synthesizedMethod
,
out
BoundExpression
receiver
,
out
NamedTypeSymbol
constructedFrame
)
{
Debug
.
Assert
(
symbol
.
MethodKind
==
MethodKind
.
LocalFunction
);
var
translatedLambdaContainer
=
synthesizedMethod
.
ContainingType
;
var
containerAsFrame
=
translatedLambdaContainer
as
LambdaFrame
;
var
constructed
=
symbol
as
SubstitutedMethodSymbol
;
if
(
constructed
!=
null
)
// All of _currentTypeParameters might not be preserved due to recursively calling upwards in the chain of local functions/lambdas
Debug
.
Assert
((
typeArgumentsOpt
.
IsDefault
&&
!
originalMethod
.
IsGenericMethod
)
||
(
typeArgumentsOpt
.
Length
==
originalMethod
.
Arity
));
var
totalTypeArgumentCount
=
translatedLambdaContainer
.
Arity
+
synthesizedMethod
.
Arity
;
var
realTypeArguments
=
ImmutableArray
.
Create
(
StaticCast
<
TypeSymbol
>.
From
(
_currentTypeParameters
),
0
,
totalTypeArgumentCount
-
originalMethod
.
Arity
);
if
(!
typeArgumentsOpt
.
IsDefault
)
{
RemapLocalFunction
(
syntax
,
constructed
.
ConstructedFrom
,
out
receiver
,
out
method
);
return
;
realTypeArguments
=
realTypeArguments
.
Concat
(
typeArgumentsOpt
);
}
var
mappedLocalFunction
=
_localFunctionMap
[(
LocalFunctionSymbol
)
symbol
];
method
=
mappedLocalFunction
.
Symbol
;
var
translatedLambdaContainer
=
method
.
ContainingType
;
var
containerAsFrame
=
translatedLambdaContainer
as
LambdaFrame
;
// Rewrite the lambda expression (and the enclosing anonymous method conversion) as a delegate creation expression
NamedTypeSymbol
constructedFrame
=
(
object
)
containerAsFrame
!=
null
?
translatedLambdaContainer
.
ConstructIfGeneric
(
StaticCast
<
TypeSymbol
>.
From
(
_currentTypeParameters
))
:
translatedLambdaContainer
;
if
(
containerAsFrame
!=
null
&&
containerAsFrame
.
Arity
!=
0
)
{
var
containerTypeArguments
=
ImmutableArray
.
Create
(
realTypeArguments
,
0
,
containerAsFrame
.
Arity
);
realTypeArguments
=
ImmutableArray
.
Create
(
realTypeArguments
,
containerAsFrame
.
Arity
,
realTypeArguments
.
Length
-
containerAsFrame
.
Arity
);
constructedFrame
=
containerAsFrame
.
Construct
(
containerTypeArguments
);
}
else
{
constructedFrame
=
translatedLambdaContainer
;
}
// for instance lambdas, receiver is the frame
// for static lambdas, get the singleton receiver
if
(
mappedLocalFunction
.
C
losureKind
!=
ClosureKind
.
Static
)
if
(
c
losureKind
!=
ClosureKind
.
Static
)
{
receiver
=
FrameOfType
(
syntax
,
constructedFrame
);
}
...
...
@@ -677,13 +691,38 @@ private void RemapLocalFunction(CSharpSyntaxNode syntax, MethodSymbol symbol, ou
receiver
=
new
BoundFieldAccess
(
syntax
,
null
,
field
,
constantValueOpt
:
null
);
}
method
=
method
.
AsMember
(
constructedFrame
);
if
(
method
.
IsGenericMethod
)
synthesizedMethod
=
synthesizedMethod
.
AsMember
(
constructedFrame
);
if
(
synthesizedMethod
.
IsGenericMethod
)
{
synthesizedMethod
=
synthesizedMethod
.
Construct
(
StaticCast
<
TypeSymbol
>.
From
(
realTypeArguments
));
}
else
{
method
=
method
.
Construct
(
StaticCast
<
TypeSymbol
>.
From
(
_currentTypeParameters
)
);
Debug
.
Assert
(
realTypeArguments
.
Length
==
0
);
}
}
private
void
RemapLocalFunction
(
CSharpSyntaxNode
syntax
,
MethodSymbol
symbol
,
out
BoundExpression
receiver
,
out
MethodSymbol
method
,
ImmutableArray
<
TypeSymbol
>
typeArguments
=
default
(
ImmutableArray
<
TypeSymbol
>))
{
Debug
.
Assert
(
symbol
.
MethodKind
==
MethodKind
.
LocalFunction
);
var
constructed
=
symbol
as
ConstructedMethodSymbol
;
if
(
constructed
!=
null
)
{
RemapLocalFunction
(
syntax
,
constructed
.
ConstructedFrom
,
out
receiver
,
out
method
,
this
.
TypeMap
.
SubstituteTypes
(
constructed
.
TypeArguments
));
return
;
}
var
mappedLocalFunction
=
_localFunctionMap
[(
LocalFunctionSymbol
)
symbol
];
method
=
mappedLocalFunction
.
Symbol
;
NamedTypeSymbol
constructedFrame
;
RemapLambdaOrLocalFunction
(
syntax
,
symbol
,
typeArguments
,
mappedLocalFunction
.
ClosureKind
,
ref
method
,
out
receiver
,
out
constructedFrame
);
}
public
override
BoundNode
VisitCall
(
BoundCall
node
)
{
if
(
node
.
Method
.
MethodKind
==
MethodKind
.
LocalFunction
)
...
...
@@ -1160,16 +1199,8 @@ private DebugId GetLambdaId(SyntaxNode syntax, ClosureKind closureKind, int clos
_framePointers
.
TryGetValue
(
translatedLambdaContainer
,
out
_innermostFramePointer
);
}
if
((
object
)
containerAsFrame
!=
null
)
{
_currentTypeParameters
=
translatedLambdaContainer
.
TypeParameters
;
_currentLambdaBodyTypeMap
=
((
LambdaFrame
)
translatedLambdaContainer
).
TypeMap
;
}
else
{
_currentTypeParameters
=
synthesizedMethod
.
TypeParameters
;
_currentLambdaBodyTypeMap
=
new
TypeMap
(
_topLevelMethod
.
TypeParameters
,
_currentTypeParameters
);
}
_currentTypeParameters
=
translatedLambdaContainer
?.
TypeParameters
.
Concat
(
synthesizedMethod
.
TypeParameters
)
??
synthesizedMethod
.
TypeParameters
;
_currentLambdaBodyTypeMap
=
synthesizedMethod
.
TypeMap
;
var
body
=
AddStatementsIfNeeded
((
BoundStatement
)
VisitBlock
(
node
.
Body
));
CheckLocalsDefined
(
body
);
...
...
@@ -1218,29 +1249,12 @@ private BoundNode RewriteLambdaConversion(BoundLambda node)
out
topLevelMethodId
,
out
lambdaId
);
// Rewrite the lambda expression (and the enclosing anonymous method conversion) as a delegate creation expression
NamedTypeSymbol
constructedFrame
=
(
object
)
containerAsFrame
!=
null
?
translatedLambdaContainer
.
ConstructIfGeneric
(
StaticCast
<
TypeSymbol
>.
From
(
_currentTypeParameters
))
:
translatedLambdaContainer
;
// for instance lambdas, receiver is the frame
// for static lambdas, get the singleton receiver
MethodSymbol
referencedMethod
=
synthesizedMethod
;
BoundExpression
receiver
;
if
(
closureKind
!=
ClosureKind
.
Static
)
{
receiver
=
FrameOfType
(
node
.
Syntax
,
constructedFrame
);
}
else
{
var
field
=
containerAsFrame
.
SingletonCache
.
AsMember
(
constructedFrame
);
receiver
=
new
BoundFieldAccess
(
node
.
Syntax
,
null
,
field
,
constantValueOpt
:
null
);
}
NamedTypeSymbol
constructedFrame
;
RemapLambdaOrLocalFunction
(
node
.
Syntax
,
node
.
Symbol
,
default
(
ImmutableArray
<
TypeSymbol
>),
closureKind
,
ref
referencedMethod
,
out
receiver
,
out
constructedFrame
);
MethodSymbol
referencedMethod
=
synthesizedMethod
.
AsMember
(
constructedFrame
);
if
(
referencedMethod
.
IsGenericMethod
)
{
referencedMethod
=
referencedMethod
.
Construct
(
StaticCast
<
TypeSymbol
>.
From
(
_currentTypeParameters
));
}
// Rewrite the lambda expression (and the enclosing anonymous method conversion) as a delegate creation expression
TypeSymbol
type
=
this
.
VisitType
(
node
.
Type
);
...
...
src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/SynthesizedLambdaMethod.cs
浏览文件 @
ef76ee11
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using
System
;
using
System.Collections.Immutable
;
using
Microsoft.CodeAnalysis.CodeGen
;
using
Microsoft.CodeAnalysis.CSharp.Symbols
;
using
System.Diagnostics
;
using
Roslyn.Utilities
;
namespace
Microsoft.CodeAnalysis.CSharp
{
...
...
@@ -36,19 +37,23 @@ internal sealed class SynthesizedLambdaMethod : SynthesizedMethodBaseSymbol, ISy
ImmutableArray
<
TypeParameterSymbol
>
typeParameters
;
LambdaFrame
lambdaFrame
;
if
(!
topLevelMethod
.
IsGenericMethod
)
lambdaFrame
=
this
.
ContainingType
as
LambdaFrame
;
switch
(
closureKind
)
{
typeMap
=
TypeMap
.
Empty
;
typeParameters
=
ImmutableArray
<
TypeParameterSymbol
>.
Empty
;
}
else
if
((
object
)(
lambdaFrame
=
this
.
ContainingType
as
LambdaFrame
)
!=
null
)
{
typeMap
=
lambdaFrame
.
TypeMap
;
typeParameters
=
ImmutableArray
<
TypeParameterSymbol
>.
Empty
;
}
else
{
typeMap
=
TypeMap
.
Empty
.
WithAlphaRename
(
topLevelMethod
,
this
,
out
typeParameters
);
case
ClosureKind
.
Static
:
// all type parameters on method (except the top level method's)
Debug
.
Assert
(
lambdaFrame
!=
null
);
typeMap
=
lambdaFrame
.
TypeMap
.
WithConcatAlphaRename
(
lambdaNode
.
Symbol
,
this
,
out
typeParameters
,
lambdaFrame
.
Arity
);
break
;
case
ClosureKind
.
ThisOnly
:
// all type parameters on method
Debug
.
Assert
(
lambdaFrame
==
null
);
typeMap
=
TypeMap
.
Empty
.
WithConcatAlphaRename
(
lambdaNode
.
Symbol
,
this
,
out
typeParameters
);
break
;
case
ClosureKind
.
General
:
// only lambda's type parameters on method (rest on class)
Debug
.
Assert
(
lambdaFrame
!=
null
);
typeMap
=
lambdaFrame
.
TypeMap
.
WithConcatAlphaRename
(
lambdaNode
.
Symbol
,
this
,
out
typeParameters
,
lambdaFrame
.
Arity
);
break
;
default
:
throw
ExceptionUtilities
.
Unreachable
;
}
AssignTypeMapAndTypeParameters
(
typeMap
,
typeParameters
);
...
...
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LoweredDynamicOperationFactory.cs
浏览文件 @
ef76ee11
...
...
@@ -674,6 +674,7 @@ private static NamedTypeSymbol CreateCallSiteContainer(SyntheticBoundNodeFactory
if
(
factory
.
TopLevelMethod
.
IsGenericMethod
)
{
// TODO: This probably doesn't work with generic local functions
return
synthesizedContainer
.
Construct
(
factory
.
TopLevelMethod
.
TypeParameters
.
Cast
<
TypeParameterSymbol
,
TypeSymbol
>());
}
...
...
src/Compilers/CSharp/Portable/Lowering/SynthesizedMethodBaseSymbol.cs
浏览文件 @
ef76ee11
...
...
@@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols
internal
abstract
class
SynthesizedMethodBaseSymbol
:
SourceMethodSymbol
{
protected
readonly
MethodSymbol
BaseMethod
;
protected
TypeMap
TypeMap
{
get
;
private
set
;
}
internal
TypeMap
TypeMap
{
get
;
private
set
;
}
private
readonly
string
_name
;
private
ImmutableArray
<
TypeParameterSymbol
>
_typeParameters
;
...
...
src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs
浏览文件 @
ef76ee11
...
...
@@ -46,8 +46,6 @@ internal class LocalFunctionSymbol : MethodSymbol
if
(
_syntax
.
TypeParameterList
!=
null
)
{
// TODO: Generics are broken. Fix binder issues when allowing generics.
diagnostics
.
Add
(
ErrorCode
.
ERR_InvalidMemberDecl
,
syntax
.
TypeParameterList
.
Location
,
syntax
.
TypeParameterList
);
binder
=
new
WithMethodTypeParametersBinder
(
this
,
binder
);
_typeParameters
=
MakeTypeParameters
(
diagnostics
);
}
...
...
src/Compilers/CSharp/Portable/Symbols/SubstitutedTypeParameterSymbol.cs
浏览文件 @
ef76ee11
...
...
@@ -15,19 +15,21 @@ internal class SubstitutedTypeParameterSymbol : TypeParameterSymbol
private
readonly
Symbol
_container
;
private
readonly
TypeMap
_map
;
private
readonly
TypeParameterSymbol
_substitutedFrom
;
private
readonly
int
_ordinal
;
#if DEBUG_ALPHA
private
static
int
_nextSequence
=
1
;
private
readonly
int
_mySequence
;
#endif
internal
SubstitutedTypeParameterSymbol
(
Symbol
newContainer
,
TypeMap
map
,
TypeParameterSymbol
substitutedFrom
)
internal
SubstitutedTypeParameterSymbol
(
Symbol
newContainer
,
TypeMap
map
,
TypeParameterSymbol
substitutedFrom
,
int
ordinal
)
{
_container
=
newContainer
;
// it is important that we don't use the map here in the constructor, as the map is still being filled
// in by TypeMap.WithAlphaRename. Instead, we can use the map lazily when yielding the constraints.
_map
=
map
;
_substitutedFrom
=
substitutedFrom
;
_ordinal
=
ordinal
;
#if DEBUG_ALPHA
_mySequence
=
_nextSequence
++;
#endif
...
...
@@ -107,7 +109,7 @@ public override int Ordinal
{
get
{
return
_
substitutedFrom
.
O
rdinal
;
return
_
o
rdinal
;
}
}
...
...
src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs
浏览文件 @
ef76ee11
...
...
@@ -27,13 +27,19 @@ protected SynthesizedContainer(string name, int parameterCount, bool returnsVoid
_typeParameters
=
CreateTypeParameters
(
parameterCount
,
returnsVoid
);
}
protected
SynthesizedContainer
(
string
name
,
MethodSymbol
topLevel
Method
)
protected
SynthesizedContainer
(
string
name
,
MethodSymbol
containing
Method
)
{
Debug
.
Assert
(
name
!=
null
);
Debug
.
Assert
(
topLevelMethod
!=
null
);
_name
=
name
;
_typeMap
=
TypeMap
.
Empty
.
WithAlphaRename
(
topLevelMethod
,
this
,
out
_typeParameters
);
if
(
containingMethod
==
null
)
{
_typeMap
=
TypeMap
.
Empty
;
_typeParameters
=
ImmutableArray
<
TypeParameterSymbol
>.
Empty
;
}
else
{
_typeMap
=
TypeMap
.
Empty
.
WithConcatAlphaRename
(
containingMethod
,
this
,
out
_typeParameters
);
}
}
protected
SynthesizedContainer
(
string
name
,
ImmutableArray
<
TypeParameterSymbol
>
typeParameters
,
TypeMap
typeMap
)
...
...
src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedSubstitutedTypeParameterSymbol.cs
浏览文件 @
ef76ee11
...
...
@@ -7,8 +7,8 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols
/// </summary>
internal
sealed
class
SynthesizedSubstitutedTypeParameterSymbol
:
SubstitutedTypeParameterSymbol
{
public
SynthesizedSubstitutedTypeParameterSymbol
(
Symbol
owner
,
TypeMap
map
,
TypeParameterSymbol
substitutedFrom
)
:
base
(
owner
,
map
,
substitutedFrom
)
public
SynthesizedSubstitutedTypeParameterSymbol
(
Symbol
owner
,
TypeMap
map
,
TypeParameterSymbol
substitutedFrom
,
int
ordinal
)
:
base
(
owner
,
map
,
substitutedFrom
,
ordinal
)
{
}
...
...
src/Compilers/CSharp/Portable/Symbols/TypeMap.cs
浏览文件 @
ef76ee11
...
...
@@ -36,7 +36,8 @@ internal TypeMap(SmallDictionary<TypeParameterSymbol, TypeSymbol> mapping)
:
base
(
new
SmallDictionary
<
TypeParameterSymbol
,
TypeSymbol
>(
mapping
,
ReferenceEqualityComparer
.
Instance
))
{
// mapping contents are read-only hereafter
Debug
.
Assert
(!
mapping
.
Keys
.
Any
(
tp
=>
tp
is
SubstitutedTypeParameterSymbol
));
// This assert fails on generic local functions
//Debug.Assert(!mapping.Keys.Any(tp => tp is SubstitutedTypeParameterSymbol));
}
private
static
SmallDictionary
<
TypeParameterSymbol
,
TypeSymbol
>
ForType
(
NamedTypeSymbol
containingType
)
...
...
@@ -100,13 +101,15 @@ private TypeMap WithAlphaRename(ImmutableArray<TypeParameterSymbol> oldTypeParam
// class or method for a lambda appearing in a generic method.
bool
synthesized
=
!
ReferenceEquals
(
oldTypeParameters
[
0
].
ContainingSymbol
.
OriginalDefinition
,
newOwner
.
OriginalDefinition
);
int
ordinal
=
0
;
foreach
(
var
tp
in
oldTypeParameters
)
{
var
newTp
=
synthesized
?
new
SynthesizedSubstitutedTypeParameterSymbol
(
newOwner
,
result
,
tp
)
:
new
SubstitutedTypeParameterSymbol
(
newOwner
,
result
,
tp
);
new
SynthesizedSubstitutedTypeParameterSymbol
(
newOwner
,
result
,
tp
,
ordinal
)
:
new
SubstitutedTypeParameterSymbol
(
newOwner
,
result
,
tp
,
ordinal
);
result
.
Mapping
.
Add
(
tp
,
newTp
);
newTypeParametersBuilder
.
Add
(
newTp
);
ordinal
++;
}
newTypeParameters
=
newTypeParametersBuilder
.
ToImmutableAndFree
();
...
...
@@ -125,6 +128,41 @@ internal TypeMap WithAlphaRename(MethodSymbol oldOwner, Symbol newOwner, out Imm
return
WithAlphaRename
(
oldOwner
.
OriginalDefinition
.
TypeParameters
,
newOwner
,
out
newTypeParameters
);
}
internal
TypeMap
WithConcatAlphaRename
(
MethodSymbol
oldOwner
,
Symbol
newOwner
,
out
ImmutableArray
<
TypeParameterSymbol
>
newTypeParameters
,
int
trimOffAt
=
0
)
{
Debug
.
Assert
(
oldOwner
.
ConstructedFrom
==
oldOwner
);
// Build the array up backwards, then reverse it.
// The following example goes through the do-loop in order M3, M2, M1
// but the type parameters have to be <T1, T2, T3, T4>
// void M1<T1>() {
// void M2<T2, T3>() {
// void M3<T4>() {
// }
// }
// }
var
parameters
=
ArrayBuilder
<
TypeParameterSymbol
>.
GetInstance
();
do
{
var
currentParameters
=
oldOwner
.
OriginalDefinition
.
TypeParameters
;
for
(
int
i
=
currentParameters
.
Length
-
1
;
i
>=
0
;
i
--)
{
parameters
.
Add
(
currentParameters
[
i
]);
}
oldOwner
=
oldOwner
.
ContainingSymbol
as
MethodSymbol
;
}
while
(
oldOwner
!=
null
);
parameters
.
ReverseContents
();
var
finalParameters
=
parameters
.
ToImmutableAndFree
();
if
(
trimOffAt
!=
0
)
{
finalParameters
=
ImmutableArray
.
Create
(
finalParameters
,
trimOffAt
,
finalParameters
.
Length
-
trimOffAt
);
}
return
WithAlphaRename
(
finalParameters
,
newOwner
,
out
newTypeParameters
);
}
private
static
SmallDictionary
<
TypeParameterSymbol
,
TypeSymbol
>
ConstructMapping
(
ImmutableArray
<
TypeParameterSymbol
>
from
,
ImmutableArray
<
TypeSymbol
>
to
)
{
SmallDictionary
<
TypeParameterSymbol
,
TypeSymbol
>
mapping
=
new
SmallDictionary
<
TypeParameterSymbol
,
TypeSymbol
>(
ReferenceEqualityComparer
.
Instance
);
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs
浏览文件 @
ef76ee11
...
...
@@ -584,54 +584,642 @@ public void Generic()
class Program
{
static void Main(string[] args)
// No closure. Return 'valu'.
static T A1<T>(T val)
{
T Local(T valu)
{
return valu;
}
return Local(val);
}
static int B1(int val)
{
T Local<T>(T valu)
{
return valu;
}
return Local(val);
}
static T1 C1<T1>(T1 val)
{
T Local<T>(T val)
T2 Local<T2>(T2 valu)
{
return valu;
}
return Local<T1>(val);
}
// General closure. Return 'val'.
static T A2<T>(T val)
{
T Local(T valu)
{
return val;
}
Console.WriteLine(Local<int>(2));
return Local(val);
}
static int B2(int val)
{
T Local<T>(T valu)
{
return (T)(object)val;
}
return Local(val);
}
static T1 C2<T1>(T1 val)
{
T2 Local<T2>(T2 valu)
{
return (T2)(object)val;
}
return Local<T1>(val);
}
// This-only closure. Return 'field'.
int field = 2;
T A3<T>(T val)
{
T Local(T valu)
{
return (T)(object)field;
}
return Local(val);
}
int B3(int val)
{
T Local<T>(T valu)
{
return (T)(object)field;
}
return Local(val);
}
T1 C3<T1>(T1 val)
{
T2 Local<T2>(T2 valu)
{
return (T2)(object)field;
}
return Local<T1>(val);
}
static void Main(string[] args)
{
var program = new Program();
Console.WriteLine(Program.A1(2));
Console.WriteLine(Program.B1(2));
Console.WriteLine(Program.C1(2));
Console.WriteLine(Program.A2(2));
Console.WriteLine(Program.B2(2));
Console.WriteLine(Program.C2(2));
Console.WriteLine(program.A3(2));
Console.WriteLine(program.B3(2));
Console.WriteLine(program.C3(2));
}
}
"
;
// TODO: Eventually support this
var
option
=
TestOptions
.
ReleaseExe
.
WithWarningLevel
(
0
);
CreateCompilationWithMscorlibAndSystemCore
(
source
,
options
:
option
,
parseOptions
:
_parseOptions
).
VerifyDiagnostics
(
// (8,16): error CS1519: Invalid token '<T>' in class, struct, or interface member declaration
// T Local<T>(T val)
Diagnostic
(
ErrorCode
.
ERR_InvalidMemberDecl
,
"<T>"
).
WithArguments
(
"<T>"
).
WithLocation
(
8
,
16
)
);
var
compilation
=
CreateCompilationWithMscorlib45
(
source
,
options
:
new
CSharpCompilationOptions
(
OutputKind
.
ConsoleApplication
),
parseOptions
:
_parseOptions
);
var
comp
=
CompileAndVerify
(
compilation
,
expectedOutput
:
@"
2
2
2
2
2
2
2
2
2
"
);
}
[
Fact
]
public
void
GenericClosure
()
public
void
Generic
TripleNestedNo
Closure
()
{
var
source
=
@"
using System;
using System.Collections.Generic;
class Program
{
static T Outer<T>(T val)
// Name of method is T[outer][middle][inner] where brackets are g=generic n=nongeneric
// One generic
static T1 Tgnn<T1>(T1 a)
{
T
Local(T valu
)
T
1 Local(T1 aa
)
{
return valu;
T1 Local2(T1 aaa)
{
return aaa;
}
return Local2(aa);
}
return Local(val);
return Local(a);
}
static int Tngn(int a)
{
T1 Local<T1>(T1 aa)
{
T1 Local2(T1 aaa)
{
return aaa;
}
return Local2(aa);
}
return Local(a);
}
static int Tnng(int a)
{
int Local(int aa)
{
T1 Local2<T1>(T1 aaa)
{
return aaa;
}
return Local2(aa);
}
return Local(a);
}
// Two generic
static T1 Tggn<T1>(T1 a)
{
T2 Local<T2>(T2 aa)
{
T2 Local2(T2 aaa)
{
return aaa;
}
return Local2(aa);
}
return Local(a);
}
static T1 Tgng<T1>(T1 a)
{
T1 Local(T1 aa)
{
T2 Local2<T2>(T2 aaa)
{
return aaa;
}
return Local2(aa);
}
return Local(a);
}
static int Tngg(int a)
{
T1 Local<T1>(T1 aa)
{
T2 Local2<T2>(T2 aaa)
{
return aaa;
}
return Local2(aa);
}
return Local(a);
}
// Three generic
static T1 Tggg<T1>(T1 a)
{
T2 Local<T2>(T2 aa)
{
T3 Local2<T3>(T3 aaa)
{
return aaa;
}
return Local2(aa);
}
return Local(a);
}
static void Main(string[] args)
{
Console.WriteLine(Outer(2));
Console.WriteLine(Program.Tgnn(2));
Console.WriteLine(Program.Tngn(2));
Console.WriteLine(Program.Tnng(2));
Console.WriteLine(Program.Tggn(2));
Console.WriteLine(Program.Tgng(2));
Console.WriteLine(Program.Tngg(2));
Console.WriteLine(Program.Tggg(2));
}
}
"
;
var
comp
=
CreateCompilationWithMscorlib
(
source
,
options
:
TestOptions
.
ReleaseExe
,
parseOptions
:
_parseOptions
);
var
verify
=
CompileAndVerify
(
comp
,
expectedOutput
:
@"
var
compilation
=
CreateCompilationWithMscorlib45
(
source
,
options
:
new
CSharpCompilationOptions
(
OutputKind
.
ConsoleApplication
),
parseOptions
:
_parseOptions
);
var
comp
=
CompileAndVerify
(
compilation
,
expectedOutput
:
@"
2
2
2
2
2
2
2
"
);
}
[
Fact
]
public
void
GenericTripleNestedMiddleClosure
()
{
var
source
=
@"
using System;
class Program
{
// Name of method is T[outer][middle][inner] where brackets are g=generic n=nongeneric
// One generic
static T1 Tgnn<T1>(T1 a)
{
T1 Local(T1 aa)
{
T1 Local2(T1 aaa)
{
return (T1)(object)aa;
}
return Local2(aa);
}
return Local(a);
}
static int Tngn(int a)
{
T1 Local<T1>(T1 aa)
{
T1 Local2(T1 aaa)
{
return (T1)(object)aa;
}
return Local2(aa);
}
return Local(a);
}
static int Tnng(int a)
{
int Local(int aa)
{
T1 Local2<T1>(T1 aaa)
{
return (T1)(object)aa;
}
return Local2(aa);
}
return Local(a);
}
// Two generic
static T1 Tggn<T1>(T1 a)
{
T2 Local<T2>(T2 aa)
{
T2 Local2(T2 aaa)
{
return (T2)(object)aa;
}
return Local2(aa);
}
return Local(a);
}
static T1 Tgng<T1>(T1 a)
{
T1 Local(T1 aa)
{
T2 Local2<T2>(T2 aaa)
{
return (T2)(object)aa;
}
return Local2(aa);
}
return Local(a);
}
static int Tngg(int a)
{
T1 Local<T1>(T1 aa)
{
T2 Local2<T2>(T2 aaa)
{
return (T2)(object)aa;
}
return Local2(aa);
}
return Local(a);
}
// Three generic
static T1 Tggg<T1>(T1 a)
{
T2 Local<T2>(T2 aa)
{
T3 Local2<T3>(T3 aaa)
{
return (T3)(object)aa;
}
return Local2(aa);
}
return Local(a);
}
static void Main(string[] args)
{
Console.WriteLine(Program.Tgnn(2));
Console.WriteLine(Program.Tngn(2));
Console.WriteLine(Program.Tnng(2));
Console.WriteLine(Program.Tggn(2));
Console.WriteLine(Program.Tgng(2));
Console.WriteLine(Program.Tngg(2));
Console.WriteLine(Program.Tggg(2));
}
}
"
;
var
compilation
=
CreateCompilationWithMscorlib45
(
source
,
options
:
new
CSharpCompilationOptions
(
OutputKind
.
ConsoleApplication
),
parseOptions
:
_parseOptions
);
var
comp
=
CompileAndVerify
(
compilation
,
expectedOutput
:
@"
2
2
2
2
2
2
2
"
);
}
[
Fact
]
public
void
GenericTripleNestedOuterClosure
()
{
var
source
=
@"
using System;
class Program
{
// Name of method is T[outer][middle][inner] where brackets are g=generic n=nongeneric
// One generic
static T1 Tgnn<T1>(T1 a)
{
T1 Local(T1 aa)
{
T1 Local2(T1 aaa)
{
return (T1)(object)a;
}
return Local2(aa);
}
return Local(a);
}
static int Tngn(int a)
{
T1 Local<T1>(T1 aa)
{
T1 Local2(T1 aaa)
{
return (T1)(object)a;
}
return Local2(aa);
}
return Local(a);
}
static int Tnng(int a)
{
int Local(int aa)
{
T1 Local2<T1>(T1 aaa)
{
return (T1)(object)a;
}
return Local2(aa);
}
return Local(a);
}
// Two generic
static T1 Tggn<T1>(T1 a)
{
T2 Local<T2>(T2 aa)
{
T2 Local2(T2 aaa)
{
return (T2)(object)a;
}
return Local2(aa);
}
return Local(a);
}
static T1 Tgng<T1>(T1 a)
{
T1 Local(T1 aa)
{
T2 Local2<T2>(T2 aaa)
{
return (T2)(object)a;
}
return Local2(aa);
}
return Local(a);
}
static int Tngg(int a)
{
T1 Local<T1>(T1 aa)
{
T2 Local2<T2>(T2 aaa)
{
return (T2)(object)a;
}
return Local2(aa);
}
return Local(a);
}
// Three generic
static T1 Tggg<T1>(T1 a)
{
T2 Local<T2>(T2 aa)
{
T3 Local2<T3>(T3 aaa)
{
return (T3)(object)a;
}
return Local2(aa);
}
return Local(a);
}
static void Main(string[] args)
{
Console.WriteLine(Program.Tgnn(2));
Console.WriteLine(Program.Tngn(2));
Console.WriteLine(Program.Tnng(2));
Console.WriteLine(Program.Tggn(2));
Console.WriteLine(Program.Tgng(2));
Console.WriteLine(Program.Tngg(2));
Console.WriteLine(Program.Tggg(2));
}
}
"
;
var
compilation
=
CreateCompilationWithMscorlib45
(
source
,
options
:
new
CSharpCompilationOptions
(
OutputKind
.
ConsoleApplication
),
parseOptions
:
_parseOptions
);
var
comp
=
CompileAndVerify
(
compilation
,
expectedOutput
:
@"
2
2
2
2
2
2
2
"
);
}
[
Fact
]
public
void
GenericTripleNestedNoClosureLambda
()
{
var
source
=
@"
using System;
class Program
{
// Name of method is T[outer][middle][inner] where brackets are g=generic n=nongeneric
// One generic
static T1 Tgnn<T1>(T1 a)
{
Func<T1, T1> Local = aa =>
{
Func<T1, T1> Local2 = aaa =>
{
return aaa;
};
return Local2(aa);
};
return Local(a);
}
static int Tngn(int a)
{
T1 Local<T1>(T1 aa)
{
Func<T1, T1> Local2 = aaa =>
{
return aaa;
};
return Local2(aa);
}
return Local(a);
}
static int Tnng(int a)
{
Func<int, int> Local = aa =>
{
T1 Local2<T1>(T1 aaa)
{
return aaa;
}
return Local2(aa);
};
return Local(a);
}
// Two generic
static T1 Tggn<T1>(T1 a)
{
T2 Local<T2>(T2 aa)
{
Func<T2, T2> Local2 = aaa =>
{
return aaa;
};
return Local2(aa);
}
return Local(a);
}
static T1 Tgng<T1>(T1 a)
{
Func<T1, T1> Local = aa =>
{
T2 Local2<T2>(T2 aaa)
{
return aaa;
}
return Local2(aa);
};
return Local(a);
}
// Tngg and Tggg are impossible with lambdas
static void Main(string[] args)
{
Console.WriteLine(Program.Tgnn(2));
Console.WriteLine(Program.Tngn(2));
Console.WriteLine(Program.Tnng(2));
Console.WriteLine(Program.Tggn(2));
Console.WriteLine(Program.Tgng(2));
}
}
"
;
var
compilation
=
CreateCompilationWithMscorlib45
(
source
,
options
:
new
CSharpCompilationOptions
(
OutputKind
.
ConsoleApplication
),
parseOptions
:
_parseOptions
);
var
comp
=
CompileAndVerify
(
compilation
,
expectedOutput
:
@"
2
2
2
2
2
"
);
}
[
Fact
]
public
void
GenericUpperCall
()
{
var
source
=
@"
using System;
class Program
{
static T1 InnerToOuter<T1>(T1 a)
{
T2 Local<T2>(T2 aa)
{
T3 Local2<T3>(T3 aaa)
{
if ((object)aaa == null)
return InnerToOuter((T3)new object());
return aaa;
}
return Local2(aa);
}
return Local(a);
}
static T1 InnerToMiddle<T1>(T1 a)
{
T2 Local<T2>(T2 aa)
{
T3 Local2<T3>(T3 aaa)
{
if ((object)aaa == null)
return InnerToMiddle((T3)new object());
return aaa;
}
return Local2(aa);
}
return Local(a);
}
static T1 InnerToOuterScoping<T1>(T1 a)
{
T2 Local<T2>(T2 aa)
{
T3 Local2<T3>(T3 aaa)
{
if ((object)aaa == null)
return (T3)(object)InnerToOuter((T1)new object());
return aaa;
}
return Local2(aa);
}
return Local(a);
}
// Tngg and Tggg are impossible with lambdas
static void Main(string[] args)
{
Console.WriteLine(Program.InnerToOuter((object)null));
Console.WriteLine(Program.InnerToMiddle((object)null));
Console.WriteLine(Program.InnerToOuterScoping((object)null));
}
}
"
;
var
compilation
=
CreateCompilationWithMscorlib45
(
source
,
options
:
new
CSharpCompilationOptions
(
OutputKind
.
ConsoleApplication
),
parseOptions
:
_parseOptions
);
var
comp
=
CompileAndVerify
(
compilation
,
expectedOutput
:
@"
System.Object
System.Object
System.Object
"
);
}
[
Fact
]
public
void
Shadows
()
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录