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
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.
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);
- }
}
////////////////////////////////////////////////////////////////////////////////
result
}
- fn path_names_to_string(&self, path: &Path) -> String {
- let names: Vec<ast::Name> = path.segments
+ fn path_names_to_string(&self, path: &Path, depth: usize) -> String {
+ let names: Vec<ast::Name> = path.segments[..path.segments.len()-depth]
.iter()
.map(|seg| seg.identifier.name)
.collect();
match *type_parameter_bound {
TraitTyParamBound(ref tref, _) => {
self.resolve_trait_reference(tref.trait_ref.ref_id,
- &tref.trait_ref.path,
+ &tref.trait_ref.path, 0,
reference_type)
}
RegionTyParamBound(..) => {}
fn resolve_trait_reference(&mut self,
id: NodeId,
trait_path: &Path,
+ path_depth: usize,
reference_type: TraitReferenceType) {
- match self.resolve_path(id, trait_path, TypeNS, true) {
+ match self.resolve_path(id, trait_path, path_depth, TypeNS, true) {
None => {
- let path_str = self.path_names_to_string(trait_path);
+ let path_str = self.path_names_to_string(trait_path, path_depth);
let usage_str = match reference_type {
TraitBoundingTypeParameter => "bound type parameter with",
TraitImplementation => "implement",
(def, _) => {
self.resolve_error(trait_path.span,
&format!("`{}` is not a trait",
- self.path_names_to_string(trait_path)));
+ self.path_names_to_string(trait_path, path_depth)));
// If it's a typedef, give a note
if let DefTy(..) = def {
}
&ast::WherePredicate::RegionPredicate(_) => {}
&ast::WherePredicate::EqPredicate(ref eq_pred) => {
- match self.resolve_path(eq_pred.id, &eq_pred.path, TypeNS, true) {
+ match self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS, true) {
Some((def @ DefTyParam(..), last_private)) => {
self.record_def(eq_pred.id, (def, last_private));
}
let new_val = match *opt_trait_ref {
Some(ref trait_ref) => {
self.resolve_trait_reference(trait_ref.ref_id,
- &trait_ref.path,
+ &trait_ref.path, 0,
TraitImplementation);
match self.def_map.borrow().get(&trait_ref.ref_id) {
// If there is a TraitRef in scope for an impl, then the method must be in the trait.
if let Some((did, ref trait_ref)) = self.current_trait_ref {
if self.trait_item_map.get(&(name, did)).is_none() {
- let path_str = self.path_names_to_string(&trait_ref.path);
+ let path_str = self.path_names_to_string(&trait_ref.path, 0);
self.resolve_error(span,
&format!("method `{}` is not a member of trait `{}`",
token::get_name(name),
match ty.node {
// Like path expressions, the interpretation of path types depends
// on whether the path has multiple elements in it or not.
- TyPath(_) | TyQPath(_) => {
- let mut path_from_qpath;
- let path = match ty.node {
- TyPath(ref path) => path,
- TyQPath(ref qpath) => {
- self.resolve_type(&*qpath.self_type);
-
- // Just make sure the trait is valid, don't record a def.
- self.resolve_trait_reference(ty.id, &qpath.trait_path, TraitQPath);
- self.def_map.borrow_mut().remove(&ty.id);
-
- path_from_qpath = qpath.trait_path.clone();
- path_from_qpath.segments.push(qpath.item_path.clone());
- &path_from_qpath
- }
- _ => unreachable!()
- };
+
+ TyPath(ref path) | TyQPath(ast::QPath { ref path, .. }) => {
+ if let TyQPath(ref qpath) = ty.node {
+ self.resolve_type(&*qpath.self_type);
+
+ // Just make sure the trait is valid, don't record a def.
+ self.resolve_trait_reference(ty.id, path, 1, TraitQPath);
+ self.def_map.borrow_mut().remove(&ty.id);
+ }
// This is a path in the type namespace. Walk through scopes
// looking for it.
}
if let None = result_def {
- result_def = self.resolve_path(ty.id, path, TypeNS, true);
+ result_def = self.resolve_path(ty.id, path, 0, TypeNS, true);
}
match result_def {
// Write the result into the def map.
debug!("(resolving type) writing resolution for `{}` \
(id {}) = {:?}",
- self.path_names_to_string(path),
+ self.path_names_to_string(path, 0),
ty.id, def);
self.record_def(ty.id, def);
}
_ => "type name"
};
let msg = format!("use of undeclared {} `{}`", kind,
- self.path_names_to_string(path));
+ self.path_names_to_string(path, 0));
self.resolve_error(ty.span, &msg[..]);
}
}
PatEnum(ref path, _) => {
// This must be an enum variant, struct or const.
- match self.resolve_path(pat_id, path, ValueNS, false) {
+ match self.resolve_path(pat_id, path, 0, ValueNS, false) {
Some(def @ (DefVariant(..), _)) |
Some(def @ (DefStruct(..), _)) |
Some(def @ (DefConst(..), _)) => {
}
PatStruct(ref path, _, _) => {
- match self.resolve_path(pat_id, path, TypeNS, false) {
+ match self.resolve_path(pat_id, path, 0, TypeNS, false) {
Some(definition) => {
self.record_def(pattern.id, definition);
}
debug!("(resolving pattern) didn't find struct \
def: {:?}", result);
let msg = format!("`{}` does not name a structure",
- self.path_names_to_string(path));
+ self.path_names_to_string(path, 0));
self.resolve_error(path.span, &msg[..]);
}
}
fn resolve_path(&mut self,
id: NodeId,
path: &Path,
+ path_depth: usize,
namespace: Namespace,
check_ribs: bool) -> Option<(Def, LastPrivate)> {
+ let span = path.span;
+ let segments = &path.segments[..path.segments.len()-path_depth];
+
// First, resolve the types and associated type bindings.
- for ty in path.segments.iter().flat_map(|s| s.parameters.types().into_iter()) {
+ for ty in segments.iter().flat_map(|s| s.parameters.types().into_iter()) {
self.resolve_type(&**ty);
}
- for binding in path.segments.iter().flat_map(|s| s.parameters.bindings().into_iter()) {
+ for binding in segments.iter().flat_map(|s| s.parameters.bindings().into_iter()) {
self.resolve_type(&*binding.ty);
}
// A special case for sugared associated type paths `T::A` where `T` is
// a type parameter and `A` is an associated type on some bound of `T`.
- if namespace == TypeNS && path.segments.len() == 2 {
- match self.resolve_identifier(path.segments[0].identifier,
+ if namespace == TypeNS && segments.len() == 2 {
+ match self.resolve_identifier(segments[0].identifier,
TypeNS,
true,
- path.span) {
+ span) {
Some((def, last_private)) => {
match def {
DefTyParam(_, _, did, _) => {
let def = DefAssociatedPath(TyParamProvenance::FromParam(did),
- path.segments.last()
+ segments.last()
.unwrap().identifier);
return Some((def, last_private));
}
DefSelfTy(nid) => {
let def = DefAssociatedPath(TyParamProvenance::FromSelf(local_def(nid)),
- path.segments.last()
+ segments.last()
.unwrap().identifier);
return Some((def, last_private));
}
}
if path.global {
- return self.resolve_crate_relative_path(path, namespace);
+ return self.resolve_crate_relative_path(span, segments, namespace);
}
// Try to find a path to an item in a module.
let unqualified_def =
- self.resolve_identifier(path.segments.last().unwrap().identifier,
+ self.resolve_identifier(segments.last().unwrap().identifier,
namespace,
check_ribs,
- path.span);
+ span);
- if path.segments.len() > 1 {
- let def = self.resolve_module_relative_path(path, namespace);
+ if segments.len() > 1 {
+ let def = self.resolve_module_relative_path(span, segments, namespace);
match (def, unqualified_def) {
(Some((ref d, _)), Some((ref ud, _))) if *d == *ud => {
self.session
.add_lint(lint::builtin::UNUSED_QUALIFICATIONS,
- id,
- path.span,
+ id, span,
"unnecessary qualification".to_string());
}
_ => ()
// resolve a "module-relative" path, e.g. a::b::c
fn resolve_module_relative_path(&mut self,
- path: &Path,
+ span: Span,
+ segments: &[ast::PathSegment],
namespace: Namespace)
-> Option<(Def, LastPrivate)> {
- let module_path = path.segments.init().iter()
- .map(|ps| ps.identifier.name)
- .collect::<Vec<_>>();
+ let module_path = segments.init().iter()
+ .map(|ps| ps.identifier.name)
+ .collect::<Vec<_>>();
let containing_module;
let last_private;
match self.resolve_module_path(module,
&module_path[..],
UseLexicalScope,
- path.span,
+ span,
PathSearch) {
Failed(err) => {
let (span, msg) = match err {
None => {
let msg = format!("Use of undeclared type or module `{}`",
self.names_to_string(&module_path));
- (path.span, msg)
+ (span, msg)
}
};
}
}
- let name = path.segments.last().unwrap().identifier.name;
+ let name = segments.last().unwrap().identifier.name;
let def = match self.resolve_definition_of_name_in_module(containing_module.clone(),
name,
namespace) {
/// Invariant: This must be called only during main resolution, not during
/// import resolution.
fn resolve_crate_relative_path(&mut self,
- path: &Path,
+ span: Span,
+ segments: &[ast::PathSegment],
namespace: Namespace)
-> Option<(Def, LastPrivate)> {
- let module_path = path.segments.init().iter()
- .map(|ps| ps.identifier.name)
- .collect::<Vec<_>>();
+ let module_path = segments.init().iter()
+ .map(|ps| ps.identifier.name)
+ .collect::<Vec<_>>();
let root_module = self.graph_root.get_module();
match self.resolve_module_path_from_root(root_module,
&module_path[..],
0,
- path.span,
+ span,
PathSearch,
LastMod(AllPublic)) {
Failed(err) => {
None => {
let msg = format!("Use of undeclared module `::{}`",
self.names_to_string(&module_path[..]));
- (path.span, msg)
+ (span, msg)
}
};
}
}
- let name = path.segments.last().unwrap().identifier.name;
+ let name = segments.last().unwrap().identifier.name;
match self.resolve_definition_of_name_in_module(containing_module,
name,
namespace) {
match get_module(self, path.span, &name_path[..]) {
Some(module) => match module.children.borrow().get(&name) {
Some(binding) => {
- let p_str = self.path_names_to_string(&path);
+ let p_str = self.path_names_to_string(&path, 0);
match binding.def_for_namespace(ValueNS) {
Some(DefStaticMethod(_, provenance)) => {
match provenance {
// Look for a method in the current trait.
match self.current_trait_ref {
Some((did, ref trait_ref)) => {
- let path_str = self.path_names_to_string(&trait_ref.path);
+ let path_str = self.path_names_to_string(&trait_ref.path, 0);
match self.trait_item_map.get(&(name, did)) {
Some(&StaticMethodTraitItemKind) => {
// The interpretation of paths depends on whether the path has
// multiple elements in it or not.
- ExprPath(_) | ExprQPath(_) => {
- let mut path_from_qpath;
- let path = match expr.node {
- ExprPath(ref path) => path,
- ExprQPath(ref qpath) => {
- self.resolve_type(&*qpath.self_type);
+ ExprPath(ref path) | ExprQPath(ast::QPath { ref path, .. }) => {
+ if let ExprQPath(ref qpath) = expr.node {
+ self.resolve_type(&*qpath.self_type);
- // 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);
+ // Just make sure the trait is valid, don't record a def.
+ self.resolve_trait_reference(expr.id, path, 1, 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
- }
- _ => unreachable!()
- };
// This is a local path in the value namespace. Walk through
// scopes looking for it.
- match self.resolve_path(expr.id, path, ValueNS, true) {
+ match self.resolve_path(expr.id, path, 0, ValueNS, true) {
// Check if struct variant
Some((DefVariant(_, _, true), _)) => {
- let path_name = self.path_names_to_string(path);
+ let path_name = self.path_names_to_string(path, 0);
self.resolve_error(expr.span,
&format!("`{}` is a struct variant name, but \
this expression \
Some(def) => {
// Write the result into the def map.
debug!("(resolving expr) resolved `{}`",
- self.path_names_to_string(path));
+ self.path_names_to_string(path, 0));
self.record_def(expr.id, def);
}
// (The pattern matching def_tys where the id is in self.structs
// matches on regular structs while excluding tuple- and enum-like
// structs, which wouldn't result in this error.)
- let path_name = self.path_names_to_string(path);
+ let path_name = self.path_names_to_string(path, 0);
match self.with_no_errors(|this|
- this.resolve_path(expr.id, path, TypeNS, false)) {
+ this.resolve_path(expr.id, path, 0, TypeNS, false)) {
Some((DefTy(struct_id, _), _))
if self.structs.contains_key(&struct_id) => {
self.resolve_error(expr.span,
// Resolve the path to the structure it goes to. We don't
// check to ensure that the path is actually a structure; that
// is checked later during typeck.
- match self.resolve_path(expr.id, path, TypeNS, false) {
+ match self.resolve_path(expr.id, path, 0, TypeNS, false) {
Some(definition) => self.record_def(expr.id, definition),
result => {
debug!("(resolving expression) didn't find struct \
def: {:?}", result);
let msg = format!("`{}` does not name a structure",
- self.path_names_to_string(path));
+ self.path_names_to_string(path, 0));
self.resolve_error(path.span, &msg[..]);
}
}
// Don't need to do anything for function calls,
// because just walking the callee path does what we want.
visit::walk_expr(self, ex);
- },
- ast::ExprPath(ref path) => {
- self.process_path(ex.id, path.span, path, None);
- visit::walk_path(self, path);
}
- ast::ExprQPath(ref qpath) => {
- 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, &**qpath);
+ ast::ExprPath(ref path) | ast::ExprQPath(ast::QPath { ref path, .. }) => {
+ self.process_path(ex.id, path.span, path, None);
+ visit::walk_expr(self, ex);
}
ast::ExprStruct(ref path, ref fields, ref base) =>
self.process_struct_lit(ex, path, fields, base),
let shifted_rscope = ShiftedRscope::new(rscope);
let trait_ref = instantiate_trait_ref(this, &shifted_rscope,
- &ast_trait_ref.trait_ref.path,
- ast_trait_ref.trait_ref.ref_id,
+ &ast_trait_ref.trait_ref,
None, self_ty, Some(&mut projections));
for projection in projections {
pub fn instantiate_trait_ref<'tcx>(
this: &AstConv<'tcx>,
rscope: &RegionScope,
- path: &ast::Path,
- path_id: ast::NodeId,
+ trait_ref: &ast::TraitRef,
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(), path.span, path_id) {
+ let path = &trait_ref.path;
+ match ::lookup_def_tcx(this.tcx(), path.span, trait_ref.ref_id) {
def::DefTrait(trait_def_id) => {
let trait_ref = ast_path_to_trait_ref(this,
rscope,
ast::TyPolyTraitRef(ref bounds) => {
conv_ty_poly_trait_ref(this, rscope, ast_ty.span, &bounds[..])
}
- ast::TyPath(_) | ast::TyQPath(_) => {
- let simple_path = |&:| match ast_ty.node {
- ast::TyPath(ref path) => path,
- _ => tcx.sess.span_bug(ast_ty.span, "expected non-qualified path")
- };
+ ast::TyPath(ref path) | ast::TyQPath(ast::QPath { ref path, .. }) => {
let a_def = match tcx.def_map.borrow().get(&ast_ty.id) {
None => {
tcx.sess
let trait_ref = object_path_to_poly_trait_ref(this,
rscope,
trait_def_id,
- simple_path(),
+ path,
&mut projection_bounds);
trait_ref_to_object_type(this, rscope, ast_ty.span,
trait_ref, projection_bounds, &[])
}
def::DefTy(did, _) | def::DefStruct(did) => {
- ast_path_to_ty(this, rscope, did, simple_path()).ty
+ ast_path_to_ty(this, rscope, did, path).ty
}
def::DefTyParam(space, index, _, name) => {
- check_path_args(tcx, simple_path(), NO_TPS | NO_REGIONS);
+ check_path_args(tcx, path, NO_TPS | NO_REGIONS);
ty::mk_param(tcx, space, index, name)
}
def::DefSelfTy(_) => {
// n.b.: resolve guarantees that the this type only appears in a
// trait, which we rely upon in various places when creating
// substs
- check_path_args(tcx, simple_path(), NO_TPS | NO_REGIONS);
+ check_path_args(tcx, path, NO_TPS | NO_REGIONS);
ty::mk_self_type(tcx)
}
def::DefMod(id) => {
panic!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call");
}
def::DefAssociatedTy(trait_did, _) => {
- let (opt_self_ty, trait_segment, item_segment) = match ast_ty.node {
- ast::TyQPath(ref qpath) => {
- (Some(&*qpath.self_type), qpath.trait_path.segments.last().unwrap(),
- &qpath.item_path)
- }
- ast::TyPath(ref path) => {
- (None, &path.segments[path.segments.len()-2],
- path.segments.last().unwrap())
- }
- _ => unreachable!()
+ let opt_self_ty = if let ast::TyQPath(ref qpath) = ast_ty.node {
+ Some(&*qpath.self_type)
+ } else {
+ None
};
- qpath_to_ty(this, rscope, ast_ty.span, opt_self_ty,
- trait_did, trait_segment, item_segment)
+ qpath_to_ty(this, rscope, ast_ty.span, opt_self_ty, trait_did,
+ &path.segments[path.segments.len()-2],
+ path.segments.last().unwrap())
}
def::DefAssociatedPath(provenance, assoc_ident) => {
associated_path_def_to_ty(this, ast_ty, provenance, assoc_ident.name)
let self_ty = fcx.to_ty(&*qpath.self_type);
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_path.clone();
- path.segments.push(qpath.item_path.clone());
- instantiate_path(fcx, &path, scheme, &predicates, Some(self_ty),
+ instantiate_path(fcx, &qpath.path, scheme, &predicates, Some(self_ty),
defn, expr.span, expr.id);
// We always require that the type provided as the value for
if let Some(ref trait_ref) = *opt_trait_ref {
astconv::instantiate_trait_ref(ccx,
&ExplicitRscope,
- &trait_ref.path,
- trait_ref.ref_id,
+ trait_ref,
Some(it.id),
Some(selfty),
None);
resolve_type(cx, p.clean(cx), self.id)
}
TyQPath(ref qp) => {
+ let mut trait_path = qp.path.clone();
+ trait_path.segments.pop();
Type::QPath {
- name: qp.item_path.identifier.clean(cx),
+ name: qp.path.segments.last().unwrap().identifier.clean(cx),
self_type: box qp.self_type.clean(cx),
- trait_: box resolve_type(cx, qp.trait_path.clean(cx), self.id)
+ trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
}
}
TyObjectSum(ref lhs, ref bounds) => {
/// type parameters, e.g. foo::bar::<baz>
ExprPath(Path),
/// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
- ExprQPath(P<QPath>),
+ ExprQPath(QPath),
ExprAddrOf(Mutability, P<Expr>),
ExprBreak(Option<Ident>),
/// A "qualified path":
///
/// <Vec<T> as SomeTrait>::SomeAssociatedItem
-/// ^~~~~ ^~~~~~~~~ ^~~~~~~~~~~~~~~~~~
-/// self_type trait_path item_path
+/// ^~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+/// self_type path
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct QPath {
pub self_type: P<Ty>,
- pub trait_path: Path,
- pub item_path: PathSegment,
+ pub path: Path,
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
/// Type parameters are stored in the Path itself
TyPath(Path),
/// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
- TyQPath(P<QPath>),
+ TyQPath(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>`
-> ast::Path;
fn qpath(&self, self_type: P<ast::Ty>,
- trait_ref: P<ast::TraitRef>,
- ident: ast::Ident )
- -> P<ast::QPath>;
+ trait_path: ast::Path,
+ ident: ast::Ident)
+ -> ast::QPath;
fn qpath_all(&self, self_type: P<ast::Ty>,
- trait_ref: P<ast::TraitRef>,
+ trait_path: ast::Path,
ident: ast::Ident,
lifetimes: Vec<ast::Lifetime>,
types: Vec<P<ast::Ty>>,
- bindings: Vec<P<ast::TypeBinding>> )
- -> P<ast::QPath>;
+ bindings: Vec<P<ast::TypeBinding>>)
+ -> ast::QPath;
// types
fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy;
// expressions
fn expr(&self, span: Span, node: ast::Expr_) -> P<ast::Expr>;
fn expr_path(&self, path: ast::Path) -> P<ast::Expr>;
- fn expr_qpath(&self, span: Span, qpath: P<ast::QPath>) -> P<ast::Expr>;
+ fn expr_qpath(&self, span: Span, qpath: ast::QPath) -> P<ast::Expr>;
fn expr_ident(&self, span: Span, id: ast::Ident) -> P<ast::Expr>;
fn expr_self(&self, span: Span) -> P<ast::Expr>;
/// Constructs a qualified path.
///
- /// Constructs a path like `<self_type as trait_ref>::ident`.
+ /// Constructs a path like `<self_type as trait_path>::ident`.
fn qpath(&self,
self_type: P<ast::Ty>,
- trait_ref: P<ast::TraitRef>,
+ trait_path: ast::Path,
ident: ast::Ident)
- -> P<ast::QPath> {
- self.qpath_all(self_type, trait_ref, ident, Vec::new(), Vec::new(), Vec::new())
+ -> ast::QPath {
+ self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![])
}
/// Constructs a qualified path.
///
- /// Constructs a path like `<self_type as trait_ref>::ident<a, T, A=Bar>`.
+ /// Constructs a path like `<self_type as trait_path>::ident<'a, T, A=Bar>`.
fn qpath_all(&self,
self_type: P<ast::Ty>,
- trait_ref: P<ast::TraitRef>,
+ trait_path: ast::Path,
ident: ast::Ident,
lifetimes: Vec<ast::Lifetime>,
types: Vec<P<ast::Ty>>,
- bindings: Vec<P<ast::TypeBinding>> )
- -> P<ast::QPath> {
- let segment = ast::PathSegment {
+ bindings: Vec<P<ast::TypeBinding>>)
+ -> ast::QPath {
+ let mut path = trait_path;
+ path.segments.push(ast::PathSegment {
identifier: ident,
parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
lifetimes: lifetimes,
types: OwnedSlice::from_vec(types),
bindings: OwnedSlice::from_vec(bindings),
})
- };
+ });
- P(ast::QPath {
+ ast::QPath {
self_type: self_type,
- trait_ref: trait_ref,
- item_path: segment,
- })
+ path: path
+ }
}
fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy {
}
/// Constructs a QPath expression.
- fn expr_qpath(&self, span: Span, qpath: P<ast::QPath>) -> P<ast::Expr> {
+ fn expr_qpath(&self, span: Span, qpath: ast::QPath) -> P<ast::Expr> {
self.expr(span, ast::ExprQPath(qpath))
}
noop_fold_ty(t, self)
}
- fn fold_qpath(&mut self, t: P<QPath>) -> P<QPath> {
- noop_fold_qpath(t, self)
- }
-
fn fold_ty_binding(&mut self, t: P<TypeBinding>) -> P<TypeBinding> {
noop_fold_ty_binding(t, self)
}
TyParen(ty) => TyParen(fld.fold_ty(ty)),
TyPath(path) => TyPath(fld.fold_path(path)),
TyQPath(qpath) => {
- TyQPath(fld.fold_qpath(qpath))
+ TyQPath(QPath {
+ self_type: fld.fold_ty(qpath.self_type),
+ path: fld.fold_path(qpath.path)
+ })
}
TyObjectSum(ty, bounds) => {
TyObjectSum(fld.fold_ty(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_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),
- }
- }
- })
-}
-
pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod {abi, items}: ForeignMod,
fld: &mut T) -> ForeignMod {
ForeignMod {
e2.map(|x| folder.fold_expr(x)))
}
ExprPath(pth) => ExprPath(folder.fold_path(pth)),
- ExprQPath(qpath) => ExprQPath(folder.fold_qpath(qpath)),
+ ExprQPath(qpath) => ExprQPath(QPath {
+ self_type: folder.fold_ty(qpath.self_type),
+ path: folder.fold_path(qpath.path)
+ }),
ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))),
ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))),
ExprRet(e) => ExprRet(e.map(|x| folder.fold_expr(x))),
// QUALIFIED PATH `<TYPE as TRAIT_REF>::item`
let self_type = self.parse_ty_sum();
self.expect_keyword(keywords::As);
- let trait_path = self.parse_path(LifetimeAndTypesWithoutColons);
+ let mut 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_path: trait_path,
- item_path: ast::PathSegment {
- identifier: item_name,
- parameters: ast::PathParameters::none()
- }
- }))
+ path.segments.push(ast::PathSegment {
+ identifier: self.parse_ident(),
+ parameters: ast::PathParameters::none()
+ });
+ TyQPath(QPath { self_type: self_type, path: path })
} else if self.check(&token::ModSep) ||
self.token.is_ident() ||
self.token.is_path() {
// QUALIFIED PATH `<TYPE as TRAIT_REF>::item::<'a, T>`
let self_type = self.parse_ty_sum();
self.expect_keyword(keywords::As);
- let trait_path = self.parse_path(LifetimeAndTypesWithoutColons);
+ let mut path = self.parse_path(LifetimeAndTypesWithoutColons);
self.expect(&token::Gt);
self.expect(&token::ModSep);
let item_name = self.parse_ident();
} else {
ast::PathParameters::none()
};
+ path.segments.push(ast::PathSegment {
+ identifier: item_name,
+ parameters: parameters
+ });
let hi = self.span.hi;
- return self.mk_expr(lo, hi, ExprQPath(P(QPath {
- self_type: self_type,
- trait_path: trait_path,
- item_path: ast::PathSegment {
- identifier: item_name,
- parameters: parameters
- }
- })));
+ return self.mk_expr(lo, hi,
+ ExprQPath(QPath { self_type: self_type, path: path }));
}
if self.eat_keyword(keywords::Move) {
return self.parse_lambda_expr(CaptureByValue);
}
pub fn path_to_string(p: &ast::Path) -> String {
- $to_string(|s| s.print_path(p, false))
+ $to_string(|s| s.print_path(p, false, 0))
}
pub fn ident_to_string(id: &ast::Ident) -> String {
None));
}
ast::TyPath(ref path) => {
- try!(self.print_path(path, false));
+ try!(self.print_path(path, false, 0));
+ }
+ ast::TyQPath(ref qpath) => {
+ try!(self.print_qpath(qpath, false))
}
ast::TyObjectSum(ref ty, ref bounds) => {
try!(self.print_type(&**ty));
ast::TyPolyTraitRef(ref bounds) => {
try!(self.print_bounds("", &bounds[..]));
}
- ast::TyQPath(ref qpath) => {
- try!(self.print_qpath(&**qpath, false))
- }
ast::TyFixedLengthVec(ref ty, ref v) => {
try!(word(&mut self.s, "["));
try!(self.print_type(&**ty));
ast::ItemMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _),
..}) => {
try!(self.print_visibility(item.vis));
- try!(self.print_path(pth, false));
+ try!(self.print_path(pth, false, 0));
try!(word(&mut self.s, "! "));
try!(self.print_ident(item.ident));
try!(self.cbox(indent_unit));
}
fn print_trait_ref(&mut self, t: &ast::TraitRef) -> IoResult<()> {
- self.print_path(&t.path, false)
+ self.print_path(&t.path, false, 0)
}
fn print_formal_lifetime_list(&mut self, lifetimes: &[ast::LifetimeDef]) -> IoResult<()> {
ast::MethMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _),
..}) => {
// code copied from ItemMac:
- try!(self.print_path(pth, false));
+ try!(self.print_path(pth, false, 0));
try!(word(&mut self.s, "! "));
try!(self.cbox(indent_unit));
try!(self.popen());
match m.node {
// I think it's reasonable to hide the ctxt here:
ast::MacInvocTT(ref pth, ref tts, _) => {
- try!(self.print_path(pth, false));
+ try!(self.print_path(pth, false, 0));
try!(word(&mut self.s, "!"));
match delim {
token::Paren => try!(self.popen()),
path: &ast::Path,
fields: &[ast::Field],
wth: &Option<P<ast::Expr>>) -> IoResult<()> {
- try!(self.print_path(path, true));
+ try!(self.print_path(path, true, 0));
if !(fields.is_empty() && wth.is_none()) {
try!(word(&mut self.s, "{"));
try!(self.commasep_cmnt(
try!(self.print_expr(&**e));
}
}
- ast::ExprPath(ref path) => try!(self.print_path(path, true)),
- ast::ExprQPath(ref qpath) => try!(self.print_qpath(&**qpath, true)),
+ ast::ExprPath(ref path) => try!(self.print_path(path, true, 0)),
+ ast::ExprQPath(ref qpath) => try!(self.print_qpath(qpath, true)),
ast::ExprBreak(opt_ident) => {
try!(word(&mut self.s, "break"));
try!(space(&mut self.s));
fn print_path(&mut self,
path: &ast::Path,
- colons_before_params: bool)
+ colons_before_params: bool,
+ depth: usize)
-> IoResult<()>
{
try!(self.maybe_print_comment(path.span.lo));
- if path.global {
- try!(word(&mut self.s, "::"));
- }
- let mut first = true;
- for segment in &path.segments {
+ let mut first = !path.global;
+ for segment in &path.segments[..path.segments.len()-depth] {
if first {
first = false
} else {
try!(self.print_type(&*qpath.self_type));
try!(space(&mut self.s));
try!(self.word_space("as"));
- try!(self.print_path(&qpath.trait_path, false));
+ try!(self.print_path(&qpath.path, false, 1));
try!(word(&mut self.s, ">"));
try!(word(&mut self.s, "::"));
- try!(self.print_ident(qpath.item_path.identifier));
- self.print_path_parameters(&qpath.item_path.parameters, colons_before_params)
+ let item_segment = qpath.path.segments.last().unwrap();
+ try!(self.print_ident(item_segment.identifier));
+ self.print_path_parameters(&item_segment.parameters, colons_before_params)
}
fn print_path_parameters(&mut self,
}
}
ast::PatEnum(ref path, ref args_) => {
- try!(self.print_path(path, true));
+ try!(self.print_path(path, true, 0));
match *args_ {
None => try!(word(&mut self.s, "(..)")),
Some(ref args) => {
}
}
ast::PatStruct(ref path, ref fields, etc) => {
- try!(self.print_path(path, true));
+ try!(self.print_path(path, true, 0));
try!(self.nbsp());
try!(self.word_space("{"));
try!(self.commasep_cmnt(
}
}
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => {
- try!(self.print_path(path, false));
+ try!(self.print_path(path, false, 0));
try!(space(&mut self.s));
try!(self.word_space("="));
try!(self.print_type(&**ty));
pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> IoResult<()> {
match vp.node {
ast::ViewPathSimple(ident, ref path) => {
- try!(self.print_path(path, false));
+ try!(self.print_path(path, false, 0));
// FIXME(#6993) can't compare identifiers directly here
if path.segments.last().unwrap().identifier.name !=
}
ast::ViewPathGlob(ref path) => {
- try!(self.print_path(path, false));
+ try!(self.print_path(path, false, 0));
word(&mut self.s, "::*")
}
if path.segments.is_empty() {
try!(word(&mut self.s, "{"));
} else {
- try!(self.print_path(path, false));
+ try!(self.print_path(path, false, 0));
try!(word(&mut self.s, "::{"));
}
try!(self.commasep(Inconsistent, &idents[..], |s, w| {
fn visit_path(&mut self, path: &'v Path, _id: ast::NodeId) {
walk_path(self, path)
}
- 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)
}
visitor.visit_path(path, typ.id);
}
TyQPath(ref qpath) => {
- visitor.visit_qpath(&**qpath, typ.id);
+ visitor.visit_ty(&*qpath.self_type);
+ visitor.visit_path(&qpath.path, typ.id);
}
TyObjectSum(ref ty, ref bounds) => {
visitor.visit_ty(&**ty);
}
}
-pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath) {
- visitor.visit_ty(&*qpath.self_type);
- 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,
path_span: Span,
segment: &'v PathSegment) {
visitor.visit_path(path, expression.id)
}
ExprQPath(ref qpath) => {
- visitor.visit_qpath(&**qpath, expression.id)
+ visitor.visit_ty(&*qpath.self_type);
+ visitor.visit_path(&qpath.path, expression.id);
}
ExprBreak(_) | ExprAgain(_) => {}
ExprRet(ref optional_expression) => {