-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Function pointer bug fixes #45473
Function pointer bug fixes #45473
Conversation
ref arguments, | ||
ref argRefKinds); | ||
|
||
Debug.Assert(arguments.IsDefault && argRefKinds.IsDefault && receiver.Kind == BoundKind.TypeExpression); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
receiver.Kind == BoundKind.TypeExpression [](start = 77, length = 41)
What is this type? #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made the var
explicit and added some more verification of the remapped method.
In reply to: 445955503 [](ancestors = 445955503)
@@ -1303,6 +1303,30 @@ public override BoundNode VisitDelegateCreationExpression(BoundDelegateCreationE | |||
return base.VisitDelegateCreationExpression(node); | |||
} | |||
|
|||
public override BoundNode VisitFunctionPointerLoad(BoundFunctionPointerLoad node) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
VisitFunctionPointerLoad [](start = 34, length = 24)
Did you check other places where we override VisitDelegateCreationExpression to confirm that we don't need to add VisitFunctionPointerLoad? We probably have several visitors that introduce virtual methods with names like that. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've taken a look. I'll add an override in MethodToClassRewriter
, but I can't find a case that it will actually change, as other than this it's only used for iterator and async method rewriting. Since we don't allow you to refer to the compiler-generated underlying methods of these from source, there's nothing that we can test. If we add a new thing that gets remapped in the future, though, it will function as expected.
In reply to: 445956108 [](ancestors = 445956108)
delegate*<void> a = &local; | ||
a(); | ||
|
||
static void local() => System.Console.Write(""local""); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding a test where the contents of this method body exist within a lambda expression. Verifying the rewriting works in a nested environment. #Resolved
Done with review pass (iteration 3) #Closed |
* Additional tests for nested function contexts. * Override VisitFunctionPointerLoad in MethodToClassRewriter. * Adjust debug asserts.
@AlekseyTs addressed feedback. This PR now addresses an additional issue I found when testing locally, where an In reply to: 649949098 [](ancestors = 649949098) |
if (used) | ||
{ | ||
_builder.EmitOpCode(ILOpCode.Ldftn); | ||
EmitSymbolToken(load.TargetMethod, load.Syntax, optArgList: null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EmitSymbolToken(load.TargetMethod, load.Syntax, optArgList: null); [](start = 16, length = 66)
Can this have a side effect, for example an exception? Is this conditional handling consistent with what we do for delegate creation? I.e. if a delegate instance is not used, are we not loading the address of a target method? #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I hadn't fixed the remapped local function bug, it would have an effect, but the only effect from this I could see now is if a tree-trimming algorithm decides the referenced method isn't used (which it isn't) and decides to remove it. However, when I implemented this I checked our handling for delegates:
static void M()
{
System.Action a = M;
}
produces this IL in release mode:
.method private hidebysig static
void M () cil managed
{
// Method begins at RVA 0x2050
// Code size 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method C::M
In reply to: 446421466 [](ancestors = 446421466)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My intuition was that the tree trimming aspect was fine, and likely desired. The fact that it lines up with delegate
behavior makes me feel good about this outcome.
if (used) | ||
{ | ||
_builder.EmitOpCode(ILOpCode.Ldftn); | ||
EmitSymbolToken(load.TargetMethod, load.Syntax, optArgList: null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My intuition was that the tree trimming aspect was fine, and likely desired. The fact that it lines up with delegate
behavior makes me feel good about this outcome.
@@ -506,6 +506,11 @@ public override BoundNode VisitDelegateCreationExpression(BoundDelegateCreationE | |||
return node.Update(rewrittenArgument, method, node.IsExtensionMethod, type); | |||
} | |||
|
|||
public override BoundNode VisitFunctionPointerLoad(BoundFunctionPointerLoad node) | |||
{ | |||
return node.Update(VisitMethodSymbol(node.TargetMethod), node.Type); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
node.Type [](start = 69, length = 9)
It looks like we should also visit type. #Closed
Done with review pass (iteration 5) #Closed |
@AlekseyTs addressed feedback. In reply to: 650448547 [](ancestors = 650448547) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM (iteration 6), assuming CI is passing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Auto-approval
Fixes a couple of function pointer bugs:
ldftn
instruction, and corrects handling of non-static local functions. This fixes Address of local function not working #45447.@dotnet/roslyn-compiler @AlekseyTs for review.