1
Fork 0

auto merge of #13713 : edwardw/rust/methodcall-span, r=alexcrichton

Specifically, the method parameter cardinality mismatch or missing
method error message span now gets method itself exactly. It was the
whole expression.

Closes #9390
Closes #13684
Closes #13709
This commit is contained in:
bors 2014-04-24 07:06:26 -07:00
commit 70647ccc6d
9 changed files with 53 additions and 17 deletions

View file

@ -791,7 +791,7 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
} }
Some(method) => { Some(method) => {
debug!("(privacy checking) checking impl method"); debug!("(privacy checking) checking impl method");
self.check_method(expr.span, method.origin, ident); self.check_method(expr.span, method.origin, ident.node);
} }
} }
} }

View file

@ -5083,7 +5083,7 @@ impl<'a> Resolver<'a> {
debug!("(recording candidate traits for expr) recording \ debug!("(recording candidate traits for expr) recording \
traits for {}", traits for {}",
expr.id); expr.id);
let traits = self.search_for_traits_containing_method(ident.name); let traits = self.search_for_traits_containing_method(ident.node.name);
self.trait_map.insert(expr.id, traits); self.trait_map.insert(expr.id, traits);
} }
_ => { _ => {

View file

@ -1722,7 +1722,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
} }
_ => { _ => {
fcx.tcx().sess.span_bug( fcx.tcx().sess.span_bug(
sp, callee_expr.span,
format!("method without bare fn type")); format!("method without bare fn type"));
} }
} }
@ -1936,7 +1936,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
// Checks a method call. // Checks a method call.
fn check_method_call(fcx: &FnCtxt, fn check_method_call(fcx: &FnCtxt,
expr: &ast::Expr, expr: &ast::Expr,
method_name: ast::Ident, method_name: ast::SpannedIdent,
args: &[@ast::Expr], args: &[@ast::Expr],
tps: &[ast::P<ast::Ty>]) { tps: &[ast::P<ast::Ty>]) {
let rcvr = args[0]; let rcvr = args[0];
@ -1952,7 +1952,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
let tps = tps.iter().map(|&ast_ty| fcx.to_ty(ast_ty)).collect::<Vec<_>>(); let tps = tps.iter().map(|&ast_ty| fcx.to_ty(ast_ty)).collect::<Vec<_>>();
let fn_ty = match method::lookup(fcx, expr, rcvr, let fn_ty = match method::lookup(fcx, expr, rcvr,
method_name.name, method_name.node.name,
expr_t, tps.as_slice(), expr_t, tps.as_slice(),
DontDerefArgs, DontDerefArgs,
CheckTraitsAndInherentMethods, CheckTraitsAndInherentMethods,
@ -1966,11 +1966,10 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
None => { None => {
debug!("(checking method call) failing expr is {}", expr.id); debug!("(checking method call) failing expr is {}", expr.id);
fcx.type_error_message(expr.span, fcx.type_error_message(method_name.span,
|actual| { |actual| {
format!("type `{}` does not implement any method in scope \ format!("type `{}` does not implement any method in scope named `{}`",
named `{}`", actual, token::get_ident(method_name.node))
actual, token::get_ident(method_name))
}, },
expr_t, expr_t,
None); None);
@ -1982,7 +1981,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
}; };
// Call the generic checker. // Call the generic checker.
let ret_ty = check_method_argument_types(fcx, expr.span, let ret_ty = check_method_argument_types(fcx, method_name.span,
fn_ty, expr, args, fn_ty, expr, args,
DontDerefArgs); DontDerefArgs);

View file

@ -481,7 +481,7 @@ pub enum Expr_ {
ExprBox(@Expr, @Expr), ExprBox(@Expr, @Expr),
ExprVec(Vec<@Expr>), ExprVec(Vec<@Expr>),
ExprCall(@Expr, Vec<@Expr>), ExprCall(@Expr, Vec<@Expr>),
ExprMethodCall(Ident, Vec<P<Ty>>, Vec<@Expr>), ExprMethodCall(SpannedIdent, Vec<P<Ty>>, Vec<@Expr>),
ExprTup(Vec<@Expr>), ExprTup(Vec<@Expr>),
ExprBinary(BinOp, @Expr, @Expr), ExprBinary(BinOp, @Expr, @Expr),
ExprUnary(UnOp, @Expr), ExprUnary(UnOp, @Expr),

View file

@ -12,7 +12,7 @@ use abi;
use ast::{P, Ident}; use ast::{P, Ident};
use ast; use ast;
use ast_util; use ast_util;
use codemap::{Span, respan, DUMMY_SP}; use codemap::{Span, respan, Spanned, DUMMY_SP};
use ext::base::ExtCtxt; use ext::base::ExtCtxt;
use ext::quote::rt::*; use ext::quote::rt::*;
use fold::Folder; use fold::Folder;
@ -548,8 +548,9 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
expr: @ast::Expr, expr: @ast::Expr,
ident: ast::Ident, ident: ast::Ident,
mut args: Vec<@ast::Expr> ) -> @ast::Expr { mut args: Vec<@ast::Expr> ) -> @ast::Expr {
let id = Spanned { node: ident, span: span };
args.unshift(expr); args.unshift(expr);
self.expr(span, ast::ExprMethodCall(ident, Vec::new(), args)) self.expr(span, ast::ExprMethodCall(id, Vec::new(), args))
} }
fn expr_block(&self, b: P<ast::Block>) -> @ast::Expr { fn expr_block(&self, b: P<ast::Block>) -> @ast::Expr {
self.expr(b.span, ast::ExprBlock(b)) self.expr(b.span, ast::ExprBlock(b))

View file

@ -798,7 +798,7 @@ pub fn noop_fold_expr<T: Folder>(e: @Expr, folder: &mut T) -> @Expr {
} }
ExprMethodCall(i, ref tps, ref args) => { ExprMethodCall(i, ref tps, ref args) => {
ExprMethodCall( ExprMethodCall(
folder.fold_ident(i), respan(i.span, folder.fold_ident(i.node)),
tps.iter().map(|&x| folder.fold_ty(x)).collect(), tps.iter().map(|&x| folder.fold_ty(x)).collect(),
args.iter().map(|&x| folder.fold_expr(x)).collect()) args.iter().map(|&x| folder.fold_expr(x)).collect())
} }

View file

@ -1646,7 +1646,11 @@ impl<'a> Parser<'a> {
ExprCall(f, args) ExprCall(f, args)
} }
fn mk_method_call(&mut self, ident: Ident, tps: Vec<P<Ty>> , args: Vec<@Expr> ) -> ast::Expr_ { fn mk_method_call(&mut self,
ident: ast::SpannedIdent,
tps: Vec<P<Ty>>,
args: Vec<@Expr>)
-> ast::Expr_ {
ExprMethodCall(ident, tps, args) ExprMethodCall(ident, tps, args)
} }
@ -1919,6 +1923,7 @@ impl<'a> Parser<'a> {
if self.eat(&token::DOT) { if self.eat(&token::DOT) {
match self.token { match self.token {
token::IDENT(i, _) => { token::IDENT(i, _) => {
let dot = self.last_span.hi;
hi = self.span.hi; hi = self.span.hi;
self.bump(); self.bump();
let (_, tys) = if self.eat(&token::MOD_SEP) { let (_, tys) = if self.eat(&token::MOD_SEP) {
@ -1940,7 +1945,8 @@ impl<'a> Parser<'a> {
hi = self.last_span.hi; hi = self.last_span.hi;
es.unshift(e); es.unshift(e);
let nd = self.mk_method_call(i, tys, es); let id = spanned(dot, hi, i);
let nd = self.mk_method_call(id, tys, es);
e = self.mk_expr(lo, hi, nd); e = self.mk_expr(lo, hi, nd);
} }
_ => { _ => {

View file

@ -1208,7 +1208,7 @@ impl<'a> State<'a> {
let base_args = args.slice_from(1); let base_args = args.slice_from(1);
try!(self.print_expr(*args.get(0))); try!(self.print_expr(*args.get(0)));
try!(word(&mut self.s, ".")); try!(word(&mut self.s, "."));
try!(self.print_ident(ident)); try!(self.print_ident(ident.node));
if tys.len() > 0u { if tys.len() > 0u {
try!(word(&mut self.s, "::<")); try!(word(&mut self.s, "::<"));
try!(self.commasep(Inconsistent, tys.as_slice(), try!(self.commasep(Inconsistent, tys.as_slice(),

View file

@ -0,0 +1,30 @@
// Copyright 2012-2014 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.
// Test that parameter cardinality or missing method error gets span exactly.
pub struct Foo;
impl Foo {
fn zero(self) -> Foo { self }
fn one(self, _: int) -> Foo { self }
fn two(self, _: int, _: int) -> Foo { self }
}
fn main() {
let x = Foo;
x.zero(0) //~ ERROR this function takes 0 parameters but 1 parameter was supplied
.one() //~ ERROR this function takes 1 parameter but 0 parameters were supplied
.two(0); //~ ERROR this function takes 2 parameters but 1 parameter was supplied
let y = Foo;
y.zero()
.take() //~ ERROR type `Foo` does not implement any method in scope named `take`
.one(0);
}