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

Require that objects can only be made from Sized types. Fixes #18333. #18750

Merged

Conversation

nikomatsakis
Copy link
Contributor

In the general case, at least, it is not possible to make an object out of an unsized type. This is because the object type would have to store the fat pointer information for the self value and the vtable -- meaning it'd have to be a fat pointer with three words -- but for the compiler to know that the object requires three words, it would have to know the self-type of the object (is self a thin or fat pointer?), which of course it doesn't.

Fixes #18333.

r? @nick29581

@sfackler
Copy link
Member

sfackler commented Nov 7, 2014

@nikomatsakis nikomatsakis force-pushed the issue-18333-skolemize-open-existential branch 2 times, most recently from a8b86b3 to f12565c Compare November 20, 2014 10:56
@nikomatsakis nikomatsakis force-pushed the issue-18333-skolemize-open-existential branch from f12565c to 7a372e2 Compare November 20, 2014 14:16
bors added a commit that referenced this pull request Nov 20, 2014
…xistential, r=nrc

In the general case, at least, it is not possible to make an object out of an unsized type. This is because the object type would have to store the fat pointer information for the `self` value *and* the vtable -- meaning it'd have to be a fat pointer with three words -- but for the compiler to know that the object requires three words, it would have to know the self-type of the object (is `self` a thin or fat pointer?), which of course it doesn't.

Fixes #18333.

r? @nick29581
@bors bors closed this Nov 20, 2014
@bors bors merged commit 7a372e2 into rust-lang:master Nov 20, 2014
@nikomatsakis nikomatsakis deleted the issue-18333-skolemize-open-existential branch March 30, 2016 16:14
@mathstuf
Copy link
Contributor

mathstuf commented Aug 4, 2016

Would it be possible to relax it such that if I have a reference to a trait, I can make a reference to the trait?

Example:

trait T {
    fn t(&self) -> &T {
        &self
    }
}

@nikomatsakis
Copy link
Contributor Author

@mathstuf I'm afraid that is not possible, but you can do this:

trait T {
    fn t(&self) -> &T where Self: Sized { &self }
}

@mathstuf
Copy link
Contributor

That comes up with this error:

error[E0277]: the trait bound `&Self: T` is not satisfied
 --> <anon>:2:41
  |
2 |   fn t(&self) -> &T where Self: Sized { &self }
  |                                         ^^^^^
  |
  = note: required for the cast to the object type `T`

error: aborting due to previous error

@nikomatsakis
Copy link
Contributor Author

@mathstuf sorry, my mistake, I didn't notice that you had written &self. Try this:

trait T {
    fn t(&self) -> &T where Self: Sized { self } // self, not &self
}

In particular, when you return &self you are trying to convert a &&Self pointer into an &T object, but you want to convert an &Self pointer into an &T object.

@mathstuf
Copy link
Contributor

That doesn't work because I can't do this:

let my_t: &T = some_ref(s);
my.t(); // since `T` is just a reference, we don't have `Sized`

@nikomatsakis
Copy link
Contributor Author

@mathstuf well, it depends on what you are trying to do =) I should have made it clear that what I wrote will allow you to make an object if you don't have one already, but it will fail if you may have one already. If you want to support that, it's a bit more annoying. You basically need an operation that applies to the reference as a whole, I think:

trait ToTObject<'a> {
    fn to_object(self) -> &'a T;
}

impl<'a> ToObject<'a> for &'a T {
    fn to_object(self) -> &'a T { self }
}

impl<'a,U: T> ToObject<'a> for &'a U {
    fn to_object(self) -> &'a T { self }
}

The point here is that the first impl doesn't do any coercion (it already has an object), and the second impl does (it has a &U for some sized U). It'd be nice to make this smoother, no doubt.

@mathstuf
Copy link
Contributor

My current workaround is:

trait T {
  fn t<'a>(&'a self) -> SomeStruct<'a> { SomeStruct { t: self._self_ref_hack() } }
  fn _self_ref_hack(&self) -> &T;
}

lnicola pushed a commit to lnicola/rust that referenced this pull request Jan 7, 2025
Back out "internal: Disable rustc test metrics"
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.

ICE when creating a slice of trait objects with DST impls
6 participants