let mut span = e.span;
let id = match e.node {
- ast::ExprPath(..) | ast::ExprStruct(..) => {
+ ast::ExprPath(..) | ast::ExprQPath(..) | ast::ExprStruct(..) => {
match cx.tcx.def_map.borrow().get(&e.id) {
Some(&def) => def.def_id(),
None => return
ast::ExprMac(..) |
ast::ExprClosure(..) |
ast::ExprLit(..) |
- ast::ExprPath(..) => {
+ ast::ExprPath(..) |
+ ast::ExprQPath(..) => {
self.straightline(expr, pred, None::<ast::Expr>.iter())
}
}
expression");
}
}
- ast::ExprPath(_) => {
+ ast::ExprPath(_) | ast::ExprQPath(_) => {
match v.tcx.def_map.borrow()[e.id] {
DefStatic(..) | DefConst(..) |
DefFn(..) | DefStaticMethod(..) | DefMethod(..) |
"{} are not allowed to have custom pointers",
self.msg());
}
- ast::ExprPath(..) => {
+ ast::ExprPath(_) | ast::ExprQPath(_) => {
match ty::resolve_expr(self.tcx, e) {
def::DefStatic(..) if self.mode == InConstant => {
let msg = "constants cannot refer to other statics, \
fn visit_expr(&mut self, e: &ast::Expr) {
match e.node {
- ast::ExprPath(..) => {
+ ast::ExprPath(_) | ast::ExprQPath(_) => {
match self.def_map.borrow().get(&e.id) {
Some(&DefStatic(def_id, _)) |
Some(&DefConst(def_id)) if
// FIXME: (#3728) we can probably do something CCI-ish
// surrounding nonlocal constants. But we don't yet.
- ast::ExprPath(_) => self.lookup_constness(e),
+ ast::ExprPath(_) | ast::ExprQPath(_) => self.lookup_constness(e),
ast::ExprRepeat(..) => general_const,
}
}
+ ast::ExprQPath(_) => {
+ match lookup_const(tcx, expr) {
+ Some(actual) => return const_expr_to_pat(tcx, actual),
+ _ => unreachable!()
+ }
+ }
+
_ => ast::PatLit(P(expr.clone()))
};
P(ast::Pat { id: expr.id, node: pat, span: expr.span })
ty::ty_float(ast::TyF64) => (f64, const_float, f64)
}))
}
- ast::ExprPath(_) => {
+ ast::ExprPath(_) | ast::ExprQPath(_) => {
match lookup_const(tcx, e) {
Some(actual_e) => eval_const_expr_partial(tcx, &*actual_e),
None => Err("non-constant path in constant expr".to_string())
ast::ExprInlineAsm(..) => {
self.require_unsafe(expr.span, "use of inline assembly");
}
- ast::ExprPath(..) => {
+ ast::ExprPath(_) | ast::ExprQPath(_) => {
if let def::DefStatic(_, true) = ty::resolve_expr(self.tcx, expr) {
self.require_unsafe(expr.span, "use of mutable static");
}
self.walk_expr(&**subexpr)
}
- ast::ExprPath(..) => { }
+ ast::ExprPath(_) | ast::ExprQPath(_) => { }
ast::ExprUnary(ast::UnDeref, ref base) => { // *base
if !self.walk_overloaded_operator(expr, &**base, Vec::new(), PassArgs::ByRef) {
fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
match expr.node {
// live nodes required for uses or definitions of variables:
- ast::ExprPath(_) => {
+ ast::ExprPath(_) | ast::ExprQPath(_) => {
let def = ir.tcx.def_map.borrow()[expr.id].clone();
debug!("expr {}: path that leads to {:?}", expr.id, def);
if let DefLocal(..) = def {
match expr.node {
// Interesting cases with control flow or which gen/kill
- ast::ExprPath(_) => {
+ ast::ExprPath(_) | ast::ExprQPath(_) => {
self.access_path(expr, succ, ACC_READ | ACC_USE)
}
// just ignore such cases and treat them as reads.
match expr.node {
- ast::ExprPath(_) => succ,
+ ast::ExprPath(_) | ast::ExprQPath(_) => succ,
ast::ExprField(ref e, _) => self.propagate_through_expr(&**e, succ),
ast::ExprTupField(ref e, _) => self.propagate_through_expr(&**e, succ),
_ => self.propagate_through_expr(expr, succ)
fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: uint)
-> LiveNode {
match expr.node {
- ast::ExprPath(_) => self.access_path(expr, succ, acc),
+ ast::ExprPath(_) | ast::ExprQPath(_) => {
+ self.access_path(expr, succ, acc)
+ }
// We do not track other lvalues, so just propagate through
// to their subcomponents. Also, it may happen that
ast::ExprBlock(..) | ast::ExprMac(..) | ast::ExprAddrOf(..) |
ast::ExprStruct(..) | ast::ExprRepeat(..) | ast::ExprParen(..) |
ast::ExprClosure(..) | ast::ExprPath(..) | ast::ExprBox(..) |
- ast::ExprRange(..) => {
+ ast::ExprRange(..) | ast::ExprQPath(..) => {
visit::walk_expr(this, expr);
}
ast::ExprIfLet(..) => {
fn check_lvalue(&mut self, expr: &Expr) {
match expr.node {
- ast::ExprPath(_) => {
+ ast::ExprPath(_) | ast::ExprQPath(_) => {
if let DefLocal(nid) = self.ir.tcx.def_map.borrow()[expr.id].clone() {
// Assignment to an immutable variable or argument: only legal
// if there is no later assignment. If this local is actually
}
}
- ast::ExprPath(_) => {
+ ast::ExprPath(_) | ast::ExprQPath(_) => {
let def = (*self.tcx().def_map.borrow())[expr.id];
self.cat_def(expr.id, expr.span, expr_ty, def)
}
struct type?!"),
}
}
- ast::ExprPath(..) => {
+ ast::ExprPath(_) | ast::ExprQPath(_) => {
let guard = |&: did: ast::DefId| {
let fields = ty::lookup_struct_fields(self.tcx, did);
let any_priv = fields.iter().any(|f| {
fn visit_expr(&mut self, expr: &ast::Expr) {
match expr.node {
- ast::ExprPath(_) => {
+ ast::ExprPath(_) | ast::ExprQPath(_) => {
let def = match self.tcx.def_map.borrow().get(&expr.id) {
Some(&def) => def,
None => {
}
match expr.node {
- ast::ExprPath(..) => {
+ ast::ExprPath(_) | ast::ExprQPath(_) => {
match resolve_expr(tcx, expr) {
def::DefVariant(tid, vid, _) => {
let variant_info = enum_variant_with_id(tcx, tid, vid);
SawExprIndex,
SawExprRange,
SawExprPath,
+ SawExprQPath,
SawExprAddrOf(ast::Mutability),
SawExprRet,
SawExprInlineAsm(&'a ast::InlineAsm),
ExprIndex(..) => SawExprIndex,
ExprRange(..) => SawExprRange,
ExprPath(..) => SawExprPath,
+ ExprQPath(..) => SawExprQPath,
ExprAddrOf(m, _) => SawExprAddrOf(m),
ExprBreak(id) => SawExprBreak(id.map(content)),
ExprAgain(id) => SawExprAgain(id.map(content)),
/// Checks whether the binding in `discr` is assigned to anywhere in the expression `body`
fn is_discr_reassigned(bcx: Block, discr: &ast::Expr, body: &ast::Expr) -> bool {
let (vid, field) = match discr.node {
- ast::ExprPath(..) => match bcx.def(discr.id) {
+ ast::ExprPath(_) | ast::ExprQPath(_) => match bcx.def(discr.id) {
def::DefLocal(vid) | def::DefUpvar(vid, _, _) => (vid, None),
_ => return false
},
debug!("callee::trans(expr={})", expr.repr(bcx.tcx()));
// pick out special kinds of expressions that can be called:
- if let ast::ExprPath(_) = expr.node {
- return trans_def(bcx, bcx.def(expr.id), expr);
+ match expr.node {
+ ast::ExprPath(_) | ast::ExprQPath(_) => {
+ return trans_def(bcx, bcx.def(expr.id), expr);
+ }
+ _ => {}
}
// any other expressions are closures:
C_array(llunitty, &vs[])
}
}
- ast::ExprPath(_) => {
+ ast::ExprPath(_) | ast::ExprQPath(_) => {
let def = cx.tcx().def_map.borrow()[e.id];
match def {
def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => {
ast::ExprLit(_) |
ast::ExprBreak(_) |
ast::ExprAgain(_) |
- ast::ExprPath(_) => {}
+ ast::ExprPath(_) |
+ ast::ExprQPath(_) => {}
ast::ExprCast(ref sub_exp, _) |
ast::ExprAddrOf(_, ref sub_exp) |
ast::ExprParen(ref e) => {
trans(bcx, &**e)
}
- ast::ExprPath(_) => {
+ ast::ExprPath(_) | ast::ExprQPath(_) => {
trans_def(bcx, expr, bcx.def(expr.id))
}
ast::ExprField(ref base, ident) => {
ast::ExprParen(ref e) => {
trans_into(bcx, &**e, dest)
}
- ast::ExprPath(_) => {
+ ast::ExprPath(_) | ast::ExprQPath(_) => {
trans_def_dps_unadjusted(bcx, expr, bcx.def(expr.id), dest)
}
ast::ExprIf(ref cond, ref thn, ref els) => {
debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(this.tcx()));
+ // `<T as Trait>::U<V>` shouldn't parse right now.
+ assert!(qpath.item_path.parameters.is_empty());
+
return this.projected_ty(ast_ty.span,
trait_ref,
- qpath.item_name.name);
+ qpath.item_path.identifier.name);
}
// Parses the programmer's textual representation of a type into our
impl Clean<Type> for ast::QPath {
fn clean(&self, cx: &DocContext) -> Type {
Type::QPath {
- name: self.item_name.clean(cx),
+ name: self.item_path.identifier.clean(cx),
self_type: box self.self_type.clean(cx),
trait_: box self.trait_ref.clean(cx)
}
/// Variable reference, possibly containing `::` and/or
/// type parameters, e.g. foo::bar::<baz>
ExprPath(Path),
+ /// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
+ ExprQPath(P<QPath>),
ExprAddrOf(Mutability, P<Expr>),
ExprBreak(Option<Ident>),
///
/// <Vec<T> as SomeTrait>::SomeAssociatedItem
/// ^~~~~ ^~~~~~~~~ ^~~~~~~~~~~~~~~~~~
-/// self_type trait_name item_name
+/// self_type trait_name item_path
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
pub struct QPath {
pub self_type: P<Ty>,
pub trait_ref: P<TraitRef>,
- pub item_name: Ident, // FIXME(#20301) -- should use Name
+ pub item_path: PathSegment,
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)]
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),
+ item_path: PathSegment {
+ identifier: fld.fold_ident(qpath.item_path.identifier),
+ parameters: fld.fold_path_parameters(qpath.item_path.parameters),
+ }
}
})
}
e2.map(|x| folder.fold_expr(x)))
}
ExprPath(pth) => ExprPath(folder.fold_path(pth)),
+ ExprQPath(qpath) => ExprQPath(folder.fold_qpath(qpath)),
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))),
try!(self.print_bounds("", &bounds[]));
}
ast::TyQPath(ref qpath) => {
- try!(word(&mut self.s, "<"));
- 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!(word(&mut self.s, ">"));
- try!(word(&mut self.s, "::"));
- try!(self.print_ident(qpath.item_name));
+ try!(self.print_qpath(&**qpath, false))
}
ast::TyFixedLengthVec(ref ty, ref v) => {
try!(word(&mut self.s, "["));
}
}
ast::ExprPath(ref path) => try!(self.print_path(path, true)),
+ 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));
Ok(())
}
+ fn print_qpath(&mut self,
+ qpath: &ast::QPath,
+ colons_before_params: bool)
+ -> IoResult<()>
+ {
+ try!(word(&mut self.s, "<"));
+ 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!(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)
+ }
+
fn print_path_parameters(&mut self,
parameters: &ast::PathParameters,
colons_before_params: bool)
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_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
walk_path_segment(self, path_span, path_segment)
}
walk_ty_param_bounds_helper(visitor, bounds);
}
TyQPath(ref qpath) => {
- visitor.visit_ty(&*qpath.self_type);
- visitor.visit_trait_ref(&*qpath.trait_ref);
- visitor.visit_ident(typ.span, qpath.item_name);
+ visitor.visit_qpath(typ.span, &**qpath);
}
TyFixedLengthVec(ref ty, ref expression) => {
visitor.visit_ty(&**ty);
}
}
+pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V,
+ qpath_span: Span,
+ 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);
+}
+
pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
path_span: Span,
segment: &'v PathSegment) {
ExprPath(ref path) => {
visitor.visit_path(path, expression.id)
}
+ ExprQPath(ref qpath) => {
+ visitor.visit_qpath(expression.span, &**qpath)
+ }
ExprBreak(_) | ExprAgain(_) => {}
ExprRet(ref optional_expression) => {
walk_expr_opt(visitor, optional_expression)