From 5c14433c00b29fb2065af0eb664e2040f88b4429 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Thu, 30 Sep 2021 01:06:56 +0000 Subject: Fix incorrect Box::pin suggestion The suggestion checked if Pin> could be coeerced to the expected type, but did not check predicates created by the coercion. We now look for predicates that definitely cannot be satisfied before giving the suggestion. The suggestion is marked MaybeIncorrect because we allow predicates that are still ambiguous and can't be proven. --- src/test/ui/suggestions/box-future-wrong-output.rs | 22 ++++++++++++++++++++++ .../ui/suggestions/box-future-wrong-output.stderr | 14 ++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 src/test/ui/suggestions/box-future-wrong-output.rs create mode 100644 src/test/ui/suggestions/box-future-wrong-output.stderr (limited to 'src/test') diff --git a/src/test/ui/suggestions/box-future-wrong-output.rs b/src/test/ui/suggestions/box-future-wrong-output.rs new file mode 100644 index 00000000000..d49819fcb14 --- /dev/null +++ b/src/test/ui/suggestions/box-future-wrong-output.rs @@ -0,0 +1,22 @@ +// Issue #72117 +// edition:2018 + +use core::future::Future; +use core::pin::Pin; + +pub type BoxFuture<'a, T> = Pin + Send + 'a>>; + +impl FutureExt for T where T: Future {} +trait FutureExt: Future { + fn boxed<'a>(self) -> BoxFuture<'a, Self::Output> + where + Self: Sized + Send + 'a, + { + Box::pin(self) + } +} + +fn main() { + let _: BoxFuture<'static, bool> = async {}.boxed(); + //~^ ERROR: mismatched types +} diff --git a/src/test/ui/suggestions/box-future-wrong-output.stderr b/src/test/ui/suggestions/box-future-wrong-output.stderr new file mode 100644 index 00000000000..e0c57af25b3 --- /dev/null +++ b/src/test/ui/suggestions/box-future-wrong-output.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/box-future-wrong-output.rs:20:39 + | +LL | let _: BoxFuture<'static, bool> = async {}.boxed(); + | ------------------------ ^^^^^^^^^^^^^^^^ expected `bool`, found `()` + | | + | expected due to this + | + = note: expected struct `Pin + Send + 'static)>>` + found struct `Pin + Send>>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. -- cgit 1.4.1-3-g733a5 From 485ae9f2c077511f7e2838919c948f9b9b0f0f4f Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Thu, 30 Sep 2021 01:22:17 +0000 Subject: Always check predicates in can_coerce This only changed two tests and I consider both changes an improvement. --- compiler/rustc_typeck/src/check/coercion.rs | 16 +++------------- compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs | 4 ++-- src/test/ui/cross/cross-borrow-trait.stderr | 6 ++---- src/test/ui/dst/dst-bad-coercions.stderr | 12 ++++-------- 4 files changed, 11 insertions(+), 27 deletions(-) (limited to 'src/test') diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 556c5d152df..a87318ff34e 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -934,20 +934,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Same as `try_coerce()`, but without side-effects. + /// + /// Returns false if the coercion creates any obligations that result in + /// errors. pub fn can_coerce(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool { - let source = self.resolve_vars_with_obligations(expr_ty); - debug!("coercion::can({:?} -> {:?})", source, target); - - let cause = self.cause(rustc_span::DUMMY_SP, ObligationCauseCode::ExprAssignable); - // We don't ever need two-phase here since we throw out the result of the coercion - let coerce = Coerce::new(self, cause, AllowTwoPhase::No); - self.probe(|_| coerce.coerce(source, target)).is_ok() - } - - /// Same as `try_coerce()`, but without side-effects and attempts to select - /// all predicates created by the coercion. This is useful for e.g. checking - /// that associated types are correct. - pub fn can_coerce_and_satisfy_predicates(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool { let source = self.resolve_vars_with_obligations(expr_ty); debug!("coercion::can_with_predicates({:?} -> {:?})", source, target); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index 62cacdbbce3..7fe841c3815 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -373,7 +373,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let box_found = self.tcx.mk_box(found); let pin_box_found = self.tcx.mk_lang_item(box_found, LangItem::Pin).unwrap(); let pin_found = self.tcx.mk_lang_item(found, LangItem::Pin).unwrap(); - if self.can_coerce_and_satisfy_predicates(pin_box_found, expected) { + if self.can_coerce(pin_box_found, expected) { debug!("can coerce {:?} to {:?}, suggesting Box::pin", pin_box_found, expected); match found.kind() { ty::Adt(def, _) if def.is_box() => { @@ -391,7 +391,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } true - } else if self.can_coerce_and_satisfy_predicates(pin_found, expected) { + } else if self.can_coerce(pin_found, expected) { match found.kind() { ty::Adt(def, _) if def.is_box() => { err.help("use `Box::pin`"); diff --git a/src/test/ui/cross/cross-borrow-trait.stderr b/src/test/ui/cross/cross-borrow-trait.stderr index f693a3149b2..81f309eae08 100644 --- a/src/test/ui/cross/cross-borrow-trait.stderr +++ b/src/test/ui/cross/cross-borrow-trait.stderr @@ -2,10 +2,8 @@ error[E0308]: mismatched types --> $DIR/cross-borrow-trait.rs:10:26 | LL | let _y: &dyn Trait = x; - | ---------- ^ - | | | - | | expected `&dyn Trait`, found struct `Box` - | | help: consider borrowing here: `&x` + | ---------- ^ expected `&dyn Trait`, found struct `Box` + | | | expected due to this | = note: expected reference `&dyn Trait` diff --git a/src/test/ui/dst/dst-bad-coercions.stderr b/src/test/ui/dst/dst-bad-coercions.stderr index 3e23c5f5c74..01f862ed516 100644 --- a/src/test/ui/dst/dst-bad-coercions.stderr +++ b/src/test/ui/dst/dst-bad-coercions.stderr @@ -13,10 +13,8 @@ error[E0308]: mismatched types --> $DIR/dst-bad-coercions.rs:15:21 | LL | let y: &dyn T = x; - | ------ ^ - | | | - | | expected `&dyn T`, found *-ptr - | | help: consider borrowing here: `&x` + | ------ ^ expected `&dyn T`, found *-ptr + | | | expected due to this | = note: expected reference `&dyn T` @@ -37,10 +35,8 @@ error[E0308]: mismatched types --> $DIR/dst-bad-coercions.rs:20:21 | LL | let y: &dyn T = x; - | ------ ^ - | | | - | | expected `&dyn T`, found *-ptr - | | help: consider borrowing here: `&x` + | ------ ^ expected `&dyn T`, found *-ptr + | | | expected due to this | = note: expected reference `&dyn T` -- cgit 1.4.1-3-g733a5 From 156c9222f52acb1a842ffc2d6e814fca8937cbf0 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Thu, 30 Sep 2021 01:29:24 +0000 Subject: Move misplaced comment --- src/test/ui/suggestions/expected-boxed-future-isnt-pinned.rs | 6 +++--- src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/test') diff --git a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.rs b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.rs index 5dee0f5dae0..89a36e89b0a 100644 --- a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.rs +++ b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.rs @@ -11,13 +11,13 @@ fn foo + Send + 'static>(x: F) -> BoxFuture<'static, i32> x //~ ERROR mismatched types } -// This case is still subpar: -// `Pin::new(x)`: store this in the heap by calling `Box::new`: `Box::new(x)` -// Should suggest changing the code from `Pin::new` to `Box::pin`. fn bar + Send + 'static>(x: F) -> BoxFuture<'static, i32> { Box::new(x) //~ ERROR mismatched types } +// This case is still subpar: +// `Pin::new(x)`: store this in the heap by calling `Box::new`: `Box::new(x)` +// Should suggest changing the code from `Pin::new` to `Box::pin`. fn baz + Send + 'static>(x: F) -> BoxFuture<'static, i32> { Pin::new(x) //~ ERROR mismatched types //~^ ERROR E0277 diff --git a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr index ff08178cb74..f0af37e0cbe 100644 --- a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr +++ b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr @@ -15,7 +15,7 @@ LL | Box::pin(x) | +++++++++ + error[E0308]: mismatched types - --> $DIR/expected-boxed-future-isnt-pinned.rs:18:5 + --> $DIR/expected-boxed-future-isnt-pinned.rs:15:5 | LL | fn bar + Send + 'static>(x: F) -> BoxFuture<'static, i32> { | ----------------------- expected `Pin + Send + 'static)>>` because of return type -- cgit 1.4.1-3-g733a5