visit::walk_path(self, p);
}
+ fn visit_qpath(&mut self, p: &ast::QPath, id: ast::NodeId) {
+ run_lints!(self, check_qpath, p, id);
+ visit::walk_qpath(self, p);
+ }
+
fn visit_attribute(&mut self, attr: &ast::Attribute) {
run_lints!(self, check_attribute, attr);
}
fn check_explicit_self(&mut self, _: &Context, _: &ast::ExplicitSelf) { }
fn check_mac(&mut self, _: &Context, _: &ast::Mac) { }
fn check_path(&mut self, _: &Context, _: &ast::Path, _: ast::NodeId) { }
+ fn check_qpath(&mut self, _: &Context, _: &ast::QPath, _: ast::NodeId) { }
fn check_attribute(&mut self, _: &Context, _: &ast::Attribute) { }
/// Called when entering a syntax node that can have lint attributes such
}
rbml_w.end_tag();
}
- if let Some(ref ast_trait_ref) = *opt_trait {
- let trait_ref = ty::node_id_to_trait_ref(
- tcx, ast_trait_ref.ref_id);
+ if opt_trait.is_some() {
+ let trait_ref = ty::impl_id_to_trait_ref(tcx, item.id);
encode_trait_ref(rbml_w, ecx, &*trait_ref, tag_item_trait_ref);
}
encode_path(rbml_w, path.clone());
visit::walk_path(self, path);
}
+ fn visit_qpath(&mut self, qpath: &ast::QPath, id: ast::NodeId) {
+ self.lookup_and_handle_definition(&id);
+ visit::walk_qpath(self, qpath);
+ }
+
fn visit_item(&mut self, _: &ast::Item) {
// Do not recurse into items. These items will be added to the
// worklist and recursed into manually if necessary.
pub impl_trait_cache: RefCell<DefIdMap<Option<Rc<ty::TraitRef<'tcx>>>>>,
- pub trait_refs: RefCell<NodeMap<Rc<TraitRef<'tcx>>>>,
+ pub impl_trait_refs: RefCell<NodeMap<Rc<TraitRef<'tcx>>>>,
pub trait_defs: RefCell<DefIdMap<Rc<TraitDef<'tcx>>>>,
/// Maps from the def-id of an item (trait/struct/enum/fn) to its
region_maps: region_maps,
node_types: RefCell::new(FnvHashMap()),
item_substs: RefCell::new(NodeMap()),
- trait_refs: RefCell::new(NodeMap()),
+ impl_trait_refs: RefCell::new(NodeMap()),
trait_defs: RefCell::new(DefIdMap()),
predicates: RefCell::new(DefIdMap()),
object_cast_map: RefCell::new(NodeMap()),
}
}
-pub fn node_id_to_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId)
+pub fn impl_id_to_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId)
-> Rc<ty::TraitRef<'tcx>> {
- match cx.trait_refs.borrow().get(&id) {
+ match cx.impl_trait_refs.borrow().get(&id) {
Some(ty) => ty.clone(),
None => cx.sess.bug(
- &format!("node_id_to_trait_ref: no trait ref for node `{}`",
+ &format!("impl_id_to_trait_ref: no trait ref for impl `{}`",
cx.map.node_to_string(id)))
}
}
memoized(&cx.impl_trait_cache, id, |id: ast::DefId| {
if id.krate == ast::LOCAL_CRATE {
debug!("(impl_trait_ref) searching for trait impl {:?}", id);
- match cx.map.find(id.node) {
- Some(ast_map::NodeItem(item)) => {
- match item.node {
- ast::ItemImpl(_, _, _, ref opt_trait, _, _) => {
- match opt_trait {
- &Some(ref t) => {
- let trait_ref = ty::node_id_to_trait_ref(cx, t.ref_id);
- Some(trait_ref)
- }
- &None => None
- }
- }
+ if let Some(ast_map::NodeItem(item)) = cx.map.find(id.node) {
+ if let ast::ItemImpl(_, _, _, ref opt_trait, _, _) = item.node {
+ opt_trait.as_ref().map(|_| {
+ ty::impl_id_to_trait_ref(cx, id.node)
+ })
+ } else {
+ None
ast::ItemDefaultImpl(_, ref ast_trait_ref) => {
Some(ty::node_id_to_trait_ref(cx, ast_trait_ref.ref_id))
}
- _ => None
- }
}
- _ => None
+ } else {
+ None
}
} else {
csearch::get_impl_trait(cx, id)
SawVariant,
SawExplicitSelf,
SawPath,
+ SawQPath,
SawOptLifetimeRef,
SawBlock,
SawPat,
SawPath.hash(self.st); visit::walk_path(self, path)
}
+ fn visit_qpath(&mut self, qpath: &QPath, _: ast::NodeId) {
+ SawQPath.hash(self.st); visit::walk_qpath(self, qpath)
+ }
+
fn visit_block(&mut self, b: &Block) {
SawBlock.hash(self.st); visit::walk_block(self, b)
}
self.check_path(path.span, id, path.segments.last().unwrap().identifier);
visit::walk_path(self, path);
}
+
+ fn visit_qpath(&mut self, qpath: &ast::QPath, id: ast::NodeId) {
+ self.check_path(qpath.trait_path.span, id, qpath.item_path.identifier);
+ visit::walk_qpath(self, qpath);
+ }
}
////////////////////////////////////////////////////////////////////////////////
this.resolve_type_parameters(&generics.ty_params);
this.resolve_where_clause(&generics.where_clause);
- this.resolve_type_parameter_bounds(item.id, bounds,
- TraitDerivation);
+ this.resolve_type_parameter_bounds(bounds, TraitDerivation);
for trait_item in &(*trait_items) {
// Create a new rib for the trait_item-specific type
type_parameter: &TyParam) {
self.check_if_primitive_type_name(type_parameter.ident.name, type_parameter.span);
for bound in &*type_parameter.bounds {
- self.resolve_type_parameter_bound(type_parameter.id, bound,
- TraitBoundingTypeParameter);
+ self.resolve_type_parameter_bound(bound, TraitBoundingTypeParameter);
}
match type_parameter.default {
Some(ref ty) => self.resolve_type(&**ty),
}
fn resolve_type_parameter_bounds(&mut self,
- id: NodeId,
type_parameter_bounds: &OwnedSlice<TyParamBound>,
reference_type: TraitReferenceType) {
for type_parameter_bound in &**type_parameter_bounds {
- self.resolve_type_parameter_bound(id, type_parameter_bound,
- reference_type);
+ self.resolve_type_parameter_bound(type_parameter_bound, reference_type);
}
}
fn resolve_type_parameter_bound(&mut self,
- id: NodeId,
type_parameter_bound: &TyParamBound,
reference_type: TraitReferenceType) {
match *type_parameter_bound {
TraitTyParamBound(ref tref, _) => {
- self.resolve_poly_trait_reference(id, tref, reference_type)
+ self.resolve_trait_reference(tref.trait_ref.ref_id,
+ &tref.trait_ref.path,
+ reference_type)
}
RegionTyParamBound(..) => {}
}
}
- fn resolve_poly_trait_reference(&mut self,
- id: NodeId,
- poly_trait_reference: &PolyTraitRef,
- reference_type: TraitReferenceType) {
- self.resolve_trait_reference(id, &poly_trait_reference.trait_ref, reference_type)
- }
-
fn resolve_trait_reference(&mut self,
id: NodeId,
- trait_reference: &TraitRef,
+ trait_path: &Path,
reference_type: TraitReferenceType) {
- match self.resolve_path(id, &trait_reference.path, TypeNS, true) {
+ match self.resolve_path(id, trait_path, TypeNS, true) {
None => {
- let path_str = self.path_names_to_string(&trait_reference.path);
+ let path_str = self.path_names_to_string(trait_path);
let usage_str = match reference_type {
TraitBoundingTypeParameter => "bound type parameter with",
TraitImplementation => "implement",
};
let msg = format!("attempt to {} a nonexistent trait `{}`", usage_str, path_str);
- self.resolve_error(trait_reference.path.span, &msg[..]);
+ self.resolve_error(trait_path.span, &msg[..]);
}
Some(def) => {
match def {
(DefTrait(_), _) => {
debug!("(resolving trait) found trait def: {:?}", def);
- self.record_def(trait_reference.ref_id, def);
+ self.record_def(id, def);
}
(def, _) => {
- self.resolve_error(trait_reference.path.span,
- &format!("`{}` is not a trait",
- self.path_names_to_string(
- &trait_reference.path)));
+ self.resolve_error(trait_path.span,
+ &format!("`{}` is not a trait",
+ self.path_names_to_string(trait_path)));
// If it's a typedef, give a note
if let DefTy(..) = def {
- self.session.span_note(
- trait_reference.path.span,
- &format!("`type` aliases cannot be used for traits")
- );
+ self.session.span_note(trait_path.span,
+ &format!("`type` aliases cannot be used for traits"));
}
}
}
self.resolve_type(&*bound_pred.bounded_ty);
for bound in &*bound_pred.bounds {
- self.resolve_type_parameter_bound(bound_pred.bounded_ty.id, bound,
- TraitBoundingTypeParameter);
+ self.resolve_type_parameter_bound(bound, TraitBoundingTypeParameter);
}
}
&ast::WherePredicate::RegionPredicate(_) => {}
result
}
- fn with_optional_trait_ref<T, F>(&mut self, id: NodeId,
+ fn with_optional_trait_ref<T, F>(&mut self,
opt_trait_ref: &Option<TraitRef>,
f: F) -> T where
F: FnOnce(&mut Resolver) -> T,
{
let new_val = match *opt_trait_ref {
Some(ref trait_ref) => {
- self.resolve_trait_reference(id, trait_ref, TraitImplementation);
+ self.resolve_trait_reference(trait_ref.ref_id,
+ &trait_ref.path,
+ TraitImplementation);
match self.def_map.borrow().get(&trait_ref.ref_id) {
Some(def) => {
this.resolve_where_clause(&generics.where_clause);
// Resolve the trait reference, if necessary.
- this.with_optional_trait_ref(id, opt_trait_reference, |this| {
+ this.with_optional_trait_ref(opt_trait_reference, |this| {
// Resolve the self type.
this.resolve_type(self_type);
TyObjectSum(ref ty, ref bound_vec) => {
self.resolve_type(&**ty);
- self.resolve_type_parameter_bounds(ty.id, bound_vec,
- TraitBoundingTypeParameter);
+ self.resolve_type_parameter_bounds(bound_vec, TraitBoundingTypeParameter);
}
TyQPath(ref qpath) => {
self.resolve_type(&*qpath.self_type);
- self.resolve_trait_reference(ty.id, &*qpath.trait_ref, TraitQPath);
+ self.resolve_trait_reference(ty.id, &qpath.trait_path, TraitQPath);
for ty in qpath.item_path.parameters.types() {
self.resolve_type(&**ty);
}
}
TyPolyTraitRef(ref bounds) => {
- self.resolve_type_parameter_bounds(
- ty.id,
- bounds,
- TraitObject);
+ self.resolve_type_parameter_bounds(bounds, TraitObject);
visit::walk_ty(self, ty);
}
_ => {
ExprPath(ref path) => path,
ExprQPath(ref qpath) => {
self.resolve_type(&*qpath.self_type);
- self.resolve_trait_reference(expr.id, &*qpath.trait_ref, TraitQPath);
- path_from_qpath = qpath.trait_ref.path.clone();
+
+ // Just make sure the trait is valid, don't record a def.
+ self.resolve_trait_reference(expr.id, &qpath.trait_path, TraitQPath);
+ self.def_map.borrow_mut().remove(&expr.id);
+
+ path_from_qpath = qpath.trait_path.clone();
path_from_qpath.segments.push(qpath.item_path.clone());
&path_from_qpath
}
visit::walk_path(self, path);
}
ast::ExprQPath(ref qpath) => {
- let mut path = qpath.trait_ref.path.clone();
+ let mut path = qpath.trait_path.clone();
path.segments.push(qpath.item_path.clone());
self.process_path(ex.id, ex.span, &path, None);
- visit::walk_qpath(self, ex.span, &**qpath);
+ visit::walk_qpath(self, &**qpath);
}
ast::ExprStruct(ref path, ref fields, ref base) =>
self.process_struct_lit(ex, path, fields, base),
// lifetimes. Oh well, not there yet.
let shifted_rscope = ShiftedRscope::new(rscope);
- let trait_ref =
- instantiate_trait_ref(this, &shifted_rscope, &ast_trait_ref.trait_ref,
- self_ty, Some(&mut projections));
+ let trait_ref = instantiate_trait_ref(this, &shifted_rscope,
+ &ast_trait_ref.trait_ref.path,
+ ast_trait_ref.trait_ref.ref_id,
+ None, self_ty, Some(&mut projections));
for projection in projections {
poly_projections.push(ty::Binder(projection));
pub fn instantiate_trait_ref<'tcx>(
this: &AstConv<'tcx>,
rscope: &RegionScope,
- ast_trait_ref: &ast::TraitRef,
+ path: &ast::Path,
+ path_id: ast::NodeId,
+ impl_id: Option<ast::NodeId>,
self_ty: Option<Ty<'tcx>>,
projections: Option<&mut Vec<ty::ProjectionPredicate<'tcx>>>)
-> Rc<ty::TraitRef<'tcx>>
{
- match ::lookup_def_tcx(this.tcx(), ast_trait_ref.path.span, ast_trait_ref.ref_id) {
+ match ::lookup_def_tcx(this.tcx(), path.span, path_id) {
def::DefTrait(trait_def_id) => {
let trait_ref = ast_path_to_trait_ref(this,
rscope,
trait_def_id,
self_ty,
- &ast_trait_ref.path,
+ path,
projections);
- this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id, trait_ref.clone());
+ if let Some(id) = impl_id {
+ this.tcx().impl_trait_refs.borrow_mut().insert(id, trait_ref.clone());
+ }
trait_ref
}
_ => {
- span_fatal!(this.tcx().sess, ast_trait_ref.path.span, E0245,
- "`{}` is not a trait",
- ast_trait_ref.path.user_string(this.tcx()));
+ span_fatal!(this.tcx().sess, path.span, E0245, "`{}` is not a trait",
+ path.user_string(this.tcx()));
}
}
}
let trait_ref = instantiate_trait_ref(this,
rscope,
- &*qpath.trait_ref,
+ &qpath.trait_path,
+ ast_ty.id,
+ None,
Some(self_type),
None);
constrain_path_type_parameters(fcx, expr);
}
ast::ExprQPath(ref qpath) => {
- // Require explicit type params for the trait.
let self_ty = fcx.to_ty(&*qpath.self_type);
- astconv::instantiate_trait_ref(fcx, fcx, &*qpath.trait_ref, Some(self_ty), None);
-
let defn = lookup_def(fcx, expr.span, id);
let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, defn);
- let mut path = qpath.trait_ref.path.clone();
+ let mut path = qpath.trait_path.clone();
path.segments.push(qpath.item_path.clone());
instantiate_path(fcx, &path, scheme, &predicates, Some(self_ty),
defn, expr.span, expr.id);
// to add defaults. If the user provided *too many* types, that's
// a problem.
for &space in &ParamSpace::all() {
- adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
+ adjust_type_parameters(fcx, span, space, type_defs,
+ opt_self_ty.is_some(), &mut substs);
assert_eq!(substs.types.len(space), type_defs.len(space));
adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
span: Span,
space: ParamSpace,
defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
+ require_type_space: bool,
substs: &mut Substs<'tcx>)
{
let provided_len = substs.types.len(space);
// Nothing specified at all: supply inference variables for
// everything.
- if provided_len == 0 {
- substs.types.replace(space,
- fcx.infcx().next_ty_vars(desired.len()));
+ if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) {
+ substs.types.replace(space, fcx.infcx().next_ty_vars(desired.len()));
return;
}
ast::ItemImpl(_, ast::ImplPolarity::Positive, _, _, _, _) => {
self.check_impl(item);
}
- ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(ref tref), _, _) => {
- let trait_ref = ty::node_id_to_trait_ref(ccx.tcx, tref.ref_id);
+ ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(_), _, _) => {
+ let trait_ref = ty::impl_id_to_trait_ref(ccx.tcx, item.id);
ty::populate_implementations_for_trait_if_necessary(ccx.tcx, trait_ref.def_id);
match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
Some(ty::BoundSend) | Some(ty::BoundSync) => {}
impl<'cx, 'tcx,'v> visit::Visitor<'v> for ImplsChecker<'cx, 'tcx> {
fn visit_item(&mut self, item: &'v ast::Item) {
match item.node {
- ast::ItemImpl(_, _, _, Some(ref opt_trait), _, _) => {
- let trait_ref = ty::node_id_to_trait_ref(self.tcx, opt_trait.ref_id);
+ ast::ItemImpl(_, _, _, Some(_), _, _) => {
+ let trait_ref = ty::impl_id_to_trait_ref(self.tcx, item.id);
if let Some(_) = self.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
match trait_ref.self_ty().sty {
ty::ty_struct(..) | ty::ty_enum(..) => {}
//debug!("(checking coherence) item '{}'", token::get_ident(item.ident));
- match item.node {
- ItemImpl(_, _, _, ref opt_trait, _, _) => {
- match opt_trait.clone() {
- Some(opt_trait) => {
- self.cc.check_implementation(item, &[opt_trait]);
- }
- None => self.cc.check_implementation(item, &[])
- }
- }
- _ => {
- // Nothing to do.
- }
- };
+ if let ItemImpl(_, _, _, ref opt_trait, _, _) = item.node {
+ self.cc.check_implementation(item, opt_trait.as_ref())
+ }
visit::walk_item(self, item);
}
self.check_implementations_of_copy();
}
- fn check_implementation(&self,
- item: &Item,
- associated_traits: &[TraitRef]) {
+ fn check_implementation(&self, item: &Item, opt_trait: Option<&TraitRef>) {
let tcx = self.crate_context.tcx;
let impl_did = local_def(item.id);
let self_type = ty::lookup_item_type(tcx, impl_did);
let impl_items = self.create_impl_from_item(item);
- for associated_trait in associated_traits {
- let trait_ref = ty::node_id_to_trait_ref(self.crate_context.tcx,
- associated_trait.ref_id);
+ if opt_trait.is_some() {
+ let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx, item.id);
debug!("(checking implementation) adding impl for trait '{}', item '{}'",
trait_ref.repr(self.crate_context.tcx),
token::get_ident(item.ident));
}
Some(base_type_def_id) => {
// FIXME: Gather up default methods?
- if associated_traits.len() == 0 {
+ if opt_trait.is_none() {
self.add_inherent_impl(base_type_def_id, impl_did);
}
}
// Converts an implementation in the AST to a vector of items.
fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
match item.node {
- ItemImpl(_, _, _, ref trait_refs, _, ref ast_items) => {
+ ItemImpl(_, _, _, ref opt_trait, _, ref ast_items) => {
let mut items: Vec<ImplOrTraitItemId> =
ast_items.iter()
.map(|ast_item| {
}
}).collect();
- if let Some(ref trait_ref) = *trait_refs {
- let ty_trait_ref = ty::node_id_to_trait_ref(
- self.crate_context.tcx,
- trait_ref.ref_id);
+ if opt_trait.is_some() {
+ let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx,
+ item.id);
self.instantiate_default_methods(local_def(item.id),
- &*ty_trait_ref,
+ &*trait_ref,
&mut items);
}
if let Some(ref trait_ref) = *opt_trait_ref {
astconv::instantiate_trait_ref(ccx,
&ExplicitRscope,
- trait_ref,
+ &trait_ref.path,
+ trait_ref.ref_id,
+ Some(it.id),
Some(selfty),
None);
}
Type::QPath {
name: self.item_path.identifier.clean(cx),
self_type: box self.self_type.clean(cx),
- trait_: box self.trait_ref.clean(cx)
+ trait_: box resolve_type(cx, self.trait_path.clean(cx), 0)
}
}
}
///
/// <Vec<T> as SomeTrait>::SomeAssociatedItem
/// ^~~~~ ^~~~~~~~~ ^~~~~~~~~~~~~~~~~~
-/// self_type trait_name item_path
+/// self_type trait_path item_path
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct QPath {
pub self_type: P<Ty>,
- pub trait_ref: P<TraitRef>,
+ pub trait_path: Path,
pub item_path: PathSegment,
}
///
/// Type parameters are stored in the Path itself
TyPath(Path),
+ /// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
+ TyQPath(P<QPath>),
/// Something like `A+B`. Note that `B` must always be a path.
TyObjectSum(P<Ty>, TyParamBounds),
/// A type like `for<'a> Foo<&'a Bar>`
TyPolyTraitRef(TyParamBounds),
- /// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
- TyQPath(P<QPath>),
/// No-op; kept solely so that we can pretty-print faithfully
TyParen(P<Ty>),
/// Unused for now
visit::walk_trait_item(self, tm);
}
- fn visit_lifetime_ref(&mut self, lifetime: &'v Lifetime) {
+ fn visit_lifetime_ref(&mut self, lifetime: &Lifetime) {
self.operation.visit_id(lifetime.id);
}
- fn visit_lifetime_def(&mut self, def: &'v LifetimeDef) {
+ fn visit_lifetime_def(&mut self, def: &LifetimeDef) {
self.visit_lifetime_ref(&def.lifetime);
}
+
+ fn visit_trait_ref(&mut self, trait_ref: &TraitRef) {
+ self.operation.visit_id(trait_ref.ref_id);
+ visit::walk_trait_ref(self, trait_ref);
+ }
}
pub fn visit_ids_for_inlined_item<O: IdVisitingOperation>(item: &InlinedItem,
TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))),
TyParen(ty) => TyParen(fld.fold_ty(ty)),
TyPath(path) => TyPath(fld.fold_path(path)),
+ TyQPath(qpath) => {
+ TyQPath(fld.fold_qpath(qpath))
+ }
TyObjectSum(ty, bounds) => {
TyObjectSum(fld.fold_ty(ty),
fld.fold_bounds(bounds))
}
- TyQPath(qpath) => {
- TyQPath(fld.fold_qpath(qpath))
- }
TyFixedLengthVec(ty, e) => {
TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e))
}
qpath.map(|qpath| {
QPath {
self_type: fld.fold_ty(qpath.self_type),
- trait_ref: qpath.trait_ref.map(|tr| fld.fold_trait_ref(tr)),
+ trait_path: fld.fold_path(qpath.trait_path),
item_path: PathSegment {
identifier: fld.fold_ident(qpath.item_path.identifier),
parameters: fld.fold_path_parameters(qpath.item_path.parameters),
// QUALIFIED PATH `<TYPE as TRAIT_REF>::item`
let self_type = self.parse_ty_sum();
self.expect_keyword(keywords::As);
- let trait_ref = self.parse_trait_ref();
+ let trait_path = self.parse_path(LifetimeAndTypesWithoutColons);
self.expect(&token::Gt);
self.expect(&token::ModSep);
let item_name = self.parse_ident();
TyQPath(P(QPath {
self_type: self_type,
- trait_ref: P(trait_ref),
+ trait_path: trait_path,
item_path: ast::PathSegment {
identifier: item_name,
parameters: ast::PathParameters::none()
// QUALIFIED PATH `<TYPE as TRAIT_REF>::item::<'a, T>`
let self_type = self.parse_ty_sum();
self.expect_keyword(keywords::As);
- let trait_ref = self.parse_trait_ref();
+ let trait_path = self.parse_path(LifetimeAndTypesWithoutColons);
self.expect(&token::Gt);
self.expect(&token::ModSep);
let item_name = self.parse_ident();
let hi = self.span.hi;
return self.mk_expr(lo, hi, ExprQPath(P(QPath {
self_type: self_type,
- trait_ref: P(trait_ref),
+ trait_path: trait_path,
item_path: ast::PathSegment {
identifier: item_name,
parameters: parameters
try!(self.print_type(&*qpath.self_type));
try!(space(&mut self.s));
try!(self.word_space("as"));
- try!(self.print_trait_ref(&*qpath.trait_ref));
+ try!(self.print_path(&qpath.trait_path, false));
try!(word(&mut self.s, ">"));
try!(word(&mut self.s, "::"));
try!(self.print_ident(qpath.item_path.identifier));
fn visit_path(&mut self, path: &'v Path, _id: ast::NodeId) {
walk_path(self, path)
}
- fn visit_qpath(&mut self, qpath_span: Span, qpath: &'v QPath) {
- walk_qpath(self, qpath_span, qpath)
+ fn visit_qpath(&mut self, qpath: &'v QPath, _id: ast::NodeId) {
+ walk_qpath(self, qpath)
}
fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
walk_path_segment(self, path_span, path_segment)
TyPath(ref path) => {
visitor.visit_path(path, typ.id);
}
+ TyQPath(ref qpath) => {
+ visitor.visit_qpath(&**qpath, typ.id);
+ }
TyObjectSum(ref ty, ref bounds) => {
visitor.visit_ty(&**ty);
walk_ty_param_bounds_helper(visitor, bounds);
}
- TyQPath(ref qpath) => {
- visitor.visit_qpath(typ.span, &**qpath);
- }
TyFixedLengthVec(ref ty, ref expression) => {
visitor.visit_ty(&**ty);
visitor.visit_expr(&**expression)
}
}
-pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V,
- qpath_span: Span,
- qpath: &'v QPath) {
+pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath) {
visitor.visit_ty(&*qpath.self_type);
- visitor.visit_trait_ref(&*qpath.trait_ref);
- visitor.visit_path_segment(qpath_span, &qpath.item_path);
+ walk_path(visitor, &qpath.trait_path);
+ visitor.visit_path_segment(qpath.trait_path.span, &qpath.item_path);
}
pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
visitor.visit_path(path, expression.id)
}
ExprQPath(ref qpath) => {
- visitor.visit_qpath(expression.span, &**qpath)
+ visitor.visit_qpath(&**qpath, expression.id)
}
ExprBreak(_) | ExprAgain(_) => {}
ExprRet(ref optional_expression) => {
fn main() {
<String as IntoCow>::into_cow("foo".to_string());
- //~^ ERROR wrong number of type arguments: expected 1, found 0
+ //~^ ERROR too few type parameters provided: expected 1 parameter(s)
}