diff options
| author | kennytm <kennytm@gmail.com> | 2019-01-05 23:56:44 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-01-05 23:56:44 +0800 |
| commit | 6c58b842d61992a470a726bbc3abfdc540c2c6af (patch) | |
| tree | 2382a8a5d6c101f46f5d8eea6d3669c7ea39dea6 | |
| parent | aa83481a5cfe668bdb081a7189204d4819c986ce (diff) | |
| parent | 2433526809644fd8990773b32a6c6e7286d20a95 (diff) | |
| download | rust-6c58b842d61992a470a726bbc3abfdc540c2c6af.tar.gz rust-6c58b842d61992a470a726bbc3abfdc540c2c6af.zip | |
Rollup merge of #57229 - mikeyhew:fix-56806, r=varkor
Fix #56806 by using `delay_span_bug` in object safety layout sanity checks
It's possible that `is_object_safe` is called on a trait method that with an invalid receiver type. This caused an ICE in #56806, because `receiver_is_dispatchable` returns `true` for `self: Box<dyn Trait>`, which causes one of the layout sanity checks in object_safety.rs to fail. Replacing `bug!` with `delay_span_bug` solves this.
The fact that `receiver_is_dispatchable` returns `true` here could be considered a bug. It passes the check that the method implements, though: `Box<dyn Trait>` implements `DispatchFromDyn<Box<dyn Trait>>` because `dyn Trait` implements `Unsize<dyn Trait>`. It would be good to hear what @eddyb and @nikomatsakis think.
Note that I only added a test for the case encountered in #56806. I could not come up with a case that triggered an ICE from the other check, `bug!("receiver when Self = dyn Trait should be ScalarPair, found Scalar")`. There is no way, to my knowledge, that you can make `receiver_is_dispatchable` return true but still have a `Scalar` ABI when `Self = dyn Trait`.
One other case I encountered while debugging #56806 was that if you have a type parameter `T` that implements `Deref<Target=Self>` and `DispatchFromDyn<T>`, and use it as a method receiver, it will cause an ICE during `is_object_safe` because `T` has no layout ([playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=d9b7497b3be0ca8382fa7d9497263214)):
```rust
trait Trait<T: Deref<Target=Self> + DispatchFromDyn<T>> {
fn foo(self: T) -> dyn Trait<T>;
}
```
I don't intend to remove the ICE there because it is a pathological case, especially since there is no way to implement `DispatchFromDyn<T>` for `T` — the checks in typeck/coherence/builtin.rs do not allow that.
fixes #56806
r? @varkor
| -rw-r--r-- | src/librustc/traits/object_safety.rs | 23 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-56806.rs | 7 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-56806.stderr | 12 |
3 files changed, 37 insertions, 5 deletions
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 31342c250e2..00967242bed 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -359,7 +359,15 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { match abi_of_ty(unit_receiver_ty) { &Abi::Scalar(..) => (), - abi => bug!("Receiver when Self = () should have a Scalar ABI, found {:?}", abi) + abi => { + self.sess.delay_span_bug( + self.def_span(method.def_id), + &format!( + "Receiver when Self = () should have a Scalar ABI, found {:?}", + abi + ), + ); + } } let trait_object_ty = self.object_ty_for_trait( @@ -373,10 +381,15 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { match abi_of_ty(trait_object_receiver) { &Abi::ScalarPair(..) => (), - abi => bug!( - "Receiver when Self = {} should have a ScalarPair ABI, found {:?}", - trait_object_ty, abi - ) + abi => { + self.sess.delay_span_bug( + self.def_span(method.def_id), + &format!( + "Receiver when Self = {} should have a ScalarPair ABI, found {:?}", + trait_object_ty, abi + ), + ); + } } } } diff --git a/src/test/ui/issues/issue-56806.rs b/src/test/ui/issues/issue-56806.rs new file mode 100644 index 00000000000..b6454e578e6 --- /dev/null +++ b/src/test/ui/issues/issue-56806.rs @@ -0,0 +1,7 @@ +pub trait Trait { + fn dyn_instead_of_self(self: Box<dyn Trait>); + //~^ ERROR invalid method receiver type: std::boxed::Box<(dyn Trait + 'static)> +} + +pub fn main() { +} diff --git a/src/test/ui/issues/issue-56806.stderr b/src/test/ui/issues/issue-56806.stderr new file mode 100644 index 00000000000..2dd3add8f60 --- /dev/null +++ b/src/test/ui/issues/issue-56806.stderr @@ -0,0 +1,12 @@ +error[E0307]: invalid method receiver type: std::boxed::Box<(dyn Trait + 'static)> + --> $DIR/issue-56806.rs:2:34 + | +LL | fn dyn_instead_of_self(self: Box<dyn Trait>); + | ^^^^^^^^^^^^^^ + | + = note: type must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0307`. |
