Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
29a1b9af
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,发现更多精彩内容 >>
提交
29a1b9af
编写于
6月 07, 2016
作者:
V
VSadov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
CR feedback on tuple type implicit conversions
上级
7a7a1833
变更
13
展开全部
隐藏空白更改
内联
并排
Showing
13 changed file
with
588 addition
and
131 deletion
+588
-131
src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
+5
-7
src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversion.cs
...Sharp/Portable/Binder/Semantics/Conversions/Conversion.cs
+1
-1
src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs
...harp/Portable/Binder/Semantics/Conversions/Conversions.cs
+10
-18
src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs
.../Portable/Binder/Semantics/Conversions/ConversionsBase.cs
+6
-8
src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs
...inder/Semantics/OverloadResolution/MethodTypeInference.cs
+27
-47
src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs
...Binder/Semantics/OverloadResolution/OverloadResolution.cs
+6
-18
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Conversion.cs
...rtable/Lowering/LocalRewriter/LocalRewriter_Conversion.cs
+22
-7
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Field.cs
...rp/Portable/Lowering/LocalRewriter/LocalRewriter_Field.cs
+6
-7
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_TupleCreationExpression.cs
...ng/LocalRewriter/LocalRewriter_TupleCreationExpression.cs
+7
-5
src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs
...ers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs
+5
-0
src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs
...mpilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs
+4
-3
src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs
...Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs
+54
-0
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs
+435
-10
未找到文件。
src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
浏览文件 @
29a1b9af
...
...
@@ -4,6 +4,7 @@
using
System.Diagnostics
;
using
Microsoft.CodeAnalysis.CSharp.Symbols
;
using
Roslyn.Utilities
;
using
System.Collections.Immutable
;
namespace
Microsoft.CodeAnalysis.CSharp
{
...
...
@@ -92,7 +93,7 @@ internal partial class Binder
if
(
conversion
.
IsTupleLiteral
||
(
conversion
.
Kind
==
ConversionKind
.
ImplicitNullable
&&
source
.
Kind
==
BoundKind
.
TupleLiteral
))
{
return
CreateTupleConversion
(
syntax
,
(
BoundTupleLiteral
)
source
,
conversion
,
isCast
,
destination
,
diagnostics
);
return
CreateTuple
Literal
Conversion
(
syntax
,
(
BoundTupleLiteral
)
source
,
conversion
,
isCast
,
destination
,
diagnostics
);
}
if
(
conversion
.
IsUserDefined
)
...
...
@@ -330,7 +331,7 @@ private BoundExpression CreateMethodGroupConversion(CSharpSyntaxNode syntax, Bou
return
new
BoundConversion
(
syntax
,
group
,
conversion
,
@checked
:
false
,
explicitCastInCode
:
isCast
,
constantValueOpt
:
ConstantValue
.
NotAvailable
,
type
:
destination
,
hasErrors
:
hasErrors
)
{
WasCompilerGenerated
=
source
.
WasCompilerGenerated
};
}
private
BoundExpression
CreateTupleConversion
(
CSharpSyntaxNode
syntax
,
BoundTupleLiteral
sourceTuple
,
Conversion
conversion
,
bool
isCast
,
TypeSymbol
destination
,
DiagnosticBag
diagnostics
)
private
BoundExpression
CreateTuple
Literal
Conversion
(
CSharpSyntaxNode
syntax
,
BoundTupleLiteral
sourceTuple
,
Conversion
conversion
,
bool
isCast
,
TypeSymbol
destination
,
DiagnosticBag
diagnostics
)
{
// We have a successful tuple conversion; rather than producing a separate conversion node
// which is a conversion on top of a tuple literal, tuple conversion is an element-wise conversion of arguments.
...
...
@@ -355,10 +356,9 @@ private BoundExpression CreateTupleConversion(CSharpSyntaxNode syntax, BoundTupl
var
arguments
=
sourceTuple
.
Arguments
;
var
convertedArguments
=
ArrayBuilder
<
BoundExpression
>.
GetInstance
(
arguments
.
Length
);
var
targetElementTypes
=
ArrayBuilder
<
TypeSymbol
>.
GetInstance
(
arguments
.
Length
);
TupleTypeSymbol
.
AddElementTypes
(
targetType
,
targetElementTypes
);
Debug
.
Assert
(
targetElementTypes
.
Count
==
arguments
.
Length
,
"converting a tuple literal to incompatible type?"
);
ImmutableArray
<
TypeSymbol
>
targetElementTypes
=
targetType
.
GetElementTypesIfTupleOrCompatible
(
);
Debug
.
Assert
(
targetElementTypes
.
Length
==
arguments
.
Length
,
"converting a tuple literal to incompatible type?"
);
for
(
int
i
=
0
;
i
<
arguments
.
Length
;
i
++)
{
...
...
@@ -367,8 +367,6 @@ private BoundExpression CreateTupleConversion(CSharpSyntaxNode syntax, BoundTupl
convertedArguments
.
Add
(
CreateConversion
(
argument
,
destType
,
diagnostics
));
}
targetElementTypes
.
Free
();
BoundExpression
result
=
new
BoundConvertedTupleLiteral
(
sourceTuple
.
Syntax
,
sourceTuple
.
Type
,
...
...
src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversion.cs
浏览文件 @
29a1b9af
...
...
@@ -47,7 +47,7 @@ public struct Conversion : IEquatable<Conversion>
private
readonly
UserDefinedConversionResult
_conversionResult
;
//no effect on Equals/GetHashCode
internal
readonly
ConversionKind
_kind
;
private
readonly
ConversionKind
_kind
;
private
readonly
byte
_flags
;
private
const
byte
IsExtensionMethodMask
=
1
<<
0
;
...
...
src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs
浏览文件 @
29a1b9af
...
...
@@ -715,29 +715,21 @@ protected override bool HasImplicitTupleLiteralConversion(BoundExpression source
return
false
;
}
var
targetElementTypes
=
ArrayBuilder
<
TypeSymbol
>.
GetInstance
(
arguments
.
Length
);
TupleTypeSymbol
.
AddElementTypes
((
NamedTypeSymbol
)
destination
,
targetElementTypes
);
Debug
.
Assert
(
arguments
.
Length
==
targetElementTypes
.
Count
);
ImmutableArray
<
TypeSymbol
>
targetElementTypes
=
destination
.
GetElementTypesIfTupleOrCompatible
();
Debug
.
Assert
(
arguments
.
Length
==
targetElementTypes
.
Length
);
try
// check arguments against flattened list of target element types
for
(
int
i
=
0
;
i
<
arguments
.
Length
;
i
++)
{
// check arguments against flattened list of target element types
for
(
int
i
=
0
;
i
<
arguments
.
Length
;
i
++)
var
argument
=
arguments
[
i
];
var
result
=
ClassifyImplicitConversionFromExpression
(
argument
,
targetElementTypes
[
i
],
ref
useSiteDiagnostics
);
if
(!
result
.
Exists
)
{
var
argument
=
arguments
[
i
];
var
result
=
ClassifyImplicitConversionFromExpression
(
argument
,
targetElementTypes
[
i
],
ref
useSiteDiagnostics
);
if
(!
result
.
Exists
)
{
return
false
;
}
return
false
;
}
return
true
;
}
finally
{
targetElementTypes
.
Free
();
}
return
true
;
}
protected
override
Conversion
GetInterpolatedStringConversion
(
BoundInterpolatedString
source
,
TypeSymbol
destination
,
ref
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
)
...
...
src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs
浏览文件 @
29a1b9af
...
...
@@ -7,6 +7,7 @@
using
Microsoft.CodeAnalysis.Text
;
using
System.Collections.Generic
;
using
Roslyn.Utilities
;
using
System.Collections.Immutable
;
namespace
Microsoft.CodeAnalysis.CSharp
{
...
...
@@ -923,15 +924,12 @@ private bool HasImplicitNullableConversion(TypeSymbol source, TypeSymbol destina
private
bool
HasImplicitTupleConversion
(
TypeSymbol
source
,
TypeSymbol
destination
,
ref
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
)
{
if
(!
source
.
IsTupleType
||
!
destination
.
IsTupleType
)
{
return
false
;
}
var
sourceTypes
=
source
.
TupleElementTypes
;
var
destTypes
=
destination
.
TupleElementTypes
;
ImmutableArray
<
TypeSymbol
>
sourceTypes
;
ImmutableArray
<
TypeSymbol
>
destTypes
;
if
(
sourceTypes
.
Length
!=
destTypes
.
Length
)
if
(!
source
.
TryGetElementTypesIfTupleOrCompatible
(
out
sourceTypes
)
||
!
destination
.
TryGetElementTypesIfTupleOrCompatible
(
out
destTypes
)
||
sourceTypes
.
Length
!=
destTypes
.
Length
)
{
return
false
;
}
...
...
src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs
浏览文件 @
29a1b9af
...
...
@@ -659,30 +659,18 @@ private void MakeExplicitParameterTypeInferences(Binder binder, BoundTupleLitera
return
;
}
var
destTypes
=
ArrayBuilder
<
TypeSymbol
>.
GetInstance
(
sourceArguments
.
Length
);
TupleTypeSymbol
.
AddElementTypes
(
destination
,
destTypes
);
var
destTypes
=
destination
.
GetElementTypesIfTupleOrCompatible
(
);
Debug
.
Assert
(
sourceArguments
.
Length
==
destTypes
.
Length
);
try
{
if
(
sourceArguments
.
Length
!=
destTypes
.
Count
)
{
return
;
}
// NOTE: we are losing tuple element names when recursing into argument expressions.
// that is ok, because we are inferring type parameters used in the matching elements,
// This is not the situation where entire tuple literal is used to infer a single type param
// NOTE: we are losing tuple element names when recursing into argument expressions.
// that is ok, because we are inferring type parameters used in the matching elements,
// This is not the situation where entire tuple literal is used to infer a single type param
for
(
int
i
=
0
;
i
<
sourceArguments
.
Length
;
i
++)
{
var
sourceArgument
=
sourceArguments
[
i
];
var
destType
=
destTypes
[
i
];
MakeExplicitParameterTypeInferences
(
binder
,
sourceArgument
,
destType
,
isExactInference
,
ref
useSiteDiagnostics
);
}
}
finally
for
(
int
i
=
0
;
i
<
sourceArguments
.
Length
;
i
++)
{
destTypes
.
Free
();
var
sourceArgument
=
sourceArguments
[
i
];
var
destType
=
destTypes
[
i
];
MakeExplicitParameterTypeInferences
(
binder
,
sourceArgument
,
destType
,
isExactInference
,
ref
useSiteDiagnostics
);
}
}
...
...
@@ -842,26 +830,14 @@ private void MakeOutputTypeInferences(Binder binder, BoundTupleLiteral argument,
return
;
}
var
destTypes
=
ArrayBuilder
<
TypeSymbol
>.
GetInstance
(
sourceArguments
.
Length
);
TupleTypeSymbol
.
AddElementTypes
(
destination
,
destTypes
);
var
destTypes
=
destination
.
GetElementTypesIfTupleOrCompatible
(
);
Debug
.
Assert
(
sourceArguments
.
Length
==
destTypes
.
Length
);
try
for
(
int
i
=
0
;
i
<
sourceArguments
.
Length
;
i
++)
{
if
(
sourceArguments
.
Length
!=
destTypes
.
Count
)
{
return
;
}
for
(
int
i
=
0
;
i
<
sourceArguments
.
Length
;
i
++)
{
var
sourceArgument
=
sourceArguments
[
i
];
var
destType
=
destTypes
[
i
];
MakeOutputTypeInferences
(
binder
,
sourceArgument
,
destType
,
ref
useSiteDiagnostics
);
}
}
finally
{
destTypes
.
Free
();
var
sourceArgument
=
sourceArguments
[
i
];
var
destType
=
destTypes
[
i
];
MakeOutputTypeInferences
(
binder
,
sourceArgument
,
destType
,
ref
useSiteDiagnostics
);
}
}
...
...
@@ -1604,11 +1580,11 @@ private bool ExactTupleInference(TypeSymbol source, TypeSymbol target, ref HashS
// that is ok, because we are inferring type parameters used in the matching elements,
// This is not the situation where entire tuple type used to infer a single type param
var
sourceTypes
=
source
.
TupleElement
Types
;
var
targetTypes
=
target
.
TupleElemen
tTypes
;
ImmutableArray
<
TypeSymbol
>
source
Types
;
ImmutableArray
<
TypeSymbol
>
targe
tTypes
;
if
(
sourceTypes
.
IsDefaultOrEmpty
||
targetTypes
.
IsDefaultOrEmpty
||
if
(
!
source
.
TryGetElementTypesIfTupleOrCompatible
(
out
sourceTypes
)
||
!
target
.
TryGetElementTypesIfTupleOrCompatible
(
out
targetTypes
)
||
sourceTypes
.
Length
!=
targetTypes
.
Length
)
{
return
false
;
...
...
@@ -1872,11 +1848,11 @@ private bool LowerBoundTupleInference(TypeSymbol source, TypeSymbol target, ref
// that is ok, because we are inferring type parameters used in the matching elements,
// This is not the situation where entire tuple type used to infer a single type param
var
sourceTypes
=
source
.
TupleElement
Types
;
var
targetTypes
=
target
.
TupleElemen
tTypes
;
ImmutableArray
<
TypeSymbol
>
source
Types
;
ImmutableArray
<
TypeSymbol
>
targe
tTypes
;
if
(
sourceTypes
.
IsDefaultOrEmpty
||
targetTypes
.
IsDefaultOrEmpty
||
if
(
!
source
.
TryGetElementTypesIfTupleOrCompatible
(
out
sourceTypes
)
||
!
target
.
TryGetElementTypesIfTupleOrCompatible
(
out
targetTypes
)
||
sourceTypes
.
Length
!=
targetTypes
.
Length
)
{
return
false
;
...
...
@@ -2133,6 +2109,10 @@ private void UpperBoundInference(TypeSymbol source, TypeSymbol target, ref HashS
// SPEC: then an exact inference is made from U1 to V1.
Debug
.
Assert
(
source
.
IsReferenceType
);
// NOTE: spec would ask us to do the following checks, but since the value types
// are trivially handled as exact inference in the callers, we do not have to.
//if (ExactNullableInference(source, target, ref useSiteDiagnostics))
//{
// return;
...
...
src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs
浏览文件 @
29a1b9af
...
...
@@ -1952,30 +1952,18 @@ private bool ExpressionMatchExactly(BoundTupleLiteral tupleSource, TypeSymbol ta
return
false
;
}
var
destTypes
=
ArrayBuilder
<
TypeSymbol
>.
GetInstance
(
sourceArguments
.
Length
);
TupleTypeSymbol
.
AddElementTypes
(
destination
,
destTypes
);
var
destTypes
=
destination
.
GetElementTypesIfTupleOrCompatible
(
);
Debug
.
Assert
(
sourceArguments
.
Length
==
destTypes
.
Length
);
try
for
(
int
i
=
0
;
i
<
sourceArguments
.
Length
;
i
++)
{
if
(
sourceArguments
.
Length
!=
destTypes
.
Count
)
if
(
!
ExpressionMatchExactly
(
sourceArguments
[
i
],
destTypes
[
i
],
ref
useSiteDiagnostics
)
)
{
return
false
;
}
for
(
int
i
=
0
;
i
<
sourceArguments
.
Length
;
i
++)
{
if
(!
ExpressionMatchExactly
(
sourceArguments
[
i
],
destTypes
[
i
],
ref
useSiteDiagnostics
))
{
return
false
;
}
}
return
true
;
}
finally
{
destTypes
.
Free
();
}
return
true
;
}
private
class
ReturnStatements
:
BoundTreeWalker
...
...
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Conversion.cs
浏览文件 @
29a1b9af
...
...
@@ -332,7 +332,7 @@ private static bool IsFloatPointExpressionOfUnknownPrecision(BoundExpression rew
conversionKind
:
conversionKind
,
@checked
:
@checked
,
explicitCastInCode
:
explicitCastInCode
,
rewrittenType
:
(
Tuple
TypeSymbol
)
rewrittenType
);
rewrittenType
:
(
Named
TypeSymbol
)
rewrittenType
);
default
:
break
;
...
...
@@ -634,14 +634,29 @@ private BoundExpression MakeImplicitConversion(BoundExpression rewrittenOperand,
ConversionKind
conversionKind
,
bool
@checked
,
bool
explicitCastInCode
,
Tuple
TypeSymbol
rewrittenType
)
Named
TypeSymbol
rewrittenType
)
{
var
destElementTypes
=
rewrittenType
.
TupleElementTypes
;
var
destElementTypes
=
rewrittenType
.
GetElementTypesIfTupleOrCompatible
()
;
var
numElements
=
destElementTypes
.
Length
;
var
srcType
=
(
TupleTypeSymbol
)
rewrittenOperand
.
Type
;
var
srcEleemntTypes
=
srcType
.
TupleElementTypes
;
var
srcElementFields
=
srcType
.
TupleElementFields
;
ImmutableArray
<
FieldSymbol
>
srcElementFields
;
TypeSymbol
srcType
=
rewrittenOperand
.
Type
;
if
(
srcType
.
IsTupleType
)
{
srcElementFields
=
((
TupleTypeSymbol
)
srcType
).
TupleElementFields
;
}
else
{
// The following codepath should be very uncommon (if reachable at all)
// we should generally not see tuple compatible types in bound trees and
// see actual tuple types instead.
Debug
.
Assert
(
srcType
.
IsTupleCompatible
());
// PERF: if allocations here become nuisance, consider caching the TupleTypeSymbol
// in the type symbols that can actually be tuple compatible
srcElementFields
=
TupleTypeSymbol
.
Create
((
NamedTypeSymbol
)
srcType
).
TupleElementFields
;
}
var
fieldAccessorsBuilder
=
ArrayBuilder
<
BoundExpression
>.
GetInstance
(
numElements
);
...
...
@@ -657,7 +672,7 @@ private BoundExpression MakeImplicitConversion(BoundExpression rewrittenOperand,
{
Symbol
.
ReportUseSiteDiagnostic
(
useSiteInfo
,
_diagnostics
,
syntax
.
Location
);
}
var
fieldAccess
=
MakeTupleFieldAccess
(
syntax
,
field
,
savedTuple
,
null
,
LookupResultKind
.
Empty
,
srcEleemntTypes
[
i
]
);
var
fieldAccess
=
MakeTupleFieldAccess
(
syntax
,
field
,
savedTuple
,
null
,
LookupResultKind
.
Empty
);
var
convertedFieldAccess
=
MakeConversion
(
fieldAccess
,
destElementTypes
[
i
],
@checked
);
fieldAccessorsBuilder
.
Add
(
convertedFieldAccess
);
}
...
...
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Field.cs
浏览文件 @
29a1b9af
...
...
@@ -25,7 +25,7 @@ public override BoundNode VisitFieldAccess(BoundFieldAccess node)
if
(
fieldSymbol
.
IsTupleField
)
{
return
MakeTupleFieldAccess
(
syntax
,
fieldSymbol
,
rewrittenReceiver
,
constantValueOpt
,
resultKind
,
type
);
return
MakeTupleFieldAccess
(
syntax
,
fieldSymbol
,
rewrittenReceiver
,
constantValueOpt
,
resultKind
);
}
BoundExpression
result
=
oldNodeOpt
!=
null
?
...
...
@@ -54,8 +54,7 @@ public override BoundNode VisitFieldAccess(BoundFieldAccess node)
FieldSymbol
tupleField
,
BoundExpression
rewrittenReceiver
,
ConstantValue
constantValueOpt
,
LookupResultKind
resultKind
,
TypeSymbol
type
)
LookupResultKind
resultKind
)
{
var
tupleType
=
tupleField
.
ContainingType
;
...
...
@@ -65,7 +64,7 @@ public override BoundNode VisitFieldAccess(BoundFieldAccess node)
if
((
object
)
underlyingField
==
null
)
{
// Use-site error must have been reported elsewhere.
return
new
BoundFieldAccess
(
syntax
,
rewrittenReceiver
,
tupleField
,
constantValueOpt
,
resultKind
,
type
,
hasErrors
:
tru
e
);
return
_factory
.
BadExpression
(
tupleField
.
Typ
e
);
}
if
(
underlyingField
.
ContainingType
!=
currentLinkType
)
...
...
@@ -76,22 +75,22 @@ public override BoundNode VisitFieldAccess(BoundFieldAccess node)
if
((
object
)
tupleRestField
==
null
)
{
// error tolerance for cases when Rest is missing
return
new
BoundFieldAccess
(
syntax
,
rewrittenReceiver
,
tupleField
,
constantValueOpt
,
resultKind
,
type
,
hasErrors
:
tru
e
);
return
_factory
.
BadExpression
(
tupleField
.
Typ
e
);
}
// make nested field accesses to Rest
do
{
FieldSymbol
nestedFieldSymbol
=
tupleRestField
.
AsMember
(
currentLinkType
);
rewrittenReceiver
=
_factory
.
Field
(
rewrittenReceiver
,
nestedFieldSymbol
);
currentLinkType
=
currentLinkType
.
TypeArgumentsNoUseSiteDiagnostics
[
TupleTypeSymbol
.
RestPosition
-
1
].
TupleUnderlyingType
;
rewrittenReceiver
=
new
BoundFieldAccess
(
syntax
,
rewrittenReceiver
,
nestedFieldSymbol
,
ConstantValue
.
NotAvailable
,
LookupResultKind
.
Viable
,
currentLinkType
);
}
while
(
underlyingField
.
ContainingType
!=
currentLinkType
);
}
// make a field access for the most local access
return
new
BoundFieldAccess
(
syntax
,
rewrittenReceiver
,
underlyingField
,
constantValueOpt
,
resultKind
,
type
);
return
_factory
.
Field
(
rewrittenReceiver
,
underlyingField
);
}
}
}
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_TupleCreationExpression.cs
浏览文件 @
29a1b9af
...
...
@@ -2,6 +2,7 @@
using
Microsoft.CodeAnalysis.CSharp.Symbols
;
using
System.Collections.Immutable
;
using
System.Diagnostics
;
namespace
Microsoft.CodeAnalysis.CSharp
{
...
...
@@ -31,12 +32,13 @@ private BoundNode VisitTupleExpression(BoundTupleExpression node)
/// </summary>
private
BoundExpression
RewriteTupleCreationExpression
(
BoundTupleExpression
node
,
ImmutableArray
<
BoundExpression
>
rewrittenArguments
)
{
return
MakeTupleCreationExpression
(
node
.
Syntax
,
(
TupleTypeSymbol
)
node
.
Type
,
rewrittenArguments
)
??
node
;
return
MakeTupleCreationExpression
(
node
.
Syntax
,
(
NamedTypeSymbol
)
node
.
Type
,
rewrittenArguments
)
;
}
private
BoundExpression
MakeTupleCreationExpression
(
CSharpSyntaxNode
syntax
,
Tuple
TypeSymbol
type
,
ImmutableArray
<
BoundExpression
>
rewrittenArguments
)
private
BoundExpression
MakeTupleCreationExpression
(
CSharpSyntaxNode
syntax
,
Named
TypeSymbol
type
,
ImmutableArray
<
BoundExpression
>
rewrittenArguments
)
{
NamedTypeSymbol
underlyingTupleType
=
type
.
TupleUnderlyingType
;
NamedTypeSymbol
underlyingTupleType
=
type
.
TupleUnderlyingType
??
type
;
Debug
.
Assert
(
underlyingTupleType
.
IsTupleCompatible
());
ArrayBuilder
<
NamedTypeSymbol
>
underlyingTupleTypeChain
=
ArrayBuilder
<
NamedTypeSymbol
>.
GetInstance
();
TupleTypeSymbol
.
GetUnderlyingTypeChain
(
underlyingTupleType
,
underlyingTupleTypeChain
);
...
...
@@ -54,7 +56,7 @@ private BoundExpression MakeTupleCreationExpression(CSharpSyntaxNode syntax, Tup
syntax
);
if
((
object
)
smallestCtor
==
null
)
{
return
null
;
return
_factory
.
BadExpression
(
type
)
;
}
MethodSymbol
smallestConstructor
=
smallestCtor
.
AsMember
(
smallestType
);
...
...
@@ -69,7 +71,7 @@ private BoundExpression MakeTupleCreationExpression(CSharpSyntaxNode syntax, Tup
syntax
);
if
((
object
)
tuple8Ctor
==
null
)
{
return
null
;
return
_factory
.
BadExpression
(
type
)
;
}
// make successively larger creation expressions containing the previous one
...
...
src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs
浏览文件 @
29a1b9af
...
...
@@ -251,6 +251,11 @@ public BoundBaseReference Base()
return
new
BoundBaseReference
(
Syntax
,
CurrentMethod
.
ThisParameter
.
Type
.
BaseTypeNoUseSiteDiagnostics
)
{
WasCompilerGenerated
=
true
};
}
public
BoundBadExpression
BadExpression
(
TypeSymbol
type
)
{
return
new
BoundBadExpression
(
Syntax
,
LookupResultKind
.
Empty
,
ImmutableArray
<
Symbol
>.
Empty
,
ImmutableArray
<
BoundNode
>.
Empty
,
type
,
hasErrors
:
true
);
}
public
BoundParameter
Parameter
(
ParameterSymbol
p
)
{
return
new
BoundParameter
(
Syntax
,
p
,
p
.
Type
)
{
WasCompilerGenerated
=
true
};
...
...
src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs
浏览文件 @
29a1b9af
...
...
@@ -714,12 +714,13 @@ private ImmutableArray<FieldSymbol> CollectTupleElementFields()
continue
;
}
var
field
=
(
TupleFieldSymbol
)
member
;
int
index
=
field
.
TupleFieldId
;
int
index
=
(
member
as
TupleFieldSymbol
)?.
TupleFieldId
??
((
TupleErrorFieldSymbol
)
member
).
TupleFieldId
;
if
(
index
>=
0
)
{
Debug
.
Assert
((
object
)
builder
[
index
]
==
null
);
builder
[
index
]
=
field
;
builder
[
index
]
=
(
FieldSymbol
)
member
;
}
}
...
...
src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs
浏览文件 @
29a1b9af
...
...
@@ -360,6 +360,60 @@ public static ImmutableArray<ParameterSymbol> DelegateParameters(this TypeSymbol
return
type
.
DelegateInvokeMethod
().
Parameters
;
}
public
static
bool
TryGetElementTypesIfTupleOrCompatible
(
this
TypeSymbol
type
,
out
ImmutableArray
<
TypeSymbol
>
elementTypes
)
{
if
(
type
.
IsTupleType
)
{
elementTypes
=
((
TupleTypeSymbol
)
type
).
TupleElementTypes
;
return
true
;
}
// The following codepath should be very uncommon since it would be rare
// to see a tuple underlying type not represented as a tuple.
// It still might happen since tuple underlying types are creatable via public APIs
// and it is also possible that they would be passed in.
// PERF: if allocations here become nuisance, consider caching the results
// in the type symbols that can actually be tuple compatible
int
cardinality
;
if
(!
type
.
IsTupleCompatible
(
out
cardinality
))
{
// source not a tuple or compatible
elementTypes
=
default
(
ImmutableArray
<
TypeSymbol
>);
return
false
;
}
var
elementTypesBuilder
=
ArrayBuilder
<
TypeSymbol
>.
GetInstance
(
cardinality
);
TupleTypeSymbol
.
AddElementTypes
((
NamedTypeSymbol
)
type
,
elementTypesBuilder
);
Debug
.
Assert
(
elementTypesBuilder
.
Count
==
cardinality
);
elementTypes
=
elementTypesBuilder
.
ToImmutableAndFree
();
return
true
;
}
public
static
ImmutableArray
<
TypeSymbol
>
GetElementTypesIfTupleOrCompatible
(
this
TypeSymbol
type
)
{
if
(
type
.
IsTupleType
)
{
return
((
TupleTypeSymbol
)
type
).
TupleElementTypes
;
}
// The following codepath should be very uncommon since it would be rare
// to see a tuple underlying type not represented as a tuple.
// It still might happen since tuple underlying types are creatable via public APIs
// and it is also possible that they would be passed in.
Debug
.
Assert
(
type
.
IsTupleCompatible
());
// PERF: if allocations here become nuisance, consider caching the results
// in the type symbols that can actually be tuple compatible
var
elementTypesBuilder
=
ArrayBuilder
<
TypeSymbol
>.
GetInstance
();
TupleTypeSymbol
.
AddElementTypes
((
NamedTypeSymbol
)
type
,
elementTypesBuilder
);
return
elementTypesBuilder
.
ToImmutableAndFree
();
}
public
static
MethodSymbol
DelegateInvokeMethod
(
this
TypeSymbol
type
)
{
Debug
.
Assert
((
object
)
type
!=
null
);
...
...
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs
浏览文件 @
29a1b9af
此差异已折叠。
点击以展开。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录