about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSNCPlay42 <SNCPlay42@gmail.com>2020-11-26 15:32:41 +0000
committerSNCPlay42 <SNCPlay42@gmail.com>2020-12-04 16:37:23 +0000
commit98fc02d6faeb39c7a4264af8ffdedc6a5a157f89 (patch)
tree3538f67ad8c5ec4850e34782711a48aa82e69070
parent0d9651648d3b741e81ba7042e49a07b78a441517 (diff)
downloadrust-98fc02d6faeb39c7a4264af8ffdedc6a5a157f89.tar.gz
rust-98fc02d6faeb39c7a4264af8ffdedc6a5a157f89.zip
check the recursion limit when finding struct tail
-rw-r--r--compiler/rustc_middle/src/ty/util.rs10
-rw-r--r--src/test/ui/infinite/infinite-struct.rs10
-rw-r--r--src/test/ui/infinite/infinite-struct.stderr27
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`.