]> git.lizzy.rs Git - rust.git/commitdiff
Refactor QPath to take an ast::TraitRef
authorNiko Matsakis <niko@alum.mit.edu>
Sat, 8 Nov 2014 11:59:10 +0000 (06:59 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Wed, 19 Nov 2014 10:53:40 +0000 (05:53 -0500)
16 files changed:
src/librustc/middle/resolve.rs
src/librustc/middle/subst.rs
src/librustc/middle/traits/mod.rs
src/librustc/middle/traits/select.rs
src/librustc/middle/traits/util.rs
src/librustc/middle/typeck/astconv.rs
src/librustc/middle/typeck/collect.rs
src/librustc/util/common.rs
src/libsyntax/ast.rs
src/libsyntax/fold.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/visit.rs
src/test/compile-fail/associated-types-in-ambiguous-context.rs
src/test/compile-fail/associated-types-in-wrong-context.rs
src/test/run-pass/associated-types-qualified-path-with-trait-with-type-parameters.rs [new file with mode: 0644]

index baf53cc34ba94bded0b8fa304f13663e15ad8621..f369f00a14e304d1d7719aa2ad08ea4af97c1ed9 100644 (file)
@@ -633,6 +633,7 @@ enum TraitReferenceType {
     TraitDerivation,                 // trait T : SomeTrait { ... }
     TraitBoundingTypeParameter,      // fn f<T:SomeTrait>() { ... }
     TraitObject,                     // Box<for<'a> SomeTrait>
+    TraitQPath,                      // <T as SomeTrait>::
 }
 
 impl NameBindings {
@@ -4532,6 +4533,7 @@ fn resolve_trait_reference(&mut self,
                     TraitImplementation        => "implement",
                     TraitDerivation            => "derive",
                     TraitObject                => "reference",
+                    TraitQPath                 => "extract an associated type from",
                 };
 
                 let msg = format!("attempt to {} a nonexistent trait `{}`", usage_str, path_str);
@@ -4969,65 +4971,8 @@ fn resolve_type(&mut self, ty: &Ty) {
             }
 
             TyQPath(ref qpath) => {
-                self.resolve_type(&*qpath.for_type);
-
-                let current_module = self.current_module.clone();
-                let module_path: Vec<_> =
-                    qpath.trait_name
-                         .segments
-                         .iter()
-                         .map(|ps| ps.identifier.name)
-                         .collect();
-                match self.resolve_module_path(
-                        current_module,
-                        module_path.as_slice(),
-                        UseLexicalScope,
-                        qpath.trait_name.span,
-                        PathSearch) {
-                    Success((ref module, _)) if module.kind.get() ==
-                            TraitModuleKind => {
-                        match self.resolve_definition_of_name_in_module(
-                                (*module).clone(),
-                                qpath.item_name.name,
-                                TypeNS) {
-                            ChildNameDefinition(def, lp) |
-                            ImportNameDefinition(def, lp) => {
-                                match def {
-                                    DefAssociatedTy(trait_type_id) => {
-                                        let def = DefAssociatedTy(
-                                            trait_type_id);
-                                        self.record_def(ty.id, (def, lp));
-                                    }
-                                    _ => {
-                                        self.resolve_error(
-                                            ty.span,
-                                            "not an associated type");
-                                    }
-                                }
-                            }
-                            NoNameDefinition => {
-                                self.resolve_error(ty.span,
-                                                   "unresolved associated \
-                                                    type");
-                            }
-                        }
-                    }
-                    Success(..) => self.resolve_error(ty.span, "not a trait"),
-                    Indeterminate => {
-                        self.session.span_bug(ty.span,
-                                              "indeterminate result when \
-                                               resolving associated type")
-                    }
-                    Failed(error) => {
-                        let (span, help) = match error {
-                            Some((span, msg)) => (span, format!("; {}", msg)),
-                            None => (ty.span, String::new()),
-                        };
-                        self.resolve_error(span,
-                                           format!("unresolved trait: {}",
-                                                   help).as_slice())
-                    }
-                }
+                self.resolve_type(&*qpath.self_type);
+                self.resolve_trait_reference(ty.id, &*qpath.trait_ref, TraitQPath);
             }
 
             TyClosure(ref c) | TyProc(ref c) => {
index bac417c8218a4383ab0f0bce396c3119bb6d5af9..b030867fc841c5fbe6670ef76c2417d2c7e687ca 100644 (file)
@@ -100,6 +100,10 @@ pub fn is_noop(&self) -> bool {
         regions_is_noop && self.types.is_empty()
     }
 
+    pub fn type_for_def(&self, ty_param_def: &ty::TypeParameterDef) -> Ty<'tcx> {
+        *self.types.get(ty_param_def.space, ty_param_def.index)
+    }
+
     pub fn has_regions_escaping_depth(&self, depth: uint) -> bool {
         self.types.iter().any(|&t| ty::type_escapes_depth(t, depth)) || {
             match self.regions {
index c5eacf35da92fd6e09bed8d9b46d2836fe8f25d4..d34d413225e808f89a91dee0f4e83a29b12271d4 100644 (file)
@@ -25,6 +25,7 @@
 use std::slice::Items;
 use syntax::ast;
 use syntax::codemap::{Span, DUMMY_SP};
+use util::common::ErrorReported;
 
 pub use self::fulfill::FulfillmentContext;
 pub use self::select::SelectionContext;
@@ -95,10 +96,6 @@ pub enum ObligationCauseCode<'tcx> {
     FieldSized,
 }
 
-// An error has already been reported to the user, so no need to continue checking.
-#[deriving(Clone,Show)]
-pub struct ErrorReported;
-
 pub type Obligations<'tcx> = subst::VecPerParamSpace<Obligation<'tcx>>;
 
 pub type Selection<'tcx> = Vtable<'tcx, Obligation<'tcx>>;
index b884cb535d7a5de9488ac78b33eb4ca2be92fc6e..9cb7023e1b59f777f99f9be3036aaa75b9cfba37 100644 (file)
@@ -17,7 +17,6 @@
 use self::BuiltinBoundConditions::*;
 use self::EvaluationResult::*;
 
-use super::{ErrorReported};
 use super::{Obligation, ObligationCause};
 use super::{SelectionError, Unimplemented, Overflow,
             OutputTypeParameterMismatch};
@@ -38,6 +37,7 @@
 use std::collections::hash_map::HashMap;
 use std::rc::Rc;
 use syntax::ast;
+use util::common::ErrorReported;
 use util::ppaux::Repr;
 
 pub struct SelectionContext<'cx, 'tcx:'cx> {
index dfd436bdc4d306458f0b49869612690b66b6232f..ec49d5010562b8d966a00e63bca3083794030a78 100644 (file)
 use std::rc::Rc;
 use syntax::ast;
 use syntax::codemap::Span;
+use util::common::ErrorReported;
 use util::ppaux::Repr;
 
-use super::{ErrorReported, Obligation, ObligationCause, VtableImpl,
+use super::{Obligation, ObligationCause, VtableImpl,
             VtableParam, VtableParamData, VtableImplData};
 
 ///////////////////////////////////////////////////////////////////////////
index ea652bc7e6599cc393b06e7135277d0a89d48562..637c1f58157e20c29170d6682f0c27e925f3d3ee 100644 (file)
@@ -207,7 +207,6 @@ fn ast_path_substs_for_ty<'tcx,AC,RS>(
     decl_def_id: ast::DefId,
     decl_generics: &ty::Generics<'tcx>,
     self_ty: Option<Ty<'tcx>>,
-    associated_ty: Option<Ty<'tcx>>,
     path: &ast::Path)
     -> Substs<'tcx>
     where AC: AstConv<'tcx>, RS: RegionScope
@@ -243,7 +242,7 @@ fn ast_path_substs_for_ty<'tcx,AC,RS>(
     };
 
     create_substs_for_ast_path(this, rscope, path.span, decl_def_id,
-                               decl_generics, self_ty, types, regions, associated_ty)
+                               decl_generics, self_ty, types, regions)
 }
 
 fn create_substs_for_ast_path<'tcx,AC,RS>(
@@ -254,8 +253,7 @@ fn create_substs_for_ast_path<'tcx,AC,RS>(
     decl_generics: &ty::Generics<'tcx>,
     self_ty: Option<Ty<'tcx>>,
     types: Vec<Ty<'tcx>>,
-    regions: Vec<ty::Region>,
-    associated_ty: Option<Ty<'tcx>>)
+    regions: Vec<ty::Region>)
     -> Substs<'tcx>
     where AC: AstConv<'tcx>, RS: RegionScope
 {
@@ -366,9 +364,9 @@ fn create_substs_for_ast_path<'tcx,AC,RS>(
         substs.types.push(
             AssocSpace,
             this.associated_type_binding(span,
-                                         associated_ty,
+                                         self_ty,
                                          decl_def_id,
-                                         param.def_id))
+                                         param.def_id));
     }
 
     return substs;
