From b64c7b83dd08c7c3afc643564d65975d57785172 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 8 Nov 2014 06:59:10 -0500 Subject: [PATCH] Refactor QPath to take an ast::TraitRef --- src/librustc/middle/resolve.rs | 63 +-------- src/librustc/middle/subst.rs | 4 + src/librustc/middle/traits/mod.rs | 5 +- src/librustc/middle/traits/select.rs | 2 +- src/librustc/middle/traits/util.rs | 3 +- src/librustc/middle/typeck/astconv.rs | 128 ++++++------------ src/librustc/middle/typeck/collect.rs | 31 +++-- src/librustc/util/common.rs | 4 + src/libsyntax/ast.rs | 6 +- src/libsyntax/fold.rs | 22 ++- src/libsyntax/parse/parser.rs | 10 +- src/libsyntax/print/pprust.rs | 4 +- src/libsyntax/visit.rs | 4 +- .../associated-types-in-ambiguous-context.rs | 4 +- .../associated-types-in-wrong-context.rs | 4 +- ...ed-path-with-trait-with-type-parameters.rs | 18 +++ 16 files changed, 122 insertions(+), 190 deletions(-) create mode 100644 src/test/run-pass/associated-types-qualified-path-with-trait-with-type-parameters.rs diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index baf53cc34ba94..f369f00a14e30 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -633,6 +633,7 @@ enum TraitReferenceType { TraitDerivation, // trait T : SomeTrait { ... } TraitBoundingTypeParameter, // fn f() { ... } TraitObject, // Box SomeTrait> + TraitQPath, // :: } impl NameBindings { @@ -4532,6 +4533,7 @@ impl<'a> Resolver<'a> { 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 @@ impl<'a> Resolver<'a> { } 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) => { diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index bac417c8218a4..b030867fc841c 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -100,6 +100,10 @@ impl<'tcx> Substs<'tcx> { 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 { diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index c5eacf35da92f..d34d413225e80 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -25,6 +25,7 @@ use std::rc::Rc; 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>; pub type Selection<'tcx> = Vtable<'tcx, Obligation<'tcx>>; diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index b884cb535d7a5..9cb7023e1b59f 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -17,7 +17,6 @@ use self::Candidate::*; 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::cell::RefCell; 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> { diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index dfd436bdc4d30..ec49d5010562b 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -18,9 +18,10 @@ use std::fmt; 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}; /////////////////////////////////////////////////////////////////////////// diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index ea652bc7e6599..637c1f58157e2 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -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>, - associated_ty: Option>, 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>, types: Vec>, - regions: Vec, - associated_ty: Option>) + regions: Vec) -> 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>, - associated_type: Option>) + self_ty: Option>) -> Rc> 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>, - associated_type: Option>) + self_ty: Option>) -> Rc> 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>, - associated_type: Option>, 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( diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index b0e8b664d06d7..90ad0d2f3e5e2 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -684,7 +684,11 @@ fn find_associated_type_in_generics<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Option>, 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(); diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 06154f68613e7..cdbe107e11c95 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -20,6 +20,10 @@ use syntax::ast; 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(do_it: bool, what: &str, u: U, f: |U| -> T) -> T { local_data_key!(depth: uint); if !do_it { return f(u); } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 15e14902727f5..61e56f0cc42e4 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -706,11 +706,11 @@ pub enum Expr_ { /// /// 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, - pub trait_name: Path, + pub self_type: P, + pub trait_ref: P, pub item_name: Ident, } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index b3137ff5f7e52..2e6ee49f0ff72 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -142,6 +142,10 @@ pub trait Folder { noop_fold_ty(t, self) } + fn fold_qpath(&mut self, t: P) -> P { + 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: P, fld: &mut T) -> P { 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: P, fld: &mut T) -> P { }) } +pub fn noop_fold_qpath(qpath: P, fld: &mut T) -> P { + 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(ForeignMod {abi, view_items, items}: ForeignMod, fld: &mut T) -> ForeignMod { ForeignMod { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 50b1a2204b041..d3ae9838c6d14 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1502,17 +1502,17 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(keywords::Proc) { self.parse_proc_type(Vec::new()) } else if self.token == token::Lt { - // QUALIFIED PATH + // QUALIFIED PATH `::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 || diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index e6e0c33a42dbd..fa6b70389b4c8 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -744,10 +744,10 @@ impl<'a> State<'a> { } 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)); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index efe1e18eda928..bbbec5e0626c5 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -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) => { diff --git a/src/test/compile-fail/associated-types-in-ambiguous-context.rs b/src/test/compile-fail/associated-types-in-ambiguous-context.rs index a2c01fe62f6bb..24de1fa2f7844 100644 --- a/src/test/compile-fail/associated-types-in-ambiguous-context.rs +++ b/src/test/compile-fail/associated-types-in-ambiguous-context.rs @@ -20,12 +20,12 @@ fn get(x: T, y: U) -> Get::Value {} trait Other { fn uhoh(&self, foo: U, bar: ::Value) {} - //~^ ERROR this associated type is not allowed in this context + //~^ ERROR no suitable bound on `Self` } impl Other for T { fn uhoh(&self, foo: U, bar: <(T, U) as Get>::Value) {} - //~^ ERROR this associated type is not allowed in this context + //~^ ERROR currently unsupported } trait Grab { diff --git a/src/test/compile-fail/associated-types-in-wrong-context.rs b/src/test/compile-fail/associated-types-in-wrong-context.rs index 8fbfc33896b41..8cab2759ad55a 100644 --- a/src/test/compile-fail/associated-types-in-wrong-context.rs +++ b/src/test/compile-fail/associated-types-in-wrong-context.rs @@ -16,7 +16,7 @@ trait Get { } fn get(x: int) -> ::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(foo: ::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 index 0000000000000..1b4eb2604a82b --- /dev/null +++ b/src/test/run-pass/associated-types-qualified-path-with-trait-with-type-parameters.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(associated_types)] + +trait Foo { + type Bar; + fn get_bar() -> >::Bar; +} + +fn main() { }