]> git.lizzy.rs Git - rust.git/commitdiff
clean the note-reporting code in report_selection_error
authorAriel Ben-Yehuda <ariel.byd@gmail.com>
Tue, 5 Apr 2016 20:19:29 +0000 (23:19 +0300)
committerAriel Ben-Yehuda <ariel.byd@gmail.com>
Tue, 5 Apr 2016 20:25:09 +0000 (23:25 +0300)
src/librustc/traits/error_reporting.rs

index dfe3f91c7b158e5b373d89cbf2260bf52760da52..5b5bea012ead0246fa96e9f8d6926b7a8b82f920 100644 (file)
@@ -174,6 +174,53 @@ trait definition for {} must have a value, \
     report
 }
 
+fn find_similar_impl_candidates<'a, 'tcx>(
+    infcx: &InferCtxt<'a, 'tcx>,
+    trait_ref: ty::PolyTraitRef<'tcx>)
+    -> Vec<ty::TraitRef<'tcx>>
+{
+    let simp = fast_reject::simplify_type(infcx.tcx,
+                                          trait_ref.skip_binder().self_ty(),
+                                          true);
+    let mut impl_candidates = Vec::new();
+    let trait_def = infcx.tcx.lookup_trait_def(trait_ref.def_id());
+
+    match simp {
+        Some(simp) => trait_def.for_each_impl(infcx.tcx, |def_id| {
+            let imp = infcx.tcx.impl_trait_ref(def_id).unwrap();
+            let imp_simp = fast_reject::simplify_type(infcx.tcx,
+                                                      imp.self_ty(),
+                                                      true);
+            if let Some(imp_simp) = imp_simp {
+                if simp != imp_simp {
+                    return;
+                }
+            }
+            impl_candidates.push(imp);
+        }),
+        None => trait_def.for_each_impl(infcx.tcx, |def_id| {
+            impl_candidates.push(
+                infcx.tcx.impl_trait_ref(def_id).unwrap());
+        })
+    };
+    impl_candidates
+}
+
+fn report_similar_impl_candidates(span: Span,
+                                  err: &mut DiagnosticBuilder,
+                                  impl_candidates: &[ty::TraitRef])
+{
+    err.fileline_help(span, &format!("the following implementations were found:"));
+
+    let end = cmp::min(4, impl_candidates.len());
+    for candidate in &impl_candidates[0..end] {
+        err.fileline_help(span, &format!("  {:?}", candidate));
+    }
+    if impl_candidates.len() > 4 {
+        err.fileline_help(span, &format!("and {} others", impl_candidates.len()-4));
+    }
+}
+
 /// Reports that an overflow has occurred and halts compilation. We
 /// halt compilation unconditionally because it is important that
 /// overflows never be masked -- they basically represent computations
@@ -364,59 +411,35 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                 "the trait bound `{}` is not satisfied",
                                 trait_ref.to_predicate());
 
-                            // Try to report a good error message.
+                            // Try to report a help message
 
                             if !trait_ref.has_infer_types() &&
                                 predicate_can_apply(infcx, trait_ref)
                             {
+                                // If a where-clause may be useful, remind the
+                                // user that they can add it.
+                                //
+                                // don't display an on-unimplemented note, as
+                                // these notes will often be of the form
+                                //     "the type `T` can't be frobnicated"
+                                // which is somewhat confusing.
                                 err.fileline_help(obligation.cause.span, &format!(
                                     "consider adding a `where {}` bound",
                                     trait_ref.to_predicate()
                                     ));
                             } else if let Some(s) = on_unimplemented_note(infcx, trait_ref,
                                                                           obligation.cause.span) {
+                                // Otherwise, if there is an on-unimplemented note,
+                                // display it.
                                 err.fileline_note(obligation.cause.span, &s);
                             } else {
-                                let simp = fast_reject::simplify_type(infcx.tcx,
-                                                                      trait_ref.self_ty(),
-                                                                      true);
-                                let mut impl_candidates = Vec::new();
-                                let trait_def = infcx.tcx.lookup_trait_def(trait_ref.def_id());
-
-                                match simp {
-                                    Some(simp) => trait_def.for_each_impl(infcx.tcx, |def_id| {
-                                        let imp = infcx.tcx.impl_trait_ref(def_id).unwrap();
-                                        let imp_simp = fast_reject::simplify_type(infcx.tcx,
-                                                                                  imp.self_ty(),
-                                                                                  true);
-                                        if let Some(imp_simp) = imp_simp {
-                                            if simp != imp_simp {
-                                                return;
-                                            }
-                                        }
-                                        impl_candidates.push(imp);
-                                    }),
-                                    None => trait_def.for_each_impl(infcx.tcx, |def_id| {
-                                        impl_candidates.push(
-                                            infcx.tcx.impl_trait_ref(def_id).unwrap());
-                                    })
-                                };
+                                // If we can't show anything useful, try to find
+                                // similar impls.
 
+                                let impl_candidates = find_similar_impl_candidates(infcx, trait_ref);
                                 if impl_candidates.len() > 0 {
-                                    err.fileline_help(
-                                        obligation.cause.span,
-                                        &format!("the following implementations were found:"));
-
-                                    let end = cmp::min(4, impl_candidates.len());
-                                    for candidate in &impl_candidates[0..end] {
-                                        err.fileline_help(obligation.cause.span,
-                                                          &format!("  {:?}", candidate));
-                                    }
-                                    if impl_candidates.len() > 4 {
-                                        err.fileline_help(obligation.cause.span,
-                                                          &format!("and {} others",
-                                                                   impl_candidates.len()-4));
-                                    }
+                                    report_similar_impl_candidates(obligation.cause.span,
+                                                                   &mut err, &impl_candidates);
                                 }
                             }
                             note_obligation_cause(infcx, &mut err, obligation);