提交 365288c1 编写于 作者: J Julien Couvreur 提交者: GitHub

Factoring common VariablePendingInference code (#16983)

上级 d2047c69
......@@ -1606,29 +1606,24 @@
<Field Name="Expression" Type="BoundExpression" Null="disallow"/>
</Node>
<!-- The node is transformed into BoundLocal or BoundFieldAccess after inference -->
<Node Name="OutVariablePendingInference" Base="BoundExpression">
<AbstractNode Name="VariablePendingInference" Base="BoundExpression">
<!-- Type is not significant for this node type; always null -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="always"/>
<!-- A local symbol or a field symbol representing the variable -->
<Field Name="VariableSymbol" Type="Symbol"/>
<!-- A field receiver when VariableSymbol is a field -->
<Field Name="ReceiverOpt" Type="BoundExpression" Null="allow"/>
</Node>
</AbstractNode>
<!-- The node is transformed into BoundDeconstructValuePlaceholder after inference -->
<Node Name="OutDeconstructVarPendingInference" Base="BoundExpression">
<!-- Type is not significant for this node type; always null -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="always"/>
</Node>
<!-- The node is transformed into BoundLocal or BoundFieldAccess after inference -->
<Node Name="OutVariablePendingInference" Base="VariablePendingInference" />
<!-- The node is transformed into BoundLocal or BoundFieldAccess after inference -->
<Node Name="DeconstructionVariablePendingInference" Base="BoundExpression">
<Node Name="DeconstructionVariablePendingInference" Base="VariablePendingInference" />
<!-- The node is transformed into BoundDeconstructValuePlaceholder after inference -->
<Node Name="OutDeconstructVarPendingInference" Base="BoundExpression">
<!-- Type is not significant for this node type; always null -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="always"/>
<!-- A local symbol or a field symbol representing the variable -->
<Field Name="VariableSymbol" Type="Symbol"/>
<!-- A field receiver when VariableSymbol is a field -->
<Field Name="ReceiverOpt" Type="BoundExpression" Null="allow"/>
</Node>
</Tree>
// 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 Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Diagnostics;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp
{
internal partial class DeconstructionVariablePendingInference
{
public BoundExpression SetInferredType(TypeSymbol type, Binder binderOpt, DiagnosticBag diagnostics)
{
Debug.Assert(binderOpt != null || (object)type != null);
Debug.Assert(this.Syntax.Kind() == SyntaxKind.SingleVariableDesignation ||
(this.Syntax.Kind() == SyntaxKind.DeclarationExpression &&
((DeclarationExpressionSyntax)this.Syntax).Designation.Kind() == SyntaxKind.SingleVariableDesignation));
bool inferenceFailed = ((object)type == null);
if (inferenceFailed)
{
type = binderOpt.CreateErrorType("var");
}
switch (this.VariableSymbol.Kind)
{
case SymbolKind.Local:
var local = (SourceLocalSymbol)this.VariableSymbol;
if (inferenceFailed)
{
ReportInferenceFailure(diagnostics);
}
else
{
Binder.CheckRestrictedTypeInAsync(local.ContainingSymbol, type, diagnostics, this.Syntax);
}
local.SetType(type);
return new BoundLocal(this.Syntax, local, isDeclaration: true, constantValueOpt: null, type: type, hasErrors: this.HasErrors || inferenceFailed);
case SymbolKind.Field:
var field = (GlobalExpressionVariable)this.VariableSymbol;
var inferenceDiagnostics = DiagnosticBag.GetInstance();
if (inferenceFailed)
{
ReportInferenceFailure(inferenceDiagnostics);
}
field.SetType(type, inferenceDiagnostics);
inferenceDiagnostics.Free();
return new BoundFieldAccess(this.Syntax, this.ReceiverOpt, field, constantValueOpt: null, hasErrors: this.HasErrors || inferenceFailed);
default:
throw ExceptionUtilities.UnexpectedValue(this.VariableSymbol.Kind);
}
}
private void ReportInferenceFailure(DiagnosticBag diagnostics)
{
SingleVariableDesignationSyntax designation;
switch (this.Syntax.Kind())
{
case SyntaxKind.SingleVariableDesignation:
designation = (SingleVariableDesignationSyntax)this.Syntax;
break;
case SyntaxKind.DeclarationExpression:
designation = (SingleVariableDesignationSyntax)((DeclarationExpressionSyntax)this.Syntax).Designation;
break;
default:
throw ExceptionUtilities.UnexpectedValue(this.Syntax.Kind());
}
Binder.Error(
diagnostics, ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, designation.Identifier,
designation.Identifier.ValueText);
}
public BoundExpression FailInference(Binder binder, DiagnosticBag diagnosticsOpt)
{
return this.SetInferredType(null, binder, diagnosticsOpt);
}
}
}
\ No newline at end of file
......@@ -2945,32 +2945,10 @@ public override void Accept(OperationVisitor visitor)
}
/// <summary>
/// This node represents an out variable.
/// This node represents an out or deconstruction variable.
/// It is only used temporarily during initial binding.
/// </summary>
internal partial class OutVariablePendingInference
{
public override void Accept(OperationVisitor visitor)
{
throw ExceptionUtilities.Unreachable;
}
public override TResult Accept<TArgument, TResult>(OperationVisitor<TArgument, TResult> visitor, TArgument argument)
{
throw ExceptionUtilities.Unreachable;
}
protected override OperationKind ExpressionKind
{
get { throw ExceptionUtilities.Unreachable; }
}
}
/// <summary>
/// This node represents a deconstruction local.
/// It is only used temporarily during initial binding.
/// </summary>
internal partial class DeconstructionVariablePendingInference
internal partial class VariablePendingInference
{
public override void Accept(OperationVisitor visitor)
{
......
......@@ -4,22 +4,35 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Roslyn.Utilities;
using System.Diagnostics;
using System;
namespace Microsoft.CodeAnalysis.CSharp
{
internal partial class DeconstructionVariablePendingInference
{
protected override ErrorCode InferenceFailedError => ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable;
}
internal partial class OutVariablePendingInference
{
public BoundExpression SetInferredType(TypeSymbol type, DiagnosticBag diagnosticsOpt)
protected override ErrorCode InferenceFailedError => ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedOutVariable;
}
internal partial class VariablePendingInference : BoundExpression
{
internal BoundExpression SetInferredType(TypeSymbol type, DiagnosticBag diagnosticsOpt)
{
Debug.Assert((object)type != null);
return SetInferredType(type, null, diagnosticsOpt);
}
private BoundExpression SetInferredType(TypeSymbol type, Binder binderOpt, DiagnosticBag diagnosticsOpt)
internal BoundExpression SetInferredType(TypeSymbol type, Binder binderOpt, DiagnosticBag diagnosticsOpt)
{
Debug.Assert(binderOpt != null || (object)type != null);
Debug.Assert(this.Syntax.Kind() == SyntaxKind.DeclarationExpression);
Debug.Assert(this.Syntax.Kind() == SyntaxKind.SingleVariableDesignation ||
(this.Syntax.Kind() == SyntaxKind.DeclarationExpression &&
((DeclarationExpressionSyntax)this.Syntax).Designation.Kind() == SyntaxKind.SingleVariableDesignation));
bool inferenceFailed = ((object)type == null);
......@@ -41,8 +54,11 @@ private BoundExpression SetInferredType(TypeSymbol type, Binder binderOpt, Diagn
}
else
{
TypeSyntax typeSyntax = ((DeclarationExpressionSyntax)Syntax).Type;
Binder.CheckRestrictedTypeInAsync(localSymbol.ContainingSymbol, type, diagnosticsOpt, typeSyntax);
SyntaxNode typeOrDesignationSyntax = this.Syntax.Kind() == SyntaxKind.DeclarationExpression ?
((DeclarationExpressionSyntax)this.Syntax).Type :
this.Syntax;
Binder.CheckRestrictedTypeInAsync(localSymbol.ContainingSymbol, type, diagnosticsOpt, typeOrDesignationSyntax);
}
}
......@@ -63,26 +79,39 @@ private BoundExpression SetInferredType(TypeSymbol type, Binder binderOpt, Diagn
return new BoundFieldAccess(this.Syntax,
this.ReceiverOpt,
fieldSymbol, null, LookupResultKind.Viable, type,
fieldSymbol, null, LookupResultKind.Viable, type,
this.HasErrors || inferenceFailed);
default:
throw ExceptionUtilities.UnexpectedValue(this.VariableSymbol.Kind);
}
}
internal BoundExpression FailInference(Binder binder, DiagnosticBag diagnosticsOpt)
{
return this.SetInferredType(null, binder, diagnosticsOpt);
}
private void ReportInferenceFailure(DiagnosticBag diagnostics)
{
var designation = (SingleVariableDesignationSyntax)((DeclarationExpressionSyntax)this.Syntax).Designation;
SingleVariableDesignationSyntax designation;
switch (this.Syntax.Kind())
{
case SyntaxKind.DeclarationExpression:
designation = (SingleVariableDesignationSyntax)((DeclarationExpressionSyntax)this.Syntax).Designation;
break;
case SyntaxKind.SingleVariableDesignation:
designation = (SingleVariableDesignationSyntax)this.Syntax;
break;
default:
throw ExceptionUtilities.Unreachable;
}
Binder.Error(
diagnostics, ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedOutVariable, designation.Identifier,
diagnostics, this.InferenceFailedError, designation.Identifier,
designation.Identifier.ValueText);
}
public BoundExpression FailInference(Binder binder, DiagnosticBag diagnosticsOpt)
{
return this.SetInferredType(null, binder, diagnosticsOpt);
}
protected abstract ErrorCode InferenceFailedError { get; }
}
}
\ No newline at end of file
}
......@@ -176,9 +176,8 @@
<Compile Include="BoundTree\DecisionTree.cs" />
<Compile Include="BoundTree\DecisionTreeBuilder.cs" />
<Compile Include="BoundTree\Expression.cs" />
<Compile Include="BoundTree\DeconstructionVariablePendingInference.cs" />
<Compile Include="BoundTree\BoundDiscardExpression.cs" />
<Compile Include="BoundTree\OutVariablePendingInference.cs" />
<Compile Include="BoundTree\VariablePendingInference.cs" />
<Compile Include="BoundTree\OutDeconstructVarPendingInference.cs" />
<Compile Include="BoundTree\PseudoVariableExpressions.cs" />
<Compile Include="BoundTree\Formatting.cs" />
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册