Using xUnit's Assert.Throws, I stumbled upon this (to me) hard to explain overload resolution issue. In xUnit, this method is marked obsolete:
[Obsolete("You must call Assert.ThrowsAsync<T> (and await the result) " +
"when testing async code.", true)]
public static T Throws<T>(Func<Task> testCode) where T : Exception
{ throw new NotImplementedException(); }
The question is, why does an inline statement lambda (or expression) that simply throws an exception resolve to this overload (and therefore doesn't compile)?
using System;
using Xunit;
class Program
{
static void Main(string[] args)
{
// this compiles (of course)
// resolves into the overload accepting an `Action`
Assert.Throws<Exception>(() => ThrowException());
// line below gives error CS0619 'Assert.Throws<T>(Func<Task>)' is obsolete:
// 'You must call Assert.ThrowsAsync<T> (and await the result) when testing async code.'
Assert.Throws<Exception>(() => { throw new Exception(); });
}
static void ThrowException()
{
throw new Exception("Some message");
}
}
I was able to reproduce this, given the function declarations:
static void CallFunction(Action action) { }
static void CallFunction(Func<Task> func) { }
And calling them:
CallFunction(() => ThrowException());
CallFunction(() => { throw new Exception(); });
The second one resolves into CallFunction(Func<Task> func) overload. The weird thing is if I change the body like this:
CallFunction(() => { int x = 1; });
It resolves to CallFunction(Action action) overload.
If the last statement in the body is a throw statement, I guess the compiler thinks method is returning something, and picks the closest -more specific- overload to that scenario which is Func<Task>.
The closest thing I found in the documentation is this:
7.5.2.12 Inferred return type
• If F is async and the body of F is either an expression classified as nothing (§7.1), or a statement block where no return statements have expressions, the inferred return type is System.Threading.Tasks.Task
The function here is a statement block, but it's not async though. Note that I'm not saying this exact rule applies here. Still I'm guessing it's related to this.
This article from Eric Lippert explains it better. (thanks for the comment #Damien_The_Unbeliever).
Here's a complete example which doesn't involve Task, to remove any hint of asynchrony being involved:
using System;
class Program
{
static void Method(Action action)
{
Console.WriteLine("Action");
}
static void Method(Func<int> func)
{
Console.WriteLine("Func<int>");
}
static void ThrowException()
{
throw new Exception();
}
static void Main()
{
// Resolvse to the Action overload
Method(() => ThrowException());
// Resolves to the Func<int> overload
Method(() => { throw new Exception(); });
}
}
Using section numbering from ECMA 334 (5th edition), we're interested in section 12.6.4 - overload resolution. The two important steps are:
Identify applicable methods (12.6.4.2)
Identify the best method (12.6.4.3)
We'll look at each call in turn
Call 1: () => ThrowException()
Let's start with the first call, which has an argument of () => ThrowException(). To check for applicability, we need a conversion from that argument to either Action or Func<int>. We can check that without involving overloading at all:
// Fine
Action action = () => ThrowException();
// Fails to compile:
// error CS0029: Cannot implicitly convert type 'void' to 'int'
// error CS1662: Cannot convert lambda expression to intended delegate type because
// some of the return types in the block are not implicitly convertible to the
// delegate return type
Func<int> func = () => ThrowException();
The CS1662 error is a little unfortunately worded in this case - it's not that there's a return type in the block that's not implicitly convertible to the delegate return type, it's that there isn't a return type in the lambda expression at all. The spec way of preventing this is in section 11.7.1. None of the permitted conversions there work. The closest is this (where F is the lambda expression and D is Func<int>):
If the body of F is an expression, and either F is non-async and D has a non-void return type T, or F is async and D has a return type Task<T>, then when each parameter of F is given the type of the corresponding parameter in D, the body of F is a valid expression (w.r.t §12) that is implicitly convertible to T.
In this case the expression ThrowException is not implicitly convertible to int, hence the error.
All of this means that only the first method is applicable for () => ThrowException(). Our pick for "best function member" is really easy when the set of applicable function members only has a single entry...
Call 2: () => { throw new Exception(); }
Now let's look at the second call, which has () => { throw new Exception(); } as the argument. Let's try the same conversions:
// Fine
Action action = () => { throw new Exception(); };
// Fine
Func<int> func = () => { throw new Exception(); };
Both conversions work here. The latter one works because of this bullet from 11.7.1:
If the body of F is a statement block, and either F is non-async and D has a
non-void return type T, or F is async and D has a return type Task<T>,
then when each parameter of F is given the type of the corresponding parameter in
D, the body of F is a valid statement block (w.r.t §13.3) with a nonreachable
end point in which each return statement specifies an expression that is implicitly
convertible to T.
I realize it sounds odd that this works, but:
The end point of the block is not reachable
There are no return statements, so the condition of "each return statement specifies [...]" is indeed met
To put it another way: you could use that block as the body of a method that's declared to return int.
That means both our methods are applicable in this case.
So which is better?
Now we need to look at section 12.6.4.3 to work out which method will actually be picked.
There are lots of rules here, but the one that decides things here is the conversion from the lambda expression to either Action or Func<int>. That's resolved in 12.6.4.4 (better conversion from expression):
Given an implicit conversion C1 that converts from an expression E to a type T1, and an implicit conversion C2 that converts from an expression E to a type T2, C1 is a better conversion than C2 if at least one of the following holds:
...
E is an anonymous function, T1 is either a delegate type D1 or an expression tree
type Expression<D1>, T2 is either a delegate type D2 or an expression tree type Expression<D2> and
one of the following holds:
D1 is a better conversion target than D2
D1 and D2 have identical parameter lists, and one of the following holds:
D1 has a return type Y1, and D2 has a return type Y2, an inferred return type X exists for E in the context of that parameter list (§12.6.3.13), and the conversion from X to Y1 is better than the conversion from X to Y2
E is async [... - skipped because it's not]
D1 has a return type Y, and D2 is void returning
The part I've put in bold is the important bit. When you consider the following scenario:
E is () => { throw new Exception(); }
T1 is Func<int> (so D1 is Func<int> too)
T2 is Action (so D2 is Action too)
... then both D1 and D2 have empty parameter lists, but D1 has a return type int, and D2 is void returning.
Therefore the conversion to Func<int> is better than the conversion to Action... which means that Method(Action) is a better function member than Member(Func<int>) for the second call.
Phew! Don't you just love overload resolution?
Related
Having these three methods available in Rx.NET library
public static IObservable<TResult> Create<TResult>(Func<IObserver<TResult>, CancellationToken, Task> subscribeAsync) {...}
public static IObservable<TResult> Create<TResult>(Func<IObserver<TResult>, CancellationToken, Task<IDisposable>> subscribeAsync) {...}
public static IObservable<TResult> Create<TResult>(Func<IObserver<TResult>, CancellationToken, Task<Action>> subscribeAsync) {...}
I write the following sample code in MSVS 2013:
var sequence =
Observable.Create<int>( async ( observer, token ) =>
{
while ( true )
{
token.ThrowIfCancellationRequested();
await Task.Delay( 100, token );
observer.OnNext( 0 );
}
} );
This does not compile due to ambiguous overloads. Exact output from the compiler being:
Error 1 The call is ambiguous between the following methods or properties:
'System.Reactive.Linq.Observable.Create<int>(System.Func<System.IObserver<int>,System.Threading.CancellationToken,System.Threading.Tasks.Task<System.Action>>)'
and
'System.Reactive.Linq.Observable.Create<int>(System.Func<System.IObserver<int>,System.Threading.CancellationToken,System.Threading.Tasks.Task>)'
However as soon as I replace while( true ) with while( false ) or with var condition = true; while( condition )...
var sequence =
Observable.Create<int>( async ( observer, token ) =>
{
while ( false ) // It's the only difference
{
token.ThrowIfCancellationRequested();
await Task.Delay( 100, token );
observer.OnNext( 0 );
}
} );
the error disappears and method call resolves to this:
public static IObservable<TResult> Create<TResult>(Func<IObserver<TResult>, CancellationToken, Task> subscribeAsync) {...}
What is going on there?
This is a fun one :) There are multiple aspects to it. To start with, let's simplify it very significantly by removing Rx and actual overload resolution from the picture. Overload resolution is handled at the very end of the answer.
Anonymous function to delegate conversions, and reachability
The difference here is whether the end-point of the lambda expression is reachable. If it is, then that lambda expression doesn't return anything, and the lambda expression can only be converted to a Func<Task>. If the end-point of the lambda expression isn't reachable, then it can be converted to any Func<Task<T>>.
The form of the while statement makes a difference because of this part of the C# specification. (This is from the ECMA C# 5 standard; other versions may have slightly different wording for the same concept.)
The end point of a while statement is reachable if at least one of the following is true:
The while statement contains a reachable break statement that exits the while statement.
The while statement is reachable and the Boolean expression does not have the constant value true.
When you have a while (true) loop with no break statements, neither bullet is true, so the end point of the while statement (and therefore the lambda expression in your case) is not reachable.
Here's a short but complete example without any Rx involved:
using System;
using System.Threading.Tasks;
public class Test
{
static void Main()
{
// Valid
Func<Task> t1 = async () => { while(true); };
// Valid: end of lambda is unreachable, so it's fine to say
// it'll return an int when it gets to that end point.
Func<Task<int>> t2 = async () => { while(true); };
// Valid
Func<Task> t3 = async () => { while(false); };
// Invalid
Func<Task<int>> t4 = async () => { while(false); };
}
}
We can simplify even further by removing async from the equation. If we have a synchronous parameterless lambda expression with no return statements, that's always convertible to Action, but it's also convertible to Func<T> for any T if the end of the lambda expression isn't reachable. Slight change to the above code:
using System;
public class Test
{
static void Main()
{
// Valid
Action t1 = () => { while(true); };
// Valid: end of lambda is unreachable, so it's fine to say
// it'll return an int when it gets to that end point.
Func<int> t2 = () => { while(true); };
// Valid
Action t3 = () => { while(false); };
// Invalid
Func<int> t4 = () => { while(false); };
}
}
We can look at this in a slightly different way by removing delegates and lambda expressions from the mix. Consider these methods:
void Method1()
{
while (true);
}
// Valid: end point is unreachable
int Method2()
{
while (true);
}
void Method3()
{
while (false);
}
// Invalid: end point is reachable
int Method4()
{
while (false);
}
Although the error method for Method4 is "not all code paths return a value" the way this is detected is "the end of the method is reachable". Now imagine those method bodies are lambda expressions trying to satisfy a delegate with the same signature as the method signature, and we're back to the second example...
Fun with overload resolution
As Panagiotis Kanavos noted, the original error around overload resolution isn't reproducible in Visual Studio 2017. So what's going on? Again, we don't actually need Rx involved to test this. But we can see some very odd behavior. Consider this:
using System;
using System.Threading.Tasks;
class Program
{
static void Foo(Func<Task> func) => Console.WriteLine("Foo1");
static void Foo(Func<Task<int>> func) => Console.WriteLine("Foo2");
static void Bar(Action action) => Console.WriteLine("Bar1");
static void Bar(Func<int> action) => Console.WriteLine("Bar2");
static void Main(string[] args)
{
Foo(async () => { while (true); });
Bar(() => { while (true) ; });
}
}
That issues a warning (no await operators) but it compiles with the C# 7 compiler. The output surprised me:
Foo1
Bar2
So the resolution for Foo is determining that the conversion to Func<Task> is better than the conversion to Func<Task<int>>, whereas the resolution for Bar is determining that the conversion to Func<int> is better than the conversion to Action. All the conversions are valid - if you comment out the Foo1 and Bar2 methods, it still compiles, but gives output of Foo2, Bar1.
With the C# 5 compiler, the Foo call is ambiguous by the Bar call resolves to Bar2, just like with the C# 7 compiler.
With a bit more research, the synchronous form is specified in 12.6.4.4 of the ECMA C# 5 specification:
C1 is a better conversion than C2 if at least one of the following holds:
...
E is an anonymous function, T1 is either a delegate type D1 or an expression tree type Expression, T2 is either a delegate type D2 or an expression tree type Expression and one of the following holds:
D1 is a better conversion target than D2 (irrelevant for us)
D1 and D2 have identical parameter lists, and one of the following holds:
D1 has a return type Y1, and D2 has a return type Y2, an inferred return type X exists for E in the context of that parameter list (§12.6.3.13), and the conversion from X to Y1 is better than the conversion from X to Y2
E is async, D1 has a return type Task<Y1>, and D2 has a return type Task<Y2>, an inferred return type Task<X> exists for E in the context of that parameter list (§12.6.3.13), and the conversion from X to Y1 is better than the conversion from X to Y2
D1 has a return type Y, and D2 is void returning
So that makes sense for the non-async case - and it also makes sense for how the C# 5 compiler isn't able to resolve the ambiguity, because those rules don't break the tie.
We don't have a full C# 6 or C# 7 specification yet, but there's a draft one available. Its overload resolution rules are expressed somewhat differently, and the change may be there somewhere.
If it's going to compile to anything though, I'd expect the Foo overload accepting a Func<Task<int>> to be chosen over the overload accepting Func<Task> - because it's a more specific type. (There's a reference conversion from Func<Task<int>> to Func<Task>, but not vice versa.)
Note that the inferred return type of the lambda expression would just be Func<Task> in both the C# 5 and draft C# 6 specifications.
Ultimately, overload resolution and type inference are really hard bits of the specification. This answer explains why the while(true) loop makes a difference (because without it, the overload accepting a func returning a Task<T> isn't even applicable) but I've reached the end of what I can work out about the choice the C# 7 compiler makes.
In addition to the answer from #Daisy Shipton I'd like to add that the same behavior can be observed in the following case, too:
var sequence = Observable.Create<int>(
async (observer, token) =>
{
throw new NotImplementedException();
});
basically because of the same reason - the compiler sees that the lambda function never returns so any return type would match, which in turn makes the lambda match any of the Observable.Create overloads.
And, finally, an example of simple solution: you can cast the lambda to the desired signature type to hint the compiler which Rx overload to choose.
var sequence =
Observable.Create<int>(
(Func<IObserver<int>, CancellationToken, Task>)(async (observer, token) =>
{
throw new NotImplementedException();
})
);
I have this issue:
Func<string,string> transformer = isRTF ? ToRTF : ToHTML;
private string ToRTF(string value) {
//Convert to RTF
return value;
}
private string ToHTML(string value) {
//Convert to HTML
return value;
}
However I am getting this error:
Error 42 Type of conditional expression cannot be determined because there is no implicit conversion between 'method group' and 'method group'
However if I do this:
Func<string, string> transformer = isRTF ? (Func<string, string>) ToRTF : (Func<string, string>) ToHTML;
it works without problems and ReSharper starts complaining that the cast is redundant.
Does anyone know why this is happening?
This is because both sides need a conversion from method group* to Func<string,string>. The compiler has rules to infer the type of one method group from the type given to the other method group, but no rules for situations when both sides of : have method groups.
You can do the conversion only on one side, and let the compiler infer the other side for you. You can also use var for the declaration to avoid repeating the type:
var transformer = isRTF ? new Func<string,string>(ToRTF) : ToHTML;
* Method name used in implicit definitions of delegates are treated as method groups, because a single name can represent multiple overloaded methods.
I know this question is answered and I think the answer is quite good and correct. Nevertheless I encountered this same problem a while ago and what I did to work around this was to return Func from the method itself. Like the following:
private static Func<string,string> A() => (v) => string.Empty;
private static Func<string,string> B() => (v) => "I am not empty =)";
And:
var myFunc = someBool ? A() : B();
I know that this will require to change method's signature and that do not solves the issue directly but at least you do not need to cast.
Hope this helps
The screenshot says it pretty much.
I have the overloads as seen in the screenshot. When using a string as second parameter the compiler should figure out that the first argument can only be a Func and not an expression.
But the compiler throws an error saying 'A lamda expression with a statement body cannot be converted to an expression tree'.
Why can't the compiler figure out the correct overload?
Explicit cast does not help. What works is when i make a local variable of type Func and then use this instead.
The framework used is FakeItEasy 1.24.0
EDIT:
Here is the code that shows the behavior:
public static void Main(string[] args)
{
//compiler error
A.CallTo(() => Main(A<string[]>.That.Matches(strings =>
{
return true;
}, "description")));
//compiles
Func<string[], bool> predicate = strings =>
{
return true;
};
A.CallTo(() => Main(A<string[]>.That.Matches(predicate, "description")));
Console.ReadLine();
}
The issue is not in the call to Matches. It's in the call to CallTo, which expects an Expression<Action>.
Apparently an Expression not only can't be a lambda expression with a statement body, it also can't contain a lambda expression with a statement body.
(I'm not sure whether your "put the lambda in a local variable" solution will work or whether it just tricks the compiler and will fail at runtime.)
Here's the test I put together:
static void Overloaded(Action a, string param) { }
static void Overloaded(Expression<Action> e) { }
static void CallToAction(Action a) { }
static void CallToExprAc(Expression<Action> a) { }
static void Main(string[] args)
{
// Works
CallToAction(() => Overloaded(() => { int i = 5; }, "hi"));
// Doesn't work - using the Expression overload
CallToAction(() => Overloaded(() => { int i = 5; }));
// Doesn't work - wrapped in an outer Expression
CallToExprAc(() => Overloaded(() => { int i = 5; }, "hi"));
}
Whether your "put the expression-bodied lambda in a local" works is up to how FakeItEasy is implemented. I suspect it'll work here, but something similar in e.g. LINQ-to-SQL wouldn't - it'd just fail at runtime rather than at compile time.
I'm not sure whether this is a compiler bug, a spec bug or desirable behaviour. In section 6.5 of the C# spec we have
Certain lambda expressions cannot be converted to expression tree types: Even though the conversion exists, it fails at compile-time. This is the case if the lambda expression:
• Has a block body
• Contains simple or compound assignment operators
• Contains a dynamically bound expression
• Is async
which doesn't say "contains a lambda expression that cannot be converted to an expression tree type".
I was implementing sync/async overloads when I came across this peculiar situation:
When I have a regular lambda expression without parameters or a return value it goes to the Run overload with the Action parameter, which is predictable. But when that lambda has a while (true) in it it goes to the overload with the Func parameter.
public void Test()
{
Run(() => { var name = "bar"; });
Run(() => { while (true) ; });
}
void Run(Action action)
{
Console.WriteLine("action");
}
void Run(Func<Task> func) // Same behavior with Func<T> of any type.
{
Console.WriteLine("func");
}
Output:
action
func
So, how can that be? Is there a reason for it?
So to start with, the first expression can only possibly call the first overload. It is not a valid expression for a Func<Task> because there is a code path that returns an invalid value (void instead of Task).
() => while(true) is actually a valid method for either signature. (It, along with implementations such as () => throw new Expression(); are valid bodies of methods that return any possible type, including void, an interesting point of trivia, and why auto generated methods from an IDE typically just throw an exception; it'll compile regardless of the signature of the method.) A method that loops infinitely is a method in which there are no code paths that don't return the correct value (and that's true whether the "correct value" is void, Task, or literally anything else). This is of course because it never returns a value, and it does so in a way that the compiler can prove. (If it did so in a way that the compiler couldn't prove, as it hasn't solved the halting problem after all, then we'd be in the same boat as A.)
So, for our infinite loop, which is better, given that both overload are applicable. This brings us to our betterness section of the C# specs.
If we go to section 7.4.3.3, bullet 4, we see:
If E is an anonymous function, T1 and T2 are delegate types or expression tree types with identical parameter lists, and an inferred return type X exists for E in the context of that parameter list (§7.4.2.11):
[...]
if T1 has a return type Y, and T2 is void returning, then C1 is the better conversion.
So when converting from an anonymous delegate, which is what we're doing, it will prefer the conversion that returns a value over one that is void, so it chooses Func<Task>.
I was playing around with a hobby project when I came across a type-inference error I didn't understand. I have simplified it to the following trivial example.
I have the following classes and functions:
class Foo { }
class Bar { }
class Baz { }
static T2 F<T1, T2>(Func<T1, T2> f) { return default(T2); }
static T3 G<T1, T2, T3>(Func<T1, Func<T2, T3>> f) { return default(T3); }
Now consider the following examples:
// 1. F with explicit type arguments - Fine
F<Foo, Bar>(x => new Bar());
// 2. F with implicit type arguments - Also fine, compiler infers <Foo, Bar>
F((Foo x) => new Bar());
// 3. G with explicit type arguments - Still fine...
G<Foo, Bar, Baz>(x => y => new Baz());
// 4. G with implicit type arguments - Bang!
// Compiler error: Type arguments cannot be inferred from usage
G((Foo x) => (Bar y) => new Baz());
The last example produces a compiler error, but it seems to me that it should be able to infer the type arguments without any problems.
QUESTION: Why can't the compiler infer <Foo, Bar, Baz> in this case?
UPDATE: I have discovered that simply wrapping the second lambda in an identity function will cause the compiler to infer all the types correctly:
static Func<T1, T2> I<T1, T2>(Func<T1, T2> f) { return f; }
// Infers G<Foo, Bar, Baz> and I<Bar, Baz>
G((Foo x) => I((Bar y) => new Baz()));
Why can it do all the individual steps perfectly, but not the whole inference at once? Is there some subtlety in the order that the compiler analyses implicit lambda types and implicit generic types?
Because the algorithm as described in the C# specification doesn’t succeed in this case. Let’s look at the specification in order to see why this is.
The algorithm description is long and complicated, so I’ll heavily abbreviate this.
The relevant types mentioned in the algorithm have the following values for you:
Eᵢ = the anonymous lambda (Foo x) => (Bar y) => new Baz()
Tᵢ = the parameter type (Func<T1, Func<T2, T3>>)
Xᵢ = the three generic type parameters (T1, T2, T3)
Firstly, there’s the first phase, which in your case does only one thing:
7.5.2.1 The first phase
For each of the method arguments Eᵢ (in your case, there’s only one, the lambda):
If Eᵢ is an anonymous function [it is], an explicit parameter type inference (§7.5.2.7) is made from Eᵢ to Tᵢ
Otherwise, [not relevant]
Otherwise, [not relevant]
Otherwise, no inference is made for this argument.
I’ll skip the details of the explicit parameter type inference here; it suffices to say that for the call G((Foo x) => (Bar y) => new Baz()), it infers that T1 = Foo.
Then comes the second phase, which is effectively a loop that tries to narrow down the type of each generic type parameter until it either finds all of them or gives up. The one important bullet point is the last one:
7.5.2.2 The second phase
The second phase proceeds as follows:
[...]
Otherwise, for all arguments Eᵢ with corresponding parameter type Tᵢ where the output types (§7.5.2.4) contain unfixed type variables Xj but the input types (§7.5.2.3) do not, an output type inference (§7.5.2.6) is made from Eᵢ to Tᵢ. Then the second phase is repeated.
[Translated and applied to your case, this means:
Otherwise, if the return type of the delegate (i.e. Func<T2,T3>) contains an as yet undetermined type variable (it does) but its parameter types (i.e. T1) do not (they do not, we already know that T1 = Foo), an output type inference (§7.5.2.6) is made.]
The output type inference now proceeds as follows; again, only one bullet point is relevant, this time it’s the first one:
7.5.2.6 Output type inferences
An output type inference is made from an expression E to a type T in the following way:
If E is an anonymous function [it is] with inferred return type U (§7.5.2.12) and T is a delegate type or expression tree type with return type Tb, then a lower-bound inference (§7.5.2.9) is made from U to Tb.
Otherwise, [rest snipped]
The “inferred return type” U is the anonymous lambda (Bar y) => new Baz() and Tb is Func<T2,T3>. Cue lower-bound inference.
I don’t think I need to quote the entire lower-bound inference algorithm now (it’s long); it is enough to say that it doesn’t mention anonymous functions. It takes care of inheritance relationships, interface implementations, array covariance, interface and delegate co-/contravariance, ... but not lambdas. Therefore, its last bullet point applies:
Otherwise, no inferences are made.
Then we come back to the second phase, which gives up because no inferences have been made for T2 and T3.
Moral of the story: the type inference algorithm is not recursive with lambdas. It can only infer types from the parameter and return types of the outer lambda, not lambdas nested inside of it. Only lower-bound inference is recursive (so that it can take nested generic constructions like List<Tuple<List<T1>, T2>> apart) but neither output type inferences (§7.5.2.6) nor explicit parameter type inferences (§7.5.2.7) are recursive and are never applied to inner lambdas.
Addendum
When you add a call to that identify function I:
G((Foo x) => I((Bar y) => new Baz()));
then type inference is first applied to the call to I, which results in I’s return type being inferred as Func<Bar, Baz>. Then the “inferred return type” U of the outer lambda is the delegate type Func<Bar, Baz> and Tb is Func<T2, T3>. Thus lower-bound inference will succeed because it will be faced with two explicit delegate types (Func<Bar, Baz> and Func<T2, T3>) but no anonymous functions/lambdas. This is why the identify function makes it succeed.
The lambda cannot be inferred what it's return type is since it is not assigned and cannot be determined by the compiler.
Check out this link on how lambdas return types are determined by the compiler.
If you would have haved:
Func<Bar, Baz> f = (Bar y) => new Baz();
G((Foo x) => f);
then the compiler would have been able to calculate the return type of the lambda based on what it is assigned to, but since now it is not assigned to anything the compiler struggles to determine what the return type for (Bar y) => new Baz(); would be.
For the compiler, a lambda function is distinct from a Func, i.e. using a lambda function for a Func implies a type conversion. The compiler does not do "nested" type conversions when specializing generics. That, however, would be required in your example:
Type of (Foo x) => (Bar y) => new Baz () is lambda (Foo, lambda (Bar, Baz)), but Func (T1, Func (T2, T3)) would be required, i.e. two conversions, which are nested.