diff options
| author | Esteban Kuber <esteban@kuber.com.ar> | 2022-03-27 01:49:01 +0000 |
|---|---|---|
| committer | Esteban Kuber <esteban@kuber.com.ar> | 2022-04-04 21:06:35 +0000 |
| commit | ef91519b45d2bbf0ce8c0180118160562eaaa0ca (patch) | |
| tree | ab798e750270dc35abaadabf38e6946025faf9b8 /compiler/rustc_trait_selection/src/traits | |
| parent | e2bba0708a1e4b0c21f94de56c2bd5d66d3b825f (diff) | |
Dedup logic and improve output for other types that impl trait
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits')
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs | 121 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs | 7 |
2 files changed, 65 insertions, 63 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index fdafb2d3d41..09b445058c0 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -30,7 +30,7 @@ use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::{ - self, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, + self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable, }; use rustc_span::symbol::{kw, sym}; use rustc_span::{ExpnKind, MultiSpan, Span, DUMMY_SP}; @@ -1756,6 +1756,60 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { trait_ref: ty::PolyTraitRef<'tcx>, err: &mut Diagnostic, ) -> bool { + let report = |mut candidates: Vec<TraitRef<'_>>, err: &mut Diagnostic| { + candidates.sort(); + candidates.dedup(); + let len = candidates.len(); + if candidates.len() == 0 { + return false; + } + let trait_ref = candidates[0]; + if candidates.len() == 1 { + err.highlighted_help(vec![ + ( + format!( + "the trait `{}` is implemented for `", + trait_ref.print_only_trait_path() + ), + Style::NoStyle, + ), + (candidates[0].self_ty().to_string(), Style::Highlight), + ("`".to_string(), Style::NoStyle), + ]); + return true; + } + // Check if the trait is the same in all cases. If so, we'll only show the type. + // FIXME: there *has* to be a better way! + let mut traits: Vec<_> = candidates + .iter() + .map(|c| format!("{}", c).split(" as ").last().unwrap().to_string()) + .collect(); + traits.sort(); + traits.dedup(); + + let mut candidates: Vec<String> = candidates + .into_iter() + .map(|c| { + if traits.len() == 1 { + format!("\n {}", c.self_ty()) + } else { + format!("\n {}", c) + } + }) + .collect(); + + candidates.sort(); + candidates.dedup(); + let end = if candidates.len() <= 9 { candidates.len() } else { 8 }; + err.help(&format!( + "the following other types implement trait `{}`:{}{}", + trait_ref.print_only_trait_path(), + candidates[..end].join(""), + if len > 9 { format!("\nand {} others", len - 8) } else { String::new() } + )); + true + }; + let def_id = trait_ref.def_id(); if impl_candidates.is_empty() { if self.tcx.trait_is_auto(def_id) @@ -1765,7 +1819,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { // Mentioning implementers of `Copy`, `Debug` and friends is not useful. return false; } - let mut normalized_impl_candidates: Vec<_> = self + let normalized_impl_candidates: Vec<_> = self .tcx .all_impls(def_id) // Ignore automatically derived impls and `!Trait` impls. @@ -1776,45 +1830,10 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { .filter_map(|def_id| self.tcx.impl_trait_ref(def_id)) // Avoid mentioning type parameters. .filter(|trait_ref| !matches!(trait_ref.self_ty().kind(), ty::Param(_))) - .map(|trait_ref| format!("\n {}", trait_ref.self_ty())) .collect(); - normalized_impl_candidates.sort(); - normalized_impl_candidates.dedup(); - let len = normalized_impl_candidates.len(); - if len == 0 { - return false; - } - if len == 1 { - err.highlighted_help(vec![ - ( - format!( - "the trait `{}` is implemented for `", - trait_ref.print_only_trait_path() - ), - Style::NoStyle, - ), - (normalized_impl_candidates[0].trim().to_string(), Style::Highlight), - ("`".to_string(), Style::NoStyle), - ]); - return true; - } - let end = if normalized_impl_candidates.len() <= 9 { - normalized_impl_candidates.len() - } else { - 8 - }; - err.help(&format!( - "the following other types implement trait `{}`:{}{}", - trait_ref.print_only_trait_path(), - normalized_impl_candidates[..end].join(""), - if len > 9 { format!("\nand {} others", len - 8) } else { String::new() } - )); - return true; + return report(normalized_impl_candidates, err); } - let len = impl_candidates.len(); - let end = if impl_candidates.len() <= 9 { impl_candidates.len() } else { 8 }; - let normalize = |candidate| { self.tcx.infer_ctxt().enter(|ref infcx| { let normalized = infcx @@ -1822,8 +1841,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { .normalize(candidate) .ok(); match normalized { - Some(normalized) => format!("\n {}", normalized.value), - None => format!("\n {}", candidate), + Some(normalized) => normalized.value, + None => candidate, } }) }; @@ -1834,7 +1853,6 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { // // Prefer more similar candidates first, then sort lexicographically // by their normalized string representation. - let first_candidate = impl_candidates.get(0).map(|candidate| candidate.trait_ref); let mut normalized_impl_candidates_and_similarities = impl_candidates .into_iter() .map(|ImplCandidate { trait_ref, similarity }| { @@ -1850,26 +1868,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { .map(|(_, normalized)| normalized) .collect::<Vec<_>>(); - if normalized_impl_candidates.len() == 1 { - err.highlighted_help(vec![ - ( - format!( - "the trait `{}` is implemented for `", - first_candidate.unwrap().print_only_trait_path() - ), - Style::NoStyle, - ), - (first_candidate.unwrap().self_ty().to_string(), Style::Highlight), - ("`".to_string(), Style::NoStyle), - ]); - } else { - err.help(&format!( - "the following implementations were found:{}{}", - normalized_impl_candidates[..end].join(""), - if len > 9 { format!("\nand {} others", len - 8) } else { String::new() } - )); - } - true + report(normalized_impl_candidates, err) } /// Gets the parent trait chain start diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index b369c733871..16ecca254c7 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -557,8 +557,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } } else if real_trait_pred != trait_pred { // This branch addresses #87437. - let obligation = - self.mk_trait_obligation_with_new_self_ty(param_env, real_trait_pred, base_ty); + let obligation = self.mk_trait_obligation_with_new_self_ty( + param_env, + real_trait_pred, + base_ty, + ); if self.predicate_may_hold(&obligation) { err.span_suggestion_verbose( span.shrink_to_lo(), |
