diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs index 12ccc00fd3..7f2477feb5 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,22 @@ 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]; + if (!actualReturnType.IsKnownType(KnownTypeCode.Void)) { + 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 +2293,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 +2371,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 +2381,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 +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]; + 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 67766a4c31..d53bcd3cdd 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs @@ -668,5 +668,55 @@ class C Assert.IsFalse(mrr.IsError); Assert.AreEqual("System.Threading.Tasks.Task", mrr.Type.ReflectionName); } + + [Test] + public void ConversionInExplicitlyTypedLambdaBody() { + 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 ConversionInImplicitlyTypedLambdaBody() { + 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); + } + + [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); + } } }