@@ -417,19 +415,17 @@ pub fn instantiate_poly_trait_ref<'tcx,AC,RS>(
     this: &AC,
     rscope: &RS,
     ast_trait_ref: &ast::PolyTraitRef,
-    self_ty: Option<Ty<'tcx>>,
-    associated_type: Option<Ty<'tcx>>)
+    self_ty: Option<Ty<'tcx>>)
     -> Rc<ty::TraitRef<'tcx>>
     where AC: AstConv<'tcx>, RS: RegionScope
 {
-    instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref, self_ty, associated_type)
+    instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref, self_ty)
 }
 
 pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC,
                                          rscope: &RS,
                                          ast_trait_ref: &ast::TraitRef,
-                                         self_ty: Option<Ty<'tcx>>,
-                                         associated_type: Option<Ty<'tcx>>)
+                                         self_ty: Option<Ty<'tcx>>)
                                          -> Rc<ty::TraitRef<'tcx>>
                                          where AC: AstConv<'tcx>,
                                                RS: RegionScope
@@ -444,8 +440,8 @@ pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC,
                          ast_trait_ref.path.span,
                          ast_trait_ref.ref_id) {
         def::DefTrait(trait_def_id) => {
-            let trait_ref = Rc::new(ast_path_to_trait_ref(this, rscope, trait_def_id, self_ty,
-                                                          associated_type, &ast_trait_ref.path));
+            let trait_ref = Rc::new(ast_path_to_trait_ref(this, rscope, trait_def_id,
+                                                          self_ty, &ast_trait_ref.path));
             this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id,
                                                       trait_ref.clone());
             trait_ref
@@ -463,7 +459,6 @@ fn ast_path_to_trait_ref<'tcx,AC,RS>(
     rscope: &RS,
     trait_def_id: ast::DefId,
     self_ty: Option<Ty<'tcx>>,
-    associated_type: Option<Ty<'tcx>>,
     path: &ast::Path)
     -> ty::TraitRef<'tcx>
     where AC: AstConv<'tcx>, RS: RegionScope
