diff options
| author | Huon Wilson <dbau.pp+github@gmail.com> | 2015-01-13 17:05:04 +1100 |
|---|---|---|
| committer | Huon Wilson <dbau.pp+github@gmail.com> | 2015-01-13 17:05:04 +1100 |
| commit | af506fa5d15b892c2fa6df442e106e1afcb7abca (patch) | |
| tree | 54fb90d44f37b8fedb8a202e60c602e6e9fc0fe8 /src | |
| parent | 3d5fbae33897a8340542f21b6ded913148ca9199 (diff) | |
| download | rust-af506fa5d15b892c2fa6df442e106e1afcb7abca.tar.gz rust-af506fa5d15b892c2fa6df442e106e1afcb7abca.zip | |
typeck: move method errors/suggestions to their own file.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_typeck/check/method/mod.rs | 105 | ||||
| -rw-r--r-- | src/librustc_typeck/check/method/suggest.rs | 122 |
2 files changed, 126 insertions, 101 deletions
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 0c53a16a811..8637a915305 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -12,7 +12,6 @@ use astconv::AstConv; use check::{FnCtxt}; -use check::{impl_self_ty}; use check::vtable; use check::vtable::select_new_fcx_obligations; use middle::subst; @@ -20,7 +19,7 @@ use middle::traits; use middle::ty::*; use middle::ty; use middle::infer; -use util::ppaux::{Repr, UserString}; +use util::ppaux::Repr; use std::rc::Rc; use syntax::ast::{DefId}; @@ -30,9 +29,12 @@ use syntax::codemap::Span; pub use self::MethodError::*; pub use self::CandidateSource::*; +pub use self::suggest::report_error; + mod confirm; mod doc; mod probe; +mod suggest; pub enum MethodError { // Did not find an applicable method, but we did find various @@ -294,105 +296,6 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, Some(callee) } -pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, - span: Span, - rcvr_ty: Ty<'tcx>, - method_name: ast::Name, - error: MethodError) -{ - match error { - NoMatch(static_sources) => { - let cx = fcx.tcx(); - let method_ustring = method_name.user_string(cx); - - // True if the type is a struct and contains a field with - // the same name as the not-found method - let is_field = match rcvr_ty.sty { - ty_struct(did, _) => - ty::lookup_struct_fields(cx, did) - .iter() - .any(|f| f.name.user_string(cx) == method_ustring), - _ => false - }; - - fcx.type_error_message( - span, - |actual| { - format!("type `{}` does not implement any \ - method in scope named `{}`", - actual, - method_ustring) - }, - rcvr_ty, - None); - - // If the method has the name of a field, give a help note - if is_field { - cx.sess.span_note(span, - &format!("use `(s.{0})(...)` if you meant to call the \ - function stored in the `{0}` field", method_ustring)[]); - } - - if static_sources.len() > 0 { - fcx.tcx().sess.fileline_note( - span, - "found defined static methods, maybe a `self` is missing?"); - - report_candidates(fcx, span, method_name, static_sources); - } - } - - Ambiguity(sources) => { - span_err!(fcx.sess(), span, E0034, - "multiple applicable methods in scope"); - - report_candidates(fcx, span, method_name, sources); - } - } - - fn report_candidates(fcx: &FnCtxt, - span: Span, - method_name: ast::Name, - mut sources: Vec<CandidateSource>) { - sources.sort(); - sources.dedup(); - - for (idx, source) in sources.iter().enumerate() { - match *source { - ImplSource(impl_did) => { - // Provide the best span we can. Use the method, if local to crate, else - // the impl, if local to crate (method may be defaulted), else the call site. - let method = impl_method(fcx.tcx(), impl_did, method_name).unwrap(); - let impl_span = fcx.tcx().map.def_id_span(impl_did, span); - let method_span = fcx.tcx().map.def_id_span(method.def_id, impl_span); - - let impl_ty = impl_self_ty(fcx, span, impl_did).ty; - - let insertion = match impl_trait_ref(fcx.tcx(), impl_did) { - None => format!(""), - Some(trait_ref) => format!(" of the trait `{}`", - ty::item_path_str(fcx.tcx(), - trait_ref.def_id)), - }; - - span_note!(fcx.sess(), method_span, - "candidate #{} is defined in an impl{} for the type `{}`", - idx + 1u, - insertion, - impl_ty.user_string(fcx.tcx())); - } - TraitSource(trait_did) => { - let (_, method) = trait_method(fcx.tcx(), trait_did, method_name).unwrap(); - let method_span = fcx.tcx().map.def_id_span(method.def_id, span); - span_note!(fcx.sess(), method_span, - "candidate #{} is defined in the trait `{}`", - idx + 1u, - ty::item_path_str(fcx.tcx(), trait_did)); - } - } - } - } -} /// Find method with name `method_name` defined in `trait_def_id` and return it, along with its /// index (or `None`, if no such method). diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs new file mode 100644 index 00000000000..b6d97d2df9d --- /dev/null +++ b/src/librustc_typeck/check/method/suggest.rs @@ -0,0 +1,122 @@ +// Copyright 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. + +//! Give useful errors and suggestions to users when a method can't be +//! found or is otherwise invalid. + +use astconv::AstConv; +use check::{self, FnCtxt}; +use middle::ty::{self, Ty}; +use util::ppaux::UserString; + +use syntax::ast; +use syntax::codemap::Span; + +use super::{MethodError, CandidateSource, impl_method, trait_method}; + +pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, + span: Span, + rcvr_ty: Ty<'tcx>, + method_name: ast::Name, + error: MethodError) +{ + match error { + MethodError::NoMatch(static_sources) => { + let cx = fcx.tcx(); + let method_ustring = method_name.user_string(cx); + + // True if the type is a struct and contains a field with + // the same name as the not-found method + let is_field = match rcvr_ty.sty { + ty::ty_struct(did, _) => + ty::lookup_struct_fields(cx, did) + .iter() + .any(|f| f.name.user_string(cx) == method_ustring), + _ => false + }; + + fcx.type_error_message( + span, + |actual| { + format!("type `{}` does not implement any \ + method in scope named `{}`", + actual, + method_ustring) + }, + rcvr_ty, + None); + + // If the method has the name of a field, give a help note + if is_field { + cx.sess.span_note(span, + &format!("use `(s.{0})(...)` if you meant to call the \ + function stored in the `{0}` field", method_ustring)[]); + } + + if static_sources.len() > 0 { + fcx.tcx().sess.fileline_note( + span, + "found defined static methods, maybe a `self` is missing?"); + + report_candidates(fcx, span, method_name, static_sources); + } + } + + MethodError::Ambiguity(sources) => { + span_err!(fcx.sess(), span, E0034, + "multiple applicable methods in scope"); + + report_candidates(fcx, span, method_name, sources); + } + } + + fn report_candidates(fcx: &FnCtxt, + span: Span, + method_name: ast::Name, + mut sources: Vec<CandidateSource>) { + sources.sort(); + sources.dedup(); + + for (idx, source) in sources.iter().enumerate() { + match *source { + CandidateSource::ImplSource(impl_did) => { + // Provide the best span we can. Use the method, if local to crate, else + // the impl, if local to crate (method may be defaulted), else the call site. + let method = impl_method(fcx.tcx(), impl_did, method_name).unwrap(); + let impl_span = fcx.tcx().map.def_id_span(impl_did, span); + let method_span = fcx.tcx().map.def_id_span(method.def_id, impl_span); + + let impl_ty = check::impl_self_ty(fcx, span, impl_did).ty; + + let insertion = match ty::impl_trait_ref(fcx.tcx(), impl_did) { + None => format!(""), + Some(trait_ref) => format!(" of the trait `{}`", + ty::item_path_str(fcx.tcx(), + trait_ref.def_id)), + }; + + span_note!(fcx.sess(), method_span, + "candidate #{} is defined in an impl{} for the type `{}`", + idx + 1u, + insertion, + impl_ty.user_string(fcx.tcx())); + } + CandidateSource::TraitSource(trait_did) => { + let (_, method) = trait_method(fcx.tcx(), trait_did, method_name).unwrap(); + let method_span = fcx.tcx().map.def_id_span(method.def_id, span); + span_note!(fcx.sess(), method_span, + "candidate #{} is defined in the trait `{}`", + idx + 1u, + ty::item_path_str(fcx.tcx(), trait_did)); + } + } + } + } +} |
