Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,11 @@ public override Binder VisitClassDeclaration(ClassDeclarationSyntax node)
return VisitTypeDeclarationCore(node);
}

public override Binder VisitRecordDeclaration(RecordDeclarationSyntax node)
{
return VisitTypeDeclarationCore(node);
}

public override Binder VisitStructDeclaration(StructDeclarationSyntax node)
{
return VisitTypeDeclarationCore(node);
Expand Down
7 changes: 5 additions & 2 deletions Src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,9 @@ private BoundExpression BindExpressionInternal(ExpressionSyntax node, Diagnostic
case SyntaxKind.IsExpression:
return BindIsOperator((BinaryExpressionSyntax)node, diagnostics);

case SyntaxKind.MatchExpression:
return BindMatchExpression((MatchExpressionSyntax)node, diagnostics);

case SyntaxKind.AsExpression:
return BindAsOperator((BinaryExpressionSyntax)node, diagnostics);

Expand Down Expand Up @@ -543,7 +546,7 @@ private BoundExpression BindDeclarationExpression(DeclarationExpressionSyntax no
TypeSymbol declType = BindVariableType(node, diagnostics, typeSyntax, ref isConst, out isVar, out alias);

SourceLocalSymbol localSymbol = this.LookupLocal(node.Variable.Identifier);

if ((object)localSymbol == null)
{
Error(diagnostics, ErrorCode.ERR_DeclarationExpressionOutOfContext, node);
Expand Down Expand Up @@ -1165,7 +1168,7 @@ private BoundExpression BindIdentifier(
Error(diagnostics, ErrorCode.ERR_NameNotInContext, node, node.Identifier.ValueText);
}
}

lookupResult.Free();
return expression;
}
Expand Down
35 changes: 30 additions & 5 deletions Src/Compilers/CSharp/Portable/Binder/Binder_Initializers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,29 @@ private static void BindRegularCSharpFieldInitializers(

foreach (var info in infos)
{
BoundFieldInitializer boundInitializer = BindFieldInitializer(info.Binder, info.Initializer.Field, info.EqualsValue, diagnostics);
BoundFieldInitializer boundInitializer;
if (info.EqualsValue.Kind == SyntaxKind.EqualsValueClause)
{
var equalsValueSyntax = (EqualsValueClauseSyntax)info.EqualsValue;
boundInitializer = BindFieldInitializer(info.Binder, info.Initializer.Field, equalsValueSyntax, diagnostics);
}
else
{
Debug.Assert(info.EqualsValue.Kind == SyntaxKind.RecordParameter);
// This is automatically generating backing field and its initializer for record parameters.

var recordParameter = (RecordParameterSyntax)info.EqualsValue;
var recordParameterName = recordParameter.Identifier.ValueText;
var lookupResult = LookupResult.GetInstance();
LookupOptions options = LookupOptions.AllMethodsOnArityZero;
HashSet<DiagnosticInfo> useSiteDiagnostics = null;
info.Binder.LookupSymbolsWithFallback(lookupResult, recordParameterName, arity: 0, useSiteDiagnostics: ref useSiteDiagnostics, options: options);
var parameterSymbol = lookupResult.Symbols[0];
Debug.Assert(parameterSymbol.Kind == SymbolKind.Parameter);
boundInitializer = new BoundFieldInitializer(recordParameter, info.Initializer.Field,
new BoundParameter(recordParameter, (ParameterSymbol)parameterSymbol));
lookupResult.Free();
}
initializersBuilder.Add(boundInitializer);
}

Expand Down Expand Up @@ -136,7 +158,7 @@ internal static ImmutableArray<LocalSymbol> GetFieldInitializerInfos(
{
//Can't assert that this is a regular C# compilation, because we could be in a nested type of a script class.
SyntaxReference syntaxRef = initializer.Syntax;
var initializerNode = (EqualsValueClauseSyntax)syntaxRef.GetSyntax();
var initializerNode = (CSharpSyntaxNode)syntaxRef.GetSyntax();

if (binderFactory == null)
{
Expand All @@ -145,6 +167,8 @@ internal static ImmutableArray<LocalSymbol> GetFieldInitializerInfos(

Binder parentBinder = binderFactory.GetBinder(initializerNode);
Debug.Assert(parentBinder.ContainingMemberOrLambda == fieldSymbol.ContainingType || //should be the binder for the type
parentBinder.ContainingMemberOrLambda == fieldSymbol.ContainingNamespace || //for the recordparametersyntax's binder
parentBinder.ContainingMemberOrLambda == fieldSymbol.ContainingType.ContainingType || //for the recordparametersyntax's binder
fieldSymbol.ContainingType.IsImplicitClass); //however, we also allow fields in namespaces to help support script scenarios

if (generateDebugInfo && firstDebugImports == null)
Expand Down Expand Up @@ -196,10 +220,11 @@ private static ImmutableArray<LocalSymbol> GetInitializationScopeLocals(ArrayBui
foreach (var info in infos)
{
// Constant initializers do not contribute to the initialization scope.
if (!info.Initializer.Field.IsConst)
if (!info.Initializer.Field.IsConst && info.EqualsValue.Kind == SyntaxKind.EqualsValueClause)
{
var walker = new LocalScopeBinder.BuildLocalsFromDeclarationsWalker(info.Binder, info.EqualsValue.Value);
walker.Visit(info.EqualsValue.Value);
var equalsValueExpression = ((EqualsValueClauseSyntax)info.EqualsValue).Value;
var walker = new LocalScopeBinder.BuildLocalsFromDeclarationsWalker(info.Binder, equalsValueExpression);
walker.Visit(equalsValueExpression);

if (walker.Locals != null)
{
Expand Down
42 changes: 41 additions & 1 deletion Src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Diagnostics;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Collections;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.CSharp
Expand Down Expand Up @@ -2392,11 +2393,50 @@ private static bool IsDivisionByZero(BinaryOperatorKind kind, ConstantValue valu
return false;
}

internal BoundExpression BindMatchExpression(MatchExpressionSyntax node, DiagnosticBag diagnostics)
{
var leftBound = BindValue(node.Expression, diagnostics, BindValueKind.RValue);
var pattern = node.Pattern;
var resultType = GetSpecialType(SpecialType.System_Boolean, diagnostics, node);
var rightBound = this.BindPattern(pattern, leftBound.Type, diagnostics);
return new BoundMatchExpression(node, leftBound, rightBound, resultType);
}

private BoundExpression BindIsOperator(BinaryExpressionSyntax node, DiagnosticBag diagnostics)
{
var operand = BindValue(node.Left, diagnostics, BindValueKind.RValue);
AliasSymbol alias;
TypeSymbol targetType = BindType(node.Right, diagnostics, out alias);
TypeSymbol targetType;
var options = (CSharpParseOptions)node.SyntaxTree.Options;
if (options.IsRecordsEnabled())
{
var extraDiagnostics = DiagnosticBag.GetInstance();
targetType = BindType(node.Right, extraDiagnostics, out alias);

// node.Right might be a constant and it might be converted to a constant expression (e.g., o is Days.Sun)
if (extraDiagnostics.HasAnyErrors() && node.Right is NameSyntax)
{
var diagnosticsForConstant = DiagnosticBag.GetInstance();
var boundConstant = BindValue(node.Right, diagnosticsForConstant, BindValueKind.RValue);
if (boundConstant.ConstantValue != null)
{
// E.g., (o is Days.Sun) Days.Sun would not be bound as a type so we will try our chance for a constant expression.
// If it is constant, remove old diagnostics about why Days.Sun could not be bounded as a type.
// Then, bind the is operator as a match expression.
extraDiagnostics.Free();
diagnostics.AddRangeAndFree(diagnosticsForConstant);
var boolType = GetSpecialType(SpecialType.System_Boolean, diagnostics, node);
return new BoundMatchExpression(node, operand, new BoundConstantPattern(node.Right, boundConstant), boolType);
}
diagnosticsForConstant.Free();
}
diagnostics.AddRangeAndFree(extraDiagnostics);
}
else
{
targetType = BindType(node.Right, diagnostics, out alias);
}

var typeExpression = new BoundTypeExpression(node.Right, alias, targetType);
var targetTypeKind = targetType.TypeKind;
var resultType = (TypeSymbol)GetSpecialType(SpecialType.System_Boolean, diagnostics, node);
Expand Down
Loading