]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
Use ty::OpaqueTy everywhere
[rust.git] / compiler / rustc_trait_selection / src / traits / error_reporting / mod.rs
index 80870d871d163240f4712caac35722e7ae4c2190..30ff07ee6c372b6df900d11c4f980d5adefe268f 100644 (file)
@@ -1,4 +1,5 @@
 mod ambiguity;
+pub mod method_chain;
 pub mod on_unimplemented;
 pub mod suggestions;
 
@@ -9,7 +10,7 @@
 };
 use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
 use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use crate::infer::{self, InferCtxt, TyCtxtInferExt};
+use crate::infer::{self, InferCtxt};
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
 use crate::traits::query::normalize::QueryNormalizeExt as _;
 use crate::traits::specialize::to_pretty_impl_header;
@@ -536,7 +537,7 @@ fn report_overflow_obligation<T>(
             |err| {
                 self.note_obligation_cause_code(
                     err,
-                    &predicate,
+                    predicate,
                     obligation.param_env,
                     obligation.cause.code(),
                     &mut vec![],
@@ -597,6 +598,7 @@ fn report_selection_error(
                 // can get a better error message by performing HIR-based well-formedness checking.
                 if let ObligationCauseCode::WellFormed(Some(wf_loc)) =
                     root_obligation.cause.code().peel_derives()
+                    && !obligation.predicate.has_non_region_infer()
                 {
                     if let Some(cause) = self
                         .tcx
@@ -1586,7 +1588,7 @@ fn report_fulfillment_error(
                 {
                     self.note_obligation_cause_code(
                         &mut diag,
-                        &error.obligation.predicate,
+                        error.obligation.predicate,
                         error.obligation.param_env,
                         code,
                         &mut vec![],
@@ -1649,7 +1651,7 @@ fn report_projection_error(
                         | ObligationCauseCode::ObjectCastObligation(..)
                         | ObligationCauseCode::OpaqueType
                 );
-                let expected_ty = data.term.ty().unwrap();
+                let expected_ty = data.term.ty().unwrap_or_else(|| self.tcx.ty_error());
 
                 // constrain inference variables a bit more to nested obligations from normalize so
                 // we can have more helpful errors.
@@ -1852,7 +1854,8 @@ fn find_similar_impl_candidates(
         &self,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> Vec<ImplCandidate<'tcx>> {
-        self.tcx
+        let mut candidates: Vec<_> = self
+            .tcx
             .all_impls(trait_pred.def_id())
             .filter_map(|def_id| {
                 if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative
@@ -1868,7 +1871,14 @@ fn find_similar_impl_candidates(
                 self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false)
                     .map(|similarity| ImplCandidate { trait_ref: imp, similarity })
             })
-            .collect()
+            .collect();
+        if candidates.iter().any(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. })) {
+            // If any of the candidates is a perfect match, we don't want to show all of them.
+            // This is particularly relevant for the case of numeric types (as they all have the
+            // same cathegory).
+            candidates.retain(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. }));
+        }
+        candidates
     }
 
     fn report_similar_impl_candidates(
@@ -1976,14 +1986,6 @@ fn report_similar_impl_candidates(
             return report(normalized_impl_candidates, err);
         }
 
-        let normalize = |candidate| {
-            let infcx = self.tcx.infer_ctxt().build();
-            infcx
-                .at(&ObligationCause::dummy(), ty::ParamEnv::empty())
-                .query_normalize(candidate)
-                .map_or(candidate, |normalized| normalized.value)
-        };
-
         // Sort impl candidates so that ordering is consistent for UI tests.
         // because the ordering of `impl_candidates` may not be deterministic:
         // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507
@@ -1993,7 +1995,11 @@ fn report_similar_impl_candidates(
         let mut normalized_impl_candidates_and_similarities = impl_candidates
             .into_iter()
             .map(|ImplCandidate { trait_ref, similarity }| {
-                let normalized = normalize(trait_ref);
+                // FIXME(compiler-errors): This should be using `NormalizeExt::normalize`
+                let normalized = self
+                    .at(&ObligationCause::dummy(), ty::ParamEnv::empty())
+                    .query_normalize(trait_ref)
+                    .map_or(trait_ref, |normalized| normalized.value);
                 (similarity, normalized)
             })
             .collect::<Vec<_>>();
@@ -2597,7 +2603,7 @@ fn note_obligation_cause(&self, err: &mut Diagnostic, obligation: &PredicateObli
         if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
             self.note_obligation_cause_code(
                 err,
-                &obligation.predicate,
+                obligation.predicate,
                 obligation.param_env,
                 obligation.cause.code(),
                 &mut vec![],