@@ -493,8 +488,7 @@ fn ast_path_to_trait_ref<'tcx,AC,RS>(
                                             &trait_def.generics,
                                             self_ty,
                                             types,
-                                            regions,
-                                            associated_type);
+                                            regions);
 
     ty::TraitRef::new(trait_def_id, substs)
 }
@@ -517,7 +511,6 @@ pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                                         did,
                                         &generics,
                                         None,
-                                        None,
                                         path);
     let ty = decl_ty.subst(tcx, &substs);
     TypeAndSubsts { substs: substs, ty: ty }
@@ -558,7 +551,7 @@ pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>(
         Substs::new(VecPerParamSpace::params_from_type(type_params),
                     VecPerParamSpace::params_from_type(region_params))
     } else {
-        ast_path_substs_for_ty(this, rscope, did, &generics, None, None, path)
+        ast_path_substs_for_ty(this, rscope, did, &generics, None, path)
     };
 
     let ty = decl_ty.subst(tcx, &substs);
@@ -726,7 +719,6 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                                                        rscope,
                                                        trait_def_id,
                                                        None,
-                                                       None,
                                                        path);
                     let empty_vec = [];
                     let bounds = match *opt_bounds { None => empty_vec.as_slice(),
@@ -750,61 +742,37 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
     constr(ast_ty_to_ty(this, rscope, a_seq_ty))
 }
 
