]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_typeck/check/method/suggest.rs
Auto merge of #30641 - tsion:match-range, r=eddyb
[rust.git] / src / librustc_typeck / check / method / suggest.rs
index 69770cd33b3528dd6b2c3b6f2e507d508df1aa79..65b0d5892756c2790735810db1a975f6daace4a3 100644 (file)
 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;
 
@@ -55,7 +56,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                            mode }) => {
             let cx = fcx.tcx();
 
-            fcx.type_error_message(
+            let mut err = fcx.type_error_struct(
                 span,
                 |actual| {
                     format!("no {} named `{}` found for type `{}` \
@@ -78,17 +79,21 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                         // 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);
@@ -96,19 +101,22 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                     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,
@@ -117,13 +125,13 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                     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!();
                             }
                         }
                     }
@@ -131,11 +139,11 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             }
 
             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() {
@@ -145,7 +153,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                      p))
                     .collect::<Vec<_>>()
                     .join(", ");
-                cx.sess.fileline_note(
+                err.fileline_note(
                     span,
                     &format!("the method `{}` exists but the \
                              following trait bounds were not satisfied: {}",
@@ -153,15 +161,17 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                              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) => {
@@ -181,6 +191,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     }
 
     fn report_candidates(fcx: &FnCtxt,
+                         err: &mut DiagnosticBuilder,
                          span: Span,
                          item_name: ast::Name,
                          mut sources: Vec<CandidateSource>) {
@@ -213,7 +224,7 @@ fn report_candidates(fcx: &FnCtxt,
                         }
                     };
 
-                    span_note!(fcx.sess(), item_span,
+                    span_note!(err, item_span,
                                "candidate #{} is defined in an impl{} for the type `{}`",
                                idx + 1,
                                insertion,
@@ -222,7 +233,7 @@ fn report_candidates(fcx: &FnCtxt,
                 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));
@@ -236,6 +247,7 @@ fn report_candidates(fcx: &FnCtxt,
 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,
@@ -255,14 +267,13 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             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
     }
@@ -301,13 +312,13 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             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)));
         }
     }
 }
@@ -418,32 +429,32 @@ fn visit_item(&mut self, i: &'v hir::Item) {
         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);
     }