From c130866286241923c2f3d9cc592035293f836195 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Wed, 11 Jun 2014 20:42:04 -0700 Subject: [PATCH] SemanticModel bug fixes: #948019 and #960755. (changeset 1276813) --- .../CSharp/Source/Binder/Binder_Statements.cs | 36 +------- .../CSharp/Source/Binder/ForLoopBinder.cs | 30 +++++++ .../CSharp/Source/CSharpResources.Designer.cs | 6 +- .../CSharp/Source/CSharpResources.resx | 4 +- .../Source/Compilation/CSharpSemanticModel.cs | 28 +++--- .../Compilation/SyntaxTreeSemanticModel.cs | 2 +- .../Source/FlowAnalysis/DataFlowPass.cs | 4 +- .../FlowAnalysis/PreciseAbstractFlowPass.cs | 4 +- .../FlowAnalysis/VariablesDeclaredWalker.cs | 4 +- .../Semantic/Semantics/ColorColorTests.cs | 9 +- .../Test/Semantic/Semantics/LambdaTests.cs | 89 +++++++++++++++++++ .../Test/Semantic/Semantics/LookupTests.cs | 10 +-- .../Compilation/GetSemanticInfoTests.cs | 22 +++-- .../SemanticModelGetSemanticInfoTests.cs | 20 ++--- .../Symbols/Source/PrimaryConstructors.cs | 4 +- .../Source/Binding/Binder_Conversions.vb | 6 +- .../Source/Binding/MemberSemanticModel.vb | 26 +++++- .../Semantics/LambdaSemanticInfoTests.vb | 83 +++++++++++++++++ .../Test/Semantic/Semantics/SelectCaseTest.vb | 74 +++++++++++++++ 19 files changed, 361 insertions(+), 100 deletions(-) diff --git a/Src/Compilers/CSharp/Source/Binder/Binder_Statements.cs b/Src/Compilers/CSharp/Source/Binder/Binder_Statements.cs index 3a2b802d7a0..52c8a40aac4 100644 --- a/Src/Compilers/CSharp/Source/Binder/Binder_Statements.cs +++ b/Src/Compilers/CSharp/Source/Binder/Binder_Statements.cs @@ -278,7 +278,7 @@ internal BoundStatement BindPossibleEmbeddedStatement(StatementSyntax node, Diag if (!locals.IsDefaultOrEmpty) { result = new BoundBlock(node, locals, ImmutableArray.Create(result)) { WasCompilerGenerated = true }; - } + } return result; } @@ -2707,37 +2707,7 @@ internal virtual BoundForStatement BindForParts(DiagnosticBag diagnostics, Binde return this.Next.BindForParts(diagnostics, originalBinder); } - // TODO: Move this method into ForLoopBinder. Keep it here fo now for better diff. - internal BoundForStatement BindForParts(ForStatementSyntax node, Binder originalBinder, DiagnosticBag diagnostics) - { - BoundStatement initializer; - if (node.Declaration != null) - { - Debug.Assert(node.Initializers.Count == 0); - ImmutableArray unused; - initializer = this.Next.BindForOrUsingOrFixedDeclarations(node.Declaration, LocalDeclarationKind.For, diagnostics, out unused); - } - else - { - initializer = this.Next.BindStatementExpressionList(node.Initializers, diagnostics); - } - - var condition = (node.Condition != null) ? BindBooleanExpression(node.Condition, diagnostics) : null; - var increment = BindStatementExpressionList(node.Incrementors, diagnostics); - var body = originalBinder.BindPossibleEmbeddedStatement(node.Statement, diagnostics); - - return new BoundForStatement(node, - ImmutableArray.Empty, - initializer, - this.Locals, - condition, - increment, - body, - this.BreakLabel, - this.ContinueLabel); - } - - protected BoundStatement BindForOrUsingOrFixedDeclarations(VariableDeclarationSyntax nodeOpt, LocalDeclarationKind localDeclarationKind, DiagnosticBag diagnostics, out ImmutableArray declarations) + internal BoundStatement BindForOrUsingOrFixedDeclarations(VariableDeclarationSyntax nodeOpt, LocalDeclarationKind localDeclarationKind, DiagnosticBag diagnostics, out ImmutableArray declarations) { if (nodeOpt == null) { @@ -2782,7 +2752,7 @@ protected BoundStatement BindForOrUsingOrFixedDeclarations(VariableDeclarationSy new BoundMultipleLocalDeclarations(nodeOpt, declarations); } - private BoundStatement BindStatementExpressionList(SeparatedSyntaxList statements, DiagnosticBag diagnostics) + internal BoundStatement BindStatementExpressionList(SeparatedSyntaxList statements, DiagnosticBag diagnostics) { int count = statements.Count; if (count == 0) diff --git a/Src/Compilers/CSharp/Source/Binder/ForLoopBinder.cs b/Src/Compilers/CSharp/Source/Binder/ForLoopBinder.cs index 1e1c5150384..55e49357730 100644 --- a/Src/Compilers/CSharp/Source/Binder/ForLoopBinder.cs +++ b/Src/Compilers/CSharp/Source/Binder/ForLoopBinder.cs @@ -62,6 +62,36 @@ internal override BoundForStatement BindForParts(DiagnosticBag diagnostics, Bind return result; } + + private BoundForStatement BindForParts(ForStatementSyntax node, Binder originalBinder, DiagnosticBag diagnostics) + { + BoundStatement initializer; + if (node.Declaration != null) + { + Debug.Assert(node.Initializers.Count == 0); + ImmutableArray unused; + initializer = this.Next.BindForOrUsingOrFixedDeclarations(node.Declaration, LocalDeclarationKind.For, diagnostics, out unused); + } + else + { + initializer = this.Next.BindStatementExpressionList(node.Initializers, diagnostics); + } + + var condition = (node.Condition != null) ? BindBooleanExpression(node.Condition, diagnostics) : null; + var increment = BindStatementExpressionList(node.Incrementors, diagnostics); + var body = originalBinder.BindPossibleEmbeddedStatement(node.Statement, diagnostics); + + return new BoundForStatement(node, + ImmutableArray.Empty, + initializer, + this.Locals, + condition, + increment, + body, + this.BreakLabel, + this.ContinueLabel); + } + } internal sealed class ForLoopInitializationBinder : LocalScopeBinder diff --git a/Src/Compilers/CSharp/Source/CSharpResources.Designer.cs b/Src/Compilers/CSharp/Source/CSharpResources.Designer.cs index b0b5f67dafd..8a08a615f47 100644 --- a/Src/Compilers/CSharp/Source/CSharpResources.Designer.cs +++ b/Src/Compilers/CSharp/Source/CSharpResources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.18449 +// Runtime Version:4.0.30319.34014 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -6856,7 +6856,7 @@ internal class CSharpResources { } /// - /// Looks up a localized string similar to '{0}': a parameter of a primary constructor cannot have the same name as containing type. + /// Looks up a localized string similar to '{0}': a parameter of a primary constructor cannot have the same name as containing type.. /// internal static string ERR_PrimaryCtorParameterSameNameAsContainingType { get { @@ -6865,7 +6865,7 @@ internal class CSharpResources { } /// - /// Looks up a localized string similar to '{0}': a parameter of a primary constructor cannot have the same name as a type's type parameter '{1}'. + /// Looks up a localized string similar to '{0}': a parameter of a primary constructor cannot have the same name as a type's type parameter '{1}'.. /// internal static string ERR_PrimaryCtorParameterSameNameAsTypeParam { get { diff --git a/Src/Compilers/CSharp/Source/CSharpResources.resx b/Src/Compilers/CSharp/Source/CSharpResources.resx index ec65579d7d7..9a9686de4b3 100644 --- a/Src/Compilers/CSharp/Source/CSharpResources.resx +++ b/Src/Compilers/CSharp/Source/CSharpResources.resx @@ -3787,10 +3787,10 @@ Since this type has a primary constructor, all instance constructor declarations must specify a constructor initializer of the form this([argument-list]). - '{0}': a parameter of a primary constructor cannot have the same name as a type's type parameter '{1}' + '{0}': a parameter of a primary constructor cannot have the same name as a type's type parameter '{1}'. - '{0}': a parameter of a primary constructor cannot have the same name as containing type + '{0}': a parameter of a primary constructor cannot have the same name as containing type. Primary constructor already has a body. diff --git a/Src/Compilers/CSharp/Source/Compilation/CSharpSemanticModel.cs b/Src/Compilers/CSharp/Source/Compilation/CSharpSemanticModel.cs index 25c217e876f..bcb8aee3dda 100644 --- a/Src/Compilers/CSharp/Source/Compilation/CSharpSemanticModel.cs +++ b/Src/Compilers/CSharp/Source/Compilation/CSharpSemanticModel.cs @@ -1723,24 +1723,7 @@ private bool IsInTypeofExpression(int position) ImmutableArray unusedHighestMemberGroup; ImmutableArray highestSymbols = GetSemanticSymbols(highestBoundExpr, boundNodeForSyntacticParent, binderOpt, options, out highestIsDynamic, out highestResultKind, out unusedHighestMemberGroup); - // For an expression of the form (x.M is T) where x.M is a method group, we return an - // arbitrary representative of the method group. - if (boundNodeForSyntacticParent != null && boundNodeForSyntacticParent.Kind == BoundKind.IsOperator && boundExpr.Kind == BoundKind.MethodGroup) - { - // Just take the first one that happens to be in our list. This code once tried to sort based - // on the LexicalOrderSymbolComparer, but that assumes that the symbols are in source, which is - // not always the case. - if (symbols.Length >= 1) - { - symbols = ImmutableArray.Create(symbols.First()); - resultKind = LookupResultKind.Viable; - } - } - // Generally, we want to use the symbols from the LOWEST node. However, if the - // lowest node doesn't have symbols (or had an overload resolution failure), and - // the highest does, use those instead. Also, if the highest node has a WORSE - // resultKind, use that. - else if ((symbols.Length != 1 || resultKind == LookupResultKind.OverloadResolutionFailure) && highestSymbols.Length > 0) + if ((symbols.Length != 1 || resultKind == LookupResultKind.OverloadResolutionFailure) && highestSymbols.Length > 0) { symbols = highestSymbols; resultKind = highestResultKind; @@ -3731,6 +3714,11 @@ private static ImmutableArray FilterOverriddenOrHiddenMethods(Immu default: symbols = methodGroup; + if (symbols.Length > 0) + { + resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure); + } + break; } } @@ -3742,6 +3730,10 @@ private static ImmutableArray FilterOverriddenOrHiddenMethods(Immu // one candidate, then we should probably succeed. symbols = methodGroup; + if (symbols.Length > 0) + { + resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure); + } } if (!symbols.Any()) diff --git a/Src/Compilers/CSharp/Source/Compilation/SyntaxTreeSemanticModel.cs b/Src/Compilers/CSharp/Source/Compilation/SyntaxTreeSemanticModel.cs index 30e32be6664..94375e2ccf3 100644 --- a/Src/Compilers/CSharp/Source/Compilation/SyntaxTreeSemanticModel.cs +++ b/Src/Compilers/CSharp/Source/Compilation/SyntaxTreeSemanticModel.cs @@ -919,7 +919,7 @@ private MemberSemanticModel GetOrAddModel(CSharpSyntaxNode node) return this.memberModels.GetOrAdd(node, createMemberModelFunction); } - // Create a the member model for the given declaration syntax. In certain very malformed + // Create a member model for the given declaration syntax. In certain very malformed // syntax trees, there may not be a symbol that can have a member model associated with it // (although we try to minimize such cases). In such cases, null is returned. private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node) diff --git a/Src/Compilers/CSharp/Source/FlowAnalysis/DataFlowPass.cs b/Src/Compilers/CSharp/Source/FlowAnalysis/DataFlowPass.cs index 09c40ef7b74..20a7328ad1e 100644 --- a/Src/Compilers/CSharp/Source/FlowAnalysis/DataFlowPass.cs +++ b/Src/Compilers/CSharp/Source/FlowAnalysis/DataFlowPass.cs @@ -1460,7 +1460,7 @@ public override BoundNode VisitDeclarationExpression(BoundDeclarationExpression return null; } - protected override void VisitLvaluetDeclarationExpression(BoundDeclarationExpression node) + protected override void VisitLvalueDeclarationExpression(BoundDeclarationExpression node) { LocalSymbol localSymbol = node.LocalSymbol; int slot = MakeSlot(localSymbol); // not initially assigned @@ -1474,7 +1474,7 @@ protected override void VisitLvaluetDeclarationExpression(BoundDeclarationExpres if (node.InitializerOpt != null) { - base.VisitLvaluetDeclarationExpression(node); + base.VisitLvalueDeclarationExpression(node); Assign(node, node.InitializerOpt); } } diff --git a/Src/Compilers/CSharp/Source/FlowAnalysis/PreciseAbstractFlowPass.cs b/Src/Compilers/CSharp/Source/FlowAnalysis/PreciseAbstractFlowPass.cs index 33cd22e08e5..2da3ac4b6a3 100644 --- a/Src/Compilers/CSharp/Source/FlowAnalysis/PreciseAbstractFlowPass.cs +++ b/Src/Compilers/CSharp/Source/FlowAnalysis/PreciseAbstractFlowPass.cs @@ -490,7 +490,7 @@ protected void VisitLvalue(BoundExpression node) break; case BoundKind.DeclarationExpression: - VisitLvaluetDeclarationExpression((BoundDeclarationExpression)node); + VisitLvalueDeclarationExpression((BoundDeclarationExpression)node); break; case BoundKind.FieldAccess: @@ -975,7 +975,7 @@ private void VisitDeclarationExpressionInitializer(BoundDeclarationExpression no } } - protected virtual void VisitLvaluetDeclarationExpression(BoundDeclarationExpression node) + protected virtual void VisitLvalueDeclarationExpression(BoundDeclarationExpression node) { VisitDeclarationExpressionInitializer(node); } diff --git a/Src/Compilers/CSharp/Source/FlowAnalysis/VariablesDeclaredWalker.cs b/Src/Compilers/CSharp/Source/FlowAnalysis/VariablesDeclaredWalker.cs index b576246253e..20a0e95f976 100644 --- a/Src/Compilers/CSharp/Source/FlowAnalysis/VariablesDeclaredWalker.cs +++ b/Src/Compilers/CSharp/Source/FlowAnalysis/VariablesDeclaredWalker.cs @@ -72,14 +72,14 @@ public override BoundNode VisitDeclarationExpression(BoundDeclarationExpression return base.VisitDeclarationExpression(node); } - protected override void VisitLvaluetDeclarationExpression(BoundDeclarationExpression node) + protected override void VisitLvalueDeclarationExpression(BoundDeclarationExpression node) { if (IsInside) { variablesDeclared.Add(node.LocalSymbol); } - base.VisitLvaluetDeclarationExpression(node); + base.VisitLvalueDeclarationExpression(node); } public override BoundNode VisitLambda(BoundLambda node) diff --git a/Src/Compilers/CSharp/Test/Semantic/Semantics/ColorColorTests.cs b/Src/Compilers/CSharp/Test/Semantic/Semantics/ColorColorTests.cs index ac21427f486..bb1854b2691 100644 --- a/Src/Compilers/CSharp/Test/Semantic/Semantics/ColorColorTests.cs +++ b/Src/Compilers/CSharp/Test/Semantic/Semantics/ColorColorTests.cs @@ -636,10 +636,11 @@ void M() Assert.Equal(SyntaxKind.SimpleMemberAccessExpression, parentExpr.Kind); var parentInfo = model.GetSymbolInfo(parentExpr); Assert.NotNull(parentInfo); - Assert.NotNull(parentInfo.Symbol); // the lexically first matching method - Assert.Equal("void Color.M()", parentInfo.Symbol.ToTestDisplayString()); - Assert.Equal(CandidateReason.None, parentInfo.CandidateReason); - Assert.Equal(0, parentInfo.CandidateSymbols.Length); + Assert.Null(parentInfo.Symbol); // the lexically first matching method + Assert.Equal(2, parentInfo.CandidateSymbols.Length); + Assert.Equal("void Color.M()", parentInfo.CandidateSymbols[0].ToTestDisplayString()); + Assert.Equal("void Color.M(System.Int32 x)", parentInfo.CandidateSymbols[1].ToTestDisplayString()); + Assert.Equal(CandidateReason.OverloadResolutionFailure, parentInfo.CandidateReason); } [Fact] diff --git a/Src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs b/Src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs index d0841af4679..61a45ca361d 100644 --- a/Src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs +++ b/Src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs @@ -1005,5 +1005,94 @@ protected void TryGetDocumentId(CancellationToken token) Diagnostic(ErrorCode.WRN_UnassignedInternalField, "integrationService").WithArguments("TestDataPointBase.integrationService", "null").WithLocation(6, 54) ); } + + [Fact, WorkItem(960755, "DevDiv")] + public void Bug960755_01() + { + var source = @" +using System.Collections.Generic; + +class C +{ + static void M(IList c) + { + var tmp = new C(); + tmp.M((a, b) => c.Add); + } +} + +"; + var tree = SyntaxFactory.ParseSyntaxTree(source); + var comp = CreateCompilationWithMscorlib(tree); + var model = comp.GetSemanticModel(tree); + + var expr = (ExpressionSyntax)tree.GetCompilationUnitRoot().DescendantNodes().OfType().Single().Body; + + var symbolInfo = model.GetSymbolInfo(expr); + + Assert.Null(symbolInfo.Symbol); + Assert.Equal("void System.Collections.Generic.ICollection.Add(C item)", symbolInfo.CandidateSymbols.Single().ToTestDisplayString()); + Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason); + } + + [Fact, WorkItem(960755, "DevDiv")] + public void Bug960755_02() + { + var source = @" +using System.Collections.Generic; + +class C +{ + static void M(IList c) + { + int tmp = c.Add; + } +} + +"; + var tree = SyntaxFactory.ParseSyntaxTree(source); + var comp = CreateCompilationWithMscorlib(tree); + var model = comp.GetSemanticModel(tree); + + var expr = (ExpressionSyntax)tree.GetCompilationUnitRoot().DescendantNodes().OfType().Single().Initializer.Value; + + var symbolInfo = model.GetSymbolInfo(expr); + + Assert.Null(symbolInfo.Symbol); + Assert.Equal("void System.Collections.Generic.ICollection.Add(C item)", symbolInfo.CandidateSymbols.Single().ToTestDisplayString()); + Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason); + } + + [Fact, WorkItem(960755, "DevDiv")] + public void Bug960755_03() + { + var source = @" +using System.Collections.Generic; + +class C +{ + static void M(IList c) + { + var tmp = new C(); + tmp.M((a, b) => c.Add); + } + + static void M(System.Func> x) + {} +} + +"; + var tree = SyntaxFactory.ParseSyntaxTree(source); + var comp = CreateCompilationWithMscorlib(tree); + var model = comp.GetSemanticModel(tree); + + var expr = (ExpressionSyntax)tree.GetCompilationUnitRoot().DescendantNodes().OfType().Single().Body; + + var symbolInfo = model.GetSymbolInfo(expr); + + Assert.Equal("void System.Collections.Generic.ICollection.Add(C item)", symbolInfo.Symbol.ToTestDisplayString()); + Assert.Equal(0, symbolInfo.CandidateSymbols.Length); + Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason); + } } } diff --git a/Src/Compilers/CSharp/Test/Semantic/Semantics/LookupTests.cs b/Src/Compilers/CSharp/Test/Semantic/Semantics/LookupTests.cs index 6b455229941..fa9ffd415f5 100644 --- a/Src/Compilers/CSharp/Test/Semantic/Semantics/LookupTests.cs +++ b/Src/Compilers/CSharp/Test/Semantic/Semantics/LookupTests.cs @@ -1447,14 +1447,12 @@ static int Main(string[] args) var model = compilation.GetSemanticModel(tree); var node = tree.GetRoot().DescendantNodes().OfType().Where(n => n.ToString() == "m.M").Single(); var symbolInfo = model.GetSymbolInfo(node); - Assert.Equal("M", symbolInfo.Symbol.Name); - Assert.Equal(SymbolKind.Method, symbolInfo.Symbol.Kind); - Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason); + Assert.Equal("void I1.M()", symbolInfo.CandidateSymbols.Single().ToTestDisplayString()); + Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason); var node2 = (ExpressionSyntax)SyntaxFactory.SyntaxTree(node).GetRoot(); symbolInfo = model.GetSpeculativeSymbolInfo(node.Position, node2, SpeculativeBindingOption.BindAsExpression); - Assert.Equal("M", symbolInfo.Symbol.Name); - Assert.Equal(SymbolKind.Method, symbolInfo.Symbol.Kind); - Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason); + Assert.Equal("void I1.M()", symbolInfo.CandidateSymbols.Single().ToTestDisplayString()); + Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason); } private void TestLookupSymbolsNestedNamespaces(List actual_lookupSymbols) diff --git a/Src/Compilers/CSharp/Test/Symbol/Compilation/GetSemanticInfoTests.cs b/Src/Compilers/CSharp/Test/Symbol/Compilation/GetSemanticInfoTests.cs index ec69f234cdb..654cb381d91 100644 --- a/Src/Compilers/CSharp/Test/Symbol/Compilation/GetSemanticInfoTests.cs +++ b/Src/Compilers/CSharp/Test/Symbol/Compilation/GetSemanticInfoTests.cs @@ -3681,7 +3681,8 @@ static void M() Assert.Equal(SyntaxKind.SimpleMemberAccessExpression, syntax.Kind); var info = model.GetSpeculativeSymbolInfo(position, syntax, SpeculativeBindingOption.BindAsExpression); - Assert.Equal(compilation.GlobalNamespace.GetMember("C").GetMember("M"), info.Symbol); + Assert.Equal(compilation.GlobalNamespace.GetMember("C").GetMember("M"), info.CandidateSymbols.Single()); + Assert.Equal(CandidateReason.OverloadResolutionFailure, info.CandidateReason); } [WorkItem(544651, "DevDiv")] @@ -3740,7 +3741,8 @@ static void M() Assert.Equal(SyntaxKind.IdentifierName, syntax.Kind); var info = model.GetSymbolInfo(syntax); - Assert.Equal(compilation.GlobalNamespace.GetMember("C").GetMember("M"), info.Symbol); + Assert.Equal(compilation.GlobalNamespace.GetMember("C").GetMember("M"), info.CandidateSymbols.Single()); + Assert.Equal(CandidateReason.OverloadResolutionFailure, info.CandidateReason); } [WorkItem(546046, "DevDiv")] @@ -4488,10 +4490,10 @@ int M(S s) var structInfo = model.GetSymbolInfo(structMemberAccess); // Only one candidate. - Assert.Equal(CandidateReason.None, classInfo.CandidateReason); - Assert.Equal(classType, classInfo.Symbol.ContainingType); - Assert.Equal(CandidateReason.None, structInfo.CandidateReason); - Assert.Equal(structType, structInfo.Symbol.ContainingType); + Assert.Equal(CandidateReason.OverloadResolutionFailure, classInfo.CandidateReason); + Assert.Equal("System.Int32 C.GetHashCode()", classInfo.CandidateSymbols.Single().ToTestDisplayString()); + Assert.Equal(CandidateReason.OverloadResolutionFailure, structInfo.CandidateReason); + Assert.Equal("System.Int32 S.GetHashCode()", structInfo.CandidateSymbols.Single().ToTestDisplayString()); } [WorkItem(530252, "DevDiv")] @@ -4535,8 +4537,8 @@ static void Main(string[] args) var info = model.GetSymbolInfo(memberAccess); // Only one candidate. - Assert.Equal(CandidateReason.None, info.CandidateReason); - Assert.Equal(classC, info.Symbol.ContainingType); + Assert.Equal(CandidateReason.OverloadResolutionFailure, info.CandidateReason); + Assert.Equal("void C.M()", info.CandidateSymbols.Single().ToTestDisplayString()); } [Fact] @@ -4804,7 +4806,9 @@ void M() var equalsNode = equalsToken.Parent; var symbolInfo = model.GetSymbolInfo(equalsNode); //note that we don't guarantee what symbol will come back on a method group in an is expression. - Assert.NotNull(symbolInfo.Symbol); + Assert.Null(symbolInfo.Symbol); + Assert.True(symbolInfo.CandidateSymbols.Length > 0); + Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason); } [Fact, WorkItem(531304, "DevDiv")] diff --git a/Src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetSemanticInfoTests.cs b/Src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetSemanticInfoTests.cs index 02729056211..32421f77f8d 100644 --- a/Src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetSemanticInfoTests.cs +++ b/Src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetSemanticInfoTests.cs @@ -8557,11 +8557,9 @@ public static int Main(string[] args) Assert.Equal(TypeKind.Error, semanticInfo.ConvertedType.TypeKind); Assert.Equal(ConversionKind.Identity, semanticInfo.ImplicitConversion.Kind); - Assert.NotNull(semanticInfo.Symbol); - Assert.Equal(CandidateReason.None, semanticInfo.CandidateReason); - Assert.Equal(0, semanticInfo.CandidateSymbols.Length); - Assert.Equal("System.Int32 Test.M()", semanticInfo.Symbol.ToTestDisplayString()); - Assert.Equal(SymbolKind.Method, semanticInfo.Symbol.Kind); + Assert.Null(semanticInfo.Symbol); + Assert.Equal(CandidateReason.OverloadResolutionFailure, semanticInfo.CandidateReason); + Assert.Equal("System.Int32 Test.M()", semanticInfo.CandidateSymbols.Single().ToTestDisplayString()); Assert.Equal(1, semanticInfo.MethodGroup.Length); var sortedMethodGroup = semanticInfo.MethodGroup.OrderBy(s => s.ToTestDisplayString()).ToArray(); @@ -8932,12 +8930,9 @@ public static int Main(string[] args) Assert.Equal(TypeKind.Class, semanticInfo.ConvertedType.TypeKind); Assert.Equal(ConversionKind.NoConversion, semanticInfo.ImplicitConversion.Kind); - Assert.NotNull(semanticInfo.Symbol); - Assert.Equal(CandidateReason.None, semanticInfo.CandidateReason); - Assert.Equal(0, semanticInfo.CandidateSymbols.Length); - var sortedCandidates = semanticInfo.CandidateSymbols.OrderBy(s => s.ToTestDisplayString()).ToArray(); - Assert.Equal("System.Int32 Test.M()", semanticInfo.Symbol.ToTestDisplayString()); - Assert.Equal(SymbolKind.Method, semanticInfo.Symbol.Kind); + Assert.Null(semanticInfo.Symbol); + Assert.Equal(CandidateReason.OverloadResolutionFailure, semanticInfo.CandidateReason); + Assert.Equal("System.Int32 Test.M()", semanticInfo.CandidateSymbols.Single().ToTestDisplayString()); Assert.Equal(1, semanticInfo.MethodGroup.Length); var sortedMethodGroup = semanticInfo.MethodGroup.OrderBy(s => s.ToTestDisplayString()).ToArray(); @@ -14395,7 +14390,8 @@ class C { } "; var semanticInfo = GetSemanticInfoForTest(sourceCode); - Utils.CheckSymbol(semanticInfo.Symbol, "void C.M(T t)"); + Utils.CheckSymbol(semanticInfo.CandidateSymbols.Single(), "void C.M(T t)"); + Assert.Equal(CandidateReason.OverloadResolutionFailure, semanticInfo.CandidateReason); Assert.Null(semanticInfo.Type); Utils.CheckSymbol(semanticInfo.ConvertedType, "D"); } diff --git a/Src/Compilers/CSharp/Test/Symbol/Symbols/Source/PrimaryConstructors.cs b/Src/Compilers/CSharp/Test/Symbol/Symbols/Source/PrimaryConstructors.cs index 94391c4b46e..6678233734c 100644 --- a/Src/Compilers/CSharp/Test/Symbol/Symbols/Source/PrimaryConstructors.cs +++ b/Src/Compilers/CSharp/Test/Symbol/Symbols/Source/PrimaryConstructors.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +// Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using Microsoft.CodeAnalysis.CSharp.Emit; diff --git a/Src/Compilers/VisualBasic/Source/Binding/Binder_Conversions.vb b/Src/Compilers/VisualBasic/Source/Binding/Binder_Conversions.vb index 9bd2af9c06b..4ba58089c32 100644 --- a/Src/Compilers/VisualBasic/Source/Binding/Binder_Conversions.vb +++ b/Src/Compilers/VisualBasic/Source/Binding/Binder_Conversions.vb @@ -330,11 +330,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return New BoundConversion(node, argument, - ConversionKind:=Nothing, + conversionKind:=Nothing, checked:=CheckOverflow, explicitCastInCode:=isExplicit, - Type:=targetType, - HasErrors:=True) + type:=targetType, + hasErrors:=True) End If If argument.HasErrors Then diff --git a/Src/Compilers/VisualBasic/Source/Binding/MemberSemanticModel.vb b/Src/Compilers/VisualBasic/Source/Binding/MemberSemanticModel.vb index 5ba568d4dec..406732ba6ff 100644 --- a/Src/Compilers/VisualBasic/Source/Binding/MemberSemanticModel.vb +++ b/Src/Compilers/VisualBasic/Source/Binding/MemberSemanticModel.vb @@ -2037,11 +2037,33 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ''' allow. ''' Public Function RecordNode(node As BoundNode, Optional allowCompilerGenerated As Boolean = False) As Boolean - If (Not allowCompilerGenerated AndAlso node.WasCompilerGenerated) OrElse node.Kind = BoundKind.UnboundLambda Then - ' Don't cache compiler generated nodes or unbound lambdas (unbound lambda are converted into bound lambdas in VisitUnboundLambda.) + + If Not allowCompilerGenerated AndAlso node.WasCompilerGenerated Then + ' Don't cache compiler generated nodes Return False End If + Select Case node.Kind + Case BoundKind.UnboundLambda + ' Don't cache unbound lambdas (unbound lambda are converted into bound lambdas in VisitUnboundLambda.) + Return False + + Case BoundKind.Conversion + If Not allowCompilerGenerated Then + Dim conversion = DirectCast(node, BoundConversion) + If Not conversion.ExplicitCastInCode AndAlso conversion.Operand.WasCompilerGenerated Then + Select Case conversion.Operand.Kind + Case BoundKind.RValuePlaceholder, + BoundKind.LValuePlaceholder, + BoundKind.WithLValueExpressionPlaceholder, + BoundKind.WithRValueExpressionPlaceholder + ' Don't cache compiler generated nodes + Return False + End Select + End If + End If + End Select + If _thisSyntaxNodeOnly IsNot Nothing AndAlso node.Syntax IsNot _thisSyntaxNodeOnly Then ' Didn't match the syntax node we're trying to handle Return False diff --git a/Src/Compilers/VisualBasic/Test/Semantic/Semantics/LambdaSemanticInfoTests.vb b/Src/Compilers/VisualBasic/Test/Semantic/Semantics/LambdaSemanticInfoTests.vb index c3dcef2331e..a361f70f46f 100644 --- a/Src/Compilers/VisualBasic/Test/Semantic/Semantics/LambdaSemanticInfoTests.vb +++ b/Src/Compilers/VisualBasic/Test/Semantic/Semantics/LambdaSemanticInfoTests.vb @@ -738,6 +738,89 @@ BC30203: Identifier expected. Assert.False(semanticInfo.ConstantValue.HasValue) End Sub + + Public Sub Bug960755_01() + + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime( + + +Imports System.Collections.Generic + +Class C + Sub M(c As IList(Of C)) + Dim tmp = New C() + tmp.M(Function(a, b) AddressOf c.Add) 'BIND:"c.Add" + End Sub +End Class + + ) + + Dim node = CompilationUtils.FindBindingText(Of ExpressionSyntax)(compilation, "a.vb") + Dim semanticModel = compilation.GetSemanticModel(node.SyntaxTree) + + Dim symbolInfo = semanticModel.GetSymbolInfo(node) + + Assert.Null(symbolInfo.Symbol) + Assert.Equal("Sub System.Collections.Generic.ICollection(Of C).Add(item As C)", symbolInfo.CandidateSymbols.Single().ToTestDisplayString()) + Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason) + End Sub + + + Public Sub Bug960755_02() + + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime( + + +Imports System.Collections.Generic + +Class C + Sub M(c As IList(Of C)) + Dim tmp As Integer = AddressOf c.Add 'BIND:"c.Add" + End Sub +End Class + + ) + + Dim node = CompilationUtils.FindBindingText(Of ExpressionSyntax)(compilation, "a.vb") + Dim semanticModel = compilation.GetSemanticModel(node.SyntaxTree) + + Dim symbolInfo = semanticModel.GetSymbolInfo(node) + + Assert.Null(symbolInfo.Symbol) + Assert.Equal("Sub System.Collections.Generic.ICollection(Of C).Add(item As C)", symbolInfo.CandidateSymbols.Single().ToTestDisplayString()) + Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason) + End Sub + + + Public Sub Bug960755_03() + + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime( + + +Imports System.Collections.Generic + +Class C + Sub M(c As IList(Of C)) + Dim tmp = New C() + tmp.M(Function(a, b) AddressOf c.Add) 'BIND:"c.Add" + End Sub + + Sub M(x as System.Func(Of Integer, Integer, System.Action(Of C))) + End Sub +End Class + + ) + + Dim node = CompilationUtils.FindBindingText(Of ExpressionSyntax)(compilation, "a.vb") + Dim semanticModel = compilation.GetSemanticModel(node.SyntaxTree) + + Dim symbolInfo = semanticModel.GetSymbolInfo(node) + + Assert.Equal("Sub System.Collections.Generic.ICollection(Of C).Add(item As C)", symbolInfo.Symbol.ToTestDisplayString()) + Assert.Equal(0, symbolInfo.CandidateSymbols.Length) + Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason) + End Sub + End Class End Namespace diff --git a/Src/Compilers/VisualBasic/Test/Semantic/Semantics/SelectCaseTest.vb b/Src/Compilers/VisualBasic/Test/Semantic/Semantics/SelectCaseTest.vb index 28d0da1f7d9..a0ed1807a4c 100644 --- a/Src/Compilers/VisualBasic/Test/Semantic/Semantics/SelectCaseTest.vb +++ b/Src/Compilers/VisualBasic/Test/Semantic/Semantics/SelectCaseTest.vb @@ -567,5 +567,79 @@ BC42016: Implicit conversion from 'Object' to 'Boolean'. ) End Sub + + + Public Sub Bug948019_01() + Dim compilation = CreateCompilationWithMscorlib( + + +) + + Dim node = CompilationUtils.FindBindingText(Of IdentifierNameSyntax)(compilation, "a.vb") + Dim semanticModel = compilation.GetSemanticModel(node.SyntaxTree) + + Dim typeInfo = semanticModel.GetTypeInfo(node) + + Assert.Equal("C.DayOfWeek", typeInfo.Type.ToTestDisplayString()) + Assert.Equal("C.DayOfWeek", typeInfo.ConvertedType.ToTestDisplayString()) + Assert.Equal(ConversionKind.Identity, semanticModel.GetConversion(node).Kind) + + Dim symbolInfo = semanticModel.GetSymbolInfo(node) + + Assert.Equal("day As C.DayOfWeek", symbolInfo.Symbol.ToTestDisplayString()) + Assert.Equal(SymbolKind.Parameter, symbolInfo.Symbol.Kind) + End Sub + + + + Public Sub Bug948019_02() + Dim compilation = CreateCompilationWithMscorlib( + + +) + + Dim node = CompilationUtils.FindBindingText(Of IdentifierNameSyntax)(compilation, "a.vb") + Dim semanticModel = compilation.GetSemanticModel(node.SyntaxTree) + + Dim typeInfo = semanticModel.GetTypeInfo(node) + + Assert.Equal("C.DayOfWeek", typeInfo.Type.ToTestDisplayString()) + Assert.Equal("C.DayOfWeek", typeInfo.ConvertedType.ToTestDisplayString()) + Assert.Equal(ConversionKind.Identity, semanticModel.GetConversion(node).Kind) + + Dim symbolInfo = semanticModel.GetSymbolInfo(node) + + Assert.Equal("day As C.DayOfWeek", symbolInfo.Symbol.ToTestDisplayString()) + Assert.Equal(SymbolKind.Parameter, symbolInfo.Symbol.Kind) + End Sub + End Class End Namespace -- GitLab