Skip to content

Conversation

Adist319
Copy link
Contributor

@Adist319 Adist319 commented Aug 1, 2025

Resolves #592.

We now only throw an error when creating an instance of an abstract class, instead of when an abstract method is called.

Behavior:

# Before: No error thrown

# After: BadInstantiation error
class Shape(ABC):
    @abstractmethod
    def area(self): pass

Shape()  # Error: Cannot instantiate abstract class `Shape`

# Concrete implementations work fine
class Circle(Shape):
    def area(self): return 3.14

Circle()  # works

@meta-cla meta-cla bot added the cla signed label Aug 1, 2025
@yangdanny97 yangdanny97 requested a review from stroxler August 1, 2025 14:46
@yangdanny97
Copy link
Contributor

Hmm, mypy primer runs are panicking. We'll get this reviewed and see if we can figure out what's going on

@yangdanny97 yangdanny97 requested a review from grievejia August 4, 2025 18:07
@@ -396,6 +396,18 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
hint: Option<&Type>,
) -> Type {
// Based on https://typing.readthedocs.io/en/latest/spec/constructors.html.
let instance_ty = Type::ClassType(cls.clone());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this appears unused?

}

// Recursively check base classes
let metadata = self.get_metadata_for_class(class_obj);
Copy link
Contributor

@yangdanny97 yangdanny97 Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can pre-calculate inherits_from_abc and store it in class metadata. cc @grievejia

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this idea, we could do something like:

pub struct ClassMetadata {
       // ... existing fields ...
       inherits_from_abc: bool,  // New field
}

And then we could populate ABC Inheritance during class metadata creation.

match &field.0 {
ClassFieldInner::Simple { ty, .. } => {
if let Type::Function(function) = ty {
if function.metadata.flags.is_abstract_method {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we might need to handle overloaded functions too

}

/// Recursively collect abstract methods from a class and its bases
fn collect_abstract_methods_from_class(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we need to traverse all the base classes like this. If we look up each field the class has like so

fn get_class_member_impl(
it would handle the lookup, and we can check if the field it returns is abstract or not.

Of course, this relies on the MRO being correct and able to handle cases when one base class declares something as abstract and another base class provides the impl. @stroxler would know more about this

@Adist319
Copy link
Contributor Author

@yangdanny97 Thanks for the feedback! I just wanted to check if the panics have been root-caused yet, or if that’s still being investigated, so I know when I can continue work on this PR.

@facebook-github-bot
Copy link
Contributor

@yangdanny97 has imported this pull request. If you are a Meta employee, you can view this in D80087011.

@yangdanny97
Copy link
Contributor

@Adist319

The panics are caused by the changes this PR, probably to handling descendants of the PathLike class (that's what declares the __fspath__ we see in the panic messages.

You can repro this by checking a simple snippet.

from pathlib import Path
p = Path("x")

This didn't show up in the unit tests, because we emit a DEBUG message instead of panic:

"LookupAnswer::get failed to find key, {module} {k:?} (concurrent changes?)"

cc @ndmitchell I'm a bit confused about what this does, or why we don't always panic

@Adist319
Copy link
Contributor Author

@yangdanny97 thanks for looking into it , will get back to this soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[feature] emit an error when trying to call an abstract method
3 participants