Skip to content

Commit 287de25

Browse files
committed
Store all generic arguments for method calls in AST
1 parent 8b1271f commit 287de25

File tree

11 files changed

+82
-69
lines changed

11 files changed

+82
-69
lines changed

src/librustc/hir/lowering.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -1844,10 +1844,17 @@ impl<'a> LoweringContext<'a> {
18441844
let f = P(self.lower_expr(f));
18451845
hir::ExprCall(f, args.iter().map(|x| self.lower_expr(x)).collect())
18461846
}
1847-
ExprKind::MethodCall(i, ref tps, ref args) => {
1847+
ExprKind::MethodCall(ref seg, ref args) => {
1848+
let tps = match seg.parameters {
1849+
Some(ref params) => match **params {
1850+
PathParameters::AngleBracketed(ref param_data) => &param_data.types[..],
1851+
_ => &[],
1852+
},
1853+
_ => &[],
1854+
};
18481855
let tps = tps.iter().map(|x| self.lower_ty(x)).collect();
18491856
let args = args.iter().map(|x| self.lower_expr(x)).collect();
1850-
hir::ExprMethodCall(respan(i.span, self.lower_ident(i.node)), tps, args)
1857+
hir::ExprMethodCall(respan(seg.span, self.lower_ident(seg.identifier)), tps, args)
18511858
}
18521859
ExprKind::Binary(binop, ref lhs, ref rhs) => {
18531860
let binop = self.lower_binop(binop);

src/librustc_passes/ast_validation.rs

+17
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
125125
ExprKind::Continue(Some(ident)) => {
126126
self.check_label(ident.node, ident.span);
127127
}
128+
ExprKind::MethodCall(ref segment, ..) => {
129+
if let Some(ref params) = segment.parameters {
130+
match **params {
131+
PathParameters::AngleBracketed(ref param_data) => {
132+
if !param_data.bindings.is_empty() {
133+
let binding_span = param_data.bindings[0].span;
134+
self.err_handler().span_err(binding_span,
135+
"type bindings cannot be used in method calls");
136+
}
137+
}
138+
PathParameters::Parenthesized(..) => {
139+
self.err_handler().span_err(expr.span,
140+
"parenthesized parameters cannot be used on method calls");
141+
}
142+
}
143+
}
144+
}
128145
_ => {}
129146
}
130147

src/librustc_resolve/lib.rs

+6-8
Original file line numberDiff line numberDiff line change
@@ -2467,9 +2467,9 @@ impl<'a> Resolver<'a> {
24672467
path_str, ident.node));
24682468
return err;
24692469
}
2470-
ExprKind::MethodCall(ident, ..) => {
2470+
ExprKind::MethodCall(ref segment, ..) => {
24712471
err.span_label(parent.span, format!("did you mean `{}::{}(...)`?",
2472-
path_str, ident.node));
2472+
path_str, segment.identifier));
24732473
return err;
24742474
}
24752475
_ => {}
@@ -3145,15 +3145,13 @@ impl<'a> Resolver<'a> {
31453145
ExprKind::Field(ref subexpression, _) => {
31463146
self.resolve_expr(subexpression, Some(expr));
31473147
}
3148-
ExprKind::MethodCall(_, ref types, ref arguments) => {
3148+
ExprKind::MethodCall(ref segment, ref arguments) => {
31493149
let mut arguments = arguments.iter();
31503150
self.resolve_expr(arguments.next().unwrap(), Some(expr));
31513151
for argument in arguments {
31523152
self.resolve_expr(argument, None);
31533153
}
3154-
for ty in types.iter() {
3155-
self.visit_ty(ty);
3156-
}
3154+
self.visit_path_segment(expr.span, segment);
31573155
}
31583156

31593157
ExprKind::Repeat(ref element, ref count) => {
@@ -3185,10 +3183,10 @@ impl<'a> Resolver<'a> {
31853183
let traits = self.get_traits_containing_item(name.node, ValueNS);
31863184
self.trait_map.insert(expr.id, traits);
31873185
}
3188-
ExprKind::MethodCall(name, ..) => {
3186+
ExprKind::MethodCall(ref segment, ..) => {
31893187
debug!("(recording candidate traits for expr) recording traits for {}",
31903188
expr.id);
3191-
let traits = self.get_traits_containing_item(name.node, ValueNS);
3189+
let traits = self.get_traits_containing_item(segment.identifier, ValueNS);
31923190
self.trait_map.insert(expr.id, traits);
31933191
}
31943192
_ => {

src/libsyntax/ast.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -848,19 +848,16 @@ pub enum ExprKind {
848848
/// The first field resolves to the function itself,
849849
/// and the second field is the list of arguments
850850
Call(P<Expr>, Vec<P<Expr>>),
851-
/// A method call (`x.foo::<Bar, Baz>(a, b, c, d)`)
851+
/// A method call (`x.foo::<'static, Bar, Baz>(a, b, c, d)`)
852852
///
853-
/// The `SpannedIdent` is the identifier for the method name.
854-
/// The vector of `Ty`s are the ascripted type parameters for the method
853+
/// The `PathSegment` represents the method name and its generic arguments
855854
/// (within the angle brackets).
856-
///
857855
/// The first element of the vector of `Expr`s is the expression that evaluates
858856
/// to the object on which the method is being called on (the receiver),
859857
/// and the remaining elements are the rest of the arguments.
860-
///
861858
/// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
862-
/// `ExprKind::MethodCall(foo, [Bar, Baz], [x, a, b, c, d])`.
863-
MethodCall(SpannedIdent, Vec<P<Ty>>, Vec<P<Expr>>),
859+
/// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`.
860+
MethodCall(PathSegment, Vec<P<Expr>>),
864861
/// A tuple (`(a, b, c ,d)`)
865862
Tup(Vec<P<Expr>>),
866863
/// A binary operation (For example: `a + b`, `a * b`)

src/libsyntax/ext/build.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -673,9 +673,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
673673
expr: P<ast::Expr>,
674674
ident: ast::Ident,
675675
mut args: Vec<P<ast::Expr>> ) -> P<ast::Expr> {
676-
let id = Spanned { node: ident, span: span };
677676
args.insert(0, expr);
678-
self.expr(span, ast::ExprKind::MethodCall(id, Vec::new(), args))
677+
self.expr(span, ast::ExprKind::MethodCall(ast::PathSegment::from_ident(ident, span), args))
679678
}
680679
fn expr_block(&self, b: P<ast::Block>) -> P<ast::Expr> {
681680
self.expr(b.span, ast::ExprKind::Block(b))

src/libsyntax/fold.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -1151,10 +1151,15 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
11511151
ExprKind::Call(folder.fold_expr(f),
11521152
folder.fold_exprs(args))
11531153
}
1154-
ExprKind::MethodCall(i, tps, args) => {
1154+
ExprKind::MethodCall(seg, args) => {
11551155
ExprKind::MethodCall(
1156-
respan(folder.new_span(i.span), folder.fold_ident(i.node)),
1157-
tps.move_map(|x| folder.fold_ty(x)),
1156+
PathSegment {
1157+
identifier: folder.fold_ident(seg.identifier),
1158+
span: folder.new_span(seg.span),
1159+
parameters: seg.parameters.map(|ps| {
1160+
ps.map(|ps| folder.fold_path_parameters(ps))
1161+
}),
1162+
},
11581163
folder.fold_exprs(args))
11591164
}
11601165
ExprKind::Binary(binop, lhs, rhs) => {

src/libsyntax/parse/parser.rs

+15-33
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use abi::{self, Abi};
12-
use ast::{AttrStyle, BareFnTy};
12+
use ast::{AngleBracketedParameterData, AttrStyle, BareFnTy};
1313
use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
1414
use ast::Unsafety;
1515
use ast::{Mod, Arg, Arm, Attribute, BindingMode, TraitItemKind};
@@ -1831,11 +1831,7 @@ impl<'a> Parser<'a> {
18311831
let parameters = if parse_generics && self.eat_lt() {
18321832
let (lifetimes, types, bindings) = self.parse_generic_args()?;
18331833
self.expect_gt()?;
1834-
ast::AngleBracketedParameterData {
1835-
lifetimes: lifetimes,
1836-
types: types,
1837-
bindings: bindings,
1838-
}.into()
1834+
AngleBracketedParameterData { lifetimes, types, bindings }.into()
18391835
} else if self.eat(&token::OpenDelim(token::Paren)) {
18401836
let lo = self.prev_span;
18411837

@@ -1898,11 +1894,7 @@ impl<'a> Parser<'a> {
18981894
segments.push(PathSegment {
18991895
identifier: identifier,
19001896
span: ident_span,
1901-
parameters: ast::AngleBracketedParameterData {
1902-
lifetimes: lifetimes,
1903-
types: types,
1904-
bindings: bindings,
1905-
}.into(),
1897+
parameters: AngleBracketedParameterData { lifetimes, types, bindings }.into(),
19061898
});
19071899

19081900
// Consumed `a::b::<T,U>`, check for `::` before proceeding
@@ -2023,14 +2015,6 @@ impl<'a> Parser<'a> {
20232015
ExprKind::Call(f, args)
20242016
}
20252017

2026-
fn mk_method_call(&mut self,
2027-
ident: ast::SpannedIdent,
2028-
tps: Vec<P<Ty>>,
2029-
args: Vec<P<Expr>>)
2030-
-> ast::ExprKind {
2031-
ExprKind::MethodCall(ident, tps, args)
2032-
}
2033-
20342018
pub fn mk_index(&mut self, expr: P<Expr>, idx: P<Expr>) -> ast::ExprKind {
20352019
ExprKind::Index(expr, idx)
20362020
}
@@ -2460,7 +2444,7 @@ impl<'a> Parser<'a> {
24602444
// parsing into an expression.
24612445
fn parse_dot_suffix(&mut self, ident: Ident, ident_span: Span, self_value: P<Expr>, lo: Span)
24622446
-> PResult<'a, P<Expr>> {
2463-
let (_, tys, bindings) = if self.eat(&token::ModSep) {
2447+
let (lifetimes, types, bindings) = if self.eat(&token::ModSep) {
24642448
self.expect_lt()?;
24652449
let args = self.parse_generic_args()?;
24662450
self.expect_gt()?;
@@ -2469,11 +2453,6 @@ impl<'a> Parser<'a> {
24692453
(Vec::new(), Vec::new(), Vec::new())
24702454
};
24712455

2472-
if !bindings.is_empty() {
2473-
let prev_span = self.prev_span;
2474-
self.span_err(prev_span, "type bindings are only permitted on trait paths");
2475-
}
2476-
24772456
Ok(match self.token {
24782457
// expr.f() method call.
24792458
token::OpenDelim(token::Paren) => {
@@ -2486,17 +2465,20 @@ impl<'a> Parser<'a> {
24862465
let hi = self.prev_span;
24872466

24882467
es.insert(0, self_value);
2489-
let id = respan(ident_span.to(ident_span), ident);
2490-
let nd = self.mk_method_call(id, tys, es);
2491-
self.mk_expr(lo.to(hi), nd, ThinVec::new())
2468+
let seg = PathSegment {
2469+
identifier: ident,
2470+
span: ident_span.to(ident_span),
2471+
parameters: AngleBracketedParameterData { lifetimes, types, bindings }.into(),
2472+
};
2473+
self.mk_expr(lo.to(hi), ExprKind::MethodCall(seg, es), ThinVec::new())
24922474
}
24932475
// Field access.
24942476
_ => {
2495-
if !tys.is_empty() {
2496-
let prev_span = self.prev_span;
2497-
self.span_err(prev_span,
2498-
"field expressions may not \
2499-
have type parameters");
2477+
if let Some(generic_arg_span) = lifetimes.get(0).map(|x| x.span).or_else(||
2478+
types.get(0).map(|x| x.span)).or_else(||
2479+
bindings.get(0).map(|x| x.span)) {
2480+
self.span_err(generic_arg_span,
2481+
"field expressions may not have generic arguments");
25002482
}
25012483

25022484
let id = respan(ident_span.to(ident_span), ident);

src/libsyntax/print/pprust.rs

+6-10
Original file line numberDiff line numberDiff line change
@@ -1951,18 +1951,14 @@ impl<'a> State<'a> {
19511951
}
19521952

19531953
fn print_expr_method_call(&mut self,
1954-
ident: ast::SpannedIdent,
1955-
tys: &[P<ast::Ty>],
1954+
segment: &ast::PathSegment,
19561955
args: &[P<ast::Expr>]) -> io::Result<()> {
19571956
let base_args = &args[1..];
19581957
self.print_expr(&args[0])?;
19591958
word(&mut self.s, ".")?;
1960-
self.print_ident(ident.node)?;
1961-
if !tys.is_empty() {
1962-
word(&mut self.s, "::<")?;
1963-
self.commasep(Inconsistent, tys,
1964-
|s, ty| s.print_type(ty))?;
1965-
word(&mut self.s, ">")?;
1959+
self.print_ident(segment.identifier)?;
1960+
if let Some(ref parameters) = segment.parameters {
1961+
self.print_path_parameters(parameters, true)?;
19661962
}
19671963
self.print_call_post(base_args)
19681964
}
@@ -2041,8 +2037,8 @@ impl<'a> State<'a> {
20412037
ast::ExprKind::Call(ref func, ref args) => {
20422038
self.print_expr_call(func, &args[..])?;
20432039
}
2044-
ast::ExprKind::MethodCall(ident, ref tys, ref args) => {
2045-
self.print_expr_method_call(ident, &tys[..], &args[..])?;
2040+
ast::ExprKind::MethodCall(ref segment, ref args) => {
2041+
self.print_expr_method_call(segment, &args[..])?;
20462042
}
20472043
ast::ExprKind::Binary(op, ref lhs, ref rhs) => {
20482044
self.print_expr_binary(op, lhs, rhs)?;

src/libsyntax/visit.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -674,9 +674,8 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
674674
visitor.visit_expr(callee_expression);
675675
walk_list!(visitor, visit_expr, arguments);
676676
}
677-
ExprKind::MethodCall(ref ident, ref types, ref arguments) => {
678-
visitor.visit_ident(ident.span, ident.node);
679-
walk_list!(visitor, visit_ty, types);
677+
ExprKind::MethodCall(ref segment, ref arguments) => {
678+
visitor.visit_path_segment(expression.span, segment);
680679
walk_list!(visitor, visit_expr, arguments);
681680
}
682681
ExprKind::Binary(_, ref left_expression, ref right_expression) => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {
12+
0.clone::<T = u8>(); //~ ERROR type bindings cannot be used in method calls
13+
}

src/test/parse-fail/type-parameters-in-field-exprs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,5 @@ fn main() {
2121
y: 2,
2222
};
2323
f.x::<isize>;
24-
//~^ ERROR field expressions may not have type parameters
24+
//~^ ERROR field expressions may not have generic arguments
2525
}

0 commit comments

Comments
 (0)