diff --git a/compiler/rustc_mir_transform/src/impossible_predicates.rs b/compiler/rustc_mir_transform/src/impossible_predicates.rs index b03518de00a9..883ee32bdec9 100644 --- a/compiler/rustc_mir_transform/src/impossible_predicates.rs +++ b/compiler/rustc_mir_transform/src/impossible_predicates.rs @@ -28,6 +28,7 @@ use rustc_middle::mir::{Body, START_BLOCK, TerminatorKind}; use rustc_middle::ty::{TyCtxt, TypeFlags, TypeVisitableExt}; +use rustc_span::def_id::DefId; use rustc_trait_selection::traits; use tracing::trace; @@ -35,23 +36,29 @@ use crate::pass_manager::MirPass; pub(crate) struct ImpossiblePredicates; +fn has_impossible_predicates(tcx: TyCtxt<'_>, def_id: DefId) -> bool { + let predicates = tcx.predicates_of(def_id).instantiate_identity(tcx); + tracing::trace!(?predicates); + let predicates = predicates.predicates.into_iter().filter(|p| { + !p.has_type_flags( + // Only consider global clauses to simplify. + TypeFlags::HAS_FREE_LOCAL_NAMES + // Clauses that refer to unevaluated constants as they cause cycles. + | TypeFlags::HAS_CT_PROJECTION, + ) + }); + let predicates: Vec<_> = traits::elaborate(tcx, predicates).collect(); + tracing::trace!(?predicates); + predicates.references_error() || traits::impossible_predicates(tcx, predicates) +} + impl<'tcx> MirPass<'tcx> for ImpossiblePredicates { #[tracing::instrument(level = "trace", skip(self, tcx, body))] fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { tracing::trace!(def_id = ?body.source.def_id()); - let predicates = tcx.predicates_of(body.source.def_id()).instantiate_identity(tcx); - tracing::trace!(?predicates); - let predicates = predicates.predicates.into_iter().filter(|p| { - !p.has_type_flags( - // Only consider global clauses to simplify. - TypeFlags::HAS_FREE_LOCAL_NAMES - // Clauses that refer to unevaluated constants as they cause cycles. - | TypeFlags::HAS_CT_PROJECTION, - ) - }); - let predicates: Vec<_> = traits::elaborate(tcx, predicates).collect(); - tracing::trace!(?predicates); - if predicates.references_error() || traits::impossible_predicates(tcx, predicates) { + let impossible = body.tainted_by_errors.is_some() + || has_impossible_predicates(tcx, body.source.def_id()); + if impossible { trace!("found unsatisfiable predicates"); // Clear the body to only contain a single `unreachable` statement. let bbs = body.basic_blocks.as_mut(); diff --git a/tests/crashes/122904-2.rs b/tests/crashes/122904-2.rs deleted file mode 100644 index db66b8625db0..000000000000 --- a/tests/crashes/122904-2.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ known-bug: #122904 -trait T {} - -type Alias<'a> = impl T; - -struct S; -impl<'a> T for &'a S {} - -#[define_opaque(Alias)] -fn with_positive(fun: impl Fn(Alias<'_>)) { - with_positive(|&n| ()); -} - -#[define_opaque(Alias)] -fn main(Alias<'_>) { - with_positive(|&a| ()); -} diff --git a/tests/crashes/139556.rs b/tests/crashes/139556.rs deleted file mode 100644 index 60dc8d7c3afc..000000000000 --- a/tests/crashes/139556.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ known-bug: #139556 - -trait T {} - -type Alias<'a> = impl T; - -struct S; -impl<'a> T for &'a S {} - -#[define_opaque(Alias)] -fn with_positive(fun: impl Fn(Alias<'_>)) { - with_positive(|&n| ()); -} diff --git a/tests/ui/consts/promoted_const_call2.rs b/tests/ui/consts/promoted_const_call2.rs index f332cd18cea3..62391f098e5d 100644 --- a/tests/ui/consts/promoted_const_call2.rs +++ b/tests/ui/consts/promoted_const_call2.rs @@ -4,7 +4,6 @@ pub const C: () = { let _: &'static _ = &id(&String::new()); //~^ ERROR: temporary value dropped while borrowed //~| ERROR: temporary value dropped while borrowed - //~| ERROR: destructor of `String` cannot be evaluated at compile-time }; fn main() { diff --git a/tests/ui/consts/promoted_const_call2.stderr b/tests/ui/consts/promoted_const_call2.stderr index bdb43385d203..e62458d1a6ae 100644 --- a/tests/ui/consts/promoted_const_call2.stderr +++ b/tests/ui/consts/promoted_const_call2.stderr @@ -18,16 +18,8 @@ LL | let _: &'static _ = &id(&String::new()); | | creates a temporary value which is freed while still in use | type annotation requires that borrow lasts for `'static` -error[E0493]: destructor of `String` cannot be evaluated at compile-time - --> $DIR/promoted_const_call2.rs:4:30 - | -LL | let _: &'static _ = &id(&String::new()); - | ^^^^^^^^^^^^^ - value is dropped here - | | - | the destructor for this type cannot be evaluated in constants - error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call2.rs:11:26 + --> $DIR/promoted_const_call2.rs:10:26 | LL | let _: &'static _ = &id(&String::new()); | ---------- ^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -38,7 +30,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call2.rs:11:30 + --> $DIR/promoted_const_call2.rs:10:30 | LL | let _: &'static _ = &id(&String::new()); | ---------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement @@ -46,7 +38,6 @@ LL | let _: &'static _ = &id(&String::new()); | | creates a temporary value which is freed while still in use | type annotation requires that borrow lasts for `'static` -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0493, E0716. -For more information about an error, try `rustc --explain E0493`. +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/crashes/122630.rs b/tests/ui/coroutine/moved-twice.rs similarity index 62% rename from tests/crashes/122630.rs rename to tests/ui/coroutine/moved-twice.rs index e66624431c51..72b83e274c92 100644 --- a/tests/crashes/122630.rs +++ b/tests/ui/coroutine/moved-twice.rs @@ -1,22 +1,27 @@ -//@ known-bug: #122630 +//! Regression test for #122630 //@ compile-flags: -Zvalidate-mir +#![feature(coroutines, coroutine_trait, yield_expr)] + use std::ops::Coroutine; const FOO_SIZE: usize = 1024; struct Foo([u8; FOO_SIZE]); impl Drop for Foo { - fn move_before_yield_with_noop() -> impl Coroutine {} + fn drop(&mut self) {} } fn overlap_move_points() -> impl Coroutine { - static || { + #[coroutine] static || { let first = Foo([0; FOO_SIZE]); yield; let second = first; yield; let second = first; + //~^ ERROR: use of moved value: `first` [E0382] yield; } } + +fn main() {} diff --git a/tests/ui/coroutine/moved-twice.stderr b/tests/ui/coroutine/moved-twice.stderr new file mode 100644 index 000000000000..2b21f6c59f0b --- /dev/null +++ b/tests/ui/coroutine/moved-twice.stderr @@ -0,0 +1,24 @@ +error[E0382]: use of moved value: `first` + --> $DIR/moved-twice.rs:21:22 + | +LL | let first = Foo([0; FOO_SIZE]); + | ----- move occurs because `first` has type `Foo`, which does not implement the `Copy` trait +LL | yield; +LL | let second = first; + | ----- value moved here +LL | yield; +LL | let second = first; + | ^^^^^ value used here after move + | +note: if `Foo` implemented `Clone`, you could clone the value + --> $DIR/moved-twice.rs:9:1 + | +LL | struct Foo([u8; FOO_SIZE]); + | ^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let second = first; + | ----- you could clone this value + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.rs b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.rs new file mode 100644 index 000000000000..5541c5267f39 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.rs @@ -0,0 +1,19 @@ +//! Regression test for ICE #139556 + +#![feature(type_alias_impl_trait)] + +trait T {} + +type Alias<'a> = impl T; + +struct S; +impl<'a> T for &'a S {} + +#[define_opaque(Alias)] +fn with_positive(fun: impl Fn(Alias<'_>)) { +//~^ WARN: function cannot return without recursing + with_positive(|&n| ()); + //~^ ERROR: cannot move out of a shared reference +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.stderr b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.stderr new file mode 100644 index 000000000000..e1fdd222ee14 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.stderr @@ -0,0 +1,30 @@ +warning: function cannot return without recursing + --> $DIR/recursive-drop-elaboration-2.rs:13:1 + | +LL | fn with_positive(fun: impl Fn(Alias<'_>)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | +LL | with_positive(|&n| ()); + | ---------------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error[E0507]: cannot move out of a shared reference + --> $DIR/recursive-drop-elaboration-2.rs:15:20 + | +LL | with_positive(|&n| ()); + | ^- + | | + | data moved here + | move occurs because `n` has type `S`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - with_positive(|&n| ()); +LL + with_positive(|n| ()); + | + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.rs b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.rs new file mode 100644 index 000000000000..dd28732ebb28 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.rs @@ -0,0 +1,24 @@ +//! Regression test for #122904. + +#![feature(type_alias_impl_trait)] + +trait T {} + +type Alias<'a> = impl T; + +struct S; +impl<'a> T for &'a S {} + +#[define_opaque(Alias)] +fn with_positive(fun: impl Fn(Alias<'_>)) { +//~^ WARN: function cannot return without recursing + with_positive(|&n| ()); + //~^ ERROR: cannot move out of a shared reference +} + +#[define_opaque(Alias)] +fn main(_: Alias<'_>) { +//~^ ERROR: `main` function has wrong type [E0580] + with_positive(|&a| ()); + //~^ ERROR: cannot move out of a shared reference +} diff --git a/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.stderr b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.stderr new file mode 100644 index 000000000000..8b5dc950afdd --- /dev/null +++ b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.stderr @@ -0,0 +1,58 @@ +warning: function cannot return without recursing + --> $DIR/recursive-drop-elaboration.rs:13:1 + | +LL | fn with_positive(fun: impl Fn(Alias<'_>)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | +LL | with_positive(|&n| ()); + | ---------------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error[E0507]: cannot move out of a shared reference + --> $DIR/recursive-drop-elaboration.rs:15:20 + | +LL | with_positive(|&n| ()); + | ^- + | | + | data moved here + | move occurs because `n` has type `S`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - with_positive(|&n| ()); +LL + with_positive(|n| ()); + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/recursive-drop-elaboration.rs:22:20 + | +LL | with_positive(|&a| ()); + | ^- + | | + | data moved here + | move occurs because `a` has type `S`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - with_positive(|&a| ()); +LL + with_positive(|a| ()); + | + +error[E0580]: `main` function has wrong type + --> $DIR/recursive-drop-elaboration.rs:20:1 + | +LL | type Alias<'a> = impl T; + | ------ the found opaque type +... +LL | fn main(_: Alias<'_>) { + | ^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters + | + = note: expected signature `fn()` + found signature `for<'a> fn(Alias<'a>)` + +error: aborting due to 3 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0507, E0580. +For more information about an error, try `rustc --explain E0507`. diff --git a/tests/crashes/125185.rs b/tests/ui/type-alias-impl-trait/type-error-drop-elaboration.rs similarity index 78% rename from tests/crashes/125185.rs rename to tests/ui/type-alias-impl-trait/type-error-drop-elaboration.rs index e77666ca73d3..c0fb9007865a 100644 --- a/tests/crashes/125185.rs +++ b/tests/ui/type-alias-impl-trait/type-error-drop-elaboration.rs @@ -1,4 +1,4 @@ -//@ known-bug: rust-lang/rust#125185 +//! Regression test for #125185 //@ compile-flags: -Zvalidate-mir #![feature(type_alias_impl_trait)] @@ -10,6 +10,7 @@ struct A; #[define_opaque(Foo)] const fn foo() -> Foo { value() + //~^ ERROR: cannot find function `value` in this scope } const VALUE: Foo = foo(); diff --git a/tests/ui/type-alias-impl-trait/type-error-drop-elaboration.stderr b/tests/ui/type-alias-impl-trait/type-error-drop-elaboration.stderr new file mode 100644 index 000000000000..1cb33eabd902 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-error-drop-elaboration.stderr @@ -0,0 +1,12 @@ +error[E0425]: cannot find function `value` in this scope + --> $DIR/type-error-drop-elaboration.rs:12:5 + | +LL | value() + | ^^^^^ help: a constant with a similar name exists: `VALUE` +... +LL | const VALUE: Foo = foo(); + | ------------------------- similarly named constant `VALUE` defined here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0425`.