Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
e8f52801
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,发现更多精彩内容 >>
未验证
提交
e8f52801
编写于
3月 02, 2020
作者:
F
Fred Silberberg
提交者:
GitHub
3月 02, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #41996 from 333fred/binder-annotations
Binder annotations
上级
4be125ca
cd848e0b
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
140 addition
and
129 deletion
+140
-129
src/Compilers/CSharp/Portable/Binder/Binder_Crefs.cs
src/Compilers/CSharp/Portable/Binder/Binder_Crefs.cs
+39
-37
src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs
src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs
+46
-42
src/Compilers/CSharp/Portable/Binder/Binder_Flags.cs
src/Compilers/CSharp/Portable/Binder/Binder_Flags.cs
+1
-0
src/Compilers/CSharp/Portable/Binder/Binder_Initializers.cs
src/Compilers/CSharp/Portable/Binder/Binder_Initializers.cs
+13
-12
src/Compilers/CSharp/Portable/Binder/Binder_InterpolatedString.cs
...ilers/CSharp/Portable/Binder/Binder_InterpolatedString.cs
+3
-2
src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs
src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs
+2
-1
src/Compilers/CSharp/Portable/Binder/Binder_NameConflicts.cs
src/Compilers/CSharp/Portable/Binder/Binder_NameConflicts.cs
+5
-4
src/Compilers/CSharp/Portable/Binder/Binder_Query.cs
src/Compilers/CSharp/Portable/Binder/Binder_Query.cs
+23
-23
src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml
src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml
+1
-1
src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs
...ers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs
+6
-6
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_DeconstructionAssignmentOperator.cs
...ewriter/LocalRewriter_DeconstructionAssignmentOperator.cs
+1
-1
未找到文件。
src/Compilers/CSharp/Portable/Binder/Binder_Crefs.cs
浏览文件 @
e8f52801
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#
nullable
enable
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
...
...
@@ -15,15 +16,15 @@ namespace Microsoft.CodeAnalysis.CSharp
{
internal
partial
class
Binder
{
internal
ImmutableArray
<
Symbol
>
BindCref
(
CrefSyntax
syntax
,
out
Symbol
ambiguityWinner
,
DiagnosticBag
diagnostics
)
internal
ImmutableArray
<
Symbol
>
BindCref
(
CrefSyntax
syntax
,
out
Symbol
?
ambiguityWinner
,
DiagnosticBag
diagnostics
)
{
ImmutableArray
<
Symbol
>
symbols
=
BindCrefInternal
(
syntax
,
out
ambiguityWinner
,
diagnostics
);
Debug
.
Assert
(!
symbols
.
IsDefault
,
"Prefer empty to null."
);
Debug
.
Assert
((
symbols
.
Length
>
1
)
==
((
object
)
ambiguityWinner
!=
null
),
"ambiguityWinner should be set iff more than one symbol is returned."
);
Debug
.
Assert
((
symbols
.
Length
>
1
)
==
((
object
?
)
ambiguityWinner
!=
null
),
"ambiguityWinner should be set iff more than one symbol is returned."
);
return
symbols
;
}
private
ImmutableArray
<
Symbol
>
BindCrefInternal
(
CrefSyntax
syntax
,
out
Symbol
ambiguityWinner
,
DiagnosticBag
diagnostics
)
private
ImmutableArray
<
Symbol
>
BindCrefInternal
(
CrefSyntax
syntax
,
out
Symbol
?
ambiguityWinner
,
DiagnosticBag
diagnostics
)
{
switch
(
syntax
.
Kind
())
{
...
...
@@ -41,7 +42,7 @@ private ImmutableArray<Symbol> BindCrefInternal(CrefSyntax syntax, out Symbol am
}
}
private
ImmutableArray
<
Symbol
>
BindTypeCref
(
TypeCrefSyntax
syntax
,
out
Symbol
ambiguityWinner
,
DiagnosticBag
diagnostics
)
private
ImmutableArray
<
Symbol
>
BindTypeCref
(
TypeCrefSyntax
syntax
,
out
Symbol
?
ambiguityWinner
,
DiagnosticBag
diagnostics
)
{
NamespaceOrTypeSymbol
result
=
BindNamespaceOrTypeSymbolInCref
(
syntax
.
Type
);
...
...
@@ -60,7 +61,7 @@ private ImmutableArray<Symbol> BindTypeCref(TypeCrefSyntax syntax, out Symbol am
return
ImmutableArray
.
Create
<
Symbol
>(
result
);
}
private
ImmutableArray
<
Symbol
>
BindQualifiedCref
(
QualifiedCrefSyntax
syntax
,
out
Symbol
ambiguityWinner
,
DiagnosticBag
diagnostics
)
private
ImmutableArray
<
Symbol
>
BindQualifiedCref
(
QualifiedCrefSyntax
syntax
,
out
Symbol
?
ambiguityWinner
,
DiagnosticBag
diagnostics
)
{
// NOTE: we won't check whether container is an error type - we'll just let BindMemberCref fail
// and report a blanket diagnostic.
...
...
@@ -98,9 +99,9 @@ private NamespaceOrTypeSymbol BindNamespaceOrTypeSymbolInCref(TypeSyntax syntax)
return
namespaceOrTypeSymbol
;
}
private
ImmutableArray
<
Symbol
>
BindMemberCref
(
MemberCrefSyntax
syntax
,
NamespaceOrTypeSymbol
containerOpt
,
out
Symbol
ambiguityWinner
,
DiagnosticBag
diagnostics
)
private
ImmutableArray
<
Symbol
>
BindMemberCref
(
MemberCrefSyntax
syntax
,
NamespaceOrTypeSymbol
?
containerOpt
,
out
Symbol
?
ambiguityWinner
,
DiagnosticBag
diagnostics
)
{
if
((
object
)
containerOpt
!=
null
&&
containerOpt
.
Kind
==
SymbolKind
.
TypeParameter
)
if
((
object
?
)
containerOpt
!=
null
&&
containerOpt
.
Kind
==
SymbolKind
.
TypeParameter
)
{
// As in normal lookup (see CreateErrorIfLookupOnTypeParameter), you can't dot into a type parameter
// (though you can dot into an expression of type parameter type).
...
...
@@ -141,9 +142,9 @@ private ImmutableArray<Symbol> BindMemberCref(MemberCrefSyntax syntax, Namespace
return
result
;
}
private
ImmutableArray
<
Symbol
>
BindNameMemberCref
(
NameMemberCrefSyntax
syntax
,
NamespaceOrTypeSymbol
containerOpt
,
out
Symbol
ambiguityWinner
,
DiagnosticBag
diagnostics
)
private
ImmutableArray
<
Symbol
>
BindNameMemberCref
(
NameMemberCrefSyntax
syntax
,
NamespaceOrTypeSymbol
?
containerOpt
,
out
Symbol
?
ambiguityWinner
,
DiagnosticBag
diagnostics
)
{
SimpleNameSyntax
nameSyntax
=
syntax
.
Name
as
SimpleNameSyntax
;
SimpleNameSyntax
?
nameSyntax
=
syntax
.
Name
as
SimpleNameSyntax
;
int
arity
;
string
memberName
;
...
...
@@ -157,7 +158,7 @@ private ImmutableArray<Symbol> BindNameMemberCref(NameMemberCrefSyntax syntax, N
{
// If the name isn't a SimpleNameSyntax, then we must have a type name followed by a parameter list.
// Thus, we're looking for a constructor.
Debug
.
Assert
((
object
)
containerOpt
==
null
);
Debug
.
Assert
((
object
?
)
containerOpt
==
null
);
// Could be an error type, but we'll just lookup fail below.
containerOpt
=
BindNamespaceOrTypeSymbolInCref
(
syntax
.
Name
);
...
...
@@ -184,13 +185,13 @@ private ImmutableArray<Symbol> BindNameMemberCref(NameMemberCrefSyntax syntax, N
sortedSymbols
,
arity
,
syntax
,
typeArgumentListSyntax
:
arity
==
0
?
null
:
((
GenericNameSyntax
)
nameSyntax
).
TypeArgumentList
,
typeArgumentListSyntax
:
arity
==
0
?
null
:
((
GenericNameSyntax
)
nameSyntax
!
).
TypeArgumentList
,
parameterListSyntax
:
syntax
.
Parameters
,
ambiguityWinner
:
out
ambiguityWinner
,
diagnostics
:
diagnostics
);
}
private
ImmutableArray
<
Symbol
>
BindIndexerMemberCref
(
IndexerMemberCrefSyntax
syntax
,
NamespaceOrTypeSymbol
containerOpt
,
out
Symbol
ambiguityWinner
,
DiagnosticBag
diagnostics
)
private
ImmutableArray
<
Symbol
>
BindIndexerMemberCref
(
IndexerMemberCrefSyntax
syntax
,
NamespaceOrTypeSymbol
?
containerOpt
,
out
Symbol
?
ambiguityWinner
,
DiagnosticBag
diagnostics
)
{
const
int
arity
=
0
;
...
...
@@ -218,17 +219,17 @@ private ImmutableArray<Symbol> BindIndexerMemberCref(IndexerMemberCrefSyntax syn
// NOTE: not guaranteed to be a method (e.g. class op_Addition)
// NOTE: constructor fallback logic applies
private
ImmutableArray
<
Symbol
>
BindOperatorMemberCref
(
OperatorMemberCrefSyntax
syntax
,
NamespaceOrTypeSymbol
containerOpt
,
out
Symbol
ambiguityWinner
,
DiagnosticBag
diagnostics
)
private
ImmutableArray
<
Symbol
>
BindOperatorMemberCref
(
OperatorMemberCrefSyntax
syntax
,
NamespaceOrTypeSymbol
?
containerOpt
,
out
Symbol
?
ambiguityWinner
,
DiagnosticBag
diagnostics
)
{
const
int
arity
=
0
;
CrefParameterListSyntax
parameterListSyntax
=
syntax
.
Parameters
;
CrefParameterListSyntax
?
parameterListSyntax
=
syntax
.
Parameters
;
// NOTE: Prefer binary to unary, unless there is exactly one parameter.
// CONSIDER: we're following dev11 by never using a binary operator name if there's
// exactly one parameter, but doing so would allow us to match single-parameter constructors.
SyntaxKind
operatorTokenKind
=
syntax
.
OperatorToken
.
Kind
();
string
memberName
=
parameterListSyntax
!=
null
&&
parameterListSyntax
.
Parameters
.
Count
==
1
string
?
memberName
=
parameterListSyntax
!=
null
&&
parameterListSyntax
.
Parameters
.
Count
==
1
?
null
:
OperatorFacts
.
BinaryOperatorNameFromSyntaxKindIfAny
(
operatorTokenKind
);
memberName
=
memberName
??
OperatorFacts
.
UnaryOperatorNameFromSyntaxKindIfAny
(
operatorTokenKind
);
...
...
@@ -258,7 +259,7 @@ private ImmutableArray<Symbol> BindOperatorMemberCref(OperatorMemberCrefSyntax s
}
// NOTE: not guaranteed to be a method (e.g. class op_Implicit)
private
ImmutableArray
<
Symbol
>
BindConversionOperatorMemberCref
(
ConversionOperatorMemberCrefSyntax
syntax
,
NamespaceOrTypeSymbol
containerOpt
,
out
Symbol
ambiguityWinner
,
DiagnosticBag
diagnostics
)
private
ImmutableArray
<
Symbol
>
BindConversionOperatorMemberCref
(
ConversionOperatorMemberCrefSyntax
syntax
,
NamespaceOrTypeSymbol
?
containerOpt
,
out
Symbol
?
ambiguityWinner
,
DiagnosticBag
diagnostics
)
{
const
int
arity
=
0
;
...
...
@@ -304,15 +305,15 @@ private ImmutableArray<Symbol> BindConversionOperatorMemberCref(ConversionOperat
/// <remarks>
/// Never returns null.
/// </remarks>
private
ImmutableArray
<
Symbol
>
ComputeSortedCrefMembers
(
CSharpSyntaxNode
syntax
,
NamespaceOrTypeSymbol
containerOpt
,
string
memberName
,
int
arity
,
bool
hasParameterList
,
DiagnosticBag
diagnostics
)
private
ImmutableArray
<
Symbol
>
ComputeSortedCrefMembers
(
CSharpSyntaxNode
syntax
,
NamespaceOrTypeSymbol
?
containerOpt
,
string
memberName
,
int
arity
,
bool
hasParameterList
,
DiagnosticBag
diagnostics
)
{
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
=
null
;
HashSet
<
DiagnosticInfo
>
?
useSiteDiagnostics
=
null
;
var
result
=
ComputeSortedCrefMembers
(
containerOpt
,
memberName
,
arity
,
hasParameterList
,
ref
useSiteDiagnostics
);
diagnostics
.
Add
(
syntax
,
useSiteDiagnostics
);
return
result
;
}
private
ImmutableArray
<
Symbol
>
ComputeSortedCrefMembers
(
NamespaceOrTypeSymbol
containerOpt
,
string
memberName
,
int
arity
,
bool
hasParameterList
,
ref
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
)
private
ImmutableArray
<
Symbol
>
ComputeSortedCrefMembers
(
NamespaceOrTypeSymbol
?
containerOpt
,
string
memberName
,
int
arity
,
bool
hasParameterList
,
ref
HashSet
<
DiagnosticInfo
>?
useSiteDiagnostics
)
{
// Since we may find symbols without going through the lookup API,
// expose the symbols via an ArrayBuilder.
...
...
@@ -373,12 +374,12 @@ private ImmutableArray<Symbol> ComputeSortedCrefMembers(NamespaceOrTypeSymbol co
// As in the native compiler, we treat this as a fallback case - something that actually has the
// specified name is preferred.
NamedTypeSymbol
constructorType
=
null
;
NamedTypeSymbol
?
constructorType
=
null
;
if
(
arity
==
0
)
// Member arity
{
NamedTypeSymbol
containerType
=
containerOpt
as
NamedTypeSymbol
;
if
((
object
)
containerType
!=
null
)
NamedTypeSymbol
?
containerType
=
containerOpt
as
NamedTypeSymbol
;
if
((
object
?
)
containerType
!=
null
)
{
// Case 1: If the name is qualified by a type with the same name, then we want a
// constructor (unless the type is generic, the cref is on/in the type (but not
...
...
@@ -389,21 +390,21 @@ private ImmutableArray<Symbol> ComputeSortedCrefMembers(NamespaceOrTypeSymbol co
constructorType
=
containerType
;
}
}
else
if
((
object
)
containerOpt
==
null
&&
hasParameterList
)
else
if
((
object
?
)
containerOpt
==
null
&&
hasParameterList
)
{
// Case 2: If the name is not qualified by anything, but we're in the scope
// of a type with the same name (regardless of arity), then we want a constructor,
// as long as there were parens after the member name.
NamedTypeSymbol
binderContainingType
=
this
.
ContainingType
;
if
((
object
)
binderContainingType
!=
null
&&
memberName
==
binderContainingType
.
Name
)
NamedTypeSymbol
?
binderContainingType
=
this
.
ContainingType
;
if
((
object
?
)
binderContainingType
!=
null
&&
memberName
==
binderContainingType
.
Name
)
{
constructorType
=
binderContainingType
;
}
}
}
if
((
object
)
constructorType
!=
null
)
if
((
object
?
)
constructorType
!=
null
)
{
ImmutableArray
<
MethodSymbol
>
instanceConstructors
=
constructorType
.
InstanceConstructors
;
int
numInstanceConstructors
=
instanceConstructors
.
Length
;
...
...
@@ -443,9 +444,9 @@ private ImmutableArray<Symbol> ComputeSortedCrefMembers(NamespaceOrTypeSymbol co
ImmutableArray
<
Symbol
>
symbols
,
int
arity
,
MemberCrefSyntax
memberSyntax
,
TypeArgumentListSyntax
typeArgumentListSyntax
,
BaseCrefParameterListSyntax
parameterListSyntax
,
out
Symbol
ambiguityWinner
,
TypeArgumentListSyntax
?
typeArgumentListSyntax
,
BaseCrefParameterListSyntax
?
parameterListSyntax
,
out
Symbol
?
ambiguityWinner
,
DiagnosticBag
diagnostics
)
{
Debug
.
Assert
(!
symbols
.
IsEmpty
);
...
...
@@ -578,8 +579,8 @@ private static bool IsNestedTypeOfUnconstructedGenericType(NamedTypeSymbol type)
ImmutableArray
<
Symbol
>
symbols
,
int
arity
,
MemberCrefSyntax
memberSyntax
,
TypeArgumentListSyntax
typeArgumentListSyntax
,
out
Symbol
ambiguityWinner
,
TypeArgumentListSyntax
?
typeArgumentListSyntax
,
out
Symbol
?
ambiguityWinner
,
DiagnosticBag
diagnostics
)
{
// If the syntax indicates arity zero, then we match methods of any arity.
...
...
@@ -679,13 +680,13 @@ private static bool IsNestedTypeOfUnconstructedGenericType(NamedTypeSymbol type)
/// Replace any named type in the symbol list with its instance constructors.
/// Construct all candidates with the implicitly-declared CrefTypeParameterSymbols.
/// </summary>
private
void
GetCrefOverloadResolutionCandidates
(
ImmutableArray
<
Symbol
>
symbols
,
int
arity
,
TypeArgumentListSyntax
typeArgumentListSyntax
,
ArrayBuilder
<
Symbol
>
candidates
)
private
void
GetCrefOverloadResolutionCandidates
(
ImmutableArray
<
Symbol
>
symbols
,
int
arity
,
TypeArgumentListSyntax
?
typeArgumentListSyntax
,
ArrayBuilder
<
Symbol
>
candidates
)
{
foreach
(
Symbol
candidate
in
symbols
)
{
Symbol
constructedCandidate
=
ConstructWithCrefTypeParameters
(
arity
,
typeArgumentListSyntax
,
candidate
);
NamedTypeSymbol
constructedCandidateType
=
constructedCandidate
as
NamedTypeSymbol
;
if
((
object
)
constructedCandidateType
==
null
)
NamedTypeSymbol
?
constructedCandidateType
=
constructedCandidate
as
NamedTypeSymbol
;
if
((
object
?
)
constructedCandidateType
==
null
)
{
// Construct before overload resolution so the signatures will match.
candidates
.
Add
(
constructedCandidate
);
...
...
@@ -705,9 +706,9 @@ private void GetCrefOverloadResolutionCandidates(ImmutableArray<Symbol> symbols,
/// Produces a diagnostic for ambiguous matches, but not for unresolved members - WRN_BadXMLRef is
/// handled in BindMemberCref.
/// </remarks>
private
static
ImmutableArray
<
Symbol
>
PerformCrefOverloadResolution
(
ArrayBuilder
<
Symbol
>
candidates
,
ImmutableArray
<
ParameterSymbol
>
parameterSymbols
,
int
arity
,
MemberCrefSyntax
memberSyntax
,
out
Symbol
ambiguityWinner
,
DiagnosticBag
diagnostics
)
private
static
ImmutableArray
<
Symbol
>
PerformCrefOverloadResolution
(
ArrayBuilder
<
Symbol
>
candidates
,
ImmutableArray
<
ParameterSymbol
>
parameterSymbols
,
int
arity
,
MemberCrefSyntax
memberSyntax
,
out
Symbol
?
ambiguityWinner
,
DiagnosticBag
diagnostics
)
{
ArrayBuilder
<
Symbol
>
viable
=
null
;
ArrayBuilder
<
Symbol
>
?
viable
=
null
;
foreach
(
Symbol
candidate
in
candidates
)
{
...
...
@@ -827,10 +828,11 @@ private static ImmutableArray<Symbol> PerformCrefOverloadResolution(ArrayBuilder
/// <summary>
/// If the member is generic, construct it with the CrefTypeParameterSymbols that should be in scope.
/// </summary>
private
Symbol
ConstructWithCrefTypeParameters
(
int
arity
,
TypeArgumentListSyntax
typeArgumentListSyntax
,
Symbol
symbol
)
private
Symbol
ConstructWithCrefTypeParameters
(
int
arity
,
TypeArgumentListSyntax
?
typeArgumentListSyntax
,
Symbol
symbol
)
{
if
(
arity
>
0
)
{
Debug
.
Assert
(
typeArgumentListSyntax
is
object
);
SeparatedSyntaxList
<
TypeSyntax
>
typeArgumentSyntaxes
=
typeArgumentListSyntax
.
Arguments
;
var
typeArgumentsWithAnnotations
=
ArrayBuilder
<
TypeWithAnnotations
>.
GetInstance
(
arity
);
...
...
src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs
浏览文件 @
e8f52801
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#
nullable
enable
using
System
;
using
System.Collections.Immutable
;
...
...
@@ -30,8 +31,8 @@ internal BoundExpression BindDeconstruction(AssignmentExpressionSyntax node, Dia
{
var
left
=
node
.
Left
;
var
right
=
node
.
Right
;
DeclarationExpressionSyntax
declaration
=
null
;
ExpressionSyntax
expression
=
null
;
DeclarationExpressionSyntax
?
declaration
=
null
;
ExpressionSyntax
?
expression
=
null
;
var
result
=
BindDeconstruction
(
node
,
left
,
right
,
diagnostics
,
ref
declaration
,
ref
expression
,
resultIsUsedOverride
);
if
(
declaration
!=
null
)
{
...
...
@@ -88,13 +89,13 @@ internal BoundExpression BindDeconstruction(AssignmentExpressionSyntax node, Dia
ExpressionSyntax
left
,
ExpressionSyntax
right
,
DiagnosticBag
diagnostics
,
ref
DeclarationExpressionSyntax
declaration
,
ref
ExpressionSyntax
expression
,
ref
DeclarationExpressionSyntax
?
declaration
,
ref
ExpressionSyntax
?
expression
,
bool
resultIsUsedOverride
=
false
,
BoundDeconstructValuePlaceholder
rightPlaceholder
=
null
)
BoundDeconstructValuePlaceholder
?
rightPlaceholder
=
null
)
{
DeconstructionVariable
locals
=
BindDeconstructionVariables
(
left
,
diagnostics
,
ref
declaration
,
ref
expression
);
Debug
.
Assert
(
locals
.
HasNestedVariables
);
Debug
.
Assert
(
locals
.
NestedVariables
is
object
);
var
deconstructionDiagnostics
=
new
DiagnosticBag
();
BoundExpression
boundRight
=
rightPlaceholder
??
BindValue
(
right
,
deconstructionDiagnostics
,
BindValueKind
.
RValue
);
...
...
@@ -120,7 +121,7 @@ internal BoundExpression BindDeconstruction(AssignmentExpressionSyntax node, Dia
{
uint
rightEscape
=
GetValEscape
(
boundRHS
,
this
.
LocalScopeDepth
);
if
((
object
)
boundRHS
.
Type
==
null
||
boundRHS
.
Type
.
IsErrorType
())
if
((
object
?
)
boundRHS
.
Type
==
null
||
boundRHS
.
Type
.
IsErrorType
())
{
// we could still not infer a type for the RHS
FailRemainingInferencesAndSetValEscape
(
checkedVariables
,
diagnostics
,
rightEscape
);
...
...
@@ -154,7 +155,8 @@ internal BoundExpression BindDeconstruction(AssignmentExpressionSyntax node, Dia
FailRemainingInferencesAndSetValEscape
(
checkedVariables
,
diagnostics
,
rightEscape
);
var
lhsTuple
=
DeconstructionVariablesAsTuple
(
left
,
checkedVariables
,
diagnostics
,
ignoreDiagnosticsFromTuple
:
diagnostics
.
HasAnyErrors
()
||
!
resultIsUsed
);
TypeSymbol
returnType
=
hasErrors
?
CreateErrorType
()
:
lhsTuple
.
Type
;
Debug
.
Assert
(
hasErrors
||
lhsTuple
.
Type
is
object
);
TypeSymbol
returnType
=
hasErrors
?
CreateErrorType
()
:
lhsTuple
.
Type
!;
uint
leftEscape
=
GetBroadestValEscape
(
lhsTuple
,
this
.
LocalScopeDepth
);
boundRHS
=
ValidateEscape
(
boundRHS
,
leftEscape
,
isByRef
:
false
,
diagnostics
:
diagnostics
);
...
...
@@ -216,13 +218,13 @@ private BoundExpression FixTupleLiteral(ArrayBuilder<DeconstructionVariable> che
// If we already have diagnostics at this point, it is not worth collecting likely duplicate diagnostics from making the merged type
bool
hadErrors
=
diagnostics
.
HasAnyErrors
();
TypeSymbol
mergedTupleType
=
MakeMergedTupleType
(
checkedVariables
,
(
BoundTupleLiteral
)
boundRHS
,
syntax
,
Compilation
,
hadErrors
?
null
:
diagnostics
);
if
((
object
)
mergedTupleType
!=
null
)
TypeSymbol
?
mergedTupleType
=
MakeMergedTupleType
(
checkedVariables
,
(
BoundTupleLiteral
)
boundRHS
,
syntax
,
Compilation
,
hadErrors
?
null
:
diagnostics
);
if
((
object
?
)
mergedTupleType
!=
null
)
{
boundRHS
=
GenerateConversionForAssignment
(
mergedTupleType
,
boundRHS
,
diagnostics
);
}
}
else
if
((
object
)
boundRHS
.
Type
==
null
)
else
if
((
object
?
)
boundRHS
.
Type
==
null
)
{
Error
(
diagnostics
,
ErrorCode
.
ERR_DeconstructRequiresExpression
,
boundRHS
.
Syntax
);
}
...
...
@@ -297,7 +299,7 @@ private BoundExpression FixTupleLiteral(ArrayBuilder<DeconstructionVariable> che
var
variable
=
variables
[
i
];
Conversion
nestedConversion
;
if
(
variable
.
HasNestedVariables
)
if
(
variable
.
NestedVariables
is
object
)
{
var
elementSyntax
=
syntax
.
Kind
()
==
SyntaxKind
.
TupleExpression
?
((
TupleExpressionSyntax
)
syntax
).
Arguments
[
i
]
:
syntax
;
...
...
@@ -307,7 +309,8 @@ private BoundExpression FixTupleLiteral(ArrayBuilder<DeconstructionVariable> che
else
{
var
single
=
variable
.
Single
;
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
=
null
;
Debug
.
Assert
(
single
is
object
);
HashSet
<
DiagnosticInfo
>?
useSiteDiagnostics
=
null
;
nestedConversion
=
this
.
Conversions
.
ClassifyConversionFromType
(
tupleOrDeconstructedTypes
[
i
],
single
.
Type
,
ref
useSiteDiagnostics
);
diagnostics
.
Add
(
single
.
Syntax
,
useSiteDiagnostics
);
...
...
@@ -334,10 +337,9 @@ private void SetInferredTypes(ArrayBuilder<DeconstructionVariable> variables, Im
for
(
int
i
=
0
;
i
<
matchCount
;
i
++)
{
var
variable
=
variables
[
i
];
if
(
!
variable
.
HasNestedVariables
)
if
(
variable
.
Single
is
{
}
pending
)
{
var
pending
=
variable
.
Single
;
if
((
object
)
pending
.
Type
!=
null
)
if
((
object
?)
pending
.
Type
!=
null
)
{
continue
;
}
...
...
@@ -359,7 +361,7 @@ private BoundExpression SetInferredType(BoundExpression expression, TypeSymbol t
case
BoundKind
.
DiscardExpression
:
{
var
pending
=
(
BoundDiscardExpression
)
expression
;
Debug
.
Assert
((
object
)
pending
.
Type
==
null
);
Debug
.
Assert
((
object
?
)
pending
.
Type
==
null
);
return
pending
.
SetInferredTypeWithAnnotations
(
TypeWithAnnotations
.
Create
(
type
));
}
default
:
...
...
@@ -378,12 +380,13 @@ private BoundExpression SetInferredType(BoundExpression expression, TypeSymbol t
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
var
variable
=
variables
[
i
];
if
(
variable
.
HasNestedVariables
)
if
(
variable
.
NestedVariables
is
object
)
{
FailRemainingInferencesAndSetValEscape
(
variable
.
NestedVariables
,
diagnostics
,
rhsValEscape
);
}
else
{
Debug
.
Assert
(
variable
.
Single
is
object
);
switch
(
variable
.
Single
.
Kind
)
{
case
BoundKind
.
Local
:
...
...
@@ -399,7 +402,7 @@ private BoundExpression SetInferredType(BoundExpression expression, TypeSymbol t
break
;
case
BoundKind
.
DiscardExpression
:
var
pending
=
(
BoundDiscardExpression
)
variable
.
Single
;
if
((
object
)
pending
.
Type
==
null
)
if
((
object
?
)
pending
.
Type
==
null
)
{
Error
(
diagnostics
,
ErrorCode
.
ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable
,
pending
.
Syntax
,
"_"
);
variables
[
i
]
=
new
DeconstructionVariable
(
pending
.
FailInference
(
this
,
diagnostics
),
pending
.
Syntax
);
...
...
@@ -408,7 +411,7 @@ private BoundExpression SetInferredType(BoundExpression expression, TypeSymbol t
}
// at this point we expect to have a type for every lvalue
Debug
.
Assert
((
object
)
variables
[
i
].
Single
.
Type
!=
null
);
Debug
.
Assert
((
object
?)
variables
[
i
].
Single
!
.
Type
!=
null
);
}
}
}
...
...
@@ -419,8 +422,8 @@ private BoundExpression SetInferredType(BoundExpression expression, TypeSymbol t
[
DebuggerDisplay
(
"{GetDebuggerDisplay(),nq}"
)]
internal
sealed
class
DeconstructionVariable
{
internal
readonly
BoundExpression
Single
;
internal
readonly
ArrayBuilder
<
DeconstructionVariable
>
NestedVariables
;
internal
readonly
BoundExpression
?
Single
;
internal
readonly
ArrayBuilder
<
DeconstructionVariable
>
?
NestedVariables
;
internal
readonly
CSharpSyntaxNode
Syntax
;
internal
DeconstructionVariable
(
BoundExpression
variable
,
SyntaxNode
syntax
)
...
...
@@ -437,8 +440,6 @@ internal DeconstructionVariable(ArrayBuilder<DeconstructionVariable> variables,
Syntax
=
(
CSharpSyntaxNode
)
syntax
;
}
internal
bool
HasNestedVariables
=>
NestedVariables
!=
null
;
internal
static
void
FreeDeconstructionVariables
(
ArrayBuilder
<
DeconstructionVariable
>
variables
)
{
variables
.
FreeAll
(
v
=>
v
.
NestedVariables
);
...
...
@@ -450,6 +451,7 @@ private string GetDebuggerDisplay()
{
return
Single
.
GetDebuggerDisplay
();
}
Debug
.
Assert
(
NestedVariables
is
object
);
return
$"Nested variables (
{
NestedVariables
.
Count
}
)"
;
}
}
...
...
@@ -459,29 +461,29 @@ private string GetDebuggerDisplay()
/// For cases where the RHS of a deconstruction-assignment is a tuple literal, the type information from the LHS determines the merged type, since all variables have a type.
/// Returns null if a merged tuple type could not be fabricated.
/// </summary>
private
static
TypeSymbol
MakeMergedTupleType
(
ArrayBuilder
<
DeconstructionVariable
>
lhsVariables
,
BoundTupleLiteral
rhsLiteral
,
CSharpSyntaxNode
syntax
,
CSharpCompilation
compilation
,
DiagnosticBag
diagnostics
)
private
static
TypeSymbol
?
MakeMergedTupleType
(
ArrayBuilder
<
DeconstructionVariable
>
lhsVariables
,
BoundTupleLiteral
rhsLiteral
,
CSharpSyntaxNode
syntax
,
CSharpCompilation
compilation
,
DiagnosticBag
?
diagnostics
)
{
int
leftLength
=
lhsVariables
.
Count
;
int
rightLength
=
rhsLiteral
.
Arguments
.
Length
;
var
typesWithAnnotationsBuilder
=
ArrayBuilder
<
TypeWithAnnotations
>.
GetInstance
(
leftLength
);
var
locationsBuilder
=
ArrayBuilder
<
Location
>.
GetInstance
(
leftLength
);
var
locationsBuilder
=
ArrayBuilder
<
Location
?
>.
GetInstance
(
leftLength
);
for
(
int
i
=
0
;
i
<
rightLength
;
i
++)
{
BoundExpression
element
=
rhsLiteral
.
Arguments
[
i
];
TypeSymbol
mergedType
=
element
.
Type
;
TypeSymbol
?
mergedType
=
element
.
Type
;
if
(
i
<
leftLength
)
{
var
variable
=
lhsVariables
[
i
];
if
(
variable
.
HasNestedVariables
)
if
(
variable
.
NestedVariables
is
object
)
{
if
(
element
.
Kind
==
BoundKind
.
TupleLiteral
)
{
// (variables) on the left and (elements) on the right
mergedType
=
MakeMergedTupleType
(
variable
.
NestedVariables
,
(
BoundTupleLiteral
)
element
,
syntax
,
compilation
,
diagnostics
);
}
else
if
((
object
)
mergedType
==
null
)
else
if
((
object
?)
mergedType
==
null
&&
diagnostics
is
object
)
{
// (variables) on the left and null on the right
Error
(
diagnostics
,
ErrorCode
.
ERR_DeconstructRequiresExpression
,
element
.
Syntax
);
...
...
@@ -489,7 +491,8 @@ private static TypeSymbol MakeMergedTupleType(ArrayBuilder<DeconstructionVariabl
}
else
{
if
((
object
)
variable
.
Single
.
Type
!=
null
)
Debug
.
Assert
(
variable
.
Single
is
object
);
if
((
object
?)
variable
.
Single
.
Type
!=
null
)
{
// typed-variable on the left
mergedType
=
variable
.
Single
.
Type
;
...
...
@@ -498,7 +501,7 @@ private static TypeSymbol MakeMergedTupleType(ArrayBuilder<DeconstructionVariabl
}
else
{
if
((
object
)
mergedType
==
null
)
if
((
object
?)
mergedType
==
null
&&
diagnostics
is
object
)
{
// a typeless element on the right, matching no variable on the left
Error
(
diagnostics
,
ErrorCode
.
ERR_DeconstructRequiresExpression
,
element
.
Syntax
);
...
...
@@ -523,7 +526,7 @@ private static TypeSymbol MakeMergedTupleType(ArrayBuilder<DeconstructionVariabl
locationOpt
:
null
,
elementTypesWithAnnotations
:
typesWithAnnotationsBuilder
.
ToImmutableAndFree
(),
elementLocations
:
locationsBuilder
.
ToImmutableAndFree
(),
elementNames
:
default
(
ImmutableArray
<
string
>),
elementNames
:
default
(
ImmutableArray
<
string
?
>),
compilation
:
compilation
,
diagnostics
:
diagnostics
,
shouldCheckConstraints
:
true
,
...
...
@@ -538,19 +541,20 @@ private static TypeSymbol MakeMergedTupleType(ArrayBuilder<DeconstructionVariabl
int
count
=
variables
.
Count
;
var
valuesBuilder
=
ArrayBuilder
<
BoundExpression
>.
GetInstance
(
count
);
var
typesWithAnnotationsBuilder
=
ArrayBuilder
<
TypeWithAnnotations
>.
GetInstance
(
count
);
var
locationsBuilder
=
ArrayBuilder
<
Location
>.
GetInstance
(
count
);
var
namesBuilder
=
ArrayBuilder
<
string
>.
GetInstance
(
count
);
var
locationsBuilder
=
ArrayBuilder
<
Location
?
>.
GetInstance
(
count
);
var
namesBuilder
=
ArrayBuilder
<
string
?
>.
GetInstance
(
count
);
foreach
(
var
variable
in
variables
)
{
BoundExpression
value
;
if
(
variable
.
HasNestedVariables
)
if
(
variable
.
NestedVariables
is
object
)
{
value
=
DeconstructionVariablesAsTuple
(
variable
.
Syntax
,
variable
.
NestedVariables
,
diagnostics
,
ignoreDiagnosticsFromTuple
);
namesBuilder
.
Add
(
null
);
}
else
{
Debug
.
Assert
(
variable
.
Single
is
object
);
value
=
variable
.
Single
;
namesBuilder
.
Add
(
ExtractDeconstructResultElementName
(
value
));
}
...
...
@@ -564,7 +568,7 @@ private static TypeSymbol MakeMergedTupleType(ArrayBuilder<DeconstructionVariabl
RemoveDuplicateInferredTupleNamesAndFreeIfEmptied
(
ref
namesBuilder
,
uniqueFieldNames
);
uniqueFieldNames
.
Free
();
ImmutableArray
<
string
>
tupleNames
=
namesBuilder
is
null
?
default
:
namesBuilder
.
ToImmutableAndFree
();
ImmutableArray
<
string
?
>
tupleNames
=
namesBuilder
is
null
?
default
:
namesBuilder
.
ToImmutableAndFree
();
ImmutableArray
<
bool
>
inferredPositions
=
tupleNames
.
IsDefault
?
default
:
tupleNames
.
SelectAsArray
(
n
=>
n
!=
null
);
bool
disallowInferredNames
=
this
.
Compilation
.
LanguageVersion
.
DisallowInferredTupleElementNames
();
...
...
@@ -581,7 +585,7 @@ private static TypeSymbol MakeMergedTupleType(ArrayBuilder<DeconstructionVariabl
}
/// <summary>Extract inferred name from a single deconstruction variable.</summary>
private
static
string
ExtractDeconstructResultElementName
(
BoundExpression
expression
)
private
static
string
?
ExtractDeconstructResultElementName
(
BoundExpression
expression
)
{
if
(
expression
.
Kind
==
BoundKind
.
DiscardExpression
)
{
...
...
@@ -607,7 +611,7 @@ private static string ExtractDeconstructResultElementName(BoundExpression expres
{
anyApplicableCandidates
=
false
;
var
receiverSyntax
=
(
CSharpSyntaxNode
)
receiver
.
Syntax
;
if
(
receiver
.
Type
.
IsDynamic
()
)
if
(
receiver
.
Type
?.
IsDynamic
()
??
false
)
{
Error
(
diagnostics
,
ErrorCode
.
ERR_CannotDeconstructDynamic
,
rightSyntax
);
outPlaceholders
=
default
(
ImmutableArray
<
BoundDeconstructValuePlaceholder
>);
...
...
@@ -695,9 +699,9 @@ private static string ExtractDeconstructResultElementName(BoundExpression expres
private
BoundBadExpression
MissingDeconstruct
(
BoundExpression
receiver
,
SyntaxNode
rightSyntax
,
int
numParameters
,
DiagnosticBag
diagnostics
,
out
ImmutableArray
<
BoundDeconstructValuePlaceholder
>
outPlaceholders
,
BoundExpression
childNode
)
{
if
(
!
receiver
.
Type
.
IsErrorType
()
)
if
(
receiver
.
Type
?.
IsErrorType
()
==
false
)
{
Error
(
diagnostics
,
ErrorCode
.
ERR_MissingDeconstruct
,
rightSyntax
,
receiver
.
Type
,
numParameters
);
Error
(
diagnostics
,
ErrorCode
.
ERR_MissingDeconstruct
,
rightSyntax
,
receiver
.
Type
!
,
numParameters
);
}
outPlaceholders
=
default
;
...
...
@@ -713,8 +717,8 @@ private static string ExtractDeconstructResultElementName(BoundExpression expres
private
DeconstructionVariable
BindDeconstructionVariables
(
ExpressionSyntax
node
,
DiagnosticBag
diagnostics
,
ref
DeclarationExpressionSyntax
declaration
,
ref
ExpressionSyntax
expression
)
ref
DeclarationExpressionSyntax
?
declaration
,
ref
ExpressionSyntax
?
expression
)
{
switch
(
node
.
Kind
())
{
...
...
src/Compilers/CSharp/Portable/Binder/Binder_Flags.cs
浏览文件 @
e8f52801
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#
nullable
enable
using
Microsoft.CodeAnalysis.CSharp.Symbols
;
using
System.Diagnostics
;
...
...
src/Compilers/CSharp/Portable/Binder/Binder_Initializers.cs
浏览文件 @
e8f52801
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#
nullable
enable
using
System.Collections.Immutable
;
using
System.Diagnostics
;
...
...
@@ -18,7 +19,7 @@ internal struct ProcessedFieldInitializers
internal
ImmutableArray
<
BoundInitializer
>
BoundInitializers
{
get
;
set
;
}
internal
BoundStatement
LoweredInitializers
{
get
;
set
;
}
internal
bool
HasErrors
{
get
;
set
;
}
internal
ImportChain
FirstImportChain
{
get
;
set
;
}
internal
ImportChain
?
FirstImportChain
{
get
;
set
;
}
}
internal
static
void
BindFieldInitializers
(
...
...
@@ -29,7 +30,7 @@ internal struct ProcessedFieldInitializers
ref
ProcessedFieldInitializers
processedInitializers
)
{
var
diagsForInstanceInitializers
=
DiagnosticBag
.
GetInstance
();
ImportChain
firstImportChain
;
ImportChain
?
firstImportChain
;
processedInitializers
.
BoundInitializers
=
BindFieldInitializers
(
compilation
,
scriptInitializerOpt
,
fieldInitializers
,
diagsForInstanceInitializers
,
out
firstImportChain
);
processedInitializers
.
HasErrors
=
diagsForInstanceInitializers
.
HasAnyErrors
();
processedInitializers
.
FirstImportChain
=
firstImportChain
;
...
...
@@ -42,7 +43,7 @@ internal struct ProcessedFieldInitializers
SynthesizedInteractiveInitializerMethod
scriptInitializerOpt
,
ImmutableArray
<
ImmutableArray
<
FieldOrPropertyInitializer
>>
initializers
,
DiagnosticBag
diagnostics
,
out
ImportChain
firstImportChain
)
out
ImportChain
?
firstImportChain
)
{
if
(
initializers
.
IsEmpty
)
{
...
...
@@ -71,7 +72,7 @@ internal struct ProcessedFieldInitializers
ImmutableArray
<
ImmutableArray
<
FieldOrPropertyInitializer
>>
initializers
,
ArrayBuilder
<
BoundInitializer
>
boundInitializers
,
DiagnosticBag
diagnostics
,
out
ImportChain
firstDebugImports
)
out
ImportChain
?
firstDebugImports
)
{
firstDebugImports
=
null
;
...
...
@@ -80,7 +81,7 @@ internal struct ProcessedFieldInitializers
// All sibling initializers share the same parent node and tree so we can reuse the binder
// factory across siblings. Unfortunately, we cannot reuse the binder itself, because
// individual fields might have their own binders (e.g. because of being declared unsafe).
BinderFactory
binderFactory
=
null
;
BinderFactory
?
binderFactory
=
null
;
foreach
(
FieldOrPropertyInitializer
initializer
in
siblingInitializers
)
{
...
...
@@ -129,7 +130,7 @@ internal struct ProcessedFieldInitializers
ImmutableArray
<
ImmutableArray
<
FieldOrPropertyInitializer
>>
initializers
,
ArrayBuilder
<
BoundInitializer
>
boundInitializers
,
DiagnosticBag
diagnostics
,
out
ImportChain
firstDebugImports
)
out
ImportChain
?
firstDebugImports
)
{
firstDebugImports
=
null
;
...
...
@@ -140,9 +141,9 @@ internal struct ProcessedFieldInitializers
// All sibling initializers share the same parent node and tree so we can reuse the binder
// factory across siblings. Unfortunately, we cannot reuse the binder itself, because
// individual fields might have their own binders (e.g. because of being declared unsafe).
BinderFactory
binderFactory
=
null
;
BinderFactory
?
binderFactory
=
null
;
// Label instances must be shared across all global statements.
ScriptLocalScopeBinder
.
Labels
labels
=
null
;
ScriptLocalScopeBinder
.
Labels
?
labels
=
null
;
for
(
int
j
=
0
;
j
<
siblingInitializers
.
Length
;
j
++)
{
...
...
@@ -169,7 +170,7 @@ internal struct ProcessedFieldInitializers
}
Binder
scriptClassBinder
=
binderFactory
.
GetBinder
(
syntax
);
Debug
.
Assert
(
((
NamedTypeSymbol
)
scriptClassBinder
.
ContainingMemberOrLambda
).
IsScriptClass
);
Debug
.
Assert
(
scriptClassBinder
.
ContainingMemberOrLambda
is
NamedTypeSymbol
{
IsScriptClass
:
true
}
);
if
(
firstDebugImports
==
null
)
{
...
...
@@ -182,7 +183,7 @@ internal struct ProcessedFieldInitializers
new
ScriptLocalScopeBinder
(
labels
,
scriptClassBinder
));
BoundInitializer
boundInitializer
;
if
((
object
)
fieldSymbol
!=
null
)
if
((
object
?
)
fieldSymbol
!=
null
)
{
boundInitializer
=
BindFieldInitializer
(
parentBinder
.
WithAdditionalFlagsAndContainingMemberOrLambda
(
BinderFlags
.
FieldInitializer
,
fieldSymbol
),
...
...
@@ -221,7 +222,7 @@ internal struct ProcessedFieldInitializers
// insert an implicit conversion for the submission return type (if needed):
var
expression
=
InitializerRewriter
.
GetTrailingScriptExpression
(
statement
);
if
(
expression
!=
null
&&
((
object
)
expression
.
Type
==
null
||
!
expression
.
Type
.
IsVoidType
()))
((
object
?
)
expression
.
Type
==
null
||
!
expression
.
Type
.
IsVoidType
()))
{
var
submissionResultType
=
scriptInitializer
.
ResultType
;
expression
=
binder
.
GenerateConversionForAssignment
(
submissionResultType
,
expression
,
diagnostics
);
...
...
@@ -256,7 +257,7 @@ internal struct ProcessedFieldInitializers
var
fieldsBeingBound
=
binder
.
FieldsBeingBound
;
var
sourceField
=
fieldSymbol
as
SourceMemberFieldSymbolFromDeclarator
;
bool
isImplicitlyTypedField
=
(
object
)
sourceField
!=
null
&&
sourceField
.
FieldTypeInferred
(
fieldsBeingBound
);
bool
isImplicitlyTypedField
=
(
object
?
)
sourceField
!=
null
&&
sourceField
.
FieldTypeInferred
(
fieldsBeingBound
);
// If the type is implicitly typed, the initializer diagnostics have already been reported, so ignore them here:
// CONSIDER (tomat): reusing the bound field initializers for implicitly typed fields.
...
...
src/Compilers/CSharp/Portable/Binder/Binder_InterpolatedString.cs
浏览文件 @
e8f52801
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#
nullable
enable
using
System
;
using
System.Collections.Generic
;
...
...
@@ -47,8 +48,8 @@ private BoundExpression BindInterpolatedString(InterpolatedStringExpressionSynta
// GenerateConversionForAssignment with objectType. However we want to preserve the original expression's
// natural type so that overload resolution may select a specialized implementation of string.Format,
// so we discard the result of that call and only preserve its diagnostics.
BoundExpression
alignment
=
null
;
BoundLiteral
format
=
null
;
BoundExpression
?
alignment
=
null
;
BoundLiteral
?
format
=
null
;
if
(
interpolation
.
AlignmentClause
!=
null
)
{
alignment
=
GenerateConversionForAssignment
(
intType
,
BindValue
(
interpolation
.
AlignmentClause
.
Value
,
diagnostics
,
Binder
.
BindValueKind
.
RValue
),
diagnostics
);
...
...
src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs
浏览文件 @
e8f52801
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#
nullable
enable
using
System
;
using
System.Collections.Immutable
;
...
...
@@ -75,7 +76,7 @@ internal partial class Binder
hasSignature
=
anon
.
ParameterList
!=
null
;
if
(
hasSignature
)
{
parameterSyntaxList
=
anon
.
ParameterList
.
Parameters
;
parameterSyntaxList
=
anon
.
ParameterList
!
.
Parameters
;
}
isAsync
=
(
anon
.
AsyncKeyword
.
Kind
()
==
SyntaxKind
.
AsyncKeyword
);
break
;
...
...
src/Compilers/CSharp/Portable/Binder/Binder_NameConflicts.cs
浏览文件 @
e8f52801
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#
nullable
enable
using
System.Collections.Immutable
;
using
Microsoft.CodeAnalysis.CSharp.Symbols
;
...
...
@@ -33,7 +34,7 @@ private static Location GetLocation(Symbol symbol)
bool
allowShadowingNames
,
DiagnosticBag
diagnostics
)
{
PooledHashSet
<
string
>
tpNames
=
null
;
PooledHashSet
<
string
>
?
tpNames
=
null
;
if
(!
typeParameters
.
IsDefaultOrEmpty
)
{
tpNames
=
PooledHashSet
<
string
>.
GetInstance
();
...
...
@@ -56,7 +57,7 @@ private static Location GetLocation(Symbol symbol)
}
}
PooledHashSet
<
string
>
pNames
=
null
;
PooledHashSet
<
string
>
?
pNames
=
null
;
if
(!
parameters
.
IsDefaultOrEmpty
)
{
pNames
=
PooledHashSet
<
string
>.
GetInstance
();
...
...
@@ -93,7 +94,7 @@ private static Location GetLocation(Symbol symbol)
/// <remarks>
/// Don't call this one directly - call one of the helpers.
/// </remarks>
private
bool
ValidateNameConflictsInScope
(
Symbol
symbol
,
Location
location
,
string
name
,
DiagnosticBag
diagnostics
)
private
bool
ValidateNameConflictsInScope
(
Symbol
?
symbol
,
Location
location
,
string
name
,
DiagnosticBag
diagnostics
)
{
if
(
string
.
IsNullOrEmpty
(
name
))
{
...
...
@@ -102,7 +103,7 @@ private bool ValidateNameConflictsInScope(Symbol symbol, Location location, stri
bool
allowShadowing
=
Compilation
.
IsFeatureEnabled
(
MessageID
.
IDS_FeatureNameShadowingInNestedFunctions
);
for
(
Binder
binder
=
this
;
binder
!=
null
;
binder
=
binder
.
Next
)
for
(
Binder
?
binder
=
this
;
binder
!=
null
;
binder
=
binder
.
Next
)
{
// no local scopes enclose members
if
(
binder
is
InContainerBinder
)
...
...
src/Compilers/CSharp/Portable/Binder/Binder_Query.cs
浏览文件 @
e8f52801
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#
nullable
enable
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
...
...
@@ -53,7 +54,7 @@ internal BoundExpression BindQuery(QueryExpressionSyntax node, DiagnosticBag dia
// from T x in e
// is translated into
// from x in ( e ) . Cast < T > ( )
BoundExpression
cast
=
null
;
BoundExpression
?
cast
=
null
;
if
(
fromClause
.
Type
!=
null
)
{
var
typeRestriction
=
BindTypeArgument
(
fromClause
.
Type
,
diagnostics
);
...
...
@@ -63,7 +64,7 @@ internal BoundExpression BindQuery(QueryExpressionSyntax node, DiagnosticBag dia
state
.
fromExpression
=
MakeQueryClause
(
fromClause
,
state
.
fromExpression
,
x
,
castInvocation
:
cast
);
BoundExpression
result
=
BindQueryInternal1
(
state
,
diagnostics
);
for
(
QueryContinuationSyntax
continuation
=
node
.
Body
.
Continuation
;
continuation
!=
null
;
continuation
=
continuation
.
Body
.
Continuation
)
for
(
QueryContinuationSyntax
?
continuation
=
node
.
Body
.
Continuation
;
continuation
!=
null
;
continuation
=
continuation
.
Body
.
Continuation
)
{
// A query expression with a continuation
// from ... into x ...
...
...
@@ -129,7 +130,7 @@ private BoundExpression BindQueryInternal2(QueryTranslationState state, Diagnost
// ignore missing or malformed Select method
DiagnosticBag
discarded
=
DiagnosticBag
.
GetInstance
();
var
unoptimized
=
FinalTranslation
(
state
,
discarded
);
BoundExpression
?
unoptimized
=
FinalTranslation
(
state
,
discarded
);
discarded
.
Free
();
if
(
unoptimized
.
HasAnyErrors
&&
!
result
.
HasAnyErrors
)
unoptimized
=
null
;
...
...
@@ -186,7 +187,7 @@ private BoundExpression FinalTranslation(QueryTranslationState state, Diagnostic
// k and v appear reversed in the invocation, so we reorder their evaluation
result
=
ReverseLastTwoParameterOrder
(
result
);
BoundExpression
unoptimizedForm
=
null
;
BoundExpression
?
unoptimizedForm
=
null
;
if
(
vId
!=
null
&&
vId
.
Identifier
.
ValueText
==
x
.
Name
)
{
// The optimized form. We store the unoptimized form for analysis
...
...
@@ -284,7 +285,7 @@ private void ReduceJoin(JoinClauseSyntax join, QueryTranslationState state, Diag
inExpression
=
BadExpression
(
join
.
InExpression
,
inExpression
);
}
BoundExpression
castInvocation
=
null
;
BoundExpression
?
castInvocation
=
null
;
if
(
join
.
Type
!=
null
)
{
// A join clause that explicitly specifies a range variable type
...
...
@@ -474,7 +475,7 @@ private void ReduceFrom(FromClauseSyntax from, QueryTranslationState state, Diag
diagnostics
);
// Adjust the second-to-last parameter to be a query clause (if it was an extension method, an extra parameter was added)
BoundExpression
castInvocation
=
(
from
.
Type
!=
null
)
?
ExtractCastInvocation
(
invocation
)
:
null
;
BoundExpression
?
castInvocation
=
(
from
.
Type
!=
null
)
?
ExtractCastInvocation
(
invocation
)
:
null
;
var
arguments
=
invocation
.
Arguments
;
invocation
=
invocation
.
Update
(
...
...
@@ -512,12 +513,12 @@ private void ReduceFrom(FromClauseSyntax from, QueryTranslationState state, Diag
ImmutableArray
.
Create
(
collectionSelectorLambda
,
resultSelectorLambda
),
diagnostics
);
BoundExpression
castInvocation
=
(
from
.
Type
!=
null
)
?
ExtractCastInvocation
(
invocation
)
:
null
;
BoundExpression
?
castInvocation
=
(
from
.
Type
!=
null
)
?
ExtractCastInvocation
(
invocation
)
:
null
;
state
.
fromExpression
=
MakeQueryClause
(
from
,
invocation
,
x2
,
invocation
,
castInvocation
);
}
}
private
static
BoundExpression
ExtractCastInvocation
(
BoundCall
invocation
)
private
static
BoundExpression
?
ExtractCastInvocation
(
BoundCall
invocation
)
{
int
index
=
invocation
.
InvokedAsExtensionMethod
?
1
:
0
;
var
c1
=
invocation
.
Arguments
[
index
]
as
BoundConversion
;
...
...
@@ -569,8 +570,7 @@ private void ReduceLet(LetClauseSyntax let, QueryTranslationState state, Diagnos
{
var
xExpression
=
new
BoundParameter
(
let
,
lambdaSymbol
.
Parameters
[
0
])
{
WasCompilerGenerated
=
true
};
lambdaBodyBinder
=
lambdaBodyBinder
.
GetBinder
(
let
.
Expression
);
Debug
.
Assert
(
lambdaBodyBinder
!=
null
);
lambdaBodyBinder
=
lambdaBodyBinder
.
GetRequiredBinder
(
let
.
Expression
);
var
yExpression
=
lambdaBodyBinder
.
BindRValueWithoutTargetType
(
let
.
Expression
,
d
);
SourceLocation
errorLocation
=
new
SourceLocation
(
let
.
SyntaxTree
,
new
TextSpan
(
let
.
Identifier
.
SpanStart
,
let
.
Expression
.
Span
.
End
-
let
.
Identifier
.
SpanStart
));
...
...
@@ -579,9 +579,9 @@ private void ReduceLet(LetClauseSyntax let, QueryTranslationState state, Diagnos
Error
(
d
,
ErrorCode
.
ERR_QueryRangeVariableAssignedBadValue
,
errorLocation
,
yExpression
.
Display
);
yExpression
=
new
BoundBadExpression
(
yExpression
.
Syntax
,
LookupResultKind
.
Empty
,
ImmutableArray
<
Symbol
>.
Empty
,
ImmutableArray
.
Create
(
yExpression
),
CreateErrorType
());
}
else
if
(!
yExpression
.
HasAnyErrors
&&
yExpression
.
Type
.
IsVoidType
())
else
if
(!
yExpression
.
HasAnyErrors
&&
yExpression
.
Type
!
.
IsVoidType
())
{
Error
(
d
,
ErrorCode
.
ERR_QueryRangeVariableAssignedBadValue
,
errorLocation
,
yExpression
.
Type
);
Error
(
d
,
ErrorCode
.
ERR_QueryRangeVariableAssignedBadValue
,
errorLocation
,
yExpression
.
Type
!
);
yExpression
=
new
BoundBadExpression
(
yExpression
.
Syntax
,
LookupResultKind
.
Empty
,
ImmutableArray
<
Symbol
>.
Empty
,
ImmutableArray
.
Create
(
yExpression
),
yExpression
.
Type
);
}
...
...
@@ -615,10 +615,10 @@ private BoundBlock CreateLambdaBlockForQueryClause(ExpressionSyntax expression,
private
BoundQueryClause
MakeQueryClause
(
CSharpSyntaxNode
syntax
,
BoundExpression
expression
,
RangeVariableSymbol
definedSymbol
=
null
,
BoundExpression
queryInvocation
=
null
,
BoundExpression
castInvocation
=
null
,
BoundExpression
unoptimizedForm
=
null
)
RangeVariableSymbol
?
definedSymbol
=
null
,
BoundExpression
?
queryInvocation
=
null
,
BoundExpression
?
castInvocation
=
null
,
BoundExpression
?
unoptimizedForm
=
null
)
{
if
(
unoptimizedForm
!=
null
&&
unoptimizedForm
.
HasAnyErrors
&&
!
expression
.
HasAnyErrors
)
unoptimizedForm
=
null
;
return
new
BoundQueryClause
(
...
...
@@ -636,7 +636,7 @@ private BoundExpression MakePair(CSharpSyntaxNode node, string field1Name, Bound
{
// we will generate a diagnostic elsewhere
field2Name
=
state
.
TransparentRangeVariableName
();
field2Value
=
new
BoundBadExpression
(
field2Value
.
Syntax
,
LookupResultKind
.
Empty
,
ImmutableArray
<
Symbol
>.
Empty
,
ImmutableArray
.
Create
(
field2Value
),
field2Value
.
Type
,
true
);
field2Value
=
new
BoundBadExpression
(
field2Value
.
Syntax
,
LookupResultKind
.
Empty
,
ImmutableArray
<
Symbol
?
>.
Empty
,
ImmutableArray
.
Create
(
field2Value
),
field2Value
.
Type
,
true
);
}
AnonymousTypeDescriptor
typeDescriptor
=
new
AnonymousTypeDescriptor
(
...
...
@@ -668,7 +668,7 @@ private UnboundLambda MakeQueryUnboundLambda(RangeVariableMap qvm, ImmutableArra
{
return
MakeQueryUnboundLambda
(
expression
,
new
QueryUnboundLambdaState
(
this
,
qvm
,
parameters
,
(
LambdaSymbol
lambdaSymbol
,
Binder
lambdaBodyBinder
,
DiagnosticBag
diagnostics
)
=>
{
lambdaBodyBinder
=
lambdaBodyBinder
.
GetBinder
(
expression
);
lambdaBodyBinder
=
lambdaBodyBinder
.
Get
Required
Binder
(
expression
);
Debug
.
Assert
(
lambdaSymbol
!=
null
);
BoundExpression
boundExpression
=
lambdaBodyBinder
.
BindValue
(
expression
,
diagnostics
,
BindValueKind
.
RValue
);
return
lambdaBodyBinder
.
CreateLambdaBlockForQueryClause
(
expression
,
boundExpression
,
diagnostics
);
...
...
@@ -679,8 +679,7 @@ private UnboundLambda MakeQueryUnboundLambdaWithCast(RangeVariableMap qvm, Range
{
return
MakeQueryUnboundLambda
(
expression
,
new
QueryUnboundLambdaState
(
this
,
qvm
,
ImmutableArray
.
Create
(
parameter
),
(
LambdaSymbol
lambdaSymbol
,
Binder
lambdaBodyBinder
,
DiagnosticBag
diagnostics
)
=>
{
lambdaBodyBinder
=
lambdaBodyBinder
.
GetBinder
(
expression
);
Debug
.
Assert
(
lambdaBodyBinder
!=
null
);
lambdaBodyBinder
=
lambdaBodyBinder
.
GetRequiredBinder
(
expression
);
BoundExpression
boundExpression
=
lambdaBodyBinder
.
BindValue
(
expression
,
diagnostics
,
BindValueKind
.
RValue
);
// We transform the expression from "expr" to "expr.Cast<castTypeOpt>()".
...
...
@@ -723,7 +722,8 @@ protected BoundCall MakeQueryInvocation(CSharpSyntaxNode node, BoundExpression r
// clean up the receiver
var
ultimateReceiver
=
receiver
;
while
(
ultimateReceiver
.
Kind
==
BoundKind
.
QueryClause
)
ultimateReceiver
=
((
BoundQueryClause
)
ultimateReceiver
).
Value
;
if
((
object
)
ultimateReceiver
.
Type
==
null
)
Debug
.
Assert
(
receiver
.
Type
is
object
||
ultimateReceiver
.
Type
is
null
);
if
((
object
?)
ultimateReceiver
.
Type
==
null
)
{
if
(
ultimateReceiver
.
HasAnyErrors
||
node
.
HasErrors
)
{
...
...
@@ -749,7 +749,7 @@ protected BoundCall MakeQueryInvocation(CSharpSyntaxNode node, BoundExpression r
else
if
(
ultimateReceiver
.
Kind
==
BoundKind
.
MethodGroup
)
{
var
methodGroup
=
(
BoundMethodGroup
)
ultimateReceiver
;
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
=
null
;
HashSet
<
DiagnosticInfo
>
?
useSiteDiagnostics
=
null
;
var
resolution
=
this
.
ResolveMethodGroup
(
methodGroup
,
analyzedArguments
:
null
,
isMethodGroupConversion
:
false
,
useSiteDiagnostics
:
ref
useSiteDiagnostics
);
diagnostics
.
Add
(
node
,
useSiteDiagnostics
);
diagnostics
.
AddRange
(
resolution
.
Diagnostics
);
...
...
@@ -767,7 +767,7 @@ protected BoundCall MakeQueryInvocation(CSharpSyntaxNode node, BoundExpression r
receiver
=
new
BoundBadExpression
(
receiver
.
Syntax
,
LookupResultKind
.
NotAValue
,
ImmutableArray
<
Symbol
>.
Empty
,
ImmutableArray
.
Create
(
receiver
),
CreateErrorType
());
}
else
if
(
receiver
.
Type
.
IsVoidType
())
else
if
(
receiver
.
Type
!
.
IsVoidType
())
{
if
(!
receiver
.
HasAnyErrors
&&
!
node
.
HasErrors
)
{
...
...
src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml
浏览文件 @
e8f52801
...
...
@@ -1576,7 +1576,7 @@
<AbstractNode
Name=
"BoundTupleExpression"
Base=
"BoundExpression"
>
<Field
Name=
"Arguments"
Type=
"ImmutableArray<BoundExpression>"
/>
<Field
Name=
"ArgumentNamesOpt"
Type=
"ImmutableArray<string>"
Null=
"allow"
/>
<Field
Name=
"ArgumentNamesOpt"
Type=
"ImmutableArray<string
?
>"
Null=
"allow"
/>
<!-- Which argument names were inferred (as opposed to explicitly provided)? -->
<Field
Name=
"InferredNamesOpt"
Type=
"ImmutableArray<bool>"
Null=
"allow"
/>
...
...
src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs
浏览文件 @
e8f52801
...
...
@@ -5542,7 +5542,7 @@ public BoundObjectCreationExpression Update(MethodSymbol constructor, ImmutableA
internal abstract partial class BoundTupleExpression : BoundExpression
{
protected BoundTupleExpression(BoundKind kind, SyntaxNode syntax, ImmutableArray<BoundExpression> arguments, ImmutableArray<string> argumentNamesOpt, ImmutableArray<bool> inferredNamesOpt, TypeSymbol? type, bool hasErrors = false)
protected BoundTupleExpression(BoundKind kind, SyntaxNode syntax, ImmutableArray<BoundExpression> arguments, ImmutableArray<string
?
> argumentNamesOpt, ImmutableArray<bool> inferredNamesOpt, TypeSymbol? type, bool hasErrors = false)
: base(kind, syntax, type, hasErrors)
{
...
...
@@ -5556,14 +5556,14 @@ protected BoundTupleExpression(BoundKind kind, SyntaxNode syntax, ImmutableArray
public ImmutableArray<BoundExpression> Arguments { get; }
public ImmutableArray<string> ArgumentNamesOpt { get; }
public ImmutableArray<string
?
> ArgumentNamesOpt { get; }
public ImmutableArray<bool> InferredNamesOpt { get; }
}
internal sealed partial class BoundTupleLiteral : BoundTupleExpression
{
public BoundTupleLiteral(SyntaxNode syntax, ImmutableArray<BoundExpression> arguments, ImmutableArray<string> argumentNamesOpt, ImmutableArray<bool> inferredNamesOpt, TypeSymbol? type, bool hasErrors = false)
public BoundTupleLiteral(SyntaxNode syntax, ImmutableArray<BoundExpression> arguments, ImmutableArray<string
?
> argumentNamesOpt, ImmutableArray<bool> inferredNamesOpt, TypeSymbol? type, bool hasErrors = false)
: base(BoundKind.TupleLiteral, syntax, arguments, argumentNamesOpt, inferredNamesOpt, type, hasErrors || arguments.HasErrors())
{
...
...
@@ -5576,7 +5576,7 @@ public BoundTupleLiteral(SyntaxNode syntax, ImmutableArray<BoundExpression> argu
[DebuggerStepThrough]
public override BoundNode? Accept(BoundTreeVisitor visitor) => visitor.VisitTupleLiteral(this);
public BoundTupleLiteral Update(ImmutableArray<BoundExpression> arguments, ImmutableArray<string> argumentNamesOpt, ImmutableArray<bool> inferredNamesOpt, TypeSymbol? type)
public BoundTupleLiteral Update(ImmutableArray<BoundExpression> arguments, ImmutableArray<string
?
> argumentNamesOpt, ImmutableArray<bool> inferredNamesOpt, TypeSymbol? type)
{
if (arguments != this.Arguments || argumentNamesOpt != this.ArgumentNamesOpt || inferredNamesOpt != this.InferredNamesOpt || !TypeSymbol.Equals(type, this.Type, TypeCompareKind.ConsiderEverything))
{
...
...
@@ -5590,7 +5590,7 @@ public BoundTupleLiteral Update(ImmutableArray<BoundExpression> arguments, Immut
internal sealed partial class BoundConvertedTupleLiteral : BoundTupleExpression
{
public BoundConvertedTupleLiteral(SyntaxNode syntax, BoundTupleLiteral? sourceTuple, bool wasTargetTyped, ImmutableArray<BoundExpression> arguments, ImmutableArray<string> argumentNamesOpt, ImmutableArray<bool> inferredNamesOpt, TypeSymbol? type, bool hasErrors = false)
public BoundConvertedTupleLiteral(SyntaxNode syntax, BoundTupleLiteral? sourceTuple, bool wasTargetTyped, ImmutableArray<BoundExpression> arguments, ImmutableArray<string
?
> argumentNamesOpt, ImmutableArray<bool> inferredNamesOpt, TypeSymbol? type, bool hasErrors = false)
: base(BoundKind.ConvertedTupleLiteral, syntax, arguments, argumentNamesOpt, inferredNamesOpt, type, hasErrors || sourceTuple.HasErrors() || arguments.HasErrors())
{
...
...
@@ -5607,7 +5607,7 @@ public BoundConvertedTupleLiteral(SyntaxNode syntax, BoundTupleLiteral? sourceTu
[DebuggerStepThrough]
public override BoundNode? Accept(BoundTreeVisitor visitor) => visitor.VisitConvertedTupleLiteral(this);
public BoundConvertedTupleLiteral Update(BoundTupleLiteral? sourceTuple, bool wasTargetTyped, ImmutableArray<BoundExpression> arguments, ImmutableArray<string> argumentNamesOpt, ImmutableArray<bool> inferredNamesOpt, TypeSymbol? type)
public BoundConvertedTupleLiteral Update(BoundTupleLiteral? sourceTuple, bool wasTargetTyped, ImmutableArray<BoundExpression> arguments, ImmutableArray<string
?
> argumentNamesOpt, ImmutableArray<bool> inferredNamesOpt, TypeSymbol? type)
{
if (sourceTuple != this.SourceTuple || wasTargetTyped != this.WasTargetTyped || arguments != this.Arguments || argumentNamesOpt != this.ArgumentNamesOpt || inferredNamesOpt != this.InferredNamesOpt || !TypeSymbol.Equals(type, this.Type, TypeCompareKind.ConsiderEverything))
{
...
...
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_DeconstructionAssignmentOperator.cs
浏览文件 @
e8f52801
...
...
@@ -129,7 +129,7 @@ private BoundExpression RewriteDeconstruction(BoundTupleExpression left, Convers
for
(
int
i
=
0
;
i
<
leftTargets
.
Count
;
i
++)
{
BoundExpression
resultPart
;
if
(
leftTargets
[
i
].
HasNestedVariables
)
if
(
leftTargets
[
i
].
NestedVariables
is
object
)
{
resultPart
=
ApplyDeconstructionConversion
(
leftTargets
[
i
].
NestedVariables
,
rightParts
[
i
],
underlyingConversions
[
i
],
temps
,
effects
,
isUsed
,
inInit
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录