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) => {
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 \
traits for {}",
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);
}
_ => {

View File

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

View File

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

View File

@ -12,7 +12,7 @@ use abi;
use ast::{P, Ident};
use ast;
use ast_util;
use codemap::{Span, respan, DUMMY_SP};
use codemap::{Span, respan, Spanned, DUMMY_SP};
use ext::base::ExtCtxt;
use ext::quote::rt::*;
use fold::Folder;
@ -548,8 +548,9 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
expr: @ast::Expr,
ident: ast::Ident,
mut args: Vec<@ast::Expr> ) -> @ast::Expr {
let id = Spanned { node: ident, span: span };
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 {
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(
folder.fold_ident(i),
respan(i.span, folder.fold_ident(i.node)),
tps.iter().map(|&x| folder.fold_ty(x)).collect(),
args.iter().map(|&x| folder.fold_expr(x)).collect())
}

View File

@ -1646,7 +1646,11 @@ impl<'a> Parser<'a> {
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)
}
@ -1919,6 +1923,7 @@ impl<'a> Parser<'a> {
if self.eat(&token::DOT) {
match self.token {
token::IDENT(i, _) => {
let dot = self.last_span.hi;
hi = self.span.hi;
self.bump();
let (_, tys) = if self.eat(&token::MOD_SEP) {
@ -1940,7 +1945,8 @@ impl<'a> Parser<'a> {
hi = self.last_span.hi;
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);
}
_ => {

View File

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