From 287de2595a40c03d9ffe81f55c13c731fd01583f Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 7 Jul 2017 02:39:55 +0300 Subject: [PATCH 1/3] Store all generic arguments for method calls in AST --- src/librustc/hir/lowering.rs | 11 ++++- src/librustc_passes/ast_validation.rs | 17 +++++++ src/librustc_resolve/lib.rs | 14 +++--- src/libsyntax/ast.rs | 11 ++--- src/libsyntax/ext/build.rs | 3 +- src/libsyntax/fold.rs | 11 +++-- src/libsyntax/parse/parser.rs | 48 ++++++------------- src/libsyntax/print/pprust.rs | 16 +++---- src/libsyntax/visit.rs | 5 +- .../compile-fail/method-call-type-binding.rs | 13 +++++ .../type-parameters-in-field-exprs.rs | 2 +- 11 files changed, 82 insertions(+), 69 deletions(-) create mode 100644 src/test/compile-fail/method-call-type-binding.rs diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index a6a294343005c..1e9314cfde32f 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1844,10 +1844,17 @@ impl<'a> LoweringContext<'a> { let f = P(self.lower_expr(f)); 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 = match seg.parameters { + Some(ref params) => match **params { + PathParameters::AngleBracketed(ref param_data) => ¶m_data.types[..], + _ => &[], + }, + _ => &[], + }; let tps = tps.iter().map(|x| self.lower_ty(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(respan(seg.span, self.lower_ident(seg.identifier)), tps, args) } ExprKind::Binary(binop, ref lhs, ref rhs) => { let binop = self.lower_binop(binop); diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 6ad03186dc778..72c7b92fe6e30 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -125,6 +125,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ExprKind::Continue(Some(ident)) => { 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"); + } + } + } + } _ => {} } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b60a8df407f7b..7754cd7366ecf 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2467,9 +2467,9 @@ impl<'a> Resolver<'a> { path_str, ident.node)); return err; } - ExprKind::MethodCall(ident, ..) => { + ExprKind::MethodCall(ref segment, ..) => { err.span_label(parent.span, format!("did you mean `{}::{}(...)`?", - path_str, ident.node)); + path_str, segment.identifier)); return err; } _ => {} @@ -3145,15 +3145,13 @@ impl<'a> Resolver<'a> { ExprKind::Field(ref subexpression, _) => { self.resolve_expr(subexpression, Some(expr)); } - ExprKind::MethodCall(_, ref types, ref arguments) => { + ExprKind::MethodCall(ref segment, ref arguments) => { let mut arguments = arguments.iter(); self.resolve_expr(arguments.next().unwrap(), Some(expr)); for argument in arguments { self.resolve_expr(argument, None); } - for ty in types.iter() { - self.visit_ty(ty); - } + self.visit_path_segment(expr.span, segment); } ExprKind::Repeat(ref element, ref count) => { @@ -3185,10 +3183,10 @@ impl<'a> Resolver<'a> { let traits = self.get_traits_containing_item(name.node, ValueNS); self.trait_map.insert(expr.id, traits); } - ExprKind::MethodCall(name, ..) => { + ExprKind::MethodCall(ref segment, ..) => { debug!("(recording candidate traits for expr) recording traits for {}", 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); } _ => { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d00e29d954fc6..f7d9d532062a9 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -848,19 +848,16 @@ pub enum ExprKind { /// The first field resolves to the function itself, /// and the second field is the list of arguments Call(P, Vec>), - /// A method call (`x.foo::(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 vector of `Ty`s are the ascripted type parameters for the method + /// The `PathSegment` represents the method name and its generic arguments /// (within the angle brackets). - /// /// 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), /// and the remaining elements are the rest of the arguments. - /// /// Thus, `x.foo::(a, b, c, d)` is represented as - /// `ExprKind::MethodCall(foo, [Bar, Baz], [x, a, b, c, d])`. - MethodCall(SpannedIdent, Vec>, Vec>), + /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`. + MethodCall(PathSegment, Vec>), /// A tuple (`(a, b, c ,d)`) Tup(Vec>), /// A binary operation (For example: `a + b`, `a * b`) diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 03e5ea529e210..2555bf6dea7ab 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -673,9 +673,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> { expr: P, ident: ast::Ident, mut args: Vec> ) -> P { - let id = Spanned { node: ident, span: span }; 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) -> P { self.expr(b.span, ast::ExprKind::Block(b)) diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 1fc670ec9f7fb..eaec1eef1722c 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1151,10 +1151,15 @@ pub fn noop_fold_expr(Expr {id, node, span, attrs}: Expr, folder: &mu ExprKind::Call(folder.fold_expr(f), folder.fold_exprs(args)) } - ExprKind::MethodCall(i, tps, args) => { + ExprKind::MethodCall(seg, args) => { ExprKind::MethodCall( - respan(folder.new_span(i.span), folder.fold_ident(i.node)), - tps.move_map(|x| folder.fold_ty(x)), + PathSegment { + 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)) } ExprKind::Binary(binop, lhs, rhs) => { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f605c4643107d..093ab0073f0db 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -9,7 +9,7 @@ // except according to those terms. use abi::{self, Abi}; -use ast::{AttrStyle, BareFnTy}; +use ast::{AngleBracketedParameterData, AttrStyle, BareFnTy}; use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; use ast::Unsafety; 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 (lifetimes, types, bindings) = self.parse_generic_args()?; self.expect_gt()?; - ast::AngleBracketedParameterData { - lifetimes: lifetimes, - types: types, - bindings: bindings, - }.into() + AngleBracketedParameterData { lifetimes, types, bindings }.into() } else if self.eat(&token::OpenDelim(token::Paren)) { let lo = self.prev_span; @@ -1898,11 +1894,7 @@ impl<'a> Parser<'a> { segments.push(PathSegment { identifier: identifier, span: ident_span, - parameters: ast::AngleBracketedParameterData { - lifetimes: lifetimes, - types: types, - bindings: bindings, - }.into(), + parameters: AngleBracketedParameterData { lifetimes, types, bindings }.into(), }); // Consumed `a::b::`, check for `::` before proceeding @@ -2023,14 +2015,6 @@ impl<'a> Parser<'a> { ExprKind::Call(f, args) } - fn mk_method_call(&mut self, - ident: ast::SpannedIdent, - tps: Vec>, - args: Vec>) - -> ast::ExprKind { - ExprKind::MethodCall(ident, tps, args) - } - pub fn mk_index(&mut self, expr: P, idx: P) -> ast::ExprKind { ExprKind::Index(expr, idx) } @@ -2460,7 +2444,7 @@ impl<'a> Parser<'a> { // parsing into an expression. fn parse_dot_suffix(&mut self, ident: Ident, ident_span: Span, self_value: P, lo: Span) -> PResult<'a, P> { - let (_, tys, bindings) = if self.eat(&token::ModSep) { + let (lifetimes, types, bindings) = if self.eat(&token::ModSep) { self.expect_lt()?; let args = self.parse_generic_args()?; self.expect_gt()?; @@ -2469,11 +2453,6 @@ impl<'a> Parser<'a> { (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 { // expr.f() method call. token::OpenDelim(token::Paren) => { @@ -2486,17 +2465,20 @@ impl<'a> Parser<'a> { let hi = self.prev_span; es.insert(0, self_value); - let id = respan(ident_span.to(ident_span), ident); - let nd = self.mk_method_call(id, tys, es); - self.mk_expr(lo.to(hi), nd, ThinVec::new()) + let seg = PathSegment { + identifier: ident, + 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. _ => { - if !tys.is_empty() { - let prev_span = self.prev_span; - self.span_err(prev_span, - "field expressions may not \ - have type parameters"); + if let Some(generic_arg_span) = lifetimes.get(0).map(|x| x.span).or_else(|| + types.get(0).map(|x| x.span)).or_else(|| + bindings.get(0).map(|x| x.span)) { + self.span_err(generic_arg_span, + "field expressions may not have generic arguments"); } let id = respan(ident_span.to(ident_span), ident); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index d449e412d6cc3..51c48f15f2975 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1951,18 +1951,14 @@ impl<'a> State<'a> { } fn print_expr_method_call(&mut self, - ident: ast::SpannedIdent, - tys: &[P], + segment: &ast::PathSegment, args: &[P]) -> io::Result<()> { let base_args = &args[1..]; self.print_expr(&args[0])?; word(&mut self.s, ".")?; - self.print_ident(ident.node)?; - if !tys.is_empty() { - word(&mut self.s, "::<")?; - self.commasep(Inconsistent, tys, - |s, ty| s.print_type(ty))?; - word(&mut self.s, ">")?; + self.print_ident(segment.identifier)?; + if let Some(ref parameters) = segment.parameters { + self.print_path_parameters(parameters, true)?; } self.print_call_post(base_args) } @@ -2041,8 +2037,8 @@ impl<'a> State<'a> { ast::ExprKind::Call(ref func, ref args) => { self.print_expr_call(func, &args[..])?; } - ast::ExprKind::MethodCall(ident, ref tys, ref args) => { - self.print_expr_method_call(ident, &tys[..], &args[..])?; + ast::ExprKind::MethodCall(ref segment, ref args) => { + self.print_expr_method_call(segment, &args[..])?; } ast::ExprKind::Binary(op, ref lhs, ref rhs) => { self.print_expr_binary(op, lhs, rhs)?; diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 18a0949af0eb1..f4ac7e341ce4b 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -674,9 +674,8 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { visitor.visit_expr(callee_expression); walk_list!(visitor, visit_expr, arguments); } - ExprKind::MethodCall(ref ident, ref types, ref arguments) => { - visitor.visit_ident(ident.span, ident.node); - walk_list!(visitor, visit_ty, types); + ExprKind::MethodCall(ref segment, ref arguments) => { + visitor.visit_path_segment(expression.span, segment); walk_list!(visitor, visit_expr, arguments); } ExprKind::Binary(_, ref left_expression, ref right_expression) => { diff --git a/src/test/compile-fail/method-call-type-binding.rs b/src/test/compile-fail/method-call-type-binding.rs new file mode 100644 index 0000000000000..acffb06ebecf2 --- /dev/null +++ b/src/test/compile-fail/method-call-type-binding.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + 0.clone::(); //~ ERROR type bindings cannot be used in method calls +} diff --git a/src/test/parse-fail/type-parameters-in-field-exprs.rs b/src/test/parse-fail/type-parameters-in-field-exprs.rs index 9b160434e36ae..e904e8b5447a4 100644 --- a/src/test/parse-fail/type-parameters-in-field-exprs.rs +++ b/src/test/parse-fail/type-parameters-in-field-exprs.rs @@ -21,5 +21,5 @@ fn main() { y: 2, }; f.x::; - //~^ ERROR field expressions may not have type parameters + //~^ ERROR field expressions may not have generic arguments } From 8c44a9dca794afc58a876dd1e9223fdc469cabed Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 7 Jul 2017 15:57:51 +0300 Subject: [PATCH 2/3] Store all generic arguments for method calls in HIR --- src/librustc/hir/intravisit.rs | 5 ++-- src/librustc/hir/lowering.rs | 11 ++------ src/librustc/hir/mod.rs | 17 +++++------- src/librustc/hir/print.rs | 17 ++++++------ src/librustc/ich/impls_hir.rs | 2 +- src/librustc_privacy/lib.rs | 4 +-- src/librustc_typeck/check/method/confirm.rs | 26 ++++++++++-------- src/librustc_typeck/check/method/mod.rs | 11 ++++---- src/librustc_typeck/check/mod.rs | 29 +++++++++------------ 9 files changed, 55 insertions(+), 67 deletions(-) diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 836d9775a3f69..57198d8ca0b77 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -944,10 +944,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { walk_list!(visitor, visit_expr, arguments); visitor.visit_expr(callee_expression) } - ExprMethodCall(ref name, ref types, ref arguments) => { - visitor.visit_name(name.span, name.node); + ExprMethodCall(ref segment, _, ref arguments) => { + visitor.visit_path_segment(expression.span, segment); walk_list!(visitor, visit_expr, arguments); - walk_list!(visitor, visit_ty, types); } ExprBinary(_, ref left_expression, ref right_expression) => { visitor.visit_expr(left_expression); diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 1e9314cfde32f..67dc069da4131 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1845,16 +1845,9 @@ impl<'a> LoweringContext<'a> { hir::ExprCall(f, args.iter().map(|x| self.lower_expr(x)).collect()) } ExprKind::MethodCall(ref seg, ref args) => { - let tps = match seg.parameters { - Some(ref params) => match **params { - PathParameters::AngleBracketed(ref param_data) => ¶m_data.types[..], - _ => &[], - }, - _ => &[], - }; - 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(); - hir::ExprMethodCall(respan(seg.span, self.lower_ident(seg.identifier)), tps, args) + hir::ExprMethodCall(hir_seg, seg.span, args) } ExprKind::Binary(binop, ref lhs, ref rhs) => { let binop = self.lower_binop(binop); diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 3443c6bb2c659..fd79ec3b6b92c 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -972,19 +972,16 @@ pub enum Expr_ { /// The first field resolves to the function itself (usually an `ExprPath`), /// and the second field is the list of arguments ExprCall(P, HirVec), - /// A method call (`x.foo::(a, b, c, d)`) + /// A method call (`x.foo::<'static, Bar, Baz>(a, b, c, d)`) /// - /// The `Spanned` is the identifier for the method name. - /// The vector of `Ty`s are the ascripted type parameters for the method + /// The `PathSegment`/`Span` represent the method name and its generic arguments /// (within the angle brackets). - /// - /// 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), and the remaining elements are the rest of the arguments. - /// + /// 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), + /// and the remaining elements are the rest of the arguments. /// Thus, `x.foo::(a, b, c, d)` is represented as - /// `ExprMethodCall(foo, [Bar, Baz], [x, a, b, c, d])`. - ExprMethodCall(Spanned, HirVec>, HirVec), + /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`. + ExprMethodCall(PathSegment, Span, HirVec), /// A tuple (`(a, b, c ,d)`) ExprTup(HirVec), /// A binary operation (For example: `a + b`, `a * b`) diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index f32fab7d847d7..1f7b73d134596 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1188,18 +1188,17 @@ impl<'a> State<'a> { } fn print_expr_method_call(&mut self, - name: Spanned, - tys: &[P], + segment: &hir::PathSegment, args: &[hir::Expr]) -> io::Result<()> { let base_args = &args[1..]; self.print_expr(&args[0])?; word(&mut self.s, ".")?; - self.print_name(name.node)?; - if !tys.is_empty() { - word(&mut self.s, "::<")?; - self.commasep(Inconsistent, tys, |s, ty| s.print_type(&ty))?; - word(&mut self.s, ">")?; + self.print_name(segment.name)?; + if !segment.parameters.lifetimes().is_empty() || + !segment.parameters.types().is_empty() || + !segment.parameters.bindings().is_empty() { + self.print_path_parameters(&segment.parameters, true)?; } self.print_call_post(base_args) } @@ -1254,8 +1253,8 @@ impl<'a> State<'a> { hir::ExprCall(ref func, ref args) => { self.print_expr_call(&func, args)?; } - hir::ExprMethodCall(name, ref tys, ref args) => { - self.print_expr_method_call(name, &tys[..], args)?; + hir::ExprMethodCall(ref segment, _, ref args) => { + self.print_expr_method_call(segment, args)?; } hir::ExprBinary(op, ref lhs, ref rhs) => { self.print_expr_binary(op, &lhs, &rhs)?; diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 7f7a545df9605..c82fea197fb75 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -626,7 +626,7 @@ impl_stable_hash_for!(enum hir::Expr_ { ExprBox(sub), ExprArray(subs), ExprCall(callee, args), - ExprMethodCall(name, ts, args), + ExprMethodCall(segment, span, args), ExprTup(fields), ExprBinary(op, lhs, rhs), ExprUnary(op, operand), diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 051b89219c1f5..4a74a9e524d0c 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -670,10 +670,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { return; } } - hir::ExprMethodCall(name, ..) => { + hir::ExprMethodCall(_, span, _) => { // Method calls have to be checked specially. 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) { return; } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 209245187b13f..0829951e12deb 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -44,15 +44,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { call_expr: &'gcx hir::Expr, unadjusted_self_ty: Ty<'tcx>, pick: probe::Pick<'tcx>, - supplied_method_types: Vec>) + segment: &hir::PathSegment) -> MethodCallee<'tcx> { - debug!("confirm(unadjusted_self_ty={:?}, pick={:?}, supplied_method_types={:?})", + debug!("confirm(unadjusted_self_ty={:?}, pick={:?}, generic_args={:?})", unadjusted_self_ty, pick, - supplied_method_types); + segment.parameters); 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, unadjusted_self_ty: Ty<'tcx>, pick: probe::Pick<'tcx>, - supplied_method_types: Vec>) + segment: &hir::PathSegment) -> MethodCallee<'tcx> { // Adjust the self expression the user provided and obtain the adjusted type. 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. 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); @@ -279,9 +279,14 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { fn instantiate_method_substs(&mut self, pick: &probe::Pick<'tcx>, - mut supplied_method_types: Vec>, + segment: &hir::PathSegment, substs: &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. // If they were not explicitly supplied, just construct fresh // variables. @@ -312,7 +317,6 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { num_method_types)) .emit(); } - supplied_method_types = vec![self.tcx.types.err; num_method_types]; } // 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; if i < substs.len() { substs.type_at(i) - } else if supplied_method_types.is_empty() { - self.type_var_for_def(self.span, def, cur_substs) + } else if let Some(ast_ty) = supplied_method_types.get(i - supplied_start) { + self.to_ty(ast_ty) } else { - supplied_method_types[i - supplied_start] + self.type_var_for_def(self.span, def, cur_substs) } }) } diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 4f4169ac93d1b..c842e47aaf51c 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -130,22 +130,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// * `supplied_method_types`: the explicit method type parameters, if any (`T1..Tn`) /// * `self_expr`: the self expression (`foo`) pub fn lookup_method(&self, - span: Span, - method_name: ast::Name, self_ty: ty::Ty<'tcx>, - supplied_method_types: Vec>, + segment: &hir::PathSegment, + span: Span, call_expr: &'gcx hir::Expr, self_expr: &'gcx hir::Expr) -> Result, MethodError<'tcx>> { debug!("lookup(method_name={}, self_ty={:?}, call_expr={:?}, self_expr={:?})", - method_name, + segment.name, self_ty, call_expr, self_expr); let mode = probe::Mode::MethodCall; 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)?; if let Some(import_id) = pick.import_id { @@ -161,7 +160,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { call_expr, self_ty, pick, - supplied_method_types)) + segment)) } /// `lookup_method_in_trait` is used for overloaded operators. diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f8c7bfc27a225..2634e8fcc006d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2771,22 +2771,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Checks a method call. fn check_method_call(&self, expr: &'gcx hir::Expr, - method_name: Spanned, + segment: &hir::PathSegment, + span: Span, args: &'gcx [hir::Expr], - tps: &[P], expected: Expectation<'tcx>, lvalue_pref: LvaluePreference) -> Ty<'tcx> { let rcvr = &args[0]; let rcvr_t = self.check_expr_with_lvalue_pref(&rcvr, lvalue_pref); - // 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::>(); - let method = match self.lookup_method(method_name.span, - method_name.node, - expr_t, - tps, + let method = match self.lookup_method(rcvr_t, + segment, + span, expr, rcvr) { Ok(method) => { @@ -2794,10 +2791,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Ok(method) } Err(error) => { - if method_name.node != keywords::Invalid.name() { - self.report_method_error(method_name.span, - expr_t, - method_name.node, + if segment.name != keywords::Invalid.name() { + self.report_method_error(span, + rcvr_t, + segment.name, Some(rcvr), error, Some(args)); @@ -2807,7 +2804,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; // Call the generic checker. - self.check_method_argument_types(method_name.span, method, + self.check_method_argument_types(span, method, &args[1..], DontTupleArguments, expected) @@ -3735,8 +3732,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::ExprCall(ref callee, ref args) => { self.check_call(expr, &callee, args, expected) } - hir::ExprMethodCall(name, ref tps, ref args) => { - self.check_method_call(expr, name, args, &tps[..], expected, lvalue_pref) + hir::ExprMethodCall(ref segment, span, ref args) => { + self.check_method_call(expr, segment, span, args, expected, lvalue_pref) } hir::ExprCast(ref e, ref t) => { // Find the type of `e`. Supply hints based on the type we are casting to, From 9ac79e4934476ba520151c24f1954cfc5895ce10 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 8 Jul 2017 03:32:19 +0300 Subject: [PATCH 3/3] Update rls to pull rustfmt with libsyntax changes --- src/Cargo.lock | 14 +++++++------- src/tools/rls | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 28c4d2e981938..1b21ffdfe70f4 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -578,7 +578,7 @@ dependencies = [ [[package]] name = "languageserver-types" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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)", "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)", - "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)", "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-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-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_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)", @@ -1474,8 +1474,8 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.1.8" +source = "git+https://github.com/rust-lang-nursery/rustfmt?branch=rustfmt-42492#7333dfc95b4af5c7283ba03f33c50f108d2be3f5" dependencies = [ "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)", @@ -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 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 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 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" @@ -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 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 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)" = "" "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 semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd61b85a0fa777f7fb7c454b9189b2941b110d1385ce84d7f76efdf1606a85" diff --git a/src/tools/rls b/src/tools/rls index 4c0a8b63d6194..70b89fdd7e5e7 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 4c0a8b63d61942349c18727409b2a600446e02d6 +Subproject commit 70b89fdd7e5e77a3b88fc68982861d39d155be29