Skip to content

Commit

Permalink
Merge branch 'release/dev17.2' into merges/release/dev17.1-to-release…
Browse files Browse the repository at this point in the history
…/dev17.2
  • Loading branch information
JoeRobich authored Mar 31, 2022
2 parents c43f531 + afe5eef commit 491a930
Show file tree
Hide file tree
Showing 4 changed files with 890 additions and 41 deletions.
14 changes: 4 additions & 10 deletions src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3402,7 +3402,7 @@ private BindValueKind GetRequiredReturnValueKind(RefKind refKind)
return requiredValueKind;
}

public virtual BoundNode BindMethodBody(CSharpSyntaxNode syntax, BindingDiagnosticBag diagnostics, bool includesFieldInitializers = false)
public virtual BoundNode BindMethodBody(CSharpSyntaxNode syntax, BindingDiagnosticBag diagnostics)
{
switch (syntax)
{
Expand All @@ -3412,7 +3412,7 @@ public virtual BoundNode BindMethodBody(CSharpSyntaxNode syntax, BindingDiagnost
case BaseMethodDeclarationSyntax method:
if (method.Kind() == SyntaxKind.ConstructorDeclaration)
{
return BindConstructorBody((ConstructorDeclarationSyntax)method, diagnostics, includesFieldInitializers);
return BindConstructorBody((ConstructorDeclarationSyntax)method, diagnostics);
}

return BindMethodBody(method, method.Body, method.ExpressionBody, diagnostics);
Expand Down Expand Up @@ -3484,7 +3484,7 @@ internal virtual BoundExpressionStatement BindConstructorInitializer(PrimaryCons
return constructorInitializer;
}

private BoundNode BindConstructorBody(ConstructorDeclarationSyntax constructor, BindingDiagnosticBag diagnostics, bool includesFieldInitializers)
private BoundNode BindConstructorBody(ConstructorDeclarationSyntax constructor, BindingDiagnosticBag diagnostics)
{
ConstructorInitializerSyntax initializer = constructor.Initializer;
if (initializer == null && constructor.Body == null && constructor.ExpressionBody == null)
Expand Down Expand Up @@ -3517,16 +3517,10 @@ private BoundNode BindConstructorBody(ConstructorDeclarationSyntax constructor,
Error(diagnostics, ErrorCode.ERR_RecordStructConstructorCallsDefaultConstructor, initializer.ThisOrBaseKeyword);
}

// The `: this()` initializer is ignored when it is a default value type constructor
// and we need to include field initializers into the constructor.
bool skipInitializer = includesFieldInitializers
&& isDefaultValueTypeInitializer;

// Using BindStatement to bind block to make sure we are reusing results of partial binding in SemanticModel
return new BoundConstructorMethodBody(constructor,
bodyBinder.GetDeclaredLocalsForScope(constructor),
skipInitializer ? new BoundNoOpStatement(constructor, NoOpStatementFlavor.Default)
: initializer == null ? null : bodyBinder.BindConstructorInitializer(initializer, diagnostics),
initializer == null ? null : bodyBinder.BindConstructorInitializer(initializer, diagnostics),
constructor.Body == null ? null : (BoundBlock)bodyBinder.BindStatement(constructor.Body, diagnostics),
constructor.ExpressionBody == null ?
null :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2474,7 +2474,7 @@ private BoundNode TryGetBoundNodeFromMap(CSharpSyntaxNode node)
return null;
}

public override BoundNode BindMethodBody(CSharpSyntaxNode node, BindingDiagnosticBag diagnostics, bool includeInitializersInBody)
public override BoundNode BindMethodBody(CSharpSyntaxNode node, BindingDiagnosticBag diagnostics)
{
BoundNode boundNode = TryGetBoundNodeFromMap(node);

Expand All @@ -2483,7 +2483,7 @@ public override BoundNode BindMethodBody(CSharpSyntaxNode node, BindingDiagnosti
return boundNode;
}

boundNode = base.BindMethodBody(node, diagnostics, includeInitializersInBody);
boundNode = base.BindMethodBody(node, diagnostics);

return boundNode;
}
Expand Down
30 changes: 18 additions & 12 deletions src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1054,11 +1054,14 @@ processedInitializers.AfterInitializersState is null &&
diagsForCurrentMethod,
processedInitializers.AfterInitializersState,
ReportNullableDiagnostics,
includesFieldInitializers: includeInitializersInBody && !processedInitializers.BoundInitializers.IsEmpty,
out importChain,
out originalBodyNested,
out bool prependedDefaultValueTypeConstructorInitializer,
out forSemanticModel);

Debug.Assert(!prependedDefaultValueTypeConstructorInitializer || originalBodyNested);
Debug.Assert(!prependedDefaultValueTypeConstructorInitializer || methodSymbol.ContainingType.IsStructType());

if (diagsForCurrentMethod.HasAnyErrors() && body != null)
{
body = (BoundBlock)body.WithHasErrors();
Expand All @@ -1081,7 +1084,13 @@ processedInitializers.AfterInitializersState is null &&
}

// In order to get correct diagnostics, we need to analyze initializers and the body together.
body = body.Update(body.Locals, body.LocalFunctions, body.Statements.Insert(0, analyzedInitializers));
int insertAt = 0;
if (originalBodyNested &&
prependedDefaultValueTypeConstructorInitializer)
{
insertAt = 1;
}
body = body.Update(body.Locals, body.LocalFunctions, body.Statements.Insert(insertAt, analyzedInitializers));
includeNonEmptyInitializersInBody = false;
analyzedInitializers = null;
}
Expand Down Expand Up @@ -1704,7 +1713,7 @@ private static void GetStateMachineSlotDebugInfo(
// NOTE: can return null if the method has no body.
internal static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationState compilationState, BindingDiagnosticBag diagnostics)
{
return BindMethodBody(method, compilationState, diagnostics, nullableInitialState: null, reportNullableDiagnostics: true, includesFieldInitializers: false, out _, out _, out _);
return BindMethodBody(method, compilationState, diagnostics, nullableInitialState: null, reportNullableDiagnostics: true, out _, out _, out _, out _);
}

// NOTE: can return null if the method has no body.
Expand All @@ -1714,12 +1723,13 @@ private static BoundBlock BindMethodBody(
BindingDiagnosticBag diagnostics,
NullableWalker.VariableState nullableInitialState,
bool reportNullableDiagnostics,
bool includesFieldInitializers,
out ImportChain importChain,
out bool originalBodyNested,
out bool prependedDefaultValueTypeConstructorInitializer,
out MethodBodySemanticModel.InitialState forSemanticModel)
{
originalBodyNested = false;
prependedDefaultValueTypeConstructorInitializer = false;
importChain = null;
forSemanticModel = default;

Expand Down Expand Up @@ -1754,7 +1764,7 @@ syntaxNode is ConstructorDeclarationSyntax constructorSyntax &&
if (bodyBinder != null)
{
importChain = bodyBinder.ImportChain;
BoundNode methodBody = bodyBinder.BindMethodBody(syntaxNode, diagnostics, includesFieldInitializers);
BoundNode methodBody = bodyBinder.BindMethodBody(syntaxNode, diagnostics);
BoundNode methodBodyForSemanticModel = methodBody;
NullableWalker.SnapshotManager snapshotManager = null;
ImmutableDictionary<Symbol, Symbol> remappedSymbols = null;
Expand Down Expand Up @@ -1801,13 +1811,7 @@ syntaxNode is ConstructorDeclarationSyntax constructorSyntax &&
var constructor = (BoundConstructorMethodBody)methodBody;
body = constructor.BlockBody ?? constructor.ExpressionBody;

if (constructor.Initializer is BoundNoOpStatement)
{
// We have field initializers and `: this()` is a default value type constructor.
Debug.Assert(body is not null);
return body;
}
else if (constructor.Initializer is BoundExpressionStatement expressionStatement)
if (constructor.Initializer is BoundExpressionStatement expressionStatement)
{
ReportCtorInitializerCycles(method, expressionStatement.Expression, compilationState, diagnostics);

Expand All @@ -1819,6 +1823,8 @@ syntaxNode is ConstructorDeclarationSyntax constructorSyntax &&
{
body = new BoundBlock(constructor.Syntax, constructor.Locals, ImmutableArray.Create<BoundStatement>(constructor.Initializer, body));
originalBodyNested = true;
prependedDefaultValueTypeConstructorInitializer =
expressionStatement.Expression is BoundCall { Method: var initMethod } && initMethod.IsDefaultValueTypeConstructor();
}

return body;
Expand Down
Loading

0 comments on commit 491a930

Please sign in to comment.