Skip to content

Commit 3934fc9

Browse files
committed
Consider errors in MIR as impossible predicates.
1 parent 5904356 commit 3934fc9

13 files changed

+201
-61
lines changed

compiler/rustc_mir_transform/src/impossible_predicates.rs

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,30 +28,37 @@
2828
2929
use rustc_middle::mir::{Body, START_BLOCK, TerminatorKind};
3030
use rustc_middle::ty::{TyCtxt, TypeFlags, TypeVisitableExt};
31+
use rustc_span::def_id::DefId;
3132
use rustc_trait_selection::traits;
3233
use tracing::trace;
3334

3435
use crate::pass_manager::MirPass;
3536

3637
pub(crate) struct ImpossiblePredicates;
3738

39+
fn has_impossible_predicates(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
40+
let predicates = tcx.predicates_of(def_id).instantiate_identity(tcx);
41+
tracing::trace!(?predicates);
42+
let predicates = predicates.predicates.into_iter().filter(|p| {
43+
!p.has_type_flags(
44+
// Only consider global clauses to simplify.
45+
TypeFlags::HAS_FREE_LOCAL_NAMES
46+
// Clauses that refer to unevaluated constants as they cause cycles.
47+
| TypeFlags::HAS_CT_PROJECTION,
48+
)
49+
});
50+
let predicates: Vec<_> = traits::elaborate(tcx, predicates).collect();
51+
tracing::trace!(?predicates);
52+
predicates.references_error() || traits::impossible_predicates(tcx, predicates)
53+
}
54+
3855
impl<'tcx> MirPass<'tcx> for ImpossiblePredicates {
3956
#[tracing::instrument(level = "trace", skip(self, tcx, body))]
4057
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
4158
tracing::trace!(def_id = ?body.source.def_id());
42-
let predicates = tcx.predicates_of(body.source.def_id()).instantiate_identity(tcx);
43-
tracing::trace!(?predicates);
44-
let predicates = predicates.predicates.into_iter().filter(|p| {
45-
!p.has_type_flags(
46-
// Only consider global clauses to simplify.
47-
TypeFlags::HAS_FREE_LOCAL_NAMES
48-
// Clauses that refer to unevaluated constants as they cause cycles.
49-
| TypeFlags::HAS_CT_PROJECTION,
50-
)
51-
});
52-
let predicates: Vec<_> = traits::elaborate(tcx, predicates).collect();
53-
tracing::trace!(?predicates);
54-
if predicates.references_error() || traits::impossible_predicates(tcx, predicates) {
59+
let impossible = body.tainted_by_errors.is_some()
60+
|| has_impossible_predicates(tcx, body.source.def_id());
61+
if impossible {
5562
trace!("found unsatisfiable predicates");
5663
// Clear the body to only contain a single `unreachable` statement.
5764
let bbs = body.basic_blocks.as_mut();

tests/crashes/122904-2.rs

Lines changed: 0 additions & 17 deletions
This file was deleted.

tests/crashes/139556.rs

Lines changed: 0 additions & 13 deletions
This file was deleted.

tests/ui/consts/promoted_const_call2.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ pub const C: () = {
44
let _: &'static _ = &id(&String::new());
55
//~^ ERROR: temporary value dropped while borrowed
66
//~| ERROR: temporary value dropped while borrowed
7-
//~| ERROR: destructor of `String` cannot be evaluated at compile-time
87
};
98

109
fn main() {

tests/ui/consts/promoted_const_call2.stderr

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,8 @@ LL | let _: &'static _ = &id(&String::new());
1818
| | creates a temporary value which is freed while still in use
1919
| type annotation requires that borrow lasts for `'static`
2020

21-
error[E0493]: destructor of `String` cannot be evaluated at compile-time
22-
--> $DIR/promoted_const_call2.rs:4:30
23-
|
24-
LL | let _: &'static _ = &id(&String::new());
25-
| ^^^^^^^^^^^^^ - value is dropped here
26-
| |
27-
| the destructor for this type cannot be evaluated in constants
28-
2921
error[E0716]: temporary value dropped while borrowed
30-
--> $DIR/promoted_const_call2.rs:11:26
22+
--> $DIR/promoted_const_call2.rs:10:26
3123
|
3224
LL | let _: &'static _ = &id(&String::new());
3325
| ---------- ^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -38,15 +30,14 @@ LL | }
3830
| - temporary value is freed at the end of this statement
3931

4032
error[E0716]: temporary value dropped while borrowed
41-
--> $DIR/promoted_const_call2.rs:11:30
33+
--> $DIR/promoted_const_call2.rs:10:30
4234
|
4335
LL | let _: &'static _ = &id(&String::new());
4436
| ---------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
4537
| | |
4638
| | creates a temporary value which is freed while still in use
4739
| type annotation requires that borrow lasts for `'static`
4840

49-
error: aborting due to 5 previous errors
41+
error: aborting due to 4 previous errors
5042

51-
Some errors have detailed explanations: E0493, E0716.
52-
For more information about an error, try `rustc --explain E0493`.
43+
For more information about this error, try `rustc --explain E0716`.
Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,27 @@
1-
//@ known-bug: #122630
1+
//! Regression test for #122630
22
//@ compile-flags: -Zvalidate-mir
33

4+
#![feature(coroutines, coroutine_trait, yield_expr)]
5+
46
use std::ops::Coroutine;
57

68
const FOO_SIZE: usize = 1024;
79
struct Foo([u8; FOO_SIZE]);
810

911
impl Drop for Foo {
10-
fn move_before_yield_with_noop() -> impl Coroutine<Yield = ()> {}
12+
fn drop(&mut self) {}
1113
}
1214

1315
fn overlap_move_points() -> impl Coroutine<Yield = ()> {
14-
static || {
16+
#[coroutine] static || {
1517
let first = Foo([0; FOO_SIZE]);
1618
yield;
1719
let second = first;
1820
yield;
1921
let second = first;
22+
//~^ ERROR: use of moved value: `first` [E0382]
2023
yield;
2124
}
2225
}
26+
27+
fn main() {}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error[E0382]: use of moved value: `first`
2+
--> $DIR/moved-twice.rs:21:22
3+
|
4+
LL | let first = Foo([0; FOO_SIZE]);
5+
| ----- move occurs because `first` has type `Foo`, which does not implement the `Copy` trait
6+
LL | yield;
7+
LL | let second = first;
8+
| ----- value moved here
9+
LL | yield;
10+
LL | let second = first;
11+
| ^^^^^ value used here after move
12+
|
13+
note: if `Foo` implemented `Clone`, you could clone the value
14+
--> $DIR/moved-twice.rs:9:1
15+
|
16+
LL | struct Foo([u8; FOO_SIZE]);
17+
| ^^^^^^^^^^ consider implementing `Clone` for this type
18+
...
19+
LL | let second = first;
20+
| ----- you could clone this value
21+
22+
error: aborting due to 1 previous error
23+
24+
For more information about this error, try `rustc --explain E0382`.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//! Regression test for ICE #139556
2+
3+
#![feature(type_alias_impl_trait)]
4+
5+
trait T {}
6+
7+
type Alias<'a> = impl T;
8+
9+
struct S;
10+
impl<'a> T for &'a S {}
11+
12+
#[define_opaque(Alias)]
13+
fn with_positive(fun: impl Fn(Alias<'_>)) {
14+
//~^ WARN: function cannot return without recursing
15+
with_positive(|&n| ());
16+
//~^ ERROR: cannot move out of a shared reference
17+
}
18+
19+
fn main() {}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
warning: function cannot return without recursing
2+
--> $DIR/recursive-drop-elaboration-2.rs:13:1
3+
|
4+
LL | fn with_positive(fun: impl Fn(Alias<'_>)) {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
6+
LL |
7+
LL | with_positive(|&n| ());
8+
| ---------------------- recursive call site
9+
|
10+
= help: a `loop` may express intention better if this is on purpose
11+
= note: `#[warn(unconditional_recursion)]` on by default
12+
13+
error[E0507]: cannot move out of a shared reference
14+
--> $DIR/recursive-drop-elaboration-2.rs:15:20
15+
|
16+
LL | with_positive(|&n| ());
17+
| ^-
18+
| |
19+
| data moved here
20+
| move occurs because `n` has type `S`, which does not implement the `Copy` trait
21+
|
22+
help: consider removing the borrow
23+
|
24+
LL - with_positive(|&n| ());
25+
LL + with_positive(|n| ());
26+
|
27+
28+
error: aborting due to 1 previous error; 1 warning emitted
29+
30+
For more information about this error, try `rustc --explain E0507`.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//! Regression test for #122904.
2+
3+
#![feature(type_alias_impl_trait)]
4+
5+
trait T {}
6+
7+
type Alias<'a> = impl T;
8+
9+
struct S;
10+
impl<'a> T for &'a S {}
11+
12+
#[define_opaque(Alias)]
13+
fn with_positive(fun: impl Fn(Alias<'_>)) {
14+
//~^ WARN: function cannot return without recursing
15+
with_positive(|&n| ());
16+
//~^ ERROR: cannot move out of a shared reference
17+
}
18+
19+
#[define_opaque(Alias)]
20+
fn main(_: Alias<'_>) {
21+
//~^ ERROR: `main` function has wrong type [E0580]
22+
with_positive(|&a| ());
23+
//~^ ERROR: cannot move out of a shared reference
24+
}

0 commit comments

Comments
 (0)