use check::{self, FnCtxt};
use front::map as hir_map;
use middle::ty::{self, Ty, ToPolyTraitRef, ToPredicate, HasTypeFlags};
+use middle::cstore::{self, CrateStore, DefLike};
use middle::def;
use middle::def_id::DefId;
use middle::lang_items::FnOnceTraitLangItem;
use middle::subst::Substs;
use middle::traits::{Obligation, SelectionContext};
-use metadata::{csearch, cstore, decoder};
use util::nodemap::{FnvHashSet};
use syntax::ast;
use syntax::codemap::Span;
+use syntax::errors::DiagnosticBuilder;
use rustc_front::print::pprust;
use rustc_front::hir;
mode }) => {
let cx = fcx.tcx();
- fcx.type_error_message(
+ let mut err = fcx.type_error_struct(
span,
|actual| {
format!("no {} named `{}` found for type `{}` \
// snippet
};
- let span_stored_function = || {
- cx.sess.span_note(span,
+ macro_rules! span_stored_function {
+ () => {
+ err.span_note(span,
&format!("use `({0}.{1})(...)` if you meant to call \
the function stored in the `{1}` field",
expr_string, item_name));
- };
+ }
+ }
- let span_did_you_mean = || {
- cx.sess.span_note(span, &format!("did you mean to write `{0}.{1}`?",
+ macro_rules! span_did_you_mean {
+ () => {
+ err.span_note(span, &format!("did you mean to write `{0}.{1}`?",
expr_string, item_name));
- };
+ }
+ }
// Determine if the field can be used as a function in some way
let field_ty = field.ty(cx, substs);
match field_ty.sty {
// Not all of these (e.g. unsafe fns) implement FnOnce
// so we look for these beforehand
- ty::TyClosure(..) | ty::TyBareFn(..) => span_stored_function(),
+ ty::TyClosure(..) | ty::TyBareFn(..) => {
+ span_stored_function!();
+ }
// If it's not a simple function, look for things which implement FnOnce
_ => {
if let Ok(fn_once_trait_did) =
cx.lang_items.require(FnOnceTraitLangItem) {
let infcx = fcx.infcx();
infcx.probe(|_| {
- let fn_once_substs = Substs::new_trait(vec![
- infcx.next_ty_var()],
- Vec::new(),
- field_ty);
- let trait_ref = ty::TraitRef::new(fn_once_trait_did,
- cx.mk_substs(fn_once_substs));
+ let fn_once_substs =
+ Substs::new_trait(vec![infcx.next_ty_var()],
+ Vec::new(),
+ field_ty);
+ let trait_ref =
+ ty::TraitRef::new(fn_once_trait_did,
+ cx.mk_substs(fn_once_substs));
let poly_trait_ref = trait_ref.to_poly_trait_ref();
let obligation = Obligation::misc(span,
fcx.body_id,
let mut selcx = SelectionContext::new(infcx);
if selcx.evaluate_obligation(&obligation) {
- span_stored_function();
+ span_stored_function!();
} else {
- span_did_you_mean();
+ span_did_you_mean!();
}
});
} else {
- span_did_you_mean()
+ span_did_you_mean!();
}
}
}
}
if !static_sources.is_empty() {
- cx.sess.fileline_note(
+ err.fileline_note(
span,
"found defined static methods, maybe a `self` is missing?");
- report_candidates(fcx, span, item_name, static_sources);
+ report_candidates(fcx, &mut err, span, item_name, static_sources);
}
if !unsatisfied_predicates.is_empty() {
p))
.collect::<Vec<_>>()
.join(", ");
- cx.sess.fileline_note(
+ err.fileline_note(
span,
&format!("the method `{}` exists but the \
following trait bounds were not satisfied: {}",
bound_list));
}
- suggest_traits_to_import(fcx, span, rcvr_ty, item_name,
- rcvr_expr, out_of_scope_traits)
+ suggest_traits_to_import(fcx, &mut err, span, rcvr_ty, item_name,
+ rcvr_expr, out_of_scope_traits);
+ err.emit();
}
MethodError::Ambiguity(sources) => {
- span_err!(fcx.sess(), span, E0034,
- "multiple applicable items in scope");
+ let mut err = struct_span_err!(fcx.sess(), span, E0034,
+ "multiple applicable items in scope");
- report_candidates(fcx, span, item_name, sources);
+ report_candidates(fcx, &mut err, span, item_name, sources);
+ err.emit();
}
MethodError::ClosureAmbiguity(trait_def_id) => {
}
fn report_candidates(fcx: &FnCtxt,
+ err: &mut DiagnosticBuilder,
span: Span,
item_name: ast::Name,
mut sources: Vec<CandidateSource>) {
}
};
- span_note!(fcx.sess(), item_span,
+ span_note!(err, item_span,
"candidate #{} is defined in an impl{} for the type `{}`",
idx + 1,
insertion,
CandidateSource::TraitSource(trait_did) => {
let item = trait_item(fcx.tcx(), trait_did, item_name).unwrap();
let item_span = fcx.tcx().map.def_id_span(item.def_id(), span);
- span_note!(fcx.sess(), item_span,
+ span_note!(err, item_span,
"candidate #{} is defined in the trait `{}`",
idx + 1,
fcx.tcx().item_path_str(trait_did));
pub type AllTraitsVec = Vec<TraitInfo>;
fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ err: &mut DiagnosticBuilder,
span: Span,
rcvr_ty: Ty<'tcx>,
item_name: ast::Name,
traits_are = if candidates.len() == 1 {"trait is"} else {"traits are"},
one_of_them = if candidates.len() == 1 {"it"} else {"one of them"});
- fcx.sess().fileline_help(span, &msg[..]);
+ err.fileline_help(span, &msg[..]);
for (i, trait_did) in candidates.iter().enumerate() {
- fcx.sess().fileline_help(span,
- &*format!("candidate #{}: use `{}`",
- i + 1,
- fcx.tcx().item_path_str(*trait_did)))
-
+ err.fileline_help(span,
+ &*format!("candidate #{}: use `{}`",
+ i + 1,
+ fcx.tcx().item_path_str(*trait_did)));
}
return
}
one_of_them = if candidates.len() == 1 {"it"} else {"one of them"},
name = item_name);
- fcx.sess().fileline_help(span, &msg[..]);
+ err.fileline_help(span, &msg[..]);
for (i, trait_info) in candidates.iter().enumerate() {
- fcx.sess().fileline_help(span,
- &*format!("candidate #{}: `{}`",
- i + 1,
- fcx.tcx().item_path_str(trait_info.def_id)))
+ err.fileline_help(span,
+ &*format!("candidate #{}: `{}`",
+ i + 1,
+ fcx.tcx().item_path_str(trait_info.def_id)));
}
}
}
/// Retrieve all traits in this crate and any dependent crates.
pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> {
if ccx.all_traits.borrow().is_none() {
- use rustc_front::visit;
+ use rustc_front::intravisit;
let mut traits = vec![];
map: &'a hir_map::Map<'tcx>,
traits: &'a mut AllTraitsVec,
}
- impl<'v, 'a, 'tcx> visit::Visitor<'v> for Visitor<'a, 'tcx> {
+ impl<'v, 'a, 'tcx> intravisit::Visitor<'v> for Visitor<'a, 'tcx> {
fn visit_item(&mut self, i: &'v hir::Item) {
match i.node {
hir::ItemTrait(..) => {
}
_ => {}
}
- visit::walk_item(self, i)
}
}
- visit::walk_crate(&mut Visitor {
+ ccx.tcx.map.krate().visit_all_items(&mut Visitor {
map: &ccx.tcx.map,
traits: &mut traits
- }, ccx.tcx.map.krate());
+ });
// Cross-crate:
let mut external_mods = FnvHashSet();
fn handle_external_def(traits: &mut AllTraitsVec,
external_mods: &mut FnvHashSet<DefId>,
ccx: &CrateCtxt,
- cstore: &cstore::CStore,
- dl: decoder::DefLike) {
+ cstore: &for<'a> cstore::CrateStore<'a>,
+ dl: cstore::DefLike) {
match dl {
- decoder::DlDef(def::DefTrait(did)) => {
+ cstore::DlDef(def::DefTrait(did)) => {
traits.push(TraitInfo::new(did));
}
- decoder::DlDef(def::DefMod(did)) => {
+ cstore::DlDef(def::DefMod(did)) => {
if !external_mods.insert(did) {
return;
}
- csearch::each_child_of_item(cstore, did, |dl, _, _| {
+ for child in cstore.item_children(did) {
handle_external_def(traits, external_mods,
- ccx, cstore, dl)
- })
+ ccx, cstore, child.def)
+ }
}
_ => {}
}
}
- let cstore = &ccx.tcx.sess.cstore;
- cstore.iter_crate_data(|cnum, _| {
- csearch::each_top_level_item_of_crate(cstore, cnum, |dl, _, _| {
- handle_external_def(&mut traits,
- &mut external_mods,
- ccx, cstore, dl)
- })
- });
+ let cstore = &*ccx.tcx.sess.cstore;
+
+ for cnum in ccx.tcx.sess.cstore.crates() {
+ for child in cstore.crate_top_level_items(cnum) {
+ handle_external_def(&mut traits, &mut external_mods,
+ ccx, cstore, child.def)
+ }
+ }
*ccx.all_traits.borrow_mut() = Some(traits);
}