Skip to content

Commit

Permalink
Add trait Self filtering to rustc_on_unimplemented
Browse files Browse the repository at this point in the history
  • Loading branch information
estebank committed Feb 13, 2020
1 parent c376fc0 commit 248f5a4
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 66 deletions.
5 changes: 1 addition & 4 deletions src/libcore/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -728,10 +728,7 @@ unsafe impl<T: ?Sized> Freeze for &mut T {}
/// [`pin module`]: ../../std/pin/index.html
#[stable(feature = "pin", since = "1.33.0")]
#[rustc_on_unimplemented(
on(
_Self = "dyn std::future::Future<Output = i32> + std::marker::Send",
note = "consider using `Box::pin`",
),
on(_Self = "std::future::Future", note = "consider using `Box::pin`",),
message = "`{Self}` cannot be unpinned"
)]
#[lang = "unpin"]
Expand Down
10 changes: 10 additions & 0 deletions src/librustc/traits/error_reporting/on_unimplemented.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
}
}
if let ty::Dynamic(traits, _) = self_ty.kind {
for t in *traits.skip_binder() {
match t {
ty::ExistentialPredicate::Trait(trait_ref) => {
flags.push((sym::_Self, Some(self.tcx.def_path_str(trait_ref.def_id))))
}
_ => {}
}
}
}

if let Ok(Some(command)) =
OnUnimplementedDirective::of_item(self.tcx, trait_ref.def_id, def_id)
Expand Down
26 changes: 14 additions & 12 deletions src/test/ui/suggestions/expected-boxed-future-isnt-pinned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,19 @@ fn foo<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32>
x //~ ERROR mismatched types
}

fn bar<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
Box::new(x) //~ ERROR mismatched types
}

fn baz<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
Pin::new(x) //~ ERROR mismatched types
//~^ ERROR E0277
}

fn qux<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
Pin::new(Box::new(x)) //~ ERROR E0277
}
// FIXME: uncomment these once this commit is in Beta and we can rely on `rustc_on_unimplemented`
// having filtering for `Self` being a trait.
//
// fn bar<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
// Box::new(x)
// }
//
// fn baz<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
// Pin::new(x)
// }
//
// fn qux<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
// Pin::new(Box::new(x))
// }

fn main() {}
52 changes: 2 additions & 50 deletions src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,54 +15,6 @@ LL | x
= help: type parameters must be constrained to match other types
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters

error[E0308]: mismatched types
--> $DIR/expected-boxed-future-isnt-pinned.rs:15:5
|
LL | fn bar<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
| ----------------------- expected `std::pin::Pin<std::boxed::Box<(dyn std::future::Future<Output = i32> + std::marker::Send + 'static)>>` because of return type
LL | Box::new(x)
| ^^^^^^^^^^^ expected struct `std::pin::Pin`, found struct `std::boxed::Box`
|
= note: expected struct `std::pin::Pin<std::boxed::Box<(dyn std::future::Future<Output = i32> + std::marker::Send + 'static)>>`
found struct `std::boxed::Box<F>`
= help: use `Box::pin`

error[E0308]: mismatched types
--> $DIR/expected-boxed-future-isnt-pinned.rs:19:14
|
LL | fn baz<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
| - this type parameter
LL | Pin::new(x)
| ^
| |
| expected struct `std::boxed::Box`, found type parameter `F`
| help: store this in the heap by calling `Box::new`: `Box::new(x)`
|
= note: expected struct `std::boxed::Box<dyn std::future::Future<Output = i32> + std::marker::Send>`
found type parameter `F`
= help: type parameters must be constrained to match other types
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
= note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html

error[E0277]: `dyn std::future::Future<Output = i32> + std::marker::Send` cannot be unpinned
--> $DIR/expected-boxed-future-isnt-pinned.rs:19:5
|
LL | Pin::new(x)
| ^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `dyn std::future::Future<Output = i32> + std::marker::Send`
|
= note: consider using `Box::pin`
= note: required by `std::pin::Pin::<P>::new`

error[E0277]: `dyn std::future::Future<Output = i32> + std::marker::Send` cannot be unpinned
--> $DIR/expected-boxed-future-isnt-pinned.rs:24:5
|
LL | Pin::new(Box::new(x))
| ^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `dyn std::future::Future<Output = i32> + std::marker::Send`
|
= note: consider using `Box::pin`
= note: required by `std::pin::Pin::<P>::new`

error: aborting due to 5 previous errors
error: aborting due to previous error

Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
For more information about this error, try `rustc --explain E0308`.

0 comments on commit 248f5a4

Please sign in to comment.