Auto merge of #43115 - petrochenkov:methlife2, r=eddyb
Store all generic arguments for method calls in AST/HIR The first part of https://github.com/rust-lang/rust/pull/42492. Landed separately to start the process of merging libsyntax changes breaking rustfmt, which is not easy these days.
This commit is contained in:
commit
d84693b93d
21 changed files with 137 additions and 136 deletions
14
src/Cargo.lock
generated
14
src/Cargo.lock
generated
|
|
@ -578,7 +578,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "languageserver-types"
|
name = "languageserver-types"
|
||||||
version = "0.11.0"
|
version = "0.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
@ -1017,14 +1017,14 @@ dependencies = [
|
||||||
"cargo 0.21.0 (git+https://github.com/rust-lang/cargo)",
|
"cargo 0.21.0 (git+https://github.com/rust-lang/cargo)",
|
||||||
"derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"languageserver-types 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"languageserver-types 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rls-analysis 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rls-analysis 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rls-data 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rls-data 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rls-vfs 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rls-vfs 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustfmt-nightly 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustfmt-nightly 0.1.8 (git+https://github.com/rust-lang-nursery/rustfmt?branch=rustfmt-42492)",
|
||||||
"serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
@ -1474,8 +1474,8 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustfmt-nightly"
|
name = "rustfmt-nightly"
|
||||||
version = "0.1.7"
|
version = "0.1.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/rust-lang-nursery/rustfmt?branch=rustfmt-42492#7333dfc95b4af5c7283ba03f33c50f108d2be3f5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
@ -2067,7 +2067,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
|
"checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
|
||||||
"checksum jobserver 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4e28adc987f6d0521ef66ad60b055968107b164b3bb3cf3dc8474e0a380474a6"
|
"checksum jobserver 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4e28adc987f6d0521ef66ad60b055968107b164b3bb3cf3dc8474e0a380474a6"
|
||||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||||
"checksum languageserver-types 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c178b944c3187527293fb9f8a0b0db3c5fb62eb127cacd65296f651a2440f5b1"
|
"checksum languageserver-types 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "680aee78c75504fdcb172635a7b7da0dccaafa4c42d935e19576c14b27942362"
|
||||||
"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
|
"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
|
||||||
"checksum libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)" = "38f5c2b18a287cf78b4097db62e20f43cace381dc76ae5c0a3073067f78b7ddc"
|
"checksum libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)" = "38f5c2b18a287cf78b4097db62e20f43cace381dc76ae5c0a3073067f78b7ddc"
|
||||||
"checksum libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "df18a822100352d9863b302faf6f8f25c0e77f0e60feb40e5dbe1238b7f13b1d"
|
"checksum libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "df18a822100352d9863b302faf6f8f25c0e77f0e60feb40e5dbe1238b7f13b1d"
|
||||||
|
|
@ -2116,7 +2116,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum rls-vfs 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1f19246a0fda45f2fb6eb34addef2a692c044cbf1c90ec7695583450fb5f23e7"
|
"checksum rls-vfs 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1f19246a0fda45f2fb6eb34addef2a692c044cbf1c90ec7695583450fb5f23e7"
|
||||||
"checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95"
|
"checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95"
|
||||||
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
|
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
|
||||||
"checksum rustfmt-nightly 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "31ac6fe40a9844ee2de3d51d0be2bbcdb361bad6f3667a02db8c4e2330afbbb5"
|
"checksum rustfmt-nightly 0.1.8 (git+https://github.com/rust-lang-nursery/rustfmt?branch=rustfmt-42492)" = "<none>"
|
||||||
"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
|
"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
|
||||||
"checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
|
"checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
|
||||||
"checksum semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd61b85a0fa777f7fb7c454b9189b2941b110d1385ce84d7f76efdf1606a85"
|
"checksum semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd61b85a0fa777f7fb7c454b9189b2941b110d1385ce84d7f76efdf1606a85"
|
||||||
|
|
|
||||||
|
|
@ -944,10 +944,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
|
||||||
walk_list!(visitor, visit_expr, arguments);
|
walk_list!(visitor, visit_expr, arguments);
|
||||||
visitor.visit_expr(callee_expression)
|
visitor.visit_expr(callee_expression)
|
||||||
}
|
}
|
||||||
ExprMethodCall(ref name, ref types, ref arguments) => {
|
ExprMethodCall(ref segment, _, ref arguments) => {
|
||||||
visitor.visit_name(name.span, name.node);
|
visitor.visit_path_segment(expression.span, segment);
|
||||||
walk_list!(visitor, visit_expr, arguments);
|
walk_list!(visitor, visit_expr, arguments);
|
||||||
walk_list!(visitor, visit_ty, types);
|
|
||||||
}
|
}
|
||||||
ExprBinary(_, ref left_expression, ref right_expression) => {
|
ExprBinary(_, ref left_expression, ref right_expression) => {
|
||||||
visitor.visit_expr(left_expression);
|
visitor.visit_expr(left_expression);
|
||||||
|
|
|
||||||
|
|
@ -1844,10 +1844,10 @@ impl<'a> LoweringContext<'a> {
|
||||||
let f = P(self.lower_expr(f));
|
let f = P(self.lower_expr(f));
|
||||||
hir::ExprCall(f, args.iter().map(|x| self.lower_expr(x)).collect())
|
hir::ExprCall(f, args.iter().map(|x| self.lower_expr(x)).collect())
|
||||||
}
|
}
|
||||||
ExprKind::MethodCall(i, ref tps, ref args) => {
|
ExprKind::MethodCall(ref seg, ref args) => {
|
||||||
let tps = tps.iter().map(|x| self.lower_ty(x)).collect();
|
let hir_seg = self.lower_path_segment(e.span, seg, ParamMode::Optional, 0);
|
||||||
let args = args.iter().map(|x| self.lower_expr(x)).collect();
|
let args = args.iter().map(|x| self.lower_expr(x)).collect();
|
||||||
hir::ExprMethodCall(respan(i.span, self.lower_ident(i.node)), tps, args)
|
hir::ExprMethodCall(hir_seg, seg.span, args)
|
||||||
}
|
}
|
||||||
ExprKind::Binary(binop, ref lhs, ref rhs) => {
|
ExprKind::Binary(binop, ref lhs, ref rhs) => {
|
||||||
let binop = self.lower_binop(binop);
|
let binop = self.lower_binop(binop);
|
||||||
|
|
|
||||||
|
|
@ -972,19 +972,16 @@ pub enum Expr_ {
|
||||||
/// The first field resolves to the function itself (usually an `ExprPath`),
|
/// The first field resolves to the function itself (usually an `ExprPath`),
|
||||||
/// and the second field is the list of arguments
|
/// and the second field is the list of arguments
|
||||||
ExprCall(P<Expr>, HirVec<Expr>),
|
ExprCall(P<Expr>, HirVec<Expr>),
|
||||||
/// A method call (`x.foo::<Bar, Baz>(a, b, c, d)`)
|
/// A method call (`x.foo::<'static, Bar, Baz>(a, b, c, d)`)
|
||||||
///
|
///
|
||||||
/// The `Spanned<Name>` is the identifier for the method name.
|
/// The `PathSegment`/`Span` represent the method name and its generic arguments
|
||||||
/// The vector of `Ty`s are the ascripted type parameters for the method
|
|
||||||
/// (within the angle brackets).
|
/// (within the angle brackets).
|
||||||
///
|
/// The first element of the vector of `Expr`s is the expression that evaluates
|
||||||
/// The first element of the vector of `Expr`s is the expression that
|
/// to the object on which the method is being called on (the receiver),
|
||||||
/// evaluates to the object on which the method is being called on (the
|
/// and the remaining elements are the rest of the arguments.
|
||||||
/// receiver), and the remaining elements are the rest of the arguments.
|
|
||||||
///
|
|
||||||
/// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
|
/// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
|
||||||
/// `ExprMethodCall(foo, [Bar, Baz], [x, a, b, c, d])`.
|
/// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`.
|
||||||
ExprMethodCall(Spanned<Name>, HirVec<P<Ty>>, HirVec<Expr>),
|
ExprMethodCall(PathSegment, Span, HirVec<Expr>),
|
||||||
/// A tuple (`(a, b, c ,d)`)
|
/// A tuple (`(a, b, c ,d)`)
|
||||||
ExprTup(HirVec<Expr>),
|
ExprTup(HirVec<Expr>),
|
||||||
/// A binary operation (For example: `a + b`, `a * b`)
|
/// A binary operation (For example: `a + b`, `a * b`)
|
||||||
|
|
|
||||||
|
|
@ -1188,18 +1188,17 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_expr_method_call(&mut self,
|
fn print_expr_method_call(&mut self,
|
||||||
name: Spanned<ast::Name>,
|
segment: &hir::PathSegment,
|
||||||
tys: &[P<hir::Ty>],
|
|
||||||
args: &[hir::Expr])
|
args: &[hir::Expr])
|
||||||
-> io::Result<()> {
|
-> io::Result<()> {
|
||||||
let base_args = &args[1..];
|
let base_args = &args[1..];
|
||||||
self.print_expr(&args[0])?;
|
self.print_expr(&args[0])?;
|
||||||
word(&mut self.s, ".")?;
|
word(&mut self.s, ".")?;
|
||||||
self.print_name(name.node)?;
|
self.print_name(segment.name)?;
|
||||||
if !tys.is_empty() {
|
if !segment.parameters.lifetimes().is_empty() ||
|
||||||
word(&mut self.s, "::<")?;
|
!segment.parameters.types().is_empty() ||
|
||||||
self.commasep(Inconsistent, tys, |s, ty| s.print_type(&ty))?;
|
!segment.parameters.bindings().is_empty() {
|
||||||
word(&mut self.s, ">")?;
|
self.print_path_parameters(&segment.parameters, true)?;
|
||||||
}
|
}
|
||||||
self.print_call_post(base_args)
|
self.print_call_post(base_args)
|
||||||
}
|
}
|
||||||
|
|
@ -1254,8 +1253,8 @@ impl<'a> State<'a> {
|
||||||
hir::ExprCall(ref func, ref args) => {
|
hir::ExprCall(ref func, ref args) => {
|
||||||
self.print_expr_call(&func, args)?;
|
self.print_expr_call(&func, args)?;
|
||||||
}
|
}
|
||||||
hir::ExprMethodCall(name, ref tys, ref args) => {
|
hir::ExprMethodCall(ref segment, _, ref args) => {
|
||||||
self.print_expr_method_call(name, &tys[..], args)?;
|
self.print_expr_method_call(segment, args)?;
|
||||||
}
|
}
|
||||||
hir::ExprBinary(op, ref lhs, ref rhs) => {
|
hir::ExprBinary(op, ref lhs, ref rhs) => {
|
||||||
self.print_expr_binary(op, &lhs, &rhs)?;
|
self.print_expr_binary(op, &lhs, &rhs)?;
|
||||||
|
|
|
||||||
|
|
@ -626,7 +626,7 @@ impl_stable_hash_for!(enum hir::Expr_ {
|
||||||
ExprBox(sub),
|
ExprBox(sub),
|
||||||
ExprArray(subs),
|
ExprArray(subs),
|
||||||
ExprCall(callee, args),
|
ExprCall(callee, args),
|
||||||
ExprMethodCall(name, ts, args),
|
ExprMethodCall(segment, span, args),
|
||||||
ExprTup(fields),
|
ExprTup(fields),
|
||||||
ExprBinary(op, lhs, rhs),
|
ExprBinary(op, lhs, rhs),
|
||||||
ExprUnary(op, operand),
|
ExprUnary(op, operand),
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
ExprKind::Continue(Some(ident)) => {
|
ExprKind::Continue(Some(ident)) => {
|
||||||
self.check_label(ident.node, ident.span);
|
self.check_label(ident.node, ident.span);
|
||||||
}
|
}
|
||||||
|
ExprKind::MethodCall(ref segment, ..) => {
|
||||||
|
if let Some(ref params) = segment.parameters {
|
||||||
|
match **params {
|
||||||
|
PathParameters::AngleBracketed(ref param_data) => {
|
||||||
|
if !param_data.bindings.is_empty() {
|
||||||
|
let binding_span = param_data.bindings[0].span;
|
||||||
|
self.err_handler().span_err(binding_span,
|
||||||
|
"type bindings cannot be used in method calls");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PathParameters::Parenthesized(..) => {
|
||||||
|
self.err_handler().span_err(expr.span,
|
||||||
|
"parenthesized parameters cannot be used on method calls");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -670,10 +670,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ExprMethodCall(name, ..) => {
|
hir::ExprMethodCall(_, span, _) => {
|
||||||
// Method calls have to be checked specially.
|
// Method calls have to be checked specially.
|
||||||
let def_id = self.tables.type_dependent_defs[&expr.id].def_id();
|
let def_id = self.tables.type_dependent_defs[&expr.id].def_id();
|
||||||
self.span = name.span;
|
self.span = span;
|
||||||
if self.tcx.type_of(def_id).visit_with(self) {
|
if self.tcx.type_of(def_id).visit_with(self) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2467,9 +2467,9 @@ impl<'a> Resolver<'a> {
|
||||||
path_str, ident.node));
|
path_str, ident.node));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
ExprKind::MethodCall(ident, ..) => {
|
ExprKind::MethodCall(ref segment, ..) => {
|
||||||
err.span_label(parent.span, format!("did you mean `{}::{}(...)`?",
|
err.span_label(parent.span, format!("did you mean `{}::{}(...)`?",
|
||||||
path_str, ident.node));
|
path_str, segment.identifier));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
@ -3145,15 +3145,13 @@ impl<'a> Resolver<'a> {
|
||||||
ExprKind::Field(ref subexpression, _) => {
|
ExprKind::Field(ref subexpression, _) => {
|
||||||
self.resolve_expr(subexpression, Some(expr));
|
self.resolve_expr(subexpression, Some(expr));
|
||||||
}
|
}
|
||||||
ExprKind::MethodCall(_, ref types, ref arguments) => {
|
ExprKind::MethodCall(ref segment, ref arguments) => {
|
||||||
let mut arguments = arguments.iter();
|
let mut arguments = arguments.iter();
|
||||||
self.resolve_expr(arguments.next().unwrap(), Some(expr));
|
self.resolve_expr(arguments.next().unwrap(), Some(expr));
|
||||||
for argument in arguments {
|
for argument in arguments {
|
||||||
self.resolve_expr(argument, None);
|
self.resolve_expr(argument, None);
|
||||||
}
|
}
|
||||||
for ty in types.iter() {
|
self.visit_path_segment(expr.span, segment);
|
||||||
self.visit_ty(ty);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprKind::Repeat(ref element, ref count) => {
|
ExprKind::Repeat(ref element, ref count) => {
|
||||||
|
|
@ -3185,10 +3183,10 @@ impl<'a> Resolver<'a> {
|
||||||
let traits = self.get_traits_containing_item(name.node, ValueNS);
|
let traits = self.get_traits_containing_item(name.node, ValueNS);
|
||||||
self.trait_map.insert(expr.id, traits);
|
self.trait_map.insert(expr.id, traits);
|
||||||
}
|
}
|
||||||
ExprKind::MethodCall(name, ..) => {
|
ExprKind::MethodCall(ref segment, ..) => {
|
||||||
debug!("(recording candidate traits for expr) recording traits for {}",
|
debug!("(recording candidate traits for expr) recording traits for {}",
|
||||||
expr.id);
|
expr.id);
|
||||||
let traits = self.get_traits_containing_item(name.node, ValueNS);
|
let traits = self.get_traits_containing_item(segment.identifier, ValueNS);
|
||||||
self.trait_map.insert(expr.id, traits);
|
self.trait_map.insert(expr.id, traits);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
|
|
||||||
|
|
@ -44,15 +44,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
call_expr: &'gcx hir::Expr,
|
call_expr: &'gcx hir::Expr,
|
||||||
unadjusted_self_ty: Ty<'tcx>,
|
unadjusted_self_ty: Ty<'tcx>,
|
||||||
pick: probe::Pick<'tcx>,
|
pick: probe::Pick<'tcx>,
|
||||||
supplied_method_types: Vec<Ty<'tcx>>)
|
segment: &hir::PathSegment)
|
||||||
-> MethodCallee<'tcx> {
|
-> MethodCallee<'tcx> {
|
||||||
debug!("confirm(unadjusted_self_ty={:?}, pick={:?}, supplied_method_types={:?})",
|
debug!("confirm(unadjusted_self_ty={:?}, pick={:?}, generic_args={:?})",
|
||||||
unadjusted_self_ty,
|
unadjusted_self_ty,
|
||||||
pick,
|
pick,
|
||||||
supplied_method_types);
|
segment.parameters);
|
||||||
|
|
||||||
let mut confirm_cx = ConfirmContext::new(self, span, self_expr, call_expr);
|
let mut confirm_cx = ConfirmContext::new(self, span, self_expr, call_expr);
|
||||||
confirm_cx.confirm(unadjusted_self_ty, pick, supplied_method_types)
|
confirm_cx.confirm(unadjusted_self_ty, pick, segment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,7 +73,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
fn confirm(&mut self,
|
fn confirm(&mut self,
|
||||||
unadjusted_self_ty: Ty<'tcx>,
|
unadjusted_self_ty: Ty<'tcx>,
|
||||||
pick: probe::Pick<'tcx>,
|
pick: probe::Pick<'tcx>,
|
||||||
supplied_method_types: Vec<Ty<'tcx>>)
|
segment: &hir::PathSegment)
|
||||||
-> MethodCallee<'tcx> {
|
-> MethodCallee<'tcx> {
|
||||||
// Adjust the self expression the user provided and obtain the adjusted type.
|
// Adjust the self expression the user provided and obtain the adjusted type.
|
||||||
let self_ty = self.adjust_self_ty(unadjusted_self_ty, &pick);
|
let self_ty = self.adjust_self_ty(unadjusted_self_ty, &pick);
|
||||||
|
|
@ -83,7 +83,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
// Create substitutions for the method's type parameters.
|
// Create substitutions for the method's type parameters.
|
||||||
let rcvr_substs = self.fresh_receiver_substs(self_ty, &pick);
|
let rcvr_substs = self.fresh_receiver_substs(self_ty, &pick);
|
||||||
let all_substs = self.instantiate_method_substs(&pick, supplied_method_types, rcvr_substs);
|
let all_substs = self.instantiate_method_substs(&pick, segment, rcvr_substs);
|
||||||
|
|
||||||
debug!("all_substs={:?}", all_substs);
|
debug!("all_substs={:?}", all_substs);
|
||||||
|
|
||||||
|
|
@ -279,9 +279,14 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
fn instantiate_method_substs(&mut self,
|
fn instantiate_method_substs(&mut self,
|
||||||
pick: &probe::Pick<'tcx>,
|
pick: &probe::Pick<'tcx>,
|
||||||
mut supplied_method_types: Vec<Ty<'tcx>>,
|
segment: &hir::PathSegment,
|
||||||
substs: &Substs<'tcx>)
|
substs: &Substs<'tcx>)
|
||||||
-> &'tcx Substs<'tcx> {
|
-> &'tcx Substs<'tcx> {
|
||||||
|
let supplied_method_types = match segment.parameters {
|
||||||
|
hir::AngleBracketedParameters(ref data) => &data.types,
|
||||||
|
_ => bug!("unexpected generic arguments: {:?}", segment.parameters),
|
||||||
|
};
|
||||||
|
|
||||||
// Determine the values for the generic parameters of the method.
|
// Determine the values for the generic parameters of the method.
|
||||||
// If they were not explicitly supplied, just construct fresh
|
// If they were not explicitly supplied, just construct fresh
|
||||||
// variables.
|
// variables.
|
||||||
|
|
@ -312,7 +317,6 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
num_method_types))
|
num_method_types))
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
supplied_method_types = vec![self.tcx.types.err; num_method_types];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create subst for early-bound lifetime parameters, combining
|
// Create subst for early-bound lifetime parameters, combining
|
||||||
|
|
@ -331,10 +335,10 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
let i = def.index as usize;
|
let i = def.index as usize;
|
||||||
if i < substs.len() {
|
if i < substs.len() {
|
||||||
substs.type_at(i)
|
substs.type_at(i)
|
||||||
} else if supplied_method_types.is_empty() {
|
} else if let Some(ast_ty) = supplied_method_types.get(i - supplied_start) {
|
||||||
self.type_var_for_def(self.span, def, cur_substs)
|
self.to_ty(ast_ty)
|
||||||
} else {
|
} else {
|
||||||
supplied_method_types[i - supplied_start]
|
self.type_var_for_def(self.span, def, cur_substs)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -130,22 +130,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
/// * `supplied_method_types`: the explicit method type parameters, if any (`T1..Tn`)
|
/// * `supplied_method_types`: the explicit method type parameters, if any (`T1..Tn`)
|
||||||
/// * `self_expr`: the self expression (`foo`)
|
/// * `self_expr`: the self expression (`foo`)
|
||||||
pub fn lookup_method(&self,
|
pub fn lookup_method(&self,
|
||||||
span: Span,
|
|
||||||
method_name: ast::Name,
|
|
||||||
self_ty: ty::Ty<'tcx>,
|
self_ty: ty::Ty<'tcx>,
|
||||||
supplied_method_types: Vec<ty::Ty<'tcx>>,
|
segment: &hir::PathSegment,
|
||||||
|
span: Span,
|
||||||
call_expr: &'gcx hir::Expr,
|
call_expr: &'gcx hir::Expr,
|
||||||
self_expr: &'gcx hir::Expr)
|
self_expr: &'gcx hir::Expr)
|
||||||
-> Result<MethodCallee<'tcx>, MethodError<'tcx>> {
|
-> Result<MethodCallee<'tcx>, MethodError<'tcx>> {
|
||||||
debug!("lookup(method_name={}, self_ty={:?}, call_expr={:?}, self_expr={:?})",
|
debug!("lookup(method_name={}, self_ty={:?}, call_expr={:?}, self_expr={:?})",
|
||||||
method_name,
|
segment.name,
|
||||||
self_ty,
|
self_ty,
|
||||||
call_expr,
|
call_expr,
|
||||||
self_expr);
|
self_expr);
|
||||||
|
|
||||||
let mode = probe::Mode::MethodCall;
|
let mode = probe::Mode::MethodCall;
|
||||||
let self_ty = self.resolve_type_vars_if_possible(&self_ty);
|
let self_ty = self.resolve_type_vars_if_possible(&self_ty);
|
||||||
let pick = self.probe_for_name(span, mode, method_name, IsSuggestion(false),
|
let pick = self.probe_for_name(span, mode, segment.name, IsSuggestion(false),
|
||||||
self_ty, call_expr.id)?;
|
self_ty, call_expr.id)?;
|
||||||
|
|
||||||
if let Some(import_id) = pick.import_id {
|
if let Some(import_id) = pick.import_id {
|
||||||
|
|
@ -161,7 +160,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
call_expr,
|
call_expr,
|
||||||
self_ty,
|
self_ty,
|
||||||
pick,
|
pick,
|
||||||
supplied_method_types))
|
segment))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `lookup_method_in_trait` is used for overloaded operators.
|
/// `lookup_method_in_trait` is used for overloaded operators.
|
||||||
|
|
|
||||||
|
|
@ -2771,22 +2771,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
// Checks a method call.
|
// Checks a method call.
|
||||||
fn check_method_call(&self,
|
fn check_method_call(&self,
|
||||||
expr: &'gcx hir::Expr,
|
expr: &'gcx hir::Expr,
|
||||||
method_name: Spanned<ast::Name>,
|
segment: &hir::PathSegment,
|
||||||
|
span: Span,
|
||||||
args: &'gcx [hir::Expr],
|
args: &'gcx [hir::Expr],
|
||||||
tps: &[P<hir::Ty>],
|
|
||||||
expected: Expectation<'tcx>,
|
expected: Expectation<'tcx>,
|
||||||
lvalue_pref: LvaluePreference) -> Ty<'tcx> {
|
lvalue_pref: LvaluePreference) -> Ty<'tcx> {
|
||||||
let rcvr = &args[0];
|
let rcvr = &args[0];
|
||||||
let rcvr_t = self.check_expr_with_lvalue_pref(&rcvr, lvalue_pref);
|
let rcvr_t = self.check_expr_with_lvalue_pref(&rcvr, lvalue_pref);
|
||||||
|
|
||||||
// no need to check for bot/err -- callee does that
|
// no need to check for bot/err -- callee does that
|
||||||
let expr_t = self.structurally_resolved_type(expr.span, rcvr_t);
|
let rcvr_t = self.structurally_resolved_type(expr.span, rcvr_t);
|
||||||
|
|
||||||
let tps = tps.iter().map(|ast_ty| self.to_ty(&ast_ty)).collect::<Vec<_>>();
|
let method = match self.lookup_method(rcvr_t,
|
||||||
let method = match self.lookup_method(method_name.span,
|
segment,
|
||||||
method_name.node,
|
span,
|
||||||
expr_t,
|
|
||||||
tps,
|
|
||||||
expr,
|
expr,
|
||||||
rcvr) {
|
rcvr) {
|
||||||
Ok(method) => {
|
Ok(method) => {
|
||||||
|
|
@ -2794,10 +2791,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
Ok(method)
|
Ok(method)
|
||||||
}
|
}
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
if method_name.node != keywords::Invalid.name() {
|
if segment.name != keywords::Invalid.name() {
|
||||||
self.report_method_error(method_name.span,
|
self.report_method_error(span,
|
||||||
expr_t,
|
rcvr_t,
|
||||||
method_name.node,
|
segment.name,
|
||||||
Some(rcvr),
|
Some(rcvr),
|
||||||
error,
|
error,
|
||||||
Some(args));
|
Some(args));
|
||||||
|
|
@ -2807,7 +2804,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Call the generic checker.
|
// Call the generic checker.
|
||||||
self.check_method_argument_types(method_name.span, method,
|
self.check_method_argument_types(span, method,
|
||||||
&args[1..],
|
&args[1..],
|
||||||
DontTupleArguments,
|
DontTupleArguments,
|
||||||
expected)
|
expected)
|
||||||
|
|
@ -3735,8 +3732,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
hir::ExprCall(ref callee, ref args) => {
|
hir::ExprCall(ref callee, ref args) => {
|
||||||
self.check_call(expr, &callee, args, expected)
|
self.check_call(expr, &callee, args, expected)
|
||||||
}
|
}
|
||||||
hir::ExprMethodCall(name, ref tps, ref args) => {
|
hir::ExprMethodCall(ref segment, span, ref args) => {
|
||||||
self.check_method_call(expr, name, args, &tps[..], expected, lvalue_pref)
|
self.check_method_call(expr, segment, span, args, expected, lvalue_pref)
|
||||||
}
|
}
|
||||||
hir::ExprCast(ref e, ref t) => {
|
hir::ExprCast(ref e, ref t) => {
|
||||||
// Find the type of `e`. Supply hints based on the type we are casting to,
|
// Find the type of `e`. Supply hints based on the type we are casting to,
|
||||||
|
|
|
||||||
|
|
@ -848,19 +848,16 @@ pub enum ExprKind {
|
||||||
/// The first field resolves to the function itself,
|
/// The first field resolves to the function itself,
|
||||||
/// and the second field is the list of arguments
|
/// and the second field is the list of arguments
|
||||||
Call(P<Expr>, Vec<P<Expr>>),
|
Call(P<Expr>, Vec<P<Expr>>),
|
||||||
/// A method call (`x.foo::<Bar, Baz>(a, b, c, d)`)
|
/// A method call (`x.foo::<'static, Bar, Baz>(a, b, c, d)`)
|
||||||
///
|
///
|
||||||
/// The `SpannedIdent` is the identifier for the method name.
|
/// The `PathSegment` represents the method name and its generic arguments
|
||||||
/// The vector of `Ty`s are the ascripted type parameters for the method
|
|
||||||
/// (within the angle brackets).
|
/// (within the angle brackets).
|
||||||
///
|
|
||||||
/// The first element of the vector of `Expr`s is the expression that evaluates
|
/// The first element of the vector of `Expr`s is the expression that evaluates
|
||||||
/// to the object on which the method is being called on (the receiver),
|
/// to the object on which the method is being called on (the receiver),
|
||||||
/// and the remaining elements are the rest of the arguments.
|
/// and the remaining elements are the rest of the arguments.
|
||||||
///
|
|
||||||
/// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
|
/// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
|
||||||
/// `ExprKind::MethodCall(foo, [Bar, Baz], [x, a, b, c, d])`.
|
/// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`.
|
||||||
MethodCall(SpannedIdent, Vec<P<Ty>>, Vec<P<Expr>>),
|
MethodCall(PathSegment, Vec<P<Expr>>),
|
||||||
/// A tuple (`(a, b, c ,d)`)
|
/// A tuple (`(a, b, c ,d)`)
|
||||||
Tup(Vec<P<Expr>>),
|
Tup(Vec<P<Expr>>),
|
||||||
/// A binary operation (For example: `a + b`, `a * b`)
|
/// A binary operation (For example: `a + b`, `a * b`)
|
||||||
|
|
|
||||||
|
|
@ -673,9 +673,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||||
expr: P<ast::Expr>,
|
expr: P<ast::Expr>,
|
||||||
ident: ast::Ident,
|
ident: ast::Ident,
|
||||||
mut args: Vec<P<ast::Expr>> ) -> P<ast::Expr> {
|
mut args: Vec<P<ast::Expr>> ) -> P<ast::Expr> {
|
||||||
let id = Spanned { node: ident, span: span };
|
|
||||||
args.insert(0, expr);
|
args.insert(0, expr);
|
||||||
self.expr(span, ast::ExprKind::MethodCall(id, Vec::new(), args))
|
self.expr(span, ast::ExprKind::MethodCall(ast::PathSegment::from_ident(ident, span), args))
|
||||||
}
|
}
|
||||||
fn expr_block(&self, b: P<ast::Block>) -> P<ast::Expr> {
|
fn expr_block(&self, b: P<ast::Block>) -> P<ast::Expr> {
|
||||||
self.expr(b.span, ast::ExprKind::Block(b))
|
self.expr(b.span, ast::ExprKind::Block(b))
|
||||||
|
|
|
||||||
|
|
@ -1151,10 +1151,15 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
|
||||||
ExprKind::Call(folder.fold_expr(f),
|
ExprKind::Call(folder.fold_expr(f),
|
||||||
folder.fold_exprs(args))
|
folder.fold_exprs(args))
|
||||||
}
|
}
|
||||||
ExprKind::MethodCall(i, tps, args) => {
|
ExprKind::MethodCall(seg, args) => {
|
||||||
ExprKind::MethodCall(
|
ExprKind::MethodCall(
|
||||||
respan(folder.new_span(i.span), folder.fold_ident(i.node)),
|
PathSegment {
|
||||||
tps.move_map(|x| folder.fold_ty(x)),
|
identifier: folder.fold_ident(seg.identifier),
|
||||||
|
span: folder.new_span(seg.span),
|
||||||
|
parameters: seg.parameters.map(|ps| {
|
||||||
|
ps.map(|ps| folder.fold_path_parameters(ps))
|
||||||
|
}),
|
||||||
|
},
|
||||||
folder.fold_exprs(args))
|
folder.fold_exprs(args))
|
||||||
}
|
}
|
||||||
ExprKind::Binary(binop, lhs, rhs) => {
|
ExprKind::Binary(binop, lhs, rhs) => {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use abi::{self, Abi};
|
use abi::{self, Abi};
|
||||||
use ast::{AttrStyle, BareFnTy};
|
use ast::{AngleBracketedParameterData, AttrStyle, BareFnTy};
|
||||||
use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
|
use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
|
||||||
use ast::Unsafety;
|
use ast::Unsafety;
|
||||||
use ast::{Mod, Arg, Arm, Attribute, BindingMode, TraitItemKind};
|
use ast::{Mod, Arg, Arm, Attribute, BindingMode, TraitItemKind};
|
||||||
|
|
@ -1831,11 +1831,7 @@ impl<'a> Parser<'a> {
|
||||||
let parameters = if parse_generics && self.eat_lt() {
|
let parameters = if parse_generics && self.eat_lt() {
|
||||||
let (lifetimes, types, bindings) = self.parse_generic_args()?;
|
let (lifetimes, types, bindings) = self.parse_generic_args()?;
|
||||||
self.expect_gt()?;
|
self.expect_gt()?;
|
||||||
ast::AngleBracketedParameterData {
|
AngleBracketedParameterData { lifetimes, types, bindings }.into()
|
||||||
lifetimes: lifetimes,
|
|
||||||
types: types,
|
|
||||||
bindings: bindings,
|
|
||||||
}.into()
|
|
||||||
} else if self.eat(&token::OpenDelim(token::Paren)) {
|
} else if self.eat(&token::OpenDelim(token::Paren)) {
|
||||||
let lo = self.prev_span;
|
let lo = self.prev_span;
|
||||||
|
|
||||||
|
|
@ -1898,11 +1894,7 @@ impl<'a> Parser<'a> {
|
||||||
segments.push(PathSegment {
|
segments.push(PathSegment {
|
||||||
identifier: identifier,
|
identifier: identifier,
|
||||||
span: ident_span,
|
span: ident_span,
|
||||||
parameters: ast::AngleBracketedParameterData {
|
parameters: AngleBracketedParameterData { lifetimes, types, bindings }.into(),
|
||||||
lifetimes: lifetimes,
|
|
||||||
types: types,
|
|
||||||
bindings: bindings,
|
|
||||||
}.into(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Consumed `a::b::<T,U>`, check for `::` before proceeding
|
// Consumed `a::b::<T,U>`, check for `::` before proceeding
|
||||||
|
|
@ -2023,14 +2015,6 @@ impl<'a> Parser<'a> {
|
||||||
ExprKind::Call(f, args)
|
ExprKind::Call(f, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mk_method_call(&mut self,
|
|
||||||
ident: ast::SpannedIdent,
|
|
||||||
tps: Vec<P<Ty>>,
|
|
||||||
args: Vec<P<Expr>>)
|
|
||||||
-> ast::ExprKind {
|
|
||||||
ExprKind::MethodCall(ident, tps, args)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn mk_index(&mut self, expr: P<Expr>, idx: P<Expr>) -> ast::ExprKind {
|
pub fn mk_index(&mut self, expr: P<Expr>, idx: P<Expr>) -> ast::ExprKind {
|
||||||
ExprKind::Index(expr, idx)
|
ExprKind::Index(expr, idx)
|
||||||
}
|
}
|
||||||
|
|
@ -2460,7 +2444,7 @@ impl<'a> Parser<'a> {
|
||||||
// parsing into an expression.
|
// parsing into an expression.
|
||||||
fn parse_dot_suffix(&mut self, ident: Ident, ident_span: Span, self_value: P<Expr>, lo: Span)
|
fn parse_dot_suffix(&mut self, ident: Ident, ident_span: Span, self_value: P<Expr>, lo: Span)
|
||||||
-> PResult<'a, P<Expr>> {
|
-> PResult<'a, P<Expr>> {
|
||||||
let (_, tys, bindings) = if self.eat(&token::ModSep) {
|
let (lifetimes, types, bindings) = if self.eat(&token::ModSep) {
|
||||||
self.expect_lt()?;
|
self.expect_lt()?;
|
||||||
let args = self.parse_generic_args()?;
|
let args = self.parse_generic_args()?;
|
||||||
self.expect_gt()?;
|
self.expect_gt()?;
|
||||||
|
|
@ -2469,11 +2453,6 @@ impl<'a> Parser<'a> {
|
||||||
(Vec::new(), Vec::new(), Vec::new())
|
(Vec::new(), Vec::new(), Vec::new())
|
||||||
};
|
};
|
||||||
|
|
||||||
if !bindings.is_empty() {
|
|
||||||
let prev_span = self.prev_span;
|
|
||||||
self.span_err(prev_span, "type bindings are only permitted on trait paths");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(match self.token {
|
Ok(match self.token {
|
||||||
// expr.f() method call.
|
// expr.f() method call.
|
||||||
token::OpenDelim(token::Paren) => {
|
token::OpenDelim(token::Paren) => {
|
||||||
|
|
@ -2486,17 +2465,20 @@ impl<'a> Parser<'a> {
|
||||||
let hi = self.prev_span;
|
let hi = self.prev_span;
|
||||||
|
|
||||||
es.insert(0, self_value);
|
es.insert(0, self_value);
|
||||||
let id = respan(ident_span.to(ident_span), ident);
|
let seg = PathSegment {
|
||||||
let nd = self.mk_method_call(id, tys, es);
|
identifier: ident,
|
||||||
self.mk_expr(lo.to(hi), nd, ThinVec::new())
|
span: ident_span.to(ident_span),
|
||||||
|
parameters: AngleBracketedParameterData { lifetimes, types, bindings }.into(),
|
||||||
|
};
|
||||||
|
self.mk_expr(lo.to(hi), ExprKind::MethodCall(seg, es), ThinVec::new())
|
||||||
}
|
}
|
||||||
// Field access.
|
// Field access.
|
||||||
_ => {
|
_ => {
|
||||||
if !tys.is_empty() {
|
if let Some(generic_arg_span) = lifetimes.get(0).map(|x| x.span).or_else(||
|
||||||
let prev_span = self.prev_span;
|
types.get(0).map(|x| x.span)).or_else(||
|
||||||
self.span_err(prev_span,
|
bindings.get(0).map(|x| x.span)) {
|
||||||
"field expressions may not \
|
self.span_err(generic_arg_span,
|
||||||
have type parameters");
|
"field expressions may not have generic arguments");
|
||||||
}
|
}
|
||||||
|
|
||||||
let id = respan(ident_span.to(ident_span), ident);
|
let id = respan(ident_span.to(ident_span), ident);
|
||||||
|
|
|
||||||
|
|
@ -1951,18 +1951,14 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_expr_method_call(&mut self,
|
fn print_expr_method_call(&mut self,
|
||||||
ident: ast::SpannedIdent,
|
segment: &ast::PathSegment,
|
||||||
tys: &[P<ast::Ty>],
|
|
||||||
args: &[P<ast::Expr>]) -> io::Result<()> {
|
args: &[P<ast::Expr>]) -> io::Result<()> {
|
||||||
let base_args = &args[1..];
|
let base_args = &args[1..];
|
||||||
self.print_expr(&args[0])?;
|
self.print_expr(&args[0])?;
|
||||||
word(&mut self.s, ".")?;
|
word(&mut self.s, ".")?;
|
||||||
self.print_ident(ident.node)?;
|
self.print_ident(segment.identifier)?;
|
||||||
if !tys.is_empty() {
|
if let Some(ref parameters) = segment.parameters {
|
||||||
word(&mut self.s, "::<")?;
|
self.print_path_parameters(parameters, true)?;
|
||||||
self.commasep(Inconsistent, tys,
|
|
||||||
|s, ty| s.print_type(ty))?;
|
|
||||||
word(&mut self.s, ">")?;
|
|
||||||
}
|
}
|
||||||
self.print_call_post(base_args)
|
self.print_call_post(base_args)
|
||||||
}
|
}
|
||||||
|
|
@ -2041,8 +2037,8 @@ impl<'a> State<'a> {
|
||||||
ast::ExprKind::Call(ref func, ref args) => {
|
ast::ExprKind::Call(ref func, ref args) => {
|
||||||
self.print_expr_call(func, &args[..])?;
|
self.print_expr_call(func, &args[..])?;
|
||||||
}
|
}
|
||||||
ast::ExprKind::MethodCall(ident, ref tys, ref args) => {
|
ast::ExprKind::MethodCall(ref segment, ref args) => {
|
||||||
self.print_expr_method_call(ident, &tys[..], &args[..])?;
|
self.print_expr_method_call(segment, &args[..])?;
|
||||||
}
|
}
|
||||||
ast::ExprKind::Binary(op, ref lhs, ref rhs) => {
|
ast::ExprKind::Binary(op, ref lhs, ref rhs) => {
|
||||||
self.print_expr_binary(op, lhs, rhs)?;
|
self.print_expr_binary(op, lhs, rhs)?;
|
||||||
|
|
|
||||||
|
|
@ -674,9 +674,8 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
|
||||||
visitor.visit_expr(callee_expression);
|
visitor.visit_expr(callee_expression);
|
||||||
walk_list!(visitor, visit_expr, arguments);
|
walk_list!(visitor, visit_expr, arguments);
|
||||||
}
|
}
|
||||||
ExprKind::MethodCall(ref ident, ref types, ref arguments) => {
|
ExprKind::MethodCall(ref segment, ref arguments) => {
|
||||||
visitor.visit_ident(ident.span, ident.node);
|
visitor.visit_path_segment(expression.span, segment);
|
||||||
walk_list!(visitor, visit_ty, types);
|
|
||||||
walk_list!(visitor, visit_expr, arguments);
|
walk_list!(visitor, visit_expr, arguments);
|
||||||
}
|
}
|
||||||
ExprKind::Binary(_, ref left_expression, ref right_expression) => {
|
ExprKind::Binary(_, ref left_expression, ref right_expression) => {
|
||||||
|
|
|
||||||
13
src/test/compile-fail/method-call-type-binding.rs
Normal file
13
src/test/compile-fail/method-call-type-binding.rs
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
0.clone::<T = u8>(); //~ ERROR type bindings cannot be used in method calls
|
||||||
|
}
|
||||||
|
|
@ -21,5 +21,5 @@ fn main() {
|
||||||
y: 2,
|
y: 2,
|
||||||
};
|
};
|
||||||
f.x::<isize>;
|
f.x::<isize>;
|
||||||
//~^ ERROR field expressions may not have type parameters
|
//~^ ERROR field expressions may not have generic arguments
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 4c0a8b63d61942349c18727409b2a600446e02d6
|
Subproject commit 70b89fdd7e5e77a3b88fc68982861d39d155be29
|
||||||
Loading…
Add table
Add a link
Reference in a new issue