syntax: add fully qualified UFCS expressions.

This commit is contained in:
Eduard Burtescu 2015-01-13 06:02:56 +02:00
parent 1c78ad937b
commit 2cdc86c180
25 changed files with 89 additions and 42 deletions

View File

@ -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

View File

@ -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())
}
}

View File

@ -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(..) |

View File

@ -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, \

View File

@ -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

View File

@ -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,
@ -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 })
@ -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())

View File

@ -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");
}

View File

@ -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) {

View File

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

View File

@ -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)
}

View File

@ -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| {

View File

@ -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 => {

View File

@ -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);

View File

@ -252,6 +252,7 @@ mod svh_visitor {
SawExprIndex,
SawExprRange,
SawExprPath,
SawExprQPath,
SawExprAddrOf(ast::Mutability),
SawExprRet,
SawExprInlineAsm(&'a ast::InlineAsm),
@ -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)),

View File

@ -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
},

View File

@ -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:

View File

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

View File

@ -3526,7 +3526,8 @@ fn create_scope_map(cx: &CrateContext,
ast::ExprLit(_) |
ast::ExprBreak(_) |
ast::ExprAgain(_) |
ast::ExprPath(_) => {}
ast::ExprPath(_) |
ast::ExprQPath(_) => {}
ast::ExprCast(ref sub_exp, _) |
ast::ExprAddrOf(_, ref sub_exp) |

View File

@ -564,7 +564,7 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
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) => {
@ -997,7 +997,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
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) => {

View File

@ -1001,9 +1001,12 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
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

View File

@ -1614,7 +1614,7 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
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)
}

View File

@ -747,6 +747,8 @@ pub enum Expr_ {
/// 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>),
@ -771,12 +773,12 @@ pub enum Expr_ {
///
/// <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)]

View File

@ -454,7 +454,10 @@ pub fn noop_fold_qpath<T: Folder>(qpath: P<QPath>, fld: &mut T) -> P<QPath> {
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),
}
}
})
}
@ -1381,6 +1384,7 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
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))),

View File

@ -727,14 +727,7 @@ impl<'a> State<'a> {
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, "["));
@ -1749,6 +1742,7 @@ impl<'a> State<'a> {
}
}
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));
@ -1933,6 +1927,22 @@ impl<'a> State<'a> {
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)

View File

@ -126,6 +126,9 @@ pub trait Visitor<'v> : Sized {
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)
}
@ -419,9 +422,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
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);
@ -450,6 +451,14 @@ pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
}
}
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) {
@ -881,6 +890,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
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)