diff --git a/docs/features/ExpressionVariables.md b/docs/features/ExpressionVariables.md new file mode 100644 index 0000000000000..9564f0eb6ee23 --- /dev/null +++ b/docs/features/ExpressionVariables.md @@ -0,0 +1,17 @@ +Expression Variables +========================= + +The *expression variables* feature extends the features introduced in C# 7 to permit expressions +containing expression variables (out variable declarations and declaration patterns) in field +initializers, property initializers, ctor-initializers, and query clauses. + +See https://github.com/dotnet/csharplang/issues/32 and +https://github.com/dotnet/csharplang/blob/master/proposals/expression-variables-in-initializers.md +for more information. + +Current state of the feature: + +[X] Permit in field initializers +[X] Permit in property initializers +[ ] Permit in ctor-initializers +[X] Permit in query clauses \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/Binder/BinderFactory.BinderFactoryVisitor.cs b/src/Compilers/CSharp/Portable/Binder/BinderFactory.BinderFactoryVisitor.cs index 3aa3764cd61d0..d5d233efdab75 100644 --- a/src/Compilers/CSharp/Portable/Binder/BinderFactory.BinderFactoryVisitor.cs +++ b/src/Compilers/CSharp/Portable/Binder/BinderFactory.BinderFactoryVisitor.cs @@ -209,6 +209,9 @@ public override Binder VisitDestructorDeclaration(DestructorDeclarationSyntax pa // Destructors have neither parameters nor type parameters, so there's nothing special to do here. resultBinder = VisitCore(parent.Parent); + SourceMemberMethodSymbol method = GetMethodSymbol(parent, resultBinder); + resultBinder = new InMethodBinder(method, resultBinder); + resultBinder = resultBinder.WithUnsafeRegionIfNecessary(parent.Modifiers); binderCache.TryAdd(key, resultBinder); diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index 740023e034672..9a06e3eef2d40 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -236,35 +236,43 @@ internal BoundExpression BindValueAllowArgList(ExpressionSyntax node, Diagnostic return CheckValue(result, valueKind, diagnostics); } - internal BoundExpression BindVariableOrAutoPropInitializer( + internal BoundFieldEqualsValue BindFieldInitializer( + FieldSymbol field, EqualsValueClauseSyntax initializerOpt, - RefKind refKind, - TypeSymbol varType, DiagnosticBag diagnostics) { + Debug.Assert((object)this.ContainingMemberOrLambda == field); + if (initializerOpt == null) { return null; } - SymbolKind containingMemberOrLambdaKind = this.ContainingMemberOrLambda.Kind; - Debug.Assert(containingMemberOrLambdaKind == SymbolKind.Field || containingMemberOrLambdaKind == SymbolKind.Method); - bool isMemberInitializer = containingMemberOrLambdaKind == SymbolKind.Field; - Binder initializerBinder = isMemberInitializer ? this.GetBinder(initializerOpt) : this; - + Binder initializerBinder = this.GetBinder(initializerOpt); Debug.Assert(initializerBinder != null); - BindValueKind valueKind; - ExpressionSyntax value; - IsInitializerRefKindValid(initializerOpt, initializerOpt, refKind, diagnostics, out valueKind, out value); - var initializer = initializerBinder.BindPossibleArrayInitializer(value, varType, valueKind, diagnostics); - initializer = initializerBinder.GenerateConversionForAssignment(varType, initializer, diagnostics); + BoundExpression result = initializerBinder.BindVariableOrAutoPropInitializerValue(initializerOpt, RefKind.None, + field.GetFieldType(initializerBinder.FieldsBeingBound), diagnostics); - if (isMemberInitializer) + return new BoundFieldEqualsValue(initializerOpt, field, initializerBinder.GetDeclaredLocalsForScope(initializerOpt), result); + } + + internal BoundExpression BindVariableOrAutoPropInitializerValue( + EqualsValueClauseSyntax initializerOpt, + RefKind refKind, + TypeSymbol varType, + DiagnosticBag diagnostics) + { + if (initializerOpt == null) { - initializer = initializerBinder.WrapWithVariablesIfAny(initializerOpt, initializer); + return null; } + BindValueKind valueKind; + ExpressionSyntax value; + IsInitializerRefKindValid(initializerOpt, initializerOpt, refKind, diagnostics, out valueKind, out value); + BoundExpression initializer = BindPossibleArrayInitializer(value, varType, valueKind, diagnostics); + initializer = GenerateConversionForAssignment(varType, initializer, diagnostics); return initializer; } @@ -278,9 +286,9 @@ internal Binder CreateBinderForParameterDefaultValue( binder); } - internal BoundExpression BindParameterDefaultValue( + internal BoundParameterEqualsValue BindParameterDefaultValue( EqualsValueClauseSyntax defaultValueSyntax, - TypeSymbol parameterType, + ParameterSymbol parameter, DiagnosticBag diagnostics, out BoundExpression valueBeforeConversion) { @@ -295,10 +303,11 @@ internal BoundExpression BindParameterDefaultValue( // Always generate the conversion, even if the expression is not convertible to the given type. // We want the erroneous conversion in the tree. - return defaultValueBinder.WrapWithVariablesIfAny(defaultValueSyntax, defaultValueBinder.GenerateConversionForAssignment(parameterType, valueBeforeConversion, diagnostics, isDefaultParameter: true)); + return new BoundParameterEqualsValue(defaultValueSyntax, parameter, defaultValueBinder.GetDeclaredLocalsForScope(defaultValueSyntax), + defaultValueBinder.GenerateConversionForAssignment(parameter.Type, valueBeforeConversion, diagnostics, isDefaultParameter: true)); } - internal BoundExpression BindEnumConstantInitializer( + internal BoundFieldEqualsValue BindEnumConstantInitializer( SourceEnumConstantSymbol symbol, EqualsValueClauseSyntax equalsValueSyntax, DiagnosticBag diagnostics) @@ -308,7 +317,7 @@ internal BoundExpression BindEnumConstantInitializer( var initializer = initializerBinder.BindValue(equalsValueSyntax.Value, diagnostics, BindValueKind.RValue); initializer = initializerBinder.GenerateConversionForAssignment(symbol.ContainingType.EnumUnderlyingType, initializer, diagnostics); - return initializerBinder.WrapWithVariablesIfAny(equalsValueSyntax, initializer); + return new BoundFieldEqualsValue(equalsValueSyntax, symbol, initializerBinder.GetDeclaredLocalsForScope(equalsValueSyntax), initializer); } public BoundExpression BindExpression(ExpressionSyntax node, DiagnosticBag diagnostics) @@ -2311,7 +2320,7 @@ private BoundExpression BindOutVariableDeclarationArgument( Debug.Assert(localSymbol.DeclarationKind == LocalDeclarationKind.OutVariable); if ((InConstructorInitializer || InFieldInitializer) && ContainingMemberOrLambda.ContainingSymbol.Kind == SymbolKind.NamedType) { - Error(diagnostics, ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, declarationExpression); + CheckFeatureAvailability(declarationExpression, MessageID.IDS_FeatureExpressionVariablesInQueriesAndInitializers, diagnostics); } bool isConst = false; @@ -3318,14 +3327,20 @@ internal BoundExpression BindConstructorInitializer( MethodSymbol constructor, DiagnosticBag diagnostics) { - Binder initializerBinder = initializerArgumentListOpt == null ? this : this.GetBinder(initializerArgumentListOpt); - Debug.Assert(initializerBinder != null); - - var result = initializerBinder.BindConstructorInitializerCore(initializerArgumentListOpt, constructor, diagnostics); + Binder argumentListBinder = null; if (initializerArgumentListOpt != null) { - result = initializerBinder.WrapWithVariablesIfAny(initializerArgumentListOpt, result); + argumentListBinder = this.GetBinder(initializerArgumentListOpt); + } + + var result = (argumentListBinder ?? this).BindConstructorInitializerCore(initializerArgumentListOpt, constructor, diagnostics); + + if (argumentListBinder != null) + { + // This code is reachable only for speculative SemanticModel. + Debug.Assert(argumentListBinder.IsSemanticModelBinder); + result = argumentListBinder.WrapWithVariablesIfAny(initializerArgumentListOpt, result); } return result; @@ -3336,7 +3351,26 @@ private BoundExpression BindConstructorInitializerCore( MethodSymbol constructor, DiagnosticBag diagnostics) { - Debug.Assert(initializerArgumentListOpt == null || this.SkipSemanticModelBinder() == this.GetBinder(initializerArgumentListOpt).SkipSemanticModelBinder()); + // Either our base type is not object, or we have an initializer syntax, or both. We're going to + // need to do overload resolution on the set of constructors of the base type, either on + // the provided initializer syntax, or on an implicit ": base()" syntax. + + // SPEC ERROR: The specification states that if you have the situation + // SPEC ERROR: class B { ... } class D1 : B {} then the default constructor + // SPEC ERROR: generated for D1 must call an accessible *parameterless* constructor + // SPEC ERROR: in B. However, it also states that if you have + // SPEC ERROR: class B { ... } class D2 : B { D2() {} } or + // SPEC ERROR: class B { ... } class D3 : B { D3() : base() {} } then + // SPEC ERROR: the compiler performs *overload resolution* to determine + // SPEC ERROR: which accessible constructor of B is called. Since B might have + // SPEC ERROR: a ctor with all optional parameters, overload resolution might + // SPEC ERROR: succeed even if there is no parameterless constructor. This + // SPEC ERROR: is unintentionally inconsistent, and the native compiler does not + // SPEC ERROR: implement this behavior. Rather, we should say in the spec that + // SPEC ERROR: if there is no ctor in D1, then a ctor is created for you exactly + // SPEC ERROR: as though you'd said "D1() : base() {}". + // SPEC ERROR: This is what we now do in Roslyn. + Debug.Assert((object)constructor != null); Debug.Assert(constructor.MethodKind == MethodKind.Constructor || constructor.MethodKind == MethodKind.StaticConstructor); // error scenario: constructor initializer on static constructor diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Initializers.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Initializers.cs index 73b583d0d7954..6919314e1a887 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Initializers.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Initializers.cs @@ -110,7 +110,7 @@ internal static void BindRegularCSharpFieldInitializers( parentBinder = new LocalScopeBinder(parentBinder).WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.FieldInitializer, fieldSymbol); - BoundFieldInitializer boundInitializer = BindFieldInitializer(parentBinder, fieldSymbol, initializerNode, diagnostics); + BoundFieldEqualsValue boundInitializer = BindFieldInitializer(parentBinder, fieldSymbol, initializerNode, diagnostics); boundInitializers.Add(boundInitializer); } } @@ -246,7 +246,7 @@ private static BoundInitializer BindGlobalStatement( return new BoundGlobalStatementInitializer(statementNode, statement); } - private static BoundFieldInitializer BindFieldInitializer(Binder binder, FieldSymbol fieldSymbol, EqualsValueClauseSyntax equalsValueClauseNode, + private static BoundFieldEqualsValue BindFieldInitializer(Binder binder, FieldSymbol fieldSymbol, EqualsValueClauseSyntax equalsValueClauseNode, DiagnosticBag diagnostics) { Debug.Assert(!fieldSymbol.IsMetadataConstant); @@ -269,17 +269,14 @@ private static BoundFieldInitializer BindFieldInitializer(Binder binder, FieldSy } binder = new ExecutableCodeBinder(equalsValueClauseNode, fieldSymbol, new LocalScopeBinder(binder)); - var boundInitValue = binder.BindVariableOrAutoPropInitializer(equalsValueClauseNode, RefKind.None, fieldSymbol.GetFieldType(fieldsBeingBound), initializerDiagnostics); + BoundFieldEqualsValue boundInitValue = binder.BindFieldInitializer(fieldSymbol, equalsValueClauseNode, initializerDiagnostics); if (isImplicitlyTypedField) { initializerDiagnostics.Free(); } - return new BoundFieldInitializer( - equalsValueClauseNode.Value, //we want the attached sequence point to indicate the value node - fieldSymbol, - boundInitValue); + return boundInitValue; } } } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs index 886f0c0518c71..e313d726aba3b 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs @@ -286,7 +286,7 @@ private BoundPattern BindDeclarationPattern( { if ((InConstructorInitializer || InFieldInitializer) && ContainingMemberOrLambda.ContainingSymbol.Kind == SymbolKind.NamedType) { - Error(diagnostics, ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, node); + CheckFeatureAvailability(node, MessageID.IDS_FeatureExpressionVariablesInQueriesAndInitializers, diagnostics); } localSymbol.SetType(declType); diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs index 569cea3042685..cae6965c02af8 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs @@ -600,7 +600,7 @@ private BoundBlock CreateLambdaBlockForQueryClause(ExpressionSyntax expression, var locals = this.GetDeclaredLocalsForScope(expression); if (locals.Any()) { - diagnostics.Add(ErrorCode.ERR_ExpressionVariableInQueryClause, locals[0].Locations[0]); + CheckFeatureAvailability(expression, MessageID.IDS_FeatureExpressionVariablesInQueriesAndInitializers, diagnostics, locals[0].Locations[0]); } return this.CreateBlockFromExpression(expression, locals, RefKind.None, result, expression, diagnostics); diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs index 90a3934143175..9c542b69859b4 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs @@ -1,5 +1,6 @@ // 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 System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; @@ -520,7 +521,7 @@ private BoundStatement BindLocalFunctionStatement(LocalFunctionStatementSyntax n { if (ImplicitReturnIsOkay(localSymbol)) { - block = FlowAnalysisPass.AppendImplicitReturn(block, localSymbol, node.Body); + block = FlowAnalysisPass.AppendImplicitReturn(block, localSymbol); } else { @@ -2855,7 +2856,7 @@ private static bool IsValidExpressionBody(SyntaxNode expressionSyntax, BoundExpr /// /// Binds an expression-bodied member with expression e as either { return e;} or { e; }. /// - internal BoundBlock BindExpressionBodyAsBlock(ArrowExpressionClauseSyntax expressionBody, + internal virtual BoundBlock BindExpressionBodyAsBlock(ArrowExpressionClauseSyntax expressionBody, DiagnosticBag diagnostics) { Binder bodyBinder = this.GetBinder(expressionBody); @@ -2901,6 +2902,75 @@ private BindValueKind GetRequiredReturnValueKind(RefKind refKind) return requiredValueKind; } + public virtual BoundNode BindMethodBody(CSharpSyntaxNode syntax, DiagnosticBag diagnostics) + { + switch (syntax) + { + case BaseMethodDeclarationSyntax method: + if (method.Kind() == SyntaxKind.ConstructorDeclaration) + { + return BindConstructorBody((ConstructorDeclarationSyntax)method, diagnostics); + } + + return BindMethodBody(method, method.Body, method.ExpressionBody, diagnostics); + + case AccessorDeclarationSyntax accessor: + return BindMethodBody(accessor, accessor.Body, accessor.ExpressionBody, diagnostics); + + case ArrowExpressionClauseSyntax arrowExpression: + return BindExpressionBodyAsBlock(arrowExpression, diagnostics); + + default: + throw ExceptionUtilities.UnexpectedValue(syntax.Kind()); + } + } + + private BoundNode BindConstructorBody(ConstructorDeclarationSyntax constructor, DiagnosticBag diagnostics) + { + if (constructor.Initializer == null && constructor.Body == null && constructor.ExpressionBody == null) + { + return null; + } + + Binder bodyBinder = this.GetBinder(constructor); + Debug.Assert(bodyBinder != null); + + // Using BindStatement to bind block to make sure we are reusing results of partial binding in SemanticModel + return new BoundConstructorMethodBody(constructor, + bodyBinder.GetDeclaredLocalsForScope(constructor), + constructor.Initializer == null ? null : bodyBinder.BindConstructorInitializer(constructor.Initializer, diagnostics), + constructor.Body == null ? null : (BoundBlock)bodyBinder.BindStatement(constructor.Body, diagnostics), + constructor.ExpressionBody == null ? + null : + bodyBinder.BindExpressionBodyAsBlock(constructor.ExpressionBody, + constructor.Body == null ? diagnostics : new DiagnosticBag())); + } + + internal virtual BoundExpressionStatement BindConstructorInitializer(ConstructorInitializerSyntax initializer, DiagnosticBag diagnostics) + { + BoundExpression initializerInvocation = GetBinder(initializer).BindConstructorInitializer(initializer.ArgumentList, (MethodSymbol)this.ContainingMember(), diagnostics); + // Base WasCompilerGenerated state off of whether constructor is implicitly declared, this will ensure proper instrumentation. + Debug.Assert(!this.ContainingMember().IsImplicitlyDeclared); + var constructorInitializer = new BoundExpressionStatement(initializer, initializerInvocation); + Debug.Assert(initializerInvocation.HasAnyErrors || constructorInitializer.IsConstructorInitializer(), "Please keep this bound node in sync with BoundNodeExtensions.IsConstructorInitializer."); + return constructorInitializer; + } + + private BoundNode BindMethodBody(CSharpSyntaxNode declaration, BlockSyntax blockBody, ArrowExpressionClauseSyntax expressionBody, DiagnosticBag diagnostics) + { + if (blockBody == null && expressionBody == null) + { + return null; + } + + // Using BindStatement to bind block to make sure we are reusing results of partial binding in SemanticModel + return new BoundNonConstructorMethodBody(declaration, + blockBody == null ? null : (BoundBlock)BindStatement(blockBody, diagnostics), + expressionBody == null ? + null : + BindExpressionBodyAsBlock(expressionBody, + blockBody == null ? diagnostics : new DiagnosticBag())); + } internal virtual ImmutableArray Locals { diff --git a/src/Compilers/CSharp/Portable/Binder/ExecutableCodeBinder.cs b/src/Compilers/CSharp/Portable/Binder/ExecutableCodeBinder.cs index d3f227eb64a93..d38596fe670c8 100644 --- a/src/Compilers/CSharp/Portable/Binder/ExecutableCodeBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/ExecutableCodeBinder.cs @@ -67,8 +67,9 @@ private void ComputeBinderMap() map = LocalBinderFactory.BuildMap(_memberSymbol, _root, this, methodsWithYield, _binderUpdatedHandler); foreach (var methodWithYield in methodsWithYield) { - Binder binder; - if (map.TryGetValue(methodWithYield, out binder)) + Binder binder = this; + if (methodWithYield.Kind() != SyntaxKind.GlobalStatement && + (methodWithYield == _root || map.TryGetValue(methodWithYield, out binder))) { Symbol containing = binder.ContainingMemberOrLambda; diff --git a/src/Compilers/CSharp/Portable/Binder/ExpressionVariableFinder.cs b/src/Compilers/CSharp/Portable/Binder/ExpressionVariableFinder.cs index f888828b62369..95178715a02fe 100644 --- a/src/Compilers/CSharp/Portable/Binder/ExpressionVariableFinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/ExpressionVariableFinder.cs @@ -42,6 +42,7 @@ protected void FindExpressionVariables( case SyntaxKind.IfStatement: case SyntaxKind.SwitchStatement: case SyntaxKind.VariableDeclarator: + case SyntaxKind.ConstructorDeclaration: break; case SyntaxKind.ArgumentList: Debug.Assert(node.Parent is ConstructorInitializerSyntax); @@ -304,6 +305,14 @@ public override void VisitAssignmentExpression(AssignmentExpressionSyntax node) Visit(node.Right); } + public override void VisitConstructorDeclaration(ConstructorDeclarationSyntax node) + { + if (node.Initializer != null) + { + VisitNodeToBind(node.Initializer); + } + } + private void CollectVariablesFromDeconstruction( ExpressionSyntax possibleTupleDeclaration, AssignmentExpressionSyntax deconstruction) diff --git a/src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs b/src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs index 35fd73042146f..db708e8ded058 100644 --- a/src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs +++ b/src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs @@ -134,32 +134,42 @@ private LocalBinderFactory(Symbol containingMemberOrLambda, SyntaxNode root, Bin public override void VisitMethodDeclaration(MethodDeclarationSyntax node) { - VisitBlock(node.Body); + Visit(node.Body); + Visit(node.ExpressionBody); } public override void VisitConstructorDeclaration(ConstructorDeclarationSyntax node) { - VisitBlock(node.Body); + Binder enclosing = new ExpressionVariableBinder(node, _enclosing); + AddToMap(node, enclosing); + + Visit(node.Initializer, enclosing); + Visit(node.Body, enclosing); + Visit(node.ExpressionBody, enclosing); } public override void VisitDestructorDeclaration(DestructorDeclarationSyntax node) { - VisitBlock(node.Body); + Visit(node.Body); + Visit(node.ExpressionBody); } public override void VisitAccessorDeclaration(AccessorDeclarationSyntax node) { - VisitBlock(node.Body); + Visit(node.Body); + Visit(node.ExpressionBody); } public override void VisitConversionOperatorDeclaration(ConversionOperatorDeclarationSyntax node) { - VisitBlock(node.Body); + Visit(node.Body); + Visit(node.ExpressionBody); } public override void VisitOperatorDeclaration(OperatorDeclarationSyntax node) { - VisitBlock(node.Body); + Visit(node.Body); + Visit(node.ExpressionBody); } public override void VisitSimpleLambdaExpression(SimpleLambdaExpressionSyntax node) @@ -290,23 +300,20 @@ public override void VisitAttribute(AttributeSyntax node) } } - public override void VisitArgumentList(ArgumentListSyntax node) + public override void VisitConstructorInitializer(ConstructorInitializerSyntax node) { - if (_root == node) - { - // We are supposed to get here only for constructor initializers - Debug.Assert(node.Parent is ConstructorInitializerSyntax); - var argBinder = new ExpressionVariableBinder(node, _enclosing); - AddToMap(node, argBinder); + var binder = _enclosing.WithAdditionalFlags(BinderFlags.ConstructorInitializer); + AddToMap(node, binder); - foreach (var arg in node.Arguments) + if (node.ArgumentList != null) + { + if (_root == node) { - Visit(arg.Expression, argBinder); + binder = new ExpressionVariableBinder(node.ArgumentList, binder); + AddToMap(node.ArgumentList, binder); } - } - else - { - base.VisitArgumentList(node); + + Visit(node.ArgumentList, binder); } } diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml index 42f645b9d0753..a6ebac2ee1e69 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml +++ b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml @@ -33,12 +33,8 @@ - - - - - - + + @@ -1673,4 +1669,20 @@ + + + + + + + + + + + + + + + + diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index d50e17632e602..d1f39b32994aa 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -4489,24 +4489,6 @@ internal static string ERR_ExpressionTreeMustHaveDelegate { } } - /// - /// Looks up a localized string similar to Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers.. - /// - internal static string ERR_ExpressionVariableInConstructorOrFieldInitializer { - get { - return ResourceManager.GetString("ERR_ExpressionVariableInConstructorOrFieldInitializer", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Out variable and pattern variable declarations are not allowed within a query clause.. - /// - internal static string ERR_ExpressionVariableInQueryClause { - get { - return ResourceManager.GetString("ERR_ExpressionVariableInQueryClause", resourceCulture); - } - } - /// /// Looks up a localized string similar to Cannot define a new extension method because the compiler required type '{0}' cannot be found. Are you missing a reference to System.Core.dll?. /// @@ -10574,6 +10556,15 @@ internal static string IDS_FeatureExpressionBodiedProperty { } } + /// + /// Looks up a localized string similar to declaration of expression variables in member initializers and queries. + /// + internal static string IDS_FeatureExpressionVariablesInQueriesAndInitializers { + get { + return ResourceManager.GetString("IDS_FeatureExpressionVariablesInQueriesAndInitializers", resourceCulture); + } + } + /// /// Looks up a localized string similar to extension method. /// diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 5c0df8816e711..f56fca4799862 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -5096,12 +5096,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ The syntax 'var (...)' as an lvalue is reserved. - - Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - - - Out variable and pattern variable declarations are not allowed within a query clause. - { or ; or => expected @@ -5318,4 +5312,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ "Invalid rank specifier: expected ']' + + declaration of expression variables in member initializers and queries + diff --git a/src/Compilers/CSharp/Portable/CodeGen/CodeGenerator.cs b/src/Compilers/CSharp/Portable/CodeGen/CodeGenerator.cs index b41c27c372933..80ecabaf4f9ac 100644 --- a/src/Compilers/CSharp/Portable/CodeGen/CodeGenerator.cs +++ b/src/Compilers/CSharp/Portable/CodeGen/CodeGenerator.cs @@ -129,7 +129,9 @@ public CodeGenerator( _boundBody = boundBody; } - _methodBodySyntaxOpt = (method as SourceMemberMethodSymbol)?.BodySyntax; + var sourceMethod = method as SourceMemberMethodSymbol; + (BlockSyntax blockBody, ArrowExpressionClauseSyntax expressionBody) = sourceMethod?.Bodies ?? default; + _methodBodySyntaxOpt = (SyntaxNode)blockBody ?? expressionBody ?? sourceMethod?.SyntaxNode; } private bool IsDebugPlus() diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs index 24f3baba16a7c..0785b20b573cc 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs @@ -774,18 +774,14 @@ public SymbolInfo GetSpeculativeSymbolInfo(int position, ConstructorInitializerS return SymbolInfo.None; } - var binder = this.GetEnclosingBinder(position); + var binder = memberModel.GetEnclosingBinder(position); if (binder != null) { var diagnostics = DiagnosticBag.GetInstance(); + binder = new ExecutableCodeBinder(constructorInitializer, binder.ContainingMemberOrLambda, binder); - if (constructorInitializer.ArgumentList != null) - { - binder = new ExecutableCodeBinder(constructorInitializer.ArgumentList, binder.ContainingMemberOrLambda, binder); - } - - var bnode = memberModel.Bind(binder, constructorInitializer, diagnostics); - var binfo = memberModel.GetSymbolInfoForNode(SymbolInfoOptions.DefaultOptions, bnode, bnode, boundNodeForSyntacticParent: null, binderOpt: binder); + BoundExpressionStatement bnode = binder.BindConstructorInitializer(constructorInitializer, diagnostics); + var binfo = memberModel.GetSymbolInfoForNode(SymbolInfoOptions.DefaultOptions, bnode.Expression, bnode.Expression, boundNodeForSyntacticParent: null, binderOpt: binder); diagnostics.Free(); return binfo; } diff --git a/src/Compilers/CSharp/Portable/Compilation/InitializerSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/InitializerSemanticModel.cs index 0047859ce91ca..e19182e794531 100644 --- a/src/Compilers/CSharp/Portable/Compilation/InitializerSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/InitializerSemanticModel.cs @@ -18,8 +18,7 @@ internal sealed class InitializerSemanticModel : MemberSemanticModel { // create a SemanticModel for: // (a) A true field initializer (field = value) of a named type (incl. Enums) OR - // (b) A constructor initializer (": this(...)" or ": base(...)") OR - // (c) A parameter default value + // (b) A parameter default value private InitializerSemanticModel(CSharpCompilation compilation, CSharpSyntaxNode syntax, Symbol symbol, @@ -28,6 +27,7 @@ private InitializerSemanticModel(CSharpCompilation compilation, int speculatedPosition = 0) : base(compilation, syntax, symbol, rootBinder, parentSemanticModelOpt, speculatedPosition) { + Debug.Assert(!(syntax is ConstructorInitializerSyntax)); } /// @@ -48,22 +48,6 @@ internal static InitializerSemanticModel Create(CSharpCompilation compilation, C return new InitializerSemanticModel(compilation, syntax, propertySymbol, rootBinder); } - /// - /// Creates a SemanticModel for a constructor initializer (": this(...)" or ": base(...)"). - /// - internal static InitializerSemanticModel Create(CSharpCompilation compilation, ConstructorInitializerSyntax syntax, MethodSymbol methodSymbol, Binder rootBinder) - { - return new InitializerSemanticModel(compilation, syntax, methodSymbol, rootBinder); - } - - /// - /// Creates a SemanticModel for a constructor initializer (": base-class(...)"). - /// - internal static InitializerSemanticModel Create(CSharpCompilation compilation, ArgumentListSyntax syntax, MethodSymbol methodSymbol, Binder rootBinder) - { - return new InitializerSemanticModel(compilation, syntax, methodSymbol, rootBinder); - } - /// /// Creates a SemanticModel for a parameter default value. /// @@ -80,10 +64,7 @@ internal static InitializerSemanticModel CreateSpeculative(SyntaxTreeSemanticMod { Debug.Assert(parentSemanticModel != null); Debug.Assert(syntax != null); - Debug.Assert(syntax.IsKind(SyntaxKind.EqualsValueClause) || - syntax.IsKind(SyntaxKind.ThisConstructorInitializer) || - syntax.IsKind(SyntaxKind.BaseConstructorInitializer) || - syntax.IsKind(SyntaxKind.ArgumentList)); + Debug.Assert(syntax.IsKind(SyntaxKind.EqualsValueClause)); Debug.Assert(rootBinder != null); Debug.Assert(rootBinder.IsSemanticModelBinder); @@ -158,13 +139,6 @@ internal override BoundNode Bind(Binder binder, CSharpSyntaxNode node, Diagnosti case SyntaxKind.EnumMemberDeclaration: equalsValue = ((EnumMemberDeclarationSyntax)node).EqualsValue; break; - - case SyntaxKind.BaseConstructorInitializer: - case SyntaxKind.ThisConstructorInitializer: - return binder.BindConstructorInitializer(((ConstructorInitializerSyntax)node).ArgumentList, (MethodSymbol)MemberSymbol, diagnostics); - - case SyntaxKind.ArgumentList: - return binder.BindConstructorInitializer((ArgumentListSyntax)node, (MethodSymbol)MemberSymbol, diagnostics); } if (equalsValue != null) @@ -183,54 +157,36 @@ private BoundEqualsValue BindEqualsValue(Binder binder, EqualsValueClauseSyntax { var field = (FieldSymbol)this.MemberSymbol; var enumField = field as SourceEnumConstantSymbol; - BoundExpression result; if ((object)enumField != null) { - result = binder.BindEnumConstantInitializer(enumField, equalsValue, diagnostics); + return binder.BindEnumConstantInitializer(enumField, equalsValue, diagnostics); } else { - result = binder.BindVariableOrAutoPropInitializer(equalsValue, RefKind.None, field.GetFieldType(binder.FieldsBeingBound), diagnostics); + return binder.BindFieldInitializer(field, equalsValue, diagnostics); } - if (result != null) - { - return new BoundFieldEqualsValue(equalsValue, field, result); - } - break; } case SymbolKind.Property: { - var property = (PropertySymbol)this.MemberSymbol; - BoundExpression result = binder.BindVariableOrAutoPropInitializer(equalsValue, RefKind.None, property.Type, diagnostics); - if (result != null) - { - return new BoundPropertyEqualsValue(equalsValue, property, result); - } - break; + var property = (SourcePropertySymbol)this.MemberSymbol; + BoundFieldEqualsValue result = binder.BindFieldInitializer(property.BackingField, equalsValue, diagnostics); + return new BoundPropertyEqualsValue(result.Syntax, property, result.Locals, result.Value); } case SymbolKind.Parameter: { - BoundExpression unusedValueBeforeConversion; // not needed. var parameter = (ParameterSymbol)this.MemberSymbol; - BoundExpression result = binder.BindParameterDefaultValue( + return binder.BindParameterDefaultValue( equalsValue, - parameter.Type, + parameter, diagnostics, - out unusedValueBeforeConversion); - if (result != null) - { - return new BoundParameterEqualsValue(equalsValue, parameter, result); - } - break; + out _); } default: throw ExceptionUtilities.UnexpectedValue(this.MemberSymbol.Kind); } - - return null; } private bool IsBindableInitializer(CSharpSyntaxNode node) @@ -257,18 +213,6 @@ private bool IsBindableInitializer(CSharpSyntaxNode node) internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, EqualsValueClauseSyntax initializer, out SemanticModel speculativeModel) { - return TryGetSpeculativeSemanticModelCore(parentModel, position, initializer, out speculativeModel); - } - - internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ConstructorInitializerSyntax constructorInitializer, out SemanticModel speculativeModel) - { - return TryGetSpeculativeSemanticModelCore(parentModel, position, constructorInitializer, out speculativeModel); - } - - private bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, CSharpSyntaxNode initializer, out SemanticModel speculativeModel) - { - Debug.Assert(initializer is EqualsValueClauseSyntax || initializer is ConstructorInitializerSyntax); - var binder = this.GetEnclosingBinder(position); if (binder == null) { @@ -276,26 +220,17 @@ private bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentMo return false; } - switch (initializer.Kind()) - { - case SyntaxKind.EqualsValueClause: - binder = new ExecutableCodeBinder(initializer, binder.ContainingMemberOrLambda, binder); - break; - - case SyntaxKind.ThisConstructorInitializer: - case SyntaxKind.BaseConstructorInitializer: - ArgumentListSyntax argList = ((ConstructorInitializerSyntax)initializer).ArgumentList; - if (argList != null) - { - binder = new ExecutableCodeBinder(argList, binder.ContainingMemberOrLambda, binder); - } - break; - } - + binder = new ExecutableCodeBinder(initializer, binder.ContainingMemberOrLambda, binder); speculativeModel = CreateSpeculative(parentModel, this.MemberSymbol, initializer, binder, position); return true; } + internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ConstructorInitializerSyntax constructorInitializer, out SemanticModel speculativeModel) + { + speculativeModel = null; + return false; + } + internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ArrowExpressionClauseSyntax expressionBody, out SemanticModel speculativeModel) { speculativeModel = null; diff --git a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs index aa8c49b2da1d6..5e8aaf56d35fe 100644 --- a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs @@ -242,6 +242,14 @@ private static Binder GetEnclosingBinderInternalWithinRoot(SyntaxNode node, int { binder = rootBinder.GetBinder(current); } + else if (kind == SyntaxKind.ThisConstructorInitializer || kind == SyntaxKind.BaseConstructorInitializer) + { + binder = rootBinder.GetBinder(current); + } + else if (kind == SyntaxKind.ConstructorDeclaration) + { + binder = rootBinder.GetBinder(current); + } else if ((current as ExpressionSyntax).IsValidScopeDesignator()) { binder = rootBinder.GetBinder(current); @@ -1291,6 +1299,15 @@ private ImmutableArray GuardedGetBoundNodesFromMap(CSharpSyntaxNode n return _guardedNodeMap.TryGetValue(node, out result) ? result : default(ImmutableArray); } + /// + /// Internal for test purposes only + /// + internal ImmutableArray TestOnlyTryGetBoundNodesFromMap(CSharpSyntaxNode node) + { + ImmutableArray result; + return _guardedNodeMap.TryGetValue(node, out result) ? result : default(ImmutableArray); + } + // Adds every syntax/bound pair in a tree rooted at the given bound node to the map, and the // performs a lookup of the given syntax node in the map. private ImmutableArray GuardedAddBoundTreeAndGetBoundNodeFromMap(CSharpSyntaxNode syntax, BoundNode bound) @@ -1315,7 +1332,7 @@ private ImmutableArray GuardedAddBoundTreeAndGetBoundNodeFromMap(CSha return _guardedNodeMap.TryGetValue(syntax, out result) ? result : default(ImmutableArray); } - internal void UnguardedAddBoundTreeForStandaloneSyntax(SyntaxNode syntax, BoundNode bound) + protected void UnguardedAddBoundTreeForStandaloneSyntax(SyntaxNode syntax, BoundNode bound) { using (_nodeMapLock.DisposableWrite()) { @@ -1374,6 +1391,14 @@ private CSharpSyntaxNode GetBindingRoot(CSharpSyntaxNode node) { return current; } + + switch (current.Kind()) + { + case SyntaxKind.ThisConstructorInitializer: + case SyntaxKind.BaseConstructorInitializer: + case SyntaxKind.ArrowExpressionClause: + return current; + } } return this.Root; @@ -1807,13 +1832,11 @@ internal protected virtual CSharpSyntaxNode GetBindableSyntaxNode(CSharpSyntaxNo case SyntaxKind.SetAccessorDeclaration: case SyntaxKind.AddAccessorDeclaration: case SyntaxKind.RemoveAccessorDeclaration: - return ((AccessorDeclarationSyntax)node).Body; case SyntaxKind.MethodDeclaration: case SyntaxKind.ConstructorDeclaration: case SyntaxKind.DestructorDeclaration: case SyntaxKind.OperatorDeclaration: case SyntaxKind.ConversionOperatorDeclaration: - return ((BaseMethodDeclarationSyntax)node).Body; case SyntaxKind.GlobalStatement: return node; } @@ -1877,6 +1900,7 @@ internal protected virtual CSharpSyntaxNode GetBindableSyntaxNode(CSharpSyntaxNo !(node is OrderingSyntax) && !(node is JoinIntoClauseSyntax) && !(node is QueryContinuationSyntax) && + !(node is ConstructorInitializerSyntax) && !(node is ArrowExpressionClauseSyntax)) { return GetBindableSyntaxNode(parent); @@ -2007,9 +2031,9 @@ public override BoundStatement BindStatement(StatementSyntax node, DiagnosticBag return synthesizedStatement; } - ImmutableArray boundNodes = _semanticModel.GuardedGetBoundNodesFromMap(node); + BoundNode boundNode = TryGetBoundNodeFromMap(node); - if (boundNodes.IsDefaultOrEmpty) + if (boundNode == null) { // Not bound already. Bind it. It will get added to the cache later by a MemberSemanticModel.NodeMapBuilder. var statement = base.BindStatement(node, diagnostics); @@ -2023,11 +2047,36 @@ public override BoundStatement BindStatement(StatementSyntax node, DiagnosticBag return statement; } - else + + return (BoundStatement)boundNode; + } + + private BoundNode TryGetBoundNodeFromMap(CSharpSyntaxNode node) + { + ImmutableArray boundNodes = _semanticModel.GuardedGetBoundNodesFromMap(node); + + if (!boundNodes.IsDefaultOrEmpty) { // Already bound. Return the top-most bound node associated with the statement. - return (BoundStatement)boundNodes[0]; + return boundNodes[0]; } + + return null; + } + + public override BoundNode BindMethodBody(CSharpSyntaxNode node, DiagnosticBag diagnostics) + { + return TryGetBoundNodeFromMap(node) ?? base.BindMethodBody(node, diagnostics); + } + + internal override BoundExpressionStatement BindConstructorInitializer(ConstructorInitializerSyntax node, DiagnosticBag diagnostics) + { + return (BoundExpressionStatement)TryGetBoundNodeFromMap(node) ?? base.BindConstructorInitializer(node, diagnostics); + } + + internal override BoundBlock BindExpressionBodyAsBlock(ArrowExpressionClauseSyntax node, DiagnosticBag diagnostics) + { + return (BoundBlock)TryGetBoundNodeFromMap(node) ?? base.BindExpressionBodyAsBlock(node, diagnostics); } } } diff --git a/src/Compilers/CSharp/Portable/Compilation/MethodBodySemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/MethodBodySemanticModel.cs index 4c839ecbbe228..60e5ee6770a62 100644 --- a/src/Compilers/CSharp/Portable/Compilation/MethodBodySemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/MethodBodySemanticModel.cs @@ -19,32 +19,45 @@ private MethodBodySemanticModel(CSharpCompilation compilation, Symbol owner, Bin } /// - /// Creates a SemanticModel that creates and owns the ExecutableCodeBinder for the method of which it is a model. + /// Creates a SemanticModel for the method. /// - internal static MethodBodySemanticModel Create(CSharpCompilation compilation, MethodSymbol owner, Binder rootBinder, CSharpSyntaxNode syntax) + internal static MethodBodySemanticModel Create(CSharpCompilation compilation, MethodSymbol owner, ExecutableCodeBinder executableCodeBinder, + CSharpSyntaxNode syntax, BoundNode boundNode = null) { - var executableCodeBinder = new ExecutableCodeBinder(syntax, owner, rootBinder); - return new MethodBodySemanticModel(compilation, owner, executableCodeBinder, syntax); - } + var result = new MethodBodySemanticModel(compilation, owner, executableCodeBinder, syntax); - internal override BoundNode Bind(Binder binder, CSharpSyntaxNode node, DiagnosticBag diagnostics) - { - if (node.Kind() == SyntaxKind.ArrowExpressionClause) + if (boundNode != null) { - return binder.BindExpressionBodyAsBlock((ArrowExpressionClauseSyntax)node, diagnostics); + result.UnguardedAddBoundTreeForStandaloneSyntax(syntax, boundNode); } - return base.Bind(binder, node, diagnostics); + + return result; } - internal override BoundNode GetBoundRoot() + internal override BoundNode Bind(Binder binder, CSharpSyntaxNode node, DiagnosticBag diagnostics) { - CSharpSyntaxNode root = this.Root; - if (root.Kind() == SyntaxKind.ArrowExpressionClause) + switch (node.Kind()) { - root = ((ArrowExpressionClauseSyntax)root).Expression; - return GetUpperBoundNode(GetBindableSyntaxNode(root)); + case SyntaxKind.ArrowExpressionClause: + return binder.BindExpressionBodyAsBlock((ArrowExpressionClauseSyntax)node, diagnostics); + + case SyntaxKind.BaseConstructorInitializer: + case SyntaxKind.ThisConstructorInitializer: + return binder.BindConstructorInitializer((ConstructorInitializerSyntax)node, diagnostics); + + case SyntaxKind.MethodDeclaration: + case SyntaxKind.ConversionOperatorDeclaration: + case SyntaxKind.OperatorDeclaration: + case SyntaxKind.ConstructorDeclaration: + case SyntaxKind.DestructorDeclaration: + case SyntaxKind.GetAccessorDeclaration: + case SyntaxKind.SetAccessorDeclaration: + case SyntaxKind.AddAccessorDeclaration: + case SyntaxKind.RemoveAccessorDeclaration: + return binder.BindMethodBody(node, diagnostics); } - return base.GetBoundRoot(); + + return base.Bind(binder, node, diagnostics); } /// @@ -73,6 +86,19 @@ internal static MethodBodySemanticModel CreateSpeculative(SyntaxTreeSemanticMode return new MethodBodySemanticModel(parentSemanticModel.Compilation, owner, rootBinder, syntax, parentSemanticModel, position); } + /// + /// Creates a speculative SemanticModel for a constructor initializer that did not appear in the original source code. + /// + internal static MethodBodySemanticModel CreateSpeculative(SyntaxTreeSemanticModel parentSemanticModel, MethodSymbol owner, ConstructorInitializerSyntax syntax, Binder rootBinder, int position) + { + Debug.Assert(parentSemanticModel != null); + Debug.Assert(syntax != null); + Debug.Assert(rootBinder != null); + Debug.Assert(rootBinder.IsSemanticModelBinder); + + return new MethodBodySemanticModel(parentSemanticModel.Compilation, owner, rootBinder, syntax, parentSemanticModel, position); + } + internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, BaseMethodDeclarationSyntax method, out SemanticModel speculativeModel) { // CONSIDER: Do we want to ensure that speculated method and the original method have identical signatures? @@ -150,6 +176,18 @@ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticMode internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ConstructorInitializerSyntax constructorInitializer, out SemanticModel speculativeModel) { + if ((MemberSymbol as MethodSymbol)?.MethodKind == MethodKind.Constructor) + { + var binder = this.GetEnclosingBinder(position); + if (binder != null) + { + var methodSymbol = (MethodSymbol)this.MemberSymbol; + binder = new ExecutableCodeBinder(constructorInitializer, methodSymbol, binder); + speculativeModel = CreateSpeculative(parentModel, methodSymbol, constructorInitializer, binder, position); + return true; + } + } + speculativeModel = null; return false; } diff --git a/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs index dc8d4cbb16aa5..0b32947a42722 100644 --- a/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs @@ -163,7 +163,24 @@ internal override Binder GetEnclosingBinderInternal(int position) internal override IOperation GetOperationWorker(CSharpSyntaxNode node, CancellationToken cancellationToken) { - var model = this.GetMemberModel(node); + MemberSemanticModel model; + + switch (node) + { + case ConstructorDeclarationSyntax constructor: + model = (constructor.HasAnyBody() || constructor.Initializer != null) ? GetOrAddModel(node) : null; + break; + case BaseMethodDeclarationSyntax method: + model = method.HasAnyBody() ? GetOrAddModel(node) : null; + break; + case AccessorDeclarationSyntax accessor: + model = (accessor.Body != null || accessor.ExpressionBody != null) ? GetOrAddModel(node) : null; + break; + default: + model = this.GetMemberModel(node); + break; + } + if (model != null) { return model.GetOperationWorker(node, cancellationToken); @@ -760,25 +777,37 @@ internal override MemberSemanticModel GetMemberModel(SyntaxNode node) { var methodDecl = (BaseMethodDeclarationSyntax)memberDecl; var expressionBody = methodDecl.GetExpressionBodySyntax(); - return GetOrAddModelIfContains(expressionBody, span) ?? - GetOrAddModelIfContains(methodDecl.Body, span); + return (expressionBody?.FullSpan.Contains(span) == true || methodDecl.Body?.FullSpan.Contains(span) == true) ? + GetOrAddModel(methodDecl) : null; } case SyntaxKind.ConstructorDeclaration: { ConstructorDeclarationSyntax constructorDecl = (ConstructorDeclarationSyntax)memberDecl; var expressionBody = constructorDecl.GetExpressionBodySyntax(); - return GetOrAddModelIfContains(constructorDecl.Initializer, span) ?? - GetOrAddModelIfContains(expressionBody, span) ?? - GetOrAddModelIfContains(constructorDecl.Body, span); + return (constructorDecl.Initializer?.FullSpan.Contains(span) == true || + expressionBody?.FullSpan.Contains(span) == true || + constructorDecl.Body?.FullSpan.Contains(span) == true) ? + GetOrAddModel(constructorDecl) : null; } case SyntaxKind.DestructorDeclaration: { DestructorDeclarationSyntax destructorDecl = (DestructorDeclarationSyntax)memberDecl; var expressionBody = destructorDecl.GetExpressionBodySyntax(); - return GetOrAddModelIfContains(expressionBody, span) ?? - GetOrAddModelIfContains(destructorDecl.Body, span); + return (expressionBody?.FullSpan.Contains(span) == true || destructorDecl.Body?.FullSpan.Contains(span) == true) ? + GetOrAddModel(destructorDecl) : null; + } + + case SyntaxKind.GetAccessorDeclaration: + case SyntaxKind.SetAccessorDeclaration: + case SyntaxKind.AddAccessorDeclaration: + case SyntaxKind.RemoveAccessorDeclaration: + // NOTE: not UnknownAccessorDeclaration since there's no corresponding method symbol from which to build a member model. + { + var accessorDecl = (AccessorDeclarationSyntax)memberDecl; + return (accessorDecl.ExpressionBody?.FullSpan.Contains(span) == true || accessorDecl.Body?.FullSpan.Contains(span) == true) ? + GetOrAddModel(accessorDecl) : null; } case SyntaxKind.IndexerDeclaration: @@ -817,14 +846,6 @@ internal override MemberSemanticModel GetMemberModel(SyntaxNode node) GetOrAddModelIfContains(propertyDecl.ExpressionBody, span); } - case SyntaxKind.GetAccessorDeclaration: - case SyntaxKind.SetAccessorDeclaration: - case SyntaxKind.AddAccessorDeclaration: - case SyntaxKind.RemoveAccessorDeclaration: - // NOTE: not UnknownAccessorDeclaration since there's no corresponding method symbol from which to build a member model. - return GetOrAddModelIfContains(((AccessorDeclarationSyntax)memberDecl).ExpressionBody, span) ?? - GetOrAddModelIfContains(((AccessorDeclarationSyntax)memberDecl).Body, span); - case SyntaxKind.GlobalStatement: return GetOrAddModel(memberDecl); @@ -839,6 +860,11 @@ internal override MemberSemanticModel GetMemberModel(SyntaxNode node) return null; } + /// + /// Internal for test purposes only + /// + internal ImmutableDictionary TestOnlyMemberModels => _memberModels; + private MemberSemanticModel GetOrAddModelForAttribute(AttributeSyntax attribute) { MemberSemanticModel containing = attribute.Parent != null ? GetMemberModel(attribute.Parent) : null; @@ -923,6 +949,11 @@ private MemberSemanticModel GetOrAddModel(CSharpSyntaxNode node) var createMemberModelFunction = _createMemberModelFunction ?? (_createMemberModelFunction = this.CreateMemberModel); + return GetOrAddModel(node, createMemberModelFunction); + } + + internal MemberSemanticModel GetOrAddModel(CSharpSyntaxNode node, Func createMemberModelFunction) + { return ImmutableInterlocked.GetOrAdd(ref _memberModels, node, createMemberModelFunction); } @@ -931,41 +962,55 @@ private MemberSemanticModel GetOrAddModel(CSharpSyntaxNode node) // (although we try to minimize such cases). In such cases, null is returned. private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node) { - var outer = _binderFactory.GetBinder(node); - + BinderFlags additionalFlags = BinderFlags.None; if (this.IgnoresAccessibility) { - outer = outer.WithAdditionalFlags(BinderFlags.IgnoreAccessibility); + additionalFlags = BinderFlags.IgnoreAccessibility; } + + Binder defaultOuter() => _binderFactory.GetBinder(node).WithAdditionalFlags(additionalFlags); switch (node.Kind()) { - case SyntaxKind.Block: - - MemberDeclarationSyntax memberDecl; - AccessorDeclarationSyntax accessorDecl; - if ((memberDecl = node.Parent as MemberDeclarationSyntax) != null) + case SyntaxKind.MethodDeclaration: + case SyntaxKind.ConversionOperatorDeclaration: + case SyntaxKind.OperatorDeclaration: + case SyntaxKind.ConstructorDeclaration: + case SyntaxKind.DestructorDeclaration: { + var memberDecl = (MemberDeclarationSyntax)node; var symbol = (SourceMemberMethodSymbol)GetDeclaredSymbol(memberDecl); - if ((object)symbol == null) + ExecutableCodeBinder binder = symbol?.TryGetBodyBinder(_binderFactory, additionalFlags); + + if (binder == null) + { return null; + } - return MethodBodySemanticModel.Create(this.Compilation, symbol, outer, memberDecl); + return MethodBodySemanticModel.Create(this.Compilation, symbol, binder, memberDecl); } - else if ((accessorDecl = node.Parent as AccessorDeclarationSyntax) != null) + case SyntaxKind.GetAccessorDeclaration: + case SyntaxKind.SetAccessorDeclaration: + case SyntaxKind.AddAccessorDeclaration: + case SyntaxKind.RemoveAccessorDeclaration: { + var accessorDecl = (AccessorDeclarationSyntax)node; var symbol = (SourceMemberMethodSymbol)GetDeclaredSymbol(accessorDecl); - if ((object)symbol == null) + ExecutableCodeBinder binder = symbol?.TryGetBodyBinder(_binderFactory, additionalFlags); + + if (binder == null) + { return null; + } - return MethodBodySemanticModel.Create(this.Compilation, symbol, outer, accessorDecl); - } - else - { - Debug.Assert(false, "Unexpected node: " + node.Parent); - return null; + return MethodBodySemanticModel.Create(this.Compilation, symbol, binder, accessorDecl); } + case SyntaxKind.Block: + // Don't throw, just use for the assert + ExceptionUtilities.UnexpectedValue(node.Parent); + break; + case SyntaxKind.EqualsValueClause: switch (node.Parent.Kind()) { @@ -979,7 +1024,7 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node) variableDecl, //pass in the entire field initializer to permit region analysis. fieldSymbol, //if we're in regular C#, then insert an extra binder to perform field initialization checks - GetFieldOrPropertyInitializerBinder(fieldSymbol, outer, variableDecl.Initializer)); + GetFieldOrPropertyInitializerBinder(fieldSymbol, defaultOuter(), variableDecl.Initializer)); } case SyntaxKind.PropertyDeclaration: @@ -990,7 +1035,7 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node) this.Compilation, propertyDecl, propertySymbol, - GetFieldOrPropertyInitializerBinder(propertySymbol.BackingField, outer, propertyDecl.Initializer)); + GetFieldOrPropertyInitializerBinder(propertySymbol.BackingField, defaultOuter(), propertyDecl.Initializer)); } case SyntaxKind.Parameter: @@ -1007,7 +1052,7 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node) this.Compilation, parameterDecl, parameterSymbol, - outer.CreateBinderForParameterDefaultValue(parameterSymbol, (EqualsValueClauseSyntax)node)); + defaultOuter().CreateBinderForParameterDefaultValue(parameterSymbol, (EqualsValueClauseSyntax)node)); } case SyntaxKind.EnumMemberDeclaration: @@ -1021,7 +1066,7 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node) this.Compilation, enumDecl, enumSymbol, - GetFieldOrPropertyInitializerBinder(enumSymbol, outer, enumDecl.EqualsValue)); + GetFieldOrPropertyInitializerBinder(enumSymbol, defaultOuter(), enumDecl.EqualsValue)); } default: throw ExceptionUtilities.UnexpectedValue(node.Parent.Kind()); @@ -1030,8 +1075,6 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node) case SyntaxKind.ArrowExpressionClause: { SourceMemberMethodSymbol symbol = null; - MemberDeclarationSyntax memberSyntax; - AccessorDeclarationSyntax accessorSyntax; var exprDecl = (ArrowExpressionClauseSyntax)node; @@ -1039,24 +1082,20 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node) { symbol = (SourceMemberMethodSymbol)GetDeclaredSymbol(exprDecl); } - else if ((memberSyntax = node.Parent as MemberDeclarationSyntax) != null) - { - symbol = (SourceMemberMethodSymbol)GetDeclaredSymbol(memberSyntax); - } - else if ((accessorSyntax = node.Parent as AccessorDeclarationSyntax) != null) - { - symbol = (SourceMemberMethodSymbol)GetDeclaredSymbol(accessorSyntax); - } else { // Don't throw, just use for the assert ExceptionUtilities.UnexpectedValue(node.Parent); } - if ((object)symbol == null) + ExecutableCodeBinder binder = symbol?.TryGetBodyBinder(_binderFactory, additionalFlags); + + if (binder == null) + { return null; - return MethodBodySemanticModel.Create( - _compilation, symbol, outer.WithContainingMemberOrLambda(symbol), exprDecl); + } + + return MethodBodySemanticModel.Create(_compilation, symbol, binder, exprDecl); } case SyntaxKind.GlobalStatement: @@ -1083,39 +1122,14 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node) return MethodBodySemanticModel.Create( this.Compilation, scriptInitializer, - new ScriptLocalScopeBinder(_globalStatementLabels, outer), + new ExecutableCodeBinder(node, scriptInitializer, new ScriptLocalScopeBinder(_globalStatementLabels, defaultOuter())), node); } } break; - case SyntaxKind.BaseConstructorInitializer: - case SyntaxKind.ThisConstructorInitializer: - { - var constructorDecl = (ConstructorDeclarationSyntax)node.Parent; - var constructorSymbol = (SourceMemberMethodSymbol)GetDeclaredSymbol(constructorDecl); - if ((object)constructorSymbol == null) - return null; - - // insert an extra binder to perform constructor initialization checks - // Handle scoping for possible pattern variables declared in the initializer - Binder initializerBinder = outer.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.ConstructorInitializer, constructorSymbol); - ArgumentListSyntax argumentList = ((ConstructorInitializerSyntax)node).ArgumentList; - - if (argumentList != null) - { - initializerBinder = new ExecutableCodeBinder(argumentList, constructorSymbol, initializerBinder); - } - - return InitializerSemanticModel.Create( - this.Compilation, - (ConstructorInitializerSyntax)node, - constructorSymbol, - initializerBinder); - } - case SyntaxKind.Attribute: - return CreateModelForAttribute(outer, (AttributeSyntax)node); + return CreateModelForAttribute(defaultOuter(), (AttributeSyntax)node); } return null; diff --git a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs index 898d0d7e41b9b..bc35982a12cb6 100644 --- a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs +++ b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs @@ -565,7 +565,7 @@ private void CompileNamedType(NamedTypeSymbol containingType) if (_moduleBeingBuiltOpt != null && !hasStaticConstructor && !processedStaticInitializers.BoundInitializers.IsDefaultOrEmpty) { Debug.Assert(processedStaticInitializers.BoundInitializers.All((init) => - (init.Kind == BoundKind.FieldInitializer) && !((BoundFieldInitializer)init).Field.IsMetadataConstant)); + (init.Kind == BoundKind.FieldEqualsValue) && !((BoundFieldEqualsValue)init).Field.IsMetadataConstant)); MethodSymbol method = new SynthesizedStaticConstructor(sourceTypeSymbol); if (PassesFilter(_filterOpt, method)) @@ -910,16 +910,19 @@ private void CompileMethod( // initializers that have been analyzed but not yet lowered. BoundStatementList analyzedInitializers = null; - + (SyntaxNode Syntax, BoundNode Body, ExecutableCodeBinder Binder) forSemanticModel = default; ImportChain importChain = null; var hasTrailingExpression = false; if (methodSymbol.IsScriptConstructor) { + Debug.Assert(methodSymbol.IsImplicitlyDeclared); body = new BoundBlock(methodSymbol.GetNonNullSyntaxNode(), ImmutableArray.Empty, ImmutableArray.Empty) { WasCompilerGenerated = true }; } else if (methodSymbol.IsScriptInitializer) { + Debug.Assert(methodSymbol.IsImplicitlyDeclared); + // rewrite top-level statements and script variable declarations to a list of statements and assignments, respectively: var initializerStatements = InitializerRewriter.RewriteScriptInitializer(processedInitializers.BoundInitializers, (SynthesizedInteractiveInitializerMethod)methodSymbol, out hasTrailingExpression); @@ -937,7 +940,7 @@ private void CompileMethod( includeInitializersInBody = !processedInitializers.BoundInitializers.IsDefaultOrEmpty && !HasThisConstructorInitializer(methodSymbol); - body = BindMethodBody(methodSymbol, compilationState, diagsForCurrentMethod, out importChain, out originalBodyNested); + body = BindMethodBody(methodSymbol, compilationState, diagsForCurrentMethod, out importChain, out originalBodyNested, out forSemanticModel); // lower initializers just once. the lowered tree will be reused when emitting all constructors // with field initializers. Once lowered, these initializers will be stashed in processedInitializers.LoweredInitializers @@ -1018,17 +1021,32 @@ private void CompileMethod( if (diagsWritten && !methodSymbol.IsImplicitlyDeclared && _compilation.EventQueue != null) { - var lazySemanticModel = body == null ? null : new Lazy(() => + Lazy lazySemanticModel = null; + + if (body != null) { - var syntax = body.Syntax; - var semanticModel = (CSharpSemanticModel)_compilation.GetSemanticModel(syntax.SyntaxTree); - var memberModel = semanticModel.GetMemberModel(syntax); - if (memberModel != null) + (SyntaxNode Syntax, BoundNode Body, ExecutableCodeBinder Binder) forSemanticModelToUseInLambda = forSemanticModel; + + lazySemanticModel = new Lazy(() => { - memberModel.UnguardedAddBoundTreeForStandaloneSyntax(syntax, body); - } - return semanticModel; - }); + var syntax = body.Syntax; + var semanticModel = (SyntaxTreeSemanticModel)_compilation.GetSemanticModel(syntax.SyntaxTree); + + if (forSemanticModelToUseInLambda.Syntax != null) + { + semanticModel.GetOrAddModel((CSharpSyntaxNode)forSemanticModelToUseInLambda.Syntax, + (rootSyntax) => + { + Debug.Assert(rootSyntax == forSemanticModelToUseInLambda.Syntax); + return MethodBodySemanticModel.Create(_compilation, methodSymbol, + forSemanticModelToUseInLambda.Binder, rootSyntax, + forSemanticModelToUseInLambda.Body); + }); + } + + return semanticModel; + }); + } _compilation.EventQueue.TryEnqueue(new SymbolDeclaredCompilationEvent(_compilation, methodSymbol, lazySemanticModel)); } @@ -1547,23 +1565,25 @@ private static void GetStateMachineSlotDebugInfo( // NOTE: can return null if the method has no body. internal static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationState compilationState, DiagnosticBag diagnostics) { - ImportChain importChain; - bool originalBodyNested; - return BindMethodBody(method, compilationState, diagnostics, out importChain, out originalBodyNested); + return BindMethodBody(method, compilationState, diagnostics, out _, out _, out _); } // NOTE: can return null if the method has no body. - private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationState compilationState, DiagnosticBag diagnostics, out ImportChain importChain, out bool originalBodyNested) + private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationState compilationState, DiagnosticBag diagnostics, + out ImportChain importChain, out bool originalBodyNested, + out (SyntaxNode Syntax, BoundNode Body, ExecutableCodeBinder Binder) forSemanticModel) { originalBodyNested = false; importChain = null; + forSemanticModel = default; BoundBlock body; var sourceMethod = method as SourceMemberMethodSymbol; if ((object)sourceMethod != null) { - var constructorSyntax = sourceMethod.SyntaxNode as ConstructorDeclarationSyntax; + CSharpSyntaxNode syntaxNode = sourceMethod.SyntaxNode; + var constructorSyntax = syntaxNode as ConstructorDeclarationSyntax; // Static constructor can't have any this/base call if (method.MethodKind == MethodKind.StaticConstructor && @@ -1575,9 +1595,11 @@ private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationSta constructorSyntax.Identifier.ValueText); } + ExecutableCodeBinder bodyBinder = sourceMethod.TryGetBodyBinder(); + if (sourceMethod.IsExtern) { - if (sourceMethod.BodySyntax == null && constructorSyntax?.Initializer == null) + if (bodyBinder == null) { // Generate warnings only if we are not generating ERR_ExternHasBody or ERR_ExternHasConstructorInitializer errors GenerateExternalMethodWarnings(sourceMethod, diagnostics); @@ -1592,23 +1614,53 @@ private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationSta return null; } - var compilation = method.DeclaringCompilation; - var factory = compilation.GetBinderFactory(sourceMethod.SyntaxTree); + if (bodyBinder != null) + { + importChain = bodyBinder.ImportChain; + bodyBinder.ValidateIteratorMethods(diagnostics); - var bodySyntax = sourceMethod.BodySyntax; + BoundNode methodBody = bodyBinder.BindMethodBody(syntaxNode, diagnostics); + forSemanticModel = (syntaxNode, methodBody, bodyBinder); - if (bodySyntax != null) - { - var inMethodBinder = factory.GetBinder(bodySyntax); - var binder = new ExecutableCodeBinder(bodySyntax, sourceMethod, inMethodBinder); - importChain = binder.ImportChain; + switch (methodBody.Kind) + { + case BoundKind.ConstructorMethodBody: + var constructor = (BoundConstructorMethodBody)methodBody; + body = constructor.BlockBody ?? constructor.ExpressionBody; + + if (constructor.Initializer != null) + { + ReportCtorInitializerCycles(method, constructor.Initializer.Expression, compilationState, diagnostics); + + if (body == null) + { + body = new BoundBlock(constructor.Syntax, constructor.Locals, ImmutableArray.Create(constructor.Initializer)); + } + else + { + body = new BoundBlock(constructor.Syntax, constructor.Locals, ImmutableArray.Create(constructor.Initializer, body)); + originalBodyNested = true; + } + + return body; + } + else + { + Debug.Assert(constructor.Locals.IsEmpty); + } + break; - binder.ValidateIteratorMethods(diagnostics); + case BoundKind.NonConstructorMethodBody: + var nonConstructor = (BoundNonConstructorMethodBody)methodBody; + body = nonConstructor.BlockBody ?? nonConstructor.ExpressionBody; + break; - body = bodySyntax.Kind() == SyntaxKind.Block - ? binder.BindEmbeddedBlock((BlockSyntax)bodySyntax, diagnostics) - : binder.BindExpressionBodyAsBlock( - (ArrowExpressionClauseSyntax)bodySyntax, diagnostics); + case BoundKind.Block: + body = (BoundBlock)methodBody; + break; + default: + throw ExceptionUtilities.UnexpectedValue(methodBody.Kind); + } } else { @@ -1632,7 +1684,7 @@ private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationSta return MethodBodySynthesizer.ConstructDestructorBody(method, body); } - var constructorInitializer = BindConstructorInitializerIfAny(method, compilationState, diagnostics); + var constructorInitializer = BindImplicitConstructorInitializerIfAny(method, compilationState, diagnostics); ImmutableArray statements; if (constructorInitializer == null) @@ -1657,22 +1709,17 @@ private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationSta return BoundBlock.SynthesizedNoLocals(method.GetNonNullSyntaxNode(), statements); } - private static BoundStatement BindConstructorInitializerIfAny(MethodSymbol method, TypeCompilationState compilationState, DiagnosticBag diagnostics) + private static BoundStatement BindImplicitConstructorInitializerIfAny(MethodSymbol method, TypeCompilationState compilationState, DiagnosticBag diagnostics) { // delegates have constructors but not constructor initializers if (method.MethodKind == MethodKind.Constructor && !method.ContainingType.IsDelegateType() && !method.IsExtern) { var compilation = method.DeclaringCompilation; - var initializerInvocation = BindConstructorInitializer(method, diagnostics, compilation); + var initializerInvocation = BindImplicitConstructorInitializer(method, diagnostics, compilation); if (initializerInvocation != null) { - var ctorCall = initializerInvocation as BoundCall; - if (ctorCall != null && !ctorCall.HasAnyErrors && ctorCall.Method != method && ctorCall.Method.ContainingType == method.ContainingType) - { - // Detect and report indirect cycles in the ctor-initializer call graph. - compilationState.ReportCtorInitializerCycles(method, ctorCall.Method, ctorCall.Syntax, diagnostics); - } + ReportCtorInitializerCycles(method, initializerInvocation, compilationState, diagnostics); // Base WasCompilerGenerated state off of whether constructor is implicitly declared, this will ensure proper instrumentation. var constructorInitializer = new BoundExpressionStatement(initializerInvocation.Syntax, initializerInvocation) { WasCompilerGenerated = method.IsImplicitlyDeclared }; @@ -1684,38 +1731,39 @@ private static BoundStatement BindConstructorInitializerIfAny(MethodSymbol metho return null; } + private static void ReportCtorInitializerCycles(MethodSymbol method, BoundExpression initializerInvocation, TypeCompilationState compilationState, DiagnosticBag diagnostics) + { + var ctorCall = initializerInvocation as BoundCall; + if (ctorCall != null && !ctorCall.HasAnyErrors && ctorCall.Method != method && ctorCall.Method.ContainingType == method.ContainingType) + { + // Detect and report indirect cycles in the ctor-initializer call graph. + compilationState.ReportCtorInitializerCycles(method, ctorCall.Method, ctorCall.Syntax, diagnostics); + } + } + /// - /// Bind the (implicit or explicit) constructor initializer of a constructor symbol. + /// Bind the implicit constructor initializer of a constructor symbol. /// /// Constructor method. /// Accumulates errors (e.g. access "this" in constructor initializer). /// Used to retrieve binder. /// A bound expression for the constructor initializer call. - internal static BoundExpression BindConstructorInitializer( + internal static BoundExpression BindImplicitConstructorInitializer( MethodSymbol constructor, DiagnosticBag diagnostics, CSharpCompilation compilation) { // Note that the base type can be null if we're compiling System.Object in source. NamedTypeSymbol baseType = constructor.ContainingType.BaseTypeNoUseSiteDiagnostics; SourceMemberMethodSymbol sourceConstructor = constructor as SourceMemberMethodSymbol; - ConstructorDeclarationSyntax constructorSyntax = null; - ArgumentListSyntax initializerArgumentListOpt = null; - if ((object)sourceConstructor != null) - { - constructorSyntax = (ConstructorDeclarationSyntax)sourceConstructor.SyntaxNode; - if (constructorSyntax.Initializer != null) - { - initializerArgumentListOpt = constructorSyntax.Initializer.ArgumentList; - } - } + Debug.Assert(((ConstructorDeclarationSyntax)sourceConstructor?.SyntaxNode)?.Initializer == null); - // The common case is that we have no constructor initializer and the type inherits directly from object. + // The common case is that the type inherits directly from object. // Also, we might be trying to generate a constructor for an entirely compiler-generated class such // as a closure class; in that case it is vexing to try to find a suitable binder for the non-existing // constructor syntax so that we can do unnecessary overload resolution on the non-existing initializer! // Simply take the early out: bind directly to the parameterless object ctor rather than attempting // overload resolution. - if (initializerArgumentListOpt == null && (object)baseType != null) + if ((object)baseType != null) { if (baseType.SpecialType == SpecialType.System_Object) { @@ -1729,32 +1777,11 @@ internal static BoundExpression BindConstructorInitializer( } } - // Either our base type is not object, or we have an initializer syntax, or both. We're going to - // need to do overload resolution on the set of constructors of the base type, either on - // the provided initializer syntax, or on an implicit ": base()" syntax. - - // SPEC ERROR: The specification states that if you have the situation - // SPEC ERROR: class B { ... } class D1 : B {} then the default constructor - // SPEC ERROR: generated for D1 must call an accessible *parameterless* constructor - // SPEC ERROR: in B. However, it also states that if you have - // SPEC ERROR: class B { ... } class D2 : B { D2() {} } or - // SPEC ERROR: class B { ... } class D3 : B { D3() : base() {} } then - // SPEC ERROR: the compiler performs *overload resolution* to determine - // SPEC ERROR: which accessible constructor of B is called. Since B might have - // SPEC ERROR: a ctor with all optional parameters, overload resolution might - // SPEC ERROR: succeed even if there is no parameterless constructor. This - // SPEC ERROR: is unintentionally inconsistent, and the native compiler does not - // SPEC ERROR: implement this behavior. Rather, we should say in the spec that - // SPEC ERROR: if there is no ctor in D1, then a ctor is created for you exactly - // SPEC ERROR: as though you'd said "D1() : base() {}". - // SPEC ERROR: This is what we now do in Roslyn. - // Now, in order to do overload resolution, we're going to need a binder. There are - // three possible situations: + // two possible situations: // // class D1 : B { } // class D2 : B { D2(int x) { } } - // class D3 : B { D3(int x) : base(x) { } } // // In the first case the binder needs to be the binder associated with // the *body* of D1 because if the base class ctor is protected, we need @@ -1764,10 +1791,6 @@ internal static BoundExpression BindConstructorInitializer( // In the second case the binder could be the binder associated with // the body of D2; since the implicit call to base() will have no arguments // there is no need to look up "x". - // - // In the third case the binder must be the binder that knows about "x" - // because x is in scope. - Binder outerBinder; if ((object)sourceConstructor == null) @@ -1778,29 +1801,20 @@ internal static BoundExpression BindConstructorInitializer( SyntaxToken bodyToken = GetImplicitConstructorBodyToken(containerNode); outerBinder = compilation.GetBinderFactory(containerNode.SyntaxTree).GetBinder(containerNode, bodyToken.Position); } - else if (initializerArgumentListOpt == null) + else { // We have a ctor in source but no explicit constructor initializer. We can't just use the binder for the // type containing the ctor because the ctor might be marked unsafe. Use the binder for the parameter list // as an approximation - the extra symbols won't matter because there are no identifiers to bind. - outerBinder = compilation.GetBinderFactory(sourceConstructor.SyntaxTree).GetBinder(constructorSyntax.ParameterList); - } - else - { - outerBinder = compilation.GetBinderFactory(sourceConstructor.SyntaxTree).GetBinder(initializerArgumentListOpt); + outerBinder = compilation.GetBinderFactory(sourceConstructor.SyntaxTree).GetBinder(((ConstructorDeclarationSyntax)sourceConstructor.SyntaxNode).ParameterList); } // wrap in ConstructorInitializerBinder for appropriate errors // Handle scoping for possible pattern variables declared in the initializer Binder initializerBinder = outerBinder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.ConstructorInitializer, constructor); - if (initializerArgumentListOpt != null) - { - initializerBinder = new ExecutableCodeBinder(initializerArgumentListOpt, constructor, initializerBinder); - } - - return initializerBinder.BindConstructorInitializer(initializerArgumentListOpt, constructor, diagnostics); + return initializerBinder.BindConstructorInitializer(null, constructor, diagnostics); } private static SyntaxToken GetImplicitConstructorBodyToken(CSharpSyntaxNode containerNode) diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 68f60af8e7f82..bd64a27b43aca 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1460,8 +1460,8 @@ internal enum ErrorCode #region more stragglers for C# 7 ERR_VarInvocationLvalueReserved = 8199, - ERR_ExpressionVariableInConstructorOrFieldInitializer = 8200, - ERR_ExpressionVariableInQueryClause = 8201, + //ERR_ExpressionVariableInConstructorOrFieldInitializer = 8200, + //ERR_ExpressionVariableInQueryClause = 8201, ERR_PublicSignNetModule = 8202, ERR_BadAssemblyName = 8203, ERR_BadAsyncMethodBuilderTaskProperty = 8204, diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index f015dc27af70a..4557a277ac43f 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -157,6 +157,7 @@ internal enum MessageID IDS_FeatureUnmanagedGenericTypeConstraint = MessageBase + 12739, IDS_FeatureStackAllocInitializer = MessageBase + 12740, IDS_FeatureTupleEquality = MessageBase + 12741, + IDS_FeatureExpressionVariablesInQueriesAndInitializers = MessageBase + 12742, } // Message IDs may refer to strings that need to be localized. @@ -207,6 +208,7 @@ internal static LanguageVersion RequiredVersion(this MessageID feature) case MessageID.IDS_FeatureDelegateGenericTypeConstraint: // semantic check case MessageID.IDS_FeatureUnmanagedGenericTypeConstraint: // semantic check case MessageID.IDS_FeatureStackAllocInitializer: + case MessageID.IDS_FeatureExpressionVariablesInQueriesAndInitializers: // semantic check return LanguageVersion.CSharp7_3; // C# 7.2 features. diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/FlowAnalysisPass.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/FlowAnalysisPass.cs index f17bf96c1bee3..51db64717fcec 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/FlowAnalysisPass.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/FlowAnalysisPass.cs @@ -41,7 +41,7 @@ public static BoundBlock Rewrite( // we don't analyze synthesized void methods. if ((method.IsImplicitlyDeclared && !method.IsScriptInitializer) || Analyze(compilation, method, block, diagnostics)) { - block = AppendImplicitReturn(block, method, (CSharpSyntaxNode)(method as SourceMemberMethodSymbol)?.BodySyntax, originalBodyNested); + block = AppendImplicitReturn(block, method, originalBodyNested); } } else if (Analyze(compilation, method, block, diagnostics)) @@ -80,7 +80,7 @@ public static BoundBlock Rewrite( return block; } - private static BoundBlock AppendImplicitReturn(BoundBlock body, MethodSymbol method, CSharpSyntaxNode syntax, bool originalBodyNested) + private static BoundBlock AppendImplicitReturn(BoundBlock body, MethodSymbol method, bool originalBodyNested) { if (originalBodyNested) { @@ -89,30 +89,30 @@ private static BoundBlock AppendImplicitReturn(BoundBlock body, MethodSymbol met var builder = ArrayBuilder.GetInstance(n); builder.AddRange(statements, n - 1); - builder.Add(AppendImplicitReturn((BoundBlock)statements[n - 1], method, syntax)); + builder.Add(AppendImplicitReturn((BoundBlock)statements[n - 1], method)); return body.Update(body.Locals, ImmutableArray.Empty, builder.ToImmutableAndFree()); } else { - return AppendImplicitReturn(body, method, syntax); + return AppendImplicitReturn(body, method); } } // insert the implicit "return" statement at the end of the method body // Normally, we wouldn't bother attaching syntax trees to compiler-generated nodes, but these // ones are going to have sequence points. - internal static BoundBlock AppendImplicitReturn(BoundBlock body, MethodSymbol method, SyntaxNode syntax = null) + internal static BoundBlock AppendImplicitReturn(BoundBlock body, MethodSymbol method) { Debug.Assert(body != null); Debug.Assert(method != null); - if (syntax == null) - { - syntax = body.Syntax; - } + SyntaxNode syntax = body.Syntax; - Debug.Assert(body.WasCompilerGenerated || syntax.IsKind(SyntaxKind.Block) || syntax.IsKind(SyntaxKind.ArrowExpressionClause)); + Debug.Assert(body.WasCompilerGenerated || + syntax.IsKind(SyntaxKind.Block) || + syntax.IsKind(SyntaxKind.ArrowExpressionClause) || + syntax.IsKind(SyntaxKind.ConstructorDeclaration)); BoundStatement ret = method.IsIterator ? (BoundStatement)BoundYieldBreakStatement.Synthesized(syntax) diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/PreciseAbstractFlowPass.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/PreciseAbstractFlowPass.cs index 1eb8c0aaef567..8bc45d838a733 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/PreciseAbstractFlowPass.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/PreciseAbstractFlowPass.cs @@ -1182,12 +1182,6 @@ public override BoundNode VisitScope(BoundScope node) return null; } - public override BoundNode VisitFieldInitializer(BoundFieldInitializer node) - { - Visit(node.InitialValue); - return null; - } - public override BoundNode VisitExpressionStatement(BoundExpressionStatement node) { VisitRvalue(node.Expression); @@ -2761,6 +2755,49 @@ public override BoundNode VisitDiscardExpression(BoundDiscardExpression node) { return null; } + + public override BoundNode VisitConstructorMethodBody(BoundConstructorMethodBody node) + { + Visit(node.Initializer); + VisitMethodBodies(node.BlockBody, node.ExpressionBody); + return null; + } + + public override BoundNode VisitNonConstructorMethodBody(BoundNonConstructorMethodBody node) + { + VisitMethodBodies(node.BlockBody, node.ExpressionBody); + return null; + } + + private void VisitMethodBodies(BoundBlock blockBody, BoundBlock expressionBody) + { + if (blockBody == null) + { + Visit(expressionBody); + return; + } + else if (expressionBody == null) + { + Visit(blockBody); + return; + } + + // In error cases we have two bodies. These are two unrelated pieces of code, + // they are not executed one after another. As we don't really know which one the developer + // intended to use, we need to visit both. We are going to pretend that there is + // an unconditional fork in execution and then we are converging after each body is executed. + // For example, if only one body assigns an out parameter, then after visiting both bodies + // we should consider that parameter is not definitely assigned. + // Note, that today this code is not executed for regular definite assignment analysis. It is + // only executed for region analysis. + LocalState initialState = this.State.Clone(); + Visit(blockBody); + LocalState afterBlock = this.State; + SetState(initialState); + Visit(expressionBody); + + IntersectWith(ref this.State, ref afterBlock); + } #endregion visitors } } diff --git a/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs b/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs index ccaf2220ef328..43980939241f8 100644 --- a/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs @@ -20,7 +20,6 @@ namespace Microsoft.CodeAnalysis.CSharp { internal enum BoundKind: byte { - FieldInitializer, FieldEqualsValue, PropertyEqualsValue, ParameterEqualsValue, @@ -173,6 +172,8 @@ internal enum BoundKind: byte OutVariablePendingInference, DeconstructionVariablePendingInference, OutDeconstructVarPendingInference, + NonConstructorMethodBody, + ConstructorMethodBody, } @@ -198,63 +199,33 @@ protected BoundInitializer(BoundKind kind, SyntaxNode syntax) } - internal sealed partial class BoundFieldInitializer : BoundInitializer + internal abstract partial class BoundEqualsValue : BoundInitializer { - public BoundFieldInitializer(SyntaxNode syntax, FieldSymbol field, BoundExpression initialValue, bool hasErrors = false) - : base(BoundKind.FieldInitializer, syntax, hasErrors || initialValue.HasErrors()) - { - - Debug.Assert(field != null, "Field 'field' cannot be null (use Null=\"allow\" in BoundNodes.xml to remove this check)"); - Debug.Assert(initialValue != null, "Field 'initialValue' cannot be null (use Null=\"allow\" in BoundNodes.xml to remove this check)"); - - this.Field = field; - this.InitialValue = initialValue; - } - - - public FieldSymbol Field { get; } - - public BoundExpression InitialValue { get; } - - public override BoundNode Accept(BoundTreeVisitor visitor) - { - return visitor.VisitFieldInitializer(this); - } - - public BoundFieldInitializer Update(FieldSymbol field, BoundExpression initialValue) - { - if (field != this.Field || initialValue != this.InitialValue) - { - var result = new BoundFieldInitializer(this.Syntax, field, initialValue, this.HasErrors); - result.WasCompilerGenerated = this.WasCompilerGenerated; - return result; - } - return this; - } - } - - internal abstract partial class BoundEqualsValue : BoundNode - { - protected BoundEqualsValue(BoundKind kind, SyntaxNode syntax, BoundExpression value, bool hasErrors = false) + protected BoundEqualsValue(BoundKind kind, SyntaxNode syntax, ImmutableArray locals, BoundExpression value, bool hasErrors = false) : base(kind, syntax, hasErrors) { + Debug.Assert(!locals.IsDefault, "Field 'locals' cannot be null (use Null=\"allow\" in BoundNodes.xml to remove this check)"); Debug.Assert(value != null, "Field 'value' cannot be null (use Null=\"allow\" in BoundNodes.xml to remove this check)"); + this.Locals = locals; this.Value = value; } + public ImmutableArray Locals { get; } + public BoundExpression Value { get; } } internal sealed partial class BoundFieldEqualsValue : BoundEqualsValue { - public BoundFieldEqualsValue(SyntaxNode syntax, FieldSymbol field, BoundExpression value, bool hasErrors = false) - : base(BoundKind.FieldEqualsValue, syntax, value, hasErrors || value.HasErrors()) + public BoundFieldEqualsValue(SyntaxNode syntax, FieldSymbol field, ImmutableArray locals, BoundExpression value, bool hasErrors = false) + : base(BoundKind.FieldEqualsValue, syntax, locals, value, hasErrors || value.HasErrors()) { Debug.Assert(field != null, "Field 'field' cannot be null (use Null=\"allow\" in BoundNodes.xml to remove this check)"); + Debug.Assert(!locals.IsDefault, "Field 'locals' cannot be null (use Null=\"allow\" in BoundNodes.xml to remove this check)"); Debug.Assert(value != null, "Field 'value' cannot be null (use Null=\"allow\" in BoundNodes.xml to remove this check)"); this.Field = field; @@ -268,11 +239,11 @@ public override BoundNode Accept(BoundTreeVisitor visitor) return visitor.VisitFieldEqualsValue(this); } - public BoundFieldEqualsValue Update(FieldSymbol field, BoundExpression value) + public BoundFieldEqualsValue Update(FieldSymbol field, ImmutableArray locals, BoundExpression value) { - if (field != this.Field || value != this.Value) + if (field != this.Field || locals != this.Locals || value != this.Value) { - var result = new BoundFieldEqualsValue(this.Syntax, field, value, this.HasErrors); + var result = new BoundFieldEqualsValue(this.Syntax, field, locals, value, this.HasErrors); result.WasCompilerGenerated = this.WasCompilerGenerated; return result; } @@ -282,11 +253,12 @@ public BoundFieldEqualsValue Update(FieldSymbol field, BoundExpression value) internal sealed partial class BoundPropertyEqualsValue : BoundEqualsValue { - public BoundPropertyEqualsValue(SyntaxNode syntax, PropertySymbol property, BoundExpression value, bool hasErrors = false) - : base(BoundKind.PropertyEqualsValue, syntax, value, hasErrors || value.HasErrors()) + public BoundPropertyEqualsValue(SyntaxNode syntax, PropertySymbol property, ImmutableArray locals, BoundExpression value, bool hasErrors = false) + : base(BoundKind.PropertyEqualsValue, syntax, locals, value, hasErrors || value.HasErrors()) { Debug.Assert(property != null, "Field 'property' cannot be null (use Null=\"allow\" in BoundNodes.xml to remove this check)"); + Debug.Assert(!locals.IsDefault, "Field 'locals' cannot be null (use Null=\"allow\" in BoundNodes.xml to remove this check)"); Debug.Assert(value != null, "Field 'value' cannot be null (use Null=\"allow\" in BoundNodes.xml to remove this check)"); this.Property = property; @@ -300,11 +272,11 @@ public override BoundNode Accept(BoundTreeVisitor visitor) return visitor.VisitPropertyEqualsValue(this); } - public BoundPropertyEqualsValue Update(PropertySymbol property, BoundExpression value) + public BoundPropertyEqualsValue Update(PropertySymbol property, ImmutableArray locals, BoundExpression value) { - if (property != this.Property || value != this.Value) + if (property != this.Property || locals != this.Locals || value != this.Value) { - var result = new BoundPropertyEqualsValue(this.Syntax, property, value, this.HasErrors); + var result = new BoundPropertyEqualsValue(this.Syntax, property, locals, value, this.HasErrors); result.WasCompilerGenerated = this.WasCompilerGenerated; return result; } @@ -314,11 +286,12 @@ public BoundPropertyEqualsValue Update(PropertySymbol property, BoundExpression internal sealed partial class BoundParameterEqualsValue : BoundEqualsValue { - public BoundParameterEqualsValue(SyntaxNode syntax, ParameterSymbol parameter, BoundExpression value, bool hasErrors = false) - : base(BoundKind.ParameterEqualsValue, syntax, value, hasErrors || value.HasErrors()) + public BoundParameterEqualsValue(SyntaxNode syntax, ParameterSymbol parameter, ImmutableArray locals, BoundExpression value, bool hasErrors = false) + : base(BoundKind.ParameterEqualsValue, syntax, locals, value, hasErrors || value.HasErrors()) { Debug.Assert(parameter != null, "Field 'parameter' cannot be null (use Null=\"allow\" in BoundNodes.xml to remove this check)"); + Debug.Assert(!locals.IsDefault, "Field 'locals' cannot be null (use Null=\"allow\" in BoundNodes.xml to remove this check)"); Debug.Assert(value != null, "Field 'value' cannot be null (use Null=\"allow\" in BoundNodes.xml to remove this check)"); this.Parameter = parameter; @@ -332,11 +305,11 @@ public override BoundNode Accept(BoundTreeVisitor visitor) return visitor.VisitParameterEqualsValue(this); } - public BoundParameterEqualsValue Update(ParameterSymbol parameter, BoundExpression value) + public BoundParameterEqualsValue Update(ParameterSymbol parameter, ImmutableArray locals, BoundExpression value) { - if (parameter != this.Parameter || value != this.Value) + if (parameter != this.Parameter || locals != this.Locals || value != this.Value) { - var result = new BoundParameterEqualsValue(this.Syntax, parameter, value, this.HasErrors); + var result = new BoundParameterEqualsValue(this.Syntax, parameter, locals, value, this.HasErrors); result.WasCompilerGenerated = this.WasCompilerGenerated; return result; } @@ -6273,6 +6246,80 @@ public OutDeconstructVarPendingInference Update() } } + internal abstract partial class BoundMethodBodyBase : BoundNode + { + protected BoundMethodBodyBase(BoundKind kind, SyntaxNode syntax, BoundBlock blockBody, BoundBlock expressionBody, bool hasErrors = false) + : base(kind, syntax, hasErrors) + { + this.BlockBody = blockBody; + this.ExpressionBody = expressionBody; + } + + + public BoundBlock BlockBody { get; } + + public BoundBlock ExpressionBody { get; } + } + + internal sealed partial class BoundNonConstructorMethodBody : BoundMethodBodyBase + { + public BoundNonConstructorMethodBody(SyntaxNode syntax, BoundBlock blockBody, BoundBlock expressionBody, bool hasErrors = false) + : base(BoundKind.NonConstructorMethodBody, syntax, blockBody, expressionBody, hasErrors || blockBody.HasErrors() || expressionBody.HasErrors()) + { + } + + + public override BoundNode Accept(BoundTreeVisitor visitor) + { + return visitor.VisitNonConstructorMethodBody(this); + } + + public BoundNonConstructorMethodBody Update(BoundBlock blockBody, BoundBlock expressionBody) + { + if (blockBody != this.BlockBody || expressionBody != this.ExpressionBody) + { + var result = new BoundNonConstructorMethodBody(this.Syntax, blockBody, expressionBody, this.HasErrors); + result.WasCompilerGenerated = this.WasCompilerGenerated; + return result; + } + return this; + } + } + + internal sealed partial class BoundConstructorMethodBody : BoundMethodBodyBase + { + public BoundConstructorMethodBody(SyntaxNode syntax, ImmutableArray locals, BoundExpressionStatement initializer, BoundBlock blockBody, BoundBlock expressionBody, bool hasErrors = false) + : base(BoundKind.ConstructorMethodBody, syntax, blockBody, expressionBody, hasErrors || initializer.HasErrors() || blockBody.HasErrors() || expressionBody.HasErrors()) + { + + Debug.Assert(!locals.IsDefault, "Field 'locals' cannot be null (use Null=\"allow\" in BoundNodes.xml to remove this check)"); + + this.Locals = locals; + this.Initializer = initializer; + } + + + public ImmutableArray Locals { get; } + + public BoundExpressionStatement Initializer { get; } + + public override BoundNode Accept(BoundTreeVisitor visitor) + { + return visitor.VisitConstructorMethodBody(this); + } + + public BoundConstructorMethodBody Update(ImmutableArray locals, BoundExpressionStatement initializer, BoundBlock blockBody, BoundBlock expressionBody) + { + if (locals != this.Locals || initializer != this.Initializer || blockBody != this.BlockBody || expressionBody != this.ExpressionBody) + { + var result = new BoundConstructorMethodBody(this.Syntax, locals, initializer, blockBody, expressionBody, this.HasErrors); + result.WasCompilerGenerated = this.WasCompilerGenerated; + return result; + } + return this; + } + } + internal abstract partial class BoundTreeVisitor { @@ -6281,8 +6328,6 @@ internal R VisitInternal(BoundNode node, A arg) { switch (node.Kind) { - case BoundKind.FieldInitializer: - return VisitFieldInitializer(node as BoundFieldInitializer, arg); case BoundKind.FieldEqualsValue: return VisitFieldEqualsValue(node as BoundFieldEqualsValue, arg); case BoundKind.PropertyEqualsValue: @@ -6587,6 +6632,10 @@ internal R VisitInternal(BoundNode node, A arg) return VisitDeconstructionVariablePendingInference(node as DeconstructionVariablePendingInference, arg); case BoundKind.OutDeconstructVarPendingInference: return VisitOutDeconstructVarPendingInference(node as OutDeconstructVarPendingInference, arg); + case BoundKind.NonConstructorMethodBody: + return VisitNonConstructorMethodBody(node as BoundNonConstructorMethodBody, arg); + case BoundKind.ConstructorMethodBody: + return VisitConstructorMethodBody(node as BoundConstructorMethodBody, arg); } return default(R); @@ -6595,10 +6644,6 @@ internal R VisitInternal(BoundNode node, A arg) internal abstract partial class BoundTreeVisitor { - public virtual R VisitFieldInitializer(BoundFieldInitializer node, A arg) - { - return this.DefaultVisit(node, arg); - } public virtual R VisitFieldEqualsValue(BoundFieldEqualsValue node, A arg) { return this.DefaultVisit(node, arg); @@ -7207,14 +7252,18 @@ public virtual R VisitOutDeconstructVarPendingInference(OutDeconstructVarPending { return this.DefaultVisit(node, arg); } + public virtual R VisitNonConstructorMethodBody(BoundNonConstructorMethodBody node, A arg) + { + return this.DefaultVisit(node, arg); + } + public virtual R VisitConstructorMethodBody(BoundConstructorMethodBody node, A arg) + { + return this.DefaultVisit(node, arg); + } } internal abstract partial class BoundTreeVisitor { - public virtual BoundNode VisitFieldInitializer(BoundFieldInitializer node) - { - return this.DefaultVisit(node); - } public virtual BoundNode VisitFieldEqualsValue(BoundFieldEqualsValue node) { return this.DefaultVisit(node); @@ -7823,15 +7872,18 @@ public virtual BoundNode VisitOutDeconstructVarPendingInference(OutDeconstructVa { return this.DefaultVisit(node); } + public virtual BoundNode VisitNonConstructorMethodBody(BoundNonConstructorMethodBody node) + { + return this.DefaultVisit(node); + } + public virtual BoundNode VisitConstructorMethodBody(BoundConstructorMethodBody node) + { + return this.DefaultVisit(node); + } } internal abstract partial class BoundTreeWalker: BoundTreeVisitor { - public override BoundNode VisitFieldInitializer(BoundFieldInitializer node) - { - this.Visit(node.InitialValue); - return null; - } public override BoundNode VisitFieldEqualsValue(BoundFieldEqualsValue node) { this.Visit(node.Value); @@ -8617,29 +8669,37 @@ public override BoundNode VisitOutDeconstructVarPendingInference(OutDeconstructV { return null; } + public override BoundNode VisitNonConstructorMethodBody(BoundNonConstructorMethodBody node) + { + this.Visit(node.BlockBody); + this.Visit(node.ExpressionBody); + return null; + } + public override BoundNode VisitConstructorMethodBody(BoundConstructorMethodBody node) + { + this.Visit(node.Initializer); + this.Visit(node.BlockBody); + this.Visit(node.ExpressionBody); + return null; + } } internal abstract partial class BoundTreeRewriter : BoundTreeVisitor { - public override BoundNode VisitFieldInitializer(BoundFieldInitializer node) - { - BoundExpression initialValue = (BoundExpression)this.Visit(node.InitialValue); - return node.Update(node.Field, initialValue); - } public override BoundNode VisitFieldEqualsValue(BoundFieldEqualsValue node) { BoundExpression value = (BoundExpression)this.Visit(node.Value); - return node.Update(node.Field, value); + return node.Update(node.Field, node.Locals, value); } public override BoundNode VisitPropertyEqualsValue(BoundPropertyEqualsValue node) { BoundExpression value = (BoundExpression)this.Visit(node.Value); - return node.Update(node.Property, value); + return node.Update(node.Property, node.Locals, value); } public override BoundNode VisitParameterEqualsValue(BoundParameterEqualsValue node) { BoundExpression value = (BoundExpression)this.Visit(node.Value); - return node.Update(node.Parameter, value); + return node.Update(node.Parameter, node.Locals, value); } public override BoundNode VisitGlobalStatementInitializer(BoundGlobalStatementInitializer node) { @@ -9524,6 +9584,19 @@ public override BoundNode VisitOutDeconstructVarPendingInference(OutDeconstructV TypeSymbol type = this.VisitType(node.Type); return node.Update(); } + public override BoundNode VisitNonConstructorMethodBody(BoundNonConstructorMethodBody node) + { + BoundBlock blockBody = (BoundBlock)this.Visit(node.BlockBody); + BoundBlock expressionBody = (BoundBlock)this.Visit(node.ExpressionBody); + return node.Update(blockBody, expressionBody); + } + public override BoundNode VisitConstructorMethodBody(BoundConstructorMethodBody node) + { + BoundExpressionStatement initializer = (BoundExpressionStatement)this.Visit(node.Initializer); + BoundBlock blockBody = (BoundBlock)this.Visit(node.BlockBody); + BoundBlock expressionBody = (BoundBlock)this.Visit(node.ExpressionBody); + return node.Update(node.Locals, initializer, blockBody, expressionBody); + } } internal sealed class BoundTreeDumperNodeProducer : BoundTreeVisitor @@ -9535,20 +9608,12 @@ public static TreeDumperNode MakeTree(BoundNode node) { return (new BoundTreeDumperNodeProducer()).Visit(node, null); } - public override TreeDumperNode VisitFieldInitializer(BoundFieldInitializer node, object arg) - { - return new TreeDumperNode("fieldInitializer", null, new TreeDumperNode[] - { - new TreeDumperNode("field", node.Field, null), - new TreeDumperNode("initialValue", null, new TreeDumperNode[] { Visit(node.InitialValue, null) }) - } - ); - } public override TreeDumperNode VisitFieldEqualsValue(BoundFieldEqualsValue node, object arg) { return new TreeDumperNode("fieldEqualsValue", null, new TreeDumperNode[] { new TreeDumperNode("field", node.Field, null), + new TreeDumperNode("locals", node.Locals, null), new TreeDumperNode("value", null, new TreeDumperNode[] { Visit(node.Value, null) }) } ); @@ -9558,6 +9623,7 @@ public override TreeDumperNode VisitPropertyEqualsValue(BoundPropertyEqualsValue return new TreeDumperNode("propertyEqualsValue", null, new TreeDumperNode[] { new TreeDumperNode("property", node.Property, null), + new TreeDumperNode("locals", node.Locals, null), new TreeDumperNode("value", null, new TreeDumperNode[] { Visit(node.Value, null) }) } ); @@ -9567,6 +9633,7 @@ public override TreeDumperNode VisitParameterEqualsValue(BoundParameterEqualsVal return new TreeDumperNode("parameterEqualsValue", null, new TreeDumperNode[] { new TreeDumperNode("parameter", node.Parameter, null), + new TreeDumperNode("locals", node.Locals, null), new TreeDumperNode("value", null, new TreeDumperNode[] { Visit(node.Value, null) }) } ); @@ -11123,5 +11190,25 @@ public override TreeDumperNode VisitOutDeconstructVarPendingInference(OutDeconst } ); } + public override TreeDumperNode VisitNonConstructorMethodBody(BoundNonConstructorMethodBody node, object arg) + { + return new TreeDumperNode("nonConstructorMethodBody", null, new TreeDumperNode[] + { + new TreeDumperNode("blockBody", null, new TreeDumperNode[] { Visit(node.BlockBody, null) }), + new TreeDumperNode("expressionBody", null, new TreeDumperNode[] { Visit(node.ExpressionBody, null) }) + } + ); + } + public override TreeDumperNode VisitConstructorMethodBody(BoundConstructorMethodBody node, object arg) + { + return new TreeDumperNode("constructorMethodBody", null, new TreeDumperNode[] + { + new TreeDumperNode("locals", node.Locals, null), + new TreeDumperNode("initializer", null, new TreeDumperNode[] { Visit(node.Initializer, null) }), + new TreeDumperNode("blockBody", null, new TreeDumperNode[] { Visit(node.BlockBody, null) }), + new TreeDumperNode("expressionBody", null, new TreeDumperNode[] { Visit(node.ExpressionBody, null) }) + } + ); + } } } diff --git a/src/Compilers/CSharp/Portable/Lowering/InitializerRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/InitializerRewriter.cs index 6f4640d218a43..db70e312f36da 100644 --- a/src/Compilers/CSharp/Portable/Lowering/InitializerRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/InitializerRewriter.cs @@ -82,9 +82,10 @@ internal static BoundExpression GetTrailingScriptExpression(BoundStatement state null; } - private static BoundStatement RewriteFieldInitializer(BoundFieldInitializer fieldInit) + private static BoundStatement RewriteFieldInitializer(BoundFieldEqualsValue fieldInit) { - var syntax = fieldInit.Syntax; + SyntaxNode syntax = fieldInit.Syntax; + syntax = (syntax as EqualsValueClauseSyntax)?.Value ?? syntax; //we want the attached sequence point to indicate the value node var boundReceiver = fieldInit.Field.IsStatic ? null : new BoundThisReference(syntax, fieldInit.Field.ContainingType); @@ -95,10 +96,15 @@ private static BoundStatement RewriteFieldInitializer(BoundFieldInitializer fiel boundReceiver, fieldInit.Field, constantValueOpt: null), - fieldInit.InitialValue, + fieldInit.Value, fieldInit.Field.Type) { WasCompilerGenerated = true }) - { WasCompilerGenerated = fieldInit.WasCompilerGenerated }; + { WasCompilerGenerated = !fieldInit.Locals.IsEmpty || fieldInit.WasCompilerGenerated }; + + if (!fieldInit.Locals.IsEmpty) + { + boundStatement = new BoundBlock(syntax, fieldInit.Locals, ImmutableArray.Create(boundStatement)) { WasCompilerGenerated = fieldInit.WasCompilerGenerated }; + } Debug.Assert(LocalRewriter.IsFieldOrPropertyInitializer(boundStatement)); return boundStatement; @@ -108,8 +114,8 @@ private static BoundStatement RewriteInitializersAsStatements(BoundInitializer i { switch (initializer.Kind) { - case BoundKind.FieldInitializer: - return RewriteFieldInitializer((BoundFieldInitializer)initializer); + case BoundKind.FieldEqualsValue: + return RewriteFieldInitializer((BoundFieldEqualsValue)initializer); case BoundKind.GlobalStatementInitializer: return ((BoundGlobalStatementInitializer)initializer).Statement; default: diff --git a/src/Compilers/CSharp/Portable/Lowering/Instrumentation/CompoundInstrumenter.cs b/src/Compilers/CSharp/Portable/Lowering/Instrumentation/CompoundInstrumenter.cs index ff4f586cd7bbb..399fd46f4da39 100644 --- a/src/Compilers/CSharp/Portable/Lowering/Instrumentation/CompoundInstrumenter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/Instrumentation/CompoundInstrumenter.cs @@ -58,7 +58,7 @@ public override BoundStatement InstrumentExpressionStatement(BoundExpressionStat return Previous.InstrumentExpressionStatement(original, rewritten); } - public override BoundStatement InstrumentFieldOrPropertyInitializer(BoundExpressionStatement original, BoundStatement rewritten) + public override BoundStatement InstrumentFieldOrPropertyInitializer(BoundStatement original, BoundStatement rewritten) { return Previous.InstrumentFieldOrPropertyInitializer(original, rewritten); } diff --git a/src/Compilers/CSharp/Portable/Lowering/Instrumentation/DebugInfoInjector.cs b/src/Compilers/CSharp/Portable/Lowering/Instrumentation/DebugInfoInjector.cs index 0db1cd2722a87..3fe06d3f74d16 100644 --- a/src/Compilers/CSharp/Portable/Lowering/Instrumentation/DebugInfoInjector.cs +++ b/src/Compilers/CSharp/Portable/Lowering/Instrumentation/DebugInfoInjector.cs @@ -5,6 +5,7 @@ using Roslyn.Utilities; using System.Collections.Immutable; using System.Diagnostics; +using System.Linq; namespace Microsoft.CodeAnalysis.CSharp { @@ -63,11 +64,22 @@ public override BoundStatement InstrumentExpressionStatement(BoundExpressionStat return AddSequencePoint(rewritten); } - public override BoundStatement InstrumentFieldOrPropertyInitializer(BoundExpressionStatement original, BoundStatement rewritten) + public override BoundStatement InstrumentFieldOrPropertyInitializer(BoundStatement original, BoundStatement rewritten) { - rewritten = base.InstrumentExpressionStatement(original, rewritten); + rewritten = base.InstrumentFieldOrPropertyInitializer(original, rewritten); SyntaxNode syntax = original.Syntax; + if (rewritten.Kind == BoundKind.Block) + { + var block = (BoundBlock)rewritten; + return block.Update(block.Locals, block.LocalFunctions, ImmutableArray.Create(InstrumentFieldOrPropertyInitializer(block.Statements.Single(), syntax))); + } + + return InstrumentFieldOrPropertyInitializer(rewritten, syntax); + } + + private static BoundStatement InstrumentFieldOrPropertyInitializer(BoundStatement rewritten, SyntaxNode syntax) + { switch (syntax.Parent.Parent.Kind()) { case SyntaxKind.VariableDeclarator: diff --git a/src/Compilers/CSharp/Portable/Lowering/Instrumentation/DynamicAnalysisInjector.cs b/src/Compilers/CSharp/Portable/Lowering/Instrumentation/DynamicAnalysisInjector.cs index 42037df50727c..9103c2cacbf50 100644 --- a/src/Compilers/CSharp/Portable/Lowering/Instrumentation/DynamicAnalysisInjector.cs +++ b/src/Compilers/CSharp/Portable/Lowering/Instrumentation/DynamicAnalysisInjector.cs @@ -342,9 +342,9 @@ public override BoundStatement InstrumentExpressionStatement(BoundExpressionStat return AddDynamicAnalysis(original, base.InstrumentExpressionStatement(original, rewritten)); } - public override BoundStatement InstrumentFieldOrPropertyInitializer(BoundExpressionStatement original, BoundStatement rewritten) + public override BoundStatement InstrumentFieldOrPropertyInitializer(BoundStatement original, BoundStatement rewritten) { - return AddDynamicAnalysis(original, base.InstrumentExpressionStatement(original, rewritten)); + return AddDynamicAnalysis(original, base.InstrumentFieldOrPropertyInitializer(original, rewritten)); } public override BoundStatement InstrumentGotoStatement(BoundGotoStatement original, BoundStatement rewritten) diff --git a/src/Compilers/CSharp/Portable/Lowering/Instrumentation/Instrumenter.cs b/src/Compilers/CSharp/Portable/Lowering/Instrumentation/Instrumenter.cs index c06756886dbb3..be2fb24c63005 100644 --- a/src/Compilers/CSharp/Portable/Lowering/Instrumentation/Instrumenter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/Instrumentation/Instrumenter.cs @@ -87,7 +87,7 @@ public virtual BoundStatement InstrumentExpressionStatement(BoundExpressionState return InstrumentStatement(original, rewritten); } - public virtual BoundStatement InstrumentFieldOrPropertyInitializer(BoundExpressionStatement original, BoundStatement rewritten) + public virtual BoundStatement InstrumentFieldOrPropertyInitializer(BoundStatement original, BoundStatement rewritten) { Debug.Assert(LocalRewriter.IsFieldOrPropertyInitializer(original)); return InstrumentStatement(original, rewritten); diff --git a/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.Analysis.cs b/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.Analysis.cs index 216cca9ee6d9e..57b2704c05a6b 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.Analysis.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.Analysis.cs @@ -111,7 +111,7 @@ private static BoundNode FindNodeToAnalyze(BoundNode node) case BoundKind.Block: case BoundKind.StatementList: - case BoundKind.FieldInitializer: + case BoundKind.FieldEqualsValue: return node; case BoundKind.GlobalStatementInitializer: diff --git a/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/SynthesizedClosureMethod.cs b/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/SynthesizedClosureMethod.cs index 6d27d06955a7c..d3a53ff916c11 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/SynthesizedClosureMethod.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/SynthesizedClosureMethod.cs @@ -30,7 +30,6 @@ internal SynthesizedClosureMethod( DebugId lambdaId) : base(containingType, originalMethod, - null, blockSyntax, originalMethod.DeclaringSyntaxReferences[0].GetLocation(), originalMethod is LocalFunctionSymbol diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs index 662c2e64509a6..e0968eb83911b 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs @@ -427,7 +427,17 @@ public override BoundNode VisitTypeOrInstanceInitializers(BoundTypeOrInstanceIni { if (IsFieldOrPropertyInitializer(initializer)) { - statements.Add(RewriteExpressionStatement((BoundExpressionStatement)initializer, suppressInstrumentation: true)); + if (initializer.Kind == BoundKind.Block) + { + var block = (BoundBlock)initializer; + statements.Add(block.Update(block.Locals, block.LocalFunctions, + ImmutableArray.Create(RewriteExpressionStatement((BoundExpressionStatement)block.Statements.Single(), + suppressInstrumentation: true)))); + } + else + { + statements.Add(RewriteExpressionStatement((BoundExpressionStatement)initializer, suppressInstrumentation: true)); + } } else { @@ -471,7 +481,7 @@ public override BoundNode VisitTypeOrInstanceInitializers(BoundTypeOrInstanceIni { if (IsFieldOrPropertyInitializer(originalStatements[i])) { - var original = (BoundExpressionStatement)originalStatements[i]; + BoundStatement original = originalStatements[i]; if (Instrument && !original.WasCompilerGenerated) { rewritten = _instrumenter.InstrumentFieldOrPropertyInitializer(original, rewritten); @@ -500,7 +510,26 @@ internal static bool IsFieldOrPropertyInitializer(BoundStatement initializer) { case SyntaxKind.VariableDeclarator: case SyntaxKind.PropertyDeclaration: - return (initializer as BoundExpressionStatement)?.Expression.Kind == BoundKind.AssignmentOperator; + + switch (initializer.Kind) + { + case BoundKind.Block: + var block = (BoundBlock)initializer; + if (block.Statements.Length == 1) + { + initializer = (BoundStatement)block.Statements.First(); + if (initializer.Kind == BoundKind.ExpressionStatement) + { + goto case BoundKind.ExpressionStatement; + } + } + break; + + case BoundKind.ExpressionStatement: + return ((BoundExpressionStatement)initializer).Expression.Kind == BoundKind.AssignmentOperator; + + } + break; } } diff --git a/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs index aeb16ff1a077a..6ce8bf3446196 100644 --- a/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs @@ -644,7 +644,7 @@ private static bool BaseReferenceInReceiverWasRewritten(BoundExpression original private sealed partial class BaseMethodWrapperSymbol : SynthesizedMethodBaseSymbol { internal BaseMethodWrapperSymbol(NamedTypeSymbol containingType, MethodSymbol methodBeingWrapped, SyntaxNode syntax, string name) - : base(containingType, methodBeingWrapped, syntax.SyntaxTree.GetReference(syntax), null, syntax.GetLocation(), name, DeclarationModifiers.Private) + : base(containingType, methodBeingWrapped, syntax.SyntaxTree.GetReference(syntax), syntax.GetLocation(), name, DeclarationModifiers.Private) { Debug.Assert(containingType.ContainingModule is SourceModuleSymbol); Debug.Assert(ReferenceEquals(methodBeingWrapped, methodBeingWrapped.ConstructedFrom)); diff --git a/src/Compilers/CSharp/Portable/Lowering/SynthesizedMethodBaseSymbol.cs b/src/Compilers/CSharp/Portable/Lowering/SynthesizedMethodBaseSymbol.cs index 7fbf0de35e127..aea517c8e088d 100644 --- a/src/Compilers/CSharp/Portable/Lowering/SynthesizedMethodBaseSymbol.cs +++ b/src/Compilers/CSharp/Portable/Lowering/SynthesizedMethodBaseSymbol.cs @@ -24,11 +24,10 @@ internal abstract class SynthesizedMethodBaseSymbol : SourceMemberMethodSymbol protected SynthesizedMethodBaseSymbol(NamedTypeSymbol containingType, MethodSymbol baseMethod, SyntaxReference syntaxReference, - SyntaxReference blockSyntaxReference, Location location, string name, DeclarationModifiers declarationModifiers) - : base(containingType, syntaxReference, blockSyntaxReference, location) + : base(containingType, syntaxReference, location) { Debug.Assert((object)containingType != null); Debug.Assert((object)baseMethod != null); diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs index 49b97d16ccccb..c37bd15970377 100644 --- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs +++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs @@ -241,6 +241,11 @@ private IOperation CreateInternal(BoundNode boundNode) return CreateBoundDelegateCreationExpressionOperation((BoundDelegateCreationExpression)boundNode); case BoundKind.RangeVariable: return CreateBoundRangeVariableOperation((BoundRangeVariable)boundNode); + case BoundKind.ConstructorMethodBody: + return CreateConstructorBodyOperation((BoundConstructorMethodBody)boundNode); + case BoundKind.NonConstructorMethodBody: + return CreateMethodBodyOperation((BoundNonConstructorMethodBody)boundNode); + default: Optional constantValue = ConvertToOptional((boundNode as BoundExpression)?.ConstantValue); bool isImplicit = boundNode.WasCompilerGenerated; @@ -259,6 +264,21 @@ private IOperation CreateInternal(BoundNode boundNode) } } + private IMethodBodyOperation CreateMethodBodyOperation(BoundNonConstructorMethodBody boundNode) + { + Lazy blockBody = new Lazy(() => (IBlockOperation)Create(boundNode.BlockBody)); + Lazy expressionBody = new Lazy(() => (IBlockOperation)Create(boundNode.ExpressionBody)); + return new LazyMethodBodyOperation(_semanticModel, boundNode.Syntax, blockBody, expressionBody); + } + + private IConstructorBodyOperation CreateConstructorBodyOperation(BoundConstructorMethodBody boundNode) + { + Lazy initializer = new Lazy(() => (IOperation)Create(boundNode.Initializer)); + Lazy blockBody = new Lazy(() => (IBlockOperation)Create(boundNode.BlockBody)); + Lazy expressionBody = new Lazy(() => (IBlockOperation)Create(boundNode.ExpressionBody)); + return new LazyConstructorBodyOperation(boundNode.Locals.As(), _semanticModel, boundNode.Syntax, initializer, blockBody, expressionBody); + } + private ImmutableArray GetIOperationChildren(BoundNode boundNode) { var boundNodeWithChildren = (IBoundNodeWithIOperationChildren)boundNode; @@ -1268,7 +1288,7 @@ private IFieldInitializerOperation CreateBoundFieldEqualsValueOperation(BoundFie ITypeSymbol type = null; Optional constantValue = default(Optional); bool isImplicit = boundFieldEqualsValue.WasCompilerGenerated; - return new LazyFieldInitializer(initializedFields, value, kind, _semanticModel, syntax, type, constantValue, isImplicit); + return new LazyFieldInitializer(boundFieldEqualsValue.Locals.As(), initializedFields, value, kind, _semanticModel, syntax, type, constantValue, isImplicit); } private IPropertyInitializerOperation CreateBoundPropertyEqualsValueOperation(BoundPropertyEqualsValue boundPropertyEqualsValue) @@ -1280,7 +1300,7 @@ private IPropertyInitializerOperation CreateBoundPropertyEqualsValueOperation(Bo ITypeSymbol type = null; Optional constantValue = default(Optional); bool isImplicit = boundPropertyEqualsValue.WasCompilerGenerated; - return new LazyPropertyInitializer(initializedProperties, value, kind, _semanticModel, syntax, type, constantValue, isImplicit); + return new LazyPropertyInitializer(boundPropertyEqualsValue.Locals.As(), initializedProperties, value, kind, _semanticModel, syntax, type, constantValue, isImplicit); } private IParameterInitializerOperation CreateBoundParameterEqualsValueOperation(BoundParameterEqualsValue boundParameterEqualsValue) @@ -1292,7 +1312,7 @@ private IParameterInitializerOperation CreateBoundParameterEqualsValueOperation( ITypeSymbol type = null; Optional constantValue = default(Optional); bool isImplicit = boundParameterEqualsValue.WasCompilerGenerated; - return new LazyParameterInitializer(parameter, value, kind, _semanticModel, syntax, type, constantValue, isImplicit); + return new LazyParameterInitializer(boundParameterEqualsValue.Locals.As(), parameter, value, kind, _semanticModel, syntax, type, constantValue, isImplicit); } private IBlockOperation CreateBoundBlockOperation(BoundBlock boundBlock) diff --git a/src/Compilers/CSharp/Portable/Symbols/ConstantValueUtils.cs b/src/Compilers/CSharp/Portable/Symbols/ConstantValueUtils.cs index e52e90d14f893..627c2c7d09cdf 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ConstantValueUtils.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ConstantValueUtils.cs @@ -36,16 +36,16 @@ public static ConstantValue EvaluateFieldConstant( binder = new EarlyWellKnownAttributeBinder(binder); } var inProgressBinder = new ConstantFieldsInProgressBinder(new ConstantFieldsInProgress(symbol, dependencies), binder); - var boundValue = BindFieldOrEnumInitializer(inProgressBinder, symbol, equalsValueNode, diagnostics); + BoundFieldEqualsValue boundValue = BindFieldOrEnumInitializer(inProgressBinder, symbol, equalsValueNode, diagnostics); var initValueNodeLocation = equalsValueNode.Value.Location; - var value = GetAndValidateConstantValue(boundValue, symbol, symbol.Type, initValueNodeLocation, diagnostics); + var value = GetAndValidateConstantValue(boundValue.Value, symbol, symbol.Type, initValueNodeLocation, diagnostics); Debug.Assert(value != null); return value; } - private static BoundExpression BindFieldOrEnumInitializer( + private static BoundFieldEqualsValue BindFieldOrEnumInitializer( Binder binder, FieldSymbol fieldSymbol, EqualsValueClauseSyntax initializer, @@ -54,7 +54,7 @@ private static BoundExpression BindFieldOrEnumInitializer( var enumConstant = fieldSymbol as SourceEnumConstantSymbol; Binder collisionDetector = new LocalScopeBinder(binder); collisionDetector = new ExecutableCodeBinder(initializer, fieldSymbol, collisionDetector); - BoundExpression result; + BoundFieldEqualsValue result; if ((object)enumConstant != null) { @@ -62,7 +62,7 @@ private static BoundExpression BindFieldOrEnumInitializer( } else { - result = collisionDetector.BindVariableOrAutoPropInitializer(initializer, RefKind.None, fieldSymbol.Type, diagnostics); + result = collisionDetector.BindFieldInitializer(fieldSymbol, initializer, diagnostics); } return result; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs index 4ff82b92a6e8e..d9f955825d4c4 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs @@ -186,7 +186,7 @@ protected ConstantValue MakeDefaultExpression(DiagnosticBag diagnostics, Binder Debug.Assert(binderForDefault.ContainingMemberOrLambda == ContainingSymbol); BoundExpression valueBeforeConversion; - var convertedExpression = binderForDefault.BindParameterDefaultValue(defaultSyntax, parameterType, diagnostics, out valueBeforeConversion); + BoundExpression convertedExpression = binderForDefault.BindParameterDefaultValue(defaultSyntax, this, diagnostics, out valueBeforeConversion).Value; if (valueBeforeConversion.HasErrors) { return ConstantValue.Bad; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs index 5e659dfda4bc4..2c5321786f074 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs @@ -30,7 +30,7 @@ private SourceConstructorSymbol( ConstructorDeclarationSyntax syntax, MethodKind methodKind, DiagnosticBag diagnostics) : - base(containingType, syntax.GetReference(), syntax.Body?.GetReference() ?? syntax.ExpressionBody?.GetReference(), ImmutableArray.Create(location)) + base(containingType, syntax.GetReference(), ImmutableArray.Create(location)) { bool modifierErrors; var declarationModifiers = this.MakeModifiers(syntax.Modifiers, methodKind, location, diagnostics, out modifierErrors); @@ -66,7 +66,7 @@ private SourceConstructorSymbol( if (!modifierErrors) { - this.CheckModifiers(methodKind, location, diagnostics); + this.CheckModifiers(methodKind, hasBlockBody || _isExpressionBodied, location, diagnostics); } CheckForBlockAndExpressionBody( @@ -213,9 +213,9 @@ private DeclarationModifiers MakeModifiers(SyntaxTokenList modifiers, MethodKind return mods; } - private void CheckModifiers(MethodKind methodKind, Location location, DiagnosticBag diagnostics) + private void CheckModifiers(MethodKind methodKind, bool hasBody, Location location, DiagnosticBag diagnostics) { - if (bodySyntaxReferenceOpt == null && !IsExtern) + if (!hasBody && !IsExtern) { diagnostics.Add(ErrorCode.ERR_ConcreteMissingBody, location, this); } @@ -273,17 +273,19 @@ internal override int CalculateLocalSyntaxOffset(int position, SyntaxTree tree) TextSpan span; // local/lambda/closure defined within the body of the constructor: - if (tree == bodySyntaxReferenceOpt?.SyntaxTree) + ConstructorDeclarationSyntax ctorSyntax = GetSyntax(); + if (tree == ctorSyntax.SyntaxTree) { - span = bodySyntaxReferenceOpt.Span; - if (span.Contains(position)) + if (ctorSyntax.Body?.Span.Contains(position) == true) + { + return position - ctorSyntax.Body.Span.Start; + } + else if (ctorSyntax.ExpressionBody?.Span.Contains(position) == true) { - return position - span.Start; + return position - ctorSyntax.ExpressionBody.Span.Start; } } - var ctorSyntax = GetSyntax(); - // closure in ctor initializer lifting its parameter(s) spans the constructor declaration: if (position == ctorSyntax.SpanStart) { diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceCustomEventAccessorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceCustomEventAccessorSymbol.cs index f2fd6d1a0174b..4670b9d5e9e0c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceCustomEventAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceCustomEventAccessorSymbol.cs @@ -29,7 +29,6 @@ internal SourceCustomEventAccessorSymbol( DiagnosticBag diagnostics) : base(@event, syntax.GetReference(), - ((SyntaxNode)syntax.Body ?? syntax.ExpressionBody)?.GetReference(), ImmutableArray.Create(syntax.Keyword.GetLocation())) { Debug.Assert(syntax != null); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs index d366dd690ba85..e925c543186da 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs @@ -24,7 +24,7 @@ protected SourceDelegateMethodSymbol( DelegateDeclarationSyntax syntax, MethodKind methodKind, DeclarationModifiers declarationModifiers) - : base(delegateType, syntax.GetReference(), bodySyntaxReferenceOpt: null, location: syntax.Identifier.GetLocation()) + : base(delegateType, syntax.GetReference(), location: syntax.Identifier.GetLocation()) { _returnType = returnType; this.MakeFlags(methodKind, declarationModifiers, _returnType.SpecialType == SpecialType.System_Void, isExtensionMethod: false); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDestructorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDestructorSymbol.cs index 0704a5035f57a..48a28c6223c42 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDestructorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDestructorSymbol.cs @@ -16,7 +16,7 @@ internal SourceDestructorSymbol( SourceMemberContainerTypeSymbol containingType, DestructorDeclarationSyntax syntax, DiagnosticBag diagnostics) : - base(containingType, syntax.GetReference(), syntax.Body?.GetReference() ?? syntax.ExpressionBody?.GetReference() , syntax.Identifier.GetLocation()) + base(containingType, syntax.GetReference(), syntax.Identifier.GetLocation()) { const MethodKind methodKind = MethodKind.Destructor; Location location = this.Locations[0]; @@ -41,7 +41,7 @@ internal SourceDestructorSymbol( } } - if (!modifierErrors && bodySyntaxReferenceOpt == null && !IsExtern) + if (!modifierErrors && !hasBlockBody && !_isExpressionBodied && !IsExtern) { diagnostics.Add(ErrorCode.ERR_ConcreteMissingBody, location, this); } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventAccessorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventAccessorSymbol.cs index 54f16f592c17d..595682874ac29 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventAccessorSymbol.cs @@ -22,9 +22,8 @@ internal abstract class SourceEventAccessorSymbol : SourceMemberMethodSymbol public SourceEventAccessorSymbol( SourceEventSymbol @event, SyntaxReference syntaxReference, - SyntaxReference blockSyntaxReference, ImmutableArray locations) - : base(@event.containingType, syntaxReference, blockSyntaxReference, locations) + : base(@event.containingType, syntaxReference, locations) { _event = @event; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs index 53dcc84201198..4f458db27166e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs @@ -165,6 +165,8 @@ internal static LocalSymbol MakeLocalSymbolWithEnclosingContext( { Debug.Assert( nodeToBind.Kind() == SyntaxKind.CasePatternSwitchLabel || + nodeToBind.Kind() == SyntaxKind.ThisConstructorInitializer || + nodeToBind.Kind() == SyntaxKind.BaseConstructorInitializer || nodeToBind.Kind() == SyntaxKind.ArgumentList && nodeToBind.Parent is ConstructorInitializerSyntax || nodeToBind.Kind() == SyntaxKind.VariableDeclarator && new[] { SyntaxKind.LocalDeclarationStatement, SyntaxKind.ForStatement, SyntaxKind.UsingStatement, SyntaxKind.FixedStatement }. @@ -543,7 +545,7 @@ private void MakeConstantTuple(LocalSymbol inProgress, BoundExpression boundInit if (boundInitValue == null) { var inProgressBinder = new LocalInProgressBinder(this, this._initializerBinder); - boundInitValue = inProgressBinder.BindVariableOrAutoPropInitializer(_initializer, this.RefKind, type, diagnostics); + boundInitValue = inProgressBinder.BindVariableOrAutoPropInitializerValue(_initializer, this.RefKind, type, diagnostics); } value = ConstantValueUtils.GetAndValidateConstantValue(boundInitValue, this, type, initValueNodeLocation, diagnostics); @@ -717,6 +719,8 @@ public LocalSymbolWithEnclosingContext( { Debug.Assert( nodeToBind.Kind() == SyntaxKind.CasePatternSwitchLabel || + nodeToBind.Kind() == SyntaxKind.ThisConstructorInitializer || + nodeToBind.Kind() == SyntaxKind.BaseConstructorInitializer || nodeToBind.Kind() == SyntaxKind.ArgumentList && nodeToBind.Parent is ConstructorInitializerSyntax || nodeToBind.Kind() == SyntaxKind.VariableDeclarator || nodeToBind is ExpressionSyntax); @@ -736,9 +740,14 @@ protected override TypeSymbol InferTypeOfVarVariable(DiagnosticBag diagnostics) { switch (_nodeToBind.Kind()) { + case SyntaxKind.ThisConstructorInitializer: + case SyntaxKind.BaseConstructorInitializer: + var initializer = (ConstructorInitializerSyntax)_nodeToBind; + _nodeBinder.BindConstructorInitializer(initializer, diagnostics); + break; case SyntaxKind.ArgumentList: var invocation = (ConstructorInitializerSyntax)_nodeToBind.Parent; - _nodeBinder.BindConstructorInitializer(invocation.ArgumentList, (MethodSymbol)ContainingSymbol, diagnostics); + _nodeBinder.BindConstructorInitializer(invocation, diagnostics); break; case SyntaxKind.CasePatternSwitchLabel: _nodeBinder.BindPatternSwitchLabelForInference((CasePatternSwitchLabelSyntax)_nodeToBind, diagnostics); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs index 091903a62f1df..9c90e2c957dc8 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs @@ -169,9 +169,6 @@ public void EnsureMetadataVirtual() // some symbols may not have a syntax (e.g. lambdas, synthesized event accessors) protected readonly SyntaxReference syntaxReferenceOpt; - // some symbols may not have a body syntax (e.g. abstract and extern members, primary constructors, synthesized event accessors, etc.) - protected readonly SyntaxReference bodySyntaxReferenceOpt; - protected ImmutableArray locations; protected string lazyDocComment; @@ -191,19 +188,18 @@ internal ImmutableArray SetDiagnostics(ImmutableArray ne return _cachedDiagnostics; } - protected SourceMemberMethodSymbol(NamedTypeSymbol containingType, SyntaxReference syntaxReferenceOpt, SyntaxReference bodySyntaxReferenceOpt, Location location) - : this(containingType, syntaxReferenceOpt, bodySyntaxReferenceOpt, ImmutableArray.Create(location)) + protected SourceMemberMethodSymbol(NamedTypeSymbol containingType, SyntaxReference syntaxReferenceOpt, Location location) + : this(containingType, syntaxReferenceOpt, ImmutableArray.Create(location)) { } - protected SourceMemberMethodSymbol(NamedTypeSymbol containingType, SyntaxReference syntaxReferenceOpt, SyntaxReference bodySyntaxReferenceOpt, ImmutableArray locations) + protected SourceMemberMethodSymbol(NamedTypeSymbol containingType, SyntaxReference syntaxReferenceOpt, ImmutableArray locations) { Debug.Assert((object)containingType != null); Debug.Assert(!locations.IsEmpty); _containingType = containingType; this.syntaxReferenceOpt = syntaxReferenceOpt; - this.bodySyntaxReferenceOpt = bodySyntaxReferenceOpt; this.locations = locations; } @@ -537,12 +533,89 @@ internal sealed override Cci.CallingConvention CallingConvention #region Syntax - internal SyntaxNode BodySyntax + internal (BlockSyntax, ArrowExpressionClauseSyntax) Bodies { get { - return (this.bodySyntaxReferenceOpt == null) ? null : this.bodySyntaxReferenceOpt.GetSyntax(); + switch (SyntaxNode) + { + case BaseMethodDeclarationSyntax method: + return (method.Body, method.ExpressionBody); + + case AccessorDeclarationSyntax accessor: + return (accessor.Body, accessor.ExpressionBody); + + case ArrowExpressionClauseSyntax arrowExpression: + Debug.Assert(arrowExpression.Parent.Kind() == SyntaxKind.PropertyDeclaration || + arrowExpression.Parent.Kind() == SyntaxKind.IndexerDeclaration || + this is SynthesizedClosureMethod); + return (null, arrowExpression); + + case BlockSyntax block: + Debug.Assert(this is SynthesizedClosureMethod); + return (block, null); + + default: + return (null, null); + } + } + } + + internal Binder TryGetInMethodBinder(BinderFactory binderFactoryOpt = null) + { + CSharpSyntaxNode contextNode = null; + + CSharpSyntaxNode syntaxNode = this.SyntaxNode; + + switch (syntaxNode) + { + case ConstructorDeclarationSyntax constructor: + contextNode = constructor.Initializer ?? (CSharpSyntaxNode)constructor.Body ?? constructor.ExpressionBody; + break; + + case BaseMethodDeclarationSyntax method: + contextNode = (CSharpSyntaxNode)method.Body ?? method.ExpressionBody; + break; + + case AccessorDeclarationSyntax accessor: + contextNode = (CSharpSyntaxNode)accessor.Body ?? accessor.ExpressionBody; + break; + + case ArrowExpressionClauseSyntax arrowExpression: + Debug.Assert(arrowExpression.Parent.Kind() == SyntaxKind.PropertyDeclaration || + arrowExpression.Parent.Kind() == SyntaxKind.IndexerDeclaration); + contextNode = arrowExpression; + break; + } + + if (contextNode == null) + { + return null; } + + Binder result = (binderFactoryOpt ?? this.DeclaringCompilation.GetBinderFactory(contextNode.SyntaxTree)).GetBinder(contextNode); +#if DEBUG + Binder current = result; + do + { + if (current is InMethodBinder) + { + break; + } + + current = current.Next; + } + while (current != null); + + Debug.Assert(current is InMethodBinder); +#endif + return result; + } + + internal ExecutableCodeBinder TryGetBodyBinder(BinderFactory binderFactoryOpt = null, BinderFlags additionalFlags = BinderFlags.None) + { + Binder inMethod = TryGetInMethodBinder(binderFactoryOpt); + return inMethod == null ? null : new ExecutableCodeBinder(SyntaxNode, this, inMethod.WithAdditionalFlags(additionalFlags)); } internal SyntaxReference SyntaxRef @@ -1604,14 +1677,28 @@ protected void CheckModifiersForBody(Location location, DiagnosticBag diagnostic internal override int CalculateLocalSyntaxOffset(int localPosition, SyntaxTree localTree) { - // Method without body doesn't declare locals. - Debug.Assert(this.BodySyntax != null); - Debug.Assert(this.BodySyntax.SyntaxTree == localTree); + Debug.Assert(this.SyntaxNode.SyntaxTree == localTree); + + (BlockSyntax blockBody, ArrowExpressionClauseSyntax expressionBody) = Bodies; + CSharpSyntaxNode bodySyntax = null; // All locals are declared within the body of the method. - Debug.Assert(this.BodySyntax.Span.Contains(localPosition)); + if (blockBody?.Span.Contains(localPosition) == true) + { + bodySyntax = blockBody; + } + else if (expressionBody?.Span.Contains(localPosition) == true) + { + bodySyntax = expressionBody; + } + else + { + // Method without body doesn't declare locals. + Debug.Assert(bodySyntax != null); + return -1; + } - return localPosition - this.BodySyntax.SpanStart; + return localPosition - bodySyntax.SpanStart; } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs index 1f9546182584c..87ba503b4b4a1 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs @@ -20,6 +20,7 @@ internal sealed class SourceOrdinaryMethodSymbol : SourceMemberMethodSymbol private readonly TypeSymbol _explicitInterfaceType; private readonly string _name; private readonly bool _isExpressionBodied; + private readonly bool _hasAnyBody; private readonly RefKind _refKind; private ImmutableArray _lazyExplicitInterfaceImplementations; @@ -72,8 +73,6 @@ private SourceOrdinaryMethodSymbol( DiagnosticBag diagnostics) : base(containingType, syntax.GetReference(), - // Prefer a block body if both exist - syntax.Body?.GetReference() ?? syntax.ExpressionBody?.GetReference(), location) { _name = name; @@ -110,9 +109,10 @@ private SourceOrdinaryMethodSymbol( bool hasBlockBody = syntax.Body != null; _isExpressionBodied = !hasBlockBody && syntax.ExpressionBody != null; + _hasAnyBody = hasBlockBody || _isExpressionBodied; _refKind = syntax.ReturnType.GetRefKind(); - if (hasBlockBody || _isExpressionBodied) + if (_hasAnyBody) { CheckModifiersForBody(location, diagnostics); } @@ -367,7 +367,7 @@ private void MethodChecks(MethodDeclarationSyntax syntax, Binder withTypeParamsB } } - CheckModifiers(location, diagnostics); + CheckModifiers(_hasAnyBody, location, diagnostics); foreach (var typeParameter in _typeParameters) { @@ -598,8 +598,7 @@ internal bool IsPartialDefinition { get { - return this.IsPartial - && this.BodySyntax == null; + return this.IsPartial && !_hasAnyBody; } } @@ -610,8 +609,7 @@ internal bool IsPartialImplementation { get { - return this.IsPartial - && this.BodySyntax != null; + return this.IsPartial && _hasAnyBody; } } @@ -874,7 +872,7 @@ private ImmutableArray MakeTypeParameters(MethodDeclaration return result.ToImmutableAndFree(); } - private void CheckModifiers(Location location, DiagnosticBag diagnostics) + private void CheckModifiers(bool hasBody, Location location, DiagnosticBag diagnostics) { const DeclarationModifiers partialMethodInvalidModifierMask = (DeclarationModifiers.AccessibilityMask & ~DeclarationModifiers.Private) | DeclarationModifiers.Virtual | @@ -953,11 +951,11 @@ private void CheckModifiers(Location location, DiagnosticBag diagnostics) // '{0}' is a new virtual member in sealed class '{1}' diagnostics.Add(ErrorCode.ERR_NewVirtualInSealed, location, this, ContainingType); } - else if (bodySyntaxReferenceOpt == null && IsAsync) + else if (!hasBody && IsAsync) { diagnostics.Add(ErrorCode.ERR_BadAsyncLacksBody, location); } - else if (bodySyntaxReferenceOpt == null && !IsExtern && !IsAbstract && !IsPartial && !IsExpressionBodied) + else if (!hasBody && !IsExtern && !IsAbstract && !IsPartial && !IsExpressionBodied) { diagnostics.Add(ErrorCode.ERR_ConcreteMissingBody, location, this); } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs index 27048319f7f3c..059a65bda598e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs @@ -144,7 +144,7 @@ private SourcePropertyAccessorSymbol( Location location, ArrowExpressionClauseSyntax syntax, DiagnosticBag diagnostics) : - base(containingType, syntax.GetReference(), syntax.GetReference(), location) + base(containingType, syntax.GetReference(), location) { _property = property; _explicitInterfaceImplementations = explicitInterfaceImplementations; @@ -169,7 +169,7 @@ private SourcePropertyAccessorSymbol( diagnostics.Add(info, location); } - this.CheckModifiers(location, isAutoPropertyOrExpressionBodied: true, diagnostics: diagnostics); + this.CheckModifiers(location, hasBody: true, isAutoPropertyOrExpressionBodied: true, diagnostics: diagnostics); if (this.IsOverride) { @@ -197,7 +197,6 @@ private SourcePropertyAccessorSymbol( DiagnosticBag diagnostics) : base(containingType, syntax.GetReference(), - ((SyntaxNode)syntax.Body ?? syntax.ExpressionBody)?.GetReference(), location) { _property = property; @@ -239,7 +238,7 @@ private SourcePropertyAccessorSymbol( if (!modifierErrors) { - this.CheckModifiers(location, isAutoPropertyAccessor, diagnostics); + this.CheckModifiers(location, hasBody || hasExpressionBody, isAutoPropertyAccessor, diagnostics); } if (this.IsOverride) @@ -435,7 +434,7 @@ private DeclarationModifiers MakeModifiers(AccessorDeclarationSyntax syntax, Loc return mods; } - private void CheckModifiers(Location location, bool isAutoPropertyOrExpressionBodied, DiagnosticBag diagnostics) + private void CheckModifiers(Location location, bool hasBody, bool isAutoPropertyOrExpressionBodied, DiagnosticBag diagnostics) { // Check accessibility against the accessibility declared on the accessor not the property. var localAccessibility = this.LocalAccessibility; @@ -450,7 +449,7 @@ private void CheckModifiers(Location location, bool isAutoPropertyOrExpressionBo // '{0}' is a new virtual member in sealed class '{1}' diagnostics.Add(ErrorCode.ERR_NewVirtualInSealed, location, this, ContainingType); } - else if (bodySyntaxReferenceOpt == null && !IsExtern && !IsAbstract && !isAutoPropertyOrExpressionBodied) + else if (!hasBody && !IsExtern && !IsAbstract && !isAutoPropertyOrExpressionBodied) { diagnostics.Add(ErrorCode.ERR_ConcreteMissingBody, location, this); } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedConversionSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedConversionSymbol.cs index 9c91e533f5799..c99140a605bdb 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedConversionSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedConversionSymbol.cs @@ -23,8 +23,7 @@ public static SourceUserDefinedConversionSymbol CreateUserDefinedConversionSymbo : WellKnownMemberNames.ExplicitConversionName; return new SourceUserDefinedConversionSymbol( - containingType, name, location, syntax, diagnostics, - syntax.Body == null && syntax.ExpressionBody != null); + containingType, name, location, syntax, diagnostics); } // NOTE: no need to call WithUnsafeRegionIfNecessary, since the signature @@ -35,18 +34,14 @@ private SourceUserDefinedConversionSymbol( string name, Location location, ConversionOperatorDeclarationSyntax syntax, - DiagnosticBag diagnostics, - bool isExpressionBodied) : + DiagnosticBag diagnostics) : base( MethodKind.Conversion, name, containingType, location, - syntax.GetReference(), - syntax.Body?.GetReference() ?? syntax.ExpressionBody?.GetReference(), - syntax.Modifiers, - diagnostics, - isExpressionBodied) + syntax, + diagnostics) { CheckForBlockAndExpressionBody( syntax.Body, syntax.ExpressionBody, syntax, diagnostics); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbol.cs index c7002900f0113..3dfed8f0d1d62 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbol.cs @@ -37,11 +37,8 @@ private SourceUserDefinedOperatorSymbol( name, containingType, location, - syntax.GetReference(), - syntax.Body?.GetReference() ?? syntax.ExpressionBody?.GetReference(), - syntax.Modifiers, - diagnostics, - isExpressionBodied) + syntax, + diagnostics) { CheckForBlockAndExpressionBody( syntax.Body, syntax.ExpressionBody, syntax, diagnostics); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs index f3d759498f95a..a4e8e1763dc82 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs @@ -23,15 +23,12 @@ protected SourceUserDefinedOperatorSymbolBase( string name, SourceMemberContainerTypeSymbol containingType, Location location, - SyntaxReference syntaxReference, - SyntaxReference bodySyntaxReference, - SyntaxTokenList modifiersSyntax, - DiagnosticBag diagnostics, - bool isExpressionBodied) : - base(containingType, syntaxReference, bodySyntaxReference, location) + BaseMethodDeclarationSyntax syntax, + DiagnosticBag diagnostics) : + base(containingType, syntax.GetReference(), location) { _name = name; - _isExpressionBodied = isExpressionBodied; + _isExpressionBodied = syntax.Body == null && syntax.ExpressionBody != null; var defaultAccess = DeclarationModifiers.Private; var allowedModifiers = @@ -42,7 +39,7 @@ protected SourceUserDefinedOperatorSymbolBase( bool modifierErrors; var declarationModifiers = ModifierUtils.MakeAndCheckNontypeMemberModifiers( - modifiersSyntax, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors); + syntax.Modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors); this.CheckUnsafeModifier(declarationModifiers, diagnostics); @@ -80,11 +77,12 @@ protected SourceUserDefinedOperatorSymbolBase( // SPEC: its operator body consists of a semicolon. For expression-bodied // SPEC: operators, the body is an expression. For all other operators, // SPEC: the operator body consists of a block... - if (bodySyntaxReference != null && IsExtern) + bool hasBody = syntax.HasAnyBody(); + if (hasBody && IsExtern) { diagnostics.Add(ErrorCode.ERR_ExternHasBody, location, this); } - else if (bodySyntaxReference == null && !IsExtern && !IsAbstract && !IsPartial) + else if (!hasBody && !IsExtern && !IsAbstract && !IsPartial) { // Do not report that the body is missing if the operator is marked as // partial or abstract; we will already have given an error for that so diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedFieldLikeEventAccessorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedFieldLikeEventAccessorSymbol.cs index c1ec557b3e3c0..03a92699ddd32 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedFieldLikeEventAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedFieldLikeEventAccessorSymbol.cs @@ -24,7 +24,7 @@ internal sealed class SynthesizedFieldLikeEventAccessorSymbol : SourceEventAcces private readonly string _name; internal SynthesizedFieldLikeEventAccessorSymbol(SourceFieldLikeEventSymbol @event, bool isAdder) - : base(@event, null, null, @event.Locations) + : base(@event, null, @event.Locations) { this.MakeFlags( isAdder ? MethodKind.EventAdd : MethodKind.EventRemove, diff --git a/src/Compilers/CSharp/Portable/Syntax/LambdaUtilities.cs b/src/Compilers/CSharp/Portable/Syntax/LambdaUtilities.cs index 2d9bdda7fe61d..dc3d7dee3d24c 100644 --- a/src/Compilers/CSharp/Portable/Syntax/LambdaUtilities.cs +++ b/src/Compilers/CSharp/Portable/Syntax/LambdaUtilities.cs @@ -395,11 +395,6 @@ internal static bool IsClosureScope(SyntaxNode node) case SyntaxKind.ConstructorDeclaration: return true; - // With the introduction of pattern-matching, many nodes now contain top-level - // expressions that may introduce pattern variables. - case SyntaxKind.EqualsValueClause: - return true; - // Due to pattern-matching, any statement that contains an expression may introduce a scope. case SyntaxKind.DoStatement: case SyntaxKind.ExpressionStatement: @@ -424,6 +419,13 @@ internal static bool IsClosureScope(SyntaxNode node) return true; default: + // With the introduction of pattern-matching, many nodes now contain top-level + // expressions that may introduce pattern variables. + if (node.Parent.IsKind(SyntaxKind.EqualsValueClause)) + { + return true; + } + break; } diff --git a/src/Compilers/CSharp/Portable/Syntax/LookupPosition.cs b/src/Compilers/CSharp/Portable/Syntax/LookupPosition.cs index bdc0d0c7f4c05..656adf5390084 100644 --- a/src/Compilers/CSharp/Portable/Syntax/LookupPosition.cs +++ b/src/Compilers/CSharp/Portable/Syntax/LookupPosition.cs @@ -179,7 +179,8 @@ internal static bool IsInConstructorParameterScope(int position, ConstructorDecl return initializerOpt == null ? IsInBody(position, constructorDecl) : - IsBetweenTokens(position, initializerOpt.ColonToken, constructorDecl.Body?.CloseBraceToken ?? constructorDecl.SemicolonToken); + IsBetweenTokens(position, initializerOpt.ColonToken, + constructorDecl.SemicolonToken.Kind() == SyntaxKind.None ? constructorDecl.Body.CloseBraceToken : constructorDecl.SemicolonToken); } internal static bool IsInMethodTypeParameterScope(int position, MethodDeclarationSyntax methodDecl) diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs index 87e2f775ac1b3..39271f1adbdec 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs @@ -473,5 +473,10 @@ public static bool IsReservedTupleElementName(string elementName) { return TupleTypeSymbol.IsElementNameReserved(elementName) != -1; } + + internal static bool HasAnyBody(this BaseMethodDeclarationSyntax declaration) + { + return (declaration.Body ?? (SyntaxNode)declaration.ExpressionBody) != null; + } } } diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxNodeExtensions.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxNodeExtensions.cs index e5d65c9153164..a985cb47577f5 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxNodeExtensions.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxNodeExtensions.cs @@ -70,6 +70,9 @@ syntax is StatementSyntax || kind == SyntaxKind.EqualsValueClause || kind == SyntaxKind.Attribute || kind == SyntaxKind.ArgumentList || + kind == SyntaxKind.BaseConstructorInitializer || + kind == SyntaxKind.ThisConstructorInitializer || + kind == SyntaxKind.ConstructorDeclaration || kind == SyntaxKind.ArrowExpressionClause || IsValidScopeDesignator(syntax as ExpressionSyntax); } diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index f9794a5e199d2..fb9b330090ecd 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -8285,16 +8285,6 @@ Pokud chcete odstranit toto varování, můžete místo toho použít /reference Syntaxe 'var (...)' jako l-hodnota je vyhrazená. - - Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - Deklarace proměnné out a pattern nejsou v inicializátorech konstruktoru, pole nebo vlastnosti povolené. - - - - Out variable and pattern variable declarations are not allowed within a query clause. - Deklarace proměnné out a pattern nejsou v klauzuli dotazu povolené. - - { or ; or => expected Očekávaly se znaky { nebo ; nebo =>. @@ -8720,6 +8710,11 @@ Pokud chcete odstranit toto varování, můžete místo toho použít /reference "Invalid rank specifier: expected ']' + + declaration of expression variables in member initializers and queries + declaration of expression variables in member initializers and queries + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index c6fa44e3cdd7c..c9fca6b839447 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -8285,16 +8285,6 @@ Um die Warnung zu beheben, können Sie stattdessen /reference verwenden (Einbett Die Syntax "var (...)" als lvalue ist reserviert. - - Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - Deklarationen von out-Variablen und Mustervariablen sind in Konstruktor-, Feld- oder Eigenschafteninitialisierern unzulässig. - - - - Out variable and pattern variable declarations are not allowed within a query clause. - Deklarationen von out-Variablen und Mustervariablen sind in einer Abfrageklausel unzulässig. - - { or ; or => expected { oder ; oder => erwartet @@ -8720,6 +8710,11 @@ Um die Warnung zu beheben, können Sie stattdessen /reference verwenden (Einbett "Invalid rank specifier: expected ']' + + declaration of expression variables in member initializers and queries + declaration of expression variables in member initializers and queries + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index fa15c2550416c..323eb0a0f74c2 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -8285,16 +8285,6 @@ Para eliminar la advertencia puede usar /reference (establezca la propiedad Embe La sintaxis 'var (...)' como valor L está reservada. - - Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - La variable out y las declaraciones de variable de patrón no se permiten en los inicializadores de constructor, de campo o de propiedades. - - - - Out variable and pattern variable declarations are not allowed within a query clause. - No se permiten declaraciones de variable out y variable pattern dentro de una cláusula de consulta. - - { or ; or => expected Se esperaba { o ; o =>. @@ -8720,6 +8710,11 @@ Para eliminar la advertencia puede usar /reference (establezca la propiedad Embe "Invalid rank specifier: expected ']' + + declaration of expression variables in member initializers and queries + declaration of expression variables in member initializers and queries + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 2e4532269cf99..7aae6c3f368ac 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -8285,16 +8285,6 @@ Pour supprimer l'avertissement, vous pouvez utiliser la commande /reference (dé La syntaxe 'var (...)' en tant que lvalue est réservée. - - Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - Les déclarations de variable de sortie et de variable de modèle ne sont pas autorisées dans les initialiseurs de constructeur, les initialiseurs de champ ou les initialiseurs de propriété. - - - - Out variable and pattern variable declarations are not allowed within a query clause. - Les déclarations de variable de sortie et de variable de modèle ne sont pas autorisées dans une clause de requête. - - { or ; or => expected { ou ; ou => attendu @@ -8720,6 +8710,11 @@ Pour supprimer l'avertissement, vous pouvez utiliser la commande /reference (dé "Invalid rank specifier: expected ']' + + declaration of expression variables in member initializers and queries + declaration of expression variables in member initializers and queries + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index b302970886a0d..08165afcacdf0 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -8285,16 +8285,6 @@ Per rimuovere l'avviso, è invece possibile usare /reference (impostare la propr La sintassi 'var (...)' come lvalue è riservata. - - Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - Le dichiarazioni di variabile out e pattern non sono consentite all'interno di inizializzatori di costruttori, inizializzatori di campi o inizializzatori di proprietà. - - - - Out variable and pattern variable declarations are not allowed within a query clause. - Le dichiarazioni di variabile out e pattern non sono consentite all'interno di una clausola di query. - - { or ; or => expected È previsto { oppure ; o => @@ -8720,6 +8710,11 @@ Per rimuovere l'avviso, è invece possibile usare /reference (impostare la propr "Invalid rank specifier: expected ']' + + declaration of expression variables in member initializers and queries + declaration of expression variables in member initializers and queries + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 358c4610cebd1..be450c64561ab 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -8285,16 +8285,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ 左辺値としての構文 'var (...)' は予約されています。 - - Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - out 変数およびパターン変数の宣言は、コンストラクター初期化子、フィールド初期化子、プロパティ初期化子内では許可されていません。 - - - - Out variable and pattern variable declarations are not allowed within a query clause. - Out 変数とパターン変数の宣言は、クエリ句内では許可されていません。 - - { or ; or => expected { or ; or => 必要 @@ -8720,6 +8710,11 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ "Invalid rank specifier: expected ']' + + declaration of expression variables in member initializers and queries + declaration of expression variables in member initializers and queries + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 0a37deed108b8..1a91d9a739409 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -8285,16 +8285,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ lvalue인 구문 'var (...)'가 예약되었습니다. - - Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - 출력 변수 또는 패턴 변수 선언은 생성자 이니셜라이저, 필드 이니셜라이저 또는 속성 이니셜라이저 내에서 사용할 수 없습니다. - - - - Out variable and pattern variable declarations are not allowed within a query clause. - 출력 변수 및 패턴 변수 선언은 쿼리 절 내에서 사용할 수 없습니다. - - { or ; or => expected { 또는 ; 또는 => 필요 @@ -8720,6 +8710,11 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ "Invalid rank specifier: expected ']' + + declaration of expression variables in member initializers and queries + declaration of expression variables in member initializers and queries + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 3418708dbad82..683fd84a12a7b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -8285,16 +8285,6 @@ Aby usunąć ostrzeżenie, możesz zamiast tego użyć opcji /reference (ustaw w Składnia „var (...)“ jako wartość lvalue jest zastrzeżona. - - Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - W inicjatorach konstruktora, pola i właściwości nie można używać deklaracji zmiennej „out” ani zmiennej wzorca. - - - - Out variable and pattern variable declarations are not allowed within a query clause. - Deklaracje zmiennej wychodzącej i zmiennej wzorca nie są dozwolone w obrębie klauzuli zapytania. - - { or ; or => expected Oczekiwano symbolu { lub ; lub => @@ -8720,6 +8710,11 @@ Aby usunąć ostrzeżenie, możesz zamiast tego użyć opcji /reference (ustaw w "Invalid rank specifier: expected ']' + + declaration of expression variables in member initializers and queries + declaration of expression variables in member initializers and queries + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index f0d1ff2aee591..2df7b86114c88 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -8285,16 +8285,6 @@ Para incorporar informações de tipo de interoperabilidade para os dois assembl A sintaxe 'var (...)' como um lvalue está reservada. - - Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - As declarações de variável out ou padrão não são permitidas em inicializadores de construtor, inicializadores de campo ou inicializadores de propriedade. - - - - Out variable and pattern variable declarations are not allowed within a query clause. - As declarações da variável de saída e da variável padrão não são permitidas em uma cláusula de consulta. - - { or ; or => expected { ou ; ou => esperado @@ -8720,6 +8710,11 @@ Para incorporar informações de tipo de interoperabilidade para os dois assembl "Invalid rank specifier: expected ']' + + declaration of expression variables in member initializers and queries + declaration of expression variables in member initializers and queries + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 86761cb2f5a43..74bdadaad29c2 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -8285,16 +8285,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Синтаксис "var (...)" как lvalue зарезервирован. - - Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - Объявления исходящих переменных или переменных шаблонов запрещены в инициализаторах конструкторов, полей и свойств. - - - - Out variable and pattern variable declarations are not allowed within a query clause. - Объявления исходящих переменных и переменных шаблонов недопустимы в предложении запроса. - - { or ; or => expected Ожидается "{" или ";" или "=>" @@ -8720,6 +8710,11 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ "Invalid rank specifier: expected ']' + + declaration of expression variables in member initializers and queries + declaration of expression variables in member initializers and queries + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 9d605ea3f2535..a44eed1e37261 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -8285,16 +8285,6 @@ Uyarıyı kaldırmak için, /reference kullanabilirsiniz (Birlikte Çalışma T var (...)' söz dizimi, lvalue olarak ayrıldı. - - Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - Oluşturucu başlatıcıları, alan başlatıcıları veya özellik başlatıcıları içinde out ve pattern değişken bildirimlerine izin verilmez. - - - - Out variable and pattern variable declarations are not allowed within a query clause. - Sorgu yan tümcesi içinde out ve pattern değişken bildirimlerine izin verilmez. - - { or ; or => expected { or ; or => beklenen @@ -8720,6 +8710,11 @@ Uyarıyı kaldırmak için, /reference kullanabilirsiniz (Birlikte Çalışma T "Invalid rank specifier: expected ']' + + declaration of expression variables in member initializers and queries + declaration of expression variables in member initializers and queries + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index a78815c3c9458..c797a36890816 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -8285,16 +8285,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ 语法 "var (...)" 作为左值保留。 - - Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - 不允许在构造函数、字段、属性初始值设定项中进行 out 变量和 pattern 变量声明。 - - - - Out variable and pattern variable declarations are not allowed within a query clause. - 查询子句中不允许使用 out 变量和 pattern 变量 - - { or ; or => expected { or ; or => 预期的 @@ -8720,6 +8710,11 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ "Invalid rank specifier: expected ']' + + declaration of expression variables in member initializers and queries + declaration of expression variables in member initializers and queries + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index c912e4aa4ac75..a1d246cab60e5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -8285,16 +8285,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ 已保留作為左值的語法 'var (...)'。 - - Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - 建構函式、欄位或屬性初始設定式中不允許 out 變數或 pattern 變數宣告。 - - - - Out variable and pattern variable declarations are not allowed within a query clause. - 查詢子句內不允許 out 變數與模式變數宣告。 - - { or ; or => expected 需要 { 或 ; 或 => @@ -8720,6 +8710,11 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ "Invalid rank specifier: expected ']' + + declaration of expression variables in member initializers and queries + declaration of expression variables in member initializers and queries + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenLocalFunctionTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenLocalFunctionTests.cs index 2e38655cdf351..cdef210f6a289 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenLocalFunctionTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenLocalFunctionTests.cs @@ -76,6 +76,7 @@ public class E } [Fact] + [CompilerTrait(CompilerFeature.IOperation)] [WorkItem(24647, "https://github.com/dotnet/roslyn/issues/24647")] public void Repro24647() { @@ -92,7 +93,21 @@ static void Main(string[] args) var creation = tree.GetRoot().DescendantNodes().OfType().Single(); var operation = model.GetOperation(creation); - Assert.Null(operation); // we didn't bind the expression body, but should. See issue https://github.com/dotnet/roslyn/issues/24650 + Assert.NotNull(operation); + + comp.VerifyOperationTree(creation, expectedOperationTree: +@" +IObjectCreationOperation (Constructor: System.Object..ctor()) (OperationKind.ObjectCreation, Type: System.Object, IsInvalid) (Syntax: 'new object()') + Arguments(0) + Initializer: + null +"); + + Assert.Equal(OperationKind.ExpressionStatement, operation.Parent.Kind); + Assert.Equal(OperationKind.Block, operation.Parent.Parent.Kind); + // We didn't bind the expression body, but should. See issue https://github.com/dotnet/roslyn/issues/24650 + // The block from the previous assert, should have a parent + Assert.Null(operation.Parent.Parent.Parent); var info = model.GetTypeInfo(creation); Assert.Equal("System.Object", info.Type.ToTestDisplayString()); diff --git a/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs b/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs index cb721bd39fd55..8303899ae52b5 100644 --- a/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs +++ b/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs @@ -7430,15 +7430,9 @@ int G(out int x) var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); c.VerifyDiagnostics( - // (9,19): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // int F = G(out var v1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var v1").WithLocation(9, 19), // (9,13): error CS0236: A field initializer cannot reference the non-static field, method, or property 'C.G(out int)' // int F = G(out var v1); Diagnostic(ErrorCode.ERR_FieldInitRefNonstatic, "G").WithArguments("C.G(out int)").WithLocation(9, 13), - // (13,16): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : base(out var v3) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var v3").WithLocation(13, 16), // (13,7): error CS1729: 'object' does not contain a constructor that takes 1 arguments // : base(out var v3) Diagnostic(ErrorCode.ERR_BadCtorArgCount, "base").WithArguments("object", "1").WithLocation(13, 7)); @@ -7488,6 +7482,725 @@ public void SyntaxOffset_OutVarInMethod() "); } + [Fact] + public void SyntaxOffset_OutVarInInitializers_01() + { + var source = +@" +class C : A +{ + int x = G(out var x); + int y {get;} = G(out var y); + + C() : base(G(out var z)) + { + } + + static int G(out int x) + { + throw null; + } +} + +class A +{ + public A(int x) {} +} +"; + + var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); + c.VerifyPdb("C..ctor", @" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +"); + } + + [Fact] + public void SyntaxOffset_OutVarInInitializers_02() + { + var source = +@" +class C : A +{ + C() : base(G(out var x)) + { + int y = 1; + y++; + } + + static int G(out int x) + { + throw null; + } +} + +class A +{ + public A(int x) {} +} +"; + + var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); + c.VerifyPdb("C..ctor", @" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +"); + } + + [Fact] + public void SyntaxOffset_OutVarInInitializers_03() + { + var source = +@" +class C : A +{ + C() : base(G(out var x)) + => G(out var y); + + static int G(out int x) + { + throw null; + } +} + +class A +{ + public A(int x) {} +} +"; + + var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); + c.VerifyPdb("C..ctor", @" + + + + + + + + + + + + + + + + + + + + + + + + + + + + +"); + } + + [Fact] + public void SyntaxOffset_OutVarInInitializers_04() + { + var source = +@" +class C +{ + static int G(out int x) + { + throw null; + } + static int F(System.Func x) + { + throw null; + } + + C() + { + } + +#line 2000 + int y1 = G(out var z) + F(() => z); +} +"; + + var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); + + c.VerifyPdb("C..ctor", @" + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + +"); + + c.VerifyPdb("C+<>c__DisplayClass2_0.<.ctor>b__0", @" + + + + + + + + + + + + + + + +"); + } + + [Fact] + public void SyntaxOffset_OutVarInInitializers_05() + { + var source = +@" +class C +{ + static int G(out int x) + { + throw null; + } + static int F(System.Func x) + { + throw null; + } + +#line 2000 + int y1 { get; } = G(out var z) + F(() => z); +} +"; + + var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); + + c.VerifyPdb("C..ctor", @" + + + + + + + + + + + + + 5 + + + + + + + + + + + + + + +"); + + c.VerifyPdb("C+<>c__DisplayClass5_0.<.ctor>b__0", @" + + + + + + + + + + + + + + + +"); + } + + [Fact] + public void SyntaxOffset_OutVarInInitializers_06() + { + var source = +@" +class C +{ + static int G(out int x) + { + throw null; + } + static int F(System.Func x) + { + throw null; + } + +#line 2000 + int y1 = G(out var z) + F(() => z), y2 = G(out var u) + F(() => u); +} +"; + + var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); + + c.VerifyPdb("C..ctor", @" + + + + + + + + + + + + + + 4 + + + + + + + + + + + + + + + + + + + +"); + + c.VerifyPdb("C+<>c__DisplayClass4_0.<.ctor>b__0", @" + + + + + + + + + + + + + + + +"); + + c.VerifyPdb("C+<>c__DisplayClass4_1.<.ctor>b__1", @" + + + + + + + + + + + + + + + +"); + } + + [Fact] + public void SyntaxOffset_OutVarInInitializers_07() + { + var source = +@" +class C : A +{ +#line 2000 + C() : base(G(out var z)+ F(() => z)) + { + } + + static int G(out int x) + { + throw null; + } + static int F(System.Func x) + { + throw null; + } +} + +class A +{ + public A(int x) {} +} +"; + + var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); + c.VerifyPdb("C..ctor", @" + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + +"); + + c.VerifyPdb("C+<>c__DisplayClass0_0.<.ctor>b__0", @" + + + + + + + + + + + + + + + +"); + } + + [Fact] + public void SyntaxOffset_OutVarInQuery_01() + { + var source = +@" +using System.Linq; + +class C +{ + C() + { + var q = from a in new [] {1} + where + G(out var x1) > a + select a; + } + + static int G(out int x) + { + throw null; + } +} +"; + + var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); + c.VerifyPdb("C..ctor", @" + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + +"); + + c.VerifyPdb("C+<>c.<.ctor>b__0_0", @" + + + + + + + + + + + + + + + + + + + + + +"); + } + + [Fact] + public void SyntaxOffset_OutVarInQuery_02() + { + var source = +@" +using System.Linq; + +class C +{ + C() +#line 2000 + { + var q = from a in new [] {1} + where + G(out var x1) > F(() => x1) + select a; + } + + static int G(out int x) + { + throw null; + } + static int F(System.Func x) + { + throw null; + } +} +"; + + var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); + c.VerifyPdb("C..ctor", @" + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + +"); + + c.VerifyPdb("C+<>c.<.ctor>b__0_0", @" + + + + + + + + + + + + + + + + + + + + +"); + + c.VerifyPdb("C+<>c__DisplayClass0_0.<.ctor>b__1", @" + + + + + + + + + + + + + + + +"); + } + #endregion [Fact, WorkItem(4370, "https://github.com/dotnet/roslyn/issues/4370")] diff --git a/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.cs b/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.cs index 2e686c57f2e00..09ca64bf045d2 100644 --- a/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.cs @@ -2323,5 +2323,90 @@ private static void TestFieldReferenceAnalyzer_InConstructorInitializer_Core(Com compilation.VerifyAnalyzerDiagnostics(analyzers, null, null, true, Diagnostic("ID", "Field").WithArguments("Field", "0").WithLocation(11, 29)); } + + [Fact, WorkItem(25167, "https://github.com/dotnet/roslyn/issues/25167")] + public void TestMethodBodyOperationAnalyzer() + { + string source = @" +internal class A +{ + public void M() { } +}"; + + var tree = CSharpSyntaxTree.ParseText(source); + var compilation = CreateCompilationWithMscorlib45(new[] { tree }); + compilation.VerifyDiagnostics(); + + var analyzers = new DiagnosticAnalyzer[] { new MethodOrConstructorBodyOperationAnalyzer() }; + compilation.VerifyAnalyzerDiagnostics(analyzers, + expected: Diagnostic("ID", squiggledText: "public void M() { }").WithArguments("M").WithLocation(4, 5)); + } + + [Fact, WorkItem(25167, "https://github.com/dotnet/roslyn/issues/25167")] + public void TestMethodBodyOperationAnalyzer_WithParameterInitializers() + { + string source = @" +internal class A +{ + public void M(int p = 0) { } +}"; + + var tree = CSharpSyntaxTree.ParseText(source); + var compilation = CreateCompilationWithMscorlib45(new[] { tree }); + compilation.VerifyDiagnostics(); + + var analyzers = new DiagnosticAnalyzer[] { new MethodOrConstructorBodyOperationAnalyzer() }; + compilation.VerifyAnalyzerDiagnostics(analyzers, + expected: Diagnostic("ID", squiggledText: "public void M(int p = 0) { }").WithArguments("M").WithLocation(4, 5)); + } + + [Fact, WorkItem(25167, "https://github.com/dotnet/roslyn/issues/25167")] + public void TestMethodBodyOperationAnalyzer_WithExpressionAndMethodBody() + { + string source = @" +internal class A +{ + public int M() { return 0; } => 0; +}"; + + var tree = CSharpSyntaxTree.ParseText(source); + var compilation = CreateCompilationWithMscorlib45(new[] { tree }); + compilation.VerifyDiagnostics( + // (4,5): error CS8057: Block bodies and expression bodies cannot both be provided. + // public int M() { return 0; } => 0; + Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, "public int M() { return 0; } => 0;").WithLocation(4, 5)); + + var analyzers = new DiagnosticAnalyzer[] { new MethodOrConstructorBodyOperationAnalyzer() }; + compilation.VerifyAnalyzerDiagnostics(analyzers, + expected: Diagnostic("ID", squiggledText: "public int M() { return 0; } => 0;").WithArguments("M").WithLocation(4, 5)); + } + + [Fact, WorkItem(25167, "https://github.com/dotnet/roslyn/issues/25167")] + public void TestConstructorBodyOperationAnalyzer() + { + string source = @" +internal class Base +{ + protected Base(int i) { } +} + +internal class Derived : Base +{ + private const int Field = 0; + + public Derived() : base(Field) { } +}"; + + var tree = CSharpSyntaxTree.ParseText(source); + var compilation = CreateCompilationWithMscorlib45(new[] { tree }); + compilation.VerifyDiagnostics(); + + var analyzers = new DiagnosticAnalyzer[] { new MethodOrConstructorBodyOperationAnalyzer() }; + compilation.VerifyAnalyzerDiagnostics(analyzers, + expected: new[] { + Diagnostic("ID", squiggledText: "protected Base(int i) { }").WithArguments(".ctor").WithLocation(4, 5), + Diagnostic("ID", squiggledText: "public Derived() : base(Field) { }").WithArguments(".ctor").WithLocation(11, 5) + }); + } } } diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IConstructorBodyOperation.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IConstructorBodyOperation.cs new file mode 100644 index 0000000000000..49d2f5c508336 --- /dev/null +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IConstructorBodyOperation.cs @@ -0,0 +1,285 @@ +// 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 System.Linq; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests +{ + [CompilerTrait(CompilerFeature.IOperation)] + public partial class IOperationTests : SemanticModelTestBase + { + [Fact] + public void ConstructorBody_01() + { + string source = @" +class C +{ + public C() +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics( + // file.cs(4,15): error CS1002: ; expected + // public C() + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(4, 15), + // file.cs(4,12): error CS0501: 'C.C()' must declare a body because it is not marked abstract, extern, or partial + // public C() + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "C").WithArguments("C.C()").WithLocation(4, 12) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + Assert.Null(model.GetOperation(node1)); + } + + [Fact] + public void ConstructorBody_02() + { + string source = @" +class C +{ + public C() : base() +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics( + // (4,24): error CS1002: ; expected + // public C() : base() + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(4, 24), + // (4,12): error CS0501: 'C.C()' must declare a body because it is not marked abstract, extern, or partial + // public C() : base() + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "C").WithArguments("C.C()").WithLocation(4, 12) + ); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: +@" +IConstructorBodyOperation (OperationKind.ConstructorBodyOperation, Type: null, IsInvalid) (Syntax: 'public C() : base() +') + Initializer: + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid, IsImplicit) (Syntax: ': base()') + Expression: + IInvocationOperation ( System.Object..ctor()) (OperationKind.Invocation, Type: System.Void, IsInvalid) (Syntax: ': base()') + Instance Receiver: + IInstanceReferenceOperation (OperationKind.InstanceReference, Type: System.Object, IsInvalid, IsImplicit) (Syntax: ': base()') + Arguments(0) + BlockBody: + null + ExpressionBody: + null +"); + } + + [Fact] + public void ConstructorBody_03() + { + string source = @" +class C +{ + public C() : base() + { throw null; } +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: +@" +IConstructorBodyOperation (OperationKind.ConstructorBodyOperation, Type: null) (Syntax: 'public C() ... row null; }') + Initializer: + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: ': base()') + Expression: + IInvocationOperation ( System.Object..ctor()) (OperationKind.Invocation, Type: System.Void) (Syntax: ': base()') + Instance Receiver: + IInstanceReferenceOperation (OperationKind.InstanceReference, Type: System.Object, IsImplicit) (Syntax: ': base()') + Arguments(0) + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ throw null; }') + IThrowOperation (OperationKind.Throw, Type: null) (Syntax: 'throw null;') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null') + ExpressionBody: + null +"); + } + + [Fact] + public void ConstructorBody_04() + { + string source = @" +class C +{ + public C() : base() + => throw null; +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: +@" +IConstructorBodyOperation (OperationKind.ConstructorBodyOperation, Type: null) (Syntax: 'public C() ... throw null;') + Initializer: + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: ': base()') + Expression: + IInvocationOperation ( System.Object..ctor()) (OperationKind.Invocation, Type: System.Void) (Syntax: ': base()') + Instance Receiver: + IInstanceReferenceOperation (OperationKind.InstanceReference, Type: System.Object, IsImplicit) (Syntax: ': base()') + Arguments(0) + BlockBody: + null + ExpressionBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '=> throw null') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: 'throw null') + Expression: + IThrowOperation (OperationKind.Throw, Type: null) (Syntax: 'throw null') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null') +"); + } + + [Fact] + public void ConstructorBody_05() + { + string source = @" +class C +{ + public C() + { throw null; } +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: +@" +IConstructorBodyOperation (OperationKind.ConstructorBodyOperation, Type: null) (Syntax: 'public C() ... row null; }') + Initializer: + null + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ throw null; }') + IThrowOperation (OperationKind.Throw, Type: null) (Syntax: 'throw null;') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null') + ExpressionBody: + null +"); + } + + [Fact] + public void ConstructorBody_06() + { + string source = @" +class C +{ + public C() + => throw null; +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: +@" +IConstructorBodyOperation (OperationKind.ConstructorBodyOperation, Type: null) (Syntax: 'public C() ... throw null;') + Initializer: + null + BlockBody: + null + ExpressionBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '=> throw null') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: 'throw null') + Expression: + IThrowOperation (OperationKind.Throw, Type: null) (Syntax: 'throw null') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null') +"); + } + + [Fact] + public void ConstructorBody_07() + { + string source = @" +class C +{ + public C() + { throw null; } + => throw null; +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics( + // (4,5): error CS8057: Block bodies and expression bodies cannot both be provided. + // public C() + Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, @"public C() + { throw null; } + => throw null;").WithLocation(4, 5) + ); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: +@" +IConstructorBodyOperation (OperationKind.ConstructorBodyOperation, Type: null, IsInvalid) (Syntax: 'public C() ... throw null;') + Initializer: + null + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '{ throw null; }') + IThrowOperation (OperationKind.Throw, Type: null, IsInvalid) (Syntax: 'throw null;') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null, IsInvalid) (Syntax: 'null') + ExpressionBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '=> throw null') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid, IsImplicit) (Syntax: 'throw null') + Expression: + IThrowOperation (OperationKind.Throw, Type: null, IsInvalid) (Syntax: 'throw null') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null, IsInvalid) (Syntax: 'null') +"); + } + + [Fact] + public void ConstructorBody_08() + { + string source = @" +class C +{ + public C(); +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics( + // file.cs(4,12): error CS0501: 'C.C()' must declare a body because it is not marked abstract, extern, or partial + // public C(); + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "C").WithArguments("C.C()").WithLocation(4, 12) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + Assert.Null(model.GetOperation(node1)); + } + } +} diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IIsPatternExpression.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IIsPatternExpression.cs index a1767c2a6eefd..bcf0c4631dfa7 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IIsPatternExpression.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IIsPatternExpression.cs @@ -551,19 +551,15 @@ class C } "; string expectedOperationTree = @" -IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean, IsInvalid) (Syntax: 'o is int x') +IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean) (Syntax: 'o is int x') Expression: IFieldReferenceOperation: System.Object C.o (Static) (OperationKind.FieldReference, Type: System.Object) (Syntax: 'o') Instance Receiver: null Pattern: - IDeclarationPatternOperation (Declared Symbol: System.Int32 x) (OperationKind.DeclarationPattern, Type: null, IsInvalid) (Syntax: 'int x') + IDeclarationPatternOperation (Declared Symbol: System.Int32 x) (OperationKind.DeclarationPattern, Type: null) (Syntax: 'int x') "; - var expectedDiagnostics = new DiagnosticDescription[] { - // CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // private readonly bool b = /**/o is int x/**/ && x >= 5; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x").WithLocation(5, 46) - }; + var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } @@ -586,17 +582,13 @@ public C (bool b) } "; string expectedOperationTree = @" -IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean, IsInvalid) (Syntax: 'o is int x') +IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean) (Syntax: 'o is int x') Expression: IParameterReferenceOperation: o (OperationKind.ParameterReference, Type: System.Object) (Syntax: 'o') Pattern: - IDeclarationPatternOperation (Declared Symbol: System.Int32 x) (OperationKind.DeclarationPattern, Type: null, IsInvalid) (Syntax: 'int x') + IDeclarationPatternOperation (Declared Symbol: System.Int32 x) (OperationKind.DeclarationPattern, Type: null) (Syntax: 'int x') "; - var expectedDiagnostics = new DiagnosticDescription[] { - // CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // this (/**/o is int x/**/ && x >= 5) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x").WithLocation(5, 30) - }; + var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IMethodBodyOperation.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IMethodBodyOperation.cs new file mode 100644 index 0000000000000..c2f53c67961a0 --- /dev/null +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IMethodBodyOperation.cs @@ -0,0 +1,671 @@ +// 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 System.Linq; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests +{ + [CompilerTrait(CompilerFeature.IOperation)] + public partial class IOperationTests : SemanticModelTestBase + { + [Fact] + public void RegularMethodBody_01() + { + string source = @" +abstract class C +{ + public abstract void M(); +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + Assert.Null(model.GetOperation(node1)); + } + + [Fact] + public void RegularMethodBody_02() + { + string source = @" +class C +{ + public void M() + { throw null; } +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: +@" +IMethodBodyOperation (OperationKind.MethodBodyOperation, Type: null) (Syntax: 'public void ... row null; }') + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ throw null; }') + IThrowOperation (OperationKind.Throw, Type: null) (Syntax: 'throw null;') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null') + ExpressionBody: + null +"); + } + + [Fact] + public void RegularMethodBody_03() + { + string source = @" +class C +{ + public void M() + => throw null; +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: +@" +IMethodBodyOperation (OperationKind.MethodBodyOperation, Type: null) (Syntax: 'public void ... throw null;') + BlockBody: + null + ExpressionBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '=> throw null') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: 'throw null') + Expression: + IThrowOperation (OperationKind.Throw, Type: null) (Syntax: 'throw null') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null') +"); + } + + [Fact] + public void RegularMethodBody_04() + { + string source = @" +class C +{ + public void M() + { throw null; } + => throw null; +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics( + // (4,5): error CS8057: Block bodies and expression bodies cannot both be provided. + // public void M() + Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, @"public void M() + { throw null; } + => throw null;").WithLocation(4, 5) + ); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: +@" +IMethodBodyOperation (OperationKind.MethodBodyOperation, Type: null, IsInvalid) (Syntax: 'public void ... throw null;') + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '{ throw null; }') + IThrowOperation (OperationKind.Throw, Type: null, IsInvalid) (Syntax: 'throw null;') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null, IsInvalid) (Syntax: 'null') + ExpressionBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '=> throw null') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid, IsImplicit) (Syntax: 'throw null') + Expression: + IThrowOperation (OperationKind.Throw, Type: null, IsInvalid) (Syntax: 'throw null') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null, IsInvalid) (Syntax: 'null') +"); + } + + [Fact] + public void OperatorBody_01() + { + string source = @" +abstract class C +{ + public static C operator ! (C x); +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics( + // (4,30): error CS0501: 'C.operator !(C)' must declare a body because it is not marked abstract, extern, or partial + // public static C operator ! (C x); + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "!").WithArguments("C.operator !(C)").WithLocation(4, 30) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + Assert.Null(model.GetOperation(node1)); + } + + [Fact] + public void OperatorMethodBody_02() + { + string source = @" +class C +{ + public static C operator ! (C x) + { throw null; } +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: +@" +IMethodBodyOperation (OperationKind.MethodBodyOperation, Type: null) (Syntax: 'public stat ... row null; }') + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ throw null; }') + IThrowOperation (OperationKind.Throw, Type: null) (Syntax: 'throw null;') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null') + ExpressionBody: + null +"); + } + + [Fact] + public void OperatorMethodBody_03() + { + string source = @" +class C +{ + public static C operator ! (C x) + => throw null; +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: +@" +IMethodBodyOperation (OperationKind.MethodBodyOperation, Type: null) (Syntax: 'public stat ... throw null;') + BlockBody: + null + ExpressionBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '=> throw null') + IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: 'throw null') + ReturnedValue: + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: C, IsImplicit) (Syntax: 'throw null') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Operand: + IThrowOperation (OperationKind.Throw, Type: null) (Syntax: 'throw null') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null') +"); + } + + [Fact] + public void OperatorMethodBody_04() + { + string source = @" +class C +{ + public static C operator ! (C x) + { throw null; } + => throw null; +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics( + // (4,5): error CS8057: Block bodies and expression bodies cannot both be provided. + // public static C operator ! (C x) + Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, @"public static C operator ! (C x) + { throw null; } + => throw null;").WithLocation(4, 5) + ); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: +@" +IMethodBodyOperation (OperationKind.MethodBodyOperation, Type: null, IsInvalid) (Syntax: 'public stat ... throw null;') + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '{ throw null; }') + IThrowOperation (OperationKind.Throw, Type: null, IsInvalid) (Syntax: 'throw null;') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null, IsInvalid) (Syntax: 'null') + ExpressionBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '=> throw null') + IReturnOperation (OperationKind.Return, Type: null, IsInvalid, IsImplicit) (Syntax: 'throw null') + ReturnedValue: + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: C, IsInvalid, IsImplicit) (Syntax: 'throw null') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Operand: + IThrowOperation (OperationKind.Throw, Type: null, IsInvalid) (Syntax: 'throw null') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null, IsInvalid) (Syntax: 'null') +"); + } + + [Fact] + public void ConversionBody_01() + { + string source = @" +abstract class C +{ + public static implicit operator int(C x); +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics( + // (4,37): error CS0501: 'C.implicit operator int(C)' must declare a body because it is not marked abstract, extern, or partial + // public static implicit operator int(C x); + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "int").WithArguments("C.implicit operator int(C)").WithLocation(4, 37) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + Assert.Null(model.GetOperation(node1)); + } + + [Fact] + public void ConversionMethodBody_02() + { + string source = @" +class C +{ + public static implicit operator int(C x) + { throw null; } +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: +@" +IMethodBodyOperation (OperationKind.MethodBodyOperation, Type: null) (Syntax: 'public stat ... row null; }') + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ throw null; }') + IThrowOperation (OperationKind.Throw, Type: null) (Syntax: 'throw null;') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null') + ExpressionBody: + null +"); + } + + [Fact] + public void ConversionMethodBody_03() + { + string source = @" +class C +{ + public static implicit operator int(C x) + => throw null; +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: +@" +IMethodBodyOperation (OperationKind.MethodBodyOperation, Type: null) (Syntax: 'public stat ... throw null;') + BlockBody: + null + ExpressionBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '=> throw null') + IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: 'throw null') + ReturnedValue: + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int32, IsImplicit) (Syntax: 'throw null') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Operand: + IThrowOperation (OperationKind.Throw, Type: null) (Syntax: 'throw null') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null') +"); + } + + [Fact] + public void ConversionMethodBody_04() + { + string source = @" +class C +{ + public static implicit operator int(C x) + { throw null; } + => throw null; +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics( + // (4,5): error CS8057: Block bodies and expression bodies cannot both be provided. + // public static implicit operator int(C x) + Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, @"public static implicit operator int(C x) + { throw null; } + => throw null;").WithLocation(4, 5) + ); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: +@" +IMethodBodyOperation (OperationKind.MethodBodyOperation, Type: null, IsInvalid) (Syntax: 'public stat ... throw null;') + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '{ throw null; }') + IThrowOperation (OperationKind.Throw, Type: null, IsInvalid) (Syntax: 'throw null;') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null, IsInvalid) (Syntax: 'null') + ExpressionBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '=> throw null') + IReturnOperation (OperationKind.Return, Type: null, IsInvalid, IsImplicit) (Syntax: 'throw null') + ReturnedValue: + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int32, IsInvalid, IsImplicit) (Syntax: 'throw null') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Operand: + IThrowOperation (OperationKind.Throw, Type: null, IsInvalid) (Syntax: 'throw null') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null, IsInvalid) (Syntax: 'null') +"); + } + + [Fact] + public void DestructorBody_01() + { + string source = @" +abstract class C +{ + ~C(); +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics( + // (4,6): error CS0501: 'C.~C()' must declare a body because it is not marked abstract, extern, or partial + // ~C(); + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "C").WithArguments("C.~C()").WithLocation(4, 6) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + Assert.Null(model.GetOperation(node1)); + } + + [Fact] + public void DestructorBody_02() + { + string source = @" +class C +{ + ~C() + { throw null; } +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: +@" +IMethodBodyOperation (OperationKind.MethodBodyOperation, Type: null) (Syntax: '~C() ... row null; }') + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ throw null; }') + IThrowOperation (OperationKind.Throw, Type: null) (Syntax: 'throw null;') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null') + ExpressionBody: + null +"); + } + + [Fact] + public void DestructorBody_03() + { + string source = @" +class C +{ + ~C() + => throw null; +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: +@" +IMethodBodyOperation (OperationKind.MethodBodyOperation, Type: null) (Syntax: '~C() ... throw null;') + BlockBody: + null + ExpressionBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '=> throw null') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: 'throw null') + Expression: + IThrowOperation (OperationKind.Throw, Type: null) (Syntax: 'throw null') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null') +"); + } + + [Fact] + public void DestructorBody_04() + { + string source = @" +class C +{ + ~C() + { throw null; } + => throw null; +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics( + // (4,5): error CS8057: Block bodies and expression bodies cannot both be provided. + // ~C() + Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, @"~C() + { throw null; } + => throw null;").WithLocation(4, 5) + ); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: +@" +IMethodBodyOperation (OperationKind.MethodBodyOperation, Type: null, IsInvalid) (Syntax: '~C() ... throw null;') + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '{ throw null; }') + IThrowOperation (OperationKind.Throw, Type: null, IsInvalid) (Syntax: 'throw null;') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null, IsInvalid) (Syntax: 'null') + ExpressionBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '=> throw null') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid, IsImplicit) (Syntax: 'throw null') + Expression: + IThrowOperation (OperationKind.Throw, Type: null, IsInvalid) (Syntax: 'throw null') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null, IsInvalid) (Syntax: 'null') +"); + } + + [Fact] + public void AccessorBody_01() + { + string source = @" +abstract class C +{ + abstract protected int P { get; } +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + Assert.Null(model.GetOperation(node1)); + } + + [Fact] + public void AccessorBody_02() + { + string source = @" +class C +{ + int P + { + set + { throw null; } + } +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: +@" +IMethodBodyOperation (OperationKind.MethodBodyOperation, Type: null) (Syntax: 'set ... row null; }') + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ throw null; }') + IThrowOperation (OperationKind.Throw, Type: null) (Syntax: 'throw null;') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null') + ExpressionBody: + null +"); + } + + [Fact] + public void AccessorBody_03() + { + string source = @" +class C +{ + event System.Action E + { + add => throw null; + remove {throw null;} + } +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().First(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: +@" +IMethodBodyOperation (OperationKind.MethodBodyOperation, Type: null) (Syntax: 'add => throw null;') + BlockBody: + null + ExpressionBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '=> throw null') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: 'throw null') + Expression: + IThrowOperation (OperationKind.Throw, Type: null) (Syntax: 'throw null') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null') +"); + } + + [Fact] + public void AccessorBody_04() + { + string source = @" +class C +{ + event System.Action E + { + remove + { throw null; } + => throw null; + add { throw null;} + } +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics( + // (6,9): error CS8057: Block bodies and expression bodies cannot both be provided. + // remove + Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, @"remove + { throw null; } + => throw null;").WithLocation(6, 9) + ); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().First(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: +@" +IMethodBodyOperation (OperationKind.MethodBodyOperation, Type: null, IsInvalid) (Syntax: 'remove ... throw null;') + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '{ throw null; }') + IThrowOperation (OperationKind.Throw, Type: null, IsInvalid) (Syntax: 'throw null;') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null, IsInvalid) (Syntax: 'null') + ExpressionBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '=> throw null') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid, IsImplicit) (Syntax: 'throw null') + Expression: + IThrowOperation (OperationKind.Throw, Type: null, IsInvalid) (Syntax: 'throw null') + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null, IsInvalid) (Syntax: 'null') +"); + } + + [Fact] + public void AccessorBody_05() + { + string source = @" +abstract class C +{ + int P { get; } => throw null; +} +"; + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics( + // (4,5): error CS8057: Block bodies and expression bodies cannot both be provided. + // int P { get; } => throw null; + Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, "int P { get; } => throw null;").WithLocation(4, 5) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + Assert.Null(model.GetOperation(node1)); + } + } +} diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/FieldInitializerBindingTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/FieldInitializerBindingTests.cs index 01aeb1e71d33d..0b2dcd019e789 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/FieldInitializerBindingTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/FieldInitializerBindingTests.cs @@ -267,12 +267,12 @@ private static void CheckBoundInitializers(IEnumerable expe foreach (var expectedInitializer in expectedInitializers) { var boundInit = boundInitializers[i++]; - Assert.Equal(BoundKind.FieldInitializer, boundInit.Kind); + Assert.Equal(BoundKind.FieldEqualsValue, boundInit.Kind); - var boundFieldInit = (BoundFieldInitializer)boundInit; + var boundFieldInit = (BoundFieldEqualsValue)boundInit; - var initValueSyntax = boundFieldInit.InitialValue.Syntax; - Assert.Same(initValueSyntax, boundInit.Syntax); + var initValueSyntax = boundFieldInit.Value.Syntax; + Assert.Same(initValueSyntax.Parent, boundInit.Syntax); Assert.Equal(expectedInitializer.InitialValue, initValueSyntax.ToFullString()); var initValueLineNumber = syntaxTree.GetLineSpan(initValueSyntax.Span).StartLinePosition.Line; diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/OutVarTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/OutVarTests.cs index 2862ebf4304d3..d37c9795c1450 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/OutVarTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/OutVarTests.cs @@ -11,6 +11,7 @@ using Xunit; using Roslyn.Test.Utilities; using Roslyn.Utilities; +using Microsoft.CodeAnalysis.Diagnostics; namespace Microsoft.CodeAnalysis.CSharp.UnitTests { @@ -3183,36 +3184,15 @@ static bool TakeOutParam(object y, out int x) "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation.VerifyDiagnostics( - // (9,36): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : this(TakeOutParam(3, out int x3) && x3 > 0) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x3").WithLocation(9, 36), // (13,16): error CS0841: Cannot use local variable 'x4' before it is declared // : this(x4 && TakeOutParam(4, out int x4)) Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x4").WithArguments("x4").WithLocation(13, 16), - // (13,42): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : this(x4 && TakeOutParam(4, out int x4)) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(13, 42), - // (17,37): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : this(TakeOutParam(51, out int x5) && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(17, 37), - // (18,37): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // TakeOutParam(52, out int x5) && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(18, 37), // (18,41): error CS0128: A local variable named 'x5' is already defined in this scope // TakeOutParam(52, out int x5) && Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(18, 41), - // (23,36): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : this(TakeOutParam(6, out int x6) && x6 > 0, - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(23, 36), - // (24,36): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // TakeOutParam(6, out int x6) && x6 > 0) // 2 - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(24, 36), // (24,40): error CS0128: A local variable named 'x6' is already defined in this scope // TakeOutParam(6, out int x6) && x6 > 0) // 2 Diagnostic(ErrorCode.ERR_LocalDuplicate, "x6").WithArguments("x6").WithLocation(24, 40), - // (27,36): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : this(TakeOutParam(7, out int x7) && x7 > 0) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x7").WithLocation(27, 36), // (30,16): error CS0103: The name 'x7' does not exist in the current context // : this(x7, 2) Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(30, 16), @@ -3306,36 +3286,15 @@ public Y(params object[] x) {} "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation.VerifyDiagnostics( - // (9,36): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : base(TakeOutParam(3, out int x3) && x3 > 0) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x3").WithLocation(9, 36), // (13,16): error CS0841: Cannot use local variable 'x4' before it is declared // : base(x4 && TakeOutParam(4, out int x4)) Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x4").WithArguments("x4").WithLocation(13, 16), - // (13,42): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : base(x4 && TakeOutParam(4, out int x4)) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(13, 42), - // (17,37): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : base(TakeOutParam(51, out int x5) && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(17, 37), - // (18,37): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // TakeOutParam(52, out int x5) && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(18, 37), // (18,41): error CS0128: A local variable named 'x5' is already defined in this scope // TakeOutParam(52, out int x5) && Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(18, 41), - // (23,36): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : base(TakeOutParam(6, out int x6) && x6 > 0, - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(23, 36), - // (24,36): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // TakeOutParam(6, out int x6) && x6 > 0) // 2 - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(24, 36), // (24,40): error CS0128: A local variable named 'x6' is already defined in this scope // TakeOutParam(6, out int x6) && x6 > 0) // 2 Diagnostic(ErrorCode.ERR_LocalDuplicate, "x6").WithArguments("x6").WithLocation(24, 40), - // (27,36): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : base(TakeOutParam(7, out int x7) && x7 > 0) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x7").WithLocation(27, 36), // (30,16): error CS0103: The name 'x7' does not exist in the current context // : base(x7, 2) Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(30, 16), @@ -3387,34 +3346,42 @@ public static void Main() { new D(1); new D(10); - new D(1.2); + new D(12); } } class D { - public D(object o) : this(TakeOutParam(o, out int x) && x >= 5) + public D(int o) : this(TakeOutParam(o, out int x1) && x1 >= 5) { - Console.WriteLine(x); + Console.WriteLine(x1); } public D(bool b) { Console.WriteLine(b); } - static bool TakeOutParam(object y, out int x) + static bool TakeOutParam(int y, out int x) { - x = 123; + x = y; return true; } } "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); - compilation.VerifyDiagnostics( - // (15,27): error CS0103: The name 'x' does not exist in the current context - // Console.WriteLine(x); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x").WithArguments("x").WithLocation(15, 27), - // (13,51): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // public D(object o) : this(TakeOutParam(o, out int x) && x >= 5) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x").WithLocation(13, 51) - ); + CompileAndVerify(compilation, expectedOutput: +@"False +1 +True +10 +True +12 +").VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclaration(tree, "x1"); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); } [Fact] @@ -3428,19 +3395,19 @@ public static void Main() { new D(1); new D(10); - new D(1.2); + new D(12); } } class D : C { - public D(object o) : base(TakeOutParam(o, out int x) && x >= 5) + public D(int o) : base(TakeOutParam(o, out int x1) && x1 >= 5) { - Console.WriteLine(x); + Console.WriteLine(x1); } - static bool TakeOutParam(object y, out int x) + static bool TakeOutParam(int y, out int x) { - x = 123; + x = y; return true; } } @@ -3449,16 +3416,227 @@ class C { public C(bool b) { Console.WriteLine(b); } } +"; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + CompileAndVerify(compilation, expectedOutput: +@"False +1 +True +10 +True +12 +").VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclaration(tree, "x1"); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + } + + [Fact] + public void Scope_ConstructorInitializers_05() + { + var source = +@"using System; +class D +{ + public D(int o) : this(SpeculateHere) + { + } + + public D(bool b) { Console.WriteLine(b); } + + static bool TakeOutParam(int y, out int x) + { + x = y; + return true; + } +} +"; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + + ArgumentListSyntax arguments = SyntaxFactory.ParseArgumentList(@"(TakeOutParam(o, out int x1) && x1 >= 5)"); + var initializer = SyntaxFactory.ConstructorInitializer(SyntaxKind.ThisConstructorInitializer, arguments); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + bool success = model.TryGetSpeculativeSemanticModel(GetReferences(tree, "SpeculateHere").Single().SpanStart, initializer, out model); + Assert.True(success); + Assert.NotNull(model); + tree = initializer.SyntaxTree; + + var x1Decl = GetOutVarDeclaration(tree, "x1"); + var x1Ref = GetReference(tree, "x1"); + VerifyModelForOutVar(model, x1Decl, x1Ref); + } + + [Fact] + public void Scope_ConstructorInitializers_06() + { + var source = +@"using System; +class D : C +{ + public D(int o) : base(SpeculateHere) + { + } + + static bool TakeOutParam(int y, out int x) + { + x = y; + return true; + } +} + +class C +{ + public C(bool b) { Console.WriteLine(b); } +} +"; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + + ArgumentListSyntax arguments = SyntaxFactory.ParseArgumentList(@"(TakeOutParam(o, out int x1) && x1 >= 5)"); + var initializer = SyntaxFactory.ConstructorInitializer(SyntaxKind.BaseConstructorInitializer, arguments); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + bool success = model.TryGetSpeculativeSemanticModel(GetReferences(tree, "SpeculateHere").Single().SpanStart, initializer, out model); + Assert.True(success); + Assert.NotNull(model); + tree = initializer.SyntaxTree; + + var x1Decl = GetOutVarDeclaration(tree, "x1"); + var x1Ref = GetReference(tree, "x1"); + VerifyModelForOutVar(model, x1Decl, x1Ref); + } + + [Fact] + public void Scope_ConstructorInitializers_07() + { + var source = +@" +public class X : Y +{ + public static void Main() + { + } + + X(byte x3) + : base(TakeOutParam(3, out var x3)) + {} + + X(sbyte x) + : base(TakeOutParam(4, out var x4)) + { + int x4 = 1; + System.Console.WriteLine(x4); + } + + X(ushort x) + : base(TakeOutParam(51, out var x5)) + => Dummy(TakeOutParam(52, out var x5), x5); + + X(short x) + : base(out int x6, x6) + {} + + X(uint x) + : base(out var x7, x7) + {} + + X(int x) + : base(TakeOutParam(out int x8, x8)) + {} + + X(ulong x) + : base(TakeOutParam(out var x9, x9)) + {} + + bool Dummy(params object[] x) {return true;} + + static bool TakeOutParam(object y, out int x) + { + x = 123; + return true; + } + static bool TakeOutParam(out int x, int y) + { + x = 123; + return true; + } +} + +public class Y +{ + public Y(params object[] x) {} + public Y(out int x, int y) { x = y; } +} "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation.VerifyDiagnostics( - // (15,27): error CS0103: The name 'x' does not exist in the current context - // Console.WriteLine(x); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x").WithArguments("x").WithLocation(15, 27), - // (13,51): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // public D(object o) : base(TakeOutParam(o, out int x) && x >= 5) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x").WithLocation(13, 51) + // (9,40): error CS0136: A local or parameter named 'x3' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // : base(TakeOutParam(3, out var x3)) + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x3").WithArguments("x3").WithLocation(9, 40), + // (15,13): error CS0136: A local or parameter named 'x4' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // int x4 = 1; + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x4").WithArguments("x4").WithLocation(15, 13), + // (21,39): error CS0136: A local or parameter named 'x5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // => Dummy(TakeOutParam(52, out var x5), x5); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x5").WithArguments("x5").WithLocation(21, 39), + // (24,28): error CS0165: Use of unassigned local variable 'x6' + // : base(out int x6, x6) + Diagnostic(ErrorCode.ERR_UseDefViolation, "x6").WithArguments("x6").WithLocation(24, 28), + // (28,28): error CS8196: Reference to an implicitly-typed out variable 'x7' is not permitted in the same argument list. + // : base(out var x7, x7) + Diagnostic(ErrorCode.ERR_ImplicitlyTypedOutVariableUsedInTheSameArgumentList, "x7").WithArguments("x7").WithLocation(28, 28), + // (28,20): error CS1615: Argument 1 may not be passed with the 'out' keyword + // : base(out var x7, x7) + Diagnostic(ErrorCode.ERR_BadArgExtraRef, "var x7").WithArguments("1", "out").WithLocation(28, 20), + // (32,41): error CS0165: Use of unassigned local variable 'x8' + // : base(TakeOutParam(out int x8, x8)) + Diagnostic(ErrorCode.ERR_UseDefViolation, "x8").WithArguments("x8").WithLocation(32, 41), + // (36,41): error CS8196: Reference to an implicitly-typed out variable 'x9' is not permitted in the same argument list. + // : base(TakeOutParam(out var x9, x9)) + Diagnostic(ErrorCode.ERR_ImplicitlyTypedOutVariableUsedInTheSameArgumentList, "x9").WithArguments("x9").WithLocation(36, 41) ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl); + + var x4Decl = GetOutVarDeclarations(tree, "x4").Single(); + var x4Ref = GetReferences(tree, "x4").Single(); + VerifyModelForOutVar(model, x4Decl); + VerifyNotAnOutLocal(model, x4Ref); + + var x5Decl = GetOutVarDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").Single(); + Assert.Equal(2, x5Decl.Length); + VerifyModelForOutVar(model, x5Decl[0]); + VerifyModelForOutVar(model, x5Decl[1], x5Ref); + + var x6Decl = GetOutVarDeclarations(tree, "x6").Single(); + var x6Ref = GetReferences(tree, "x6").Single(); + VerifyModelForOutVarWithoutDataFlow(model, x6Decl, x6Ref); + + var x7Decl = GetOutVarDeclarations(tree, "x7").Single(); + var x7Ref = GetReferences(tree, "x7").Single(); + VerifyModelForOutVarWithoutDataFlow(model, x7Decl, x7Ref); + + var x8Decl = GetOutVarDeclarations(tree, "x8").Single(); + var x8Ref = GetReferences(tree, "x8").Single(); + VerifyModelForOutVarWithoutDataFlow(model, x8Decl, x8Ref); + + var x9Decl = GetOutVarDeclarations(tree, "x9").Single(); + var x9Ref = GetReferences(tree, "x9").Single(); + VerifyModelForOutVarWithoutDataFlow(model, x9Decl, x9Ref); } [Fact] @@ -4915,6 +5093,9 @@ public static void Main() bool Test72 = Dummy(x7, 2); void Test73() { Dummy(x7, 3); } + bool Test81 = TakeOutParam(8, out int x8), Test82 = x8 > 0; + bool Test91 = x9 > 0, Test92 = TakeOutParam(9, out int x9); + bool Dummy(params object[] x) {return true;} static bool TakeOutParam(object y, out int x) { @@ -4925,39 +5106,24 @@ static bool TakeOutParam(object y, out int x) "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation.VerifyDiagnostics( - // (8,38): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test3 = TakeOutParam(3, out int x3) && x3 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x3").WithLocation(8, 38), // (10,18): error CS0841: Cannot use local variable 'x4' before it is declared // bool Test4 = x4 && TakeOutParam(4, out int x4); Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x4").WithArguments("x4").WithLocation(10, 18), - // (10,44): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test4 = x4 && TakeOutParam(4, out int x4); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(10, 44), - // (12,39): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test5 = TakeOutParam(51, out int x5) && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(12, 39), - // (13,39): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // TakeOutParam(52, out int x5) && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(13, 39), // (13,43): error CS0128: A local variable named 'x5' is already defined in this scope // TakeOutParam(52, out int x5) && Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(13, 43), - // (16,39): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test61 = TakeOutParam(6, out int x6) && x6 > 0, Test62 = TakeOutParam(6, out int x6) && x6 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(16, 39), - // (16,87): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test61 = TakeOutParam(6, out int x6) && x6 > 0, Test62 = TakeOutParam(6, out int x6) && x6 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(16, 87), - // (18,39): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test71 = TakeOutParam(7, out int x7) && x7 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x7").WithLocation(18, 39), // (19,25): error CS0103: The name 'x7' does not exist in the current context // bool Test72 = Dummy(x7, 2); Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(19, 25), // (20,27): error CS0103: The name 'x7' does not exist in the current context // void Test73() { Dummy(x7, 3); } - Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(20, 27) + Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(20, 27), + // (22,57): error CS0103: The name 'x8' does not exist in the current context + // bool Test81 = TakeOutParam(8, out int x8), Test82 = x8 > 0; + Diagnostic(ErrorCode.ERR_NameNotInContext, "x8").WithArguments("x8").WithLocation(22, 57), + // (23,19): error CS0103: The name 'x9' does not exist in the current context + // bool Test91 = x9 > 0, Test92 = TakeOutParam(9, out int x9); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x9").WithArguments("x9").WithLocation(23, 19) ); var tree = compilation.SyntaxTrees.Single(); @@ -4990,8 +5156,19 @@ static bool TakeOutParam(object y, out int x) VerifyModelForOutVar(model, x7Decl, x7Ref[0]); VerifyNotInScope(model, x7Ref[1]); VerifyNotInScope(model, x7Ref[2]); + + var x8Decl = GetOutVarDeclarations(tree, "x8").Single(); + var x8Ref = GetReference(tree, "x8"); + VerifyModelForOutVar(model, x8Decl); + VerifyNotInScope(model, x8Ref); + + var x9Decl = GetOutVarDeclarations(tree, "x9").Single(); + var x9Ref = GetReference(tree, "x9"); + VerifyNotInScope(model, x9Ref); + VerifyModelForOutVar(model, x9Decl); } + [CompilerTrait(CompilerFeature.IOperation)] [Fact] public void Scope_FieldInitializers_02() { @@ -5027,15 +5204,6 @@ public static bool TakeOutParam(object y, out int x) // (6,13): error CS0841: Cannot use local variable 'x4' before it is declared // Test4 = x4 && TakeOutParam(4, out int x4) ? 1 : 0, Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x4").WithArguments("x4").WithLocation(6, 13), - // (6,39): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // Test4 = x4 && TakeOutParam(4, out int x4) ? 1 : 0, - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(6, 39), - // (8,34): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // Test5 = TakeOutParam(51, out int x5) && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(8, 34), - // (9,34): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // TakeOutParam(52, out int x5) && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(9, 34), // (9,38): error CS0128: A local variable named 'x5' is already defined in this scope // TakeOutParam(52, out int x5) && Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(9, 38), @@ -5044,30 +5212,18 @@ public static bool TakeOutParam(object y, out int x) Diagnostic(ErrorCode.ERR_NotConstantExpression, @"TakeOutParam(51, out int x5) && TakeOutParam(52, out int x5) && x5 > 0 ? 1 : 0").WithArguments("X.Test5").WithLocation(8, 13), - // (12,34): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // Test61 = TakeOutParam(6, out int x6) && x6 > 0 ? 1 : 0, Test62 = TakeOutParam(6, out int x6) && x6 > 0 ? 1 : 0, - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(12, 34), // (12,14): error CS0133: The expression being assigned to 'X.Test61' must be constant // Test61 = TakeOutParam(6, out int x6) && x6 > 0 ? 1 : 0, Test62 = TakeOutParam(6, out int x6) && x6 > 0 ? 1 : 0, Diagnostic(ErrorCode.ERR_NotConstantExpression, "TakeOutParam(6, out int x6) && x6 > 0 ? 1 : 0").WithArguments("X.Test61").WithLocation(12, 14), - // (12,90): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // Test61 = TakeOutParam(6, out int x6) && x6 > 0 ? 1 : 0, Test62 = TakeOutParam(6, out int x6) && x6 > 0 ? 1 : 0, - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(12, 90), // (12,70): error CS0133: The expression being assigned to 'X.Test62' must be constant // Test61 = TakeOutParam(6, out int x6) && x6 > 0 ? 1 : 0, Test62 = TakeOutParam(6, out int x6) && x6 > 0 ? 1 : 0, Diagnostic(ErrorCode.ERR_NotConstantExpression, "TakeOutParam(6, out int x6) && x6 > 0 ? 1 : 0").WithArguments("X.Test62").WithLocation(12, 70), - // (14,34): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // Test71 = TakeOutParam(7, out int x7) && x7 > 0 ? 1 : 0, - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x7").WithLocation(14, 34), // (14,14): error CS0133: The expression being assigned to 'X.Test71' must be constant // Test71 = TakeOutParam(7, out int x7) && x7 > 0 ? 1 : 0, Diagnostic(ErrorCode.ERR_NotConstantExpression, "TakeOutParam(7, out int x7) && x7 > 0 ? 1 : 0").WithArguments("X.Test71").WithLocation(14, 14), // (15,14): error CS0103: The name 'x7' does not exist in the current context // Test72 = x7, Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(15, 14), - // (4,33): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // Test3 = TakeOutParam(3, out int x3) ? x3 : 0, - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x3").WithLocation(4, 33), // (4,13): error CS0133: The expression being assigned to 'X.Test3' must be constant // Test3 = TakeOutParam(3, out int x3) ? x3 : 0, Diagnostic(ErrorCode.ERR_NotConstantExpression, "TakeOutParam(3, out int x3) ? x3 : 0").WithArguments("X.Test3").WithLocation(4, 13) @@ -5102,6 +5258,36 @@ public static bool TakeOutParam(object y, out int x) Assert.Equal(2, x7Ref.Length); VerifyModelForOutVar(model, x7Decl, x7Ref[0]); VerifyNotInScope(model, x7Ref[1]); + + var node = tree.GetRoot().DescendantNodes().OfType().First(); + + compilation.VerifyOperationTree(node, expectedOperationTree: +@" +IFieldInitializerOperation (Field: X.Test3) (OperationKind.FieldInitializer, Type: null, IsInvalid) (Syntax: '= TakeOutPa ... 3) ? x3 : 0') + Locals: Local_1: System.Int32 x3 + IConditionalOperation (OperationKind.Conditional, Type: System.Int32, IsInvalid) (Syntax: 'TakeOutPara ... 3) ? x3 : 0') + Condition: + IInvocationOperation (System.Boolean Test.TakeOutParam(System.Object y, out System.Int32 x)) (OperationKind.Invocation, Type: System.Boolean, IsInvalid) (Syntax: 'TakeOutPara ... out int x3)') + Instance Receiver: + null + Arguments(2): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: y) (OperationKind.Argument, Type: null, IsInvalid) (Syntax: '3') + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Object, IsInvalid, IsImplicit) (Syntax: '3') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Operand: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 3, IsInvalid) (Syntax: '3') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null, IsInvalid) (Syntax: 'out int x3') + IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32, IsInvalid) (Syntax: 'int x3') + ILocalReferenceOperation: x3 (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'x3') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + WhenTrue: + ILocalReferenceOperation: x3 (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'x3') + WhenFalse: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0, IsInvalid) (Syntax: '0') +"); } [Fact] @@ -5139,24 +5325,12 @@ static bool TakeOutParam(object y, out int x) "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation.VerifyDiagnostics( - // (8,44): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // const bool Test3 = TakeOutParam(3, out int x3) && x3 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x3").WithLocation(8, 44), // (8,24): error CS0133: The expression being assigned to 'X.Test3' must be constant // const bool Test3 = TakeOutParam(3, out int x3) && x3 > 0; Diagnostic(ErrorCode.ERR_NotConstantExpression, "TakeOutParam(3, out int x3) && x3 > 0").WithArguments("X.Test3").WithLocation(8, 24), // (10,24): error CS0841: Cannot use local variable 'x4' before it is declared // const bool Test4 = x4 && TakeOutParam(4, out int x4); Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x4").WithArguments("x4").WithLocation(10, 24), - // (10,50): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // const bool Test4 = x4 && TakeOutParam(4, out int x4); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(10, 50), - // (12,45): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // const bool Test5 = TakeOutParam(51, out int x5) && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(12, 45), - // (13,45): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // TakeOutParam(52, out int x5) && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(13, 45), // (13,49): error CS0128: A local variable named 'x5' is already defined in this scope // TakeOutParam(52, out int x5) && Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(13, 49), @@ -5165,21 +5339,12 @@ static bool TakeOutParam(object y, out int x) Diagnostic(ErrorCode.ERR_NotConstantExpression, @"TakeOutParam(51, out int x5) && TakeOutParam(52, out int x5) && x5 > 0").WithArguments("X.Test5").WithLocation(12, 24), - // (16,45): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // const bool Test61 = TakeOutParam(6, out int x6) && x6 > 0, Test62 = TakeOutParam(6, out int x6) && x6 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(16, 45), // (16,25): error CS0133: The expression being assigned to 'X.Test61' must be constant // const bool Test61 = TakeOutParam(6, out int x6) && x6 > 0, Test62 = TakeOutParam(6, out int x6) && x6 > 0; Diagnostic(ErrorCode.ERR_NotConstantExpression, "TakeOutParam(6, out int x6) && x6 > 0").WithArguments("X.Test61").WithLocation(16, 25), - // (16,93): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // const bool Test61 = TakeOutParam(6, out int x6) && x6 > 0, Test62 = TakeOutParam(6, out int x6) && x6 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(16, 93), // (16,73): error CS0133: The expression being assigned to 'X.Test62' must be constant // const bool Test61 = TakeOutParam(6, out int x6) && x6 > 0, Test62 = TakeOutParam(6, out int x6) && x6 > 0; Diagnostic(ErrorCode.ERR_NotConstantExpression, "TakeOutParam(6, out int x6) && x6 > 0").WithArguments("X.Test62").WithLocation(16, 73), - // (18,45): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // const bool Test71 = TakeOutParam(7, out int x7) && x7 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x7").WithLocation(18, 45), // (18,25): error CS0133: The expression being assigned to 'X.Test71' must be constant // const bool Test71 = TakeOutParam(7, out int x7) && x7 > 0; Diagnostic(ErrorCode.ERR_NotConstantExpression, "TakeOutParam(7, out int x7) && x7 > 0").WithArguments("X.Test71").WithLocation(18, 25), @@ -5223,6 +5388,106 @@ static bool TakeOutParam(object y, out int x) VerifyNotInScope(model, x7Ref[2]); } + [Fact] + public void Scope_FieldInitializers_04() + { + var source = +@" +class X : Y +{ + public static void Main() + { + } + + bool Test3 = TakeOutParam(out int x3, x3); + + bool Test4 = TakeOutParam(out var x4, x4); + + bool Test5 = TakeOutParam(out int x5, 5); + + X() + : this(x5) + { + System.Console.WriteLine(x5); + } + + X(object x) + : base(x5) + => System.Console.WriteLine(x5); + + static bool Test6 = TakeOutParam(out int x6, 6); + static X() + { + System.Console.WriteLine(x6); + } + + static bool TakeOutParam(out int x, int y) + { + x = 123; + return true; + } +} + +class Y +{ + public Y(object y) {} +} +"; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + compilation.VerifyDiagnostics( + // (8,43): error CS0165: Use of unassigned local variable 'x3' + // bool Test3 = TakeOutParam(out int x3, x3); + Diagnostic(ErrorCode.ERR_UseDefViolation, "x3").WithArguments("x3").WithLocation(8, 43), + // (10,43): error CS0165: Use of unassigned local variable 'x4' + // bool Test4 = TakeOutParam(out var x4, x4); + Diagnostic(ErrorCode.ERR_UseDefViolation, "x4").WithArguments("x4").WithLocation(10, 43), + // (10,43): error CS8196: Reference to an implicitly-typed out variable 'x4' is not permitted in the same argument list. + // bool Test4 = TakeOutParam(out var x4, x4); + Diagnostic(ErrorCode.ERR_ImplicitlyTypedOutVariableUsedInTheSameArgumentList, "x4").WithArguments("x4").WithLocation(10, 43), + // (15,12): error CS0103: The name 'x5' does not exist in the current context + // : this(x5) + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(15, 12), + // (17,34): error CS0103: The name 'x5' does not exist in the current context + // System.Console.WriteLine(x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(17, 34), + // (21,12): error CS0103: The name 'x5' does not exist in the current context + // : base(x5) + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(21, 12), + // (22,33): error CS0103: The name 'x5' does not exist in the current context + // => System.Console.WriteLine(x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(22, 33), + // (27,34): error CS0103: The name 'x6' does not exist in the current context + // System.Console.WriteLine(x6); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x6").WithArguments("x6").WithLocation(27, 34) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVarWithoutDataFlow(model, x3Decl, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").Single(); + var x4Ref = GetReferences(tree, "x4").Single(); + VerifyModelForOutVarWithoutDataFlow(model, x4Decl, x4Ref); + + var x5Decl = GetOutVarDeclarations(tree, "x5").Single(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(4, x5Ref.Length); + VerifyModelForOutVar(model, x5Decl); + VerifyNotInScope(model, x5Ref[0]); + VerifyNotInScope(model, x5Ref[1]); + VerifyNotInScope(model, x5Ref[2]); + VerifyNotInScope(model, x5Ref[3]); + + var x6Decl = GetOutVarDeclarations(tree, "x6").Single(); + var x6Ref = GetReferences(tree, "x6").Single(); + VerifyModelForOutVar(model, x6Decl); + VerifyNotInScope(model, x6Ref); + } + + [CompilerTrait(CompilerFeature.IOperation)] [Fact] public void FieldInitializers_01() { @@ -5251,16 +5516,53 @@ static bool TakeOutParam(int y, out int x) } "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); -#if ALLOW_IN_FIELD_INITIALIZERS CompileAndVerify(compilation, expectedOutput: @"1 True"); -#else - compilation.VerifyDiagnostics( - // (9,45): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. + + CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_2).VerifyDiagnostics( + // (9,45): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // static bool Test1 = TakeOutParam(1, out int x1) && Dummy(x1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x1").WithLocation(9, 45) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "int x1").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(9, 45) ); -#endif + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").Single(); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var node = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node, expectedOperationTree: +@" +IFieldInitializerOperation (Field: System.Boolean X.Test1) (OperationKind.FieldInitializer, Type: null) (Syntax: '= TakeOutPa ... & Dummy(x1)') + Locals: Local_1: System.Int32 x1 + IBinaryOperation (BinaryOperatorKind.And) (OperationKind.BinaryOperator, Type: System.Boolean) (Syntax: 'TakeOutPara ... & Dummy(x1)') + Left: + IInvocationOperation (System.Boolean X.TakeOutParam(System.Int32 y, out System.Int32 x)) (OperationKind.Invocation, Type: System.Boolean) (Syntax: 'TakeOutPara ... out int x1)') + Instance Receiver: + null + Arguments(2): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: y) (OperationKind.Argument, Type: null) (Syntax: '1') + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: 'out int x1') + IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32) (Syntax: 'int x1') + ILocalReferenceOperation: x1 (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x1') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Right: + IInvocationOperation (System.Boolean X.Dummy(System.Int32 x)) (OperationKind.Invocation, Type: System.Boolean) (Syntax: 'Dummy(x1)') + Instance Receiver: + null + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: 'x1') + ILocalReferenceOperation: x1 (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x1') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) +"); } [Fact] @@ -5292,16 +5594,8 @@ static bool TakeOutParam(int y, out int x) } "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); -#if ALLOW_IN_FIELD_INITIALIZERS CompileAndVerify(compilation, expectedOutput: @"1 True"); -#else - compilation.VerifyDiagnostics( - // (9,45): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // static bool Test1 = TakeOutParam(1, out int x1) && Dummy(() => x1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x1").WithLocation(9, 45) - ); -#endif } [Fact] @@ -5337,6 +5631,83 @@ static bool TakeOutParam(int y, out int x) True"); } + [Fact] + public void FieldInitializers_05() + { + var source = +@" +public class X +{ + public static void Main() + { + } + static bool a = false; + bool Test1 = a && TakeOutParam(3, out int x1) || x1 > 0; + static bool TakeOutParam(object y, out int x) + { + x = 123; + return true; + } +} +"; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + compilation.VerifyDiagnostics( + // (8,54): error CS0165: Use of unassigned local variable 'x1' + // bool Test1 = a && TakeOutParam(3, out int x1) || x1 > 0; + Diagnostic(ErrorCode.ERR_UseDefViolation, "x1").WithArguments("x1").WithLocation(8, 54) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").Single(); + VerifyModelForOutVar(model, x1Decl, x1Ref); + } + + [Fact] + public void FieldInitializers_06() + { + var source = +@" +public class X +{ + public static void Main() + { + System.Console.WriteLine(Test1); + } + + static int Test1 = TakeOutParam(1, out var x1) ? Test2(((System.Func)(() => x1++))(), ref x1) : -1; + + static int Test2(object a, ref int x) + { + System.Console.WriteLine(x); + x++; + return x; + } + + static bool TakeOutParam(int y, out int x) + { + x = y; + return true; + } +} +"; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + CompileAndVerify(compilation, expectedOutput: +@"2 +3"); + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclaration(tree, "x1"); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + Assert.Equal("System.Int32", ((LocalSymbol)compilation.GetSemanticModel(tree).GetDeclaredSymbol(GetVariableDesignation(x1Decl))).Type.ToTestDisplayString()); + } + [Fact] public void Scope_Fixed_01() { @@ -10387,6 +10758,7 @@ static bool TakeOutParam(T y, out T x) VerifyModelForOutVar(model, x1Decl[1], x1Ref[1]); } + [CompilerTrait(CompilerFeature.IOperation)] [Fact] public void Scope_ParameterDefault_01() { @@ -10493,6 +10865,35 @@ static bool TakeOutParam(int y, out int x) VerifyModelForOutVar(model, x7Decl, x7Ref[0]); VerifyNotInScope(model, x7Ref[1]); VerifyNotInScope(model, x7Ref[2]); + + var node = tree.GetRoot().DescendantNodes().OfType().First(); + + compilation.VerifyOperationTree(node, expectedOperationTree: +@" +IParameterInitializerOperation (Parameter: [System.Boolean p = default(System.Boolean)]) (OperationKind.ParameterInitializer, Type: null, IsInvalid) (Syntax: '= TakeOutPa ... ) && x3 > 0') + Locals: Local_1: System.Int32 x3 + IBinaryOperation (BinaryOperatorKind.And) (OperationKind.BinaryOperator, Type: System.Boolean, IsInvalid) (Syntax: 'TakeOutPara ... ) && x3 > 0') + Left: + IInvocationOperation (System.Boolean X.TakeOutParam(System.Int32 y, out System.Int32 x)) (OperationKind.Invocation, Type: System.Boolean, IsInvalid) (Syntax: 'TakeOutPara ... out int x3)') + Instance Receiver: + null + Arguments(2): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: y) (OperationKind.Argument, Type: null, IsInvalid) (Syntax: '3') + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 3, IsInvalid) (Syntax: '3') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null, IsInvalid) (Syntax: 'out int x3') + IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32, IsInvalid) (Syntax: 'int x3') + ILocalReferenceOperation: x3 (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'x3') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Right: + IBinaryOperation (BinaryOperatorKind.GreaterThan) (OperationKind.BinaryOperator, Type: System.Boolean, IsInvalid) (Syntax: 'x3 > 0') + Left: + ILocalReferenceOperation: x3 (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'x3') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0, IsInvalid) (Syntax: '0') +"); } [Fact] @@ -10639,33 +11040,12 @@ static bool TakeOutParam(int y, out int x) "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation.VerifyDiagnostics( - // (8,45): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test3 {get;} = TakeOutParam(3, out int x3) && x3 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x3").WithLocation(8, 45), // (10,25): error CS0841: Cannot use local variable 'x4' before it is declared // bool Test4 {get;} = x4 && TakeOutParam(4, out int x4); Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x4").WithArguments("x4").WithLocation(10, 25), - // (10,51): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test4 {get;} = x4 && TakeOutParam(4, out int x4); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(10, 51), - // (12,46): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test5 {get;} = TakeOutParam(51, out int x5) && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(12, 46), - // (13,39): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // TakeOutParam(52, out int x5) && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(13, 39), // (13,43): error CS0128: A local variable named 'x5' is already defined in this scope // TakeOutParam(52, out int x5) && Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(13, 43), - // (16,46): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test61 {get;} = TakeOutParam(6, out int x6) && x6 > 0; bool Test62 {get;} = TakeOutParam(6, out int x6) && x6 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(16, 46), - // (16,106): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test61 {get;} = TakeOutParam(6, out int x6) && x6 > 0; bool Test62 {get;} = TakeOutParam(6, out int x6) && x6 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(16, 106), - // (18,46): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test71 {get;} = TakeOutParam(7, out int x7) && x7 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x7").WithLocation(18, 46), // (19,32): error CS0103: The name 'x7' does not exist in the current context // bool Test72 {get;} = Dummy(x7, 2); Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(19, 32), @@ -10706,6 +11086,7 @@ static bool TakeOutParam(int y, out int x) VerifyNotInScope(model, x7Ref[2]); } + [CompilerTrait(CompilerFeature.IOperation)] [Fact] public void PropertyInitializers_01() { @@ -10734,16 +11115,46 @@ static bool TakeOutParam(int y, out int x) } "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); -#if ALLOW_IN_FIELD_INITIALIZERS CompileAndVerify(compilation, expectedOutput: @"1 True"); -#else - compilation.VerifyDiagnostics( - // (9,52): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. + + CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_2).VerifyDiagnostics( + // (9,52): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // static bool Test1 {get;} = TakeOutParam(1, out int x1) && Dummy(x1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x1").WithLocation(9, 52) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "int x1").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(9, 52) ); -#endif + var tree = compilation.SyntaxTrees.Single(); + var node = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node, expectedOperationTree: +@" +IPropertyInitializerOperation (Property: System.Boolean X.Test1 { get; }) (OperationKind.PropertyInitializer, Type: null) (Syntax: '= TakeOutPa ... & Dummy(x1)') + Locals: Local_1: System.Int32 x1 + IBinaryOperation (BinaryOperatorKind.And) (OperationKind.BinaryOperator, Type: System.Boolean) (Syntax: 'TakeOutPara ... & Dummy(x1)') + Left: + IInvocationOperation (System.Boolean X.TakeOutParam(System.Int32 y, out System.Int32 x)) (OperationKind.Invocation, Type: System.Boolean) (Syntax: 'TakeOutPara ... out int x1)') + Instance Receiver: + null + Arguments(2): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: y) (OperationKind.Argument, Type: null) (Syntax: '1') + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: 'out int x1') + IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32) (Syntax: 'int x1') + ILocalReferenceOperation: x1 (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x1') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Right: + IInvocationOperation (System.Boolean X.Dummy(System.Int32 x)) (OperationKind.Invocation, Type: System.Boolean) (Syntax: 'Dummy(x1)') + Instance Receiver: + null + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: 'x1') + ILocalReferenceOperation: x1 (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x1') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) +"); } [Fact] @@ -10779,6 +11190,81 @@ static bool TakeOutParam(int y, out int x) True"); } + [Fact] + public void PropertyInitializers_03() + { + var source = +@" +public class X +{ + public static void Main() + { + } + static bool a = false; + bool Test1 { get; } = a && TakeOutParam(3, out int x1) || x1 > 0; + static bool TakeOutParam(object y, out int x) + { + x = 123; + return true; + } +} +"; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + compilation.VerifyDiagnostics( + // (8,63): error CS0165: Use of unassigned local variable 'x1' + // bool Test1 { get; } = a && TakeOutParam(3, out int x1) || x1 > 0; + Diagnostic(ErrorCode.ERR_UseDefViolation, "x1").WithArguments("x1").WithLocation(8, 63) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").Single(); + VerifyModelForOutVar(model, x1Decl, x1Ref); + } + + [Fact] + public void PropertyInitializers_04() + { + var source = +@" +public class X +{ + public static void Main() + { + System.Console.WriteLine(new X().Test1); + } + + int Test1 { get; } = TakeOutParam(1, out int x1) ? Test2(((System.Func)(() => x1++))(), ref x1) : -1; + + static int Test2(object a, ref int x) + { + System.Console.WriteLine(x); + x++; + return x; + } + + static bool TakeOutParam(int y, out int x) + { + x = y; + return true; + } +} +"; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + CompileAndVerify(compilation, expectedOutput: +@"2 +3"); + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclaration(tree, "x1"); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + } + [Fact] public void Scope_Query_01() { @@ -10923,18 +11409,12 @@ static bool TakeOutParam(T y, out T x) "; var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation.VerifyDiagnostics( - // (23,63): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // from x2 in new[] { TakeOutParam(x1, out var z2) ? z2 : 0, z2, y2} - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z2").WithLocation(23, 63), // (25,26): error CS0103: The name 'z2' does not exist in the current context // z2; Diagnostic(ErrorCode.ERR_NameNotInContext, "z2").WithArguments("z2").WithLocation(25, 26), // (27,15): error CS0103: The name 'z2' does not exist in the current context // Dummy(z2); Diagnostic(ErrorCode.ERR_NameNotInContext, "z2").WithArguments("z2").WithLocation(27, 15), - // (33,53): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // let x2 = TakeOutParam(x1, out var z3) && z3 > 0 && y3 < 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z3").WithLocation(33, 53), // (35,32): error CS0103: The name 'z3' does not exist in the current context // z3}; Diagnostic(ErrorCode.ERR_NameNotInContext, "z3").WithArguments("z3").WithLocation(35, 32), @@ -10944,15 +11424,9 @@ static bool TakeOutParam(T y, out T x) // (45,35): error CS0103: The name 'v4' does not exist in the current context // v4 Diagnostic(ErrorCode.ERR_NameNotInContext, "v4").WithArguments("v4").WithLocation(45, 35), - // (44,72): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // on x1 + y4 + z4 + (TakeOutParam(3, out var u4) ? u4 : 0) + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "u4").WithLocation(44, 72), // (47,35): error CS1938: The name 'u4' is not in scope on the right side of 'equals'. Consider swapping the expressions on either side of 'equals'. // u4 Diagnostic(ErrorCode.ERR_QueryInnerKey, "u4").WithArguments("u4").WithLocation(47, 35), - // (46,79): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // equals x2 + y4 + z4 + (TakeOutParam(4, out var v4) ? v4 : 0) + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "v4").WithLocation(46, 79), // (49,32): error CS0103: The name 'u4' does not exist in the current context // u4, v4 }; Diagnostic(ErrorCode.ERR_NameNotInContext, "u4").WithArguments("u4").WithLocation(49, 32), @@ -10968,15 +11442,9 @@ static bool TakeOutParam(T y, out T x) // (61,35): error CS0103: The name 'v5' does not exist in the current context // v5 Diagnostic(ErrorCode.ERR_NameNotInContext, "v5").WithArguments("v5").WithLocation(61, 35), - // (60,72): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // on x1 + y5 + z5 + (TakeOutParam(3, out var u5) ? u5 : 0) + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "u5").WithLocation(60, 72), // (63,35): error CS1938: The name 'u5' is not in scope on the right side of 'equals'. Consider swapping the expressions on either side of 'equals'. // u5 Diagnostic(ErrorCode.ERR_QueryInnerKey, "u5").WithArguments("u5").WithLocation(63, 35), - // (62,79): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // equals x2 + y5 + z5 + (TakeOutParam(4, out var v5) ? v5 : 0) + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "v5").WithLocation(62, 79), // (66,32): error CS0103: The name 'u5' does not exist in the current context // u5, v5 }; Diagnostic(ErrorCode.ERR_NameNotInContext, "u5").WithArguments("u5").WithLocation(66, 32), @@ -10989,9 +11457,6 @@ static bool TakeOutParam(T y, out T x) // (70,15): error CS0103: The name 'v5' does not exist in the current context // Dummy(v5); Diagnostic(ErrorCode.ERR_NameNotInContext, "v5").WithArguments("v5").WithLocation(70, 15), - // (76,59): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // where x > y6 && TakeOutParam(1, out var z6) && z6 == 1 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z6").WithLocation(76, 59), // (78,26): error CS0103: The name 'z6' does not exist in the current context // z6; Diagnostic(ErrorCode.ERR_NameNotInContext, "z6").WithArguments("z6").WithLocation(78, 26), @@ -11001,15 +11466,9 @@ static bool TakeOutParam(T y, out T x) // (87,27): error CS0103: The name 'u7' does not exist in the current context // u7, Diagnostic(ErrorCode.ERR_NameNotInContext, "u7").WithArguments("u7").WithLocation(87, 27), - // (86,61): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // orderby x > y7 && TakeOutParam(1, out var z7) && z7 == - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z7").WithLocation(86, 61), // (89,27): error CS0103: The name 'z7' does not exist in the current context // z7 Diagnostic(ErrorCode.ERR_NameNotInContext, "z7").WithArguments("z7").WithLocation(89, 27), - // (88,61): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // x > y7 && TakeOutParam(1, out var u7) && u7 == - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "u7").WithLocation(88, 61), // (91,26): error CS0103: The name 'z7' does not exist in the current context // z7 + u7; Diagnostic(ErrorCode.ERR_NameNotInContext, "z7").WithArguments("z7").WithLocation(91, 26), @@ -11025,24 +11484,15 @@ static bool TakeOutParam(T y, out T x) // (88,68): error CS0165: Use of unassigned local variable 'u7' // x > y7 && TakeOutParam(1, out var u7) && u7 == Diagnostic(ErrorCode.ERR_UseDefViolation, "u7").WithArguments("u7").WithLocation(88, 68), - // (100,60): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // select x > y8 && TakeOutParam(1, out var z8) && z8 == 1; - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z8").WithLocation(100, 60), // (102,15): error CS0103: The name 'z8' does not exist in the current context // Dummy(z8); Diagnostic(ErrorCode.ERR_NameNotInContext, "z8").WithArguments("z8").WithLocation(102, 15), // (112,25): error CS0103: The name 'z9' does not exist in the current context // z9; Diagnostic(ErrorCode.ERR_NameNotInContext, "z9").WithArguments("z9").WithLocation(112, 25), - // (111,59): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // x > y9 && TakeOutParam(1, out var u9) && u9 == - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "u9").WithLocation(111, 59), // (109,25): error CS0103: The name 'u9' does not exist in the current context // u9 Diagnostic(ErrorCode.ERR_NameNotInContext, "u9").WithArguments("u9").WithLocation(109, 25), - // (108,59): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // group x > y9 && TakeOutParam(1, out var z9) && z9 == - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z9").WithLocation(108, 59), // (114,15): error CS0103: The name 'z9' does not exist in the current context // Dummy(z9); Diagnostic(ErrorCode.ERR_NameNotInContext, "z9").WithArguments("z9").WithLocation(114, 15), @@ -11279,15 +11729,9 @@ static bool TakeOutParam(T y, out T x) // (18,35): error CS0103: The name 'v4' does not exist in the current context // v4 Diagnostic(ErrorCode.ERR_NameNotInContext, "v4").WithArguments("v4").WithLocation(18, 35), - // (17,72): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // on x1 + y4 + z4 + (TakeOutParam(3, out var u4) ? u4 : 0) + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "u4").WithLocation(17, 72), // (20,35): error CS1938: The name 'u4' is not in scope on the right side of 'equals'. Consider swapping the expressions on either side of 'equals'. // u4 Diagnostic(ErrorCode.ERR_QueryInnerKey, "u4").WithArguments("u4").WithLocation(20, 35), - // (19,79): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // equals x2 + y4 + z4 + (TakeOutParam(4, out var v4) ? v4 : 0) + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "v4").WithLocation(19, 79), // (22,32): error CS0103: The name 'u4' does not exist in the current context // u4, v4 }; Diagnostic(ErrorCode.ERR_NameNotInContext, "u4").WithArguments("u4").WithLocation(22, 32), @@ -11303,15 +11747,9 @@ static bool TakeOutParam(T y, out T x) // (35,35): error CS0103: The name 'v5' does not exist in the current context // v5 Diagnostic(ErrorCode.ERR_NameNotInContext, "v5").WithArguments("v5").WithLocation(35, 35), - // (34,72): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // on x1 + y5 + z5 + (TakeOutParam(3, out var u5) ? u5 : 0) + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "u5").WithLocation(34, 72), // (37,35): error CS1938: The name 'u5' is not in scope on the right side of 'equals'. Consider swapping the expressions on either side of 'equals'. // u5 Diagnostic(ErrorCode.ERR_QueryInnerKey, "u5").WithArguments("u5").WithLocation(37, 35), - // (36,80): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // equals x2 + y5 + z5 + (TakeOutParam(4 , out var v5) ? v5 : 0) + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "v5").WithLocation(36, 80), // (40,32): error CS0103: The name 'u5' does not exist in the current context // u5, v5 }; Diagnostic(ErrorCode.ERR_NameNotInContext, "u5").WithArguments("u5").WithLocation(40, 32), @@ -11436,69 +11874,36 @@ static bool TakeOutParam(T y, out T x) // (17,62): error CS0136: A local or parameter named 'y2' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // from x2 in new[] { TakeOutParam(2, out var y2) ? y2 : 0} Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y2").WithArguments("y2").WithLocation(17, 62), - // (17,62): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // from x2 in new[] { TakeOutParam(2, out var y2) ? y2 : 0} - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y2").WithLocation(17, 62), // (18,62): error CS0128: A local variable or function named 'y3' is already defined in this scope // join x3 in new[] { TakeOutParam(3, out var y3) ? y3 : 0} Diagnostic(ErrorCode.ERR_LocalDuplicate, "y3").WithArguments("y3").WithLocation(18, 62), // (19,51): error CS0136: A local or parameter named 'y4' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // on TakeOutParam(4, out var y4) ? y4 : 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y4").WithArguments("y4").WithLocation(19, 51), - // (19,51): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // on TakeOutParam(4, out var y4) ? y4 : 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y4").WithLocation(19, 51), // (20,58): error CS0136: A local or parameter named 'y5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // equals TakeOutParam(5, out var y5) ? y5 : 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y5").WithArguments("y5").WithLocation(20, 58), - // (20,58): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // equals TakeOutParam(5, out var y5) ? y5 : 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y5").WithLocation(20, 58), // (21,49): error CS0136: A local or parameter named 'y6' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // where TakeOutParam(6, out var y6) && y6 == 1 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y6").WithArguments("y6").WithLocation(21, 49), - // (21,49): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // where TakeOutParam(6, out var y6) && y6 == 1 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y6").WithLocation(21, 49), // (22,51): error CS0136: A local or parameter named 'y7' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // orderby TakeOutParam(7, out var y7) && y7 > 0, Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y7").WithArguments("y7").WithLocation(22, 51), - // (22,51): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // orderby TakeOutParam(7, out var y7) && y7 > 0, - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y7").WithLocation(22, 51), // (23,51): error CS0136: A local or parameter named 'y8' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // TakeOutParam(8, out var y8) && y8 > 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y8").WithArguments("y8").WithLocation(23, 51), - // (23,51): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // TakeOutParam(8, out var y8) && y8 > 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y8").WithLocation(23, 51), // (25,47): error CS0136: A local or parameter named 'y10' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // by TakeOutParam(10, out var y10) && y10 > 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y10").WithArguments("y10").WithLocation(25, 47), - // (25,47): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // by TakeOutParam(10, out var y10) && y10 > 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y10").WithLocation(25, 47), // (24,49): error CS0136: A local or parameter named 'y9' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // group TakeOutParam(9, out var y9) && y9 > 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y9").WithArguments("y9").WithLocation(24, 49), - // (24,49): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // group TakeOutParam(9, out var y9) && y9 > 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y9").WithLocation(24, 49), // (27,54): error CS0136: A local or parameter named 'y11' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // let x11 = TakeOutParam(11, out var y11) && y11 > 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y11").WithArguments("y11").WithLocation(27, 54), - // (27,54): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // let x11 = TakeOutParam(11, out var y11) && y11 > 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y11").WithLocation(27, 54), // (28,51): error CS0136: A local or parameter named 'y12' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // select TakeOutParam(12, out var y12) && y12 > 0 - Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y12").WithArguments("y12").WithLocation(28, 51), - // (28,51): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // select TakeOutParam(12, out var y12) && y12 > 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y12").WithLocation(28, 51), - // (30,115): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // select y1 + y2 + y3 + y4 + y5 + y6 + y7 + y8 + y9 + y10 + y11 + y12 + (TakeOutParam(13, out var y13) ? y13 : 0); - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y13").WithLocation(30, 115) + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y12").WithArguments("y12").WithLocation(28, 51) ); var tree = compilation.SyntaxTrees.Single(); @@ -11609,66 +12014,36 @@ static bool TakeOutParam(out int x) // (27,62): error CS0136: A local or parameter named 'y2' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // from x2 in new[] { TakeOutParam(2, out var y2) ? y2 : 0} Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y2").WithArguments("y2").WithLocation(27, 62), - // (27,62): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // from x2 in new[] { TakeOutParam(2, out var y2) ? y2 : 0} - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y2").WithLocation(27, 62), // (28,62): error CS0128: A local variable or function named 'y3' is already defined in this scope // join x3 in new[] { TakeOutParam(3, out var y3) ? y3 : 0} Diagnostic(ErrorCode.ERR_LocalDuplicate, "y3").WithArguments("y3").WithLocation(28, 62), // (29,51): error CS0136: A local or parameter named 'y4' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // on TakeOutParam(4, out var y4) ? y4 : 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y4").WithArguments("y4").WithLocation(29, 51), - // (29,51): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // on TakeOutParam(4, out var y4) ? y4 : 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y4").WithLocation(29, 51), // (30,58): error CS0136: A local or parameter named 'y5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // equals TakeOutParam(5, out var y5) ? y5 : 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y5").WithArguments("y5").WithLocation(30, 58), - // (30,58): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // equals TakeOutParam(5, out var y5) ? y5 : 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y5").WithLocation(30, 58), // (31,49): error CS0136: A local or parameter named 'y6' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // where TakeOutParam(6, out var y6) && y6 == 1 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y6").WithArguments("y6").WithLocation(31, 49), - // (31,49): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // where TakeOutParam(6, out var y6) && y6 == 1 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y6").WithLocation(31, 49), // (32,51): error CS0136: A local or parameter named 'y7' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // orderby TakeOutParam(7, out var y7) && y7 > 0, Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y7").WithArguments("y7").WithLocation(32, 51), - // (32,51): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // orderby TakeOutParam(7, out var y7) && y7 > 0, - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y7").WithLocation(32, 51), // (33,51): error CS0136: A local or parameter named 'y8' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // TakeOutParam(8, out var y8) && y8 > 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y8").WithArguments("y8").WithLocation(33, 51), - // (33,51): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // TakeOutParam(8, out var y8) && y8 > 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y8").WithLocation(33, 51), // (35,47): error CS0136: A local or parameter named 'y10' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // by TakeOutParam(10, out var y10) && y10 > 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y10").WithArguments("y10").WithLocation(35, 47), - // (35,47): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // by TakeOutParam(10, out var y10) && y10 > 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y10").WithLocation(35, 47), // (34,49): error CS0136: A local or parameter named 'y9' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // group TakeOutParam(9, out var y9) && y9 > 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y9").WithArguments("y9").WithLocation(34, 49), - // (34,49): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // group TakeOutParam(9, out var y9) && y9 > 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y9").WithLocation(34, 49), // (37,54): error CS0136: A local or parameter named 'y11' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // let x11 = TakeOutParam(11, out var y11) && y11 > 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y11").WithArguments("y11").WithLocation(37, 54), - // (37,54): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // let x11 = TakeOutParam(11, out var y11) && y11 > 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y11").WithLocation(37, 54), // (38,51): error CS0136: A local or parameter named 'y12' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // select TakeOutParam(12, out var y12) && y12 > 0 - Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y12").WithArguments("y12").WithLocation(38, 51), - // (38,51): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // select TakeOutParam(12, out var y12) && y12 > 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y12").WithLocation(38, 51) + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y12").WithArguments("y12").WithLocation(38, 51) ); var tree = compilation.SyntaxTrees.Single(); @@ -12026,63 +12401,33 @@ static bool TakeOutParam(out int x) // (15,59): error CS0136: A local or parameter named 'y1' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // from x2 in new[] { TakeOutParam(out var y1) ? y1 : 1 } Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y1").WithArguments("y1").WithLocation(15, 59), - // (15,59): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // from x2 in new[] { TakeOutParam(out var y1) ? y1 : 1 } - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y1").WithLocation(15, 59), // (23,48): error CS0136: A local or parameter named 'y2' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // on TakeOutParam(out var y2) ? y2 : 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y2").WithArguments("y2").WithLocation(23, 48), - // (23,48): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // on TakeOutParam(out var y2) ? y2 : 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y2").WithLocation(23, 48), // (33,52): error CS0136: A local or parameter named 'y3' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // equals TakeOutParam(out var y3) ? y3 : 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y3").WithArguments("y3").WithLocation(33, 52), - // (33,52): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // equals TakeOutParam(out var y3) ? y3 : 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y3").WithLocation(33, 52), // (40,46): error CS0136: A local or parameter named 'y4' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // where TakeOutParam(out var y4) && y4 == 1 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y4").WithArguments("y4").WithLocation(40, 46), - // (40,46): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // where TakeOutParam(out var y4) && y4 == 1 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y4").WithLocation(40, 46), // (47,48): error CS0136: A local or parameter named 'y5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // orderby TakeOutParam(out var y5) && y5 > 1, Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y5").WithArguments("y5").WithLocation(47, 48), - // (47,48): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // orderby TakeOutParam(out var y5) && y5 > 1, - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y5").WithLocation(47, 48), // (56,48): error CS0136: A local or parameter named 'y6' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // TakeOutParam(out var y6) && y6 > 1 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y6").WithArguments("y6").WithLocation(56, 48), - // (56,48): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // TakeOutParam(out var y6) && y6 > 1 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y6").WithLocation(56, 48), // (63,46): error CS0136: A local or parameter named 'y7' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // group TakeOutParam(out var y7) && y7 == 3 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y7").WithArguments("y7").WithLocation(63, 46), - // (63,46): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // group TakeOutParam(out var y7) && y7 == 3 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y7").WithLocation(63, 46), // (71,43): error CS0136: A local or parameter named 'y8' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // by TakeOutParam(out var y8) && y8 == 3; Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y8").WithArguments("y8").WithLocation(71, 43), - // (71,43): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // by TakeOutParam(out var y8) && y8 == 3; - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y8").WithLocation(71, 43), // (77,49): error CS0136: A local or parameter named 'y9' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // let x4 = TakeOutParam(out var y9) && y9 > 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y9").WithArguments("y9").WithLocation(77, 49), - // (77,49): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // let x4 = TakeOutParam(out var y9) && y9 > 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y9").WithLocation(77, 49), // (84,47): error CS0136: A local or parameter named 'y10' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // select TakeOutParam(out var y10) && y10 > 0; - Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y10").WithArguments("y10").WithLocation(84, 47), - // (84,47): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // select TakeOutParam(out var y10) && y10 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y10").WithLocation(84, 47) + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y10").WithArguments("y10").WithLocation(84, 47) ); var tree = compilation.SyntaxTrees.Single(); @@ -12117,6 +12462,107 @@ static bool TakeOutParam(out int x) } } + [Fact] + public void Scope_Query_11() + { + var source = +@" +using System.Linq; + +public class X +{ + public static void Main() + { + } + + bool Dummy(params object[] x) {return true;} + + void Test1() + { + var res = from x1 in new [] { 1 } + where Dummy(TakeOutParam(x1, out var y1), + from x2 in new [] { y1 } + where TakeOutParam(x1, out var y1) + select x2) + select x1; + } + + void Test2() + { + var res = from x1 in new [] { 1 } + where Dummy(TakeOutParam(x1, out var y2), + TakeOutParam(x1 + 1, out var y2)) + select x1; + } + + void Test3() + { + var res = from x1 in new [] { 1 } + where TakeOutParam(out int y3, y3) + select x1; + } + + void Test4() + { + var res = from x1 in new [] { 1 } + where TakeOutParam(out var y4, y4) + select x1; + } + + static bool TakeOutParam(T y, out T x) + { + x = y; + return true; + } + static bool TakeOutParam(out int x, int y) + { + x = y; + return true; + } +} +"; + var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + compilation.VerifyDiagnostics( + // (17,62): error CS0136: A local or parameter named 'y1' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // where TakeOutParam(x1, out var y1) + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y1").WithArguments("y1").WithLocation(17, 62), + // (26,60): error CS0128: A local variable or function named 'y2' is already defined in this scope + // TakeOutParam(x1 + 1, out var y2)) + Diagnostic(ErrorCode.ERR_LocalDuplicate, "y2").WithArguments("y2").WithLocation(26, 60), + // (33,50): error CS0165: Use of unassigned local variable 'y3' + // where TakeOutParam(out int y3, y3) + Diagnostic(ErrorCode.ERR_UseDefViolation, "y3").WithArguments("y3").WithLocation(33, 50), + // (40,50): error CS8196: Reference to an implicitly-typed out variable 'y4' is not permitted in the same argument list. + // where TakeOutParam(out var y4, y4) + Diagnostic(ErrorCode.ERR_ImplicitlyTypedOutVariableUsedInTheSameArgumentList, "y4").WithArguments("y4").WithLocation(40, 50), + // (40,50): error CS0165: Use of unassigned local variable 'y4' + // where TakeOutParam(out var y4, y4) + Diagnostic(ErrorCode.ERR_UseDefViolation, "y4").WithArguments("y4").WithLocation(40, 50) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var y1Decl = GetOutVarDeclarations(tree, "y1").ToArray(); + var y1Ref = GetReferences(tree, "y1").Single(); + Assert.Equal(2, y1Decl.Length); + VerifyModelForOutVar(model, y1Decl[0], y1Ref); + VerifyModelForOutVar(model, y1Decl[1]); + + var y2Decl = GetOutVarDeclarations(tree, "y2").ToArray(); + Assert.Equal(2, y2Decl.Length); + VerifyModelForOutVar(model, y2Decl[0]); + VerifyModelForOutVarDuplicateInSameScope(model, y2Decl[1]); + + var y3Decl = GetOutVarDeclarations(tree, "y3").Single(); + var y3Ref = GetReferences(tree, "y3").Single(); + VerifyModelForOutVarWithoutDataFlow(model, y3Decl, y3Ref); + + var y4Decl = GetOutVarDeclarations(tree, "y4").Single(); + var y4Ref = GetReferences(tree, "y4").Single(); + VerifyModelForOutVarWithoutDataFlow(model, y4Decl, y4Ref); + } + [Fact] public void Query_01() { @@ -12164,57 +12610,22 @@ static bool Print(object x) } "; var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); - compilation.VerifyDiagnostics( - // (14,62): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // from x2 in new[] { TakeOutParam(2, out var y2) && Print(y2) ? 1 : 0} - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y2").WithLocation(14, 62), - // (16,51): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // on TakeOutParam(4, out var y4) && Print(y4) ? 1 : 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y4").WithLocation(16, 51), - // (17,58): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // equals TakeOutParam(5, out var y5) && Print(y5) ? 1 : 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y5").WithLocation(17, 58), - // (18,49): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // where TakeOutParam(6, out var y6) && Print(y6) - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y6").WithLocation(18, 49), - // (19,51): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // orderby TakeOutParam(7, out var y7) && Print(y7), - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y7").WithLocation(19, 51), - // (20,51): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // TakeOutParam(8, out var y8) && Print(y8) - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y8").WithLocation(20, 51), - // (22,47): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // by TakeOutParam(10, out var y10) && Print(y10) - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y10").WithLocation(22, 47), - // (21,49): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // group TakeOutParam(9, out var y9) && Print(y9) - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y9").WithLocation(21, 49), - // (24,54): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // let x11 = TakeOutParam(11, out var y11) && Print(y11) - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y11").WithLocation(24, 54), - // (25,51): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // select TakeOutParam(12, out var y12) && Print(y12); - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y12").WithLocation(25, 51) - ); - - // Because expression variables are not permitted in query clauses (https://github.com/dotnet/roslyn/issues/15910) - // this program cannot be run. However, once we allow that (https://github.com/dotnet/roslyn/issues/15619) - // the program wil be capable of being run. In that case the following (commented code) would test for the expected output. + compilation.VerifyDiagnostics(); - // CompileAndVerify(compilation, expectedOutput: - //@"1 - //3 - //5 - //2 - //4 - //6 - //7 - //8 - //10 - //9 - //11 - //12 - //"); + CompileAndVerify(compilation, expectedOutput: +@"1 +3 +5 +2 +4 +6 +7 +8 +10 +9 +11 +12 +"); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); @@ -12225,6 +12636,8 @@ static bool Print(object x) var yDecl = GetOutVarDeclarations(tree, id).Single(); var yRef = GetReferences(tree, id).Single(); VerifyModelForOutVar(model, yDecl, yRef); + + Assert.Equal("System.Int32", ((LocalSymbol)compilation.GetSemanticModel(tree).GetDeclaredSymbol(GetVariableDesignation(yDecl))).Type.ToTestDisplayString()); } } @@ -12277,6 +12690,139 @@ static bool Print(object x) VerifyModelForOutVar(model, yDecl, yRef); } + [Fact] + public void Query_03() + { + var source = +@" +using System.Linq; + +public class X +{ + public static void Main() + { + } + + static void Test1() + { + var res = from a in new[] { true } + select a && TakeOutParam(3, out int x1) || x1 > 0; + } + + static bool TakeOutParam(T y, out T x) + { + x = y; + return true; + } +} +"; + var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + + compilation.VerifyDiagnostics( + // (13,62): error CS0165: Use of unassigned local variable 'x1' + // select a && TakeOutParam(3, out int x1) || x1 > 0; + Diagnostic(ErrorCode.ERR_UseDefViolation, "x1").WithArguments("x1").WithLocation(13, 62) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").Single(); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + compilation.VerifyOperationTree(x1Decl, expectedOperationTree: +@" +IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32) (Syntax: 'int x1') + ILocalReferenceOperation: x1 (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x1') +"); + } + + [Fact] + public void Query_04() + { + var source = +@" +using System.Linq; + +public class X +{ + public static void Main() + { + System.Console.WriteLine(Test1()); + } + + static int Test1() + { + var res = from a in new[] { 1 } + select TakeOutParam(a, out int x1) ? Test2(((System.Func)(() => x1++))(), ref x1) : -1; + + return res.Single(); + } + + static int Test2(object a, ref int x) + { + System.Console.WriteLine(x); + x++; + return x; + } + + static bool TakeOutParam(T y, out T x) + { + x = y; + return true; + } +} +"; + var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + + CompileAndVerify(compilation, expectedOutput: +@"2 +3"); + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclaration(tree, "x1"); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + } + + [Fact] + public void Query_05() + { + var source = +@" +using System.Linq; + +public class X +{ + public static void Main() + { + } + + static void Test1() + { + var res = from a in (new[] { 1 }).AsQueryable() + select TakeOutParam(a, out int x1); + } + + static bool TakeOutParam(T y, out T x) + { + x = y; + return true; + } +} +"; + var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + + compilation.VerifyDiagnostics( + // (13,46): error CS8198: An expression tree may not contain an out argument variable declaration. + // select TakeOutParam(a, out int x1); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOutVariable, "int x1").WithLocation(13, 46) + ); + } + [Fact] public void Scope_ReturnStatement_01() { @@ -17647,19 +18193,9 @@ public Test2() {} } }"; - var compilation = CreateCompilation(text, - options: TestOptions.ReleaseExe, - parseOptions: TestOptions.Regular); + var compilation = CreateCompilation(text, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular); -#if ALLOW_IN_CONSTRUCTOR_INITIALIZER CompileAndVerify(compilation, expectedOutput: @"123").VerifyDiagnostics(); -#else - compilation.VerifyDiagnostics( - // (25,26): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : this(Test1(out var x1), x1) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x1").WithLocation(25, 26) - ); -#endif var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); @@ -17667,6 +18203,23 @@ public Test2() var x1Decl = GetOutVarDeclaration(tree, "x1"); var x1Ref = GetReference(tree, "x1"); VerifyModelForOutVar(model, x1Decl, x1Ref); + + Assert.Equal("System.Int32", ((LocalSymbol)compilation.GetSemanticModel(tree).GetDeclaredSymbol(GetVariableDesignation(x1Decl))).Type.ToTestDisplayString()); + + CreateCompilation(text, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular7_2).VerifyDiagnostics( + // (25,26): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. + // : this(Test1(out var x1), x1) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "var x1").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(25, 26) + ); + + var initializer = tree.GetRoot().DescendantNodes().OfType().Single(); + var typeInfo = model.GetTypeInfo(initializer); + var symbolInfo = model.GetSymbolInfo(initializer); + var group = model.GetMemberGroup(initializer); + + Assert.Equal("System.Void", typeInfo.Type.ToTestDisplayString()); + Assert.Equal("Cls.Test2..ctor(System.Object x, System.Object y)", symbolInfo.Symbol.ToTestDisplayString()); + Assert.Empty(group); // https://github.com/dotnet/roslyn/issues/24936 } [Fact] @@ -17704,19 +18257,9 @@ public Test3() {} } }"; - var compilation = CreateCompilation(text, - options: TestOptions.ReleaseExe, - parseOptions: TestOptions.Regular); + var compilation = CreateCompilation(text, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular); -#if ALLOW_IN_CONSTRUCTOR_INITIALIZER CompileAndVerify(compilation, expectedOutput: @"123").VerifyDiagnostics(); -#else - compilation.VerifyDiagnostics( - // (29,26): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : base(Test1(out var x1), x1) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x1").WithLocation(29, 26) - ); -#endif var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); @@ -17724,6 +18267,14 @@ public Test3() var x1Decl = GetOutVarDeclaration(tree, "x1"); var x1Ref = GetReference(tree, "x1"); VerifyModelForOutVar(model, x1Decl, x1Ref); + + Assert.Equal("System.Int32", ((LocalSymbol)compilation.GetSemanticModel(tree).GetDeclaredSymbol(GetVariableDesignation(x1Decl))).Type.ToTestDisplayString()); + + CreateCompilation(text, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular7_2).VerifyDiagnostics( + // (29,26): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. + // : base(Test1(out var x1), x1) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "var x1").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(29, 26) + ); } [Fact] @@ -17734,8 +18285,11 @@ public class Cls { public static void Main() { + Do(new Test2()); } + static void Do(object x){} + class Test2 { Test2(out int x) @@ -17743,26 +18297,27 @@ class Test2 x = 2; } - Test2() + public Test2() : this(out var x1) - {} + { + System.Console.WriteLine(x1); + } } }"; var compilation = CreateCompilation(text, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular); - compilation.VerifyDiagnostics( - // (16,20): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : this(out var x1) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x1").WithLocation(16, 20) - ); + CompileAndVerify(compilation, expectedOutput: @"2").VerifyDiagnostics(); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var x1Decl = GetOutVarDeclaration(tree, "x1"); - VerifyModelForOutVar(model, x1Decl); + var x1Ref = GetReference(tree, "x1"); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + Assert.Equal("System.Int32", ((LocalSymbol)compilation.GetSemanticModel(tree).GetDeclaredSymbol(GetVariableDesignation(x1Decl))).Type.ToTestDisplayString()); } [Fact] @@ -17773,8 +18328,11 @@ public class Cls { public static void Main() { + Do(new Test3()); } + static void Do(object x){} + class Test2 { public Test2(out int x) @@ -17786,26 +18344,25 @@ public Test2(out int x) class Test3 : Test2 { - Test3() + public Test3() : base(out var x1) - {} + => System.Console.WriteLine(x1); } }"; var compilation = CreateCompilation(text, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular); - compilation.VerifyDiagnostics( - // (20,20): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : base(out var x1) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x1").WithLocation(20, 20) - ); + CompileAndVerify(compilation, expectedOutput: @"1").VerifyDiagnostics(); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var x1Decl = GetOutVarDeclaration(tree, "x1"); - VerifyModelForOutVar(model, x1Decl); + var x1Ref = GetReference(tree, "x1"); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + Assert.Equal("System.Int32", ((LocalSymbol)compilation.GetSemanticModel(tree).GetDeclaredSymbol(GetVariableDesignation(x1Decl))).Type.ToTestDisplayString()); } [Fact] @@ -17858,6 +18415,617 @@ public Test2() VerifyModelForOutVar(model, x1Decl, x1Ref); } + [Fact] + public void ConstructorInitializers_06() + { + var text = @" +public class Cls +{ + public static void Main() + { + Do(new Test2()); + } + + static void Do(object x){} + + public static object Test1(out int x) + { + x = 123; + return null; + } + + class Test2 + { + Test2(object x) + { + } + + public Test2() + : this(Test1(out var x1)) + { + System.Console.WriteLine(x1); + } + } +}"; + var compilation = CreateCompilation(text, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular); + + CompileAndVerify(compilation, expectedOutput: @"123").VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclaration(tree, "x1"); + var x1Ref = GetReference(tree, "x1"); + VerifyModelForOutVar(model, x1Decl, x1Ref); + } + + [Fact] + public void ConstructorInitializers_07() + { + var text = @" +public class Cls +{ + public static void Main() + { + Do(new Test2()); + } + + static void Do(object x){} + + public static object Test1(out int x) + { + x = 123; + return null; + } + + class Test2 + { + Test2(object x) + { + } + + public Test2() + : this(Test1(out var x1)) + => System.Console.WriteLine(x1); + } +}"; + var compilation = CreateCompilation(text, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular); + + CompileAndVerify(compilation, expectedOutput: @"123").VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclaration(tree, "x1"); + var x1Ref = GetReference(tree, "x1"); + VerifyModelForOutVar(model, x1Decl, x1Ref); + } + + [Fact] + public void ConstructorInitializers_08() + { + var text = @" +public class Cls +{ + public static void Main() + { + Do(new Test2()); + } + + static void Do(object x){} + + public static object Test1(out int x) + { + x = 123; + return null; + } + + class Test2 + { + Test2(object x) + { + } + + public Test2() + : this(Test1(out var x1)) + { + System.Console.WriteLine(x1); + } + => System.Console.WriteLine(x1); + } +}"; + var compilation = CreateCompilation(text, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular); + + compilation.VerifyDiagnostics( + // (23,9): error CS8057: Block bodies and expression bodies cannot both be provided. + // public Test2() + Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, @"public Test2() + : this(Test1(out var x1)) + { + System.Console.WriteLine(x1); + } + => System.Console.WriteLine(x1);").WithLocation(23, 9) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclaration(tree, "x1"); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var analyzer = new ConstructorInitializers_08_SyntaxAnalyzer(); + CreateCompilation(text, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular) + .GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.True(analyzer.ActionFired); + } + + private class ConstructorInitializers_08_SyntaxAnalyzer : DiagnosticAnalyzer + { + public bool ActionFired { get; private set; } + + private static readonly DiagnosticDescriptor Descriptor = + new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test"); + + public override ImmutableArray SupportedDiagnostics + => ImmutableArray.Create(Descriptor); + + public override void Initialize(AnalysisContext context) + { + context.RegisterSyntaxNodeAction(Handle, SyntaxKind.ThisConstructorInitializer); + } + + private void Handle(SyntaxNodeAnalysisContext context) + { + ActionFired = true; + var tree = context.Node.SyntaxTree; + var model = context.SemanticModel; + var constructorDeclaration = (ConstructorDeclarationSyntax)context.Node.Parent; + SyntaxTreeSemanticModel syntaxTreeModel = ((SyntaxTreeSemanticModel)model); + + Assert.True(syntaxTreeModel.TestOnlyMemberModels.ContainsKey(constructorDeclaration)); + + MemberSemanticModel mm = syntaxTreeModel.TestOnlyMemberModels[constructorDeclaration]; + + Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(constructorDeclaration).IsDefaultOrEmpty); + Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(constructorDeclaration.Initializer).IsDefaultOrEmpty); + Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(constructorDeclaration.Body).IsDefaultOrEmpty); + Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(constructorDeclaration.ExpressionBody).IsDefaultOrEmpty); + + var x1Decl = GetOutVarDeclaration(tree, "x1"); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + Assert.Same(mm, syntaxTreeModel.GetMemberModel(x1Decl)); + Assert.Same(mm, syntaxTreeModel.GetMemberModel(x1Ref[0])); + Assert.Same(mm, syntaxTreeModel.GetMemberModel(x1Ref[1])); + } + } + + [Fact] + public void ConstructorInitializers_09() + { + var text = @" +public class Cls +{ + public static void Main() + { + } + + public static bool Test1(out int x) + { + throw null; + } + + class Test2 + { + Test2(bool x, int y) + { + } + + public Test2(bool a) + : this(a && Test1(out var x1), x1) + { + } + } +}"; + var compilation = CreateCompilation(text, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular); + + compilation.VerifyDiagnostics( + // (20,40): error CS0165: Use of unassigned local variable 'x1' + // : this(a && Test1(out var x1), x1) + Diagnostic(ErrorCode.ERR_UseDefViolation, "x1").WithArguments("x1").WithLocation(20, 40) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclaration(tree, "x1"); + var x1Ref = GetReference(tree, "x1"); + VerifyModelForOutVar(model, x1Decl, x1Ref); + } + + [Fact] + public void ConstructorInitializers_10() + { + var text = @" +public class Cls +{ + public static void Main() + { + } + + public static bool Test1(out int x) + { + throw null; + } + + class Test2 + { + Test2(bool x, int y) + { + } + + public Test2(bool a) + : this(a && Test1(out var x1), 1) + { + System.Console.WriteLine(x1); + } + } +}"; + var compilation = CreateCompilation(text, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular); + + compilation.VerifyDiagnostics( + // (22,38): error CS0165: Use of unassigned local variable 'x1' + // System.Console.WriteLine(x1); + Diagnostic(ErrorCode.ERR_UseDefViolation, "x1").WithArguments("x1").WithLocation(22, 38) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclaration(tree, "x1"); + var x1Ref = GetReference(tree, "x1"); + VerifyModelForOutVar(model, x1Decl, x1Ref); + } + + [Fact] + public void ConstructorInitializers_11() + { + var text = @" +public class Cls +{ + public static void Main() + { + } + + public static bool Test1(out int x) + { + throw null; + } + + class Test2 + { + Test2(bool x, int y) + { + } + + public Test2(bool a) + : this(a && Test1(out var x1), 1) + => System.Console.WriteLine(x1); + } +}"; + var compilation = CreateCompilation(text, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular); + + compilation.VerifyDiagnostics( + // (21,37): error CS0165: Use of unassigned local variable 'x1' + // => System.Console.WriteLine(x1); + Diagnostic(ErrorCode.ERR_UseDefViolation, "x1").WithArguments("x1").WithLocation(21, 37) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclaration(tree, "x1"); + var x1Ref = GetReference(tree, "x1"); + VerifyModelForOutVar(model, x1Decl, x1Ref); + } + + [Fact] + public void ConstructorInitializers_12() + { + var text = @" +public class Cls +{ + public static void Main() + { + } + + public static bool Test1(out int x) + { + throw null; + } + + class Test2 + { + Test2(bool x, int y) + { + } + + public Test2(bool a) + : this(a && Test1(out var x1), 1) + { + System.Console.WriteLine(x1); + } + => System.Console.WriteLine(x1); + } +}"; + var compilation = CreateCompilation(text, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular); + + compilation.VerifyDiagnostics( + // (19,9): error CS8057: Block bodies and expression bodies cannot both be provided. + // public Test2(bool a) + Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, @"public Test2(bool a) + : this(a && Test1(out var x1), 1) + { + System.Console.WriteLine(x1); + } + => System.Console.WriteLine(x1);").WithLocation(19, 9), + // (22,38): error CS0165: Use of unassigned local variable 'x1' + // System.Console.WriteLine(x1); + Diagnostic(ErrorCode.ERR_UseDefViolation, "x1").WithArguments("x1").WithLocation(22, 38) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclaration(tree, "x1"); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + } + + [Fact] + public void ConstructorInitializers_13() + { + var text = @" +public class Cls +{ + public static void Main() + { + } + + public static bool Test1(out int x) + { + throw null; + } + + class Test2 + { + Test2(bool x, int y) + { + } + + public Test2(bool a) + : this(a && Test1(out var x1), x1) + { + System.Console.WriteLine(x1); + } + } +}"; + var compilation = CreateCompilation(text, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular); + + compilation.VerifyDiagnostics( + // (20,40): error CS0165: Use of unassigned local variable 'x1' + // : this(a && Test1(out var x1), x1) + Diagnostic(ErrorCode.ERR_UseDefViolation, "x1").WithArguments("x1").WithLocation(20, 40) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclaration(tree, "x1"); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + } + + [Fact] + public void ConstructorInitializers_14() + { + var text = @" +public class Cls +{ + public static void Main() + { + } + + public static bool Test1(out int x) + { + throw null; + } + + class Test2 + { + Test2(bool x, int y) + { + } + + public Test2(bool a) + : this(a && Test1(out var x1), x1) + => System.Console.WriteLine(x1); + } +}"; + var compilation = CreateCompilation(text, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular); + + compilation.VerifyDiagnostics( + // (20,40): error CS0165: Use of unassigned local variable 'x1' + // : this(a && Test1(out var x1), x1) + Diagnostic(ErrorCode.ERR_UseDefViolation, "x1").WithArguments("x1").WithLocation(20, 40) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclaration(tree, "x1"); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + } + + [Fact] + public void ConstructorInitializers_15() + { + var text = @" +public class Cls +{ + public static void Main() + { + } + + public static bool Test1(out int x) + { + throw null; + } + + class Test2 + { + Test2(bool x, int y) + { + } + + public Test2(bool a) + : this(a && Test1(out var x1), x1) + { + System.Console.WriteLine(x1); + } + => System.Console.WriteLine(x1); + } +}"; + var compilation = CreateCompilation(text, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular); + + compilation.VerifyDiagnostics( + // (19,9): error CS8057: Block bodies and expression bodies cannot both be provided. + // public Test2(bool a) + Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, @"public Test2(bool a) + : this(a && Test1(out var x1), x1) + { + System.Console.WriteLine(x1); + } + => System.Console.WriteLine(x1);").WithLocation(19, 9), + // (20,40): error CS0165: Use of unassigned local variable 'x1' + // : this(a && Test1(out var x1), x1) + Diagnostic(ErrorCode.ERR_UseDefViolation, "x1").WithArguments("x1").WithLocation(20, 40) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclaration(tree, "x1"); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(3, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + } + + [Fact] + public void ConstructorInitializers_16() + { + var text = @" +public class Cls +{ + public static void Main() + { + Do(new Test2()); + } + + static void Do(object x){} + + public static object Test1(out int x) + { + x = 123; + return null; + } + + class Test2 + { + Test2(object a, object b, ref int x) + { + System.Console.WriteLine(x); + x++; + } + + public Test2() + : this(Test1(out var x1), ((System.Func)(() => x1++))(), ref x1) + { + System.Console.WriteLine(x1); + } + } +}"; + var compilation = CreateCompilation(text, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular); + + CompileAndVerify(compilation, expectedOutput: +@"124 +125").VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclaration(tree, "x1"); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(3, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + } + + [Fact] + public void ConstructorInitializers_17() + { + var text = @" +public class Cls +{ + public static void Main() + { + Do(new Test2()); + } + + static void Do(object x){} + + public static object Test1(out int x) + { + x = 123; + return null; + } + + class Test2 + { + Test2(object a, object b, ref int x) + { + System.Console.WriteLine(x); + x++; + } + + public Test2() + : this(Test1(out var x1), ((System.Func)(() => x1++))(), ref x1) + => System.Console.WriteLine(x1); + } +}"; + var compilation = CreateCompilation(text, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular); + + CompileAndVerify(compilation, expectedOutput: +@"124 +125").VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclaration(tree, "x1"); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(3, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + } + [Fact] public void SimpleVar_14() { @@ -22882,30 +24050,18 @@ static bool TakeOutParam(T y, out T x) { var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.ReleaseExe.WithScriptClassName("Script"), parseOptions: TestOptions.Script); compilation.VerifyDiagnostics( - // (12,57): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // from x2 in new[] { TakeOutParam(x1, out var z2) ? z2 : 0, z2, y2} - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z2").WithLocation(12, 57), // (14,21): error CS0103: The name 'z2' does not exist in the current context // z2; Diagnostic(ErrorCode.ERR_NameNotInContext, "z2").WithArguments("z2").WithLocation(14, 21), - // (19,47): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // let x2 = TakeOutParam(x1, out var z3) && z3 > 0 && y3 < 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z3").WithLocation(19, 47), // (21,25): error CS0103: The name 'z3' does not exist in the current context // z3}; Diagnostic(ErrorCode.ERR_NameNotInContext, "z3").WithArguments("z3").WithLocation(21, 25), // (28,29): error CS0103: The name 'v4' does not exist in the current context // v4 Diagnostic(ErrorCode.ERR_NameNotInContext, "v4").WithArguments("v4").WithLocation(28, 29), - // (27,64): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // on x1 + y4 + z4 + (TakeOutParam(3, out var u4) ? u4 : 0) + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "u4").WithLocation(27, 64), // (30,29): error CS1938: The name 'u4' is not in scope on the right side of 'equals'. Consider swapping the expressions on either side of 'equals'. // u4 Diagnostic(ErrorCode.ERR_QueryInnerKey, "u4").WithArguments("u4").WithLocation(30, 29), - // (29,72): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // equals x2 + y4 + z4 + (TakeOutParam(4, out var v4) ? v4 : 0) + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "v4").WithLocation(29, 72), // (32,25): error CS0103: The name 'u4' does not exist in the current context // u4, v4 }; Diagnostic(ErrorCode.ERR_NameNotInContext, "u4").WithArguments("u4").WithLocation(32, 25), @@ -22915,60 +24071,36 @@ static bool TakeOutParam(T y, out T x) // (41,29): error CS0103: The name 'v5' does not exist in the current context // v5 Diagnostic(ErrorCode.ERR_NameNotInContext, "v5").WithArguments("v5").WithLocation(41, 29), - // (40,64): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // on x1 + y5 + z5 + (TakeOutParam(3, out var u5) ? u5 : 0) + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "u5").WithLocation(40, 64), // (43,29): error CS1938: The name 'u5' is not in scope on the right side of 'equals'. Consider swapping the expressions on either side of 'equals'. // u5 Diagnostic(ErrorCode.ERR_QueryInnerKey, "u5").WithArguments("u5").WithLocation(43, 29), - // (42,72): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // equals x2 + y5 + z5 + (TakeOutParam(4, out var v5) ? v5 : 0) + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "v5").WithLocation(42, 72), // (46,25): error CS0103: The name 'u5' does not exist in the current context // u5, v5 }; Diagnostic(ErrorCode.ERR_NameNotInContext, "u5").WithArguments("u5").WithLocation(46, 25), // (46,29): error CS0103: The name 'v5' does not exist in the current context // u5, v5 }; Diagnostic(ErrorCode.ERR_NameNotInContext, "v5").WithArguments("v5").WithLocation(46, 29), - // (53,53): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // where x > y6 && TakeOutParam(1, out var z6) && z6 == 1 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z6").WithLocation(53, 53), // (55,21): error CS0103: The name 'z6' does not exist in the current context // z6; Diagnostic(ErrorCode.ERR_NameNotInContext, "z6").WithArguments("z6").WithLocation(55, 21), // (61,21): error CS0103: The name 'u7' does not exist in the current context // u7, Diagnostic(ErrorCode.ERR_NameNotInContext, "u7").WithArguments("u7").WithLocation(61, 21), - // (60,55): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // orderby x > y7 && TakeOutParam(1, out var z7) && z7 == - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z7").WithLocation(60, 55), // (63,21): error CS0103: The name 'z7' does not exist in the current context // z7 Diagnostic(ErrorCode.ERR_NameNotInContext, "z7").WithArguments("z7").WithLocation(63, 21), - // (62,55): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // x > y7 && TakeOutParam(1, out var u7) && u7 == - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "u7").WithLocation(62, 55), // (65,21): error CS0103: The name 'z7' does not exist in the current context // z7 + u7; Diagnostic(ErrorCode.ERR_NameNotInContext, "z7").WithArguments("z7").WithLocation(65, 21), // (65,26): error CS0103: The name 'u7' does not exist in the current context // z7 + u7; Diagnostic(ErrorCode.ERR_NameNotInContext, "u7").WithArguments("u7").WithLocation(65, 26), - // (71,54): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // select x > y8 && TakeOutParam(1, out var z8) && z8 == 1; - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z8").WithLocation(71, 54), // (80,17): error CS0103: The name 'z9' does not exist in the current context // z9; Diagnostic(ErrorCode.ERR_NameNotInContext, "z9").WithArguments("z9").WithLocation(80, 17), - // (79,51): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // x > y9 && TakeOutParam(1, out var u9) && u9 == - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "u9").WithLocation(79, 51), // (77,17): error CS0103: The name 'u9' does not exist in the current context // u9 Diagnostic(ErrorCode.ERR_NameNotInContext, "u9").WithArguments("u9").WithLocation(77, 17), - // (76,53): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // group x > y9 && TakeOutParam(1, out var z9) && z9 == - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z9").WithLocation(76, 53), // (16,7): error CS0103: The name 'z2' does not exist in the current context // Dummy(z2); Diagnostic(ErrorCode.ERR_NameNotInContext, "z2").WithArguments("z2").WithLocation(16, 7), @@ -23187,9 +24319,7 @@ static bool TakeOutParam(T y, out T x) (int)ErrorCode.ERR_TypeVarNotFound, (int)ErrorCode.ERR_TupleElementNamesAttributeMissing, (int)ErrorCode.ERR_IdentifierExpectedKW, - (int)ErrorCode.ERR_NameNotInContext, - (int)ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, - (int)ErrorCode.ERR_ExpressionVariableInQueryClause + (int)ErrorCode.ERR_NameNotInContext }; compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( @@ -26958,213 +28088,177 @@ public static bool TakeOutParam(T y, out T x) }; compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,32): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool b = H.TakeOutParam(1, out int x1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x1").WithLocation(3, 32), - // (7,32): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool d = H.TakeOutParam(2, out int x2); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x2").WithLocation(7, 32), - // (9,32): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool f = H.TakeOutParam(3, out int x3); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x3").WithLocation(9, 32), - // (12,41): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool h = H.Dummy(H.TakeOutParam(41, out int x4), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(12, 41), - // (13,41): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // H.TakeOutParam(42, out int x4)); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(13, 41), - // (13,45): error CS0128: A local variable named 'x4' is already defined in this scope - // H.TakeOutParam(42, out int x4)); - Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 45), - // (15,33): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool x5 = H.TakeOutParam(5, out int x5); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(15, 33), - // (20,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(20, 13), - // (20,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(20, 17), - // (20,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(20, 21), - // (20,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(20, 25), - // (20,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(20, 29) - ); - - var tree = compilation.SyntaxTrees.Single(); - var model = compilation.GetSemanticModel(tree); - - var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); - var x1Ref = GetReferences(tree, "x1").ToArray(); - Assert.Equal(2, x1Ref.Length); - VerifyModelForOutVar(model, x1Decl); - VerifyModelNotSupported(model, x1Ref); - - var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); - var x2Ref = GetReferences(tree, "x2").Single(); - VerifyModelForOutVar(model, x2Decl); - VerifyModelNotSupported(model, x2Ref); - - var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); - var x3Ref = GetReferences(tree, "x3").Single(); - VerifyModelForOutVar(model, x3Decl); - VerifyModelNotSupported(model, x3Ref); - - var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); - var x4Ref = GetReferences(tree, "x4").Single(); - Assert.Equal(2, x4Decl.Length); - VerifyModelForOutVar(model, x4Decl[0]); - VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); - VerifyModelNotSupported(model, x4Ref); - - var x5Decl = GetOutVarDeclarations(tree, "x5").Single(); - var x5Ref = GetReferences(tree, "x5").ToArray(); - Assert.Equal(2, x5Ref.Length); - VerifyModelForOutVar(model, x5Decl); - VerifyModelNotSupported(model, x5Ref); - } - } - - [Fact] - public void GlobalCode_LabeledStatement_05() - { - string source = -@" -a: -bool b = H.TakeOutParam(1, out var x1); -H.Dummy(x1); -object x2; -c: -bool d = H.TakeOutParam(2, out var x2); -e: -bool f = H.TakeOutParam(3, out var x3); -object x3; -g: -bool h = H.Dummy(H.TakeOutParam(41, out var x4), - H.TakeOutParam(42, out var x4)); -i: -bool x5 = H.TakeOutParam(5, out var x5); -H.Dummy(x5); - -void Test() -{ - H.Dummy(x1, x2, x3, x4, x5); -} - -class H -{ - public static bool Dummy(params object[] x) {return true;} - public static bool TakeOutParam(T y, out T x) - { - x = y; - return true; - } -} -"; - { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe.WithScriptClassName("Script"), parseOptions: TestOptions.Script); - - compilation.VerifyDiagnostics( - // (7,36): error CS0102: The type 'Script' already contains a definition for 'x2' - // bool d = H.TakeOutParam(2, out var x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("Script", "x2").WithLocation(7, 36), - // (10,8): error CS0102: The type 'Script' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("Script", "x3").WithLocation(10, 8), - // (13,45): error CS0102: The type 'Script' already contains a definition for 'x4' - // H.TakeOutParam(42, out var x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("Script", "x4").WithLocation(13, 45), - // (2,1): warning CS0164: This label has not been referenced - // a: - Diagnostic(ErrorCode.WRN_UnreferencedLabel, "a").WithLocation(2, 1), - // (6,1): warning CS0164: This label has not been referenced - // c: - Diagnostic(ErrorCode.WRN_UnreferencedLabel, "c").WithLocation(6, 1), - // (8,1): warning CS0164: This label has not been referenced - // e: - Diagnostic(ErrorCode.WRN_UnreferencedLabel, "e").WithLocation(8, 1), - // (11,1): warning CS0164: This label has not been referenced - // g: - Diagnostic(ErrorCode.WRN_UnreferencedLabel, "g").WithLocation(11, 1), - // (14,1): warning CS0164: This label has not been referenced - // i: - Diagnostic(ErrorCode.WRN_UnreferencedLabel, "i").WithLocation(14, 1), - // (20,17): error CS0229: Ambiguity between 'x2' and 'x2' - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_AmbigMember, "x2").WithArguments("x2", "x2").WithLocation(20, 17), - // (20,21): error CS0229: Ambiguity between 'x3' and 'x3' - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_AmbigMember, "x3").WithArguments("x3", "x3").WithLocation(20, 21), - // (20,25): error CS0229: Ambiguity between 'x4' and 'x4' - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_AmbigMember, "x4").WithArguments("x4", "x4").WithLocation(20, 25) - ); - - var tree = compilation.SyntaxTrees.Single(); - var model = compilation.GetSemanticModel(tree); - - var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); - var x1Ref = GetReferences(tree, "x1").ToArray(); - Assert.Equal(2, x1Ref.Length); - VerifyModelForOutField(model, x1Decl, x1Ref); - - var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); - var x2Ref = GetReferences(tree, "x2").Single(); - VerifyModelForOutFieldDuplicate(model, x2Decl, x2Ref); - - var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); - var x3Ref = GetReferences(tree, "x3").Single(); - VerifyModelForOutFieldDuplicate(model, x3Decl, x3Ref); - - var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); - var x4Ref = GetReferences(tree, "x4").Single(); - Assert.Equal(2, x4Decl.Length); - VerifyModelForOutFieldDuplicate(model, x4Decl[0], x4Ref); - VerifyModelForOutFieldDuplicate(model, x4Decl[1], x4Ref); - - var x5Decl = GetOutVarDeclarations(tree, "x5").Single(); - var x5Ref = GetReferences(tree, "x5").ToArray(); - Assert.Equal(2, x5Ref.Length); - VerifyModelForOutField(model, x5Decl, x5Ref); - } - - { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,32): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool b = H.TakeOutParam(1, out var x1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x1").WithLocation(3, 32), - // (7,32): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. + // (13,45): error CS0128: A local variable named 'x4' is already defined in this scope + // H.TakeOutParam(42, out int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 45), + // (20,13): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(20, 13), + // (20,17): error CS0103: The name 'x2' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(20, 17), + // (20,21): error CS0103: The name 'x3' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(20, 21), + // (20,25): error CS0103: The name 'x4' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(20, 25), + // (20,29): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(20, 29) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl); + VerifyModelNotSupported(model, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVar(model, x2Decl); + VerifyModelNotSupported(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl); + VerifyModelNotSupported(model, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0]); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); + VerifyModelNotSupported(model, x4Ref); + + var x5Decl = GetOutVarDeclarations(tree, "x5").Single(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(2, x5Ref.Length); + VerifyModelForOutVar(model, x5Decl); + VerifyModelNotSupported(model, x5Ref); + } + } + + [Fact] + public void GlobalCode_LabeledStatement_05() + { + string source = +@" +a: +bool b = H.TakeOutParam(1, out var x1); +H.Dummy(x1); +object x2; +c: +bool d = H.TakeOutParam(2, out var x2); +e: +bool f = H.TakeOutParam(3, out var x3); +object x3; +g: +bool h = H.Dummy(H.TakeOutParam(41, out var x4), + H.TakeOutParam(42, out var x4)); +i: +bool x5 = H.TakeOutParam(5, out var x5); +H.Dummy(x5); + +void Test() +{ + H.Dummy(x1, x2, x3, x4, x5); +} + +class H +{ + public static bool Dummy(params object[] x) {return true;} + public static bool TakeOutParam(T y, out T x) + { + x = y; + return true; + } +} +"; + { + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe.WithScriptClassName("Script"), parseOptions: TestOptions.Script); + + compilation.VerifyDiagnostics( + // (7,36): error CS0102: The type 'Script' already contains a definition for 'x2' // bool d = H.TakeOutParam(2, out var x2); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x2").WithLocation(7, 32), - // (9,32): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool f = H.TakeOutParam(3, out var x3); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x3").WithLocation(9, 32), - // (12,41): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool h = H.Dummy(H.TakeOutParam(41, out var x4), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x4").WithLocation(12, 41), - // (13,41): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. + Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("Script", "x2").WithLocation(7, 36), + // (10,8): error CS0102: The type 'Script' already contains a definition for 'x3' + // object x3; + Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("Script", "x3").WithLocation(10, 8), + // (13,45): error CS0102: The type 'Script' already contains a definition for 'x4' // H.TakeOutParam(42, out var x4)); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x4").WithLocation(13, 41), + Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("Script", "x4").WithLocation(13, 45), + // (2,1): warning CS0164: This label has not been referenced + // a: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "a").WithLocation(2, 1), + // (6,1): warning CS0164: This label has not been referenced + // c: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "c").WithLocation(6, 1), + // (8,1): warning CS0164: This label has not been referenced + // e: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "e").WithLocation(8, 1), + // (11,1): warning CS0164: This label has not been referenced + // g: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "g").WithLocation(11, 1), + // (14,1): warning CS0164: This label has not been referenced + // i: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "i").WithLocation(14, 1), + // (20,17): error CS0229: Ambiguity between 'x2' and 'x2' + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_AmbigMember, "x2").WithArguments("x2", "x2").WithLocation(20, 17), + // (20,21): error CS0229: Ambiguity between 'x3' and 'x3' + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_AmbigMember, "x3").WithArguments("x3", "x3").WithLocation(20, 21), + // (20,25): error CS0229: Ambiguity between 'x4' and 'x4' + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_AmbigMember, "x4").WithArguments("x4", "x4").WithLocation(20, 25) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutField(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutFieldDuplicate(model, x2Decl, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutFieldDuplicate(model, x3Decl, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutFieldDuplicate(model, x4Decl[0], x4Ref); + VerifyModelForOutFieldDuplicate(model, x4Decl[1], x4Ref); + + var x5Decl = GetOutVarDeclarations(tree, "x5").Single(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(2, x5Ref.Length); + VerifyModelForOutField(model, x5Decl, x5Ref); + } + + { + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); + int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, + (int)ErrorCode.ERR_CloseParenExpected, + (int)ErrorCode.ERR_SemicolonExpected, + (int)ErrorCode.ERR_TypeExpected, + (int)ErrorCode.ERR_NamespaceUnexpected, + (int)ErrorCode.ERR_TupleTooFewElements + }; + + compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( // (13,45): error CS0128: A local variable named 'x4' is already defined in this scope // H.TakeOutParam(42, out var x4)); Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 45), - // (15,33): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool x5 = H.TakeOutParam(5, out var x5); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x5").WithLocation(15, 33), // (20,13): error CS0103: The name 'x1' does not exist in the current context // H.Dummy(x1, x2, x3, x4, x5); Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(20, 13), @@ -27770,30 +28864,9 @@ public static bool TakeOutParam(T y, out T x) }; compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,32): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool b = H.TakeOutParam(1, out int x1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x1").WithLocation(3, 32), - // (7,32): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool d = H.TakeOutParam(2, out int x2); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x2").WithLocation(7, 32), - // (9,32): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool f = H.TakeOutParam(3, out int x3); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x3").WithLocation(9, 32), - // (12,41): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool h = H.Dummy(H.TakeOutParam(41, out int x4), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(12, 41), - // (13,41): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // H.TakeOutParam(42, out int x4)); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(13, 41), // (13,45): error CS0128: A local variable named 'x4' is already defined in this scope // H.TakeOutParam(42, out int x4)); Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 45), - // (16,33): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // H.TakeOutParam(5, out int x5); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(16, 33), - // (18,32): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool i = H.TakeOutParam(5, out int x6), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(18, 32), // (23,13): error CS0103: The name 'x1' does not exist in the current context // H.Dummy(x1, x2, x3, x4, x5, x6); Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), @@ -27969,30 +29042,9 @@ public static bool TakeOutParam(T y, out T x) }; compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,32): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool b = H.TakeOutParam(1, out var x1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x1").WithLocation(3, 32), - // (7,32): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool d = H.TakeOutParam(2, out var x2); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x2").WithLocation(7, 32), - // (9,32): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool f = H.TakeOutParam(3, out var x3); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x3").WithLocation(9, 32), - // (12,41): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool h = H.Dummy(H.TakeOutParam(41, out var x4), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x4").WithLocation(12, 41), - // (13,41): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // H.TakeOutParam(42, out var x4)); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x4").WithLocation(13, 41), // (13,45): error CS0128: A local variable named 'x4' is already defined in this scope // H.TakeOutParam(42, out var x4)); Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 45), - // (16,33): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // H.TakeOutParam(5, out var x5); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x5").WithLocation(16, 33), - // (18,32): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool i = H.TakeOutParam(5, out var x6), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x6").WithLocation(18, 32), // (23,13): error CS0103: The name 'x1' does not exist in the current context // H.Dummy(x1, x2, x3, x4, x5, x6); Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), @@ -28381,202 +29433,166 @@ public static bool TakeOutParam(T y, out T x) }; compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,41): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool b { get; } = H.TakeOutParam(1, out int x1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x1").WithLocation(3, 41), - // (7,41): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool d { get; } = H.TakeOutParam(2, out int x2); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x2").WithLocation(7, 41), - // (9,41): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool f { get; } = H.TakeOutParam(3, out int x3); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x3").WithLocation(9, 41), - // (12,50): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool h { get; } = H.Dummy(H.TakeOutParam(41, out int x4), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(12, 50), - // (13,50): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // H.TakeOutParam(42, out int x4)); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(13, 50), - // (13,54): error CS0128: A local variable named 'x4' is already defined in this scope - // H.TakeOutParam(42, out int x4)); - Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 54), - // (16,33): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // H.TakeOutParam(5, out int x5); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(16, 33), - // (20,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(20, 13), - // (20,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(20, 17), - // (20,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(20, 21), - // (20,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(20, 25), - // (20,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(20, 29) - ); - - var tree = compilation.SyntaxTrees.Single(); - var model = compilation.GetSemanticModel(tree); - - var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); - var x1Ref = GetReferences(tree, "x1").ToArray(); - Assert.Equal(2, x1Ref.Length); - VerifyModelForOutVar(model, x1Decl); - VerifyModelNotSupported(model, x1Ref); - - var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); - var x2Ref = GetReferences(tree, "x2").Single(); - VerifyModelForOutVar(model, x2Decl); - VerifyModelNotSupported(model, x2Ref); - - var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); - var x3Ref = GetReferences(tree, "x3").Single(); - VerifyModelForOutVar(model, x3Decl); - VerifyModelNotSupported(model, x3Ref); - - var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); - var x4Ref = GetReferences(tree, "x4").Single(); - Assert.Equal(2, x4Decl.Length); - VerifyModelForOutVar(model, x4Decl[0]); - VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); - VerifyModelNotSupported(model, x4Ref); - - var x5Decl = GetOutVarDeclarations(tree, "x5").Single(); - var x5Ref = GetReferences(tree, "x5").Single(); - VerifyModelForOutVar(model, x5Decl); - VerifyModelNotSupported(model, x5Ref); - } - } - - [Fact] - public void GlobalCode_PropertyDeclaration_02() - { - string source = -@" - -bool b { get; } = H.TakeOutParam(1, out var x1); -H.Dummy(x1); - -object x2; -bool d { get; } = H.TakeOutParam(2, out var x2); - -bool f { get; } = H.TakeOutParam(3, out var x3); -object x3; - -bool h { get; } = H.Dummy(H.TakeOutParam(41, out var x4), - H.TakeOutParam(42, out var x4)); - -bool x5 { get; } = - H.TakeOutParam(5, out var x5); - -void Test() -{ - H.Dummy(x1, x2, x3, x4, x5); -} - -class H -{ - public static bool Dummy(params object[] x) {return true;} - public static bool TakeOutParam(T y, out T x) - { - x = y; - return true; - } -} -"; - { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe.WithScriptClassName("Script"), parseOptions: TestOptions.Script); - - compilation.VerifyDiagnostics( - // (7,45): error CS0102: The type 'Script' already contains a definition for 'x2' - // bool d { get; } = H.TakeOutParam(2, out var x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("Script", "x2").WithLocation(7, 45), - // (10,8): error CS0102: The type 'Script' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("Script", "x3").WithLocation(10, 8), - // (13,54): error CS0102: The type 'Script' already contains a definition for 'x4' - // H.TakeOutParam(42, out var x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("Script", "x4").WithLocation(13, 54), - // (16,37): error CS0102: The type 'Script' already contains a definition for 'x5' - // H.TakeOutParam(5, out var x5); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("Script", "x5").WithLocation(16, 37), - // (20,17): error CS0229: Ambiguity between 'x2' and 'x2' - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_AmbigMember, "x2").WithArguments("x2", "x2").WithLocation(20, 17), - // (20,21): error CS0229: Ambiguity between 'x3' and 'x3' - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_AmbigMember, "x3").WithArguments("x3", "x3").WithLocation(20, 21), - // (20,25): error CS0229: Ambiguity between 'x4' and 'x4' - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_AmbigMember, "x4").WithArguments("x4", "x4").WithLocation(20, 25), - // (20,29): error CS0229: Ambiguity between 'x5' and 'x5' - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_AmbigMember, "x5").WithArguments("x5", "x5").WithLocation(20, 29) - ); - - var tree = compilation.SyntaxTrees.Single(); - var model = compilation.GetSemanticModel(tree); - - var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); - var x1Ref = GetReferences(tree, "x1").ToArray(); - Assert.Equal(2, x1Ref.Length); - VerifyModelForOutField(model, x1Decl, x1Ref); - - var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); - var x2Ref = GetReferences(tree, "x2").Single(); - VerifyModelForOutFieldDuplicate(model, x2Decl, x2Ref); - - var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); - var x3Ref = GetReferences(tree, "x3").Single(); - VerifyModelForOutFieldDuplicate(model, x3Decl, x3Ref); - - var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); - var x4Ref = GetReferences(tree, "x4").Single(); - Assert.Equal(2, x4Decl.Length); - VerifyModelForOutFieldDuplicate(model, x4Decl[0], x4Ref); - VerifyModelForOutFieldDuplicate(model, x4Decl[1], x4Ref); - - var x5Decl = GetOutVarDeclarations(tree, "x5").Single(); - var x5Ref = GetReferences(tree, "x5").Single(); - VerifyModelForOutFieldDuplicate(model, x5Decl, x5Ref); - } - - { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,41): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool b { get; } = H.TakeOutParam(1, out var x1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x1").WithLocation(3, 41), - // (7,41): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. + // (13,54): error CS0128: A local variable named 'x4' is already defined in this scope + // H.TakeOutParam(42, out int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 54), + // (20,13): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(20, 13), + // (20,17): error CS0103: The name 'x2' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(20, 17), + // (20,21): error CS0103: The name 'x3' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(20, 21), + // (20,25): error CS0103: The name 'x4' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(20, 25), + // (20,29): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(20, 29) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl); + VerifyModelNotSupported(model, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVar(model, x2Decl); + VerifyModelNotSupported(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl); + VerifyModelNotSupported(model, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0]); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); + VerifyModelNotSupported(model, x4Ref); + + var x5Decl = GetOutVarDeclarations(tree, "x5").Single(); + var x5Ref = GetReferences(tree, "x5").Single(); + VerifyModelForOutVar(model, x5Decl); + VerifyModelNotSupported(model, x5Ref); + } + } + + [Fact] + public void GlobalCode_PropertyDeclaration_02() + { + string source = +@" + +bool b { get; } = H.TakeOutParam(1, out var x1); +H.Dummy(x1); + +object x2; +bool d { get; } = H.TakeOutParam(2, out var x2); + +bool f { get; } = H.TakeOutParam(3, out var x3); +object x3; + +bool h { get; } = H.Dummy(H.TakeOutParam(41, out var x4), + H.TakeOutParam(42, out var x4)); + +bool x5 { get; } = + H.TakeOutParam(5, out var x5); + +void Test() +{ + H.Dummy(x1, x2, x3, x4, x5); +} + +class H +{ + public static bool Dummy(params object[] x) {return true;} + public static bool TakeOutParam(T y, out T x) + { + x = y; + return true; + } +} +"; + { + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe.WithScriptClassName("Script"), parseOptions: TestOptions.Script); + + compilation.VerifyDiagnostics( + // (7,45): error CS0102: The type 'Script' already contains a definition for 'x2' // bool d { get; } = H.TakeOutParam(2, out var x2); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x2").WithLocation(7, 41), - // (9,41): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool f { get; } = H.TakeOutParam(3, out var x3); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x3").WithLocation(9, 41), - // (12,50): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool h { get; } = H.Dummy(H.TakeOutParam(41, out var x4), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x4").WithLocation(12, 50), - // (13,50): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. + Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("Script", "x2").WithLocation(7, 45), + // (10,8): error CS0102: The type 'Script' already contains a definition for 'x3' + // object x3; + Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("Script", "x3").WithLocation(10, 8), + // (13,54): error CS0102: The type 'Script' already contains a definition for 'x4' // H.TakeOutParam(42, out var x4)); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x4").WithLocation(13, 50), + Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("Script", "x4").WithLocation(13, 54), + // (16,37): error CS0102: The type 'Script' already contains a definition for 'x5' + // H.TakeOutParam(5, out var x5); + Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("Script", "x5").WithLocation(16, 37), + // (20,17): error CS0229: Ambiguity between 'x2' and 'x2' + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_AmbigMember, "x2").WithArguments("x2", "x2").WithLocation(20, 17), + // (20,21): error CS0229: Ambiguity between 'x3' and 'x3' + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_AmbigMember, "x3").WithArguments("x3", "x3").WithLocation(20, 21), + // (20,25): error CS0229: Ambiguity between 'x4' and 'x4' + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_AmbigMember, "x4").WithArguments("x4", "x4").WithLocation(20, 25), + // (20,29): error CS0229: Ambiguity between 'x5' and 'x5' + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_AmbigMember, "x5").WithArguments("x5", "x5").WithLocation(20, 29) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutField(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutFieldDuplicate(model, x2Decl, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutFieldDuplicate(model, x3Decl, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutFieldDuplicate(model, x4Decl[0], x4Ref); + VerifyModelForOutFieldDuplicate(model, x4Decl[1], x4Ref); + + var x5Decl = GetOutVarDeclarations(tree, "x5").Single(); + var x5Ref = GetReferences(tree, "x5").Single(); + VerifyModelForOutFieldDuplicate(model, x5Decl, x5Ref); + } + + { + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); + int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, + (int)ErrorCode.ERR_CloseParenExpected, + (int)ErrorCode.ERR_SemicolonExpected, + (int)ErrorCode.ERR_TypeExpected, + (int)ErrorCode.ERR_NamespaceUnexpected, + (int)ErrorCode.ERR_TupleTooFewElements + }; + + compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( // (13,54): error CS0128: A local variable named 'x4' is already defined in this scope // H.TakeOutParam(42, out var x4)); Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 54), - // (16,33): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // H.TakeOutParam(5, out var x5); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x5").WithLocation(16, 33), // (20,13): error CS0103: The name 'x1' does not exist in the current context // H.Dummy(x1, x2, x3, x4, x5); Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(20, 13), @@ -28926,30 +29942,9 @@ public static System.Action TakeOutParam(T y, out T x) }; compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,47): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // event System.Action b = H.TakeOutParam(1, out int x1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x1").WithLocation(3, 47), - // (7,47): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // event System.Action d = H.TakeOutParam(2, out int x2); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x2").WithLocation(7, 47), - // (9,47): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // event System.Action f = H.TakeOutParam(3, out int x3); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x3").WithLocation(9, 47), - // (12,56): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // event System.Action h = H.Dummy(H.TakeOutParam(41, out int x4), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(12, 56), - // (13,48): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // H.TakeOutParam(42, out int x4)); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(13, 48), // (13,52): error CS0128: A local variable named 'x4' is already defined in this scope // H.TakeOutParam(42, out int x4)); Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 52), - // (16,33): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // H.TakeOutParam(5, out int x5); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(16, 33), - // (18,47): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // event System.Action i = H.TakeOutParam(5, out int x6), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(18, 47), // (23,13): error CS0103: The name 'x1' does not exist in the current context // H.Dummy(x1, x2, x3, x4, x5, x6); Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), @@ -29125,30 +30120,9 @@ public static System.Action TakeOutParam(T y, out T x) }; compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,47): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // event System.Action b = H.TakeOutParam(1, out var x1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x1").WithLocation(3, 47), - // (7,47): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // event System.Action d = H.TakeOutParam(2, out var x2); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x2").WithLocation(7, 47), - // (9,47): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // event System.Action f = H.TakeOutParam(3, out var x3); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x3").WithLocation(9, 47), - // (12,56): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // event System.Action h = H.Dummy(H.TakeOutParam(41, out var x4), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x4").WithLocation(12, 56), - // (13,48): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // H.TakeOutParam(42, out var x4)); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x4").WithLocation(13, 48), // (13,52): error CS0128: A local variable named 'x4' is already defined in this scope // H.TakeOutParam(42, out var x4)); Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 52), - // (16,33): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // H.TakeOutParam(5, out var x5); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x5").WithLocation(16, 33), - // (18,47): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // event System.Action i = H.TakeOutParam(5, out var x6), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x6").WithLocation(18, 47), // (23,13): error CS0103: The name 'x1' does not exist in the current context // H.Dummy(x1, x2, x3, x4, x5, x6); Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), @@ -32192,9 +33166,6 @@ class C "; var compilation = CreateCompilationWithMscorlib45(text); compilation.VerifyDiagnostics( - // (5,35): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // const bool b = M(nameof(M(out var z2)), z2); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var z2").WithLocation(5, 35), // (5,29): error CS8081: Expression does not have a name. // const bool b = M(nameof(M(out var z2)), z2); Diagnostic(ErrorCode.ERR_ExpressionHasNoName, "M(out var z2)").WithLocation(5, 29), @@ -32207,9 +33178,6 @@ class C // (6,26): error CS0103: The name 'z2' does not exist in the current context // const bool c = (z1 + z2) == 0; Diagnostic(ErrorCode.ERR_NameNotInContext, "z2").WithArguments("z2").WithLocation(6, 26), - // (4,35): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // const bool a = M(nameof(M(out int z1)), z1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int z1").WithLocation(4, 35), // (4,29): error CS8081: Expression does not have a name. // const bool a = M(nameof(M(out int z1)), z1); Diagnostic(ErrorCode.ERR_ExpressionHasNoName, "M(out int z1)").WithLocation(4, 29), @@ -32809,10 +33777,7 @@ static bool F(out object o) } }"; var comp = CreateCompilationWithMscorlib40AndSystemCore(source); - comp.VerifyDiagnostics( - // (7,38): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // group x > 1 && F(out var y) && y == null - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y").WithLocation(7, 38)); + comp.VerifyDiagnostics(); } [Fact] @@ -33079,6 +34044,339 @@ public class C ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1') "); } + + [Fact] + public void EventInitializers_01() + { + var source = +@" +public class X +{ + public static void Main() + { + System.Console.WriteLine(Test1()); + } + + static event System.Func Test1 = GetDelegate(TakeOutParam(1, out int x1) && Dummy(x1)); + + static System.Func GetDelegate(bool value) => () => value; + + static bool Dummy(int x) + { + System.Console.WriteLine(x); + return true; + } + + static bool TakeOutParam(int y, out int x) + { + x = y; + return true; + } +} +"; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + CompileAndVerify(compilation, expectedOutput: @"1 +True"); + + CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_2).VerifyDiagnostics( + // (9,76): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. + // static event System.Func Test1 = GetDelegate(TakeOutParam(1, out int x1) && Dummy(x1)); + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "int x1").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(9, 76) + ); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ConstructorBodyOperation() + { + var text = @" +public class C +{ + C() : this(out var x) + { M(out var y); } + => M(out var z); + + C (out int x){x=1;} + void M (out int x){x=1;} +} + + +"; + var compilation = CreateCompilation(text, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var initializerSyntax = tree.GetRoot().DescendantNodes().OfType().Single(); + + Assert.Equal(": this(out var x)", initializerSyntax.ToString()); + + compilation.VerifyOperationTree(initializerSyntax, expectedOperationTree: +@" +IInvocationOperation ( C..ctor(out System.Int32 x)) (OperationKind.Invocation, Type: System.Void, IsInvalid) (Syntax: ': this(out var x)') + Instance Receiver: + IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsInvalid, IsImplicit) (Syntax: ': this(out var x)') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null, IsInvalid) (Syntax: 'out var x') + IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32, IsInvalid) (Syntax: 'var x') + ILocalReferenceOperation: x (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'x') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) +"); + IOperation initializerOperation = model.GetOperation(initializerSyntax); + Assert.Equal(OperationKind.ExpressionStatement, initializerOperation.Parent.Kind); + + var blockBodySyntax = tree.GetRoot().DescendantNodes().OfType().First(); + + Assert.Equal("{ M(out var y); }", blockBodySyntax.ToString()); + + compilation.VerifyOperationTree(blockBodySyntax, expectedOperationTree: +@" +IBlockOperation (1 statements, 1 locals) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '{ M(out var y); }') + Locals: Local_1: System.Int32 y + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid) (Syntax: 'M(out var y);') + Expression: + IInvocationOperation ( void C.M(out System.Int32 x)) (OperationKind.Invocation, Type: System.Void, IsInvalid) (Syntax: 'M(out var y)') + Instance Receiver: + IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsInvalid, IsImplicit) (Syntax: 'M') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null, IsInvalid) (Syntax: 'out var y') + IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32, IsInvalid) (Syntax: 'var y') + ILocalReferenceOperation: y (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'y') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) +"); + IOperation blockBodyOperation = model.GetOperation(blockBodySyntax); + Assert.Equal(OperationKind.ConstructorBodyOperation, blockBodyOperation.Parent.Kind); + Assert.Same(initializerOperation.Parent.Parent, blockBodyOperation.Parent); + Assert.Null(blockBodyOperation.Parent.Parent); + + var expressionBodySyntax = tree.GetRoot().DescendantNodes().OfType().First(); + + Assert.Equal("=> M(out var z)", expressionBodySyntax.ToString()); + + compilation.VerifyOperationTree(expressionBodySyntax, expectedOperationTree: +@" +IBlockOperation (1 statements, 1 locals) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '=> M(out var z)') + Locals: Local_1: System.Int32 z + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid, IsImplicit) (Syntax: 'M(out var z)') + Expression: + IInvocationOperation ( void C.M(out System.Int32 x)) (OperationKind.Invocation, Type: System.Void, IsInvalid) (Syntax: 'M(out var z)') + Instance Receiver: + IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsInvalid, IsImplicit) (Syntax: 'M') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null, IsInvalid) (Syntax: 'out var z') + IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32, IsInvalid) (Syntax: 'var z') + ILocalReferenceOperation: z (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'z') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) +"); + + Assert.Same(blockBodyOperation.Parent, model.GetOperation(expressionBodySyntax).Parent); + + var declarationSyntax = tree.GetRoot().DescendantNodes().OfType().First(); + + Assert.Same(blockBodyOperation.Parent, model.GetOperation(declarationSyntax)); + + compilation.VerifyOperationTree(declarationSyntax, expectedOperationTree: +@" +IConstructorBodyOperation (OperationKind.ConstructorBodyOperation, Type: null, IsInvalid) (Syntax: 'C() : this( ... out var z);') + Locals: Local_1: System.Int32 x + Initializer: + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid, IsImplicit) (Syntax: ': this(out var x)') + Expression: + IInvocationOperation ( C..ctor(out System.Int32 x)) (OperationKind.Invocation, Type: System.Void, IsInvalid) (Syntax: ': this(out var x)') + Instance Receiver: + IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsInvalid, IsImplicit) (Syntax: ': this(out var x)') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null, IsInvalid) (Syntax: 'out var x') + IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32, IsInvalid) (Syntax: 'var x') + ILocalReferenceOperation: x (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'x') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + BlockBody: + IBlockOperation (1 statements, 1 locals) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '{ M(out var y); }') + Locals: Local_1: System.Int32 y + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid) (Syntax: 'M(out var y);') + Expression: + IInvocationOperation ( void C.M(out System.Int32 x)) (OperationKind.Invocation, Type: System.Void, IsInvalid) (Syntax: 'M(out var y)') + Instance Receiver: + IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsInvalid, IsImplicit) (Syntax: 'M') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null, IsInvalid) (Syntax: 'out var y') + IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32, IsInvalid) (Syntax: 'var y') + ILocalReferenceOperation: y (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'y') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + ExpressionBody: + IBlockOperation (1 statements, 1 locals) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '=> M(out var z)') + Locals: Local_1: System.Int32 z + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid, IsImplicit) (Syntax: 'M(out var z)') + Expression: + IInvocationOperation ( void C.M(out System.Int32 x)) (OperationKind.Invocation, Type: System.Void, IsInvalid) (Syntax: 'M(out var z)') + Instance Receiver: + IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsInvalid, IsImplicit) (Syntax: 'M') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null, IsInvalid) (Syntax: 'out var z') + IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32, IsInvalid) (Syntax: 'var z') + ILocalReferenceOperation: z (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'z') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) +"); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void MethodBodyOperation() + { + var text = @" +public class C +{ + int P + { + get {return M(out var x);} => M(out var y); + } => M(out var z); + + int M (out int x){x=1; return 1;} +} + + +"; + var compilation = CreateCompilation(text, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var expressionBodySyntax = tree.GetRoot().DescendantNodes().OfType().First(); + + Assert.Equal("=> M(out var y)", expressionBodySyntax.ToString()); + + compilation.VerifyOperationTree(expressionBodySyntax, expectedOperationTree: +@" +IBlockOperation (1 statements, 1 locals) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '=> M(out var y)') + Locals: Local_1: System.Int32 y + IReturnOperation (OperationKind.Return, Type: null, IsInvalid, IsImplicit) (Syntax: 'M(out var y)') + ReturnedValue: + IInvocationOperation ( System.Int32 C.M(out System.Int32 x)) (OperationKind.Invocation, Type: System.Int32, IsInvalid) (Syntax: 'M(out var y)') + Instance Receiver: + IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsInvalid, IsImplicit) (Syntax: 'M') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null, IsInvalid) (Syntax: 'out var y') + IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32, IsInvalid) (Syntax: 'var y') + ILocalReferenceOperation: y (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'y') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) +"); + IOperation expressionBodyOperation = model.GetOperation(expressionBodySyntax); + Assert.Equal(OperationKind.MethodBodyOperation, expressionBodyOperation.Parent.Kind); + Assert.Null(expressionBodyOperation.Parent.Parent); + + var blockBodySyntax = tree.GetRoot().DescendantNodes().OfType().First(); + + Assert.Equal("{return M(out var x);}", blockBodySyntax.ToString()); + + compilation.VerifyOperationTree(blockBodySyntax, expectedOperationTree: +@" +IBlockOperation (1 statements, 1 locals) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '{return M(out var x);}') + Locals: Local_1: System.Int32 x + IReturnOperation (OperationKind.Return, Type: null, IsInvalid) (Syntax: 'return M(out var x);') + ReturnedValue: + IInvocationOperation ( System.Int32 C.M(out System.Int32 x)) (OperationKind.Invocation, Type: System.Int32, IsInvalid) (Syntax: 'M(out var x)') + Instance Receiver: + IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsInvalid, IsImplicit) (Syntax: 'M') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null, IsInvalid) (Syntax: 'out var x') + IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32, IsInvalid) (Syntax: 'var x') + ILocalReferenceOperation: x (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'x') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) +"); + + IOperation blockBodyOperation = model.GetOperation(blockBodySyntax); + Assert.Same(expressionBodyOperation.Parent, blockBodyOperation.Parent); + + var propertyExpressionBodySyntax = tree.GetRoot().DescendantNodes().OfType().ElementAt(1); + + Assert.Equal("=> M(out var z)", propertyExpressionBodySyntax.ToString()); + Assert.Null(model.GetOperation(propertyExpressionBodySyntax)); // https://github.com/dotnet/roslyn/issues/24900 + + var declarationSyntax = tree.GetRoot().DescendantNodes().OfType().Single(); + Assert.Same(expressionBodyOperation.Parent, model.GetOperation(declarationSyntax)); + compilation.VerifyOperationTree(declarationSyntax, expectedOperationTree: +@" +IMethodBodyOperation (OperationKind.MethodBodyOperation, Type: null, IsInvalid) (Syntax: 'get {return ... out var y);') + BlockBody: + IBlockOperation (1 statements, 1 locals) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '{return M(out var x);}') + Locals: Local_1: System.Int32 x + IReturnOperation (OperationKind.Return, Type: null, IsInvalid) (Syntax: 'return M(out var x);') + ReturnedValue: + IInvocationOperation ( System.Int32 C.M(out System.Int32 x)) (OperationKind.Invocation, Type: System.Int32, IsInvalid) (Syntax: 'M(out var x)') + Instance Receiver: + IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsInvalid, IsImplicit) (Syntax: 'M') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null, IsInvalid) (Syntax: 'out var x') + IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32, IsInvalid) (Syntax: 'var x') + ILocalReferenceOperation: x (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'x') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + ExpressionBody: + IBlockOperation (1 statements, 1 locals) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '=> M(out var y)') + Locals: Local_1: System.Int32 y + IReturnOperation (OperationKind.Return, Type: null, IsInvalid, IsImplicit) (Syntax: 'M(out var y)') + ReturnedValue: + IInvocationOperation ( System.Int32 C.M(out System.Int32 x)) (OperationKind.Invocation, Type: System.Int32, IsInvalid) (Syntax: 'M(out var y)') + Instance Receiver: + IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsInvalid, IsImplicit) (Syntax: 'M') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null, IsInvalid) (Syntax: 'out var y') + IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32, IsInvalid) (Syntax: 'var y') + ILocalReferenceOperation: y (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'y') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) +"); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void PropertyExpressionBodyOperation() + { + var text = @" +public class C +{ + int P => M(out var z); + + int M (out int x){x=1; return 1;} +} + + +"; + var compilation = CreateCompilation(text, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var node3 = tree.GetRoot().DescendantNodes().OfType().First(); + + Assert.Equal("=> M(out var z)", node3.ToString()); + + compilation.VerifyOperationTree(node3, expectedOperationTree: +@" +IBlockOperation (1 statements, 1 locals) (OperationKind.Block, Type: null) (Syntax: '=> M(out var z)') + Locals: Local_1: System.Int32 z + IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: 'M(out var z)') + ReturnedValue: + IInvocationOperation ( System.Int32 C.M(out System.Int32 x)) (OperationKind.Invocation, Type: System.Int32) (Syntax: 'M(out var z)') + Instance Receiver: + IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'M') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: 'out var z') + IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32) (Syntax: 'var z') + ILocalReferenceOperation: z (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'z') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) +"); + Assert.Null(model.GetOperation(node3).Parent); + } } internal static class OutVarTestsExtensions diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs index 742efe92cbbe3..c08a47802b9b0 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs @@ -251,7 +251,6 @@ public D(object o) : this(o is int x && x >= 5) {} } "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); -#if ALLOW_IN_CONSTRUCTOR_INITIALIZER compilation.VerifyDiagnostics( ); var expectedOutput = @@ -259,13 +258,6 @@ public D(object o) : this(o is int x && x >= 5) {} True False"; var comp = CompileAndVerify(compilation, expectedOutput: expectedOutput); -#else - compilation.VerifyDiagnostics( - // (13,36): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // public D(object o) : this(o is int x && x >= 5) {} - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x").WithLocation(13, 36) - ); -#endif } [Fact] @@ -334,7 +326,6 @@ private static bool M(object o, bool result) } "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); -#if ALLOW_IN_FIELD_INITIALIZER compilation.VerifyDiagnostics(); using (new EnsureInvariantCulture()) { @@ -344,19 +335,6 @@ private static bool M(object o, bool result) False for 1.2"; var comp = CompileAndVerify(compilation, expectedOutput: expectedOutput); } -#else - compilation.VerifyDiagnostics( - // (7,35): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // static bool b1 = M(o1, (o1 is int x && x >= 5)), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x").WithLocation(7, 35), - // (8,35): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // b2 = M(o2, (o2 is int x && x >= 5)), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x").WithLocation(8, 35), - // (9,35): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // b3 = M(o3, (o3 is int x && x >= 5)); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x").WithLocation(9, 35) - ); -#endif } [Fact] @@ -845,57 +823,22 @@ static bool Print(object x) } "; var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe); - compilation.VerifyDiagnostics( - // (14,47): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // from x2 in new[] { 2 is var y2 && Print(y2) ? 1 : 0} - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y2").WithLocation(14, 47), - // (16,36): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // on 4 is var y4 && Print(y4) ? 1 : 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y4").WithLocation(16, 36), - // (17,43): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // equals 5 is var y5 && Print(y5) ? 1 : 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y5").WithLocation(17, 43), - // (18,34): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // where 6 is var y6 && Print(y6) - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y6").WithLocation(18, 34), - // (19,36): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // orderby 7 is var y7 && Print(y7), - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y7").WithLocation(19, 36), - // (20,36): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // 8 is var y8 && Print(y8) - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y8").WithLocation(20, 36), - // (22,32): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // by 10 is var y10 && Print(y10) - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y10").WithLocation(22, 32), - // (21,34): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // group 9 is var y9 && Print(y9) - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y9").WithLocation(21, 34), - // (24,39): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // let x11 = 11 is var y11 && Print(y11) - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y11").WithLocation(24, 39), - // (25,36): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // select 12 is var y12 && Print(y12); - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y12").WithLocation(25, 36) - ); + compilation.VerifyDiagnostics(); - // Because expression variables are not permitted in query clauses (https://github.com/dotnet/roslyn/issues/15910) - // this program cannot be run. However, once we allow that (https://github.com/dotnet/roslyn/issues/15619) - // the program wil be capable of being run. In that case the following (commented code) would test for the expected output. - -// CompileAndVerify(compilation, expectedOutput: -//@"1 -//3 -//5 -//2 -//4 -//6 -//7 -//8 -//10 -//9 -//11 -//12 -//"); + CompileAndVerify(compilation, expectedOutput: +@"1 +3 +5 +2 +4 +6 +7 +8 +10 +9 +11 +12 +"); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); @@ -1031,16 +974,14 @@ static bool Dummy(int x) } "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); -#if ALLOW_IN_FIELD_INITIALIZER CompileAndVerify(compilation, expectedOutput: @"1 True"); -#else - compilation.VerifyDiagnostics( - // (9,30): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. + + CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_2).VerifyDiagnostics( + // (9,30): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // static bool Test1 = 1 is int x1 && Dummy(x1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x1").WithLocation(9, 30) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "int x1").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(9, 30) ); -#endif } [Fact, WorkItem(10487, "https://github.com/dotnet/roslyn/issues/10487")] @@ -1071,21 +1012,10 @@ static bool Dummy(System.Func x) } "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); -#if ALLOW_IN_FIELD_INITIALIZER CompileAndVerify(compilation, expectedOutput: @"1 True 2 True"); -#else - compilation.VerifyDiagnostics( - // (14,30): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // static bool Test1 = 1 is int x1 && Dummy(() => x1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x1").WithLocation(14, 30), - // (15,23): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test2 = 2 is int x1 && Dummy(() => x1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x1").WithLocation(15, 23) - ); -#endif } [Fact] @@ -1137,16 +1067,14 @@ static bool Dummy(int x) } "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); -#if ALLOW_IN_FIELD_INITIALIZER CompileAndVerify(compilation, expectedOutput: @"1 True"); -#else - compilation.VerifyDiagnostics( - // (9,37): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. + + CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_2).VerifyDiagnostics( + // (9,37): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // static bool Test1 {get;} = 1 is int x1 && Dummy(x1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x1").WithLocation(9, 37) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "int x1").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(9, 37) ); -#endif } [Fact] @@ -1191,7 +1119,7 @@ public static void Main() class D : C { - public D(object o) : base(2 is int x1 && Dummy(x1)) + public D(object o) : base(2 is var x1 && Dummy(x1)) { System.Console.WriteLine(o); } @@ -1216,22 +1144,31 @@ public C(object b) } "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); -#if ALLOW_IN_CONSTRUCTOR_INITIALIZER CompileAndVerify(compilation, expectedOutput: @"1 2 True True"); -#else - compilation.VerifyDiagnostics( - // (12,36): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // public D(object o) : base(2 is int x1 && Dummy(x1)) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x1").WithLocation(12, 36), - // (17,28): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").ToArray(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Decl.Length); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationPattern(model, x1Decl[0], x1Ref[0]); + VerifyModelForDeclarationPattern(model, x1Decl[1], x1Ref[1]); + + Assert.Equal("System.Int32", ((LocalSymbol)compilation.GetSemanticModel(tree).GetDeclaredSymbol(x1Decl[0])).Type.ToTestDisplayString()); + + CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_2).VerifyDiagnostics( + // (12,36): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. + // public D(object o) : base(2 is var x1 && Dummy(x1)) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "var x1").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(12, 36), + // (17,28): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // public D() : this(1 is int x1 && Dummy(x1)) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x1").WithLocation(17, 28) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "int x1").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(17, 28) ); -#endif } [Fact] @@ -1280,6 +1217,16 @@ public C(System.Func b) True 1 True"); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").ToArray(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Decl.Length); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationPattern(model, x1Decl[0], x1Ref[0]); + VerifyModelForDeclarationPattern(model, x1Decl[1], x1Ref[1]); } [Fact] @@ -6522,5 +6469,39 @@ public static void Main() Diagnostic(ErrorCode.ERR_DefaultInPattern, "default").WithLocation(12, 28) ); } + + [Fact] + public void EventInitializers_01() + { + var source = +@" +public class X +{ + public static void Main() + { + System.Console.WriteLine(Test1()); + } + + static event System.Func Test1 = GetDelegate(1 is int x1 && Dummy(x1)); + + static System.Func GetDelegate(bool value) => () => value; + + static bool Dummy(int x) + { + System.Console.WriteLine(x); + return true; + } +} +"; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + CompileAndVerify(compilation, expectedOutput: @"1 +True"); + + CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_2).VerifyDiagnostics( + // (9,61): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. + // static event System.Func Test1 = GetDelegate(1 is int x1 && Dummy(x1)); + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "int x1").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(9, 61) + ); + } } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_Global.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_Global.cs index 3d79b12152182..365a900fe8231 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_Global.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_Global.cs @@ -3298,27 +3298,9 @@ class H }; compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,16): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool b = (1 is int x1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x1").WithLocation(3, 16), - // (7,16): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool d = (2 is int x2); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x2").WithLocation(7, 16), - // (9,16): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool f = (3 is int x3); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x3").WithLocation(9, 16), - // (12,25): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool h = H.Dummy((41 is int x4), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(12, 25), - // (13,25): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // (42 is int x4)); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(13, 25), // (13,29): error CS0128: A local variable named 'x4' is already defined in this scope // (42 is int x4)); Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 29), - // (15,17): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool x5 = (5 is int x5); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(15, 17), // (20,13): error CS0103: The name 'x1' does not exist in the current context // H.Dummy(x1, x2, x3, x4, x5); Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(20, 13), @@ -3479,27 +3461,9 @@ class H }; compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,16): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool b = (1 is var x1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x1").WithLocation(3, 16), - // (7,16): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool d = (2 is var x2); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x2").WithLocation(7, 16), - // (9,16): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool f = (3 is var x3); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x3").WithLocation(9, 16), - // (12,25): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool h = H.Dummy((41 is var x4), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x4").WithLocation(12, 25), - // (13,25): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // (42 is var x4)); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x4").WithLocation(13, 25), // (13,29): error CS0128: A local variable named 'x4' is already defined in this scope // (42 is var x4)); Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 29), - // (15,17): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool x5 = (5 is var x5); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x5").WithLocation(15, 17), // (20,13): error CS0103: The name 'x1' does not exist in the current context // H.Dummy(x1, x2, x3, x4, x5); Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(20, 13), @@ -4070,30 +4034,9 @@ class H }; compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,16): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool b = (1 is int x1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x1").WithLocation(3, 16), - // (7,16): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool d = (2 is int x2); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x2").WithLocation(7, 16), - // (9,16): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool f = (3 is int x3); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x3").WithLocation(9, 16), - // (12,25): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool h = H.Dummy((41 is int x4), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(12, 25), - // (13,25): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // (42 is int x4)); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(13, 25), // (13,29): error CS0128: A local variable named 'x4' is already defined in this scope // (42 is int x4)); Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 29), - // (16,17): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // (5 is int x5); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(16, 17), - // (18,16): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool i = (5 is int x6), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(18, 16), // (23,13): error CS0103: The name 'x1' does not exist in the current context // H.Dummy(x1, x2, x3, x4, x5, x6); Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), @@ -4264,30 +4207,9 @@ class H }; compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,16): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool b = (1 is var x1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x1").WithLocation(3, 16), - // (7,16): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool d = (2 is var x2); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x2").WithLocation(7, 16), - // (9,16): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool f = (3 is var x3); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x3").WithLocation(9, 16), - // (12,25): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool h = H.Dummy((41 is var x4), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x4").WithLocation(12, 25), - // (13,25): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // (42 is var x4)); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x4").WithLocation(13, 25), // (13,29): error CS0128: A local variable named 'x4' is already defined in this scope // (42 is var x4)); Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 29), - // (16,17): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // (5 is var x5); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x5").WithLocation(16, 17), - // (18,16): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool i = (5 is var x6), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x6").WithLocation(18, 16), // (23,13): error CS0103: The name 'x1' does not exist in the current context // H.Dummy(x1, x2, x3, x4, x5, x6); Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), @@ -4634,27 +4556,9 @@ class H }; compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,25): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool b { get; } = (1 is int x1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x1").WithLocation(3, 25), - // (7,25): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool d { get; } = (2 is int x2); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x2").WithLocation(7, 25), - // (9,25): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool f { get; } = (3 is int x3); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x3").WithLocation(9, 25), - // (12,34): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool h { get; } = H.Dummy((41 is int x4), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(12, 34), - // (13,34): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // (42 is int x4)); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(13, 34), // (13,38): error CS0128: A local variable named 'x4' is already defined in this scope // (42 is int x4)); Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 38), - // (16,17): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // (5 is int x5); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(16, 17), // (20,13): error CS0103: The name 'x1' does not exist in the current context // H.Dummy(x1, x2, x3, x4, x5); Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(20, 13), @@ -4804,27 +4708,9 @@ class H }; compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,25): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool b { get; } = (1 is var x1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x1").WithLocation(3, 25), - // (7,25): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool d { get; } = (2 is var x2); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x2").WithLocation(7, 25), - // (9,25): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool f { get; } = (3 is var x3); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x3").WithLocation(9, 25), - // (12,34): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool h { get; } = H.Dummy((41 is var x4), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x4").WithLocation(12, 34), - // (13,34): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // (42 is var x4)); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x4").WithLocation(13, 34), // (13,38): error CS0128: A local variable named 'x4' is already defined in this scope // (42 is var x4)); Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 38), - // (16,17): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // (5 is var x5); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x5").WithLocation(16, 17), // (20,13): error CS0103: The name 'x1' does not exist in the current context // H.Dummy(x1, x2, x3, x4, x5); Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(20, 13), @@ -5141,30 +5027,9 @@ class H }; compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,38): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // event System.Action b = H.Dummy(1 is int x1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x1").WithLocation(3, 38), - // (7,38): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // event System.Action d = H.Dummy(2 is int x2); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x2").WithLocation(7, 38), - // (9,38): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // event System.Action f = H.Dummy(3 is int x3); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x3").WithLocation(9, 38), - // (12,40): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // event System.Action h = H.Dummy((41 is int x4), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(12, 40), - // (13,32): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // (42 is int x4)); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(13, 32), // (13,36): error CS0128: A local variable named 'x4' is already defined in this scope // (42 is int x4)); Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 36), - // (16,24): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // H.Dummy(5 is int x5); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(16, 24), - // (18,38): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // event System.Action i = H.Dummy(5 is int x6), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(18, 38), // (23,13): error CS0103: The name 'x1' does not exist in the current context // H.Dummy(x1, x2, x3, x4, x5, x6); Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), @@ -5335,30 +5200,9 @@ class H }; compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,38): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // event System.Action b = H.Dummy(1 is var x1); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x1").WithLocation(3, 38), - // (7,38): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // event System.Action d = H.Dummy(2 is var x2); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x2").WithLocation(7, 38), - // (9,38): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // event System.Action f = H.Dummy(3 is var x3); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x3").WithLocation(9, 38), - // (12,40): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // event System.Action h = H.Dummy((41 is var x4), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x4").WithLocation(12, 40), - // (13,32): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // (42 is var x4)); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x4").WithLocation(13, 32), // (13,36): error CS0128: A local variable named 'x4' is already defined in this scope // (42 is var x4)); Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 36), - // (16,24): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // H.Dummy(5 is var x5); - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x5").WithLocation(16, 24), - // (18,38): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // event System.Action i = H.Dummy(5 is var x6), - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "var x6").WithLocation(18, 38), // (23,13): error CS0103: The name 'x1' does not exist in the current context // H.Dummy(x1, x2, x3, x4, x5, x6); Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), @@ -7332,30 +7176,18 @@ from y10 in new[] { 1 } { var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.ReleaseExe.WithScriptClassName("Script"), parseOptions: TestOptions.Script); compilation.VerifyDiagnostics( - // (12,42): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // from x2 in new[] { x1 is var z2 ? z2 : 0, z2, y2} - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z2").WithLocation(12, 42), // (14,21): error CS0103: The name 'z2' does not exist in the current context // z2; Diagnostic(ErrorCode.ERR_NameNotInContext, "z2").WithArguments("z2").WithLocation(14, 21), - // (19,32): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // let x2 = x1 is var z3 && z3 > 0 && y3 < 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z3").WithLocation(19, 32), // (21,25): error CS0103: The name 'z3' does not exist in the current context // z3}; Diagnostic(ErrorCode.ERR_NameNotInContext, "z3").WithArguments("z3").WithLocation(21, 25), // (28,29): error CS0103: The name 'v4' does not exist in the current context // v4 Diagnostic(ErrorCode.ERR_NameNotInContext, "v4").WithArguments("v4").WithLocation(28, 29), - // (27,49): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // on x1 + y4 + z4 + (3 is var u4 ? u4 : 0) + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "u4").WithLocation(27, 49), // (30,29): error CS1938: The name 'u4' is not in scope on the right side of 'equals'. Consider swapping the expressions on either side of 'equals'. // u4 Diagnostic(ErrorCode.ERR_QueryInnerKey, "u4").WithArguments("u4").WithLocation(30, 29), - // (29,57): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // equals x2 + y4 + z4 + (4 is var v4 ? v4 : 0) + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "v4").WithLocation(29, 57), // (32,25): error CS0103: The name 'u4' does not exist in the current context // u4, v4 }; Diagnostic(ErrorCode.ERR_NameNotInContext, "u4").WithArguments("u4").WithLocation(32, 25), @@ -7365,60 +7197,36 @@ from y10 in new[] { 1 } // (41,29): error CS0103: The name 'v5' does not exist in the current context // v5 Diagnostic(ErrorCode.ERR_NameNotInContext, "v5").WithArguments("v5").WithLocation(41, 29), - // (40,49): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // on x1 + y5 + z5 + (3 is var u5 ? u5 : 0) + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "u5").WithLocation(40, 49), // (43,29): error CS1938: The name 'u5' is not in scope on the right side of 'equals'. Consider swapping the expressions on either side of 'equals'. // u5 Diagnostic(ErrorCode.ERR_QueryInnerKey, "u5").WithArguments("u5").WithLocation(43, 29), - // (42,57): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // equals x2 + y5 + z5 + (4 is var v5 ? v5 : 0) + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "v5").WithLocation(42, 57), // (46,25): error CS0103: The name 'u5' does not exist in the current context // u5, v5 }; Diagnostic(ErrorCode.ERR_NameNotInContext, "u5").WithArguments("u5").WithLocation(46, 25), // (46,29): error CS0103: The name 'v5' does not exist in the current context // u5, v5 }; Diagnostic(ErrorCode.ERR_NameNotInContext, "v5").WithArguments("v5").WithLocation(46, 29), - // (53,38): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // where x > y6 && 1 is var z6 && z6 == 1 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z6").WithLocation(53, 38), // (55,21): error CS0103: The name 'z6' does not exist in the current context // z6; Diagnostic(ErrorCode.ERR_NameNotInContext, "z6").WithArguments("z6").WithLocation(55, 21), // (61,21): error CS0103: The name 'u7' does not exist in the current context // u7, Diagnostic(ErrorCode.ERR_NameNotInContext, "u7").WithArguments("u7").WithLocation(61, 21), - // (60,40): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // orderby x > y7 && 1 is var z7 && z7 == - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z7").WithLocation(60, 40), // (63,21): error CS0103: The name 'z7' does not exist in the current context // z7 Diagnostic(ErrorCode.ERR_NameNotInContext, "z7").WithArguments("z7").WithLocation(63, 21), - // (62,40): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // x > y7 && 1 is var u7 && u7 == - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "u7").WithLocation(62, 40), // (65,21): error CS0103: The name 'z7' does not exist in the current context // z7 + u7; Diagnostic(ErrorCode.ERR_NameNotInContext, "z7").WithArguments("z7").WithLocation(65, 21), // (65,26): error CS0103: The name 'u7' does not exist in the current context // z7 + u7; Diagnostic(ErrorCode.ERR_NameNotInContext, "u7").WithArguments("u7").WithLocation(65, 26), - // (71,39): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // select x > y8 && 1 is var z8 && z8 == 1; - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z8").WithLocation(71, 39), // (80,17): error CS0103: The name 'z9' does not exist in the current context // z9; Diagnostic(ErrorCode.ERR_NameNotInContext, "z9").WithArguments("z9").WithLocation(80, 17), - // (79,36): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // x > y9 && 1 is var u9 && u9 == - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "u9").WithLocation(79, 36), // (77,17): error CS0103: The name 'u9' does not exist in the current context // u9 Diagnostic(ErrorCode.ERR_NameNotInContext, "u9").WithArguments("u9").WithLocation(77, 17), - // (76,38): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // group x > y9 && 1 is var z9 && z9 == - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z9").WithLocation(76, 38), // (16,7): error CS0103: The name 'z2' does not exist in the current context // Dummy(z2); Diagnostic(ErrorCode.ERR_NameNotInContext, "z2").WithArguments("z2").WithLocation(16, 7), @@ -7638,8 +7446,6 @@ from y10 in new[] { 1 } (int)ErrorCode.ERR_TupleElementNamesAttributeMissing, (int)ErrorCode.ERR_IdentifierExpectedKW, (int)ErrorCode.ERR_NameNotInContext, - (int)ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, - (int)ErrorCode.ERR_ExpressionVariableInQueryClause, (int)ErrorCode.ERR_UseDefViolation }; diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_Scope.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_Scope.cs index eff3019ac3dd8..cd842c3ab934d 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_Scope.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_Scope.cs @@ -1661,18 +1661,12 @@ void Test11() "; var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( - // (23,48): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // from x2 in new[] { x1 is var z2 ? z2 : 0, z2, y2} - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z2").WithLocation(23, 48), // (25,26): error CS0103: The name 'z2' does not exist in the current context // z2; Diagnostic(ErrorCode.ERR_NameNotInContext, "z2").WithArguments("z2").WithLocation(25, 26), // (27,15): error CS0103: The name 'z2' does not exist in the current context // Dummy(z2); Diagnostic(ErrorCode.ERR_NameNotInContext, "z2").WithArguments("z2").WithLocation(27, 15), - // (33,38): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // let x2 = x1 is var z3 && z3 > 0 && y3 < 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z3").WithLocation(33, 38), // (35,32): error CS0103: The name 'z3' does not exist in the current context // z3}; Diagnostic(ErrorCode.ERR_NameNotInContext, "z3").WithArguments("z3").WithLocation(35, 32), @@ -1682,15 +1676,9 @@ void Test11() // (45,35): error CS0103: The name 'v4' does not exist in the current context // v4 Diagnostic(ErrorCode.ERR_NameNotInContext, "v4").WithArguments("v4").WithLocation(45, 35), - // (44,56): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // on x1 + y4 + z4 + 3 is var u4 ? u4 : 0 + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "u4").WithLocation(44, 56), // (47,35): error CS1938: The name 'u4' is not in scope on the right side of 'equals'. Consider swapping the expressions on either side of 'equals'. // u4 Diagnostic(ErrorCode.ERR_QueryInnerKey, "u4").WithArguments("u4").WithLocation(47, 35), - // (46,63): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // equals x2 + y4 + z4 + 4 is var v4 ? v4 : 0 + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "v4").WithLocation(46, 63), // (49,32): error CS0103: The name 'u4' does not exist in the current context // u4, v4 }; Diagnostic(ErrorCode.ERR_NameNotInContext, "u4").WithArguments("u4").WithLocation(49, 32), @@ -1706,15 +1694,9 @@ void Test11() // (61,35): error CS0103: The name 'v5' does not exist in the current context // v5 Diagnostic(ErrorCode.ERR_NameNotInContext, "v5").WithArguments("v5").WithLocation(61, 35), - // (60,56): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // on x1 + y5 + z5 + 3 is var u5 ? u5 : 0 + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "u5").WithLocation(60, 56), // (63,35): error CS1938: The name 'u5' is not in scope on the right side of 'equals'. Consider swapping the expressions on either side of 'equals'. // u5 Diagnostic(ErrorCode.ERR_QueryInnerKey, "u5").WithArguments("u5").WithLocation(63, 35), - // (62,63): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // equals x2 + y5 + z5 + 4 is var v5 ? v5 : 0 + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "v5").WithLocation(62, 63), // (66,32): error CS0103: The name 'u5' does not exist in the current context // u5, v5 }; Diagnostic(ErrorCode.ERR_NameNotInContext, "u5").WithArguments("u5").WithLocation(66, 32), @@ -1727,9 +1709,6 @@ void Test11() // (70,15): error CS0103: The name 'v5' does not exist in the current context // Dummy(v5); Diagnostic(ErrorCode.ERR_NameNotInContext, "v5").WithArguments("v5").WithLocation(70, 15), - // (76,44): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // where x > y6 && 1 is var z6 && z6 == 1 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z6").WithLocation(76, 44), // (78,26): error CS0103: The name 'z6' does not exist in the current context // z6; Diagnostic(ErrorCode.ERR_NameNotInContext, "z6").WithArguments("z6").WithLocation(78, 26), @@ -1739,15 +1718,9 @@ void Test11() // (87,27): error CS0103: The name 'u7' does not exist in the current context // u7, Diagnostic(ErrorCode.ERR_NameNotInContext, "u7").WithArguments("u7").WithLocation(87, 27), - // (86,46): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // orderby x > y7 && 1 is var z7 && z7 == - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z7").WithLocation(86, 46), // (89,27): error CS0103: The name 'z7' does not exist in the current context // z7 Diagnostic(ErrorCode.ERR_NameNotInContext, "z7").WithArguments("z7").WithLocation(89, 27), - // (88,46): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // x > y7 && 1 is var u7 && u7 == - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "u7").WithLocation(88, 46), // (91,26): error CS0103: The name 'z7' does not exist in the current context // z7 + u7; Diagnostic(ErrorCode.ERR_NameNotInContext, "z7").WithArguments("z7").WithLocation(91, 26), @@ -1763,24 +1736,15 @@ void Test11() // (88,52): error CS0165: Use of unassigned local variable 'u7' // x > y7 && 1 is var u7 && u7 == Diagnostic(ErrorCode.ERR_UseDefViolation, "u7").WithArguments("u7").WithLocation(88, 52), - // (100,45): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // select x > y8 && 1 is var z8 && z8 == 1; - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z8").WithLocation(100, 45), // (102,15): error CS0103: The name 'z8' does not exist in the current context // Dummy(z8); Diagnostic(ErrorCode.ERR_NameNotInContext, "z8").WithArguments("z8").WithLocation(102, 15), // (112,25): error CS0103: The name 'z9' does not exist in the current context // z9; Diagnostic(ErrorCode.ERR_NameNotInContext, "z9").WithArguments("z9").WithLocation(112, 25), - // (111,44): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // x > y9 && 1 is var u9 && u9 == - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "u9").WithLocation(111, 44), // (109,25): error CS0103: The name 'u9' does not exist in the current context // u9 Diagnostic(ErrorCode.ERR_NameNotInContext, "u9").WithArguments("u9").WithLocation(109, 25), - // (108,44): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // group x > y9 && 1 is var z9 && z9 == - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z9").WithLocation(108, 44), // (114,15): error CS0103: The name 'z9' does not exist in the current context // Dummy(z9); Diagnostic(ErrorCode.ERR_NameNotInContext, "z9").WithArguments("z9").WithLocation(114, 15), @@ -2011,15 +1975,9 @@ into g // (18,35): error CS0103: The name 'v4' does not exist in the current context // v4 Diagnostic(ErrorCode.ERR_NameNotInContext, "v4").WithArguments("v4").WithLocation(18, 35), - // (17,56): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // on x1 + y4 + z4 + 3 is var u4 ? u4 : 0 + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "u4").WithLocation(17, 56), // (20,35): error CS1938: The name 'u4' is not in scope on the right side of 'equals'. Consider swapping the expressions on either side of 'equals'. // u4 Diagnostic(ErrorCode.ERR_QueryInnerKey, "u4").WithArguments("u4").WithLocation(20, 35), - // (19,63): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // equals x2 + y4 + z4 + 4 is var v4 ? v4 : 0 + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "v4").WithLocation(19, 63), // (22,32): error CS0103: The name 'u4' does not exist in the current context // u4, v4 }; Diagnostic(ErrorCode.ERR_NameNotInContext, "u4").WithArguments("u4").WithLocation(22, 32), @@ -2035,15 +1993,9 @@ into g // (35,35): error CS0103: The name 'v5' does not exist in the current context // v5 Diagnostic(ErrorCode.ERR_NameNotInContext, "v5").WithArguments("v5").WithLocation(35, 35), - // (34,56): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // on x1 + y5 + z5 + 3 is var u5 ? u5 : 0 + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "u5").WithLocation(34, 56), // (37,35): error CS1938: The name 'u5' is not in scope on the right side of 'equals'. Consider swapping the expressions on either side of 'equals'. // u5 Diagnostic(ErrorCode.ERR_QueryInnerKey, "u5").WithArguments("u5").WithLocation(37, 35), - // (36,63): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // equals x2 + y5 + z5 + 4 is var v5 ? v5 : 0 + - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "v5").WithLocation(36, 63), // (40,32): error CS0103: The name 'u5' does not exist in the current context // u5, v5 }; Diagnostic(ErrorCode.ERR_NameNotInContext, "u5").WithArguments("u5").WithLocation(40, 32), @@ -2162,66 +2114,36 @@ into s // (17,47): error CS0136: A local or parameter named 'y2' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // from x2 in new[] { 2 is var y2 ? y2 : 0} Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y2").WithArguments("y2").WithLocation(17, 47), - // (17,47): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // from x2 in new[] { 2 is var y2 ? y2 : 0} - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y2").WithLocation(17, 47), // (18,47): error CS0128: A local variable or function named 'y3' is already defined in this scope // join x3 in new[] { 3 is var y3 ? y3 : 0} Diagnostic(ErrorCode.ERR_LocalDuplicate, "y3").WithArguments("y3").WithLocation(18, 47), // (19,36): error CS0136: A local or parameter named 'y4' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // on 4 is var y4 ? y4 : 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y4").WithArguments("y4").WithLocation(19, 36), - // (19,36): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // on 4 is var y4 ? y4 : 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y4").WithLocation(19, 36), // (20,43): error CS0136: A local or parameter named 'y5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // equals 5 is var y5 ? y5 : 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y5").WithArguments("y5").WithLocation(20, 43), - // (20,43): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // equals 5 is var y5 ? y5 : 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y5").WithLocation(20, 43), // (21,34): error CS0136: A local or parameter named 'y6' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // where 6 is var y6 && y6 == 1 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y6").WithArguments("y6").WithLocation(21, 34), - // (21,34): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // where 6 is var y6 && y6 == 1 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y6").WithLocation(21, 34), // (22,36): error CS0136: A local or parameter named 'y7' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // orderby 7 is var y7 && y7 > 0, Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y7").WithArguments("y7").WithLocation(22, 36), - // (22,36): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // orderby 7 is var y7 && y7 > 0, - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y7").WithLocation(22, 36), // (23,36): error CS0136: A local or parameter named 'y8' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // 8 is var y8 && y8 > 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y8").WithArguments("y8").WithLocation(23, 36), - // (23,36): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // 8 is var y8 && y8 > 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y8").WithLocation(23, 36), // (25,32): error CS0136: A local or parameter named 'y10' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // by 10 is var y10 && y10 > 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y10").WithArguments("y10").WithLocation(25, 32), - // (25,32): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // by 10 is var y10 && y10 > 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y10").WithLocation(25, 32), // (24,34): error CS0136: A local or parameter named 'y9' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // group 9 is var y9 && y9 > 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y9").WithArguments("y9").WithLocation(24, 34), - // (24,34): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // group 9 is var y9 && y9 > 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y9").WithLocation(24, 34), // (27,39): error CS0136: A local or parameter named 'y11' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // let x11 = 11 is var y11 && y11 > 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y11").WithArguments("y11").WithLocation(27, 39), - // (27,39): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // let x11 = 11 is var y11 && y11 > 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y11").WithLocation(27, 39), // (28,36): error CS0136: A local or parameter named 'y12' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // select 12 is var y12 && y12 > 0 - Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y12").WithArguments("y12").WithLocation(28, 36), - // (28,36): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // select 12 is var y12 && y12 > 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y12").WithLocation(28, 36) + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y12").WithArguments("y12").WithLocation(28, 36) ); var tree = compilation.SyntaxTrees.Single(); @@ -2318,66 +2240,36 @@ into s // (27,47): error CS0136: A local or parameter named 'y2' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // from x2 in new[] { 2 is var y2 ? y2 : 0} Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y2").WithArguments("y2").WithLocation(27, 47), - // (27,47): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // from x2 in new[] { 2 is var y2 ? y2 : 0} - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y2").WithLocation(27, 47), // (28,47): error CS0128: A local variable or function named 'y3' is already defined in this scope // join x3 in new[] { 3 is var y3 ? y3 : 0} Diagnostic(ErrorCode.ERR_LocalDuplicate, "y3").WithArguments("y3").WithLocation(28, 47), // (29,36): error CS0136: A local or parameter named 'y4' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // on 4 is var y4 ? y4 : 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y4").WithArguments("y4").WithLocation(29, 36), - // (29,36): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // on 4 is var y4 ? y4 : 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y4").WithLocation(29, 36), // (30,43): error CS0136: A local or parameter named 'y5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // equals 5 is var y5 ? y5 : 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y5").WithArguments("y5").WithLocation(30, 43), - // (30,43): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // equals 5 is var y5 ? y5 : 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y5").WithLocation(30, 43), // (31,34): error CS0136: A local or parameter named 'y6' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // where 6 is var y6 && y6 == 1 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y6").WithArguments("y6").WithLocation(31, 34), - // (31,34): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // where 6 is var y6 && y6 == 1 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y6").WithLocation(31, 34), // (32,36): error CS0136: A local or parameter named 'y7' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // orderby 7 is var y7 && y7 > 0, Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y7").WithArguments("y7").WithLocation(32, 36), - // (32,36): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // orderby 7 is var y7 && y7 > 0, - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y7").WithLocation(32, 36), // (33,36): error CS0136: A local or parameter named 'y8' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // 8 is var y8 && y8 > 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y8").WithArguments("y8").WithLocation(33, 36), - // (33,36): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // 8 is var y8 && y8 > 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y8").WithLocation(33, 36), // (35,32): error CS0136: A local or parameter named 'y10' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // by 10 is var y10 && y10 > 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y10").WithArguments("y10").WithLocation(35, 32), - // (35,32): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // by 10 is var y10 && y10 > 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y10").WithLocation(35, 32), // (34,34): error CS0136: A local or parameter named 'y9' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // group 9 is var y9 && y9 > 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y9").WithArguments("y9").WithLocation(34, 34), - // (34,34): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // group 9 is var y9 && y9 > 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y9").WithLocation(34, 34), // (37,39): error CS0136: A local or parameter named 'y11' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // let x11 = 11 is var y11 && y11 > 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y11").WithArguments("y11").WithLocation(37, 39), - // (37,39): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // let x11 = 11 is var y11 && y11 > 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y11").WithLocation(37, 39), // (38,36): error CS0136: A local or parameter named 'y12' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // select 12 is var y12 && y12 > 0 - Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y12").WithArguments("y12").WithLocation(38, 36), - // (38,36): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // select 12 is var y12 && y12 > 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y12").WithLocation(38, 36) + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y12").WithArguments("y12").WithLocation(38, 36) ); var tree = compilation.SyntaxTrees.Single(); @@ -2705,63 +2597,33 @@ void Test10() // (15,47): error CS0136: A local or parameter named 'y1' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // from x2 in new[] { 1 is var y1 ? y1 : 1 } Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y1").WithArguments("y1").WithLocation(15, 47), - // (15,47): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // from x2 in new[] { 1 is var y1 ? y1 : 1 } - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y1").WithLocation(15, 47), // (23,36): error CS0136: A local or parameter named 'y2' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // on 2 is var y2 ? y2 : 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y2").WithArguments("y2").WithLocation(23, 36), - // (23,36): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // on 2 is var y2 ? y2 : 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y2").WithLocation(23, 36), // (33,40): error CS0136: A local or parameter named 'y3' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // equals 3 is var y3 ? y3 : 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y3").WithArguments("y3").WithLocation(33, 40), - // (33,40): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // equals 3 is var y3 ? y3 : 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y3").WithLocation(33, 40), // (40,34): error CS0136: A local or parameter named 'y4' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // where 4 is var y4 && y4 == 1 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y4").WithArguments("y4").WithLocation(40, 34), - // (40,34): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // where 4 is var y4 && y4 == 1 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y4").WithLocation(40, 34), // (47,36): error CS0136: A local or parameter named 'y5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // orderby 5 is var y5 && y5 > 1, Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y5").WithArguments("y5").WithLocation(47, 36), - // (47,36): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // orderby 5 is var y5 && y5 > 1, - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y5").WithLocation(47, 36), // (56,36): error CS0136: A local or parameter named 'y6' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // 6 is var y6 && y6 > 1 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y6").WithArguments("y6").WithLocation(56, 36), - // (56,36): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // 6 is var y6 && y6 > 1 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y6").WithLocation(56, 36), // (63,34): error CS0136: A local or parameter named 'y7' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // group 7 is var y7 && y7 == 3 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y7").WithArguments("y7").WithLocation(63, 34), - // (63,34): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // group 7 is var y7 && y7 == 3 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y7").WithLocation(63, 34), // (71,31): error CS0136: A local or parameter named 'y8' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // by 8 is var y8 && y8 == 3; Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y8").WithArguments("y8").WithLocation(71, 31), - // (71,31): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // by 8 is var y8 && y8 == 3; - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y8").WithLocation(71, 31), // (77,37): error CS0136: A local or parameter named 'y9' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // let x4 = 9 is var y9 && y9 > 0 Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y9").WithArguments("y9").WithLocation(77, 37), - // (77,37): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // let x4 = 9 is var y9 && y9 > 0 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y9").WithLocation(77, 37), // (84,36): error CS0136: A local or parameter named 'y10' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // select 10 is var y10 && y10 > 0; - Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y10").WithArguments("y10").WithLocation(84, 36), - // (84,36): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. - // select 10 is var y10 && y10 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y10").WithLocation(84, 36) + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y10").WithArguments("y10").WithLocation(84, 36) ); var tree = compilation.SyntaxTrees.Single(); @@ -2796,6 +2658,64 @@ void Test10() } } + [Fact] + public void ScopeOfPatternVariables_Query_11() + { + var source = +@" +using System.Linq; + +public class X +{ + public static void Main() + { + } + + bool Dummy(params object[] x) {return true;} + + void Test1() + { + var res = from x1 in new [] { 1 } + where Dummy(x1 is var y1, + from x2 in new [] { 1 } + where x1 is var y1 + select x2) + select x1; + } + + void Test2() + { + var res = from x1 in new [] { 1 } + where Dummy(x1 is var y2, + x1 + 1 is var y2) + select x1; + } +} +"; + var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe); + compilation.VerifyDiagnostics( + // (17,47): error CS0136: A local or parameter named 'y1' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // where x1 is var y1 + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y1").WithArguments("y1").WithLocation(17, 47), + // (26,45): error CS0128: A local variable or function named 'y2' is already defined in this scope + // x1 + 1 is var y2) + Diagnostic(ErrorCode.ERR_LocalDuplicate, "y2").WithArguments("y2").WithLocation(26, 45) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var y1Decl = GetPatternDeclarations(tree, "y1").ToArray(); + Assert.Equal(2, y1Decl.Length); + VerifyModelForDeclarationPattern(model, y1Decl[0]); + VerifyModelForDeclarationPattern(model, y1Decl[1]); + + var y2Decl = GetPatternDeclarations(tree, "y2").ToArray(); + Assert.Equal(2, y2Decl.Length); + VerifyModelForDeclarationPattern(model, y2Decl[0]); + VerifyModelForDeclarationPatternDuplicateInSameScope(model, y2Decl[1]); + } + [Fact] public void ScopeOfPatternVariables_ExpressionBodiedLocalFunctions_01() { @@ -3286,44 +3206,32 @@ 52 is int x5 && bool Test72 = Dummy(x7, 2); void Test73() { Dummy(x7, 3); } + bool Test81 = 8 is int x8, Test82 = x8 > 0; + bool Test91 = x9 > 0, Test92 = 9 is int x9; + bool Dummy(params object[] x) {return true;} } "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( - // (8,23): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test3 = 3 is int x3 && x3 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x3").WithLocation(8, 23), // (10,18): error CS0841: Cannot use local variable 'x4' before it is declared // bool Test4 = x4 && 4 is int x4; Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x4").WithArguments("x4").WithLocation(10, 18), - // (10,29): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test4 = x4 && 4 is int x4; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(10, 29), - // (12,24): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test5 = 51 is int x5 && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(12, 24), - // (13,24): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // 52 is int x5 && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(13, 24), // (13,28): error CS0128: A local variable named 'x5' is already defined in this scope // 52 is int x5 && Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(13, 28), - // (16,24): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test61 = 6 is int x6 && x6 > 0, Test62 = 6 is int x6 && x6 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(16, 24), - // (16,56): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test61 = 6 is int x6 && x6 > 0, Test62 = 6 is int x6 && x6 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(16, 56), - // (18,24): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test71 = 7 is int x7 && x7 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x7").WithLocation(18, 24), // (19,25): error CS0103: The name 'x7' does not exist in the current context // bool Test72 = Dummy(x7, 2); Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(19, 25), // (20,27): error CS0103: The name 'x7' does not exist in the current context // void Test73() { Dummy(x7, 3); } - Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(20, 27) + Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(20, 27), + // (22,41): error CS0103: The name 'x8' does not exist in the current context + // bool Test81 = 8 is int x8, Test82 = x8 > 0; + Diagnostic(ErrorCode.ERR_NameNotInContext, "x8").WithArguments("x8").WithLocation(22, 41), + // (23,19): error CS0103: The name 'x9' does not exist in the current context + // bool Test91 = x9 > 0, Test92 = 9 is int x9; + Diagnostic(ErrorCode.ERR_NameNotInContext, "x9").WithArguments("x9").WithLocation(23, 19) ); var tree = compilation.SyntaxTrees.Single(); @@ -3356,6 +3264,16 @@ 52 is int x5 && VerifyModelForDeclarationPattern(model, x7Decl, x7Ref[0]); VerifyNotInScope(model, x7Ref[1]); VerifyNotInScope(model, x7Ref[2]); + + var x8Decl = GetPatternDeclarations(tree, "x8").Single(); + var x8Ref = GetReference(tree, "x8"); + VerifyModelForDeclarationPattern(model, x8Decl); + VerifyNotInScope(model, x8Ref); + + var x9Decl = GetPatternDeclarations(tree, "x9").Single(); + var x9Ref = GetReference(tree, "x9"); + VerifyNotInScope(model, x9Ref); + VerifyModelForDeclarationPattern(model, x9Decl); } [Fact] @@ -3384,42 +3302,21 @@ 52 is int x5 && // (6,13): error CS0841: Cannot use local variable 'x4' before it is declared // Test4 = x4 && 4 is int x4 ? 1 : 0, Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x4").WithArguments("x4").WithLocation(6, 13), - // (6,24): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // Test4 = x4 && 4 is int x4 ? 1 : 0, - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(6, 24), - // (8,19): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // Test5 = 51 is int x5 && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(8, 19), - // (9,19): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // 52 is int x5 && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(9, 19), // (9,23): error CS0128: A local variable named 'x5' is already defined in this scope // 52 is int x5 && Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(9, 23), - // (12,19): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // Test61 = 6 is int x6 && x6 > 0 ? 1 : 0, Test62 = 6 is int x6 && x6 > 0 ? 1 : 0, - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(12, 19), // (12,14): error CS0133: The expression being assigned to 'X.Test61' must be constant // Test61 = 6 is int x6 && x6 > 0 ? 1 : 0, Test62 = 6 is int x6 && x6 > 0 ? 1 : 0, Diagnostic(ErrorCode.ERR_NotConstantExpression, "6 is int x6 && x6 > 0 ? 1 : 0").WithArguments("X.Test61").WithLocation(12, 14), - // (12,59): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // Test61 = 6 is int x6 && x6 > 0 ? 1 : 0, Test62 = 6 is int x6 && x6 > 0 ? 1 : 0, - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(12, 59), // (12,54): error CS0133: The expression being assigned to 'X.Test62' must be constant // Test61 = 6 is int x6 && x6 > 0 ? 1 : 0, Test62 = 6 is int x6 && x6 > 0 ? 1 : 0, Diagnostic(ErrorCode.ERR_NotConstantExpression, "6 is int x6 && x6 > 0 ? 1 : 0").WithArguments("X.Test62").WithLocation(12, 54), - // (14,19): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // Test71 = 7 is int x7 && x7 > 0 ? 1 : 0, - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x7").WithLocation(14, 19), // (14,14): error CS0133: The expression being assigned to 'X.Test71' must be constant // Test71 = 7 is int x7 && x7 > 0 ? 1 : 0, Diagnostic(ErrorCode.ERR_NotConstantExpression, "7 is int x7 && x7 > 0 ? 1 : 0").WithArguments("X.Test71").WithLocation(14, 14), // (15,14): error CS0103: The name 'x7' does not exist in the current context // Test72 = x7, Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(15, 14), - // (4,18): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // Test3 = 3 is int x3 ? x3 : 0, - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x3").WithLocation(4, 18), // (4,13): error CS0133: The expression being assigned to 'X.Test3' must be constant // Test3 = 3 is int x3 ? x3 : 0, Diagnostic(ErrorCode.ERR_NotConstantExpression, "3 is int x3 ? x3 : 0").WithArguments("X.Test3").WithLocation(4, 13) @@ -3486,42 +3383,21 @@ 52 is int x5 && "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( - // (8,29): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // const bool Test3 = 3 is int x3 && x3 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x3").WithLocation(8, 29), // (8,24): error CS0133: The expression being assigned to 'X.Test3' must be constant // const bool Test3 = 3 is int x3 && x3 > 0; Diagnostic(ErrorCode.ERR_NotConstantExpression, "3 is int x3 && x3 > 0").WithArguments("X.Test3").WithLocation(8, 24), // (10,24): error CS0841: Cannot use local variable 'x4' before it is declared // const bool Test4 = x4 && 4 is int x4; Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x4").WithArguments("x4").WithLocation(10, 24), - // (10,35): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // const bool Test4 = x4 && 4 is int x4; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(10, 35), - // (12,30): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // const bool Test5 = 51 is int x5 && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(12, 30), - // (13,30): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // 52 is int x5 && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(13, 30), // (13,34): error CS0128: A local variable named 'x5' is already defined in this scope // 52 is int x5 && Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(13, 34), - // (16,30): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // const bool Test61 = 6 is int x6 && x6 > 0, Test62 = 6 is int x6 && x6 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(16, 30), // (16,25): error CS0133: The expression being assigned to 'X.Test61' must be constant // const bool Test61 = 6 is int x6 && x6 > 0, Test62 = 6 is int x6 && x6 > 0; Diagnostic(ErrorCode.ERR_NotConstantExpression, "6 is int x6 && x6 > 0").WithArguments("X.Test61").WithLocation(16, 25), - // (16,62): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // const bool Test61 = 6 is int x6 && x6 > 0, Test62 = 6 is int x6 && x6 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(16, 62), // (16,57): error CS0133: The expression being assigned to 'X.Test62' must be constant // const bool Test61 = 6 is int x6 && x6 > 0, Test62 = 6 is int x6 && x6 > 0; Diagnostic(ErrorCode.ERR_NotConstantExpression, "6 is int x6 && x6 > 0").WithArguments("X.Test62").WithLocation(16, 57), - // (18,30): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // const bool Test71 = 7 is int x7 && x7 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x7").WithLocation(18, 30), // (18,25): error CS0133: The expression being assigned to 'X.Test71' must be constant // const bool Test71 = 7 is int x7 && x7 > 0; Diagnostic(ErrorCode.ERR_NotConstantExpression, "7 is int x7 && x7 > 0").WithArguments("X.Test71").WithLocation(18, 25), @@ -3595,33 +3471,12 @@ 52 is int x5 && "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( - // (8,30): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test3 {get;} = 3 is int x3 && x3 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x3").WithLocation(8, 30), // (10,25): error CS0841: Cannot use local variable 'x4' before it is declared // bool Test4 {get;} = x4 && 4 is int x4; Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x4").WithArguments("x4").WithLocation(10, 25), - // (10,36): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test4 {get;} = x4 && 4 is int x4; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(10, 36), - // (12,31): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test5 {get;} = 51 is int x5 && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(12, 31), - // (13,24): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // 52 is int x5 && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(13, 24), // (13,28): error CS0128: A local variable named 'x5' is already defined in this scope // 52 is int x5 && Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(13, 28), - // (16,31): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test61 {get;} = 6 is int x6 && x6 > 0; bool Test62 {get;} = 6 is int x6 && x6 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(16, 31), - // (16,75): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test61 {get;} = 6 is int x6 && x6 > 0; bool Test62 {get;} = 6 is int x6 && x6 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(16, 75), - // (18,31): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // bool Test71 {get;} = 7 is int x7 && x7 > 0; - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x7").WithLocation(18, 31), // (19,32): error CS0103: The name 'x7' does not exist in the current context // bool Test72 {get;} = Dummy(x7, 2); Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(19, 32), @@ -3980,36 +3835,15 @@ 52 is int x5 && "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( - // (9,21): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : this(3 is int x3 && x3 > 0) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x3").WithLocation(9, 21), // (13,16): error CS0841: Cannot use local variable 'x4' before it is declared // : this(x4 && 4 is int x4) Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x4").WithArguments("x4").WithLocation(13, 16), - // (13,27): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : this(x4 && 4 is int x4) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(13, 27), - // (17,22): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : this(51 is int x5 && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(17, 22), - // (18,22): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // 52 is int x5 && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(18, 22), // (18,26): error CS0128: A local variable named 'x5' is already defined in this scope // 52 is int x5 && Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(18, 26), - // (23,21): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : this(6 is int x6 && x6 > 0, 6 is int x6 && x6 > 0) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(23, 21), - // (23,44): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : this(6 is int x6 && x6 > 0, 6 is int x6 && x6 > 0) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(23, 44), // (23,48): error CS0128: A local variable named 'x6' is already defined in this scope // : this(6 is int x6 && x6 > 0, 6 is int x6 && x6 > 0) Diagnostic(ErrorCode.ERR_LocalDuplicate, "x6").WithArguments("x6").WithLocation(23, 48), - // (27,21): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : this(7 is int x7 && x7 > 0) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x7").WithLocation(27, 21), // (30,16): error CS0103: The name 'x7' does not exist in the current context // : this(x7, 2) Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(30, 16), @@ -4097,36 +3931,15 @@ public Y(params object[] x) {} "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( - // (9,21): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : base(3 is int x3 && x3 > 0) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x3").WithLocation(9, 21), // (13,16): error CS0841: Cannot use local variable 'x4' before it is declared // : base(x4 && 4 is int x4) Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x4").WithArguments("x4").WithLocation(13, 16), - // (13,27): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : base(x4 && 4 is int x4) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x4").WithLocation(13, 27), - // (17,22): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : base(51 is int x5 && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(17, 22), - // (18,22): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // 52 is int x5 && - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x5").WithLocation(18, 22), // (18,26): error CS0128: A local variable named 'x5' is already defined in this scope // 52 is int x5 && Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(18, 26), - // (23,21): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : base(6 is int x6 && x6 > 0, 6 is int x6 && x6 > 0) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(23, 21), - // (23,44): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : base(6 is int x6 && x6 > 0, 6 is int x6 && x6 > 0) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x6").WithLocation(23, 44), // (23,48): error CS0128: A local variable named 'x6' is already defined in this scope // : base(6 is int x6 && x6 > 0, 6 is int x6 && x6 > 0) Diagnostic(ErrorCode.ERR_LocalDuplicate, "x6").WithArguments("x6").WithLocation(23, 48), - // (27,21): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // : base(7 is int x7 && x7 > 0) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x7").WithLocation(27, 21), // (30,16): error CS0103: The name 'x7' does not exist in the current context // : base(x7, 2) Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(30, 16), @@ -4193,12 +4006,9 @@ public D(object o) : this(o is int x && x >= 5) "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( - // (15,27): error CS0103: The name 'x' does not exist in the current context - // Console.WriteLine(x); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x").WithArguments("x").WithLocation(15, 27), - // (13,36): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // public D(object o) : this(o is int x && x >= 5) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x").WithLocation(13, 36) + // (15,27): error CS0165: Use of unassigned local variable 'x' + // Console.WriteLine(x); + Diagnostic(ErrorCode.ERR_UseDefViolation, "x").WithArguments("x").WithLocation(15, 27) ); } @@ -4231,15 +4041,77 @@ class C "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( - // (15,27): error CS0103: The name 'x' does not exist in the current context - // Console.WriteLine(x); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x").WithArguments("x").WithLocation(15, 27), - // (13,36): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. - // public D(object o) : base(o is int x && x >= 5) - Diagnostic(ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, "int x").WithLocation(13, 36) + // (15,27): error CS0165: Use of unassigned local variable 'x' + // Console.WriteLine(x); + Diagnostic(ErrorCode.ERR_UseDefViolation, "x").WithArguments("x").WithLocation(15, 27) ); } + [Fact] + public void ScopeOfPatternVariables_ConstructorInitializers_07() + { + var source = +@" +public class X : Y +{ + public static void Main() + { + } + + X(byte x3) + : base(3 is int x3) + {} + + X(sbyte x) + : base(4 is int x4) + { + int x4 = 1; + System.Console.WriteLine(x4); + } + + X(ushort x) + : base(51 is int x5) + => Dummy(52 is int x5, x5); + + bool Dummy(params object[] x) {return true;} +} + +public class Y +{ + public Y(params object[] x) {} +} +"; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + compilation.VerifyDiagnostics( + // (9,25): error CS0136: A local or parameter named 'x3' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // : base(3 is int x3) + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x3").WithArguments("x3").WithLocation(9, 25), + // (15,13): error CS0136: A local or parameter named 'x4' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // int x4 = 1; + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x4").WithArguments("x4").WithLocation(15, 13), + // (21,24): error CS0136: A local or parameter named 'x5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // => Dummy(52 is int x5, x5); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x5").WithArguments("x5").WithLocation(21, 24) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + VerifyModelForDeclarationPattern(model, x3Decl); + + var x4Decl = GetPatternDeclarations(tree, "x4").Single(); + var x4Ref = GetReferences(tree, "x4").Single(); + VerifyModelForDeclarationPattern(model, x4Decl); + VerifyNotAPatternLocal(model, x4Ref); + + var x5Decl = GetPatternDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").Single(); + Assert.Equal(2, x5Decl.Length); + VerifyModelForDeclarationPattern(model, x5Decl[0]); + VerifyModelForDeclarationPattern(model, x5Decl[1], x5Ref); + } + [Fact] public void ScopeOfPatternVariables_SwitchLabelGuard_01() { diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/QueryTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/QueryTests.cs index 9683dee10cece..a3726cfab407b 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/QueryTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/QueryTests.cs @@ -3857,44 +3857,46 @@ public static void Main(string[] args) } public static T M(T x, out T z) => z = x; }"; - CreateCompilationWithMscorlib40AndSystemCore(csSource).VerifyDiagnostics( - // (10,53): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + CreateCompilationWithMscorlib40AndSystemCore(csSource, parseOptions: TestOptions.Regular7_2).VerifyDiagnostics( + // (10,53): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zc = from x in a from y in M(a, out var z) select x; // error 1 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(10, 53), - // (11,57): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(10, 53), + // (11,57): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zd = from x in a from int y in M(a, out var z) select x; // error 2 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(11, 57), - // (12,53): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(11, 57), + // (12,53): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var ze = from x in a from y in M(a, out var z) where true select x; // error 3 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(12, 53), - // (13,57): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(12, 53), + // (13,57): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zf = from x in a from int y in M(a, out var z) where true select x; // error 4 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(13, 57), - // (14,51): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(13, 57), + // (14,51): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zg = from x in a let y = M(a, out var z) select x; // error 5 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(14, 51), - // (15,49): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(14, 51), + // (15,49): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zh = from x in a where M(x, out var z) == 1 select x; // error 6 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(15, 49), - // (17,58): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(15, 49), + // (17,58): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zj = from x in a join y in a on M(x, out var z) equals y select x; // error 7 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(17, 58), - // (18,67): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(17, 58), + // (18,67): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zk = from x in a join y in a on x equals M(y, out var z) select x; // error 8 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(18, 67), - // (19,51): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(18, 67), + // (19,51): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zl = from x in a orderby M(x, out var z) select x; // error 9 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(19, 51), - // (20,54): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(19, 51), + // (20,54): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zm = from x in a orderby x, M(x, out var z) select x; // error 10 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(20, 54), - // (21,49): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(20, 54), + // (21,49): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zn = from x in a group M(x, out var z) by x; // error 11 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(21, 49), - // (22,54): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(21, 49), + // (22,54): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zo = from x in a group x by M(x, out var z); // error 12 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(22, 54) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(22, 54) ); + + CreateCompilationWithMscorlib40AndSystemCore(csSource).VerifyDiagnostics(); } [WorkItem(15910, "https://github.com/dotnet/roslyn/issues/15910")] @@ -3926,44 +3928,46 @@ public static void Main(string[] args) } public static T M(T x, bool b) => x; }"; - CreateCompilationWithMscorlib40AndSystemCore(csSource).VerifyDiagnostics( - // (10,54): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + CreateCompilationWithMscorlib40AndSystemCore(csSource, parseOptions: TestOptions.Regular7_2).VerifyDiagnostics( + // (10,54): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zc = from x in a from y in M(a, a is var z) select x; // error 1 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(10, 54), - // (11,58): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(10, 54), + // (11,58): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zd = from x in a from int y in M(a, a is var z) select x; // error 2 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(11, 58), - // (12,54): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(11, 58), + // (12,54): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var ze = from x in a from y in M(a, a is var z) where true select x; // error 3 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(12, 54), - // (13,58): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(12, 54), + // (13,58): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zf = from x in a from int y in M(a, a is var z) where true select x; // error 4 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(13, 58), - // (14,52): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(13, 58), + // (14,52): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zg = from x in a let y = M(a, a is var z) select x; // error 5 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(14, 52), - // (15,50): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(14, 52), + // (15,50): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zh = from x in a where M(x, x is var z) == 1 select x; // error 6 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(15, 50), - // (17,59): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(15, 50), + // (17,59): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zj = from x in a join y in a on M(x, x is var z) equals y select x; // error 7 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(17, 59), - // (18,68): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(17, 59), + // (18,68): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zk = from x in a join y in a on x equals M(y, y is var z) select x; // error 8 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(18, 68), - // (19,52): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(18, 68), + // (19,52): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zl = from x in a orderby M(x, x is var z) select x; // error 9 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(19, 52), - // (20,55): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(19, 52), + // (20,55): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zm = from x in a orderby x, M(x, x is var z) select x; // error 10 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(20, 55), - // (21,50): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(20, 55), + // (21,50): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zn = from x in a group M(x, x is var z) by x; // error 11 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(21, 50), - // (22,55): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(21, 50), + // (22,55): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zo = from x in a group x by M(x, x is var z); // error 12 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(22, 55) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(22, 55) ); + + CreateCompilationWithMscorlib40AndSystemCore(csSource).VerifyDiagnostics(); } [WorkItem(15910, "https://github.com/dotnet/roslyn/issues/15910")] @@ -4009,47 +4013,52 @@ public ValueTuple(T1 item1, T2 item2) } } "; - CreateCompilationWithMscorlib40AndSystemCore(csSource) + CreateCompilationWithMscorlib40AndSystemCore(csSource, parseOptions: TestOptions.Regular7_2) .GetDiagnostics() .Where(d => d.Code != (int)ErrorCode.ERR_DeclarationExpressionNotPermitted) .Verify( - // (10,50): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + // (10,50): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zc = from x in a from y in M(a, (int z, int w) = x) select x; // error 1 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(10, 50), - // (11,54): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(10, 50), + // (11,54): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zd = from x in a from int y in M(a, (int z, int w) = x) select x; // error 2 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(11, 54), - // (12,50): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(11, 54), + // (12,50): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var ze = from x in a from y in M(a, (int z, int w) = x) where true select x; // error 3 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(12, 50), - // (13,54): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(12, 50), + // (13,54): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zf = from x in a from int y in M(a, (int z, int w) = x) where true select x; // error 4 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(13, 54), - // (14,48): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(13, 54), + // (14,48): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zg = from x in a let y = M(x, (int z, int w) = x) select x; // error 5 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(14, 48), - // (15,46): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(14, 48), + // (15,46): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zh = from x in a where M(x, (int z, int w) = x).Item1 == 1 select x; // error 6 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(15, 46), - // (17,55): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(15, 46), + // (17,55): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zj = from x in a join y in a on M(x, (int z, int w) = x) equals y select x; // error 7 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(17, 55), - // (18,64): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(17, 55), + // (18,64): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zk = from x in a join y in a on x equals M(y, (int z, int w) = y) select x; // error 8 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(18, 64), - // (19,48): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(18, 64), + // (19,48): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zl = from x in a orderby M(x, (int z, int w) = x) select x; // error 9 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(19, 48), - // (20,51): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(19, 48), + // (20,51): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zm = from x in a orderby x, M(x, (int z, int w) = x) select x; // error 10 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(20, 51), - // (21,46): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(20, 51), + // (21,46): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zn = from x in a group M(x, (int z, int w) = x) by x; // error 11 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(21, 46), - // (22,51): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(21, 46), + // (22,51): error CS8320: Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.2. Please use language version 7.3 or greater. // var zo = from x in a group x by M(x, (int z, int w) = x); // error 12 - Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(22, 51) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "z").WithArguments("declaration of expression variables in member initializers and queries", "7.3").WithLocation(22, 51) ); + + CreateCompilationWithMscorlib40AndSystemCore(csSource) + .GetDiagnostics() + .Where(d => d.Code != (int)ErrorCode.ERR_DeclarationExpressionNotPermitted) + .Verify(); } [CompilerTrait(CompilerFeature.IOperation)] diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs index 8131604115f07..b9f61e3e02eb7 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs @@ -2071,12 +2071,42 @@ private static ImmutableArray GetOperationsToAnalyze( ImmutableArray operationBlocks) { ArrayBuilder operationsToAnalyze = ArrayBuilder.GetInstance(); + var checkParent = true; foreach (IOperation operationBlock in operationBlocks) { - operationsToAnalyze.AddRange(operationBlock.DescendantsAndSelf()); + if (checkParent) + { + // Special handling for IMethodBodyOperation and IConstructorBodyOperation. + // These are newly added root operation nodes for C# method and constructor bodies. + // However, to avoid a breaking change for existing operation block analyzers, + // we have decided to retain the current behavior of making operation block callbacks with the contained + // method body and/or constructor initialer operation nodes. + // Hence we detect here if the operation block is parented by IMethodBodyOperation or IConstructorBodyOperation and + // add them to 'operationsToAnalyze' so that analyzers that explicitly register for these operation kinds + // can get callbacks for these nodes. + if (operationBlock.Parent != null) + { + switch (operationBlock.Parent.Kind) + { + case OperationKind.MethodBodyOperation: + case OperationKind.ConstructorBodyOperation: + operationsToAnalyze.Add(operationBlock.Parent); + break; + + default: + Debug.Fail($"Expected operation with kind '{operationBlock.Kind}' to be the root operation with null 'Parent', but instead it has a non-null Parent with kind '{operationBlock.Parent.Kind}'"); + break; + } + + checkParent = false; + } + } + + operationsToAnalyze.AddRange(operationBlock.DescendantsAndSelf()); } + Debug.Assert(operationsToAnalyze.ToImmutableHashSet().Count == operationsToAnalyze.Count); return operationsToAnalyze.ToImmutableAndFree(); } diff --git a/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs b/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs index 220502d9ff9ab..cbe8f1f450f20 100644 --- a/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs @@ -1817,6 +1817,8 @@ public override TResult Accept(OperationVisitor ISymbolInitializerOperation.Locals => ImmutableArray.Empty; } /// @@ -1852,11 +1854,15 @@ public LazyVariableInitializer(Lazy value, SemanticModel semanticMod /// internal abstract partial class BaseFieldInitializer : SymbolInitializer, IFieldInitializerOperation { - public BaseFieldInitializer(ImmutableArray initializedFields, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + public BaseFieldInitializer(ImmutableArray locals, ImmutableArray initializedFields, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : base(kind, semanticModel, syntax, type, constantValue, isImplicit) { + Locals = locals; InitializedFields = initializedFields; } + + public ImmutableArray Locals { get; } + /// /// Initialized fields. There can be multiple fields for Visual Basic fields declared with As New. /// @@ -1887,8 +1893,8 @@ public override TResult Accept(OperationVisitor internal sealed partial class FieldInitializer : BaseFieldInitializer, IFieldInitializerOperation { - public FieldInitializer(ImmutableArray initializedFields, IOperation value, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(initializedFields, kind, semanticModel, syntax, type, constantValue, isImplicit) + public FieldInitializer(ImmutableArray locals, ImmutableArray initializedFields, IOperation value, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(locals, initializedFields, kind, semanticModel, syntax, type, constantValue, isImplicit) { ValueImpl = value; } @@ -1902,8 +1908,8 @@ internal sealed partial class LazyFieldInitializer : BaseFieldInitializer, IFiel { private readonly Lazy _lazyValue; - public LazyFieldInitializer(ImmutableArray initializedFields, Lazy value, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(initializedFields, kind, semanticModel, syntax, type, constantValue, isImplicit) + public LazyFieldInitializer(ImmutableArray locals, ImmutableArray initializedFields, Lazy value, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(locals, initializedFields, kind, semanticModel, syntax, type, constantValue, isImplicit) { _lazyValue = value ?? throw new System.ArgumentNullException(nameof(value)); } @@ -3846,11 +3852,15 @@ public override TResult Accept(OperationVisitor internal abstract partial class BaseParameterInitializer : SymbolInitializer, IParameterInitializerOperation { - public BaseParameterInitializer(IParameterSymbol parameter, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + public BaseParameterInitializer(ImmutableArray locals, IParameterSymbol parameter, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : base(kind, semanticModel, syntax, type, constantValue, isImplicit) { + Locals = locals; Parameter = parameter; } + + public ImmutableArray Locals { get; } + /// /// Initialized parameter. /// @@ -3881,8 +3891,8 @@ public override TResult Accept(OperationVisitor internal sealed partial class ParameterInitializer : BaseParameterInitializer, IParameterInitializerOperation { - public ParameterInitializer(IParameterSymbol parameter, IOperation value, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(parameter, kind, semanticModel, syntax, type, constantValue, isImplicit) + public ParameterInitializer(ImmutableArray locals, IParameterSymbol parameter, IOperation value, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(locals, parameter, kind, semanticModel, syntax, type, constantValue, isImplicit) { ValueImpl = value; } @@ -3896,8 +3906,8 @@ internal sealed partial class LazyParameterInitializer : BaseParameterInitialize { private readonly Lazy _lazyValue; - public LazyParameterInitializer(IParameterSymbol parameter, Lazy value, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(parameter, kind, semanticModel, syntax, type, constantValue, isImplicit) + public LazyParameterInitializer(ImmutableArray locals, IParameterSymbol parameter, Lazy value, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(locals, parameter, kind, semanticModel, syntax, type, constantValue, isImplicit) { _lazyValue = value ?? throw new System.ArgumentNullException(nameof(value)); } @@ -4099,11 +4109,15 @@ public LazyPointerIndirectionReferenceExpression(Lazy pointer, Seman /// internal abstract partial class BasePropertyInitializer : SymbolInitializer, IPropertyInitializerOperation { - public BasePropertyInitializer(ImmutableArray initializedProperties, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + public BasePropertyInitializer(ImmutableArray locals, ImmutableArray initializedProperties, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : base(kind, semanticModel, syntax, type, constantValue, isImplicit) { + Locals = locals; InitializedProperties = initializedProperties; } + + public ImmutableArray Locals { get; } + /// /// Initialized properties. There can be multiple properties for Visual Basic 'WithEvents' declaration with AsNew clause. /// @@ -4134,8 +4148,8 @@ public override TResult Accept(OperationVisitor internal sealed partial class PropertyInitializer : BasePropertyInitializer, IPropertyInitializerOperation { - public PropertyInitializer(ImmutableArray initializedProperties, IOperation value, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(initializedProperties, kind, semanticModel, syntax, type, constantValue, isImplicit) + public PropertyInitializer(ImmutableArray locals, ImmutableArray initializedProperties, IOperation value, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(locals, initializedProperties, kind, semanticModel, syntax, type, constantValue, isImplicit) { ValueImpl = value; } @@ -4149,8 +4163,8 @@ internal sealed partial class LazyPropertyInitializer : BasePropertyInitializer, { private readonly Lazy _lazyValue; - public LazyPropertyInitializer(ImmutableArray initializedProperties, Lazy value, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(initializedProperties, kind, semanticModel, syntax, type, constantValue, isImplicit) + public LazyPropertyInitializer(ImmutableArray locals, ImmutableArray initializedProperties, Lazy value, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(locals, initializedProperties, kind, semanticModel, syntax, type, constantValue, isImplicit) { _lazyValue = value ?? throw new System.ArgumentNullException(nameof(value)); } @@ -4797,7 +4811,7 @@ public LazySwitchStatement(Lazy value, Lazy /// Represents an initializer for a field, property, or parameter. /// - internal abstract partial class SymbolInitializer : Operation, ISymbolInitializerOperation + internal abstract partial class SymbolInitializer : Operation { protected SymbolInitializer(OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : base(kind, semanticModel, syntax, type, constantValue, isImplicit) @@ -6550,4 +6564,163 @@ public LazyTranslatedQueryExpression(Lazy expression, SemanticModel } protected override IOperation ExpressionImpl => _lazyExpression.Value; } + + internal abstract class BaseMethodBodyBaseOperation : Operation, IMethodBodyBaseOperation + { + protected BaseMethodBodyBaseOperation(OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax) : + base(kind, semanticModel, syntax, type: null, constantValue: default, isImplicit: false) + { + } + + public abstract IBlockOperation BlockBody { get; } + public abstract IBlockOperation ExpressionBody { get; } + public abstract override IEnumerable Children { get; } + } + + internal abstract class BaseMethodBodyOperation : BaseMethodBodyBaseOperation, IMethodBodyOperation + { + protected BaseMethodBodyOperation(SemanticModel semanticModel, SyntaxNode syntax) : + base(OperationKind.MethodBodyOperation, semanticModel, syntax) + { + } + + public sealed override IEnumerable Children + { + get + { + IBlockOperation blockBody = BlockBody; + if (blockBody != null) + { + yield return blockBody; + } + + IBlockOperation expressionBody = ExpressionBody; + if (expressionBody != null) + { + yield return expressionBody; + } + } + } + + public sealed override void Accept(OperationVisitor visitor) + { + visitor.VisitMethodBodyOperation(this); + } + + public sealed override TResult Accept(OperationVisitor visitor, TArgument argument) + { + return visitor.VisitMethodBodyOperation(this, argument); + } + } + + internal sealed class MethodBodyOperation : BaseMethodBodyOperation + { + public MethodBodyOperation(SemanticModel semanticModel, SyntaxNode syntax, IBlockOperation blockBody, IBlockOperation expressionBody) : + base(semanticModel, syntax) + { + BlockBody = SetParentOperation(blockBody, this); + ExpressionBody = SetParentOperation(expressionBody, this); + } + + public override IBlockOperation BlockBody { get; } + public override IBlockOperation ExpressionBody { get; } + } + + internal sealed class LazyMethodBodyOperation : BaseMethodBodyOperation + { + private readonly Lazy _lazyBlockBody; + private readonly Lazy _lazyExpressionBody; + + public LazyMethodBodyOperation(SemanticModel semanticModel, SyntaxNode syntax, Lazy blockBody, Lazy expressionBody) : + base(semanticModel, syntax) + { + _lazyBlockBody = blockBody; + _lazyExpressionBody = expressionBody; + } + + public override IBlockOperation BlockBody => SetParentOperation(_lazyBlockBody.Value, this); + public override IBlockOperation ExpressionBody => SetParentOperation(_lazyExpressionBody.Value, this); + } + + internal abstract class BaseConstructorBodyOperation : BaseMethodBodyBaseOperation, IConstructorBodyOperation + { + protected BaseConstructorBodyOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax) : + base(OperationKind.ConstructorBodyOperation, semanticModel, syntax) + { + Locals = locals; + } + + public ImmutableArray Locals { get; } + public abstract IOperation Initializer { get; } + + public sealed override IEnumerable Children + { + get + { + IOperation initializer = Initializer; + if (initializer != null) + { + yield return initializer; + } + + IBlockOperation blockBody = BlockBody; + if (blockBody != null) + { + yield return blockBody; + } + + IBlockOperation expressionBody = ExpressionBody; + if (expressionBody != null) + { + yield return expressionBody; + } + } + } + + public sealed override void Accept(OperationVisitor visitor) + { + visitor.VisitConstructorBodyOperation(this); + } + + public sealed override TResult Accept(OperationVisitor visitor, TArgument argument) + { + return visitor.VisitConstructorBodyOperation(this, argument); + } + } + + internal sealed class ConstructorBodyOperation : BaseConstructorBodyOperation + { + public ConstructorBodyOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, + IOperation initializer, IBlockOperation blockBody, IBlockOperation expressionBody) : + base(locals, semanticModel, syntax) + { + Initializer = SetParentOperation(initializer, this); + BlockBody = SetParentOperation(blockBody, this); + ExpressionBody = SetParentOperation(expressionBody, this); + } + + public override IOperation Initializer { get; } + public override IBlockOperation BlockBody { get; } + public override IBlockOperation ExpressionBody { get; } + } + + internal sealed class LazyConstructorBodyOperation : BaseConstructorBodyOperation + { + private readonly Lazy _lazyInitializer; + private readonly Lazy _lazyBlockBody; + private readonly Lazy _lazyExpressionBody; + + public LazyConstructorBodyOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, + Lazy initializer, Lazy blockBody, Lazy expressionBody) : + base(locals, semanticModel, syntax) + { + _lazyInitializer = initializer; + _lazyBlockBody = blockBody; + _lazyExpressionBody = expressionBody; + } + + public override IOperation Initializer => SetParentOperation(_lazyInitializer.Value, this); + public override IBlockOperation BlockBody => SetParentOperation(_lazyBlockBody.Value, this); + public override IBlockOperation ExpressionBody => SetParentOperation(_lazyExpressionBody.Value, this); + } } diff --git a/src/Compilers/Core/Portable/Operations/IConstructorBodyOperation .cs b/src/Compilers/Core/Portable/Operations/IConstructorBodyOperation .cs new file mode 100644 index 0000000000000..86ff9fdc74e3b --- /dev/null +++ b/src/Compilers/Core/Portable/Operations/IConstructorBodyOperation .cs @@ -0,0 +1,30 @@ +// 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 System.Collections.Immutable; + +namespace Microsoft.CodeAnalysis.Operations +{ + /// + /// Represents a constructor method body operation. + /// + /// Current usage: + /// (1) C# method body for constructor declaration + /// + /// + /// + /// This interface is reserved for implementation by its associated APIs. We reserve the right to + /// change it in the future. + /// + public interface IConstructorBodyOperation : IMethodBodyBaseOperation + { + /// + /// Local declarations contained within the . + /// + ImmutableArray Locals { get; } + + /// + /// Constructor initializer, if any + /// + IOperation Initializer { get; } + } +} diff --git a/src/Compilers/Core/Portable/Operations/IMethodBodyBaseOperation.cs b/src/Compilers/Core/Portable/Operations/IMethodBodyBaseOperation.cs new file mode 100644 index 0000000000000..c18059d04cb18 --- /dev/null +++ b/src/Compilers/Core/Portable/Operations/IMethodBodyBaseOperation.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.CodeAnalysis.Operations +{ + /// + /// Represents a method body operation. + /// + /// Current usage: + /// (1) C# method body + /// + /// + /// + /// This interface is reserved for implementation by its associated APIs. We reserve the right to + /// change it in the future. + /// + public interface IMethodBodyBaseOperation : IOperation + { + /// + /// Method body corresponding to BaseMethodDeclarationSyntax.Body or AccessorDeclarationSyntax.Body + /// + IBlockOperation BlockBody { get; } + + /// + /// Method body corresponding to BaseMethodDeclarationSyntax.ExpressionBody or AccessorDeclarationSyntax.ExpressionBody + /// + IBlockOperation ExpressionBody { get; } + } +} diff --git a/src/Compilers/Core/Portable/Operations/IMethodBodyOperation.cs b/src/Compilers/Core/Portable/Operations/IMethodBodyOperation.cs new file mode 100644 index 0000000000000..2a7db20724d74 --- /dev/null +++ b/src/Compilers/Core/Portable/Operations/IMethodBodyOperation.cs @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.CodeAnalysis.Operations +{ + /// + /// Represents a method body operation. + /// + /// Current usage: + /// (1) C# method body for non-constructor + /// + /// + /// + /// This interface is reserved for implementation by its associated APIs. We reserve the right to + /// change it in the future. + /// + public interface IMethodBodyOperation : IMethodBodyBaseOperation + { + } +} diff --git a/src/Compilers/Core/Portable/Operations/ISymbolInitializerOperation.cs b/src/Compilers/Core/Portable/Operations/ISymbolInitializerOperation.cs index a793c5ce702c0..236238edc7fb8 100644 --- a/src/Compilers/Core/Portable/Operations/ISymbolInitializerOperation.cs +++ b/src/Compilers/Core/Portable/Operations/ISymbolInitializerOperation.cs @@ -1,5 +1,7 @@ // 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 System.Collections.Immutable; + namespace Microsoft.CodeAnalysis.Operations { /// @@ -16,6 +18,11 @@ namespace Microsoft.CodeAnalysis.Operations /// public interface ISymbolInitializerOperation : IOperation { + /// + /// Local declared in and scoped to the . + /// + ImmutableArray Locals { get; } + /// /// Underlying initializer value. /// diff --git a/src/Compilers/Core/Portable/Operations/OperationCloner.cs b/src/Compilers/Core/Portable/Operations/OperationCloner.cs index 9418f124630cc..02d883a8f7c78 100644 --- a/src/Compilers/Core/Portable/Operations/OperationCloner.cs +++ b/src/Compilers/Core/Portable/Operations/OperationCloner.cs @@ -347,7 +347,7 @@ public override IOperation VisitCollectionElementInitializer(ICollectionElementI public override IOperation VisitFieldInitializer(IFieldInitializerOperation operation, object argument) { - return new FieldInitializer(operation.InitializedFields, Visit(operation.Value), operation.Kind, ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); + return new FieldInitializer(operation.Locals, operation.InitializedFields, Visit(operation.Value), operation.Kind, ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } public override IOperation VisitVariableInitializer(IVariableInitializerOperation operation, object argument) @@ -357,12 +357,12 @@ public override IOperation VisitVariableInitializer(IVariableInitializerOperatio public override IOperation VisitPropertyInitializer(IPropertyInitializerOperation operation, object argument) { - return new PropertyInitializer(operation.InitializedProperties, Visit(operation.Value), operation.Kind, ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); + return new PropertyInitializer(operation.Locals, operation.InitializedProperties, Visit(operation.Value), operation.Kind, ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } public override IOperation VisitParameterInitializer(IParameterInitializerOperation operation, object argument) { - return new ParameterInitializer(operation.Parameter, Visit(operation.Value), operation.Kind, ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); + return new ParameterInitializer(operation.Locals, operation.Parameter, Visit(operation.Value), operation.Kind, ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } public override IOperation VisitArrayCreation(IArrayCreationOperation operation, object argument) @@ -490,5 +490,15 @@ public override IOperation VisitRaiseEvent(IRaiseEventOperation operation, objec { return new RaiseEventStatement(Visit(operation.EventReference), VisitArray(operation.Arguments), ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } + + public override IOperation VisitConstructorBodyOperation(IConstructorBodyOperation operation, object argument) + { + return new ConstructorBodyOperation(operation.Locals, ((Operation)operation).SemanticModel, operation.Syntax, Visit(operation.Initializer), Visit(operation.BlockBody), Visit(operation.ExpressionBody)); + } + + public override IOperation VisitMethodBodyOperation(IMethodBodyOperation operation, object argument) + { + return new MethodBodyOperation(((Operation)operation).SemanticModel, operation.Syntax, Visit(operation.BlockBody), Visit(operation.ExpressionBody)); + } } } diff --git a/src/Compilers/Core/Portable/Operations/OperationKind.cs b/src/Compilers/Core/Portable/Operations/OperationKind.cs index 9ad2b608380bf..90ca72e9b87ba 100644 --- a/src/Compilers/Core/Portable/Operations/OperationKind.cs +++ b/src/Compilers/Core/Portable/Operations/OperationKind.cs @@ -183,6 +183,10 @@ public enum OperationKind DeclarationPattern = 0x56, /// Indicates an . TupleBinaryOperator = 0x57, + /// Indicates an . + MethodBodyOperation = 0x58, + /// Indicates an . + ConstructorBodyOperation = 0x59, // /// Indicates an . // https://github.com/dotnet/roslyn/issues/21281 diff --git a/src/Compilers/Core/Portable/Operations/OperationVisitor.cs b/src/Compilers/Core/Portable/Operations/OperationVisitor.cs index 6811f7a44a860..468d3313f17aa 100644 --- a/src/Compilers/Core/Portable/Operations/OperationVisitor.cs +++ b/src/Compilers/Core/Portable/Operations/OperationVisitor.cs @@ -499,6 +499,16 @@ public virtual void VisitRaiseEvent(IRaiseEventOperation operation) { DefaultVisit(operation); } + + public virtual void VisitMethodBodyOperation(IMethodBodyOperation operation) + { + DefaultVisit(operation); + } + + public virtual void VisitConstructorBodyOperation(IConstructorBodyOperation operation) + { + DefaultVisit(operation); + } } /// @@ -1004,5 +1014,15 @@ public virtual TResult VisitRaiseEvent(IRaiseEventOperation operation, TArgument { return DefaultVisit(operation, argument); } + + public virtual TResult VisitMethodBodyOperation(IMethodBodyOperation operation, TArgument argument) + { + return DefaultVisit(operation, argument); + } + + public virtual TResult VisitConstructorBodyOperation(IConstructorBodyOperation operation, TArgument argument) + { + return DefaultVisit(operation, argument); + } } } diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt index 30da669988e98..fe772ba2a6500 100644 --- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt @@ -11,6 +11,16 @@ Microsoft.CodeAnalysis.MetadataImportOptions.All = 2 -> Microsoft.CodeAnalysis.M Microsoft.CodeAnalysis.MetadataImportOptions.Internal = 1 -> Microsoft.CodeAnalysis.MetadataImportOptions Microsoft.CodeAnalysis.MetadataImportOptions.Public = 0 -> Microsoft.CodeAnalysis.MetadataImportOptions Microsoft.CodeAnalysis.OperationKind.TupleBinaryOperator = 87 -> Microsoft.CodeAnalysis.OperationKind +Microsoft.CodeAnalysis.OperationKind.ConstructorBodyOperation = 89 -> Microsoft.CodeAnalysis.OperationKind +Microsoft.CodeAnalysis.OperationKind.MethodBodyOperation = 88 -> Microsoft.CodeAnalysis.OperationKind +Microsoft.CodeAnalysis.Operations.IConstructorBodyOperation +Microsoft.CodeAnalysis.Operations.IConstructorBodyOperation.Initializer.get -> Microsoft.CodeAnalysis.IOperation +Microsoft.CodeAnalysis.Operations.IConstructorBodyOperation.Locals.get -> System.Collections.Immutable.ImmutableArray +Microsoft.CodeAnalysis.Operations.IMethodBodyBaseOperation +Microsoft.CodeAnalysis.Operations.IMethodBodyBaseOperation.BlockBody.get -> Microsoft.CodeAnalysis.Operations.IBlockOperation +Microsoft.CodeAnalysis.Operations.IMethodBodyBaseOperation.ExpressionBody.get -> Microsoft.CodeAnalysis.Operations.IBlockOperation +Microsoft.CodeAnalysis.Operations.IMethodBodyOperation +Microsoft.CodeAnalysis.Operations.ISymbolInitializerOperation.Locals.get -> System.Collections.Immutable.ImmutableArray Microsoft.CodeAnalysis.Operations.ITupleBinaryOperation Microsoft.CodeAnalysis.Operations.ITupleBinaryOperation.LeftOperand.get -> Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.Operations.ITupleBinaryOperation.OperatorKind.get -> Microsoft.CodeAnalysis.Operations.BinaryOperatorKind @@ -23,3 +33,7 @@ static Microsoft.CodeAnalysis.Diagnostic.Create(Microsoft.CodeAnalysis.Diagnosti virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitTupleBinaryOperator(Microsoft.CodeAnalysis.Operations.ITupleBinaryOperation operation) -> void virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitTupleBinaryOperator(Microsoft.CodeAnalysis.Operations.ITupleBinaryOperation operation, TArgument argument) -> TResult Microsoft.CodeAnalysis.Platform.Arm64 = 6 -> Microsoft.CodeAnalysis.Platform +virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitConstructorBodyOperation(Microsoft.CodeAnalysis.Operations.IConstructorBodyOperation operation) -> void +virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitMethodBodyOperation(Microsoft.CodeAnalysis.Operations.IMethodBodyOperation operation) -> void +virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitConstructorBodyOperation(Microsoft.CodeAnalysis.Operations.IConstructorBodyOperation operation, TArgument argument) -> TResult +virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitMethodBodyOperation(Microsoft.CodeAnalysis.Operations.IMethodBodyOperation operation, TArgument argument) -> TResult \ No newline at end of file diff --git a/src/Compilers/Test/Utilities/CSharp/CompilingTestBase.cs b/src/Compilers/Test/Utilities/CSharp/CompilingTestBase.cs index 788be590b03ab..f22eaf2781dce 100644 --- a/src/Compilers/Test/Utilities/CSharp/CompilingTestBase.cs +++ b/src/Compilers/Test/Utilities/CSharp/CompilingTestBase.cs @@ -61,36 +61,6 @@ public void TestAllErrors(string code, params string[] errors) AssertEx.SetEqual(errors, diagnostics.Select(DumpDiagnostic)); } - // Tests just the errors found while binding method M in class C. - [Obsolete("Use VerifyDiagnostics", true)] - public void TestErrors(string code, params string[] errors) - { - var compilation = CreateCompilation(code); - var method = (SourceMemberMethodSymbol)compilation.GlobalNamespace.GetTypeMembers("C").Single().GetMembers("M").Single(); - var factory = compilation.GetBinderFactory(method.SyntaxTree); - var bodyBlock = (BlockSyntax)method.BodySyntax; - var parameterBinderContext = factory.GetBinder(bodyBlock); - var binder = new ExecutableCodeBinder(bodyBlock.Parent, method, parameterBinderContext); - var diagnostics = new DiagnosticBag(); - var block = binder.BindEmbeddedBlock(bodyBlock, diagnostics); - AssertEx.SetEqual(errors, diagnostics.AsEnumerable().Select(DumpDiagnostic)); - } - - [Obsolete("Use VerifyDiagnostics", true)] - public void TestWarnings(string code, params string[] expectedWarnings) - { - var compilation = CreateCompilation(code); - var method = (SourceMemberMethodSymbol)compilation.GlobalNamespace.GetTypeMembers("C").Single().GetMembers("M").Single(); - var factory = compilation.GetBinderFactory(method.SyntaxTree); - var bodyBlock = (BlockSyntax)method.BodySyntax; - var parameterBinderContext = factory.GetBinder(bodyBlock); - var binder = new ExecutableCodeBinder(bodyBlock.Parent, method, parameterBinderContext); - var block = binder.BindEmbeddedBlock(bodyBlock, new DiagnosticBag()); - var actualWarnings = new DiagnosticBag(); - DiagnosticsPass.IssueDiagnostics(compilation, block, actualWarnings, method); - AssertEx.SetEqual(expectedWarnings, actualWarnings.AsEnumerable().Select(DumpDiagnostic)); - } - public const string LINQ = #region the string LINQ defines a complete LINQ API called List1 (for instance method) and List2 (for extension methods) @"using System; diff --git a/src/Compilers/Test/Utilities/CSharp/LocalVariableDeclaratorsCollector.cs b/src/Compilers/Test/Utilities/CSharp/LocalVariableDeclaratorsCollector.cs index d3ca0c756bb1a..879080fdd178e 100644 --- a/src/Compilers/Test/Utilities/CSharp/LocalVariableDeclaratorsCollector.cs +++ b/src/Compilers/Test/Utilities/CSharp/LocalVariableDeclaratorsCollector.cs @@ -20,7 +20,8 @@ internal static ImmutableArray GetDeclarators(SourceMemberMethodSymb { var builder = ArrayBuilder.GetInstance(); var visitor = new LocalVariableDeclaratorsCollector(builder); - visitor.Visit(method.BodySyntax); + var bodies = method.Bodies; + visitor.Visit(bodies.Item1 ?? (SyntaxNode)bodies.Item2); return builder.ToImmutableAndFree(); } diff --git a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb index fd18940202a5f..41293cff33002 100644 --- a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb +++ b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb @@ -853,7 +853,7 @@ Namespace Microsoft.CodeAnalysis.Operations Dim type As ITypeSymbol = Nothing Dim constantValue As [Optional](Of Object) = New [Optional](Of Object)() Dim isImplicit As Boolean = boundFieldInitializer.WasCompilerGenerated - Return New LazyFieldInitializer(initializedFields, value, kind, _semanticModel, syntax, type, constantValue, isImplicit) + Return New LazyFieldInitializer(ImmutableArray(Of ILocalSymbol).Empty, initializedFields, value, kind, _semanticModel, syntax, type, constantValue, isImplicit) End Function Private Function CreateBoundPropertyInitializerOperation(boundPropertyInitializer As BoundPropertyInitializer) As IPropertyInitializerOperation @@ -864,7 +864,7 @@ Namespace Microsoft.CodeAnalysis.Operations Dim type As ITypeSymbol = Nothing Dim constantValue As [Optional](Of Object) = New [Optional](Of Object)() Dim isImplicit As Boolean = boundPropertyInitializer.WasCompilerGenerated - Return New LazyPropertyInitializer(initializedProperties, value, kind, _semanticModel, syntax, type, constantValue, isImplicit) + Return New LazyPropertyInitializer(ImmutableArray(Of ILocalSymbol).Empty, initializedProperties, value, kind, _semanticModel, syntax, type, constantValue, isImplicit) End Function Private Function CreateBoundParameterEqualsValueOperation(boundParameterEqualsValue As BoundParameterEqualsValue) As IParameterInitializerOperation @@ -875,7 +875,7 @@ Namespace Microsoft.CodeAnalysis.Operations Dim type As ITypeSymbol = Nothing Dim constantValue As [Optional](Of Object) = New [Optional](Of Object)() Dim isImplicit As Boolean = boundParameterEqualsValue.WasCompilerGenerated - Return New LazyParameterInitializer(parameter, value, kind, _semanticModel, syntax, type, constantValue, isImplicit) + Return New LazyParameterInitializer(ImmutableArray(Of ILocalSymbol).Empty, parameter, value, kind, _semanticModel, syntax, type, constantValue, isImplicit) End Function Private Function CreateBoundRValuePlaceholderOperation(boundRValuePlaceholder As BoundRValuePlaceholder) As IOperation diff --git a/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.vb b/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.vb index 481c0f96e5ed2..78853159229b5 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.vb @@ -1408,5 +1408,29 @@ End Class Diagnostic("ID", "FieldForPropertyReturnType").WithArguments("FieldForPropertyReturnType", "30").WithLocation(72, 43), Diagnostic("ID", "FieldForIndexerReturnType").WithArguments("FieldForIndexerReturnType", "31").WithLocation(83, 101)) End Sub + + + Public Sub TestMethodBodyOperationAnalyzer() + Dim source = + + + + + + Dim comp = CreateCompilationWithMscorlib40AndVBRuntime(source) + comp.VerifyDiagnostics() + + ' VB methods/constructors don't have an IMethodBodyOperation or an IConstructorBodyOperation. + comp.VerifyAnalyzerDiagnostics({New MethodOrConstructorBodyOperationAnalyzer()}) + End Sub + End Class End Namespace diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EEConstructorSymbol.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EEConstructorSymbol.cs index f596f7ad42139..f5cfdbae24f24 100644 --- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EEConstructorSymbol.cs +++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EEConstructorSymbol.cs @@ -18,7 +18,7 @@ internal EEConstructorSymbol(NamedTypeSymbol containingType) internal override void GenerateMethodBody(TypeCompilationState compilationState, DiagnosticBag diagnostics) { var noLocals = ImmutableArray.Empty; - var initializerInvocation = MethodCompiler.BindConstructorInitializer(this, diagnostics, compilationState.Compilation); + var initializerInvocation = MethodCompiler.BindImplicitConstructorInitializer(this, diagnostics, compilationState.Compilation); var syntax = initializerInvocation.Syntax; compilationState.AddSynthesizedMethod(this, diff --git a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ExpressionCompilerTests.cs b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ExpressionCompilerTests.cs index 50199b5c4b908..98f95d445e57c 100644 --- a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ExpressionCompilerTests.cs +++ b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ExpressionCompilerTests.cs @@ -6409,5 +6409,43 @@ static ref int M(D d) Assert.Equal("error CS8168: Cannot return local 'local' by reference because it is not a ref local", error); }); } + + [Fact] + public void OutVarInExpression() + { + var source = +@"class C +{ + static void Main() + { + } + + static object Test(out int x) + { + x = 1; + return x; + } +}"; + var testData = Evaluate(source, OutputKind.ConsoleApplication, "C.Main", "Test(out var z)"); + var methodData = testData.GetMethodData("<>x.<>m0"); + methodData.VerifyIL( +@"{ + // Code size 46 (0x2e) + .maxstack 4 + .locals init (System.Guid V_0) + IL_0000: ldtoken ""int"" + IL_0005: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)"" + IL_000a: ldstr ""z"" + IL_000f: ldloca.s V_0 + IL_0011: initobj ""System.Guid"" + IL_0017: ldloc.0 + IL_0018: ldnull + IL_0019: call ""void Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.CreateVariable(System.Type, string, System.Guid, byte[])"" + IL_001e: ldstr ""z"" + IL_0023: call ""int Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.GetVariableAddress(string)"" + IL_0028: call ""object C.Test(out int)"" + IL_002d: ret +}"); + } } } diff --git a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/LocalsTests.cs b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/LocalsTests.cs index fa930bb3f3e7b..19404b0483294 100644 --- a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/LocalsTests.cs +++ b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/LocalsTests.cs @@ -3888,6 +3888,1154 @@ static void M(object x) }); } + [Fact] + public void LocalsInFieldInitializer_01() + { + var source = +@"class C +{ +#line 1000 + bool Test1 = TakeOutParam(1, out var x1); + + C() {} + + static bool TakeOutParam(int y, out int x) + { + x = y; + return true; + } +}"; + var compilation0 = CreateCompilation(source, options: TestOptions.DebugDll); + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C..ctor", atLineNumber: 1000); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 2); + VerifyLocal(testData, typeName, locals[0], "<>m0", "this", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0) //x1 + IL_0000: ldarg.0 + IL_0001: ret +}"); + VerifyLocal(testData, typeName, locals[1], "<>m1", "x1", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0) //x1 + IL_0000: ldloc.0 + IL_0001: ret +}"); + + locals.Free(); + }); + } + + [Fact] + public void LocalsInFieldInitializer_02() + { + var source = +@"class C : Base +{ +#line 1000 + bool Test1 = TakeOutParam(1, out var x1), + Test2 = TakeOutParam(2, out var x2); + + C() +#line 2000 + : base(TakeOutParam(0, out var x0)) + {} + + static bool TakeOutParam(int y, out int x) + { + x = y; + return true; + } +} + +class Base +{ + public Base(bool x) {} +} +"; + var compilation0 = CreateCompilation(source, options: TestOptions.DebugDll); + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C..ctor", atLineNumber: 1000); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 2); + VerifyLocal(testData, typeName, locals[0], "<>m0", "this", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0, //x1 + int V_1, + int V_2) + IL_0000: ldarg.0 + IL_0001: ret +}"); + VerifyLocal(testData, typeName, locals[1], "<>m1", "x1", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0, //x1 + int V_1, + int V_2) + IL_0000: ldloc.0 + IL_0001: ret +}"); + + locals.Free(); + }); + + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C..ctor", atLineNumber: 1001); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 2); + VerifyLocal(testData, typeName, locals[0], "<>m0", "this", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0, + int V_1, //x2 + int V_2) + IL_0000: ldarg.0 + IL_0001: ret +}"); + VerifyLocal(testData, typeName, locals[1], "<>m1", "x2", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0, + int V_1, //x2 + int V_2) + IL_0000: ldloc.1 + IL_0001: ret +}"); + + locals.Free(); + }); + + + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C..ctor", atLineNumber: 2000); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 2); + VerifyLocal(testData, typeName, locals[0], "<>m0", "this", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0, + int V_1, + int V_2) //x0 + IL_0000: ldarg.0 + IL_0001: ret +}"); + VerifyLocal(testData, typeName, locals[1], "<>m1", "x0", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0, + int V_1, + int V_2) //x0 + IL_0000: ldloc.2 + IL_0001: ret +}"); + + locals.Free(); + }); + } + + [Fact] + public void LocalsInFieldInitializer_03() + { + var source = +@"class C +{ +#line 1000 + bool Test1 = TakeOutParam(1, out var x1) && F(() => x1); + + C() {} + + static bool TakeOutParam(int y, out int x) + { + x = y; + return true; + } + static bool F(System.Func x) + { + throw null; + } +}"; + var compilation0 = CreateCompilation(source, options: TestOptions.DebugDll); + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C..ctor", atLineNumber: 1000); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 2); + VerifyLocal(testData, typeName, locals[0], "<>m0", "this", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (C.<>c__DisplayClass1_0 V_0) //CS$<>8__locals0 + IL_0000: ldarg.0 + IL_0001: ret +}"); + VerifyLocal(testData, typeName, locals[1], "<>m1", "x1", expectedILOpt: +@"{ + // Code size 7 (0x7) + .maxstack 1 + .locals init (C.<>c__DisplayClass1_0 V_0) //CS$<>8__locals0 + IL_0000: ldloc.0 + IL_0001: ldfld ""int C.<>c__DisplayClass1_0.x1"" + IL_0006: ret +}"); + + locals.Free(); + }); + + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C.<>c__DisplayClass1_0.<.ctor>b__0", atLineNumber: 1000); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 1); + VerifyLocal(testData, typeName, locals[0], "<>m0", "x1", expectedILOpt: +@"{ + // Code size 7 (0x7) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: ldfld ""int C.<>c__DisplayClass1_0.x1"" + IL_0006: ret +}"); + + locals.Free(); + }); + } + + [Fact] + public void LocalsInFieldInitializer_04() + { + var source = +@"class C +{ +#line 1000 + bool Test1 = TakeOutParam(1, out var x1) && F(() => x1), + Test2 = TakeOutParam(2, out var x2) && F(() => x2); + + static bool TakeOutParam(int y, out int x) + { + x = y; + return true; + } + static bool F(System.Func x) + { + throw null; + } +}"; + var compilation0 = CreateCompilation(source, options: TestOptions.DebugDll); + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C..ctor", atLineNumber: 1000); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 2); + VerifyLocal(testData, typeName, locals[0], "<>m0", "this", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (C.<>c__DisplayClass4_0 V_0, //CS$<>8__locals0 + C.<>c__DisplayClass4_1 V_1) + IL_0000: ldarg.0 + IL_0001: ret +}"); + VerifyLocal(testData, typeName, locals[1], "<>m1", "x1", expectedILOpt: +@"{ + // Code size 7 (0x7) + .maxstack 1 + .locals init (C.<>c__DisplayClass4_0 V_0, //CS$<>8__locals0 + C.<>c__DisplayClass4_1 V_1) + IL_0000: ldloc.0 + IL_0001: ldfld ""int C.<>c__DisplayClass4_0.x1"" + IL_0006: ret +}"); + + locals.Free(); + }); + + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C.<>c__DisplayClass4_0.<.ctor>b__0", atLineNumber: 1000); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 1); + VerifyLocal(testData, typeName, locals[0], "<>m0", "x1", expectedILOpt: +@"{ + // Code size 7 (0x7) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: ldfld ""int C.<>c__DisplayClass4_0.x1"" + IL_0006: ret +}"); + + locals.Free(); + }); + + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C..ctor", atLineNumber: 1001); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 2); + VerifyLocal(testData, typeName, locals[0], "<>m0", "this", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (C.<>c__DisplayClass4_0 V_0, + C.<>c__DisplayClass4_1 V_1) //CS$<>8__locals1 + IL_0000: ldarg.0 + IL_0001: ret +}"); + VerifyLocal(testData, typeName, locals[1], "<>m1", "x2", expectedILOpt: +@"{ + // Code size 7 (0x7) + .maxstack 1 + .locals init (C.<>c__DisplayClass4_0 V_0, + C.<>c__DisplayClass4_1 V_1) //CS$<>8__locals1 + IL_0000: ldloc.1 + IL_0001: ldfld ""int C.<>c__DisplayClass4_1.x2"" + IL_0006: ret +}"); + + locals.Free(); + }); + + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C.<>c__DisplayClass4_1.<.ctor>b__1", atLineNumber: 1001); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 1); + VerifyLocal(testData, typeName, locals[0], "<>m0", "x2", expectedILOpt: +@"{ + // Code size 7 (0x7) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: ldfld ""int C.<>c__DisplayClass4_1.x2"" + IL_0006: ret +}"); + + locals.Free(); + }); + } + + [Fact] + public void LocalsInPropertyInitializer_01() + { + var source = +@"class C +{ +#line 1000 + bool Test1 { get; } = TakeOutParam(1, out var x1); + + C() {} + + static bool TakeOutParam(int y, out int x) + { + x = y; + return true; + } +}"; + var compilation0 = CreateCompilation(source, options: TestOptions.DebugDll); + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C..ctor", atLineNumber: 1000); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 2); + VerifyLocal(testData, typeName, locals[0], "<>m0", "this", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0) //x1 + IL_0000: ldarg.0 + IL_0001: ret +}"); + VerifyLocal(testData, typeName, locals[1], "<>m1", "x1", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0) //x1 + IL_0000: ldloc.0 + IL_0001: ret +}"); + + locals.Free(); + }); + } + + [Fact] + public void LocalsInPropertyInitializer_02() + { + var source = +@"class C +{ +#line 1000 + bool Test1 { get; } = TakeOutParam(1, out var x1) && F(() => x1); + + C() {} + + static bool TakeOutParam(int y, out int x) + { + x = y; + return true; + } + static bool F(System.Func x) + { + throw null; + } +}"; + var compilation0 = CreateCompilation(source, options: TestOptions.DebugDll); + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C..ctor", atLineNumber: 1000); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 2); + VerifyLocal(testData, typeName, locals[0], "<>m0", "this", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (C.<>c__DisplayClass3_0 V_0) //CS$<>8__locals0 + IL_0000: ldarg.0 + IL_0001: ret +}"); + VerifyLocal(testData, typeName, locals[1], "<>m1", "x1", expectedILOpt: +@"{ + // Code size 7 (0x7) + .maxstack 1 + .locals init (C.<>c__DisplayClass3_0 V_0) //CS$<>8__locals0 + IL_0000: ldloc.0 + IL_0001: ldfld ""int C.<>c__DisplayClass3_0.x1"" + IL_0006: ret +}"); + + locals.Free(); + }); + + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C.<>c__DisplayClass3_0.<.ctor>b__0", atLineNumber: 1000); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 1); + VerifyLocal(testData, typeName, locals[0], "<>m0", "x1", expectedILOpt: +@"{ + // Code size 7 (0x7) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: ldfld ""int C.<>c__DisplayClass3_0.x1"" + IL_0006: ret +}"); + + locals.Free(); + }); + } + + [Fact] + public void LocalsInConstructorInitializer_01() + { + var source = +@"class C : Base +{ + C() +#line 1000 + : base(TakeOutParam(1, out var x1)) + {} + + static bool TakeOutParam(int y, out int x) + { + x = y; + return true; + } +} + +class Base +{ + public Base(bool x) {} +} +"; + var compilation0 = CreateCompilation(source, options: TestOptions.DebugDll); + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C..ctor", atLineNumber: 1000); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 2); + VerifyLocal(testData, typeName, locals[0], "<>m0", "this", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0) //x1 + IL_0000: ldarg.0 + IL_0001: ret +}"); + + VerifyLocal(testData, typeName, locals[1], "<>m1", "x1", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0) //x1 + IL_0000: ldloc.0 + IL_0001: ret +}"); + + locals.Free(); + }); + } + + [Fact] + public void LocalsInConstructorInitializer_02() + { + var source = +@"class C : Base +{ + C() + : base(TakeOutParam(1, out var x1)) + { +#line 1000 + ; + } + + static bool TakeOutParam(int y, out int x) + { + x = y; + return true; + } +} + +class Base +{ + public Base(bool x) {} +} +"; + var compilation0 = CreateCompilation(source, options: TestOptions.DebugDll); + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C..ctor", atLineNumber: 1000); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 2); + VerifyLocal(testData, typeName, locals[0], "<>m0", "this", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0) //x1 + IL_0000: ldarg.0 + IL_0001: ret +}"); + + VerifyLocal(testData, typeName, locals[1], "<>m1", "x1", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0) //x1 + IL_0000: ldloc.0 + IL_0001: ret +}"); + + locals.Free(); + }); + } + + [Fact] + public void LocalsInConstructorInitializer_03() + { + var source = +@"class C : Base +{ + C() + : base(TakeOutParam(1, out var x1)) +#line 1000 + => System.Console.WriteLine(); + + static bool TakeOutParam(int y, out int x) + { + x = y; + return true; + } +} + +class Base +{ + public Base(bool x) {} +} +"; + var compilation0 = CreateCompilation(source, options: TestOptions.DebugDll); + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C..ctor", atLineNumber: 1000); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 2); + VerifyLocal(testData, typeName, locals[0], "<>m0", "this", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0) //x1 + IL_0000: ldarg.0 + IL_0001: ret +}"); + + VerifyLocal(testData, typeName, locals[1], "<>m1", "x1", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0) //x1 + IL_0000: ldloc.0 + IL_0001: ret +}"); + + locals.Free(); + }); + } + + [Fact] + public void LocalsInConstructorInitializer_04() + { + var source = +@"class C : Base +{ + C() + : base(TakeOutParam(1, out var x1)) + { + int x2 = 1; +#line 1000 + System.Console.WriteLine(x2); + } + + static bool TakeOutParam(int y, out int x) + { + x = y; + return true; + } +} + +class Base +{ + public Base(bool x) {} +} +"; + var compilation0 = CreateCompilation(source, options: TestOptions.DebugDll); + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C..ctor", atLineNumber: 1000); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 3); + VerifyLocal(testData, typeName, locals[0], "<>m0", "this", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0, //x1 + int V_1) //x2 + IL_0000: ldarg.0 + IL_0001: ret +}"); + + VerifyLocal(testData, typeName, locals[1], "<>m1", "x1", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0, //x1 + int V_1) //x2 + IL_0000: ldloc.0 + IL_0001: ret +}"); + + VerifyLocal(testData, typeName, locals[2], "<>m2", "x2", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0, //x1 + int V_1) //x2 + IL_0000: ldloc.1 + IL_0001: ret +}"); + locals.Free(); + }); + } + + [Fact] + public void LocalsInConstructorInitializer_05() + { + var source = +@"class C : Base +{ + C() + : base(TakeOutParam(1, out var x1)) +#line 1000 + => System.Console.WriteLine(TakeOutParam(2, out var x2)); + + static bool TakeOutParam(int y, out int x) + { + x = y; + return true; + } +} + +class Base +{ + public Base(bool x) {} +} +"; + var compilation0 = CreateCompilation(source, options: TestOptions.DebugDll); + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C..ctor", atLineNumber: 1000); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 3); + VerifyLocal(testData, typeName, locals[0], "<>m0", "this", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0, //x1 + int V_1) //x2 + IL_0000: ldarg.0 + IL_0001: ret +}"); + + VerifyLocal(testData, typeName, locals[1], "<>m1", "x1", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0, //x1 + int V_1) //x2 + IL_0000: ldloc.0 + IL_0001: ret +}"); + + VerifyLocal(testData, typeName, locals[2], "<>m2", "x2", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0, //x1 + int V_1) //x2 + IL_0000: ldloc.1 + IL_0001: ret +}"); + locals.Free(); + }); + } + + [Fact] + public void LocalsInConstructorInitializer_06() + { + var source = +@"class C : Base +{ + C() +#line 1000 + : base(TakeOutParam(1, out var x1) && F(() => x1)) + {} + + static bool TakeOutParam(int y, out int x) + { + x = y; + return true; + } + static bool F(System.Func x) + { + throw null; + } +} + +class Base +{ + public Base(bool x) {} +} +"; + var compilation0 = CreateCompilation(source, options: TestOptions.DebugDll); + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C..ctor", atLineNumber: 1000); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 2); + VerifyLocal(testData, typeName, locals[0], "<>m0", "this", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (C.<>c__DisplayClass0_0 V_0) //CS$<>8__locals0 + IL_0000: ldarg.0 + IL_0001: ret +}"); + + VerifyLocal(testData, typeName, locals[1], "<>m1", "x1", expectedILOpt: +@"{ + // Code size 7 (0x7) + .maxstack 1 + .locals init (C.<>c__DisplayClass0_0 V_0) //CS$<>8__locals0 + IL_0000: ldloc.0 + IL_0001: ldfld ""int C.<>c__DisplayClass0_0.x1"" + IL_0006: ret +}"); + + locals.Free(); + }); + + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C.<>c__DisplayClass0_0.<.ctor>b__0", atLineNumber: 1000); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 1); + VerifyLocal(testData, typeName, locals[0], "<>m0", "x1", expectedILOpt: +@"{ + // Code size 7 (0x7) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: ldfld ""int C.<>c__DisplayClass0_0.x1"" + IL_0006: ret +}"); + + locals.Free(); + }); + } + + [Fact] + public void LocalsInConstructorInitializer_07() + { + var source = +@"class C +{ + C() +#line 1000 + : this(TakeOutParam(1, out var x1)) + {} + + static bool TakeOutParam(int y, out int x) + { + x = y; + return true; + } + + C(bool x) {} +} +"; + var compilation0 = CreateCompilation(source, options: TestOptions.DebugDll); + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C..ctor", atLineNumber: 1000); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 2); + VerifyLocal(testData, typeName, locals[0], "<>m0", "this", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0) //x1 + IL_0000: ldarg.0 + IL_0001: ret +}"); + + VerifyLocal(testData, typeName, locals[1], "<>m1", "x1", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0) //x1 + IL_0000: ldloc.0 + IL_0001: ret +}"); + + locals.Free(); + }); + } + + [Fact] + public void LocalsInQuery_01() + { + var source = +@" +using System.Linq; + +class C +{ + C() + { +#line 1000 + var q = from a in new [] {1} + where + TakeOutParam(a, out var x1) + select a; + } + + static bool TakeOutParam(int y, out int x) + { + x = y; + return true; + } +}"; + var compilation0 = CreateCompilation(source, options: TestOptions.DebugDll); + + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C.<>c.<.ctor>b__0_0", atLineNumber: 1002); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 2); + VerifyLocal(testData, typeName, locals[0], "<>m0", "a", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0) //x1 + IL_0000: ldarg.1 + IL_0001: ret +}"); + + VerifyLocal(testData, typeName, locals[1], "<>m1", "x1", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (int V_0) //x1 + IL_0000: ldloc.0 + IL_0001: ret +}"); + + locals.Free(); + }); + } + + [Fact] + public void LocalsInQuery_02() + { + var source = +@" +using System.Linq; + +class C +{ + C() + { +#line 1000 + var q = from a in new [] {1} + where + TakeOutParam(a, out var x1) && F(() => x1) + select a; + } + + static bool TakeOutParam(int y, out int x) + { + x = y; + return true; + } + static bool F(System.Func x) + { + throw null; + } +}"; + var compilation0 = CreateCompilation(source, options: TestOptions.DebugDll); + + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C.<>c.<.ctor>b__0_0", atLineNumber: 1002); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 2); + VerifyLocal(testData, typeName, locals[0], "<>m0", "a", expectedILOpt: +@"{ + // Code size 2 (0x2) + .maxstack 1 + .locals init (C.<>c__DisplayClass0_0 V_0) //CS$<>8__locals0 + IL_0000: ldarg.1 + IL_0001: ret +}"); + + VerifyLocal(testData, typeName, locals[1], "<>m1", "x1", expectedILOpt: +@"{ + // Code size 7 (0x7) + .maxstack 1 + .locals init (C.<>c__DisplayClass0_0 V_0) //CS$<>8__locals0 + IL_0000: ldloc.0 + IL_0001: ldfld ""int C.<>c__DisplayClass0_0.x1"" + IL_0006: ret +}"); + + locals.Free(); + }); + + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C.<>c__DisplayClass0_0.<.ctor>b__1", atLineNumber: 1002); + + var testData = new CompilationTestData(); + var locals = ArrayBuilder.GetInstance(); + string typeName; + var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); + Assert.NotNull(assembly); + Assert.NotEqual(assembly.Count, 0); + + Assert.Equal(locals.Count, 1); + VerifyLocal(testData, typeName, locals[0], "<>m0", "x1", expectedILOpt: +@"{ + // Code size 7 (0x7) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: ldfld ""int C.<>c__DisplayClass0_0.x1"" + IL_0006: ret +}"); + + locals.Free(); + }); + } + private static void GetLocals(RuntimeInstance runtime, string methodName, bool argumentsOnly, ArrayBuilder locals, int count, out string typeName, out CompilationTestData testData) { var context = CreateMethodContext(runtime, methodName); diff --git a/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs b/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs index 6bc597239702c..8529fa9cf8a80 100644 --- a/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs +++ b/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs @@ -1210,6 +1210,7 @@ public override void VisitFieldInitializer(IFieldInitializerOperation operation) Unindent(); } + LogLocals(operation.Locals); base.VisitFieldInitializer(operation); } @@ -1217,7 +1218,7 @@ public override void VisitVariableInitializer(IVariableInitializerOperation oper { LogString(nameof(IVariableInitializerOperation)); LogCommonPropertiesAndNewLine(operation); - + Assert.Empty(operation.Locals); base.VisitVariableInitializer(operation); } @@ -1251,7 +1252,8 @@ public override void VisitPropertyInitializer(IPropertyInitializerOperation oper Unindent(); } - + + LogLocals(operation.Locals); base.VisitPropertyInitializer(operation); } @@ -1262,6 +1264,7 @@ public override void VisitParameterInitializer(IParameterInitializerOperation op LogString(")"); LogCommonPropertiesAndNewLine(operation); + LogLocals(operation.Locals); base.VisitParameterInitializer(operation); } @@ -1554,6 +1557,25 @@ public override void VisitRaiseEvent(IRaiseEventOperation operation) VisitArguments(operation.Arguments); } + public override void VisitConstructorBodyOperation(IConstructorBodyOperation operation) + { + LogString(nameof(IConstructorBodyOperation)); + LogCommonPropertiesAndNewLine(operation); + + LogLocals(operation.Locals); + Visit(operation.Initializer, "Initializer"); + Visit(operation.BlockBody, "BlockBody"); + Visit(operation.ExpressionBody, "ExpressionBody"); + } + + public override void VisitMethodBodyOperation(IMethodBodyOperation operation) + { + LogString(nameof(IMethodBodyOperation)); + LogCommonPropertiesAndNewLine(operation); + Visit(operation.BlockBody, "BlockBody"); + Visit(operation.ExpressionBody, "ExpressionBody"); + } + #endregion } } diff --git a/src/Test/Utilities/Portable/Compilation/TestOperationVisitor.cs b/src/Test/Utilities/Portable/Compilation/TestOperationVisitor.cs index 821a56d8d66f2..07498388446a3 100644 --- a/src/Test/Utilities/Portable/Compilation/TestOperationVisitor.cs +++ b/src/Test/Utilities/Portable/Compilation/TestOperationVisitor.cs @@ -7,6 +7,7 @@ using System.Linq; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Operations; +using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.VisualBasic; using Roslyn.Test.Utilities; using Xunit; @@ -86,11 +87,7 @@ public override void Visit(IOperation operation) public override void VisitBlock(IBlockOperation operation) { Assert.Equal(OperationKind.Block, operation.Kind); - - foreach (var local in operation.Locals) - { - Assert.NotNull(local); - } + VisitLocals(operation.Locals); AssertEx.Equal(operation.Operations, operation.Children); } @@ -839,6 +836,7 @@ public override void VisitCollectionElementInitializer(ICollectionElementInitial private void VisitSymbolInitializer(ISymbolInitializerOperation operation) { + VisitLocals(operation.Locals); Assert.Same(operation.Value, operation.Children.Single()); } @@ -855,6 +853,7 @@ public override void VisitFieldInitializer(IFieldInitializerOperation operation) public override void VisitVariableInitializer(IVariableInitializerOperation operation) { Assert.Equal(OperationKind.VariableInitializer, operation.Kind); + Assert.Empty(operation.Locals); VisitSymbolInitializer(operation); } @@ -1120,5 +1119,56 @@ public override void VisitRangeCaseClause(IRangeCaseClauseOperation operation) AssertEx.Equal(new[] { operation.MinimumValue, operation.MaximumValue }, operation.Children); } } + + public override void VisitConstructorBodyOperation(IConstructorBodyOperation operation) + { + Assert.Equal(OperationKind.ConstructorBodyOperation, operation.Kind); + VisitLocals(operation.Locals); + + var builder = ArrayBuilder.GetInstance(); + + if (operation.Initializer != null) + { + builder.Add(operation.Initializer); + } + + if (operation.BlockBody != null) + { + builder.Add(operation.BlockBody); + } + + if (operation.ExpressionBody != null) + { + builder.Add(operation.ExpressionBody); + } + + AssertEx.Equal(builder, operation.Children); + builder.Free(); + } + + public override void VisitMethodBodyOperation(IMethodBodyOperation operation) + { + Assert.Equal(OperationKind.MethodBodyOperation, operation.Kind); + + if (operation.BlockBody != null) + { + if (operation.ExpressionBody != null) + { + AssertEx.Equal(new[] { operation.BlockBody, operation.ExpressionBody }, operation.Children); + } + else + { + Assert.Same(operation.BlockBody, operation.Children.Single()); + } + } + else if (operation.ExpressionBody != null) + { + Assert.Same(operation.ExpressionBody, operation.Children.Single()); + } + else + { + Assert.Empty(operation.Children); + } + } } } diff --git a/src/Test/Utilities/Portable/Diagnostics/CommonDiagnosticAnalyzers.cs b/src/Test/Utilities/Portable/Diagnostics/CommonDiagnosticAnalyzers.cs index ddbf62f6678c3..6d17e9e499ed3 100644 --- a/src/Test/Utilities/Portable/Diagnostics/CommonDiagnosticAnalyzers.cs +++ b/src/Test/Utilities/Portable/Diagnostics/CommonDiagnosticAnalyzers.cs @@ -958,6 +958,28 @@ private static void AnalyzerFieldReferenceOperation(IFieldReferenceOperation ope } } + [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] + public sealed class MethodOrConstructorBodyOperationAnalyzer : DiagnosticAnalyzer + { + public static readonly DiagnosticDescriptor Descriptor = new DiagnosticDescriptor( + "ID", + "Title", + "Method {0}", + "Category", + defaultSeverity: DiagnosticSeverity.Warning, + isEnabledByDefault: true); + + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Descriptor); + public override void Initialize(AnalysisContext context) + { + context.RegisterOperationAction(operationContext => + { + var diagnostic = Diagnostic.Create(Descriptor, operationContext.Operation.Syntax.GetLocation(), operationContext.ContainingSymbol.Name); + operationContext.ReportDiagnostic(diagnostic); + }, OperationKind.MethodBodyOperation, OperationKind.ConstructorBodyOperation); + } + } + [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] public class GeneratedCodeAnalyzer : DiagnosticAnalyzer {