about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/middle/traits/project.rs5
-rw-r--r--src/librustc_trans/trans/context.rs23
-rw-r--r--src/librustc_trans/trans/type_of.rs2
-rw-r--r--src/test/compile-fail/issue-21946.rs22
-rw-r--r--src/test/compile-fail/issue-26548.rs19
-rw-r--r--src/test/run-pass/issue-23992.rs28
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);
+}