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

@ -2,7 +2,7 @@ use crate::check::intrinsicck::InlineAsmCtxt;
use super::coercion::CoerceMany;
use super::compare_method::check_type_bounds;
use super::compare_method::{compare_const_impl, compare_impl_method, compare_ty_impl};
use super::compare_method::{compare_impl_method, compare_ty_impl};
use super::*;
use rustc_attr as attr;
use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan};
@ -1048,14 +1048,10 @@ fn check_impl_items_against_trait<'tcx>(
let impl_item_full = tcx.hir().impl_item(impl_item.id);
match impl_item_full.kind {
hir::ImplItemKind::Const(..) => {
// Find associated const definition.
compare_const_impl(
tcx,
&ty_impl_item,
impl_item.span,
&ty_trait_item,
impl_trait_ref,
);
let _ = tcx.compare_assoc_const_impl_item_with_trait_item((
impl_item.id.def_id.def_id,
ty_impl_item.trait_item_def_id.unwrap(),
));
}
hir::ImplItemKind::Fn(..) => {
let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);

View file

@ -1,6 +1,6 @@
use super::potentially_plural_count;
use crate::errors::LifetimesOrBoundsMismatchOnTrait;
use hir::def_id::DefId;
use hir::def_id::{DefId, LocalDefId};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed};
use rustc_hir as hir;
@ -1300,17 +1300,20 @@ fn compare_generic_param_kinds<'tcx>(
Ok(())
}
pub(crate) fn compare_const_impl<'tcx>(
/// Use `tcx.compare_assoc_const_impl_item_with_trait_item` instead
pub(crate) fn raw_compare_const_impl<'tcx>(
tcx: TyCtxt<'tcx>,
impl_c: &ty::AssocItem,
impl_c_span: Span,
trait_c: &ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
) {
(impl_const_item_def, trait_const_item_def): (LocalDefId, DefId),
) -> Result<(), ErrorGuaranteed> {
let impl_const_item = tcx.associated_item(impl_const_item_def);
let trait_const_item = tcx.associated_item(trait_const_item_def);
let impl_trait_ref = tcx.impl_trait_ref(impl_const_item.container_id(tcx)).unwrap();
debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref);
let impl_c_span = tcx.def_span(impl_const_item_def.to_def_id());
tcx.infer_ctxt().enter(|infcx| {
let param_env = tcx.param_env(impl_c.def_id);
let param_env = tcx.param_env(impl_const_item_def.to_def_id());
let ocx = ObligationCtxt::new(&infcx);
// The below is for the most part highly similar to the procedure
@ -1322,18 +1325,18 @@ pub(crate) fn compare_const_impl<'tcx>(
// Create a parameter environment that represents the implementation's
// method.
let impl_c_hir_id = tcx.hir().local_def_id_to_hir_id(impl_c.def_id.expect_local());
let impl_c_hir_id = tcx.hir().local_def_id_to_hir_id(impl_const_item_def);
// Compute placeholder form of impl and trait const tys.
let impl_ty = tcx.type_of(impl_c.def_id);
let trait_ty = tcx.bound_type_of(trait_c.def_id).subst(tcx, trait_to_impl_substs);
let impl_ty = tcx.type_of(impl_const_item_def.to_def_id());
let trait_ty = tcx.bound_type_of(trait_const_item_def).subst(tcx, trait_to_impl_substs);
let mut cause = ObligationCause::new(
impl_c_span,
impl_c_hir_id,
ObligationCauseCode::CompareImplItemObligation {
impl_item_def_id: impl_c.def_id.expect_local(),
trait_item_def_id: trait_c.def_id,
kind: impl_c.kind,
impl_item_def_id: impl_const_item_def,
trait_item_def_id: trait_const_item_def,
kind: impl_const_item.kind,
},
);
@ -1358,9 +1361,9 @@ pub(crate) fn compare_const_impl<'tcx>(
);
// Locate the Span containing just the type of the offending impl
match tcx.hir().expect_impl_item(impl_c.def_id.expect_local()).kind {
match tcx.hir().expect_impl_item(impl_const_item_def).kind {
ImplItemKind::Const(ref ty, _) => cause.span = ty.span,
_ => bug!("{:?} is not a impl const", impl_c),
_ => bug!("{:?} is not a impl const", impl_const_item),
}
let mut diag = struct_span_err!(
@ -1368,14 +1371,14 @@ pub(crate) fn compare_const_impl<'tcx>(
cause.span,
E0326,
"implemented const `{}` has an incompatible type for trait",
trait_c.name
trait_const_item.name
);
let trait_c_span = trait_c.def_id.as_local().map(|trait_c_def_id| {
let trait_c_span = trait_const_item_def.as_local().map(|trait_c_def_id| {
// Add a label to the Span containing just the type of the const
match tcx.hir().expect_trait_item(trait_c_def_id).kind {
TraitItemKind::Const(ref ty, _) => ty.span,
_ => bug!("{:?} is not a trait const", trait_c),
_ => bug!("{:?} is not a trait const", trait_const_item),
}
});
@ -1391,23 +1394,22 @@ pub(crate) fn compare_const_impl<'tcx>(
false,
false,
);
diag.emit();
}
return Err(diag.emit());
};
// Check that all obligations are satisfied by the implementation's
// version.
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
infcx.report_fulfillment_errors(&errors, None, false);
return;
return Err(infcx.report_fulfillment_errors(&errors, None, false));
}
// FIXME return `ErrorReported` if region obligations error?
let outlives_environment = OutlivesEnvironment::new(param_env);
infcx.check_region_obligations_and_report_errors(
impl_c.def_id.expect_local(),
&outlives_environment,
);
});
infcx
.check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment);
Ok(())
})
}
pub(crate) fn compare_ty_impl<'tcx>(

View file

@ -251,6 +251,7 @@ pub fn provide(providers: &mut Providers) {
check_mod_item_types,
region_scope_tree,
collect_trait_impl_trait_tys,
compare_assoc_const_impl_item_with_trait_item: compare_method::raw_compare_const_impl,
..*providers
};
}