check the recursion limit when finding struct tail

This commit is contained in:
SNCPlay42 2020-11-26 15:32:41 +00:00
parent 0d9651648d
commit 98fc02d6fa
3 changed files with 45 additions and 2 deletions

View File

@ -18,7 +18,7 @@
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_macros::HashStable; use rustc_macros::HashStable;
use rustc_span::Span; use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::{Integer, Size, TargetDataLayout}; use rustc_target::abi::{Integer, Size, TargetDataLayout};
use smallvec::SmallVec; use smallvec::SmallVec;
use std::{cmp, fmt}; use std::{cmp, fmt};
@ -221,7 +221,13 @@ pub fn struct_tail_with_normalize(
mut ty: Ty<'tcx>, mut ty: Ty<'tcx>,
normalize: impl Fn(Ty<'tcx>) -> Ty<'tcx>, normalize: impl Fn(Ty<'tcx>) -> 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() { match *ty.kind() {
ty::Adt(def, substs) => { ty::Adt(def, substs) => {
if !def.is_struct() { if !def.is_struct() {

View File

@ -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() {}

View File

@ -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`.