Skip to content

Commit 2cdc86c

Browse files
committed
syntax: add fully qualified UFCS expressions.
1 parent 1c78ad9 commit 2cdc86c

25 files changed

+89
-42
lines changed

src/librustc/lint/builtin.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1731,7 +1731,7 @@ impl LintPass for Stability {
17311731
let mut span = e.span;
17321732

17331733
let id = match e.node {
1734-
ast::ExprPath(..) | ast::ExprStruct(..) => {
1734+
ast::ExprPath(..) | ast::ExprQPath(..) | ast::ExprStruct(..) => {
17351735
match cx.tcx.def_map.borrow().get(&e.id) {
17361736
Some(&def) => def.def_id(),
17371737
None => return

src/librustc/middle/cfg/construct.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
495495
ast::ExprMac(..) |
496496
ast::ExprClosure(..) |
497497
ast::ExprLit(..) |
498-
ast::ExprPath(..) => {
498+
ast::ExprPath(..) |
499+
ast::ExprQPath(..) => {
499500
self.straightline(expr, pred, None::<ast::Expr>.iter())
500501
}
501502
}

src/librustc/middle/check_const.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) {
111111
expression");
112112
}
113113
}
114-
ast::ExprPath(_) => {
114+
ast::ExprPath(_) | ast::ExprQPath(_) => {
115115
match v.tcx.def_map.borrow()[e.id] {
116116
DefStatic(..) | DefConst(..) |
117117
DefFn(..) | DefStaticMethod(..) | DefMethod(..) |

src/librustc/middle/check_static.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckStaticVisitor<'a, 'tcx> {
228228
"{} are not allowed to have custom pointers",
229229
self.msg());
230230
}
231-
ast::ExprPath(..) => {
231+
ast::ExprPath(_) | ast::ExprQPath(_) => {
232232
match ty::resolve_expr(self.tcx, e) {
233233
def::DefStatic(..) if self.mode == InConstant => {
234234
let msg = "constants cannot refer to other statics, \

src/librustc/middle/check_static_recursion.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ impl<'a, 'ast, 'v> Visitor<'v> for CheckItemRecursionVisitor<'a, 'ast> {
9393

9494
fn visit_expr(&mut self, e: &ast::Expr) {
9595
match e.node {
96-
ast::ExprPath(..) => {
96+
ast::ExprPath(_) | ast::ExprQPath(_) => {
9797
match self.def_map.borrow().get(&e.id) {
9898
Some(&DefStatic(def_id, _)) |
9999
Some(&DefConst(def_id)) if

src/librustc/middle/const_eval.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ impl<'a, 'tcx> ConstEvalVisitor<'a, 'tcx> {
244244

245245
// FIXME: (#3728) we can probably do something CCI-ish
246246
// surrounding nonlocal constants. But we don't yet.
247-
ast::ExprPath(_) => self.lookup_constness(e),
247+
ast::ExprPath(_) | ast::ExprQPath(_) => self.lookup_constness(e),
248248

249249
ast::ExprRepeat(..) => general_const,
250250

@@ -356,6 +356,13 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P<ast::Pat> {
356356
}
357357
}
358358

359+
ast::ExprQPath(_) => {
360+
match lookup_const(tcx, expr) {
361+
Some(actual) => return const_expr_to_pat(tcx, actual),
362+
_ => unreachable!()
363+
}
364+
}
365+
359366
_ => ast::PatLit(P(expr.clone()))
360367
};
361368
P(ast::Pat { id: expr.id, node: pat, span: expr.span })
@@ -542,7 +549,7 @@ pub fn eval_const_expr_partial(tcx: &ty::ctxt, e: &Expr) -> Result<const_val, St
542549
ty::ty_float(ast::TyF64) => (f64, const_float, f64)
543550
}))
544551
}
545-
ast::ExprPath(_) => {
552+
ast::ExprPath(_) | ast::ExprQPath(_) => {
546553
match lookup_const(tcx, e) {
547554
Some(actual_e) => eval_const_expr_partial(tcx, &*actual_e),
548555
None => Err("non-constant path in constant expr".to_string())

src/librustc/middle/effect.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
175175
ast::ExprInlineAsm(..) => {
176176
self.require_unsafe(expr.span, "use of inline assembly");
177177
}
178-
ast::ExprPath(..) => {
178+
ast::ExprPath(_) | ast::ExprQPath(_) => {
179179
if let def::DefStatic(_, true) = ty::resolve_expr(self.tcx, expr) {
180180
self.require_unsafe(expr.span, "use of mutable static");
181181
}

src/librustc/middle/expr_use_visitor.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
424424
self.walk_expr(&**subexpr)
425425
}
426426

427-
ast::ExprPath(..) => { }
427+
ast::ExprPath(_) | ast::ExprQPath(_) => { }
428428

429429
ast::ExprUnary(ast::UnDeref, ref base) => { // *base
430430
if !self.walk_overloaded_operator(expr, &**base, Vec::new(), PassArgs::ByRef) {

src/librustc/middle/liveness.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ fn visit_arm(ir: &mut IrMaps, arm: &ast::Arm) {
447447
fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
448448
match expr.node {
449449
// live nodes required for uses or definitions of variables:
450-
ast::ExprPath(_) => {
450+
ast::ExprPath(_) | ast::ExprQPath(_) => {
451451
let def = ir.tcx.def_map.borrow()[expr.id].clone();
452452
debug!("expr {}: path that leads to {:?}", expr.id, def);
453453
if let DefLocal(..) = def {
@@ -960,7 +960,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
960960
match expr.node {
961961
// Interesting cases with control flow or which gen/kill
962962

963-
ast::ExprPath(_) => {
963+
ast::ExprPath(_) | ast::ExprQPath(_) => {
964964
self.access_path(expr, succ, ACC_READ | ACC_USE)
965965
}
966966

@@ -1289,7 +1289,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
12891289
// just ignore such cases and treat them as reads.
12901290

12911291
match expr.node {
1292-
ast::ExprPath(_) => succ,
1292+
ast::ExprPath(_) | ast::ExprQPath(_) => succ,
12931293
ast::ExprField(ref e, _) => self.propagate_through_expr(&**e, succ),
12941294
ast::ExprTupField(ref e, _) => self.propagate_through_expr(&**e, succ),
12951295
_ => self.propagate_through_expr(expr, succ)
@@ -1300,7 +1300,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
13001300
fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: uint)
13011301
-> LiveNode {
13021302
match expr.node {
1303-
ast::ExprPath(_) => self.access_path(expr, succ, acc),
1303+
ast::ExprPath(_) | ast::ExprQPath(_) => {
1304+
self.access_path(expr, succ, acc)
1305+
}
13041306

13051307
// We do not track other lvalues, so just propagate through
13061308
// to their subcomponents. Also, it may happen that
@@ -1492,7 +1494,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
14921494
ast::ExprBlock(..) | ast::ExprMac(..) | ast::ExprAddrOf(..) |
14931495
ast::ExprStruct(..) | ast::ExprRepeat(..) | ast::ExprParen(..) |
14941496
ast::ExprClosure(..) | ast::ExprPath(..) | ast::ExprBox(..) |
1495-
ast::ExprRange(..) => {
1497+
ast::ExprRange(..) | ast::ExprQPath(..) => {
14961498
visit::walk_expr(this, expr);
14971499
}
14981500
ast::ExprIfLet(..) => {
@@ -1583,7 +1585,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
15831585

15841586
fn check_lvalue(&mut self, expr: &Expr) {
15851587
match expr.node {
1586-
ast::ExprPath(_) => {
1588+
ast::ExprPath(_) | ast::ExprQPath(_) => {
15871589
if let DefLocal(nid) = self.ir.tcx.def_map.borrow()[expr.id].clone() {
15881590
// Assignment to an immutable variable or argument: only legal
15891591
// if there is no later assignment. If this local is actually

src/librustc/middle/mem_categorization.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
520520
}
521521
}
522522

523-
ast::ExprPath(_) => {
523+
ast::ExprPath(_) | ast::ExprQPath(_) => {
524524
let def = (*self.tcx().def_map.borrow())[expr.id];
525525
self.cat_def(expr.id, expr.span, expr_ty, def)
526526
}

src/librustc/middle/privacy.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -920,7 +920,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
920920
struct type?!"),
921921
}
922922
}
923-
ast::ExprPath(..) => {
923+
ast::ExprPath(_) | ast::ExprQPath(_) => {
924924
let guard = |&: did: ast::DefId| {
925925
let fields = ty::lookup_struct_fields(self.tcx, did);
926926
let any_priv = fields.iter().any(|f| {

src/librustc/middle/reachable.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> {
104104
fn visit_expr(&mut self, expr: &ast::Expr) {
105105

106106
match expr.node {
107-
ast::ExprPath(_) => {
107+
ast::ExprPath(_) | ast::ExprQPath(_) => {
108108
let def = match self.tcx.def_map.borrow().get(&expr.id) {
109109
Some(&def) => def,
110110
None => {

src/librustc/middle/ty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4515,7 +4515,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
45154515
}
45164516

45174517
match expr.node {
4518-
ast::ExprPath(..) => {
4518+
ast::ExprPath(_) | ast::ExprQPath(_) => {
45194519
match resolve_expr(tcx, expr) {
45204520
def::DefVariant(tid, vid, _) => {
45214521
let variant_info = enum_variant_with_id(tcx, tid, vid);

src/librustc_back/svh.rs

+2
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ mod svh_visitor {
252252
SawExprIndex,
253253
SawExprRange,
254254
SawExprPath,
255+
SawExprQPath,
255256
SawExprAddrOf(ast::Mutability),
256257
SawExprRet,
257258
SawExprInlineAsm(&'a ast::InlineAsm),
@@ -285,6 +286,7 @@ mod svh_visitor {
285286
ExprIndex(..) => SawExprIndex,
286287
ExprRange(..) => SawExprRange,
287288
ExprPath(..) => SawExprPath,
289+
ExprQPath(..) => SawExprQPath,
288290
ExprAddrOf(m, _) => SawExprAddrOf(m),
289291
ExprBreak(id) => SawExprBreak(id.map(content)),
290292
ExprAgain(id) => SawExprAgain(id.map(content)),

src/librustc_trans/trans/_match.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1235,7 +1235,7 @@ pub fn trans_match<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
12351235
/// Checks whether the binding in `discr` is assigned to anywhere in the expression `body`
12361236
fn is_discr_reassigned(bcx: Block, discr: &ast::Expr, body: &ast::Expr) -> bool {
12371237
let (vid, field) = match discr.node {
1238-
ast::ExprPath(..) => match bcx.def(discr.id) {
1238+
ast::ExprPath(_) | ast::ExprQPath(_) => match bcx.def(discr.id) {
12391239
def::DefLocal(vid) | def::DefUpvar(vid, _, _) => (vid, None),
12401240
_ => return false
12411241
},

src/librustc_trans/trans/callee.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,11 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
9191
debug!("callee::trans(expr={})", expr.repr(bcx.tcx()));
9292

9393
// pick out special kinds of expressions that can be called:
94-
if let ast::ExprPath(_) = expr.node {
95-
return trans_def(bcx, bcx.def(expr.id), expr);
94+
match expr.node {
95+
ast::ExprPath(_) | ast::ExprQPath(_) => {
96+
return trans_def(bcx, bcx.def(expr.id), expr);
97+
}
98+
_ => {}
9699
}
97100

98101
// any other expressions are closures:

src/librustc_trans/trans/consts.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef {
600600
C_array(llunitty, &vs[])
601601
}
602602
}
603-
ast::ExprPath(_) => {
603+
ast::ExprPath(_) | ast::ExprQPath(_) => {
604604
let def = cx.tcx().def_map.borrow()[e.id];
605605
match def {
606606
def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => {

src/librustc_trans/trans/debuginfo.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -3526,7 +3526,8 @@ fn create_scope_map(cx: &CrateContext,
35263526
ast::ExprLit(_) |
35273527
ast::ExprBreak(_) |
35283528
ast::ExprAgain(_) |
3529-
ast::ExprPath(_) => {}
3529+
ast::ExprPath(_) |
3530+
ast::ExprQPath(_) => {}
35303531

35313532
ast::ExprCast(ref sub_exp, _) |
35323533
ast::ExprAddrOf(_, ref sub_exp) |

src/librustc_trans/trans/expr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,7 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
564564
ast::ExprParen(ref e) => {
565565
trans(bcx, &**e)
566566
}
567-
ast::ExprPath(_) => {
567+
ast::ExprPath(_) | ast::ExprQPath(_) => {
568568
trans_def(bcx, expr, bcx.def(expr.id))
569569
}
570570
ast::ExprField(ref base, ident) => {
@@ -997,7 +997,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
997997
ast::ExprParen(ref e) => {
998998
trans_into(bcx, &**e, dest)
999999
}
1000-
ast::ExprPath(_) => {
1000+
ast::ExprPath(_) | ast::ExprQPath(_) => {
10011001
trans_def_dps_unadjusted(bcx, expr, bcx.def(expr.id), dest)
10021002
}
10031003
ast::ExprIf(ref cond, ref thn, ref els) => {

src/librustc_typeck/astconv.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1001,9 +1001,12 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
10011001

10021002
debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(this.tcx()));
10031003

1004+
// `<T as Trait>::U<V>` shouldn't parse right now.
1005+
assert!(qpath.item_path.parameters.is_empty());
1006+
10041007
return this.projected_ty(ast_ty.span,
10051008
trait_ref,
1006-
qpath.item_name.name);
1009+
qpath.item_path.identifier.name);
10071010
}
10081011

10091012
// Parses the programmer's textual representation of a type into our

src/librustdoc/clean/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1614,7 +1614,7 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
16141614
impl Clean<Type> for ast::QPath {
16151615
fn clean(&self, cx: &DocContext) -> Type {
16161616
Type::QPath {
1617-
name: self.item_name.clean(cx),
1617+
name: self.item_path.identifier.clean(cx),
16181618
self_type: box self.self_type.clean(cx),
16191619
trait_: box self.trait_ref.clean(cx)
16201620
}

src/libsyntax/ast.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,8 @@ pub enum Expr_ {
747747
/// Variable reference, possibly containing `::` and/or
748748
/// type parameters, e.g. foo::bar::<baz>
749749
ExprPath(Path),
750+
/// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
751+
ExprQPath(P<QPath>),
750752

751753
ExprAddrOf(Mutability, P<Expr>),
752754
ExprBreak(Option<Ident>),
@@ -771,12 +773,12 @@ pub enum Expr_ {
771773
///
772774
/// <Vec<T> as SomeTrait>::SomeAssociatedItem
773775
/// ^~~~~ ^~~~~~~~~ ^~~~~~~~~~~~~~~~~~
774-
/// self_type trait_name item_name
776+
/// self_type trait_name item_path
775777
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
776778
pub struct QPath {
777779
pub self_type: P<Ty>,
778780
pub trait_ref: P<TraitRef>,
779-
pub item_name: Ident, // FIXME(#20301) -- should use Name
781+
pub item_path: PathSegment,
780782
}
781783

782784
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)]

src/libsyntax/fold.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,10 @@ pub fn noop_fold_qpath<T: Folder>(qpath: P<QPath>, fld: &mut T) -> P<QPath> {
454454
QPath {
455455
self_type: fld.fold_ty(qpath.self_type),
456456
trait_ref: qpath.trait_ref.map(|tr| fld.fold_trait_ref(tr)),
457-
item_name: fld.fold_ident(qpath.item_name),
457+
item_path: PathSegment {
458+
identifier: fld.fold_ident(qpath.item_path.identifier),
459+
parameters: fld.fold_path_parameters(qpath.item_path.parameters),
460+
}
458461
}
459462
})
460463
}
@@ -1381,6 +1384,7 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
13811384
e2.map(|x| folder.fold_expr(x)))
13821385
}
13831386
ExprPath(pth) => ExprPath(folder.fold_path(pth)),
1387+
ExprQPath(qpath) => ExprQPath(folder.fold_qpath(qpath)),
13841388
ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))),
13851389
ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))),
13861390
ExprRet(e) => ExprRet(e.map(|x| folder.fold_expr(x))),

src/libsyntax/print/pprust.rs

+18-8
Original file line numberDiff line numberDiff line change
@@ -727,14 +727,7 @@ impl<'a> State<'a> {
727727
try!(self.print_bounds("", &bounds[]));
728728
}
729729
ast::TyQPath(ref qpath) => {
730-
try!(word(&mut self.s, "<"));
731-
try!(self.print_type(&*qpath.self_type));
732-
try!(space(&mut self.s));
733-
try!(self.word_space("as"));
734-
try!(self.print_trait_ref(&*qpath.trait_ref));
735-
try!(word(&mut self.s, ">"));
736-
try!(word(&mut self.s, "::"));
737-
try!(self.print_ident(qpath.item_name));
730+
try!(self.print_qpath(&**qpath, false))
738731
}
739732
ast::TyFixedLengthVec(ref ty, ref v) => {
740733
try!(word(&mut self.s, "["));
@@ -1749,6 +1742,7 @@ impl<'a> State<'a> {
17491742
}
17501743
}
17511744
ast::ExprPath(ref path) => try!(self.print_path(path, true)),
1745+
ast::ExprQPath(ref qpath) => try!(self.print_qpath(&**qpath, true)),
17521746
ast::ExprBreak(opt_ident) => {
17531747
try!(word(&mut self.s, "break"));
17541748
try!(space(&mut self.s));
@@ -1933,6 +1927,22 @@ impl<'a> State<'a> {
19331927
Ok(())
19341928
}
19351929

1930+
fn print_qpath(&mut self,
1931+
qpath: &ast::QPath,
1932+
colons_before_params: bool)
1933+
-> IoResult<()>
1934+
{
1935+
try!(word(&mut self.s, "<"));
1936+
try!(self.print_type(&*qpath.self_type));
1937+
try!(space(&mut self.s));
1938+
try!(self.word_space("as"));
1939+
try!(self.print_trait_ref(&*qpath.trait_ref));
1940+
try!(word(&mut self.s, ">"));
1941+
try!(word(&mut self.s, "::"));
1942+
try!(self.print_ident(qpath.item_path.identifier));
1943+
self.print_path_parameters(&qpath.item_path.parameters, colons_before_params)
1944+
}
1945+
19361946
fn print_path_parameters(&mut self,
19371947
parameters: &ast::PathParameters,
19381948
colons_before_params: bool)

0 commit comments

Comments
 (0)