Skip to content
Closed
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
10 changes: 9 additions & 1 deletion compiler/rustc_mir_transform/src/sroa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,17 @@ impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates {
return;
}

// Cap the number of iterations to avoid non-termination on tainted
// input (e.g. when layout cycle errors cause `iter_fields` to keep
// producing self-referential field types, cf.
// https://github.com/rust-lang/rust/issues/153205). In practice, 2
// iterations capture nearly all the value and more than 10 is never
// needed for non-contrived code, so 10 is enough.
const MAX_ITERATIONS: usize = 10;

let mut excluded = excluded_locals(body);
let typing_env = body.typing_env(tcx);
loop {
for _ in 0..MAX_ITERATIONS {
debug!(?excluded);
let escaping = escaping_locals(tcx, &excluded, body);
debug!(?escaping);
Expand Down
30 changes: 30 additions & 0 deletions tests/ui/layout/hang-sroa-layout-cycle.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//@ build-fail
//~^ ERROR cycle detected when computing layout of `Thing<Identity>`
//@ compile-flags: -Copt-level=3

// Regression test for https://github.com/rust-lang/rust/issues/153205:
// a struct that contains itself via an associated type used to cause the
// `ScalarReplacementOfAggregates` MIR pass to loop forever after the
// layout-cycle error was emitted. The SROA pass now bounds its iteration
// count, so the compile terminates with the expected layout-cycle error
// rather than hanging.

trait Apply {
type Output<T>;
}

struct Identity;

impl Apply for Identity {
type Output<T> = T;
}

struct Thing<A: Apply>(A::Output<Self>);

fn foo<A: Apply>() {
let _x: Thing<A>;
}

fn main() {
foo::<Identity>();
}
14 changes: 14 additions & 0 deletions tests/ui/layout/hang-sroa-layout-cycle.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error[E0391]: cycle detected when computing layout of `Thing<Identity>`
|
= note: ...which requires computing layout of `<Identity as Apply>::Output<Thing<Identity>>`...
= note: ...which again requires computing layout of `Thing<Identity>`, completing the cycle
note: cycle used when optimizing MIR for `main`
--> $DIR/hang-sroa-layout-cycle.rs:28:1
|
LL | fn main() {
| ^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0391`.
Loading