Rollup merge of #98496 - BoxyUwU:instancers_bad_equality, r=lcnr

make `compare_const_impl` a query and use it in `instance.rs`

Fixes #88365

the bug in #88365 was caused by some `instance.rs` code using the `PartialEq` impl on `Ty` to check that the type of the associated const in an impl is the same as the type of the associated const in the trait definition. This was wrong for two reasons:
- the check typeck does is that the impl type is a subtype of the trait definition's type (see `mismatched_impl_ty_2.rs` which [was ICEing](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f6d60ebe6745011f0d52ab2bc712025d) before this PR on stable)
- it assumes that if two types are equal then the `PartialEq` impl will reflect that which isnt true for higher ranked types or type level constants when `feature(generic_const_exprs)` is enabled (see `mismatched_impl_ty_3.rs` for higher ranked types which was [ICEing on stable](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=d7af131a655ed515b035624626c62c71))

r? `@lcnr`
This commit is contained in:
Matthias Krüger 2022-10-06 16:29:43 +02:00 committed by GitHub
commit dd0fa6f871
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 90 additions and 70 deletions

View file

@ -186,40 +186,14 @@ fn resolve_associated_item<'tcx>(
// a `trait` to an associated `const` definition in an `impl`, where
// the definition in the `impl` has the wrong type (for which an
// error has already been/will be emitted elsewhere).
//
// NB: this may be expensive, we try to skip it in all the cases where
// we know the error would've been caught (e.g. in an upstream crate).
//
// A better approach might be to just introduce a query (returning
// `Result<(), ErrorGuaranteed>`) for the check that `rustc_hir_analysis`
// performs (i.e. that the definition's type in the `impl` matches
// the declaration in the `trait`), so that we can cheaply check
// here if it failed, instead of approximating it.
if leaf_def.item.kind == ty::AssocKind::Const
&& trait_item_id != leaf_def.item.def_id
&& leaf_def.item.def_id.is_local()
&& let Some(leaf_def_item) = leaf_def.item.def_id.as_local()
{
let normalized_type_of = |def_id, substs| {
tcx.subst_and_normalize_erasing_regions(substs, param_env, tcx.type_of(def_id))
};
let original_ty = normalized_type_of(trait_item_id, rcvr_substs);
let resolved_ty = normalized_type_of(leaf_def.item.def_id, substs);
if original_ty != resolved_ty {
let msg = format!(
"Instance::resolve: inconsistent associated `const` type: \
was `{}: {}` but resolved to `{}: {}`",
tcx.def_path_str_with_substs(trait_item_id, rcvr_substs),
original_ty,
tcx.def_path_str_with_substs(leaf_def.item.def_id, substs),
resolved_ty,
);
let span = tcx.def_span(leaf_def.item.def_id);
let reported = tcx.sess.delay_span_bug(span, &msg);
return Err(reported);
}
tcx.compare_assoc_const_impl_item_with_trait_item((
leaf_def_item,
trait_item_id,
))?;
}
Some(ty::Instance::new(leaf_def.item.def_id, substs))