Skip to content

Commit f79e4c7

Browse files
committed
Merge pull request #21077 from eddyb/expr-qpath
[r+] Implement fully qualified UFCS expressions. Reviewed-by: nikomatsakis
2 parents 0c96037 + b90028d commit f79e4c7

32 files changed

+255
-86
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_resolve/lib.rs

+28-25
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ use rustc::util::lev_distance::lev_distance;
6161
use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum};
6262
use syntax::ast::{DefId, Expr, ExprAgain, ExprBreak, ExprField};
6363
use syntax::ast::{ExprClosure, ExprForLoop, ExprLoop, ExprWhile, ExprMethodCall};
64-
use syntax::ast::{ExprPath, ExprStruct, FnDecl};
64+
use syntax::ast::{ExprPath, ExprQPath, ExprStruct, FnDecl};
6565
use syntax::ast::{ForeignItemFn, ForeignItemStatic, Generics};
6666
use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemFn};
6767
use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic};
@@ -3169,7 +3169,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
31693169
TraitImplementation => "implement",
31703170
TraitDerivation => "derive",
31713171
TraitObject => "reference",
3172-
TraitQPath => "extract an associated type from",
3172+
TraitQPath => "extract an associated item from",
31733173
};
31743174

31753175
let msg = format!("attempt to {} a nonexistent trait `{}`", usage_str, path_str);
@@ -3565,31 +3565,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
35653565
}
35663566
}
35673567

3568-
match result_def {
3569-
None => {
3570-
match self.resolve_path(ty.id, path, TypeNS, true) {
3571-
Some(def) => {
3572-
debug!("(resolving type) resolved `{:?}` to \
3573-
type {:?}",
3574-
token::get_ident(path.segments.last().unwrap() .identifier),
3575-
def);
3576-
result_def = Some(def);
3577-
}
3578-
None => {
3579-
result_def = None;
3580-
}
3581-
}
3582-
}
3583-
Some(_) => {} // Continue.
3568+
if let None = result_def {
3569+
result_def = self.resolve_path(ty.id, path, TypeNS, true);
35843570
}
35853571

35863572
match result_def {
35873573
Some(def) => {
35883574
// Write the result into the def map.
35893575
debug!("(resolving type) writing resolution for `{}` \
3590-
(id {})",
3576+
(id {}) = {:?}",
35913577
self.path_names_to_string(path),
3592-
path_id);
3578+
path_id, def);
35933579
self.record_def(path_id, def);
35943580
}
35953581
None => {
@@ -3609,6 +3595,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
36093595
TyQPath(ref qpath) => {
36103596
self.resolve_type(&*qpath.self_type);
36113597
self.resolve_trait_reference(ty.id, &*qpath.trait_ref, TraitQPath);
3598+
for ty in qpath.item_path.parameters.types().into_iter() {
3599+
self.resolve_type(&**ty);
3600+
}
3601+
for binding in qpath.item_path.parameters.bindings().into_iter() {
3602+
self.resolve_type(&*binding.ty);
3603+
}
36123604
}
36133605

36143606
TyPolyTraitRef(ref bounds) => {
@@ -4400,15 +4392,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
44004392
// The interpretation of paths depends on whether the path has
44014393
// multiple elements in it or not.
44024394

4403-
ExprPath(ref path) => {
4395+
ExprPath(_) | ExprQPath(_) => {
4396+
let mut path_from_qpath;
4397+
let path = match expr.node {
4398+
ExprPath(ref path) => path,
4399+
ExprQPath(ref qpath) => {
4400+
self.resolve_type(&*qpath.self_type);
4401+
self.resolve_trait_reference(expr.id, &*qpath.trait_ref, TraitQPath);
4402+
path_from_qpath = qpath.trait_ref.path.clone();
4403+
path_from_qpath.segments.push(qpath.item_path.clone());
4404+
&path_from_qpath
4405+
}
4406+
_ => unreachable!()
4407+
};
44044408
// This is a local path in the value namespace. Walk through
44054409
// scopes looking for it.
4406-
4407-
let path_name = self.path_names_to_string(path);
4408-
44094410
match self.resolve_path(expr.id, path, ValueNS, true) {
44104411
// Check if struct variant
44114412
Some((DefVariant(_, _, true), _)) => {
4413+
let path_name = self.path_names_to_string(path);
44124414
self.resolve_error(expr.span,
44134415
format!("`{}` is a struct variant name, but \
44144416
this expression \
@@ -4423,7 +4425,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
44234425
Some(def) => {
44244426
// Write the result into the def map.
44254427
debug!("(resolving expr) resolved `{}`",
4426-
path_name);
4428+
self.path_names_to_string(path));
44274429

44284430
self.record_def(expr.id, def);
44294431
}
@@ -4432,6 +4434,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
44324434
// (The pattern matching def_tys where the id is in self.structs
44334435
// matches on regular structs while excluding tuple- and enum-like
44344436
// structs, which wouldn't result in this error.)
4437+
let path_name = self.path_names_to_string(path);
44354438
match self.with_no_errors(|this|
44364439
this.resolve_path(expr.id, path, TypeNS, false)) {
44374440
Some((DefTy(struct_id, _), _))

src/librustc_trans/save/mod.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
767767
span: Span,
768768
path: &ast::Path,
769769
ref_kind: Option<recorder::Row>) {
770-
if generated_code(path.span) {
770+
if generated_code(span) {
771771
return
772772
}
773773

@@ -1307,9 +1307,15 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
13071307
visit::walk_expr(self, ex);
13081308
},
13091309
ast::ExprPath(ref path) => {
1310-
self.process_path(ex.id, ex.span, path, None);
1310+
self.process_path(ex.id, path.span, path, None);
13111311
visit::walk_path(self, path);
13121312
}
1313+
ast::ExprQPath(ref qpath) => {
1314+
let mut path = qpath.trait_ref.path.clone();
1315+
path.segments.push(qpath.item_path.clone());
1316+
self.process_path(ex.id, ex.span, &path, None);
1317+
visit::walk_qpath(self, ex.span, &**qpath);
1318+
}
13131319
ast::ExprStruct(ref path, ref fields, ref base) =>
13141320
self.process_struct_lit(ex, path, fields, base),
13151321
ast::ExprMethodCall(_, _, ref args) => self.process_method_call(ex, args),
@@ -1439,7 +1445,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
14391445
"")
14401446
}
14411447
def::DefVariant(..) => {
1442-
paths_to_process.push((id, p.span, p.clone(), Some(ref_kind)))
1448+
paths_to_process.push((id, p.clone(), Some(ref_kind)))
14431449
}
14441450
// FIXME(nrc) what are these doing here?
14451451
def::DefStatic(_, _) => {}
@@ -1448,8 +1454,8 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
14481454
*def)
14491455
}
14501456
}
1451-
for &(id, span, ref path, ref_kind) in paths_to_process.iter() {
1452-
self.process_path(id, span, path, ref_kind);
1457+
for &(id, ref path, ref_kind) in paths_to_process.iter() {
1458+
self.process_path(id, path.span, path, ref_kind);
14531459
}
14541460
self.collecting = false;
14551461
self.collected_paths.clear();

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(..) => {

0 commit comments

Comments
 (0)