Skip to content

[r+] Implement fully qualified UFCS expressions. #21077

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 15, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/librustc/lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1731,7 +1731,7 @@ impl LintPass for Stability {
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
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/middle/cfg/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
ast::ExprMac(..) |
ast::ExprClosure(..) |
ast::ExprLit(..) |
ast::ExprPath(..) => {
ast::ExprPath(..) |
ast::ExprQPath(..) => {
self.straightline(expr, pred, None::<ast::Expr>.iter())
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/check_const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) {
expression");
}
}
ast::ExprPath(_) => {
ast::ExprPath(_) | ast::ExprQPath(_) => {
match v.tcx.def_map.borrow()[e.id] {
DefStatic(..) | DefConst(..) |
DefFn(..) | DefStaticMethod(..) | DefMethod(..) |
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/check_static.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckStaticVisitor<'a, 'tcx> {
"{} 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, \
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/check_static_recursion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ impl<'a, 'ast, 'v> Visitor<'v> for CheckItemRecursionVisitor<'a, 'ast> {

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
Expand Down
11 changes: 9 additions & 2 deletions src/librustc/middle/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ impl<'a, 'tcx> ConstEvalVisitor<'a, 'tcx> {

// 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,

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

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 })
Expand Down Expand Up @@ -542,7 +549,7 @@ pub fn eval_const_expr_partial(tcx: &ty::ctxt, e: &Expr) -> Result<const_val, St
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())
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/effect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
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");
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
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) {
Expand Down
14 changes: 8 additions & 6 deletions src/librustc/middle/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ fn visit_arm(ir: &mut IrMaps, arm: &ast::Arm) {
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 {
Expand Down Expand Up @@ -960,7 +960,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
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)
}

Expand Down Expand Up @@ -1289,7 +1289,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
// 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)
Expand All @@ -1300,7 +1300,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
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
Expand Down Expand Up @@ -1492,7 +1494,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
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(..) => {
Expand Down Expand Up @@ -1583,7 +1585,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {

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
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
}
}

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)
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/privacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -920,7 +920,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
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| {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/reachable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> {
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 => {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4515,7 +4515,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
}

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);
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_back/svh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ mod svh_visitor {
SawExprIndex,
SawExprRange,
SawExprPath,
SawExprQPath,
SawExprAddrOf(ast::Mutability),
SawExprRet,
SawExprInlineAsm(&'a ast::InlineAsm),
Expand Down Expand Up @@ -285,6 +286,7 @@ mod svh_visitor {
ExprIndex(..) => SawExprIndex,
ExprRange(..) => SawExprRange,
ExprPath(..) => SawExprPath,
ExprQPath(..) => SawExprQPath,
ExprAddrOf(m, _) => SawExprAddrOf(m),
ExprBreak(id) => SawExprBreak(id.map(content)),
ExprAgain(id) => SawExprAgain(id.map(content)),
Expand Down
53 changes: 28 additions & 25 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ use rustc::util::lev_distance::lev_distance;
use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum};
use syntax::ast::{DefId, Expr, ExprAgain, ExprBreak, ExprField};
use syntax::ast::{ExprClosure, ExprForLoop, ExprLoop, ExprWhile, ExprMethodCall};
use syntax::ast::{ExprPath, ExprStruct, FnDecl};
use syntax::ast::{ExprPath, ExprQPath, ExprStruct, FnDecl};
use syntax::ast::{ForeignItemFn, ForeignItemStatic, Generics};
use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemFn};
use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic};
Expand Down Expand Up @@ -3169,7 +3169,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
TraitImplementation => "implement",
TraitDerivation => "derive",
TraitObject => "reference",
TraitQPath => "extract an associated type from",
TraitQPath => "extract an associated item from",
};

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

match result_def {
None => {
match self.resolve_path(ty.id, path, TypeNS, true) {
Some(def) => {
debug!("(resolving type) resolved `{:?}` to \
type {:?}",
token::get_ident(path.segments.last().unwrap() .identifier),
def);
result_def = Some(def);
}
None => {
result_def = None;
}
}
}
Some(_) => {} // Continue.
if let None = result_def {
result_def = self.resolve_path(ty.id, path, TypeNS, true);
}

match result_def {
Some(def) => {
// Write the result into the def map.
debug!("(resolving type) writing resolution for `{}` \
(id {})",
(id {}) = {:?}",
self.path_names_to_string(path),
path_id);
path_id, def);
self.record_def(path_id, def);
}
None => {
Expand All @@ -3609,6 +3595,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
TyQPath(ref qpath) => {
self.resolve_type(&*qpath.self_type);
self.resolve_trait_reference(ty.id, &*qpath.trait_ref, TraitQPath);
for ty in qpath.item_path.parameters.types().into_iter() {
self.resolve_type(&**ty);
}
for binding in qpath.item_path.parameters.bindings().into_iter() {
self.resolve_type(&*binding.ty);
}
}

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

ExprPath(ref path) => {
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);
self.resolve_trait_reference(expr.id, &*qpath.trait_ref, TraitQPath);
path_from_qpath = qpath.trait_ref.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.

let path_name = self.path_names_to_string(path);

match self.resolve_path(expr.id, path, ValueNS, true) {
// Check if struct variant
Some((DefVariant(_, _, true), _)) => {
let path_name = self.path_names_to_string(path);
self.resolve_error(expr.span,
format!("`{}` is a struct variant name, but \
this expression \
Expand All @@ -4423,7 +4425,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
Some(def) => {
// Write the result into the def map.
debug!("(resolving expr) resolved `{}`",
path_name);
self.path_names_to_string(path));

self.record_def(expr.id, def);
}
Expand All @@ -4432,6 +4434,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// (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);
match self.with_no_errors(|this|
this.resolve_path(expr.id, path, TypeNS, false)) {
Some((DefTy(struct_id, _), _))
Expand Down
16 changes: 11 additions & 5 deletions src/librustc_trans/save/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -767,7 +767,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
span: Span,
path: &ast::Path,
ref_kind: Option<recorder::Row>) {
if generated_code(path.span) {
if generated_code(span) {
return
}

Expand Down Expand Up @@ -1307,9 +1307,15 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
visit::walk_expr(self, ex);
},
ast::ExprPath(ref path) => {
self.process_path(ex.id, ex.span, path, None);
self.process_path(ex.id, path.span, path, None);
visit::walk_path(self, path);
}
ast::ExprQPath(ref qpath) => {
let mut path = qpath.trait_ref.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);
}
ast::ExprStruct(ref path, ref fields, ref base) =>
self.process_struct_lit(ex, path, fields, base),
ast::ExprMethodCall(_, _, ref args) => self.process_method_call(ex, args),
Expand Down Expand Up @@ -1439,7 +1445,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
"")
}
def::DefVariant(..) => {
paths_to_process.push((id, p.span, p.clone(), Some(ref_kind)))
paths_to_process.push((id, p.clone(), Some(ref_kind)))
}
// FIXME(nrc) what are these doing here?
def::DefStatic(_, _) => {}
Expand All @@ -1448,8 +1454,8 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
*def)
}
}
for &(id, span, ref path, ref_kind) in paths_to_process.iter() {
self.process_path(id, span, path, ref_kind);
for &(id, ref path, ref_kind) in paths_to_process.iter() {
self.process_path(id, path.span, path, ref_kind);
}
self.collecting = false;
self.collected_paths.clear();
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/trans/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1235,7 +1235,7 @@ pub fn trans_match<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
/// 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
},
Expand Down
7 changes: 5 additions & 2 deletions src/librustc_trans/trans/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,11 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
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:
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/trans/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef {
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(..) => {
Expand Down
Loading