Disable 'use local function' in a few important language cases.#23136
Conversation
|
Tagging @dotnet/roslyn-ide @Pilchie . |
|
Note: this fixes all of the cases from #22672 except for this one: using System;
class Enclosing<T>
{
delegate T MyDelegate(T t);
static void Callee(MyDelegate d) => d(default);
public class Class<T>
{
public void Caller()
{
MyDelegate local = x => x;
Callee(local);
}
}
}We will still offer the feature here, which will produce the broken code: using System;
class Enclosing<T>
{
delegate T MyDelegate(T t);
static void Callee(MyDelegate d) => d(default);
public class Class<T>
{
public void Caller()
{
T local(T x) => x;
Callee(local);
}
}
}The reason this is broken is that The reason i didn't fix this was that it seemed like a pretty unlikely case. Reusing the same type parameter name is highly discouraged in C# (the compiler even reports a warning for this). As such, most people will gives these non conflicting names, and the change will be fine. If this is felt to be important enough to fix, it will take medium effort to fix. Specifically, the analysis code will have to see which type parameters were captured in the parameter and return type of the lambda. It will then have to see if, from the replacement location, the names of those type parameters bind back to that type parameter and not to some other type in scope (like another nested type, or a method/class type parameter, etc.). |
| delegateType.DelegateInvokeMethod == null) | ||
| { | ||
| return; | ||
| } |
There was a problem hiding this comment.
this code was already here. i just swapped it with the complex check which now comes afterwards.
| } | ||
|
|
||
| var convertedType = semanticModel.GetTypeInfo(nodeToCheck, cancellationToken).ConvertedType; | ||
| if (convertedType == null || !convertedType.IsDelegateType()) |
There was a problem hiding this comment.
i prefer this to if (convertedType?.IsDelegateType() != true).
There was a problem hiding this comment.
💡 IsDelegateType() is an extension method which handles null internally. The null check here is unnecessary.
Let's just file this as a follow-up bug. |
sharwell
left a comment
There was a problem hiding this comment.
💡 Consider filing follow-up issues for remaining cases. They are lower priority, but often these are good candidates for new contributors since we can point them at an example of a similar feature already implemented.
| } | ||
|
|
||
| var convertedType = semanticModel.GetTypeInfo(nodeToCheck, cancellationToken).ConvertedType; | ||
| if (convertedType == null || !convertedType.IsDelegateType()) |
There was a problem hiding this comment.
💡 IsDelegateType() is an extension method which handles null internally. The null check here is unnecessary.
| { | ||
| public void Caller() | ||
| { | ||
| MyDelegate [||]local = x => x; |
There was a problem hiding this comment.
💡 Would be good to file a follow-up issue (feature request) to handle the case where the only member access is Invoke.
|
@CyrusNajmabadi Let me know when you have seen the feedback above and I'll move it forward after you are done with any changes you wanted to make. |
Simplify check.
|
Have made the code change. Feel free to do what you want now :) |
|
Thanks, @CyrusNajmabadi :) |
|
Any time! |
Fixes #23118
Fixes #22672