Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't call query_normalize when reporting similar impls #113005

Merged
merged 2 commits into from
Jul 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 34 additions & 32 deletions compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCod
use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
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;
use crate::traits::NormalizeExt;
use on_unimplemented::{AppendConstMessage, OnUnimplementedNote, TypeErrCtxtExt as _};
Expand All @@ -31,7 +30,7 @@ use rustc_middle::traits::select::OverflowError;
use rustc_middle::traits::SelectionOutputTypeParameterMismatch;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print};
use rustc_middle::ty::{
self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
Expand Down Expand Up @@ -60,7 +59,7 @@ pub enum CandidateSimilarity {
Fuzzy { ignoring_lifetimes: bool },
}

#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ImplCandidate<'tcx> {
pub trait_ref: ty::TraitRef<'tcx>,
pub similarity: CandidateSimilarity,
Expand Down Expand Up @@ -1927,10 +1926,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
other: bool,
) -> bool {
let other = if other { "other " } else { "" };
let report = |mut candidates: Vec<TraitRef<'tcx>>, err: &mut Diagnostic| {
candidates.sort();
candidates.dedup();
let len = candidates.len();
let report = |candidates: Vec<TraitRef<'tcx>>, err: &mut Diagnostic| {
if candidates.is_empty() {
return false;
}
Expand Down Expand Up @@ -1959,26 +1955,31 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
candidates.iter().map(|c| c.print_only_trait_path().to_string()).collect();
traits.sort();
traits.dedup();
// FIXME: this could use a better heuristic, like just checking
// that substs[1..] is the same.
let all_traits_equal = traits.len() == 1;

let mut candidates: Vec<String> = candidates
let candidates: Vec<String> = candidates
.into_iter()
.map(|c| {
if traits.len() == 1 {
if all_traits_equal {
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() }
if candidates.len() > 9 {
format!("\nand {} others", candidates.len() - 8)
} else {
String::new()
}
));
true
};
Expand All @@ -1992,7 +1993,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Mentioning implementers of `Copy`, `Debug` and friends is not useful.
return false;
}
let normalized_impl_candidates: Vec<_> = self
let mut impl_candidates: Vec<_> = self
.tcx
.all_impls(def_id)
// Ignore automatically derived impls and `!Trait` impls.
Expand All @@ -2019,7 +2020,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
})
.collect();
return report(normalized_impl_candidates, err);

impl_candidates.sort();
impl_candidates.dedup();
return report(impl_candidates, err);
}