-fn associated_ty_to_ty<'tcx,AC,RS>(this: &AC,
-                                   rscope: &RS,
-                                   trait_path: &ast::Path,
-                                   for_ast_type: &ast::Ty,
-                                   trait_type_id: ast::DefId,
-                                   span: Span)
-                                   -> Ty<'tcx>
-                                   where AC: AstConv<'tcx>, RS: RegionScope
+fn qpath_to_ty<'tcx,AC,RS>(this: &AC,
+                           rscope: &RS,
+                           ast_ty: &ast::Ty, // the TyQPath
+                           qpath: &ast::QPath)
+                           -> Ty<'tcx>
+    where AC: AstConv<'tcx>, RS: RegionScope
 {
-    debug!("associated_ty_to_ty(trait_path={}, for_ast_type={}, trait_type_id={})",
-           trait_path.repr(this.tcx()),
-           for_ast_type.repr(this.tcx()),
-           trait_type_id.repr(this.tcx()));
-
-    // Find the trait that this associated type belongs to.
-    let trait_did = match ty::impl_or_trait_item(this.tcx(),
-                                                 trait_type_id).container() {
-        ty::ImplContainer(_) => {
-            this.tcx().sess.span_bug(span,
-                                     "associated_ty_to_ty(): impl associated \
-                                      types shouldn't go through this \
-                                      function")
-        }
-        ty::TraitContainer(trait_id) => trait_id,
-    };
+    debug!("qpath_to_ty(ast_ty={})",
+           ast_ty.repr(this.tcx()));
 
-    let for_type = ast_ty_to_ty(this, rscope, for_ast_type);
-    if !this.associated_types_of_trait_are_valid(for_type, trait_did) {
-        this.tcx().sess.span_err(span,
-                                 "this associated type is not \
-                                  allowed in this context");
-        return ty::mk_err()
-    }
+    let self_type = ast_ty_to_ty(this, rscope, &*qpath.self_type);
+
+    debug!("qpath_to_ty: self_type={}", self_type.repr(this.tcx()));
 
-    let trait_ref = ast_path_to_trait_ref(this,
+    let trait_ref = instantiate_trait_ref(this,
                                           rscope,
-                                          trait_did,
-                                          None,
-                                          Some(for_type),
-                                          trait_path);
-
-    debug!("associated_ty_to_ty(trait_ref={})",
-           trait_ref.repr(this.tcx()));
-
-    let trait_def = this.get_trait_def(trait_did);
-    for type_parameter in trait_def.generics.types.iter() {
-        if type_parameter.def_id == trait_type_id {
-            debug!("associated_ty_to_ty(type_parameter={} substs={})",
-                   type_parameter.repr(this.tcx()),
-                   trait_ref.substs.repr(this.tcx()));
-            return *trait_ref.substs.types.get(type_parameter.space,
-                                               type_parameter.index)
+                                          &*qpath.trait_ref,
+                                          Some(self_type));
+
+    debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(this.tcx()));
+
+    let trait_def = this.get_trait_def(trait_ref.def_id);
+
+    for ty_param_def in trait_def.generics.types.get_slice(AssocSpace).iter() {
+        if ty_param_def.name == qpath.item_name.name {
+            debug!("qpath_to_ty: corresponding ty_param_def={}", ty_param_def);
+            return trait_ref.substs.type_for_def(ty_param_def);
         }
     }
-    this.tcx().sess.span_bug(span,
+
+    this.tcx().sess.span_bug(ast_ty.span,
                              "this associated type didn't get added \
                               as a parameter for some reason")
 }
@@ -931,7 +899,6 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                                                            rscope,
                                                            trait_def_id,
                                                            None,
-                                                           None,
                                                            path);
                         let empty_bounds: &[ast::TyParamBound] = &[];
                         let ast_bounds = match *bounds {
@@ -996,26 +963,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                 }
             }
             ast::TyQPath(ref qpath) => {
-                match tcx.def_map.borrow().get(&ast_ty.id) {
-                    None => {
-                        tcx.sess.span_bug(ast_ty.span,
-                                          "unbound qualified path")
-                    }
-                    Some(&def::DefAssociatedTy(trait_type_id)) => {
-                        associated_ty_to_ty(this,
-                                            rscope,
-                                            &qpath.trait_name,
-                                            &*qpath.for_type,
-                                            trait_type_id,
-                                            ast_ty.span)
-                    }
-                    Some(_) => {
-                        tcx.sess.span_err(ast_ty.span,
-                                          "this qualified path does not name \
-                                           an associated type");
-                        ty::mk_err()
-                    }
-                }
+                qpath_to_ty(this, rscope, ast_ty, &**qpath)
             }
             ast::TyFixedLengthVec(ref ty, ref e) => {
                 match const_eval::eval_const_expr_partial(tcx, &**e) {
@@ -1411,7 +1359,7 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>(
 
     let main_trait_bound = match partitioned_bounds.trait_bounds.remove(0) {
         Some(trait_bound) => {
-            Some(instantiate_poly_trait_ref(this, rscope, trait_bound, None, None))
+            Some(instantiate_poly_trait_ref(this, rscope, trait_bound, None))
         }
         None => {
             this.tcx().sess.span_err(
index b0e8b664d06d7d7189d00d8ae88a6fbd47921575..90ad0d2f3e5e223d3537e2cc7a2eba022d92e830 100644 (file)
@@ -684,7 +684,11 @@ fn find_associated_type_in_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
                                           ty: Option<Ty<'tcx>>,
                                           associated_type_id: ast::DefId,
                                           generics: &ty::Generics<'tcx>)
-                                          -> Ty<'tcx> {
+                                          -> Ty<'tcx>
+{
+    debug!("find_associated_type_in_generics(ty={}, associated_type_id={}, generics={}",
+           ty.repr(tcx), associated_type_id.repr(tcx), generics.repr(tcx));
+
     let ty = match ty {
         None => {
             tcx.sess.span_bug(span,
@@ -703,20 +707,22 @@ fn find_associated_type_in_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
             for type_parameter in generics.types.iter() {
                 if type_parameter.def_id == associated_type_id
                     && type_parameter.associated_with == Some(param_id) {
-                    return ty::mk_param_from_def(tcx, type_parameter)
+                    return ty::mk_param_from_def(tcx, type_parameter);
                 }
             }
 
-            tcx.sess.span_bug(span,
-                              "find_associated_type_in_generics(): didn't \
-                               find associated type anywhere in the generics \
-                               list")
+            tcx.sess.span_err(
+                span,
+                format!("no suitable bound on `{}`",
+                        ty.user_string(tcx))[]);
+            ty::mk_err()
         }
         _ => {
-            tcx.sess.span_bug(span,
-                              "find_associated_type_in_generics(): self type \
-                               is not a parameter")
-
+            tcx.sess.span_err(
+                span,
+                "it is currently unsupported to access associated types except \
+                 through a type parameter; this restriction will be lifted in time");
+            ty::mk_err()
         }
     }
 }
@@ -1155,7 +1161,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
 
             for trait_ref in opt_trait_ref.iter() {
                 astconv::instantiate_trait_ref(&icx, &ExplicitRscope, trait_ref,
-                                               Some(selfty), None);
+                                               Some(selfty));
             }
         },
         ast::ItemTrait(_, _, _, ref trait_methods) => {
@@ -1627,7 +1633,7 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                         ccx,
                         subst::AssocSpace,
                         &associated_type.ty_param,
-                        generics.types.len(subst::TypeSpace),
+                        generics.types.len(subst::AssocSpace),
                         &ast_generics.where_clause,
                         Some(local_def(trait_id)));
                 ccx.tcx.ty_param_defs.borrow_mut().insert(associated_type.ty_param.id,
@@ -2019,7 +2025,6 @@ fn conv_param_bounds<'tcx,AC>(this: &AC,
             astconv::instantiate_poly_trait_ref(this,
                                                 &ExplicitRscope,
                                                 bound,
-                                                Some(param_ty.to_ty(this.tcx())),
                                                 Some(param_ty.to_ty(this.tcx())))
         })
         .collect();
index 06154f68613e7626c7110853726827738b40e038..cdbe107e11c9576fdd1f02ae540ccceabb9d6e97 100644 (file)
 use syntax::visit;
 use syntax::visit::Visitor;
 
+// An error has already been reported to the user, so no need to continue checking.
+#[deriving(Clone,Show)]
+pub struct ErrorReported;
+
 pub fn time<T, U>(do_it: bool, what: &str, u: U, f: |U| -> T) -> T {
     local_data_key!(depth: uint);
     if !do_it { return f(u); }
index 15e14902727f5db6e4dff09d7e143b57a430bdc3..61e56f0cc42e4f1e172f4094fa43564e3adcaf80 100644 (file)
@@ -706,11 +706,11 @@ pub enum Expr_ {
 ///
 ///     <Vec<T> as SomeTrait>::SomeAssociatedItem
 ///      ^~~~~     ^~~~~~~~~   ^~~~~~~~~~~~~~~~~~
-///      for_type  trait_name  item_name
+///      self_type  trait_name  item_name
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct QPath {
-    pub for_type: P<Ty>,
-    pub trait_name: Path,
+    pub self_type: P<Ty>,
+    pub trait_ref: P<TraitRef>,
     pub item_name: Ident,
 }
 
index b3137ff5f7e52c0acd00cac02a9b748dfffcade9..2e6ee49f0ff72200c2ce9d239831274cbda5f661 100644 (file)
@@ -142,6 +142,10 @@ fn fold_ty(&mut self, t: P<Ty>) -> P<Ty> {
         noop_fold_ty(t, self)
     }
 
+    fn fold_qpath(&mut self, t: P<QPath>) -> P<QPath> {
+        noop_fold_qpath(t, self)
+    }
+
     fn fold_mod(&mut self, m: Mod) -> Mod {
         noop_fold_mod(m, self)
     }
@@ -435,12 +439,8 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
                         fld.fold_opt_bounds(bounds),
                         id)
             }
-            TyQPath(ref qpath) => {
-                TyQPath(P(QPath {
-                    for_type: fld.fold_ty(qpath.for_type.clone()),
-                    trait_name: fld.fold_path(qpath.trait_name.clone()),
-                    item_name: fld.fold_ident(qpath.item_name.clone()),
-                }))
+            TyQPath(qpath) => {
+                TyQPath(fld.fold_qpath(qpath))
             }
             TyFixedLengthVec(ty, e) => {
                 TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e))
@@ -456,6 +456,16 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
     })
 }
 
+pub fn noop_fold_qpath<T: Folder>(qpath: P<QPath>, fld: &mut T) -> P<QPath> {
+    qpath.map(|qpath| {
+        QPath {
+            self_type: fld.fold_ty(qpath.self_type),
+            trait_ref: qpath.trait_ref.map(|tr| fld.fold_trait_ref(tr)),
+            item_name: fld.fold_ident(qpath.item_name),
+        }
+    })
+}
+
 pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod {abi, view_items, items}: ForeignMod,
                                         fld: &mut T) -> ForeignMod {
     ForeignMod {
index 50b1a2204b04180b6a438b56c5e49eec9450f373..d3ae9838c6d147c1f890092baf9ce1262704b283 100644 (file)
@@ -1502,17 +1502,17 @@ pub fn parse_ty(&mut self, plus_allowed: bool) -> P<Ty> {
         } else if self.eat_keyword(keywords::Proc) {
             self.parse_proc_type(Vec::new())
         } else if self.token == token::Lt {
-            // QUALIFIED PATH
+            // QUALIFIED PATH `<TYPE as TRAIT_REF>::item`
             self.bump();
-            let for_type = self.parse_ty(true);
+            let self_type = self.parse_ty(true);
             self.expect_keyword(keywords::As);
-            let trait_name = self.parse_path(LifetimeAndTypesWithoutColons);
+            let trait_ref = self.parse_trait_ref();
             self.expect(&token::Gt);
             self.expect(&token::ModSep);
             let item_name = self.parse_ident();
             TyQPath(P(QPath {
-                for_type: for_type,
-                trait_name: trait_name.path,
+                self_type: self_type,
+                trait_ref: P(trait_ref),
                 item_name: item_name,
             }))
         } else if self.token == token::ModSep ||
index e6e0c33a42dbdf0497ddb841ba33f3d09cacf429..fa6b70389b4c873f3b62f2b0884c3d5a5e2d8294 100644 (file)
@@ -744,10 +744,10 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> IoResult<()> {
             }
             ast::TyQPath(ref qpath) => {
                 try!(word(&mut self.s, "<"));
-                try!(self.print_type(&*qpath.for_type));
+                try!(self.print_type(&*qpath.self_type));
                 try!(space(&mut self.s));
                 try!(self.word_space("as"));
-                try!(self.print_path(&qpath.trait_name, false));
+                try!(self.print_trait_ref(&*qpath.trait_ref));
                 try!(word(&mut self.s, ">"));
                 try!(word(&mut self.s, "::"));
                 try!(self.print_ident(qpath.item_name));
index efe1e18eda92872d6b2800373a4e64034cb45727..bbbec5e0626c5965d238d4464093f3da445d5fbf 100644 (file)
@@ -403,8 +403,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
             }
         }
         TyQPath(ref qpath) => {
-            visitor.visit_ty(&*qpath.for_type);
-            visitor.visit_path(&qpath.trait_name, typ.id);
+            visitor.visit_ty(&*qpath.self_type);
+            visitor.visit_trait_ref(&*qpath.trait_ref);
             visitor.visit_ident(typ.span, qpath.item_name);
         }
         TyFixedLengthVec(ref ty, ref expression) => {
index a2c01fe62f6bba1960d229f08791537acb562f98..24de1fa2f78444ecc6b40426dcf355fab96f8669 100644 (file)
@@ -20,12 +20,12 @@ fn get<T:Get,U:Get>(x: T, y: U) -> Get::Value {}
 
 trait Other {
     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
-    //~^ ERROR this associated type is not allowed in this context
+    //~^ ERROR no suitable bound on `Self`
 }
 
 impl<T:Get> Other for T {
     fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {}
-    //~^ ERROR this associated type is not allowed in this context
+    //~^ ERROR currently unsupported
 }
 
 trait Grab {
index 8fbfc33896b41914bfad7ffcb56dbdc13b66b984..8cab2759ad55a319c34aa258e27bfd11e109c279 100644 (file)
@@ -16,7 +16,7 @@ trait Get {
 }
 
 fn get(x: int) -> <int as Get>::Value {}
-//~^ ERROR this associated type is not allowed in this context
+//~^ ERROR unsupported
 
 struct Struct {
     x: int,
@@ -24,7 +24,7 @@ struct Struct {
 
 impl Struct {
     fn uhoh<T>(foo: <T as Get>::Value) {}
-    //~^ ERROR this associated type is not allowed in this context
+    //~^ ERROR no suitable bound on `T`
 }
 
 fn main() {
diff --git a/src/test/run-pass/associated-types-qualified-path-with-trait-with-type-parameters.rs b/src/test/run-pass/associated-types-qualified-path-with-trait-with-type-parameters.rs
new file mode 100644 (file)
index 0000000..1b4eb26
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2014 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.
+
+#![feature(associated_types)]
+
+trait Foo<T> {
+    type Bar;
+    fn get_bar() -> <Self as Foo<T>>::Bar;
+}
+
+fn main() { }