about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-01-15 14:11:47 -0800
committerAlex Crichton <alex@alexcrichton.com>2015-01-15 14:11:47 -0800
commit692d9426e77757c976cfb841105c159af2385d36 (patch)
tree5342804cb2443b9d50eac2bf43046187836e59ae
parentd7009e6f31c63fc2e0ba2153e6354ce44663ddb4 (diff)
parent2479dfcbf7abc401e5925bf5d53b7ac2e0eed694 (diff)
downloadrust-692d9426e77757c976cfb841105c159af2385d36.tar.gz
rust-692d9426e77757c976cfb841105c159af2385d36.zip
rollup merge of #21107: nikomatsakis/assoc-type-ice-hunt-take-1
Fixes for #20831 and #21010

r? @nick29581
-rw-r--r--src/librustc/middle/ty.rs16
-rw-r--r--src/librustc/util/ppaux.rs2
-rw-r--r--src/librustc_trans/trans/common.rs11
-rw-r--r--src/librustc_trans/trans/debuginfo.rs80
-rw-r--r--src/librustc_typeck/astconv.rs74
-rw-r--r--src/test/compile-fail/issue-20831-debruijn.rs49
-rw-r--r--src/test/run-pass/associated-types-normalize-unifield-struct.rs32
-rw-r--r--src/test/run-pass/associated-types-projection-in-object-type.rs43
-rw-r--r--src/test/run-pass/regions-debruijn-of-object.rs (renamed from src/test/debuginfo/associated_types.rs)27
9 files changed, 226 insertions, 108 deletions
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 525fe86cf24..46cce164781 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -2605,12 +2605,17 @@ impl FlagComputation {
 
             &ty_projection(ref data) => {
                 self.add_flags(HAS_PROJECTION);
-                self.add_substs(data.trait_ref.substs);
+                self.add_projection_ty(data);
             }
 
             &ty_trait(box TyTrait { ref principal, ref bounds }) => {
                 let mut computation = FlagComputation::new();
                 computation.add_substs(principal.0.substs);
+                for projection_bound in bounds.projection_bounds.iter() {
+                    let mut proj_computation = FlagComputation::new();
+                    proj_computation.add_projection_predicate(&projection_bound.0);
+                    computation.add_bound_computation(&proj_computation);
+                }
                 self.add_bound_computation(&computation);
 
                 self.add_bounds(bounds);
@@ -2674,6 +2679,15 @@ impl FlagComputation {
         }
     }
 
+    fn add_projection_predicate(&mut self, projection_predicate: &ProjectionPredicate) {
+        self.add_projection_ty(&projection_predicate.projection_ty);
+        self.add_ty(projection_predicate.ty);
+    }
+
+    fn add_projection_ty(&mut self, projection_ty: &ProjectionTy) {
+        self.add_substs(projection_ty.trait_ref.substs);
+    }
+
     fn add_substs(&mut self, substs: &Substs) {
         self.add_tys(substs.types.as_slice());
         match substs.regions {
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 1a1ad899d4e..fb44d0cadfa 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -1430,7 +1430,7 @@ impl<'tcx> UserString<'tcx> for ty::ProjectionPredicate<'tcx> {
 impl<'tcx> Repr<'tcx> for ty::ProjectionTy<'tcx> {
     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
         format!("<{} as {}>::{}",
-                self.trait_ref.self_ty().repr(tcx),
+                self.trait_ref.substs.self_ty().repr(tcx),
                 self.trait_ref.repr(tcx),
                 self.item_name.repr(tcx))
     }
diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs
index f59e70d099a..3eee4637de1 100644
--- a/src/librustc_trans/trans/common.rs
+++ b/src/librustc_trans/trans/common.rs
@@ -217,12 +217,15 @@ pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>,
     ty::type_contents(cx, ty).needs_drop(cx)
 }
 
-fn type_is_newtype_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                                   ty: Ty<'tcx>) -> bool {
+fn type_is_newtype_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
     match ty.sty {
         ty::ty_struct(def_id, substs) => {
-            let fields = ty::struct_fields(ccx.tcx(), def_id, substs);
-            fields.len() == 1 && type_is_immediate(ccx, fields[0].mt.ty)
+            let fields = ty::lookup_struct_fields(ccx.tcx(), def_id);
+            fields.len() == 1 && {
+                let ty = ty::lookup_field_type(ccx.tcx(), def_id, fields[0].id, substs);
+                let ty = monomorphize::normalize_associated_type(ccx.tcx(), &ty);
+                type_is_immediate(ccx, ty)
+            }
         }
         _ => false
     }
diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs
index d5416ae0631..0ef0fa6dfe6 100644
--- a/src/librustc_trans/trans/debuginfo.rs
+++ b/src/librustc_trans/trans/debuginfo.rs
@@ -323,28 +323,26 @@ impl<'tcx> TypeMap<'tcx> {
     fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>,
                                       type_: Ty<'tcx>) -> UniqueTypeId {
 
-        // basic type               -> {:name of the type:}
-        // tuple                    -> {tuple_(:param-uid:)*}
-        // struct                   -> {struct_:svh: / :node-id:_<(:param-uid:),*> }
-        // enum                     -> {enum_:svh: / :node-id:_<(:param-uid:),*> }
-        // enum variant             -> {variant_:variant-name:_:enum-uid:}
-        // reference (&)            -> {& :pointee-uid:}
-        // mut reference (&mut)     -> {&mut :pointee-uid:}
-        // ptr (*)                  -> {* :pointee-uid:}
-        // mut ptr (*mut)           -> {*mut :pointee-uid:}
-        // unique ptr (~)           -> {~ :pointee-uid:}
-        // @-ptr (@)                -> {@ :pointee-uid:}
-        // sized vec ([T; x])       -> {[:size:] :element-uid:}
-        // unsized vec ([T])        -> {[] :element-uid:}
-        // trait (T)                -> {trait_:svh: / :node-id:_<(:param-uid:),*> }
-        // closure                  -> {<unsafe_> <once_> :store-sigil:
-        //                                  |(:param-uid:),* <,_...>| -> \
-        //                                  :return-type-uid: : (:bounds:)*}
-        // function                 -> {<unsafe_> <abi_> fn( (:param-uid:)* <,_...> ) -> \
-        //                                  :return-type-uid:}
-        // unique vec box (~[])     -> {HEAP_VEC_BOX<:pointee-uid:>}
-        // gc box                   -> {GC_BOX<:pointee-uid:>}
-        // projection (<T as U>::V) -> {<:ty-uid: as :trait-uid:> :: :name-uid: }
+        // basic type           -> {:name of the type:}
+        // tuple                -> {tuple_(:param-uid:)*}
+        // struct               -> {struct_:svh: / :node-id:_<(:param-uid:),*> }
+        // enum                 -> {enum_:svh: / :node-id:_<(:param-uid:),*> }
+        // enum variant         -> {variant_:variant-name:_:enum-uid:}
+        // reference (&)        -> {& :pointee-uid:}
+        // mut reference (&mut) -> {&mut :pointee-uid:}
+        // ptr (*)              -> {* :pointee-uid:}
+        // mut ptr (*mut)       -> {*mut :pointee-uid:}
+        // unique ptr (~)       -> {~ :pointee-uid:}
+        // @-ptr (@)            -> {@ :pointee-uid:}
+        // sized vec ([T; x])   -> {[:size:] :element-uid:}
+        // unsized vec ([T])    -> {[] :element-uid:}
+        // trait (T)            -> {trait_:svh: / :node-id:_<(:param-uid:),*> }
+        // closure              -> {<unsafe_> <once_> :store-sigil: |(:param-uid:),* <,_...>| -> \
+        //                             :return-type-uid: : (:bounds:)*}
+        // function             -> {<unsafe_> <abi_> fn( (:param-uid:)* <,_...> ) -> \
+        //                             :return-type-uid:}
+        // unique vec box (~[]) -> {HEAP_VEC_BOX<:pointee-uid:>}
+        // gc box               -> {GC_BOX<:pointee-uid:>}
 
         match self.type_to_unique_id.get(&type_).cloned() {
             Some(unique_type_id) => return unique_type_id,
@@ -437,25 +435,6 @@ impl<'tcx> TypeMap<'tcx> {
                                        principal.substs,
                                        &mut unique_type_id);
             },
-            ty::ty_projection(ref projection) => {
-                unique_type_id.push_str("<");
-
-                let self_ty = projection.trait_ref.self_ty();
-                let self_type_id = self.get_unique_type_id_of_type(cx, self_ty);
-                let self_type_id = self.get_unique_type_id_as_string(self_type_id);
-                unique_type_id.push_str(&self_type_id[]);
-
-                unique_type_id.push_str(" as ");
-
-                from_def_id_and_substs(self,
-                                       cx,
-                                       projection.trait_ref.def_id,
-                                       projection.trait_ref.substs,
-                                       &mut unique_type_id);
-
-                unique_type_id.push_str(">::");
-                unique_type_id.push_str(token::get_name(projection.item_name).get());
-            },
             ty::ty_bare_fn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
                 if unsafety == ast::Unsafety::Unsafe {
                     unique_type_id.push_str("unsafe ");
@@ -499,10 +478,7 @@ impl<'tcx> TypeMap<'tcx> {
                                                         closure_ty,
                                                         &mut unique_type_id);
             },
-            ty::ty_err |
-            ty::ty_infer(_) |
-            ty::ty_open(_) |
-            ty::ty_param(_) => {
+            _ => {
                 cx.sess().bug(&format!("get_unique_type_id_of_type() - unexpected type: {}, {:?}",
                                       &ppaux::ty_to_string(cx.tcx(), type_)[],
                                       type_.sty)[])
@@ -3880,22 +3856,10 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         ty::ty_unboxed_closure(..) => {
             output.push_str("closure");
         }
-        ty::ty_projection(ref projection) => {
-            output.push_str("<");
-            let self_ty = projection.trait_ref.self_ty();
-            push_debuginfo_type_name(cx, self_ty, true, output);
-
-            output.push_str(" as ");
-
-            push_item_name(cx, projection.trait_ref.def_id, false, output);
-            push_type_params(cx, projection.trait_ref.substs, output);
-
-            output.push_str(">::");
-            output.push_str(token::get_name(projection.item_name).get());
-        }
         ty::ty_err |
         ty::ty_infer(_) |
         ty::ty_open(_) |
+        ty::ty_projection(..) |
         ty::ty_param(_) => {
             cx.sess().bug(&format!("debuginfo: Trying to create type name for \
                 unexpected type: {}", ppaux::ty_to_string(cx.tcx(), t))[]);
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 27d31a3a2f7..f2927dfd843 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -516,8 +516,15 @@ pub fn instantiate_poly_trait_ref<'tcx>(
 {
     let mut projections = Vec::new();
 
+    // the trait reference introduces a binding level here, so
+    // we need to shift the `rscope`. It'd be nice if we could
+    // do away with this rscope stuff and work this knowledge
+    // into resolve_lifetimes, as we do with non-omitted
+    // lifetimes. Oh well, not there yet.
+    let shifted_rscope = ShiftedRscope::new(rscope);
+
     let trait_ref =
-        instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref,
+        instantiate_trait_ref(this, &shifted_rscope, &ast_trait_ref.trait_ref,
                               self_ty, Some(&mut projections));
 
     for projection in projections.into_iter() {
@@ -561,6 +568,29 @@ pub fn instantiate_trait_ref<'tcx>(
     }
 }
 
+fn object_path_to_poly_trait_ref<'a,'tcx>(
+    this: &AstConv<'tcx>,
+    rscope: &RegionScope,
+    trait_def_id: ast::DefId,
+    path: &ast::Path,
+    mut projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
+    -> ty::PolyTraitRef<'tcx>
+{
+    // we are introducing a binder here, so shift the
+    // anonymous regions depth to account for that
+    let shifted_rscope = ShiftedRscope::new(rscope);
+
+    let mut tmp = Vec::new();
+    let trait_ref = ty::Binder(ast_path_to_trait_ref(this,
+                                                     &shifted_rscope,
+                                                     trait_def_id,
+                                                     None,
+                                                     path,
+                                                     Some(&mut tmp)));
+    projections.extend(tmp.into_iter().map(ty::Binder));
+    trait_ref
+}
+
 fn ast_path_to_trait_ref<'a,'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
@@ -573,13 +603,6 @@ fn ast_path_to_trait_ref<'a,'tcx>(
     debug!("ast_path_to_trait_ref {:?}", path);
     let trait_def = this.get_trait_def(trait_def_id);
 
-    // the trait reference introduces a binding level here, so
-    // we need to shift the `rscope`. It'd be nice if we could
-    // do away with this rscope stuff and work this knowledge
-    // into resolve_lifetimes, as we do with non-omitted
-    // lifetimes. Oh well, not there yet.
-    let shifted_rscope = ShiftedRscope::new(rscope);
-
     let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters {
         ast::AngleBracketedParameters(ref data) => {
             // For now, require that parenthetical notation be used
@@ -595,7 +618,7 @@ fn ast_path_to_trait_ref<'a,'tcx>(
                             the crate attributes to enable");
             }
 
-            convert_angle_bracketed_parameters(this, &shifted_rscope, data)
+            convert_angle_bracketed_parameters(this, rscope, data)
         }
         ast::ParenthesizedParameters(ref data) => {
             // For now, require that parenthetical notation be used
@@ -616,7 +639,7 @@ fn ast_path_to_trait_ref<'a,'tcx>(
     };
 
     let substs = create_substs_for_ast_path(this,
-                                            &shifted_rscope,
+                                            rscope,
                                             path.span,
                                             &trait_def.generics,
                                             self_ty,
@@ -851,15 +874,11 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
             match this.tcx().def_map.borrow().get(&id) {
                 Some(&def::DefTrait(trait_def_id)) => {
                     let mut projection_bounds = Vec::new();
-                    let trait_ref = ty::Binder(ast_path_to_trait_ref(this,
-                                                                     rscope,
-                                                                     trait_def_id,
-                                                                     None,
-                                                                     path,
-                                                                     Some(&mut projection_bounds)));
-                    let projection_bounds = projection_bounds.into_iter()
-                                                             .map(ty::Binder)
-                                                             .collect();
+                    let trait_ref = object_path_to_poly_trait_ref(this,
+                                                                  rscope,
+                                                                  trait_def_id,
+                                                                  path,
+                                                                  &mut projection_bounds);
                     Ok((trait_ref, projection_bounds))
                 }
                 _ => {
@@ -1098,16 +1117,13 @@ pub fn ast_ty_to_ty<'tcx>(
                         // N.B. this case overlaps somewhat with
                         // TyObjectSum, see that fn for details
                         let mut projection_bounds = Vec::new();
-                        let trait_ref = ast_path_to_trait_ref(this,
-                                                              rscope,
-                                                              trait_def_id,
-                                                              None,
-                                                              path,
-                                                              Some(&mut projection_bounds));
-                        let trait_ref = ty::Binder(trait_ref);
-                        let projection_bounds = projection_bounds.into_iter()
-                                                                 .map(ty::Binder)
-                                                                 .collect();
+
+                        let trait_ref = object_path_to_poly_trait_ref(this,
+                                                                      rscope,
+                                                                      trait_def_id,
+                                                                      path,
+                                                                      &mut projection_bounds);
+
                         trait_ref_to_object_type(this, rscope, path.span,
                                                  trait_ref, projection_bounds, &[])
                     }
diff --git a/src/test/compile-fail/issue-20831-debruijn.rs b/src/test/compile-fail/issue-20831-debruijn.rs
new file mode 100644
index 00000000000..aaf45f27398
--- /dev/null
+++ b/src/test/compile-fail/issue-20831-debruijn.rs
@@ -0,0 +1,49 @@
+// 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.
+
+// Regression test for #20831: debruijn index account was thrown off
+// by the (anonymous) lifetime in `<Self as Publisher>::Output`
+// below. Note that changing to a named lifetime made the problem go
+// away.
+
+use std::ops::{Shl, Shr};
+use std::cell::RefCell;
+
+pub trait Subscriber {
+    type Input;
+}
+
+pub trait Publisher<'a> {
+    type Output;
+    fn subscribe(&mut self, Box<Subscriber<Input=Self::Output> + 'a>);
+}
+
+pub trait Processor<'a> : Subscriber + Publisher<'a> { }
+
+impl<'a, P> Processor<'a> for P where P : Subscriber + Publisher<'a> { }
+
+struct MyStruct<'a> {
+    sub: Box<Subscriber<Input=u64> + 'a>
+}
+
+impl<'a> Publisher<'a> for MyStruct<'a> {
+    type Output = u64;
+    fn subscribe(&mut self, t : Box<Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+        // Not obvious, but there is an implicit lifetime here -------^
+        //~^^ ERROR cannot infer
+        //
+        // The fact that `Publisher` is using an implicit lifetime is
+        // what was causing the debruijn accounting to be off, so
+        // leave it that way!
+        self.sub = t;
+    }
+}
+
+fn main() {}
diff --git a/src/test/run-pass/associated-types-normalize-unifield-struct.rs b/src/test/run-pass/associated-types-normalize-unifield-struct.rs
new file mode 100644
index 00000000000..c517f61de0c
--- /dev/null
+++ b/src/test/run-pass/associated-types-normalize-unifield-struct.rs
@@ -0,0 +1,32 @@
+// 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.
+
+// Regression test for issue #21010: Normalize associated types in
+// various special paths in the `type_is_immediate` function.
+
+#![allow(unstable)]
+
+pub trait OffsetState: Sized {}
+pub trait Offset { type State: OffsetState; }
+
+#[derive(Copy)] pub struct X;
+impl Offset for X { type State = Y; }
+
+#[derive(Copy)] pub struct Y;
+impl OffsetState for Y {}
+
+pub fn now() -> DateTime<X> { from_utc(Y) }
+
+pub struct DateTime<Off: Offset> { pub offset: Off::State }
+pub fn from_utc<Off: Offset>(offset: Off::State) -> DateTime<Off> { DateTime { offset: offset } }
+
+pub fn main() {
+    let _x = now();
+}
diff --git a/src/test/run-pass/associated-types-projection-in-object-type.rs b/src/test/run-pass/associated-types-projection-in-object-type.rs
new file mode 100644
index 00000000000..44dd49b7297
--- /dev/null
+++ b/src/test/run-pass/associated-types-projection-in-object-type.rs
@@ -0,0 +1,43 @@
+// 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.
+
+// Corrected regression test for #20831. The original did not compile.
+// When fixed, it revealed another problem concerning projections that
+// appear in associated type bindings in object types, which were not
+// being properly flagged.
+
+use std::ops::{Shl, Shr};
+use std::cell::RefCell;
+
+pub trait Subscriber {
+    type Input;
+}
+
+pub trait Publisher<'a> {
+    type Output;
+    fn subscribe(&mut self, Box<Subscriber<Input=Self::Output> + 'a>);
+}
+
+pub trait Processor<'a> : Subscriber + Publisher<'a> { }
+
+impl<'a, P> Processor<'a> for P where P : Subscriber + Publisher<'a> { }
+
+struct MyStruct<'a> {
+    sub: Box<Subscriber<Input=u64> + 'a>
+}
+
+impl<'a> Publisher<'a> for MyStruct<'a> {
+    type Output = u64;
+    fn subscribe(&mut self, t : Box<Subscriber<Input=u64> + 'a>) {
+        self.sub = t;
+    }
+}
+
+fn main() {}
diff --git a/src/test/debuginfo/associated_types.rs b/src/test/run-pass/regions-debruijn-of-object.rs
index 92336e9b34b..b9d3ed49c62 100644
--- a/src/test/debuginfo/associated_types.rs
+++ b/src/test/run-pass/regions-debruijn-of-object.rs
@@ -1,4 +1,4 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -8,21 +8,18 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-android: FIXME(#10381)
-// min-lldb-version: 310
-
-// compile-flags:-g
+struct ctxt<'tcx> {
+    x: &'tcx i32
+}
 
-struct Peekable<I> where I: Iterator {
-    _iter: I,
-    _next: Option<<I as Iterator>::Item>,
+trait AstConv<'tcx> {
+    fn tcx<'a>(&'a self) -> &'a ctxt<'tcx>;
 }
 
-fn main() {
-    let mut iter = Vec::<i32>::new().into_iter();
-    let next = iter.next();
-    let _v = Peekable {
-        _iter: iter,
-        _next : next,
-    };
+fn foo(conv: &AstConv) { }
+
+fn bar<'tcx>(conv: &AstConv<'tcx>) {
+    foo(conv)
 }
+
+fn main() { }