From: Ariel Ben-Yehuda Date: Sun, 25 Oct 2015 21:02:15 +0000 (+0200) Subject: add a recursion limit for type representation X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=1220e016bd242cf17e005943c4f2cc3e0b5de20b;p=rust.git add a recursion limit for type representation I could have added a check for explicit recursion, as irregular types tend to cause selection errors, but I am not sufficiently sure that cannot be bypassed. Fixes #22919 Fixes #25639 Fixes #26548 --- diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs index b92e02fec5c..a14663483a9 100644 --- a/src/librustc_trans/trans/context.rs +++ b/src/librustc_trans/trans/context.rs @@ -156,6 +156,9 @@ pub struct LocalCrateContext<'tcx> { /// contexts around the same size. n_llvm_insns: Cell, + /// Depth of the current type-of computation - used to bail out + type_of_depth: Cell, + trait_cache: RefCell, traits::Vtable<'tcx, ()>>>, } @@ -470,6 +473,7 @@ fn new<'a>(shared: &SharedCrateContext<'a, 'tcx>, unwind_resume_hooked: Cell::new(false), intrinsics: RefCell::new(FnvHashMap()), n_llvm_insns: Cell::new(0), + type_of_depth: Cell::new(0), trait_cache: RefCell::new(FnvHashMap()), }; @@ -774,6 +778,17 @@ pub fn report_overbig_object(&self, obj: Ty<'tcx>) -> ! { obj)) } + pub fn enter_type_of(&self, ty: Ty<'tcx>) -> TypeOfDepthLock<'b, 'tcx> { + let current_depth = self.local.type_of_depth.get(); + debug!("enter_type_of({:?}) at depth {:?}", ty, current_depth); + if current_depth > self.sess().recursion_limit.get() { + self.sess().fatal( + &format!("overflow representing the type `{}`", ty)) + } + self.local.type_of_depth.set(current_depth + 1); + TypeOfDepthLock(self.local) + } + pub fn check_overflow(&self) -> bool { self.shared.check_overflow } @@ -790,6 +805,14 @@ pub fn use_dll_storage_attrs(&self) -> bool { } } +pub struct TypeOfDepthLock<'a, 'tcx: 'a>(&'a LocalCrateContext<'tcx>); + +impl<'a, 'tcx> Drop for TypeOfDepthLock<'a, 'tcx> { + fn drop(&mut self) { + self.0.type_of_depth.set(self.0.type_of_depth.get() - 1); + } +} + /// Declare any llvm intrinsics that you might need fn declare_intrinsic(ccx: &CrateContext, key: &str) -> Option { macro_rules! ifn { diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs index 437c0d9cbc3..50b9c0b5ad6 100644 --- a/src/librustc_trans/trans/type_of.rs +++ b/src/librustc_trans/trans/type_of.rs @@ -184,6 +184,8 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ } debug!("sizing_type_of {:?}", t); + let _recursion_lock = cx.enter_type_of(t); + let llsizingty = match t.sty { _ if !type_is_sized(cx.tcx(), t) => { Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false) diff --git a/src/test/compile-fail/issue-26548.rs b/src/test/compile-fail/issue-26548.rs new file mode 100644 index 00000000000..8b02e8e7046 --- /dev/null +++ b/src/test/compile-fail/issue-26548.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern: overflow representing the type `S` + +trait Mirror { type It; } +impl Mirror for T { type It = Self; } +struct S(Option<::It>); + +fn main() { + let _s = S(None); +}