From 4380297cceaaae42856ab0f198d4923f0b7e8470 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20K=C3=A4ll=C3=A9n?= Date: Tue, 26 Feb 2013 23:37:18 +0100 Subject: [PATCH 1/3] Add a ConversionResolveResult to lambda body expressions, if required --- .../Resolver/ResolveVisitor.cs | 24 +++++++++++++---- .../CSharp/Resolver/LambdaTests.cs | 26 +++++++++++++++++++ 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs index 12ccc00fd3..221c2c54d8 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs @@ -2000,6 +2000,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver CSharpResolver storedContext; ResolveVisitor visitor; AstNode body; + ResolveResult bodyRR; IType inferredReturnType; IList returnExpressions; @@ -2024,12 +2025,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public override ResolveResult Body { get { + if (bodyRR != null) + return bodyRR; + if (body is Expression) { Analyze(); - if (returnValues.Count == 1) - return returnValues[0]; + if (returnValues.Count == 1) { + bodyRR = returnValues[0]; + var conv = storedContext.conversions.ImplicitConversion(bodyRR, actualReturnType); + if (!conv.IsIdentityConversion) + bodyRR = new ConversionResolveResult(actualReturnType, bodyRR, conv, storedContext.CheckForOverflow); + return bodyRR; + } } - return visitor.voidResult; + return bodyRR = visitor.voidResult; } } @@ -2282,7 +2291,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return h; } ResolveVisitor visitor = new ResolveVisitor(storedContext, unresolvedFile); - var newHypothesis = new LambdaTypeHypothesis(this, parameterTypes, visitor, lambda != null ? lambda.Parameters : null); + var newHypothesis = new LambdaTypeHypothesis(this, parameterTypes, visitor, lambda != null ? lambda.Parameters : null, storedContext); hypotheses.Add(newHypothesis); return newHypothesis; } @@ -2360,6 +2369,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver readonly IParameter[] lambdaParameters; internal readonly IType[] parameterTypes; readonly ResolveVisitor visitor; + readonly CSharpResolver storedContext; internal readonly IType inferredReturnType; IList returnExpressions; @@ -2369,13 +2379,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver internal bool success; public LambdaTypeHypothesis(ImplicitlyTypedLambda lambda, IType[] parameterTypes, ResolveVisitor visitor, - ICollection parameterDeclarations) + ICollection parameterDeclarations, CSharpResolver storedContext) { Debug.Assert(parameterTypes.Length == lambda.Parameters.Count); this.lambda = lambda; this.parameterTypes = parameterTypes; this.visitor = visitor; + this.storedContext = storedContext; visitor.SetNavigator(this); Log.WriteLine("Analyzing " + ToString() + "..."); @@ -2454,6 +2465,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver lambda.parameters = lambdaParameters; // replace untyped parameters with typed parameters if (lambda.BodyExpression is Expression && returnValues.Count == 1) { lambda.bodyResult = returnValues[0]; + var conv = storedContext.conversions.ImplicitConversion(lambda.bodyResult, returnType); + if (!conv.IsIdentityConversion) + lambda.bodyResult = new ConversionResolveResult(returnType, lambda.bodyResult, conv, storedContext.CheckForOverflow); } Log.WriteLine("Applying return type {0} to implicitly-typed lambda {1}", returnType, lambda.LambdaExpression); diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs index 67766a4c31..0c59016623 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs @@ -668,5 +668,31 @@ class C Assert.IsFalse(mrr.IsError); Assert.AreEqual("System.Threading.Tasks.Task", mrr.Type.ReflectionName); } + + [Test] + public void ConversionInExplicitLambdaResult() { + string program = @"using System; +class Test { + public object M() { + System.Func f = $(int i) => null$; + } +}"; + var rr = Resolve(program); + Assert.IsInstanceOf(rr.Body); + Assert.That(((ConversionResolveResult)rr.Body).Conversion.IsNullLiteralConversion); + } + + [Test] + public void ConversionInImplicitLambdaResult() { + string program = @"using System; +class Test { + public object M() { + System.Func f = $i => null$; + } +}"; + var rr = Resolve(program); + Assert.IsInstanceOf(rr.Body); + Assert.That(((ConversionResolveResult)rr.Body).Conversion.IsNullLiteralConversion); + } } } From 2978af440e3d8d5c28bd0abcaea1e2d6b90f25b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20K=C3=A4ll=C3=A9n?= Date: Wed, 27 Feb 2013 00:00:07 +0100 Subject: [PATCH 2/3] No conversions in body for void lambdas --- .../Resolver/ResolveVisitor.cs | 16 +++++++---- .../CSharp/Resolver/LambdaTests.cs | 28 +++++++++++++++++-- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs index 221c2c54d8..267d061bbb 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs @@ -2032,9 +2032,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver Analyze(); if (returnValues.Count == 1) { bodyRR = returnValues[0]; - var conv = storedContext.conversions.ImplicitConversion(bodyRR, actualReturnType); - if (!conv.IsIdentityConversion) - bodyRR = new ConversionResolveResult(actualReturnType, bodyRR, conv, storedContext.CheckForOverflow); + if (!actualReturnType.Equals(SpecialType.UnknownType)) { + var conv = storedContext.conversions.ImplicitConversion(bodyRR, actualReturnType); + if (!conv.IsIdentityConversion) + bodyRR = new ConversionResolveResult(actualReturnType, bodyRR, conv, storedContext.CheckForOverflow); + } return bodyRR; } } @@ -2465,9 +2467,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver lambda.parameters = lambdaParameters; // replace untyped parameters with typed parameters if (lambda.BodyExpression is Expression && returnValues.Count == 1) { lambda.bodyResult = returnValues[0]; - var conv = storedContext.conversions.ImplicitConversion(lambda.bodyResult, returnType); - if (!conv.IsIdentityConversion) - lambda.bodyResult = new ConversionResolveResult(returnType, lambda.bodyResult, conv, storedContext.CheckForOverflow); + if (!returnType.IsKnownType(KnownTypeCode.Void)) { + var conv = storedContext.conversions.ImplicitConversion(lambda.bodyResult, returnType); + if (!conv.IsIdentityConversion) + lambda.bodyResult = new ConversionResolveResult(returnType, lambda.bodyResult, conv, storedContext.CheckForOverflow); + } } Log.WriteLine("Applying return type {0} to implicitly-typed lambda {1}", returnType, lambda.LambdaExpression); diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs index 0c59016623..178f525a97 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs @@ -670,7 +670,7 @@ class C } [Test] - public void ConversionInExplicitLambdaResult() { + public void ConversionInExplicitlyTypedLambdaBody() { string program = @"using System; class Test { public object M() { @@ -683,7 +683,7 @@ class Test { } [Test] - public void ConversionInImplicitLambdaResult() { + public void ConversionInImplicitlyTypedLambdaBody() { string program = @"using System; class Test { public object M() { @@ -694,5 +694,29 @@ class Test { Assert.IsInstanceOf(rr.Body); Assert.That(((ConversionResolveResult)rr.Body).Conversion.IsNullLiteralConversion); } + + [Test] + public void NoConversionInVoidExplicitlyTypedLambdaBody() { + string program = @"using System; +class Test { + public object M() { + System.Action f = $(int i) => i++$; + } +}"; + var rr = Resolve(program); + Assert.IsInstanceOf(rr.Body); + } + + [Test] + public void NoConversionInVoidImplicitlyTypedLambdaBody() { + string program = @"using System; +class Test { + public object M() { + System.Action f = $i => i++$; + } +}"; + var rr = Resolve(program); + Assert.IsInstanceOf(rr.Body); + } } } From 0e76cae70d5a35f7eadda9d414d2fca08be7dbc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20K=C3=A4ll=C3=A9n?= Date: Wed, 27 Feb 2013 00:06:34 +0100 Subject: [PATCH 3/3] Fixed stupid thing in the "no conversion in void lambda" test. --- ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs | 2 +- ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs index 267d061bbb..7f2477feb5 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs @@ -2032,7 +2032,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver Analyze(); if (returnValues.Count == 1) { bodyRR = returnValues[0]; - if (!actualReturnType.Equals(SpecialType.UnknownType)) { + if (!actualReturnType.IsKnownType(KnownTypeCode.Void)) { var conv = storedContext.conversions.ImplicitConversion(bodyRR, actualReturnType); if (!conv.IsIdentityConversion) bodyRR = new ConversionResolveResult(actualReturnType, bodyRR, conv, storedContext.CheckForOverflow); diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs index 178f525a97..d53bcd3cdd 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs @@ -700,7 +700,7 @@ class Test { string program = @"using System; class Test { public object M() { - System.Action f = $(int i) => i++$; + System.Action f = $(int i) => i++$; } }"; var rr = Resolve(program);