-
Notifications
You must be signed in to change notification settings - Fork 159
C should not be assignable to Self@C unless C is final #706 #1117
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
base: main
Are you sure you want to change the base?
Conversation
Hi @edmondop! Thank you for your pull request and welcome to our community. Action RequiredIn order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you. ProcessIn order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA. Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with If you have received this in error or have any questions, please contact us at [email protected]. Thanks! |
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks! |
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.
Hi @edmondop, thanks for the PR!
This looks plausible to me, but there are several failing tests and it would be nice to see the behavior changes in the diff view in case this is interacting badly with other parts of Pyrefly (in particular, I see some incompatible-override errors popping up and it would be nice to make sure those make sense).
cc @rchen152 and @samwgoldman who are probably our experts on the Self type (and for that matter function subtyping as well!)
Thanks, will look into the failing tests. I didn’t catch them locally
because I think they were all passing until the new one was failing and
once I fixed the new one, I forgot to run again the others. Let me look
into the failing tests before anyone spend time reviewing broken code
…On Sat, Sep 20, 2025 at 8:31 PM Steven Troxler ***@***.***> wrote:
***@***.**** commented on this pull request.
Hi @edmondop <https://github.com/edmondop>, thanks for the PR!
This looks plausible to me, but there are several failing tests and it
would be nice to see the behavior changes in the diff view in case this is
interacting badly with other parts of Pyrefly (in particular, I see some
incompatible-override errors popping up and it would be nice to make sure
those make sense).
cc @rchen152 <https://github.com/rchen152> and @samwgoldman
<https://github.com/samwgoldman> who are probably our experts on the Self
type (and for that matter function subtyping as well!)
—
Reply to this email directly, view it on GitHub
<#1117 (review)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAGGOKIYFZYYSJ6654MZCCL3TXWWNAVCNFSM6AAAAACHB4ZOT2VHI2DSMVQWIX3LMV43YUDVNRWFEZLROVSXG5CSMV3GSZLXHMZTENBZGMZDEOBYGY>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
I confirm the change has broken some existing funtionality, and some tests that should be passing are not. I haven't investigated the other tests, but this one is a good example: testcase!(
test_call_instance_method_from_classmethod,
r#"
class A:
def f(self):
pass
class B(A):
@classmethod
def g(cls):
super().f(cls())
"#,
); I need to dive deeper into |
I haven't being able to find a solution that affect only |
pyrefly/lib/alt/solve.rs
Outdated
self.expr(expr, hint.as_ref().map(|t| (t, tcc)), errors) | ||
} else { | ||
if let Some(Type::SelfType(want_class)) = hint.as_ref() { | ||
if !self.type_order().is_final(want_class.class_object()) { |
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.
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.
Thanks, I thought I had run cargo clippy. Fixed now
Yeah this is tricky and tied into a few very difficult questions:
If we actually solved The adhoc handling has benefits because it allows us to do things like handle an attribute specified as Let's see if @rchen152 and @samwgoldman have thoughts |
Thanks for contributing! I don't think the fix is in the right place. This diff adds some logic to the code handling returns with explicit annotations, but assignability happens in more places, like The right place for this fix is to remove the invalid rules in subset.rs, here: https://github.com/facebook/pyrefly/blob/main/pyrefly/lib/solver/subset.rs#L1005-L1013 These rules say it is OK to assign C to Self@C, which is exactly false, so the right thing to do is remove them. However, there is a snag -- we rely on this rule in a few places. Usually this happens when we fail to preserve "Self"-ness. I recently fixed a couple examples of this, in 968a99c and in fc7592c. I know of at least one other place we get this wrong -- calling a constructor on the call target |
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 think the original issue is mislabeled as "good first issue" -- but you are welcome to keep going if you'd like. Try removing the invalid rules first and see what tests fail. Hopefully you will see an example like the ctor call on type[Self]
, but maybe some others. Those issues would need to be fixed first, preferably in separate PRs.
Thanks, I tried to originally make that change and it was causing several test to fail. I was trying to restrict my condition in the |
I see -- in subset.rs it would not be possible to restrict to just return types, but I don't think such a restriction is worthwhile, since the bug exists everywhere. The fact that other tests start to fail is likely because of other latent issues that need to be fixed first, per my comment above. For example, the |
I think I found the root cause of why I wasn't able to solve the problem in The problem was that in Type::Type(box Type::ClassType(cls)) | Type::Type(box Type::SelfType(cls)) => {
Some(CallTarget::Class(cls))
} this handling means that later in the In practice this mean that would end up being processed on a different branch of subset.rs rather than the one we expect class B:
@classmethod
def factory(cls) -> Self:
return cls() The solution seems to be to introduce a new enum type for the CallTarget of type Self, and produce a Type::SelfType later for subset.rs. This ensures that |
self.construct_class(cls, args, keywords, range, errors, context, hint) | ||
} | ||
CallTarget::SelfClass(cls) => { | ||
if cls.has_qname("typing", "Any") { |
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.
maybe this should be factor out so we can share it between ClassTarget::Class and ClassTarget::SelfClass since this code is identical
This PR addresses #706 by making the return-type check verify, in case the return type is Self, that the class is defined as final