Closed BurntSushi closed 9 years ago
CC @nikomatsakis
I think the problem is worse than this; trait objects in general don’t seem to be being recognised as implementing their traits:
trait Trait { }
fn a(x: &Trait) { try(x); }
fn b(x: &mut Trait) { try(x); }
fn c(x: Box<Trait>) { try(x); }
fn try<T: Trait>(t: T) { }
fn main() { }
All three fail:
i.rs:3:19: 3:22 error: the trait `Trait` is not implemented for the type `&Trait`
i.rs:3 fn a(x: &Trait) { try(x); }
^~~
i.rs:4:23: 4:26 error: the trait `Trait` is not implemented for the type `&mut Trait`
i.rs:4 fn b(x: &mut Trait) { try(x); }
^~~
i.rs:5:23: 5:26 error: the trait `Trait` is not implemented for the type `Box<Trait>`
i.rs:5 fn c(x: Box<Trait>) { try(x); }
^~~
error: aborting due to 3 previous errors
I'm not sure this is a bug at all. You're pretty much asking for an automatic impl<T> Trait for &mut T where T: Trait
- I did come up with a Deref
& DerefMut
-based model that would kinda work for this and IIRC @nikomatsakis pointed out that object-safe traits would eventually qualify for this. We do have object safety now, so it might be doable, but I wouldn't bet on it making into 1.0.
In the meanwhile, does .by_ref()
work? If it doesn't, is it just the case of missing ?Sized
in a couple places?
This a particular case of #20617. See comments over there. @nikomatsakis is leaning towards an opt-in derive
syntax extension that handles the boiler plate code, instead of automatic impl
s by the compiler.
ByRef for trait objects seems to hit the same llvm assertion:
fn main() {
struct ByRef<'r, I: ?Sized>(&'r mut I) where I: 'r;
impl<'r, I: ?Sized> Iterator for ByRef<'r, I> where
I: 'r + Iterator
{
type Item = <I as Iterator>::Item;
fn next(&mut self) -> Option<<I as Iterator>::Item>
{
self.0.next()
}
}
let mut it = Box::new(0..10) as Box<Iterator<Item=i32>>;
assert_eq!(it.next(), Some(0));
let mut jt: &mut Iterator<Item=i32> = &mut *it;
assert_eq!(jt.next(), Some(1));
let mut r = ByRef(jt);
assert_eq!(r.next(), Some(2)); // No ICE without this line.
}
output:
rustc: /build/rust-git/src/rust/src/llvm/lib/IR/Instructions.cpp:1086: void llvm::StoreInst::AssertOK(): Assertion `getOperand(0)->getType() == cast<PointerType>(getOperand(1)->getType())->getElementType() && "Ptr must be a pointer to Val type!"' failed.
I'm not sure this is a bug at all. You're pretty much asking for an automatic
impl<T> Trait for &mut T where T: Trait
Interesting. So if I have a value with type Box<T>
where T
is a trait, then we can't say that Box<T>
implements T
in the general case? (Assuming object safety.) So my guess is that Box<Iterator>
can still call next
because of auto deref? Shouldn't that mean it can work with for
? Maybe that is what #20605 is about... You have to explicitly deref a Box<Iterator>
to use it in for
?
(Sorry for all the questions. I'm just confused!)
@BurntSushi doing autoderef on the iterator in for
seems like something reasonable to have.
On Mon, Jan 12, 2015 at 01:33:08PM -0800, Andrew Gallant wrote:
Interesting. So if I have a value with type
Box<T>
whereT
is a trait, then we can't say thatBox<T>
implementsT
in the general case?
Actually, I believe it works with Box
, but not with the other types.
Just thank you for this issue. It resolves all my problems perfectly!
This code fails to compile:
error message:
A similar error occurs if
&mut Iterator
is used instead ofBox<Iterator>
. However, if you comment out the for loop, the call tonext
works just fine. I thought maybe it had something to do with auto-deref, so I tried dereferencing the iterator:but
rustc
dumps core:I'm not sure, but this may be related to #20605?
rustc
dumps core when I try&mut Iterator
too.rustc
version: