diff options
| -rw-r--r-- | src/librustc/middle/traits/project.rs | 5 | ||||
| -rw-r--r-- | src/librustc_trans/trans/context.rs | 23 | ||||
| -rw-r--r-- | src/librustc_trans/trans/type_of.rs | 2 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-21946.rs | 22 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-26548.rs | 19 | ||||
| -rw-r--r-- | src/test/run-pass/issue-23992.rs | 28 |
6 files changed, 97 insertions, 2 deletions
diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index bf90b3a02a8..c1ff0f985cb 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -343,7 +343,8 @@ pub fn normalize_projection_type<'a,'b,'tcx>( projection_ty: projection_ty, ty: ty_var }); - let obligation = Obligation::with_depth(cause, depth+1, projection.to_predicate()); + let obligation = Obligation::with_depth( + cause, depth + 1, projection.to_predicate()); Normalized { value: ty_var, obligations: vec!(obligation) @@ -382,7 +383,7 @@ fn opt_normalize_projection_type<'a,'b,'tcx>( obligations); if projected_ty.has_projection_types() { - let mut normalizer = AssociatedTypeNormalizer::new(selcx, cause, depth); + let mut normalizer = AssociatedTypeNormalizer::new(selcx, cause, depth+1); let normalized_ty = normalizer.fold(&projected_ty); debug!("normalize_projection_type: normalized_ty={:?} depth={}", 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<usize>, + /// Depth of the current type-of computation - used to bail out + type_of_depth: Cell<usize>, + trait_cache: RefCell<FnvHashMap<ty::PolyTraitRef<'tcx>, traits::Vtable<'tcx, ()>>>, } @@ -470,6 +473,7 @@ impl<'tcx> LocalCrateContext<'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 @@ impl<'b, 'tcx> CrateContext<'b, '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 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { } } +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<ValueRef> { 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-21946.rs b/src/test/compile-fail/issue-21946.rs new file mode 100644 index 00000000000..0d652be5c26 --- /dev/null +++ b/src/test/compile-fail/issue-21946.rs @@ -0,0 +1,22 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Foo { + type A; +} + +struct FooStruct; + +impl Foo for FooStruct { +//~^ ERROR overflow evaluating the requirement `<FooStruct as Foo>::A` + type A = <FooStruct as Foo>::A; +} + +fn main() {} 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T> Mirror for T { type It = Self; } +struct S(Option<<S as Mirror>::It>); + +fn main() { + let _s = S(None); +} diff --git a/src/test/run-pass/issue-23992.rs b/src/test/run-pass/issue-23992.rs new file mode 100644 index 00000000000..d1ee4208b78 --- /dev/null +++ b/src/test/run-pass/issue-23992.rs @@ -0,0 +1,28 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub struct Outer<T: Trait>(T); +pub struct Inner<'a> { value: &'a bool } + +pub trait Trait { + type Error; + fn ready(self) -> Self::Error; +} + +impl<'a> Trait for Inner<'a> { + type Error = Outer<Inner<'a>>; + fn ready(self) -> Outer<Inner<'a>> { Outer(self) } +} + +fn main() { + let value = true; + let inner = Inner { value: &value }; + assert_eq!(inner.ready().0.value, &value); +} |
