Skip to content
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

Remove dyn Trait slides #2609

Closed
wants to merge 1 commit into from
Closed

Conversation

randomPoison
Copy link
Collaborator

After many classes and seeing how many students absorb the contents, I think it'd better if we don't cover trait objects in the course. I have a few reasons for this:

  • It's a more complicated topic because it requires talking about runtime dispatch and vtables, something that we don't otherwise bring up and isn't necessarily intuitive for students depending on what language they come from.
  • We never cover dyn Trait in exercises, so students never get a chance to get hand-on experience. I think this hampers learning a lot, as the topic is unintuitive and students are unlikely to absorb it without practice.
  • The only other times that trait objects are mentioned are when talking about dynamic error types in the error handling section, and in the modules exercise.
    • In the former I think we can hand wave past talking about trait objects in detail and just say "This allows you to take anything that implements Error and turn it into this Box<dyn Error> type". We could probably put more details in the "More to Explore" section of that slide, but I think that's really the most we need to say about trait objects.
    • In the latter students don't actually interact with the trait objects at all, they're just an implementation detail that they can ignore.
  • Classes tend to run short on time, and these slides aren't quick to go through in my experience. I think we gain more value in the extra time than we gain from keeping this topic.

On the other hand, dyn Trait is referenced in the Android and Concurrency classes. I've taught the Android class and I don't think it's essential to the class, or at least I could briefly explain enough for students to at least understand how to use a trait object, even if they wouldn't fully understand how they work. I'm not sure how this would impact the Concurrency class though, so I'm curious what @fw-immunant and other people who have taught the class think.

@djmitche djmitche self-requested a review January 31, 2025 17:35
Copy link
Collaborator

@fw-immunant fw-immunant left a comment

Choose a reason for hiding this comment

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

NAK. Trait objects are important to know about both for designing programs/libraries and for understanding the performance of Rust code.

Trait objects are a key part of Rust's story about extensibility and programming in the large. The orphan rule and extension traits allow for code to be extended with new types or new traits, but storing objects in collections by dispatching on enums requires a closed, foreknown set of types in order to define the enum. Without trait objects, the ability to store heterogeneous objects from downstream crates is effectively gone.

When teaching C++ programmers, they're often curious about the operational (machine) side of Rust. They see generics, which largely mirror templates to provide static dispatch for polymorphic code, and are generally curious about the flip side: "does rust have vtables?" and "what's the answer to C++ patterns that use inheritance? (e.g. std::vector<std::unique_ptr<BaseClass>>)" are two common questions. Trait objects are the answer to both of these.

Also from the side of C++ users, the presence of vtables as a pointer in trait objects rather than inline in regular structs is a significant design difference between Rust and many other languages, with has its own performance implications worth discussing. IMO this design falls rather neatly out of the way Rust makes traits an extension of a type's functionality rather than an inherent part of the type's definition.

I think we should keep teaching about trait objects; if time is of the essence we could perhaps move the two slides discussing them together and eliminate some redundancies.

@djmitche
Copy link
Collaborator

I tend to agree that this is a critical part of the language that we shouldn't omit. But, covering it more quickly might make sense. Maybe that means moving discussion of the memory representation into a "More to Explore" section?

And as @fw-immunant says, maybe the two slides could be combined. Maybe the "impl Trait" slide can talk about monomorphization and refer forward to say that there is a dynamic-dispatch / type-erased / vtable-based way to do this too. Then the trait objects slide can introduce the dyn keyword and mention that it also works for function signatures.

djmitche

This comment was marked as resolved.

@randomPoison
Copy link
Collaborator Author

Okay, if folks feel like dyn Trait is important to cover, I might want to instead try revamping how we cover it. Maybe it deserves its own small section following generics where we can cover it a bit more clearly over a couple of slides. I'm hesitant to add that to day 2 since that day seems especially packed with the existing content, but I'll think about how we could better cover trait objects.

@randomPoison randomPoison deleted the legare/delete-trait-objects branch February 7, 2025 22:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants