From 43cf0c5517f751421736cd219365cdce67528ca1 Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Mon, 6 Jun 2016 16:19:41 -0700 Subject: [PATCH 01/11] Refreshing ValueTuple library --- .../NetFX/ValueTuple/System.ValueTuple.dll | Bin 46792 -> 77512 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/Compilers/Test/Resources/Core/NetFX/ValueTuple/System.ValueTuple.dll b/src/Compilers/Test/Resources/Core/NetFX/ValueTuple/System.ValueTuple.dll index bf1b74f27f12f6ecdcd7b0e3f5396ce199a67254..c20ee6cf2ad231078d0c54bdbb7713cbaf8bcda5 100644 GIT binary patch literal 77512 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
Ia;Jjw33 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�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 YNB8{BJ0iY^^M`uKbGcC8NKm^O0ACQFyZ`_I From c52e3d47c3ccb06279907cd8a1a508c6fbf7cf0a Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Tue, 7 Jun 2016 14:12:02 -0700 Subject: [PATCH 02/11] Lookup for Deconstruct method --- docs/features/deconstruction.md | 14 +- .../Portable/Binder/Binder_Expressions.cs | 13 +- .../Portable/Binder/Binder_Invocation.cs | 11 +- .../Portable/Binder/Binder_Statements.cs | 113 ++++--- .../OverloadResolution/OverloadResolution.cs | 23 +- .../OverloadResolutionResult.cs | 4 +- .../CSharp/Portable/BoundTree/BoundNodes.xml | 7 +- .../CSharp/Portable/BoundTree/Expression.cs | 26 +- .../CSharp/Portable/BoundTree/Formatting.cs | 11 + .../OutDeconstructVarPendingInference.cs | 23 ++ .../CSharp/Portable/CSharpCodeAnalysis.csproj | 1 + .../Portable/CSharpResources.Designer.cs | 9 + .../CSharp/Portable/CSharpResources.resx | 3 + .../CSharp/Portable/Errors/ErrorCode.cs | 1 + ...writer_DeconstructionAssignmentOperator.cs | 11 +- .../Emit/CodeGen/CodeGenDeconstructTests.cs | 302 ++++++++++++++++-- 16 files changed, 482 insertions(+), 90 deletions(-) create mode 100644 src/Compilers/CSharp/Portable/BoundTree/OutDeconstructVarPendingInference.cs diff --git a/docs/features/deconstruction.md b/docs/features/deconstruction.md index 945498dff3667..93d4a303a1837 100644 --- a/docs/features/deconstruction.md +++ b/docs/features/deconstruction.md @@ -41,6 +41,8 @@ It will be updated to support deconstruction-assignment, ie. when the left-hand- - Each item on the left needs to be assignable and needs to be compatible with corresponding position on the right (resulting from previous step). - Needs to handle nesting case such as `(x, (y, z)) = M();`, but note that the second item in the top-level group has no discernable type. +#### Evaluation order + The evaluation order can be summarized as: (1) all the side-effects on the left-hand-side, (2) all the Deconstruct invocations (if not tuple), (3) conversions (if needed), and (4) assignments. In the general case, the lowering for deconstruction-assignment would translate: `(expressionX, expressionY, expressionZ) = expressionRight` into: @@ -100,7 +102,17 @@ evaluate the right-hand-side and do a tuple conversion (using a fake tuple repre assign element-wise from the right to the left ``` -Note that tuples (`System.ValueTuple` and `System.Tuple`) don't need to invoke Deconstruct. +#### Resolution of the Deconstruct method + +The resolution is equivalent to typing `rhs.Deconstruct(out var x1, out var x2, ...);` with the appropriate number of parameters to deconstruct into. +It is based on normal overload resolution. +This implies that `rhs` cannot be dynamic. +Also, the `Deconstruct` method must be an instance method or an extension (but not a static method). + +#### Tuple Deconstruction + +Note that tuples (`System.ValueTuple`) don't need to invoke Deconstruct. +`System.Tuple` are not recognized as tuples, and so will rely on Deconstruct (which will be provided for up to 3 nestings deep, that is 21 elements) ###Deconstruction-declaration (deconstruction into new variables): diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index 4d1aba2c07219..affbabbbdc339 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -345,7 +345,7 @@ internal BoundExpression BindValueAllowArgList(ExpressionSyntax node, Diagnostic if (isMemberInitializer) { initializer = initializerBinder.WrapWithVariablesIfAny(initializerOpt, initializer); - } + } return initializer; } @@ -1389,8 +1389,8 @@ private BoundExpression BindNonMethod(SimpleNameSyntax node, Symbol symbol, Diag var parameter = (ParameterSymbol)symbol; if (IsBadLocalOrParameterCapture(parameter, parameter.RefKind)) { - Error(diagnostics, ErrorCode.ERR_AnonDelegateCantUse, node, parameter.Name); - } + Error(diagnostics, ErrorCode.ERR_AnonDelegateCantUse, node, parameter.Name); + } return new BoundParameter(node, parameter, hasErrors: isError); } @@ -1829,7 +1829,7 @@ private BoundExpression BindOriginal(OriginalExpressionSyntax syntax, Diagnostic { var replacedProperty = (PropertySymbol)replaced; Debug.Assert((object)replacedProperty != null); - if (replacedProperty.IsIndexer || replacedProperty.IsIndexedProperty) + if (replacedProperty.IsIndexer || replacedProperty.IsIndexedProperty) { return new BoundPropertyGroup( syntax, @@ -2230,6 +2230,11 @@ private bool RefMustBeObeyed(bool isDelegateCreation, ArgumentSyntax argumentSyn arguments[arg] = CreateConversion(argument.Syntax, argument, kind, false, type, diagnostics); } + else if (argument.Kind == BoundKind.OutDeconstructVarPendingInference) + { + TypeSymbol parameterType = GetCorrespondingParameterType(ref result, parameters, arg); + arguments[arg] = ((OutDeconstructVarPendingInference)argument).SetInferredType(parameterType, success: true); + } } } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs index 763599635e26d..f4b2d410bfa00 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs @@ -114,6 +114,7 @@ private static ImmutableArray GetOriginalMethods(OverloadResolutio var analyzedArguments = AnalyzedArguments.GetInstance(); analyzedArguments.Arguments.AddRange(args); + Debug.Assert(!args.Any(e => e.Kind == BoundKind.OutDeconstructVarPendingInference)); BoundExpression result = BindInvocationExpression( node, node, methodName, boundExpression, analyzedArguments, diagnostics, queryClause, allowUnexpandedForm: allowUnexpandedForm); @@ -1100,7 +1101,8 @@ private ImmutableArray BuildArgumentsForErrorRecovery(AnalyzedA { BoundKind argumentKind = oldArguments[i].Kind; - if (argumentKind == BoundKind.UnboundLambda && i < parameterCount) + if (argumentKind == BoundKind.OutDeconstructVarPendingInference || + (argumentKind == BoundKind.UnboundLambda && i < parameterCount)) { ArrayBuilder newArguments = ArrayBuilder.GetInstance(argumentCount); newArguments.AddRange(oldArguments); @@ -1120,8 +1122,15 @@ private ImmutableArray BuildArgumentsForErrorRecovery(AnalyzedA newArguments[i] = ((UnboundLambda)oldArgument).Bind(parameterType); } break; + case BoundKind.OutDeconstructVarPendingInference: + newArguments[i] = ((OutDeconstructVarPendingInference)oldArgument).SetInferredType(parameters[i].Type, success: true); + break; } } + else if (oldArgument.Kind == BoundKind.OutDeconstructVarPendingInference) + { + newArguments[i] = ((OutDeconstructVarPendingInference)oldArgument).FailInference(this); + } i++; } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs index 86ee7db2c0368..328af374595df 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs @@ -1,6 +1,5 @@ // 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; @@ -1831,7 +1830,7 @@ private BoundExpression BindDeconstructionAssignment(AssignmentExpressionSyntax /// This will generate and stack appropriate deconstruction and assignment steps for a non-tuple type. /// Returns null if there was an error (if a suitable Deconstruct method was not found). /// - static private BoundDeconstructionDeconstructStep MakeNonTupleDeconstructStep( + private BoundDeconstructionDeconstructStep MakeNonTupleDeconstructStep( BoundDeconstructValuePlaceholder targetPlaceholder, AssignmentExpressionSyntax syntax, DiagnosticBag diagnostics, @@ -1840,16 +1839,22 @@ private BoundExpression BindDeconstructionAssignment(AssignmentExpressionSyntax ArrayBuilder assignmentSteps) { // symbol and parameters for Deconstruct - MethodSymbol deconstructMethod = FindDeconstruct(variables.Length, targetPlaceholder, syntax, diagnostics); + ImmutableArray outPlaceholders; + var deconstructInvocation = MakeDeconstructInvocationExpression(variables.Length, targetPlaceholder, syntax, diagnostics, out outPlaceholders); - if ((object)deconstructMethod == null) + if (deconstructInvocation.HasAnyErrors) { return null; } - - return new BoundDeconstructionDeconstructStep(syntax, deconstructMethod, targetPlaceholder, deconstructMethod.Parameters.SelectAsArray((p, s) => new BoundDeconstructValuePlaceholder(s, p.Type), syntax)); + else + { + return new BoundDeconstructionDeconstructStep(syntax, deconstructInvocation, targetPlaceholder, outPlaceholders); + } } + /// + /// Holds the variables on the LHS of a deconstruction as a tree of bound expressions. + /// private class DeconstructionVariable { public readonly BoundExpression Single; @@ -1898,7 +1903,7 @@ public DeconstructionVariable(ImmutableArray variables) } else { - var assignment = MakeAssignmentInfo(variable.Single, valuePlaceholder.Type, valuePlaceholder, syntax, diagnostics); + var assignment = MakeDeconstructionAssignmentStep(variable.Single, valuePlaceholder.Type, valuePlaceholder, syntax, diagnostics); assignmentSteps.Add(assignment); } } @@ -1962,7 +1967,9 @@ private ImmutableArray BindDeconstructionVariables(Separ /// /// Figures out how to assign from sourceType into receivingVariable and bundles the information (leaving holes for the actual source and receiver) into an AssignmentInfo. /// - private BoundDeconstructionAssignmentStep MakeAssignmentInfo(BoundExpression receivingVariable, TypeSymbol sourceType, BoundDeconstructValuePlaceholder inputPlaceholder, AssignmentExpressionSyntax node, DiagnosticBag diagnostics) + private BoundDeconstructionAssignmentStep MakeDeconstructionAssignmentStep( + BoundExpression receivingVariable, TypeSymbol sourceType, BoundDeconstructValuePlaceholder inputPlaceholder, + AssignmentExpressionSyntax node, DiagnosticBag diagnostics) { var outputPlaceholder = new BoundDeconstructValuePlaceholder(receivingVariable.Syntax, receivingVariable.Type) { WasCompilerGenerated = true }; @@ -1996,55 +2003,69 @@ static private void FlattenDeconstructVariables(ImmutableArray - /// Find the Deconstruct method for the expression on the right, that will fit the assignable bound expressions on the left. - /// Returns true if the Deconstruct method is found. - /// If so, it outputs the method. + /// Find the Deconstruct method for the expression on the right, that will fit the number of assignable variables on the left. + /// Returns an invocation expression if the Deconstruct method is found. + /// If so, it outputs placeholders that were coerced to the output types of the resolved Deconstruct method. + /// The overload resolution is similar to writing `receiver.Deconstruct(out var x1, out var x2, ...)`. /// - private static MethodSymbol FindDeconstruct(int numCheckedVariables, BoundExpression boundRHS, SyntaxNode node, DiagnosticBag diagnostics) + private BoundExpression MakeDeconstructInvocationExpression( + int numCheckedVariables, BoundExpression receiver, AssignmentExpressionSyntax assignmentSyntax, + DiagnosticBag diagnostics, out ImmutableArray outPlaceholders) { - // find symbol for Deconstruct member - ImmutableArray candidates = boundRHS.Type.GetMembers("Deconstruct"); - switch (candidates.Length) + var receiverSyntax = receiver.Syntax; + + if (receiver.Type.IsDynamic()) { - case 0: - Error(diagnostics, ErrorCode.ERR_MissingDeconstruct, boundRHS.Syntax, boundRHS.Type); - return null; - case 1: - break; - default: - Error(diagnostics, ErrorCode.ERR_AmbiguousDeconstruct, boundRHS.Syntax, boundRHS.Type); - return null; + Error(diagnostics, ErrorCode.ERR_CannotDeconstructDynamic, receiverSyntax); + outPlaceholders = default(ImmutableArray); + + return BadExpression(receiverSyntax, receiver); } - Symbol deconstructMember = candidates[0]; + var analyzedArguments = AnalyzedArguments.GetInstance(); + var outVars = ArrayBuilder.GetInstance(numCheckedVariables); - // check that the deconstruct fits - if (deconstructMember.Kind != SymbolKind.Method) + try { - Error(diagnostics, ErrorCode.ERR_MissingDeconstruct, boundRHS.Syntax, boundRHS.Type); - return null; - } + for (int i = 0; i < numCheckedVariables; i++) + { + var variable = new OutDeconstructVarPendingInference(assignmentSyntax); + analyzedArguments.Arguments.Add(variable); + analyzedArguments.RefKinds.Add(RefKind.Out); + outVars.Add(variable); + } - MethodSymbol deconstructMethod = (MethodSymbol)deconstructMember; - if (deconstructMethod.MethodKind != MethodKind.Ordinary) - { - Error(diagnostics, ErrorCode.ERR_MissingDeconstruct, boundRHS.Syntax, boundRHS.Type); - return null; - } + string methodName = "Deconstruct"; + var boundExpression = BindInstanceMemberAccess( + receiverSyntax, receiverSyntax, receiver, methodName, rightArity: 0, + typeArgumentsSyntax: default(SeparatedSyntaxList), typeArguments: default(ImmutableArray), + invoked: true, diagnostics: diagnostics); - if (deconstructMethod.ParameterCount != numCheckedVariables) - { - Error(diagnostics, ErrorCode.ERR_DeconstructWrongParams, boundRHS.Syntax, deconstructMethod, numCheckedVariables); - return null; - } + boundExpression = CheckValue(boundExpression, BindValueKind.RValueOrMethodGroup, diagnostics); + boundExpression.WasCompilerGenerated = true; + + BoundExpression result = BindInvocationExpression( + receiverSyntax, receiverSyntax, methodName, boundExpression, analyzedArguments, diagnostics, queryClause: null, + allowUnexpandedForm: true); - if (deconstructMethod.Parameters.Any(p => p.RefKind != RefKind.Out)) + result.WasCompilerGenerated = true; + + if (result.HasAnyErrors) + { + outPlaceholders = default(ImmutableArray); + return BadExpression(assignmentSyntax, result); + } + + outPlaceholders = outVars.SelectAsArray(v => v.Placeholder); + + return result; + } + finally { - Error(diagnostics, ErrorCode.ERR_DeconstructRequiresOutParams, boundRHS.Syntax, deconstructMethod); - return null; + analyzedArguments.Free(); + outVars.Free(); } - return deconstructMethod; } private BoundAssignmentOperator BindAssignment(AssignmentExpressionSyntax node, BoundExpression op1, BoundExpression op2, DiagnosticBag diagnostics) @@ -2196,6 +2217,10 @@ private BoundExpression CheckValue(BoundExpression expr, BindValueKind valueKind case BoundKind.PropertyGroup: expr = BindIndexedPropertyAccess((BoundPropertyGroup)expr, mustHaveAllOptionalParameters: false, diagnostics: diagnostics); break; + + case BoundKind.OutDeconstructVarPendingInference: + Debug.Assert(valueKind == BindValueKind.RefOrOut); + return expr; } bool hasResolutionErrors = false; diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs index 18179989c79af..0c6d2192ce309 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs @@ -6,7 +6,6 @@ using System.Linq; using Microsoft.CodeAnalysis.CSharp.Symbols; using Roslyn.Utilities; -using System; namespace Microsoft.CodeAnalysis.CSharp { @@ -1230,7 +1229,18 @@ private static TypeSymbol GetParameterType(int argIndex, MemberAnalysisResult re var type2 = GetParameterType(i, m2.Result, m2.LeastOverriddenMember.GetParameters(), out refKind2); bool okToDowngradeToNeither; - var r = BetterConversionFromExpression(arguments[i], + BetterResult r; + + if (argumentKind == BoundKind.OutDeconstructVarPendingInference) + { + // If argument is an out variable that needs type inference, + // neither candidate is better in this argument. + r = BetterResult.Neither; + okToDowngradeToNeither = false; + } + else + { + r = BetterConversionFromExpression(arguments[i], type1, m1.Result.ConversionForArg(i), refKind1, @@ -1240,6 +1250,7 @@ private static TypeSymbol GetParameterType(int argIndex, MemberAnalysisResult re considerRefKinds, ref useSiteDiagnostics, out okToDowngradeToNeither); + } if (r == BetterResult.Neither) { @@ -2906,6 +2917,14 @@ private RefKind GetEffectiveParameterRefKind(ParameterSymbol parameter, RefKind return Conversion.ImplicitDynamic; } + if (argument.Kind == BoundKind.OutDeconstructVarPendingInference) + { + Debug.Assert(argRefKind != RefKind.None); + + // Any parameter type is good, we'll use it for the var local. + return Conversion.Identity; + } + if (argRefKind == RefKind.None) { var conversion = Conversions.ClassifyImplicitConversionFromExpression(argument, parameterType, ref useSiteDiagnostics); diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolutionResult.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolutionResult.cs index 8687ffd0a57ef..5068ec18fea53 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolutionResult.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolutionResult.cs @@ -924,7 +924,7 @@ private static bool HadLambdaConversionError(DiagnosticBag diagnostics, Analyzed // If the expression is untyped because it is a lambda, anonymous method, method group or null // then we never want to report the error "you need a ref on that thing". Rather, we want to // say that you can't convert "null" to "ref int". - if (!argument.HasExpressionType()) + if (!argument.HasExpressionType() && argument.Kind != BoundKind.OutDeconstructVarPendingInference) { // If the problem is that a lambda isn't convertible to the given type, also report why. // The argument and parameter type might match, but may not have same in/out modifiers @@ -971,6 +971,8 @@ private static bool HadLambdaConversionError(DiagnosticBag diagnostics, Analyzed } else { + Debug.Assert(argument.Kind != BoundKind.OutDeconstructVarPendingInference); + TypeSymbol argType = argument.Display as TypeSymbol; Debug.Assert((object)argType != null); diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml index 677404f63ca20..a215dfdf9e6f3 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml +++ b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml @@ -403,7 +403,7 @@ - + @@ -1501,4 +1501,9 @@ + + + + + diff --git a/src/Compilers/CSharp/Portable/BoundTree/Expression.cs b/src/Compilers/CSharp/Portable/BoundTree/Expression.cs index 19fc6c1aa4211..2fa132d369d46 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/Expression.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/Expression.cs @@ -197,7 +197,7 @@ private static IArgument DeriveArgument(int parameterIndex, int argumentIndex, I return new Argument(ArgumentKind.Named, parameter, argument); }); } - + private static IOperation CreateParamArray(IParameterSymbol parameter, ImmutableArray boundArguments, int firstArgumentElementIndex, SyntaxNode invocationSyntax) { if (parameter.Type.TypeKind == TypeKind.Array) @@ -515,7 +515,7 @@ public override void Accept(OperationVisitor visitor) } } - internal partial class BoundTupleExpression + internal partial class BoundTupleExpression { protected override OperationKind ExpressionKind => OperationKind.None; @@ -1322,7 +1322,7 @@ public override void Accept(OperationVisitor visitor) internal partial class BoundImplicitReceiver : IInstanceReferenceExpression { InstanceReferenceKind IInstanceReferenceExpression.InstanceReferenceKind => InstanceReferenceKind.Implicit; - + protected override OperationKind ExpressionKind => OperationKind.InstanceReferenceExpression; public override void Accept(OperationVisitor visitor) @@ -1951,7 +1951,7 @@ public override void Accept(OperationVisitor visitor) return visitor.VisitNoneOperation(this, argument); } } - + internal partial class BoundDynamicCollectionElementInitializer { protected override OperationKind ExpressionKind => OperationKind.None; @@ -2826,6 +2826,24 @@ internal static BinaryOperationKind DeriveBinaryOperationKind(BinaryOperatorKind } } + /// + /// Providing implementation as OperationKind.None. This implementation is sufficient because the node doesn't survive initial binding. + /// + internal partial class OutDeconstructVarPendingInference + { + public override void Accept(OperationVisitor visitor) + { + visitor.VisitNoneOperation(this); + } + + public override TResult Accept(OperationVisitor visitor, TArgument argument) + { + return visitor.VisitNoneOperation(this, argument); + } + + protected override OperationKind ExpressionKind => OperationKind.None; + } + partial class BoundIsPatternExpression { public override void Accept(OperationVisitor visitor) diff --git a/src/Compilers/CSharp/Portable/BoundTree/Formatting.cs b/src/Compilers/CSharp/Portable/BoundTree/Formatting.cs index a51da0578be39..689eb8c06e11f 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/Formatting.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/Formatting.cs @@ -75,4 +75,15 @@ public override object Display get { throw ExceptionUtilities.Unreachable; } } } + + internal partial class OutDeconstructVarPendingInference + { + public override object Display + { + get + { + return MessageID.IDS_FeatureTuples.Localize(); + } + } + } } diff --git a/src/Compilers/CSharp/Portable/BoundTree/OutDeconstructVarPendingInference.cs b/src/Compilers/CSharp/Portable/BoundTree/OutDeconstructVarPendingInference.cs new file mode 100644 index 0000000000000..e9272b42964fb --- /dev/null +++ b/src/Compilers/CSharp/Portable/BoundTree/OutDeconstructVarPendingInference.cs @@ -0,0 +1,23 @@ +// 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 Microsoft.CodeAnalysis.CSharp.Symbols; + +namespace Microsoft.CodeAnalysis.CSharp +{ + internal partial class OutDeconstructVarPendingInference + { + public BoundDeconstructValuePlaceholder Placeholder; + + public BoundDeconstructValuePlaceholder SetInferredType(TypeSymbol type, bool success) + { + Placeholder = new BoundDeconstructValuePlaceholder(this.Syntax, type, hasErrors: this.HasErrors || !success); + return Placeholder; + } + + public BoundDeconstructValuePlaceholder FailInference(Binder binder) + { + return SetInferredType(binder.CreateErrorType("var"), success: false); + } + } +} \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj b/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj index e12dba4e58b7e..22a43de275fd0 100644 --- a/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj +++ b/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj @@ -200,6 +200,7 @@ + diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index 49c5e930aca20..d26a1ca4c015a 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -2320,6 +2320,15 @@ internal class CSharpResources { } } + /// + /// Looks up a localized string similar to Cannot deconstruct dynamic objects.. + /// + internal static string ERR_CannotDeconstructDynamic { + get { + return ResourceManager.GetString("ERR_CannotDeconstructDynamic", resourceCulture); + } + } + /// /// Looks up a localized string similar to Cannot pass null for friend assembly name. /// diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index cce4a2d44fe35..9a2d4d32fb126 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -4902,4 +4902,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Cannot deconstruct a tuple of '{0}' elements into '{1}' variables. + + Cannot deconstruct dynamic objects. + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index cd9f590566a3e..bb24d9fc12c17 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1400,5 +1400,6 @@ internal enum ErrorCode ERR_DeconstructWrongParams = 8209, ERR_DeconstructRequiresExpression = 8210, ERR_DeconstructWrongCardinality = 8211, + ERR_CannotDeconstructDynamic = 8212, } } diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_DeconstructionAssignmentOperator.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_DeconstructionAssignmentOperator.cs index 94e3dc6ccc484..e75ad18d58c9b 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_DeconstructionAssignmentOperator.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_DeconstructionAssignmentOperator.cs @@ -28,7 +28,7 @@ public override BoundNode VisitDeconstructionAssignmentOperator(BoundDeconstruct foreach (var deconstruction in node.DeconstructSteps) { - if (deconstruction.DeconstructMemberOpt == null) + if (deconstruction.DeconstructInvocationOpt == null) { // tuple case AccessTupleFields(node, deconstruction, temps, stores, placeholders); @@ -122,12 +122,12 @@ private void AccessTupleFields(BoundDeconstructionAssignmentOperator node, Bound /// private void CallDeconstruct(BoundDeconstructionAssignmentOperator node, BoundDeconstructionDeconstructStep deconstruction, ArrayBuilder temps, ArrayBuilder stores, ArrayBuilder placeholders) { - Debug.Assert((object)deconstruction.DeconstructMemberOpt != null); + Debug.Assert((object)deconstruction.DeconstructInvocationOpt != null); CSharpSyntaxNode syntax = node.Syntax; // prepare out parameters for Deconstruct - var deconstructParameters = deconstruction.DeconstructMemberOpt.Parameters; + var deconstructParameters = deconstruction.OutputPlaceholders; var outParametersBuilder = ArrayBuilder.GetInstance(deconstructParameters.Length); for (var i = 0; i < deconstructParameters.Length; i++) @@ -151,9 +151,8 @@ private void CallDeconstruct(BoundDeconstructionAssignmentOperator node, BoundDe var outParameters = outParametersBuilder.ToImmutableAndFree(); - // invoke Deconstruct - var invokeDeconstruct = MakeCall(syntax, PlaceholderReplacement(deconstruction.TargetPlaceholder), deconstruction.DeconstructMemberOpt, outParameters, deconstruction.DeconstructMemberOpt.ReturnType); - stores.Add(invokeDeconstruct); + // invoke Deconstruct with placeholders replaced by locals + stores.Add((BoundExpression)Visit(deconstruction.DeconstructInvocationOpt)); } } } diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs index 460bfb47f52a1..4b592565835f6 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.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.Linq; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Test.Utilities; @@ -117,9 +118,9 @@ static void Main() "; var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics( - // (8,18): error CS8206: No Deconstruct instance or extension method was found for type 'C'. + // (8,18): error CS1061: 'C' does not contain a definition for 'Deconstruct' and no extension method 'Deconstruct' accepting a first argument of type 'C' could be found (are you missing a using directive or an assembly reference?) // (x, y) = new C(); - Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C()").WithArguments("C").WithLocation(8, 18) + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "new C()").WithArguments("C", "Deconstruct").WithLocation(8, 18) ); } @@ -149,11 +150,7 @@ public void Deconstruct(out int a) }"; var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); - comp.VerifyDiagnostics( - // (8,18): error CS8207: More than one Deconstruct instance or extension method was found for type 'C'. - // (x, y) = new C(); - Diagnostic(ErrorCode.ERR_AmbiguousDeconstruct, "new C()").WithArguments("C").WithLocation(8, 18) - ); + comp.VerifyDiagnostics(); } [Fact] @@ -168,16 +165,40 @@ static void Main() string y; (x, y) = new C(); } - public void Deconstruct(out int a) + public void Deconstruct(out int a) // too few arguments { a = 1; } }"; var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics( - // (8,18): error CS8209: The Deconstruct method for type 'C.Deconstruct(out int)' doesn't have the number of parameters (2) needed for this deconstruction. + // (8,18): error CS1501: No overload for method 'Deconstruct' takes 2 arguments // (x, y) = new C(); - Diagnostic(ErrorCode.ERR_DeconstructWrongParams, "new C()").WithArguments("C.Deconstruct(out int)", "2").WithLocation(8, 18) + Diagnostic(ErrorCode.ERR_BadArgCount, "new C()").WithArguments("Deconstruct", "2").WithLocation(8, 18) + ); + } + + [Fact] + public void DeconstructWrongParams2() + { + string source = @" +class C +{ + static void Main() + { + long x, y; + (x, y) = new C(); + } + public void Deconstruct(out int a, out int b, out int c) // too many arguments + { + a = b = c = 1; + } +}"; + var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics( + // (7,18): error CS7036: There is no argument given that corresponds to the required formal parameter 'c' of 'C.Deconstruct(out int, out int, out int)' + // (x, y) = new C(); + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "new C()").WithArguments("c", "C.Deconstruct(out int, out int, out int)").WithLocation(7, 18) ); } @@ -204,9 +225,9 @@ static void Main() // (8,17): error CS1061: 'string' does not contain a definition for 'g' and no extension method 'g' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) // (x.f, y.g) = new C(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "g").WithArguments("string", "g").WithLocation(8, 17), - // (8,22): error CS8209: The Deconstruct method for type 'C.Deconstruct()' doesn't have the number of parameters (2) needed for this deconstruction. + // (8,22): error CS1501: No overload for method 'Deconstruct' takes 2 arguments // (x.f, y.g) = new C(); - Diagnostic(ErrorCode.ERR_DeconstructWrongParams, "new C()").WithArguments("C.Deconstruct()", "2").WithLocation(8, 22) + Diagnostic(ErrorCode.ERR_BadArgCount, "new C()").WithArguments("Deconstruct", "2").WithLocation(8, 22) ); } @@ -227,9 +248,9 @@ static void Main() "; var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics( - // (8,18): error CS8208: The Deconstruct method for type 'C.Deconstruct(out int, int)' must have only out parameters. + // (8,9): error CS1615: Argument 2 may not be passed with the 'out' keyword // (x, y) = new C(); - Diagnostic(ErrorCode.ERR_DeconstructRequiresOutParams, "new C()").WithArguments("C.Deconstruct(out int, int)").WithLocation(8, 18) + Diagnostic(ErrorCode.ERR_BadArgExtraRef, "(x, y) = new C()").WithArguments("2", "out").WithLocation(8, 9) ); } @@ -250,9 +271,9 @@ static void Main() "; var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics( - // (8,18): error CS8208: The Deconstruct method for type 'C.Deconstruct(ref int, out int)' must have only out parameters. + // (8,9): error CS1620: Argument 1 must be passed with the 'ref' keyword // (x, y) = new C(); - Diagnostic(ErrorCode.ERR_DeconstructRequiresOutParams, "new C()").WithArguments("C.Deconstruct(ref int, out int)").WithLocation(8, 18) + Diagnostic(ErrorCode.ERR_BadArgRef, "(x, y) = new C()").WithArguments("1", "ref").WithLocation(8, 9) ); } @@ -679,8 +700,7 @@ void Deconstruct(out int x, out int y) "; var comp = CompileAndVerify(source, expectedOutput: expected, parseOptions: TestOptions.Regular.WithTuplesFeature().WithRefsFeature()); - comp.VerifyDiagnostics( - ); + comp.VerifyDiagnostics(); } [Fact(Skip = "PROTOTYPE(tuples)")] @@ -784,9 +804,9 @@ static void Main() var comp = CreateCompilationWithMscorlib(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics( - // (7,18): error CS8206: No Deconstruct instance or extension method was found for type 'int'. + // (7,18): error CS1061: 'int' does not contain a definition for 'Deconstruct' and no extension method 'Deconstruct' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?) // (x, x) = x; - Diagnostic(ErrorCode.ERR_MissingDeconstruct, "x").WithArguments("int").WithLocation(7, 18), + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "x").WithArguments("int", "Deconstruct").WithLocation(7, 18), // (7,18): error CS0165: Use of unassigned local variable 'x' // (x, x) = x; Diagnostic(ErrorCode.ERR_UseDefViolation, "x").WithArguments("x").WithLocation(7, 18) @@ -892,9 +912,9 @@ static void Main() var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature().WithRefsFeature()); comp.VerifyDiagnostics( - // (7,18): error CS8206: No Deconstruct instance or extension method was found for type 'void'. + // (7,18): error CS1061: 'void' does not contain a definition for 'Deconstruct' and no extension method 'Deconstruct' accepting a first argument of type 'void' could be found (are you missing a using directive or an assembly reference?) // (x, x) = M(); - Diagnostic(ErrorCode.ERR_MissingDeconstruct, "M()").WithArguments("void").WithLocation(7, 18) + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "M()").WithArguments("void", "Deconstruct").WithLocation(7, 18) ); } @@ -919,8 +939,8 @@ static void Main() comp.VerifyDiagnostics(); } - [Fact(Skip = "PROTOTYPE(tuples)")] - public void AssigningTuple2() + [Fact] + public void AssigningTupleWithConversion() { string source = @" class C @@ -940,7 +960,6 @@ static void Main() } } "; - // Should not give this error: (9,18): error CS0029: Cannot implicitly convert type '(int, string)' to '(long, string)' var comp = CompileAndVerify(source, expectedOutput: "1 hello", additionalRefs: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics(); } @@ -1325,6 +1344,237 @@ static void Main() comp.VerifyDiagnostics(); } + [Fact] + public void DeconstructUsingBaseDeconstructMethod() + { + string source = @" +class Base +{ + public void Deconstruct(out int a, out int b) { a = 1; b = 2; } +} +class C : Base +{ + static void Main() + { + int x, y; + (x, y) = new C(); + + System.Console.WriteLine(x + "" "" + y); + } + + public void Deconstruct(out int c) { c = 42; } +} +"; + + var comp = CompileAndVerify(source, expectedOutput: "1 2", additionalRefs: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular.WithTuplesFeature().WithRefsFeature()); + comp.VerifyDiagnostics(); + } + + [Fact] + public void AssignUsingAmbiguousDeconstruction() + { + string source = @" +class Base +{ + public void Deconstruct(out int a, out int b) { a = 1; b = 2; } + public void Deconstruct(out long a, out long b) { a = 1; b = 2; } +} +class C : Base +{ + static void Main() + { + int x, y; + (x, y) = new C(); + + System.Console.WriteLine(x + "" "" + y); + } +} +"; + + var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics( + // (12,18): error CS0121: The call is ambiguous between the following methods or properties: 'Base.Deconstruct(out int, out int)' and 'Base.Deconstruct(out long, out long)' + // (x, y) = new C(); + Diagnostic(ErrorCode.ERR_AmbigCall, "new C()").WithArguments("Base.Deconstruct(out int, out int)", "Base.Deconstruct(out long, out long)").WithLocation(12, 18) + ); + } + + [Fact] + public void DeconstructUsingExtensionMethod() + { + string source = @" +using System; +class C +{ + static void Main() + { + int x; + string y, z; + (x, (y, z)) = Tuple.Create(1, Tuple.Create(""hello"", ""world"")); + + System.Console.WriteLine(x + "" "" + y + "" "" + z); + } +} +"; + + var comp = CompileAndVerify(source, expectedOutput: "1 hello world", additionalRefs: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular.WithTuplesFeature().WithRefsFeature()); + comp.VerifyDiagnostics(); + } + + [Fact] + public void NestedDeconstructUsingExtensionMethod() + { + string source = @" +using System; +class C +{ + static void Main() + { + int x; + string y, z; + (x, (y, z)) = Tuple.Create(1, Tuple.Create(""hello"", ""world"")); + + System.Console.WriteLine(x + "" "" + y + "" "" + z); + } +} +"; + + var comp = CompileAndVerify(source, expectedOutput: "1 hello world", additionalRefs: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular.WithTuplesFeature().WithRefsFeature()); + comp.VerifyDiagnostics(); + } + + [Fact] + public void OverrideDeconstruct() + { + string source = @" +class Base +{ + public virtual void Deconstruct(out int a, out string b) { a = 1; b = ""hello""; } +} +class C : Base +{ + static void Main() + { + int x; + string y; + (x, y) = new C(); + } + public override void Deconstruct(out int a, out string b) { a = 1; b = ""hello""; System.Console.WriteLine(""override""); } +} +"; + + var comp = CompileAndVerify(source, expectedOutput: "override", additionalRefs: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular.WithTuplesFeature().WithRefsFeature()); + comp.VerifyDiagnostics(); + } + + [Fact] + public void DeconstructRefTuple() + { + string template = @" +using System; +class C +{ + static void Main() + { + int VARIABLES; // int x1, x2, ... + (VARIABLES) = (TUPLE).ToTuple(); // (x1, x2, ...) = (1, 2, ...).ToTuple(); + + System.Console.WriteLine(OUTPUT); + } +} +"; + for (int i = 2; i <= 21; i++) + { + var tuple = String.Join(", ", Enumerable.Range(1, i).Select(n => n.ToString())); + var variables = String.Join(", ", Enumerable.Range(1, i).Select(n => $"x{n}")); + var output = String.Join(@" + "" "" + ", Enumerable.Range(1, i).Select(n => $"x{n}")); + var expected = String.Join(" ", Enumerable.Range(1, i).Select(n => n)); + + var source = template.Replace("VARIABLES", variables).Replace("TUPLE", tuple).Replace("OUTPUT", output); + var comp = CompileAndVerify(source, expectedOutput: expected, additionalRefs: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular.WithTuplesFeature().WithRefsFeature()); + comp.VerifyDiagnostics(); + } + } + + [Fact] + public void CannotDeconstructRefTuple22() + { + string template = @" +using System; +class C +{ + static void Main() + { + int VARIABLES; // int x1, x2, ... + (VARIABLES) = CreateLongRef(1, 2, 3, 4, 5, 6, 7, CreateLongRef(8, 9, 10, 11, 12, 13, 14, Tuple.Create(15, 16, 17, 18, 19, 20, 21, 22))); + } + + public static Tuple CreateLongRef(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, TRest rest) => + new Tuple(item1, item2, item3, item4, item5, item6, item7, rest); +} +"; + var tuple = String.Join(", ", Enumerable.Range(1, 22).Select(n => n.ToString())); + var variables = String.Join(", ", Enumerable.Range(1, 22).Select(n => $"x{n}")); + + var source = template.Replace("VARIABLES", variables).Replace("TUPLE", tuple); + + var comp = CreateCompilationWithMscorlib(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics( + // (8,113): error CS1501: No overload for method 'Deconstruct' takes 22 arguments + // (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22) = CreateLongRef(1, 2, 3, 4, 5, 6, 7, CreateLongRef(8, 9, 10, 11, 12, 13, 14, Tuple.Create(15, 16, 17, 18, 19, 20, 21, 22))); + Diagnostic(ErrorCode.ERR_BadArgCount, "CreateLongRef(1, 2, 3, 4, 5, 6, 7, CreateLongRef(8, 9, 10, 11, 12, 13, 14, Tuple.Create(15, 16, 17, 18, 19, 20, 21, 22)))").WithArguments("Deconstruct", "22").WithLocation(8, 113) + ); + } + + [Fact] + public void DeconstructUsingDynamicMethod() + { + string source = @" +class C +{ + static void Main() + { + int x; + string y; + + dynamic c = new C(); + (x, y) = c; + } + public void Deconstruct(out int a, out string b) { a = 1; b = ""hello""; } +} +"; + var comp = CreateCompilationWithMscorlib(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics( + // (10,18): error CS8212: Cannot deconstruct dynamic objects. + // (x, y) = c; + Diagnostic(ErrorCode.ERR_CannotDeconstructDynamic, "c").WithLocation(10, 18) + ); + } + + [Fact] + public void StaticDeconstruct() + { + string source = @" +class C +{ + static void Main() + { + int x; + string y; + + (x, y) = new C(); + } + public static void Deconstruct(out int a, out string b) { a = 1; b = ""hello""; } +} +"; + var comp = CreateCompilationWithMscorlib(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics( + // (9,18): error CS0176: Member 'C.Deconstruct(out int, out string)' cannot be accessed with an instance reference; qualify it with a type name instead + // (x, y) = new C(); + Diagnostic(ErrorCode.ERR_ObjectProhibited, "new C()").WithArguments("C.Deconstruct(out int, out string)").WithLocation(9, 18) + ); + } + [Fact] public void AssignmentTypeIsVoid() { @@ -1672,7 +1922,7 @@ public void Deconstruct(out int a, out string b) } } "; - // PROTOTYPE(tuples) we expect "2 hello" instead + // PROTOTYPE(tuples) we expect "2 hello" instead, which means the evaluation order is wrong var comp = CompileAndVerify(source, expectedOutput: "1 hello", parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics(); } From cc63d938d6386bf10e4b40656a4c6deef998e366 Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Thu, 9 Jun 2016 10:07:01 -0700 Subject: [PATCH 03/11] PR feedback (1) --- .../Portable/Binder/Binder_Statements.cs | 22 +++++++-- .../CSharp/Portable/BoundTree/Expression.cs | 10 ++-- .../OutDeconstructVarPendingInference.cs | 3 ++ .../Portable/CSharpResources.Designer.cs | 27 ----------- .../CSharp/Portable/CSharpResources.resx | 9 ---- .../CSharp/Portable/Errors/ErrorCode.cs | 3 -- .../Emit/CodeGen/CodeGenDeconstructTests.cs | 48 +++++++++++++++++++ 7 files changed, 75 insertions(+), 47 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs index 328af374595df..9e73f981b15ea 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs @@ -1968,7 +1968,7 @@ private ImmutableArray BindDeconstructionVariables(Separ /// Figures out how to assign from sourceType into receivingVariable and bundles the information (leaving holes for the actual source and receiver) into an AssignmentInfo. /// private BoundDeconstructionAssignmentStep MakeDeconstructionAssignmentStep( - BoundExpression receivingVariable, TypeSymbol sourceType, BoundDeconstructValuePlaceholder inputPlaceholder, + BoundExpression receivingVariable, TypeSymbol sourceType, BoundDeconstructValuePlaceholder inputPlaceholder, AssignmentExpressionSyntax node, DiagnosticBag diagnostics) { var outputPlaceholder = new BoundDeconstructValuePlaceholder(receivingVariable.Syntax, receivingVariable.Type) { WasCompilerGenerated = true }; @@ -2036,16 +2036,28 @@ static private void FlattenDeconstructVariables(ImmutableArray), typeArguments: default(ImmutableArray), invoked: true, diagnostics: diagnostics); - boundExpression = CheckValue(boundExpression, BindValueKind.RValueOrMethodGroup, diagnostics); - boundExpression.WasCompilerGenerated = true; + memberAccess = CheckValue(memberAccess, BindValueKind.RValueOrMethodGroup, diagnostics); + memberAccess.WasCompilerGenerated = true; + if (memberAccess.Kind != BoundKind.MethodGroup) + { + Error(diagnostics, ErrorCode.ERR_MissingDeconstruct, receiverSyntax, receiver.Type); + outPlaceholders = default(ImmutableArray); + + return BadExpression(receiverSyntax, receiver); + } + + // After the overload resolution completes, the last step is to coerce the arguments with inferred types. + // That step returns placeholder (of correct type) instead of the outVar nodes that were passed in as arguments. + // So the generated invocation expression will contain placeholders instead of those outVar nodes. + // Those placeholders are also recorded in the outVar for easy access below. BoundExpression result = BindInvocationExpression( - receiverSyntax, receiverSyntax, methodName, boundExpression, analyzedArguments, diagnostics, queryClause: null, + receiverSyntax, receiverSyntax, methodName, memberAccess, analyzedArguments, diagnostics, queryClause: null, allowUnexpandedForm: true); result.WasCompilerGenerated = true; diff --git a/src/Compilers/CSharp/Portable/BoundTree/Expression.cs b/src/Compilers/CSharp/Portable/BoundTree/Expression.cs index 2fa132d369d46..d6f4059862f76 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/Expression.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/Expression.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Runtime.CompilerServices; using Microsoft.CodeAnalysis.Semantics; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp { @@ -2833,15 +2834,18 @@ internal partial class OutDeconstructVarPendingInference { public override void Accept(OperationVisitor visitor) { - visitor.VisitNoneOperation(this); + throw ExceptionUtilities.Unreachable; } public override TResult Accept(OperationVisitor visitor, TArgument argument) { - return visitor.VisitNoneOperation(this, argument); + throw ExceptionUtilities.Unreachable; } - protected override OperationKind ExpressionKind => OperationKind.None; + protected override OperationKind ExpressionKind + { + get { throw ExceptionUtilities.Unreachable; } + } } partial class BoundIsPatternExpression diff --git a/src/Compilers/CSharp/Portable/BoundTree/OutDeconstructVarPendingInference.cs b/src/Compilers/CSharp/Portable/BoundTree/OutDeconstructVarPendingInference.cs index e9272b42964fb..12290c92e65f2 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/OutDeconstructVarPendingInference.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/OutDeconstructVarPendingInference.cs @@ -2,6 +2,7 @@ using System; using Microsoft.CodeAnalysis.CSharp.Symbols; +using System.Diagnostics; namespace Microsoft.CodeAnalysis.CSharp { @@ -11,6 +12,8 @@ internal partial class OutDeconstructVarPendingInference public BoundDeconstructValuePlaceholder SetInferredType(TypeSymbol type, bool success) { + Debug.Assert((object)Placeholder == null); + Placeholder = new BoundDeconstructValuePlaceholder(this.Syntax, type, hasErrors: this.HasErrors || !success); return Placeholder; } diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index d26a1ca4c015a..15f8a2243141b 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -394,15 +394,6 @@ internal class CSharpResources { } } - /// - /// Looks up a localized string similar to More than one Deconstruct instance or extension method was found for type '{0}'.. - /// - internal static string ERR_AmbiguousDeconstruct { - get { - return ResourceManager.GetString("ERR_AmbiguousDeconstruct", resourceCulture); - } - } - /// /// Looks up a localized string similar to Cannot use ref or out parameter '{0}' inside an anonymous method, lambda expression, or query expression. /// @@ -3112,15 +3103,6 @@ internal class CSharpResources { } } - /// - /// Looks up a localized string similar to The Deconstruct method for type '{0}' must have only out parameters.. - /// - internal static string ERR_DeconstructRequiresOutParams { - get { - return ResourceManager.GetString("ERR_DeconstructRequiresOutParams", resourceCulture); - } - } - /// /// Looks up a localized string similar to Cannot deconstruct a tuple of '{0}' elements into '{1}' variables.. /// @@ -3130,15 +3112,6 @@ internal class CSharpResources { } } - /// - /// Looks up a localized string similar to The Deconstruct method for type '{0}' doesn't have the number of parameters ({1}) needed for this deconstruction.. - /// - internal static string ERR_DeconstructWrongParams { - get { - return ResourceManager.GetString("ERR_DeconstructWrongParams", resourceCulture); - } - } - /// /// Looks up a localized string similar to Cannot specify the DefaultMember attribute on a type containing an indexer. /// diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 9a2d4d32fb126..2d423ba9e5cc3 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -4875,15 +4875,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ tuples - - More than one Deconstruct instance or extension method was found for type '{0}'. - - - The Deconstruct method for type '{0}' must have only out parameters. - - - The Deconstruct method for type '{0}' doesn't have the number of parameters ({1}) needed for this deconstruction. - No Deconstruct instance or extension method was found for type '{0}'. diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index bb24d9fc12c17..97eae9e0245da 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1395,9 +1395,6 @@ internal enum ErrorCode ERR_PredefinedTypeMemberNotFoundInAssembly = 8205, ERR_MissingDeconstruct = 8206, - ERR_AmbiguousDeconstruct = 8207, - ERR_DeconstructRequiresOutParams = 8208, - ERR_DeconstructWrongParams = 8209, ERR_DeconstructRequiresExpression = 8210, ERR_DeconstructWrongCardinality = 8211, ERR_CannotDeconstructDynamic = 8212, diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs index 4b592565835f6..15695a9469da3 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs @@ -1443,6 +1443,54 @@ static void Main() comp.VerifyDiagnostics(); } + [Fact] + public void DeconstructIsDynamicField() + { + string source = @" +class C +{ + static void Main() + { + int x, y; + (x, y) = new C(); + + } + public dynamic Deconstruct = null; +} +"; + + var comp = CreateCompilationWithMscorlib(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef, SystemCoreRef, CSharpRef }, parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics( + // (7,18): error CS8206: No Deconstruct instance or extension method was found for type 'C'. + // (x, y) = new C(); + Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C()").WithArguments("C").WithLocation(7, 18) + ); + } + + [Fact] + public void DeconstructIsField() + { + string source = @" +class C +{ + static void Main() + { + int x, y; + (x, y) = new C(); + + } + public object Deconstruct = null; +} +"; + + var comp = CreateCompilationWithMscorlib(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics( + // (7,18): error CS1955: Non-invocable member 'C.Deconstruct' cannot be used like a method. + // (x, y) = new C(); + Diagnostic(ErrorCode.ERR_NonInvocableMemberCalled, "new C()").WithArguments("C.Deconstruct").WithLocation(7, 18) + ); + } + [Fact] public void OverrideDeconstruct() { From 9b003a709fa4ba646c24e6ee9bc6872d1eaafa6e Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Fri, 10 Jun 2016 10:28:30 -0700 Subject: [PATCH 04/11] Adding suggested tests --- .../Portable/Binder/Binder_Statements.cs | 6 +- .../Emit/CodeGen/CodeGenDeconstructTests.cs | 290 ++++++++++++++++++ 2 files changed, 293 insertions(+), 3 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs index 9e73f981b15ea..421f0c5039d44 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs @@ -2055,9 +2055,9 @@ static private void FlattenDeconstructVariables(ImmutableArray Date: Fri, 10 Jun 2016 16:40:13 -0700 Subject: [PATCH 05/11] PR feedback (2) --- .../Portable/Binder/Binder_Statements.cs | 37 ++++- .../CSharp/Portable/BoundTree/Expression.cs | 3 +- .../OutDeconstructVarPendingInference.cs | 2 +- .../Portable/CSharpResources.Designer.cs | 2 +- .../CSharp/Portable/CSharpResources.resx | 2 +- ...writer_DeconstructionAssignmentOperator.cs | 2 +- .../Emit/CodeGen/CodeGenDeconstructTests.cs | 153 +++++++++++++----- 7 files changed, 147 insertions(+), 54 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs index 421f0c5039d44..144c26058b326 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs @@ -2024,6 +2024,7 @@ static private void FlattenDeconstructVariables(ImmutableArray.GetInstance(numCheckedVariables); + DiagnosticBag bag = null; try { @@ -2046,26 +2047,34 @@ static private void FlattenDeconstructVariables(ImmutableArray); - - return BadExpression(receiverSyntax, receiver); + return MissingDeconstruct(receiver, assignmentSyntax, numCheckedVariables, diagnostics, out outPlaceholders, receiver); } // After the overload resolution completes, the last step is to coerce the arguments with inferred types. // That step returns placeholder (of correct type) instead of the outVar nodes that were passed in as arguments. // So the generated invocation expression will contain placeholders instead of those outVar nodes. // Those placeholders are also recorded in the outVar for easy access below, by the `SetInferredType` call on the outVar nodes. + bag = DiagnosticBag.GetInstance(); BoundExpression result = BindMethodGroupInvocation( - receiverSyntax, receiverSyntax, methodName, (BoundMethodGroup)memberAccess, analyzedArguments, diagnostics, queryClause: null, + receiverSyntax, receiverSyntax, methodName, (BoundMethodGroup)memberAccess, analyzedArguments, bag, queryClause: null, allowUnexpandedForm: true); result.WasCompilerGenerated = true; - if (result.HasAnyErrors) + if (bag.HasAnyErrors()) + { + return MissingDeconstruct(receiver, assignmentSyntax, numCheckedVariables, diagnostics, out outPlaceholders, result); + } + else + { + diagnostics.AddRange(bag); + } + + var deconstructMethod = ((BoundCall)result).Method; + var parameters = deconstructMethod.IsExtensionMethod ? deconstructMethod.Parameters.Skip(1) : deconstructMethod.Parameters; + if (parameters.Any(p => p.RefKind != RefKind.Out && !p.IsThis)) { - outPlaceholders = default(ImmutableArray); - return BadExpression(assignmentSyntax, result); + return MissingDeconstruct(receiver, assignmentSyntax, numCheckedVariables, diagnostics, out outPlaceholders, result); } outPlaceholders = outVars.SelectAsArray(v => v.Placeholder); @@ -2076,10 +2085,22 @@ static private void FlattenDeconstructVariables(ImmutableArray outPlaceholders, BoundNode childNode) + { + Error(diagnostics, ErrorCode.ERR_MissingDeconstruct, receiver.Syntax, receiver.Type, numParameters); + outPlaceholders = default(ImmutableArray); + + return BadExpression(syntax, childNode); + } + private BoundAssignmentOperator BindAssignment(AssignmentExpressionSyntax node, BoundExpression op1, BoundExpression op2, DiagnosticBag diagnostics) { Debug.Assert(op1 != null); diff --git a/src/Compilers/CSharp/Portable/BoundTree/Expression.cs b/src/Compilers/CSharp/Portable/BoundTree/Expression.cs index d6f4059862f76..f3d60eb3cc562 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/Expression.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/Expression.cs @@ -2828,7 +2828,8 @@ internal static BinaryOperationKind DeriveBinaryOperationKind(BinaryOperatorKind } /// - /// Providing implementation as OperationKind.None. This implementation is sufficient because the node doesn't survive initial binding. + /// This node represents an 'out var' parameter to a Deconstruct method. + /// It is only used temporarily during initial binding. /// internal partial class OutDeconstructVarPendingInference { diff --git a/src/Compilers/CSharp/Portable/BoundTree/OutDeconstructVarPendingInference.cs b/src/Compilers/CSharp/Portable/BoundTree/OutDeconstructVarPendingInference.cs index 12290c92e65f2..f4804ebbc8c72 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/OutDeconstructVarPendingInference.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/OutDeconstructVarPendingInference.cs @@ -20,7 +20,7 @@ public BoundDeconstructValuePlaceholder SetInferredType(TypeSymbol type, bool su public BoundDeconstructValuePlaceholder FailInference(Binder binder) { - return SetInferredType(binder.CreateErrorType("var"), success: false); + return SetInferredType(binder.CreateErrorType(), success: false); } } } \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index 15f8a2243141b..bdd7cafaa8466 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -5903,7 +5903,7 @@ internal class CSharpResources { } /// - /// Looks up a localized string similar to No Deconstruct instance or extension method was found for type '{0}'.. + /// Looks up a localized string similar to No Deconstruct instance or extension method was found for type '{0}', with {1} out parameters.. /// internal static string ERR_MissingDeconstruct { get { diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 2d423ba9e5cc3..74bf5c3edab53 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -4876,7 +4876,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ tuples - No Deconstruct instance or extension method was found for type '{0}'. + No Deconstruct instance or extension method was found for type '{0}', with {1} out parameters. Deconstruct assignment requires an expression with a type on the right-hand-side. diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_DeconstructionAssignmentOperator.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_DeconstructionAssignmentOperator.cs index e75ad18d58c9b..246cd7494c33f 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_DeconstructionAssignmentOperator.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_DeconstructionAssignmentOperator.cs @@ -152,7 +152,7 @@ private void CallDeconstruct(BoundDeconstructionAssignmentOperator node, BoundDe var outParameters = outParametersBuilder.ToImmutableAndFree(); // invoke Deconstruct with placeholders replaced by locals - stores.Add((BoundExpression)Visit(deconstruction.DeconstructInvocationOpt)); + stores.Add(VisitExpression(deconstruction.DeconstructInvocationOpt)); } } } diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs index 1cdc3b7657a0b..807ba8f323698 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs @@ -118,9 +118,9 @@ static void Main() "; var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics( - // (8,18): error CS1061: 'C' does not contain a definition for 'Deconstruct' and no extension method 'Deconstruct' accepting a first argument of type 'C' could be found (are you missing a using directive or an assembly reference?) + // (8,18): error CS8206: No Deconstruct instance or extension method was found for type 'C', with 2 out parameters. // (x, y) = new C(); - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "new C()").WithArguments("C", "Deconstruct").WithLocation(8, 18) + Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C()").WithArguments("C", "2").WithLocation(8, 18) ); } @@ -172,9 +172,9 @@ static void Main() }"; var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics( - // (8,18): error CS1501: No overload for method 'Deconstruct' takes 2 arguments + // (8,18): error CS8206: No Deconstruct instance or extension method was found for type 'C', with 2 out parameters. // (x, y) = new C(); - Diagnostic(ErrorCode.ERR_BadArgCount, "new C()").WithArguments("Deconstruct", "2").WithLocation(8, 18) + Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C()").WithArguments("C", "2").WithLocation(8, 18) ); } @@ -196,9 +196,9 @@ static void Main() }"; var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics( - // (7,18): error CS7036: There is no argument given that corresponds to the required formal parameter 'c' of 'C.Deconstruct(out int, out int, out int)' + // (7,18): error CS8206: No Deconstruct instance or extension method was found for type 'C', with 2 out parameters. // (x, y) = new C(); - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "new C()").WithArguments("c", "C.Deconstruct(out int, out int, out int)").WithLocation(7, 18) + Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C()").WithArguments("C", "2").WithLocation(7, 18) ); } @@ -225,9 +225,9 @@ static void Main() // (8,17): error CS1061: 'string' does not contain a definition for 'g' and no extension method 'g' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) // (x.f, y.g) = new C(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "g").WithArguments("string", "g").WithLocation(8, 17), - // (8,22): error CS1501: No overload for method 'Deconstruct' takes 2 arguments + // (8,22): error CS8206: No Deconstruct instance or extension method was found for type 'C', with 2 out parameters. // (x.f, y.g) = new C(); - Diagnostic(ErrorCode.ERR_BadArgCount, "new C()").WithArguments("Deconstruct", "2").WithLocation(8, 22) + Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C()").WithArguments("C", "2").WithLocation(8, 22) ); } @@ -248,9 +248,9 @@ static void Main() "; var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics( - // (8,9): error CS1615: Argument 2 may not be passed with the 'out' keyword + // (8,18): error CS8206: No Deconstruct instance or extension method was found for type 'C', with 2 out parameters. // (x, y) = new C(); - Diagnostic(ErrorCode.ERR_BadArgExtraRef, "(x, y) = new C()").WithArguments("2", "out").WithLocation(8, 9) + Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C()").WithArguments("C", "2").WithLocation(8, 18) ); } @@ -271,9 +271,9 @@ static void Main() "; var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics( - // (8,9): error CS1620: Argument 1 must be passed with the 'ref' keyword + // (8,18): error CS8206: No Deconstruct instance or extension method was found for type 'C', with 2 out parameters. // (x, y) = new C(); - Diagnostic(ErrorCode.ERR_BadArgRef, "(x, y) = new C()").WithArguments("1", "ref").WithLocation(8, 9) + Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C()").WithArguments("C", "2").WithLocation(8, 18) ); } @@ -521,7 +521,7 @@ static void Main() System.Console.WriteLine(x + "" "" + y); } - public void Deconstruct(out int a, out string b, int c = 42) + public void Deconstruct(out int a, out string b, int c = 42) // not a Deconstruct operator { a = 1; b = ""hello""; @@ -529,8 +529,12 @@ public void Deconstruct(out int a, out string b, int c = 42) } "; - var comp = CompileAndVerify(source, expectedOutput: "1 hello", additionalRefs: new[] { SystemCoreRef, CSharpRef }, parseOptions: TestOptions.Regular.WithTuplesFeature()); - comp.VerifyDiagnostics(); + var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics( + // (9,18): error CS8206: No Deconstruct instance or extension method was found for type 'C', with 2 out parameters. + // (x, y) = new C(); + Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C()").WithArguments("C", "2").WithLocation(9, 18) + ); } [Fact] @@ -548,7 +552,7 @@ static void Main() System.Console.WriteLine(x + "" "" + y); } - public void Deconstruct(out int a, out string b, params int[] c) + public void Deconstruct(out int a, out string b, params int[] c) // not a Deconstruct operator { a = 1; b = ""hello""; @@ -556,7 +560,44 @@ public void Deconstruct(out int a, out string b, params int[] c) } "; - var comp = CompileAndVerify(source, expectedOutput: "1 hello", additionalRefs: new[] { SystemCoreRef, CSharpRef }, parseOptions: TestOptions.Regular.WithTuplesFeature()); + var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics( + // (9,18): error CS8206: No Deconstruct instance or extension method was found for type 'C', with 2 out parameters. + // (x, y) = new C(); + Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C()").WithArguments("C", "2").WithLocation(9, 18) + ); + } + + [Fact] + public void DeconstructMethodHasParams2() + { + string source = @" +class C +{ + static void Main() + { + long x; + string y; + + (x, y) = new C(); + System.Console.WriteLine(x + "" "" + y); + } + + public void Deconstruct(out int a, out string b, params int[] c) // not a Deconstruct operator + { + a = 1; + b = ""ignored""; + } + + public void Deconstruct(out int a, out string b) + { + a = 2; + b = ""hello""; + } +} +"; + + var comp = CompileAndVerify(source, expectedOutput: "2 hello", parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics(); } @@ -584,9 +625,9 @@ static void Main() var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics( - // (9,18): error CS7036: There is no argument given that corresponds to the required formal parameter '__arglist' of 'C.Deconstruct(out int, out string, __arglist)' + // (9,18): error CS8206: No Deconstruct instance or extension method was found for type 'C', with 2 out parameters. // (x, y) = new C(); - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "new C()").WithArguments("__arglist", "C.Deconstruct(out int, out string, __arglist)").WithLocation(9, 18) + Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C()").WithArguments("C", "2").WithLocation(9, 18) ); } @@ -611,7 +652,7 @@ public void Deconstruct(out int a, out string b) b = ""hello""; } - public void Deconstruct(out int a, out string b, __arglist) + public void Deconstruct(out int a, out string b, __arglist) // not a Deconstruct operator { a = 2; b = ""ignored""; @@ -645,9 +686,9 @@ static void Main() var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics( - // (11,18): error CS8206: No Deconstruct instance or extension method was found for type 'C'. + // (11,18): error CS8206: No Deconstruct instance or extension method was found for type 'C', with 2 out parameters. // (x, y) = new C() { Deconstruct = DeconstructMethod }; - Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C() { Deconstruct = DeconstructMethod }").WithArguments("C").WithLocation(11, 18) + Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C() { Deconstruct = DeconstructMethod }").WithArguments("C", "2").WithLocation(11, 18) ); } @@ -695,7 +736,7 @@ public void DeconstructEvent() class C { - public event D1 Deconstruct; + public event D1 Deconstruct; // not a Deconstruct operator static void Main() { @@ -716,9 +757,9 @@ public static void DeconstructMethod(out int a, out int b) var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics( - // (14,18): error CS8206: No Deconstruct instance or extension method was found for type 'C'. + // (14,18): error CS8206: No Deconstruct instance or extension method was found for type 'C', with 2 out parameters. // (x, y) = c; - Diagnostic(ErrorCode.ERR_MissingDeconstruct, "c").WithArguments("C").WithLocation(14, 18), + Diagnostic(ErrorCode.ERR_MissingDeconstruct, "c").WithArguments("C", "2").WithLocation(14, 18), // (6,21): warning CS0067: The event 'C.Deconstruct' is never used // public event D1 Deconstruct; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "Deconstruct").WithArguments("C.Deconstruct").WithLocation(6, 21) @@ -1090,13 +1131,14 @@ static void Main() (x, x) = x; } } +static class D +{ + public static void Deconstruct(this int input, out int output, out int output2) { output = input; output2 = input; } +} "; - var comp = CreateCompilationWithMscorlib(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular.WithTuplesFeature()); + var comp = CreateCompilationWithMscorlib(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef, SystemCoreRef }, parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics( - // (7,18): error CS1061: 'int' does not contain a definition for 'Deconstruct' and no extension method 'Deconstruct' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?) - // (x, x) = x; - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "x").WithArguments("int", "Deconstruct").WithLocation(7, 18), // (7,18): error CS0165: Use of unassigned local variable 'x' // (x, x) = x; Diagnostic(ErrorCode.ERR_UseDefViolation, "x").WithArguments("x").WithLocation(7, 18) @@ -1202,9 +1244,9 @@ static void Main() var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature().WithRefsFeature()); comp.VerifyDiagnostics( - // (7,18): error CS1061: 'void' does not contain a definition for 'Deconstruct' and no extension method 'Deconstruct' accepting a first argument of type 'void' could be found (are you missing a using directive or an assembly reference?) + // (7,18): error CS8206: No Deconstruct instance or extension method was found for type 'void', with 2 out parameters. // (x, x) = M(); - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "M()").WithArguments("void", "Deconstruct").WithLocation(7, 18) + Diagnostic(ErrorCode.ERR_MissingDeconstruct, "M()").WithArguments("void", "2").WithLocation(7, 18) ); } @@ -1683,9 +1725,9 @@ static void Main() var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics( - // (12,18): error CS0121: The call is ambiguous between the following methods or properties: 'Base.Deconstruct(out int, out int)' and 'Base.Deconstruct(out long, out long)' + // (12,18): error CS8206: No Deconstruct instance or extension method was found for type 'C', with 2 out parameters. // (x, y) = new C(); - Diagnostic(ErrorCode.ERR_AmbigCall, "new C()").WithArguments("Base.Deconstruct(out int, out int)", "Base.Deconstruct(out long, out long)").WithLocation(12, 18) + Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C()").WithArguments("C", "2").WithLocation(12, 18) ); } @@ -1751,9 +1793,9 @@ static void Main() var comp = CreateCompilationWithMscorlib(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef, SystemCoreRef, CSharpRef }, parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics( - // (7,18): error CS8206: No Deconstruct instance or extension method was found for type 'C'. + // (7,18): error CS8206: No Deconstruct instance or extension method was found for type 'C', with 2 out parameters. // (x, y) = new C(); - Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C()").WithArguments("C").WithLocation(7, 18) + Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C()").WithArguments("C", "2").WithLocation(7, 18) ); } @@ -1775,9 +1817,9 @@ static void Main() var comp = CreateCompilationWithMscorlib(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics( - // (7,18): error CS1955: Non-invocable member 'C.Deconstruct' cannot be used like a method. + // (7,18): error CS8206: No Deconstruct instance or extension method was found for type 'C', with 2 out parameters. // (x, y) = new C(); - Diagnostic(ErrorCode.ERR_NonInvocableMemberCalled, "new C()").WithArguments("C.Deconstruct").WithLocation(7, 18) + Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C()").WithArguments("C", "2").WithLocation(7, 18) ); } @@ -1858,12 +1900,41 @@ static void Main() var comp = CreateCompilationWithMscorlib(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics( - // (8,113): error CS1501: No overload for method 'Deconstruct' takes 22 arguments + // (8,113): error CS8206: No Deconstruct instance or extension method was found for type 'Tuple>>>', with 22 out parameters. // (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22) = CreateLongRef(1, 2, 3, 4, 5, 6, 7, CreateLongRef(8, 9, 10, 11, 12, 13, 14, Tuple.Create(15, 16, 17, 18, 19, 20, 21, 22))); - Diagnostic(ErrorCode.ERR_BadArgCount, "CreateLongRef(1, 2, 3, 4, 5, 6, 7, CreateLongRef(8, 9, 10, 11, 12, 13, 14, Tuple.Create(15, 16, 17, 18, 19, 20, 21, 22)))").WithArguments("Deconstruct", "22").WithLocation(8, 113) + Diagnostic(ErrorCode.ERR_MissingDeconstruct, "CreateLongRef(1, 2, 3, 4, 5, 6, 7, CreateLongRef(8, 9, 10, 11, 12, 13, 14, Tuple.Create(15, 16, 17, 18, 19, 20, 21, 22)))").WithArguments("System.Tuple>>>", "22").WithLocation(8, 113) ); } + [Fact] + public void DeconstructExtensionMethod() + { + string source = @" +class C +{ + static void Main() + { + long x; + string y; + + (x, y) = new C(); + System.Console.WriteLine(x + "" "" + y); + } +} +static class D +{ + public static void Deconstruct(this C value, out int a, out string b) + { + a = 1; + b = ""hello""; + } +} +"; + + var comp = CompileAndVerify(source, expectedOutput: "1 hello", additionalRefs: new[] { SystemCoreRef }, parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics(); + } + [Fact] public void DeconstructUsingDynamicMethod() { @@ -1907,9 +1978,9 @@ static void Main() "; var comp = CreateCompilationWithMscorlib(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics( - // (9,18): error CS0176: Member 'C.Deconstruct(out int, out string)' cannot be accessed with an instance reference; qualify it with a type name instead + // (9,18): error CS8206: No Deconstruct instance or extension method was found for type 'C', with 2 out parameters. // (x, y) = new C(); - Diagnostic(ErrorCode.ERR_ObjectProhibited, "new C()").WithArguments("C.Deconstruct(out int, out string)").WithLocation(9, 18) + Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C()").WithArguments("C", "2").WithLocation(9, 18) ); } From b9a6233d77095a00cac3a007cd076407ef946b11 Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Fri, 10 Jun 2016 19:27:27 -0700 Subject: [PATCH 06/11] PR feedback (3) --- .../Portable/Binder/Binder_Statements.cs | 11 ++++-- .../Emit/CodeGen/CodeGenDeconstructTests.cs | 35 +++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs index 144c26058b326..ac12356c47451 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs @@ -2070,11 +2070,15 @@ static private void FlattenDeconstructVariables(ImmutableArray p.RefKind != RefKind.Out && !p.IsThis)) + var parameters = deconstructMethod.Parameters; + for (int i = (deconstructMethod.IsExtensionMethod ? 1 : 0); i < parameters.Length; i++) { - return MissingDeconstruct(receiver, assignmentSyntax, numCheckedVariables, diagnostics, out outPlaceholders, result); + if (parameters[i].RefKind != RefKind.Out) + { + return MissingDeconstruct(receiver, assignmentSyntax, numCheckedVariables, diagnostics, out outPlaceholders, result); + } } outPlaceholders = outVars.SelectAsArray(v => v.Placeholder); @@ -2085,6 +2089,7 @@ static private void FlattenDeconstructVariables(ImmutableArray Date: Mon, 13 Jun 2016 08:50:38 -0700 Subject: [PATCH 07/11] PR feedback (4) --- .../Portable/Binder/Binder_Invocation.cs | 2 + .../Portable/Binder/Binder_Statements.cs | 12 +++++- .../Emit/CodeGen/CodeGenDeconstructTests.cs | 37 ++++++++++++++++++- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs index f4b2d410bfa00..324632ae2ba6e 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs @@ -330,6 +330,8 @@ private BoundExpression BindArgListOperator(InvocationExpressionSyntax node, Dia private ImmutableArray BuildArgumentsForDynamicInvocation(AnalyzedArguments arguments, DiagnosticBag diagnostics) { + Debug.Assert(!arguments.Arguments.Any(a => a.Kind == BoundKind.OutDeconstructVarPendingInference)); + return arguments.Arguments.ToImmutable(); } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs index ac12356c47451..92cb360a6b40c 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs @@ -2036,7 +2036,7 @@ static private void FlattenDeconstructVariables(ImmutableArray), typeArguments: default(ImmutableArray), @@ -2071,6 +2071,11 @@ static private void FlattenDeconstructVariables(ImmutableArray (object)v.Placeholder == null)) + { + return MissingDeconstruct(receiver, assignmentSyntax, numCheckedVariables, diagnostics, out outPlaceholders, result); + } + outPlaceholders = outVars.SelectAsArray(v => v.Placeholder); return result; diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs index 1b42efd992eae..2a21b958e7c9f 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs @@ -135,6 +135,7 @@ static void Main() long x; string y; (x, y) = new C(); + System.Console.WriteLine(x + "" "" + y); } public void Deconstruct(out int a, out string b) @@ -145,11 +146,11 @@ public void Deconstruct(out int a, out string b) public void Deconstruct(out int a) { - a = 1; + a = 2; } }"; - var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); + var comp = CompileAndVerify(source, expectedOutput: "1 hello", parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics(); } @@ -1970,6 +1971,38 @@ public static void Deconstruct(this C value, out int a, out string b) comp.VerifyDiagnostics(); } + [Fact] + public void DeconstructGenericExtensionMethod() + { + string source = @" +class C +{ + static void Main() + { + long x; + string y; + + (x, y) = new C1(); + } +} + +public class C1 { } + +static class Extension +{ + public static void Deconstruct(this C1 value, out int a, out T b) + { + a = 2; + b = default(T); + System.Console.WriteLine(""Deconstructed""); + } +} +"; + + var comp = CompileAndVerify(source, expectedOutput: "Deconstructed", additionalRefs: new[] { SystemCoreRef }, parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics(); + } + [Fact] public void DeconstructUsingDynamicMethod() { From 0e0bda32ed4b6d78a941ec5f5057894e27a0c120 Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Mon, 13 Jun 2016 09:02:00 -0700 Subject: [PATCH 08/11] Reporting overload resolution errors plus Deconstruct message --- .../Portable/Binder/Binder_Statements.cs | 5 +-- .../Emit/CodeGen/CodeGenDeconstructTests.cs | 36 +++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs index 92cb360a6b40c..a227d1c577d7f 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs @@ -2060,15 +2060,12 @@ static private void FlattenDeconstructVariables(ImmutableArray>>>', with 22 out parameters. // (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22) = CreateLongRef(1, 2, 3, 4, 5, 6, 7, CreateLongRef(8, 9, 10, 11, 12, 13, 14, Tuple.Create(15, 16, 17, 18, 19, 20, 21, 22))); Diagnostic(ErrorCode.ERR_MissingDeconstruct, "CreateLongRef(1, 2, 3, 4, 5, 6, 7, CreateLongRef(8, 9, 10, 11, 12, 13, 14, Tuple.Create(15, 16, 17, 18, 19, 20, 21, 22)))").WithArguments("System.Tuple>>>", "22").WithLocation(8, 113) @@ -2046,6 +2079,9 @@ static void Main() "; var comp = CreateCompilationWithMscorlib(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics( + // (9,18): error CS0176: Member 'C.Deconstruct(out int, out string)' cannot be accessed with an instance reference; qualify it with a type name instead + // (x, y) = new C(); + Diagnostic(ErrorCode.ERR_ObjectProhibited, "new C()").WithArguments("C.Deconstruct(out int, out string)").WithLocation(9, 18), // (9,18): error CS8206: No Deconstruct instance or extension method was found for type 'C', with 2 out parameters. // (x, y) = new C(); Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C()").WithArguments("C", "2").WithLocation(9, 18) From bc3bd436ebe247a74309808baf1b5bbc91da0675 Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Mon, 13 Jun 2016 10:09:44 -0700 Subject: [PATCH 09/11] Test with inaccessible method --- .../Emit/CodeGen/CodeGenDeconstructTests.cs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs index fb7f606251350..e239a5dc8c06d 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs @@ -2061,6 +2061,36 @@ static void Main() ); } + [Fact] + public void DeconstructMethodInaccessible() + { + string source = @" +class C +{ + static void Main() + { + int x; + string y; + + (x, y) = new C1(); + } +} +class C1 +{ + protected void Deconstruct(out int a, out string b) { a = 1; b = ""hello""; } +} +"; + var comp = CreateCompilationWithMscorlib(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics( + // (9,18): error CS0122: 'C1.Deconstruct(out int, out string)' is inaccessible due to its protection level + // (x, y) = new C1(); + Diagnostic(ErrorCode.ERR_BadAccess, "new C1()").WithArguments("C1.Deconstruct(out int, out string)").WithLocation(9, 18), + // (9,18): error CS8206: No Deconstruct instance or extension method was found for type 'C1', with 2 out parameters. + // (x, y) = new C1(); + Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C1()").WithArguments("C1", "2").WithLocation(9, 18) + ); + } + [Fact] public void StaticDeconstruct() { From 3496abbad540bfe07adfb427ce78c9be89dfba9b Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Mon, 13 Jun 2016 12:32:55 -0700 Subject: [PATCH 10/11] Empty Display string, test for use-site errors, Visit throws --- .../CSharp/Portable/BoundTree/Formatting.cs | 5 +-- .../Portable/FlowAnalysis/DataFlowPass.cs | 6 +++ .../Emit/CodeGen/CodeGenDeconstructTests.cs | 39 +++++++++++++++++++ 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src/Compilers/CSharp/Portable/BoundTree/Formatting.cs b/src/Compilers/CSharp/Portable/BoundTree/Formatting.cs index 689eb8c06e11f..803f23c9453c1 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/Formatting.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/Formatting.cs @@ -80,10 +80,7 @@ internal partial class OutDeconstructVarPendingInference { public override object Display { - get - { - return MessageID.IDS_FeatureTuples.Localize(); - } + get { return string.Empty; } } } } diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPass.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPass.cs index ef66ff6fc8d7e..c6800b1b64156 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPass.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPass.cs @@ -1735,6 +1735,12 @@ public override BoundNode VisitDeconstructionAssignmentOperator(BoundDeconstruct return null; } + public override BoundNode VisitOutDeconstructVarPendingInference(OutDeconstructVarPendingInference node) + { + // OutDeconstructVarPendingInference nodes are only used within initial binding, but don't survive past that stage + throw ExceptionUtilities.Unreachable; + } + public override BoundNode VisitIncrementOperator(BoundIncrementOperator node) { base.VisitIncrementOperator(node); diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs index e239a5dc8c06d..38012f2a26c4a 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs @@ -2091,6 +2091,45 @@ class C1 ); } + [Fact] + public void DeconstructHasUseSiteError() + { + string libMissingSource = @"public class Missing { }"; + + string libSource = @" +public class C +{ + public void Deconstruct(out Missing a, out Missing b) { a = new Missing(); b = new Missing(); } +} +"; + + string source = @" +class C1 +{ + static void Main() + { + object x, y; + (x, y) = new C(); + } +} +"; + var libMissingComp = CreateCompilationWithMscorlib(new string[] { libMissingSource }, assemblyName: "libMissingComp").VerifyDiagnostics(); + var libMissingRef = libMissingComp.EmitToImageReference(); + + var libComp = CreateCompilationWithMscorlib(new string[] { libSource }, references: new[] { libMissingRef }, parseOptions: TestOptions.Regular.WithTuplesFeature()).VerifyDiagnostics(); + var libRef = libComp.EmitToImageReference(); + + var comp = CreateCompilationWithMscorlib(new string[] { source }, references: new[] { libRef }, parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics( + // (7,18): error CS0012: The type 'Missing' is defined in an assembly that is not referenced. You must add a reference to assembly 'libMissingComp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. + // (x, y) = new C(); + Diagnostic(ErrorCode.ERR_NoTypeDef, "new C()").WithArguments("Missing", "libMissingComp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(7, 18), + // (7,18): error CS8206: No Deconstruct instance or extension method was found for type 'C', with 2 out parameters. + // (x, y) = new C(); + Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C()").WithArguments("C", "2").WithLocation(7, 18) + ); + } + [Fact] public void StaticDeconstruct() { From 079ccced60d6a4a9aecdd3d2c989fced06d8f31c Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Mon, 13 Jun 2016 13:16:43 -0700 Subject: [PATCH 11/11] Moving throwing Visit code and adding to lower rewriter too --- src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPass.cs | 6 ------ .../Portable/FlowAnalysis/PreciseAbstractFlowPass.cs | 6 ++++++ .../Portable/Lowering/LocalRewriter/LocalRewriter.cs | 7 +++++++ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPass.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPass.cs index c6800b1b64156..ef66ff6fc8d7e 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPass.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPass.cs @@ -1735,12 +1735,6 @@ public override BoundNode VisitDeconstructionAssignmentOperator(BoundDeconstruct return null; } - public override BoundNode VisitOutDeconstructVarPendingInference(OutDeconstructVarPendingInference node) - { - // OutDeconstructVarPendingInference nodes are only used within initial binding, but don't survive past that stage - throw ExceptionUtilities.Unreachable; - } - public override BoundNode VisitIncrementOperator(BoundIncrementOperator node) { base.VisitIncrementOperator(node); diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/PreciseAbstractFlowPass.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/PreciseAbstractFlowPass.cs index aab14c7e3ffdc..5ab45d338ad9a 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/PreciseAbstractFlowPass.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/PreciseAbstractFlowPass.cs @@ -1526,6 +1526,12 @@ public override BoundNode VisitDeconstructionAssignmentOperator(BoundDeconstruct return null; } + public override sealed BoundNode VisitOutDeconstructVarPendingInference(OutDeconstructVarPendingInference node) + { + // OutDeconstructVarPendingInference nodes are only used within initial binding, but don't survive past that stage + throw ExceptionUtilities.Unreachable; + } + public override BoundNode VisitCompoundAssignmentOperator(BoundCompoundAssignmentOperator node) { // TODO: should events be handled specially too? diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs index 0c7fc2f9e592c..1c099f8d8bbc3 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs @@ -8,6 +8,7 @@ using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.RuntimeMembers; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp { @@ -293,6 +294,12 @@ private void RemovePlaceholderReplacements(ArrayBuilder