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

The use of Self in traits may lead to soundness holes #318

Closed
yorickpeterse opened this issue Jul 18, 2022 · 4 comments · Fixed by #508
Closed

The use of Self in traits may lead to soundness holes #318

yorickpeterse opened this issue Jul 18, 2022 · 4 comments · Fixed by #508
Labels
bug Defects, unintended behaviour, etc compiler Changes related to the compiler
Milestone

Comments

@yorickpeterse
Copy link
Collaborator

Consider this trait definition:

trait Eq {
  fn ==(other: ref Self) -> Bool
}

This can lead to soundness holes like so:

let a: Eq = 10
let b: Eq = "test"

a == b

This isn't sound because different types that implement the trait expect Self to be their own type (e.g. String expects a ref String), but in the above code we end up comparing Int == String, which will likely crash the VM.

I'm not sure yet how to best handle this. I believe Rust disallows using traits as objects when they have methods that refer to Self, but I'm not convinced yet that this is the best way of going about it.

@yorickpeterse
Copy link
Collaborator Author

added #252 as child task

@yorickpeterse
Copy link
Collaborator Author

added #253 as child task

@yorickpeterse
Copy link
Collaborator Author

Perhaps a first step is to simply disallow the use of Self in the arguments of trait methods. Allowing Self in return/throw types should still be fine.

@yorickpeterse
Copy link
Collaborator Author

In the last week I thought about this a bit more, as working towards a native code compiler revealed just how annoying it is to provide support for Self types. Basically every time we have a type we have to account for that being Self and substitute it with another type.

I'm starting to lean towards just removing Self types outright. Within traits their use is generally unsound, apart from maybe throw/return types. In classes Self is mostly used when you're too lazy to write the type out manually, but this makes the code less clear as, depending on how the code is written, it may not be immediately obvious what Self resolves to.

In case of traits, returning/throwing Self has one benefit over using the trait type explicitly: when the method is used in the context of a class, the type is correctly inferred as that class instead of the trait. That is, if you have -> Self and Int implements the trait, the method's return type is Int not TheTrait. This however isn't that big of a deal: when implementing a trait you can just override the type to be that of the class, and it achieves the same results.

Currently the common use case of Self is for Clone and the various operator traits. In all cases the traits can just be made generic, which also gives you the option to change what the return type is (though at least for Clone it's rare to not want the return type to be the same as the receiver).

@yorickpeterse yorickpeterse added bug Defects, unintended behaviour, etc and removed type::bug labels Mar 15, 2023
@yorickpeterse yorickpeterse modified the milestones: 0.6.0, 0.11.0 Mar 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Defects, unintended behaviour, etc compiler Changes related to the compiler
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant