Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 20 additions & 13 deletions compiler/rustc_mir_transform/src/impossible_predicates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,37 @@

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;

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();
Expand Down
17 changes: 0 additions & 17 deletions tests/crashes/122904-2.rs

This file was deleted.

13 changes: 0 additions & 13 deletions tests/crashes/139556.rs

This file was deleted.

1 change: 0 additions & 1 deletion tests/ui/consts/promoted_const_call2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
17 changes: 4 additions & 13 deletions tests/ui/consts/promoted_const_call2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -38,15 +30,14 @@ 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
| | |
| | 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`.
11 changes: 8 additions & 3 deletions tests/crashes/122630.rs → tests/ui/coroutine/moved-twice.rs
Original file line number Diff line number Diff line change
@@ -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<Yield = ()> {}
fn drop(&mut self) {}
}

fn overlap_move_points() -> impl Coroutine<Yield = ()> {
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() {}
24 changes: 24 additions & 0 deletions tests/ui/coroutine/moved-twice.stderr
Original file line number Diff line number Diff line change
@@ -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`.
19 changes: 19 additions & 0 deletions tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.rs
Original file line number Diff line number Diff line change
@@ -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() {}
30 changes: 30 additions & 0 deletions tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.stderr
Original file line number Diff line number Diff line change
@@ -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`.
24 changes: 24 additions & 0 deletions tests/ui/type-alias-impl-trait/recursive-drop-elaboration.rs
Original file line number Diff line number Diff line change
@@ -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
}
58 changes: 58 additions & 0 deletions tests/ui/type-alias-impl-trait/recursive-drop-elaboration.stderr
Original file line number Diff line number Diff line change
@@ -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`.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//@ known-bug: rust-lang/rust#125185
//! Regression test for #125185
//@ compile-flags: -Zvalidate-mir

#![feature(type_alias_impl_trait)]
Expand All @@ -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();
Expand Down
12 changes: 12 additions & 0 deletions tests/ui/type-alias-impl-trait/type-error-drop-elaboration.stderr
Original file line number Diff line number Diff line change
@@ -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`.
Loading