Skip to content

Commit

Permalink
Rollup merge of rust-lang#113005 - compiler-errors:dont-query-normali…
Browse files Browse the repository at this point in the history
…ze, r=cjgillot

Don't call `query_normalize` when reporting similar impls

Firstly, It's sketchy to be using `query_normalize` at all during HIR typeck -- it's asking for an ICE 😅. Secondly, we're normalizing an impl trait ref that potentially has parameter types in `ty::ParamEnv::empty()`, which is kinda sketchy as well.

The only UI test change from removing this normalization is that we don't evaluate anonymous constants in impls, which end up giving us really ugly suggestions:

```
error[E0277]: the trait bound `[X; 35]: Default` is not satisfied
 --> /home/gh-compiler-errors/test.rs:4:5
  |
4 |     <[X; 35] as Default>::default();
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `[X; 35]`
  |
  = help: the following other types implement trait `Default`:
            &[T]
            &mut [T]
            [T; 32]
            [T; core::::array::{impl#30}::{constant#0}]
            [T; core::::array::{impl#31}::{constant#0}]
            [T; core::::array::{impl#32}::{constant#0}]
            [T; core::::array::{impl#33}::{constant#0}]
            [T; core::::array::{impl#34}::{constant#0}]
          and 27 others
```

So just fold the impls with a `BottomUpFolder` that calls `ty::Const::eval`. This doesn't work totally correctly with generic-const-exprs, but it's fine for stable code, and this is error reporting after all.
  • Loading branch information
matthiaskrgr authored Jul 8, 2023
2 parents f521d93 + 2c33dfe commit 6e20345
Show file tree
Hide file tree
Showing 45 changed files with 299 additions and 268 deletions.
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 @@ -12,7 +12,6 @@ use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use crate::infer::{self, InferCtxt};
use crate::solve::{GenerateProofTree, InferCtxtEvalExt, UseGlobalCache};
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 @@ -33,7 +32,7 @@ use rustc_middle::traits::solve::Goal;
use rustc_middle::traits::{DefiningAnchor, 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 @@ -63,7 +62,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 @@ -1941,10 +1940,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 @@ -1973,26 +1969,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 @@ -2006,7 +2007,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 @@ -2033,7 +2034,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 @@ -2042,27 +2046,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));
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

0 comments on commit 6e20345

Please sign in to comment.