From da60463e987dd0263e5d4584be7ea61e3da428df Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Fri, 8 Jun 2018 08:46:14 -0700 Subject: [PATCH] Fix crash in GetDeconstructionInfo (#27605) --- .../Compilation/MemberSemanticModel.cs | 10 +++++- .../Emit/CodeGen/CodeGenDeconstructTests.cs | 33 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs index 6c6c13c48ed..b34a8b9c8ba 100644 --- a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs @@ -854,7 +854,11 @@ public override DeconstructionInfo GetDeconstructionInfo(AssignmentExpressionSyn } var boundConversion = boundDeconstruction.Right; - Debug.Assert(boundConversion != null || boundDeconstruction.HasAnyErrors); + Debug.Assert(boundConversion != null); + if (boundConversion is null) + { + return default; + } return new DeconstructionInfo(boundConversion.Conversion); } @@ -869,6 +873,10 @@ public override DeconstructionInfo GetDeconstructionInfo(ForEachVariableStatemen var boundDeconstruction = boundForEach.DeconstructionOpt; Debug.Assert(boundDeconstruction != null || boundForEach.HasAnyErrors); + if (boundDeconstruction is null) + { + return default; + } return new DeconstructionInfo(boundDeconstruction.DeconstructionAssignment.Right.Conversion); } diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs index 539d365f40a..e9953eae16c 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs @@ -273,6 +273,39 @@ public void Deconstruct(out int a) Assert.Equal(ConversionKind.NoConversion, defaultInfo.Conversion.Value.Kind); } + [Fact] + [WorkItem(27520, "https://github.com/dotnet/roslyn/issues/27520")] + public void GetDeconstructionInfoOnIncompleteCode() + { + string source = @" +class C +{ + static void M(string s) + { + foreach (char in s) { } + } +}"; + + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (6,18): error CS1525: Invalid expression term 'char' + // foreach (char in s) { } + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "char").WithArguments("char").WithLocation(6, 18), + // (6,23): error CS0230: Type and identifier are both required in a foreach statement + // foreach (char in s) { } + Diagnostic(ErrorCode.ERR_BadForeachDecl, "in").WithLocation(6, 23) + ); + + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + var foreachDeconstruction = (ForEachVariableStatementSyntax)tree.FindNodeOrTokenByKind(SyntaxKind.ForEachVariableStatement).AsNode(); + Assert.Equal(@"foreach (char in s) { }", foreachDeconstruction.ToString()); + var deconstructionInfo = model.GetDeconstructionInfo(foreachDeconstruction); + Assert.Equal(Conversion.NoConversion, deconstructionInfo.Conversion); + Assert.Null(deconstructionInfo.Method); + Assert.Empty(deconstructionInfo.Nested); + } + [Fact] [WorkItem(15634, "https://github.com/dotnet/roslyn/issues/15634")] public void DeconstructMustReturnVoid() -- GitLab