-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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 Any
trait should not use virtual calls for type checks
#10382
Comments
To be clear what it should be doing instead: It should be pulling the vtable out of the trait object and inspecting the tydesc therein directly. |
This would also address #10389 |
Well, it might address #10389 anyway. Though I think in practice we'd probably have to limit the types that Any could be applied to to nominal types which can have a unique type descriptor -- actually, I wasn't considering genericity. Even that doesn't work so obviously well. Never mind. Carry on. |
Any using the typedesc from the vtable was the initial design, I changed it to what got merged for two reasons:
|
We can also just add a |
Breaks the dependency between `gfx` and `script`, which is nice. This exposed some performance issues with Rust's `Any` type, which I've filed: rust-lang/rust#10382
There are two non-Any-specific-compiler-magic ways of solving this, that I can think of:
|
Triage bump, carry on. |
Given that we are going to get associated items, an associated constant with |
There's no type id or type descriptor in the virtual function table right now. There's only a slot for a destructor and then the methods. |
If someone is willing to mentor me on this, I'd be interested in giving it a try. |
@Yoric It's a design problem, i.e. how do you represent the I was going to go with "associated constant" a while back, but now that trait objects work by having the compiler implement Anything that has to look up the vtable needs access to |
Right, and I take it that we want to ensure that there is no vtable even when we don't monomorphize. How would |
I don't understand what you mean here. This issue is about avoiding a virtual call, not the entire vtable, which is necessary (and having
Assuming the following definition compiles, trait Trait {
fn method(&self) -> char;
const CONST: char where Self: Sized;
} Then one could imagine the vtable to also contain struct VtableForTrait {
dtor: unsafe fn(*mut u8),
size: usize,
align: usize,
method: unsafe fn(*const u8) -> char,
// The above fields are present in current Rust, only CONST below is new:
CONST: char
} And let's add some impls: struct A;
impl Trait for A {
fn method(&self) -> char { 'A' }
const CONST: char = 'A';
}
struct B;
impl Trait for B {
fn method(&self) -> char { 'B' }
const CONST: char = 'B';
}
Methods don't have this problem: we could call However, we don't want the cost of calling a method through a vtable, especially if we can just load And what I'm proposing is to just use let trait_objects: [&Trait; 2] = [&A, &B];
assert_eq!(trait_objects[0].CONST, 'A');
assert_eq!(trait_objects[1].CONST, 'B'); |
Thinking more about this, it's effectively a feature request for accessing constants on trait objects, or a similar feature, allowing Therefore, I believe it belongs on the RFCs repo, as an issue in this form, or a fully fledged RFC. cc @rust-lang/lang |
@eddyb I agree. I'm actually working with @nikomatsakis on a related RFC in the near future :) |
Sorry, I meant a virtual dispatch. |
I'm not up-to-date in how traits and vtables are represented, so please bear with me if I stumble upon this like a complete noob, but wouldn't it be as simple to somehow use the address of the vtable implementing Or is this a problem because of @Kimundi 's earlier comment on eliminating duplicate vtables? |
@Yoric we do not and cannot (AFAIK) deduplicate vtables to make that work. |
@eddyb Out of curiosity, how/when do we end up with vtables that would need to be deduplicated? |
@Yoric More than one crate. If you want to make it even more complicated, add generics that you monomorphize in different crates with different parameters. |
Right, that makes sense. On the other hand, could it be possible to generate a globally unique identifier per type (using, basically, mangling), and store it at constant position in the vtable? |
@eddyb another option would be to special-case this some, and just have all vtables include a |
That doesn't sound very different from my suggestion, except for the mangling part. |
Closing, since our preferred approach here would require an RFC. |
…-layout-data); r=metajack Breaks the dependency between `gfx` and `script`, which is nice. This exposed some performance issues with Rust's `Any` type, which I've filed: rust-lang/rust#10382 Source-Repo: https://github.com/servo/servo Source-Revision: 4eb84496211bb48d2804a0ddcd16849536546103 UltraBlame original commit: 307ff07f5dc6474afb4176fcf3c599315d4408f2
…-layout-data); r=metajack Breaks the dependency between `gfx` and `script`, which is nice. This exposed some performance issues with Rust's `Any` type, which I've filed: rust-lang/rust#10382 Source-Repo: https://github.com/servo/servo Source-Revision: 4eb84496211bb48d2804a0ddcd16849536546103 UltraBlame original commit: 307ff07f5dc6474afb4176fcf3c599315d4408f2
…-layout-data); r=metajack Breaks the dependency between `gfx` and `script`, which is nice. This exposed some performance issues with Rust's `Any` type, which I've filed: rust-lang/rust#10382 Source-Repo: https://github.com/servo/servo Source-Revision: 4eb84496211bb48d2804a0ddcd16849536546103 UltraBlame original commit: 307ff07f5dc6474afb4176fcf3c599315d4408f2
Box::default(): do not omit the type of the removed trait object Within a larger expression, when the type of `Box::new(T::default())` is `Box<dyn Trait>`, the concrete type `T` cannot be omitted in the proposed replacement `Box::<T>::default()`. Fixes rust-lang#10381 changelog: [`box_default`]: in case of a trait object do not omit the concrete type name
These are slow and should be unnecessary. They are showing up in Servo profiles.
The text was updated successfully, but these errors were encountered: