-
-
Notifications
You must be signed in to change notification settings - Fork 672
Fix Issue 21288 & 10886 - incorrect this pointer #14969
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1155,6 +1155,69 @@ L1: | |
| return e1; | ||
| } | ||
|
|
||
| /* | ||
| * Check whether `outerFunc` and `calledFunc` have the same `this`. | ||
| * If `calledFunc` is the member of a base class of the class that contains | ||
| * `outerFunc` we consider that they have the same this. | ||
| * | ||
| * This function is used to test whether `this` needs to be prepended to | ||
| * a function call or function symbol. For example: | ||
| * | ||
| * struct X | ||
| * { | ||
| * void gun() {} | ||
| * } | ||
| * struct A | ||
| * { | ||
| * void fun() {} | ||
| * void sun() | ||
| * { | ||
| * fun(); | ||
| * X.gun(); // error | ||
| * } | ||
| * } | ||
| * | ||
| * When `fun` is called, `outerfunc` = `sun` and `calledFunc = `fun`. | ||
| * `sun` is a member of `A` and `fun` is also a member of `A`, therefore | ||
| * `this` can be prepended to `fun`. When `gun` is called (it will result | ||
| * in an error, but that is not relevant here), which is a member of `X`, | ||
| * no `this` is needed because the outer function does not have the same | ||
| * `this` as `gun`. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But it will fail anyway because X.gun() does not supply a |
||
| * | ||
| * Returns: | ||
| * `true` if outerFunc and calledFunc may use the same `this` pointer. | ||
| * `false` otherwise. | ||
| */ | ||
| private bool haveSameThis(FuncDeclaration outerFunc, FuncDeclaration calledFunc) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function doesn't look right. The logic in the function is surprisingly complex (many branches). I would expect
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Initially, I thought the fix is easy. I thought it would suffice to make sure that the this of the function containing the call and the this of the function being called are the same, however that does not cut it for derived member functions. Later on, I noticed that for nested functions there is some extra engineering done to get the right this. That's when I ended up with this function. I suspect that there are other places where this function might be used. I don't think it can be made any simpler than that, but I am confident that what is in there at this point is correct. |
||
| { | ||
| auto thisAd = outerFunc.isMemberLocal(); | ||
| if (!thisAd) | ||
| return false; | ||
PetarKirov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| auto requiredAd = calledFunc.isMemberLocal(); | ||
| if (!requiredAd) | ||
| return false; | ||
|
|
||
| if (thisAd == requiredAd) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wouldn't just
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed, Long story-short: both is and == are fine in this case. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I dont see the problem with |
||
| return true; | ||
|
|
||
| // outerfunc is the member of a base class that contains calledFunc, | ||
| // then we consider that they have the same this. | ||
| auto cd = requiredAd.isClassDeclaration(); | ||
| if (!cd) | ||
| return false; | ||
|
|
||
| if (cd.isBaseOf2(thisAd.isClassDeclaration())) | ||
| return true; | ||
|
|
||
| // if outerfunc is the member of a nested aggregate, then let | ||
| // getRightThis take care of this. | ||
| if (thisAd.isNested()) | ||
| return true; | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /*************************************** | ||
| * Pull out any properties. | ||
| */ | ||
|
|
@@ -5209,7 +5272,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor | |
| if (exp.f.checkNestedReference(sc, exp.loc)) | ||
| return setError(); | ||
|
|
||
| if (hasThis(sc)) | ||
| auto memberFunc = hasThis(sc); | ||
| if (memberFunc && haveSameThis(memberFunc, exp.f)) | ||
| { | ||
| // Supply an implicit 'this', as in | ||
| // this.ident | ||
|
|
@@ -6892,8 +6956,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor | |
| AggregateDeclaration ad = f.isMemberLocal(); | ||
| if (f.needThis()) | ||
| e.e1 = getRightThis(e.loc, sc, ad, e.e1, f); | ||
| if (e.e1.op == EXP.error) | ||
| return setError(); | ||
|
Comment on lines
-6895
to
-6896
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this removed?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because it was added to fix a symptom of the bug this PR is fixing. Take a look at: #10123 |
||
|
|
||
| if (f.type.ty == Tfunction) | ||
| { | ||
|
|
@@ -7207,7 +7269,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor | |
| } | ||
| if (f.needThis()) | ||
| { | ||
| if (hasThis(sc)) | ||
| auto memberFunc = hasThis(sc); | ||
| if (memberFunc && haveSameThis(memberFunc, f)) | ||
| { | ||
| /* Should probably supply 'this' after overload resolution, | ||
| * not before. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| struct S1(T...) { | ||
| auto fun() { | ||
| static assert(__traits(compiles, &T[0])); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This compiles now, but does the resulting delegate have the right
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But the result is not a delegate, it's a function, so there is no this pointer. |
||
| } | ||
| } | ||
|
|
||
| struct S2 { | ||
| void gun() {} | ||
| S1!gun overloaded; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| // https://issues.dlang.org/show_bug.cgi?id=10886 | ||
|
|
||
| struct A | ||
| { | ||
| @property int foo() { return 0; } | ||
| int bar() { return 0; } | ||
| } | ||
|
|
||
| struct B | ||
| { | ||
| void bar() | ||
| { | ||
| alias f = typeof(A.foo); // NG | ||
| alias b = typeof(A.bar); // ok | ||
| } | ||
| } | ||
|
|
||
| // https://issues.dlang.org/show_bug.cgi?id=21288 | ||
|
|
||
| struct XA | ||
| { | ||
| int p; | ||
| } | ||
|
|
||
| struct XB | ||
| { | ||
| XA a() { return XA.init; } | ||
| alias a this; | ||
| } | ||
|
|
||
| struct XC | ||
| { | ||
| void foo() | ||
| { | ||
| static assert(XB.p.stringof == "p"); // Error: this for s needs to be type B not type C | ||
| } | ||
| } |
This file was deleted.
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.
The example makes it unclear what "have same
this" means, it sounds more like "have covarianttypeof(this)"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.
Well, I followed the existing naming pattern after
getRightThis.