diff options
| author | SNCPlay42 <SNCPlay42@gmail.com> | 2020-11-26 15:32:41 +0000 |
|---|---|---|
| committer | SNCPlay42 <SNCPlay42@gmail.com> | 2020-12-04 16:37:23 +0000 |
| commit | 98fc02d6faeb39c7a4264af8ffdedc6a5a157f89 (patch) | |
| tree | 3538f67ad8c5ec4850e34782711a48aa82e69070 | |
| parent | 0d9651648d3b741e81ba7042e49a07b78a441517 (diff) | |
| download | rust-98fc02d6faeb39c7a4264af8ffdedc6a5a157f89.tar.gz rust-98fc02d6faeb39c7a4264af8ffdedc6a5a157f89.zip | |
check the recursion limit when finding struct tail
| -rw-r--r-- | compiler/rustc_middle/src/ty/util.rs | 10 | ||||
| -rw-r--r-- | src/test/ui/infinite/infinite-struct.rs | 10 | ||||
| -rw-r--r-- | src/test/ui/infinite/infinite-struct.stderr | 27 |
3 files changed, 45 insertions, 2 deletions
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index e23c3f51967..25787f005aa 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -18,7 +18,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{Integer, Size, TargetDataLayout}; use smallvec::SmallVec; use std::{cmp, fmt}; @@ -221,7 +221,13 @@ impl<'tcx> TyCtxt<'tcx> { mut ty: Ty<'tcx>, normalize: impl Fn(Ty<'tcx>) -> Ty<'tcx>, ) -> Ty<'tcx> { - loop { + for iteration in 0.. { + if !self.sess.recursion_limit().value_within_limit(iteration) { + return self.ty_error_with_message( + DUMMY_SP, + &format!("reached the recursion limit finding the struct tail for {}", ty), + ); + } match *ty.kind() { ty::Adt(def, substs) => { if !def.is_struct() { diff --git a/src/test/ui/infinite/infinite-struct.rs b/src/test/ui/infinite/infinite-struct.rs new file mode 100644 index 00000000000..70a203ea6e8 --- /dev/null +++ b/src/test/ui/infinite/infinite-struct.rs @@ -0,0 +1,10 @@ +struct Take(Take); +//~^ ERROR has infinite size +//~| ERROR cycle detected + +// check that we don't hang trying to find the tail of a recursive struct (#79437) +fn foo() -> Take { + Take(loop {}) +} + +fn main() {} diff --git a/src/test/ui/infinite/infinite-struct.stderr b/src/test/ui/infinite/infinite-struct.stderr new file mode 100644 index 00000000000..d180670e38f --- /dev/null +++ b/src/test/ui/infinite/infinite-struct.stderr @@ -0,0 +1,27 @@ +error[E0072]: recursive type `Take` has infinite size + --> $DIR/infinite-struct.rs:1:1 + | +LL | struct Take(Take); + | ^^^^^^^^^^^^----^^ + | | | + | | recursive without indirection + | recursive type has infinite size + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Take` representable + | +LL | struct Take(Box<Take>); + | ^^^^ ^ + +error[E0391]: cycle detected when computing drop-check constraints for `Take` + --> $DIR/infinite-struct.rs:1:1 + | +LL | struct Take(Take); + | ^^^^^^^^^^^^^^^^^^ + | + = note: ...which again requires computing drop-check constraints for `Take`, completing the cycle + = note: cycle used when computing dropck types for `Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: Take } }` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0072, E0391. +For more information about an error, try `rustc --explain E0072`. |