// Sort impl candidates so that ordering is consistent for UI tests.
Expand All @@ -2028,27 +2032,25 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
//
// Prefer more similar candidates first, then sort lexicographically
// by their normalized string representation.
let mut normalized_impl_candidates_and_similarities = impl_candidates
let mut impl_candidates: Vec<_> = impl_candidates
.iter()
.copied()
.map(|ImplCandidate { trait_ref, similarity }| {
// 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)
.cloned()
.map(|mut cand| {
// Fold the consts so that they shows up as, e.g., `10`
// instead of `core::::array::{impl#30}::{constant#0}`.
cand.trait_ref = cand.trait_ref.fold_with(&mut BottomUpFolder {
tcx: self.tcx,
ty_op: |ty| ty,
lt_op: |lt| lt,
ct_op: |ct| ct.eval(self.tcx, ty::ParamEnv::empty()),
});
cand
})
.collect::<Vec<_>>();
normalized_impl_candidates_and_similarities.sort();
normalized_impl_candidates_and_similarities.dedup();

let normalized_impl_candidates = normalized_impl_candidates_and_similarities
.into_iter()
.map(|(_, normalized)| normalized)
.collect::<Vec<_>>();
.collect();
impl_candidates.sort_by_key(|cand| (cand.similarity, cand.trait_ref));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this useful? report sorts everything again.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the sort in report -- that should fix the weird rendering and also actually make this sort meaningful. It does have a lot of fallout, but the changes are either neutral or slightly better suggestions.

impl_candidates.dedup();

report(normalized_impl_candidates, err)
report(impl_candidates.into_iter().map(|cand| cand.trait_ref).collect(), err)
}

fn report_similar_impl_candidates_for_root_obligation(
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/binop/binop-mul-i32-f32.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ LL | x * y
|
= help: the trait `Mul<f32>` is not implemented for `i32`
= help: the following other types implement trait `Mul<Rhs>`:
<i32 as Mul>
<i32 as Mul<&i32>>
<&'a i32 as Mul<i32>>
<&i32 as Mul<&i32>>
<i32 as Mul<&i32>>
<i32 as Mul>

error: aborting due to previous error

Expand Down
48 changes: 24 additions & 24 deletions tests/ui/binop/shift-various-bad-types.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ LL | 22 >> p.char;
|
= help: the trait `Shr<char>` is not implemented for `{integer}`
= help: the following other types implement trait `Shr<Rhs>`:
<&'a i128 as Shr<i128>>
<&'a i128 as Shr<i16>>
<&'a i128 as Shr<i32>>
<&'a i128 as Shr<i64>>
<&'a i128 as Shr<i8>>
<&'a i128 as Shr<isize>>
<&'a i128 as Shr<u128>>
<&'a i128 as Shr<u16>>
<isize as Shr>
<isize as Shr<i8>>
<isize as Shr<i16>>
<isize as Shr<i32>>
<isize as Shr<i64>>
<isize as Shr<i128>>
<isize as Shr<usize>>
<isize as Shr<u8>>
and 568 others

error[E0277]: no implementation for `{integer} >> &str`
Expand All @@ -24,14 +24,14 @@ LL | 22 >> p.str;
|
= help: the trait `Shr<&str>` is not implemented for `{integer}`
= help: the following other types implement trait `Shr<Rhs>`:
<&'a i128 as Shr<i128>>
<&'a i128 as Shr<i16>>
<&'a i128 as Shr<i32>>
<&'a i128 as Shr<i64>>
<&'a i128 as Shr<i8>>
<&'a i128 as Shr<isize>>
<&'a i128 as Shr<u128>>
<&'a i128 as Shr<u16>>
<isize as Shr>
<isize as Shr<i8>>
<isize as Shr<i16>>
<isize as Shr<i32>>
<isize as Shr<i64>>
<isize as Shr<i128>>
<isize as Shr<usize>>
<isize as Shr<u8>>
and 568 others

error[E0277]: no implementation for `{integer} >> &Panolpy`
Expand All @@ -42,14 +42,14 @@ LL | 22 >> p;
|
= help: the trait `Shr<&Panolpy>` is not implemented for `{integer}`
= help: the following other types implement trait `Shr<Rhs>`:
<&'a i128 as Shr<i128>>
<&'a i128 as Shr<i16>>
<&'a i128 as Shr<i32>>
<&'a i128 as Shr<i64>>
<&'a i128 as Shr<i8>>
<&'a i128 as Shr<isize>>
<&'a i128 as Shr<u128>>
<&'a i128 as Shr<u16>>
<isize as Shr>
<isize as Shr<i8>>
<isize as Shr<i16>>
<isize as Shr<i32>>
<isize as Shr<i64>>
<isize as Shr<i128>>
<isize as Shr<usize>>
<isize as Shr<u8>>
and 568 others

error[E0308]: mismatched types
Expand Down
14 changes: 7 additions & 7 deletions tests/ui/const-generics/exhaustive-value.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ LL | <() as Foo<N>>::test()
|
= help: the following other types implement trait `Foo<N>`:
<() as Foo<0>>
<() as Foo<100>>
<() as Foo<101>>
<() as Foo<102>>
<() as Foo<103>>
<() as Foo<104>>
<() as Foo<105>>
<() as Foo<106>>
<() as Foo<1>>
<() as Foo<2>>
<() as Foo<3>>
<() as Foo<4>>
<() as Foo<5>>
<() as Foo<6>>
<() as Foo<7>>
and 248 others

error: aborting due to previous error
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/const-generics/generic_arg_infer/issue-91614.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ LL | let y = Mask::<_, _>::splat(false);
|
= note: cannot satisfy `_: MaskElement`
= help: the following types implement trait `MaskElement`:
isize
i8
i16
i32
i64
i8
isize
note: required by a bound in `Mask::<T, LANES>::splat`
--> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/masks.rs:LL:COL
help: consider giving `y` an explicit type, where the type for type parameter `T` is specified
Expand Down
12 changes: 6 additions & 6 deletions tests/ui/const-generics/issues/issue-67185-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ LL | <u8 as Baz>::Quaks: Bar,
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `[u16; 3]`
|
= help: the following other types implement trait `Bar`:
[[u16; 3]; 3]
[u16; 4]
[[u16; 3]; 3]
= help: see issue #48214
= help: add `#![feature(trivial_bounds)]` to the crate attributes to enable

Expand All @@ -17,8 +17,8 @@ LL | [<u8 as Baz>::Quaks; 2]: Bar,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`
|
= help: the following other types implement trait `Bar`:
[[u16; 3]; 3]
[u16; 4]
[[u16; 3]; 3]
= help: see issue #48214
= help: add `#![feature(trivial_bounds)]` to the crate attributes to enable

Expand All @@ -29,8 +29,8 @@ LL | impl Foo for FooImpl {}
| ^^^ the trait `Bar` is not implemented for `[u16; 3]`
|
= help: the following other types implement trait `Bar`:
[[u16; 3]; 3]
[u16; 4]
[[u16; 3]; 3]
note: required by a bound in `Foo`
--> $DIR/issue-67185-2.rs:15:25
|
Expand All @@ -47,8 +47,8 @@ LL | impl Foo for FooImpl {}
| ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`
|
= help: the following other types implement trait `Bar`:
[[u16; 3]; 3]
[u16; 4]
[[u16; 3]; 3]
note: required by a bound in `Foo`
--> $DIR/issue-67185-2.rs:14:30
|
Expand All @@ -65,8 +65,8 @@ LL | fn f(_: impl Foo) {}
| ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`
|
= help: the following other types implement trait `Bar`:
[[u16; 3]; 3]
[u16; 4]
[[u16; 3]; 3]
note: required by a bound in `Foo`
--> $DIR/issue-67185-2.rs:14:30
|
Expand All @@ -83,8 +83,8 @@ LL | fn f(_: impl Foo) {}
| ^^^ the trait `Bar` is not implemented for `[u16; 3]`
|
= help: the following other types implement trait `Bar`:
[[u16; 3]; 3]
[u16; 4]
[[u16; 3]; 3]
note: required by a bound in `Foo`
--> $DIR/issue-67185-2.rs:15:25
|
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/consts/const-eval/const-eval-overflow-3b.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ LL | = [0; (i8::MAX + 1u8) as usize];
|
= help: the trait `Add<u8>` is not implemented for `i8`
= help: the following other types implement trait `Add<Rhs>`:
<i8 as Add>
<i8 as Add<&i8>>
<&'a i8 as Add<i8>>
<&i8 as Add<&i8>>
<i8 as Add<&i8>>
<i8 as Add>

error: aborting due to 2 previous errors

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/consts/const-eval/const-eval-overflow-4b.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ LL | : [u32; (i8::MAX as i8 + 1u8) as usize]
|
= help: the trait `Add<u8>` is not implemented for `i8`
= help: the following other types implement trait `Add<Rhs>`:
<i8 as Add>
<i8 as Add<&i8>>
<&'a i8 as Add<i8>>
<&i8 as Add<&i8>>
<i8 as Add<&i8>>
<i8 as Add>

error[E0604]: only `u8` can be cast as `char`, not `i8`
--> $DIR/const-eval-overflow-4b.rs:22:13
Expand Down
9 changes: 9 additions & 0 deletions tests/ui/consts/missing-larger-array-impl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
struct X;

// Make sure that we show the impl trait refs in the help message with
// their evaluated constants, rather than `core::::array::{impl#30}::{constant#0}`

fn main() {
<[X; 35] as Default>::default();
//~^ ERROR the trait bound `[X; 35]: Default` is not satisfied
}
20 changes: 20 additions & 0 deletions tests/ui/consts/missing-larger-array-impl.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error[E0277]: the trait bound `[X; 35]: Default` is not satisfied
--> $DIR/missing-larger-array-impl.rs:7:5
|
LL | <[X; 35] as Default>::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `[X; 35]`
|
= help: the following other types implement trait `Default`:
[T; 0]
[T; 1]
[T; 2]
[T; 3]
[T; 4]
[T; 5]
[T; 6]
[T; 7]
and 27 others

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
12 changes: 6 additions & 6 deletions tests/ui/consts/too_generic_eval_ice.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ LL | [5; Self::HOST_SIZE] == [6; 0]
|
= help: the trait `PartialEq<[{integer}; 0]>` is not implemented for `[{integer}; Self::HOST_SIZE]`
= help: the following other types implement trait `PartialEq<Rhs>`:
<&[B] as PartialEq<[A; N]>>
<&[T] as PartialEq<Vec<U, A>>>
<&mut [B] as PartialEq<[A; N]>>
<&mut [T] as PartialEq<Vec<U, A>>>
<[A; N] as PartialEq<&[B]>>
<[A; N] as PartialEq<&mut [B]>>
<[A; N] as PartialEq<[B; N]>>
<[A; N] as PartialEq<[B]>>
<[A; N] as PartialEq<&[B]>>
<[A; N] as PartialEq<&mut [B]>>
<[T] as PartialEq<Vec<U, A>>>
<[A] as PartialEq<[B]>>
<[B] as PartialEq<[A; N]>>
<&[T] as PartialEq<Vec<U, A>>>
and 3 others

error: aborting due to 3 previous errors
Expand Down
Loading
Loading