Auto merge of #133365 - compiler-errors:compare-impl-item, r=lcnr
Make `compare_impl_item` into a query Turns `compare_impl_item` into a query (generalizing the existing query for `compare_impl_const`), and uses that in `Instance::resolve` to fail resolution when an implementation is incompatible with the trait it comes from. Fixes #119701 Fixes #121127 Fixes #121411 Fixes #129075 Fixes #129127 Fixes #129214 Fixes #131294
This commit is contained in:
commit
4af7fa79a0
18 changed files with 123 additions and 228 deletions
|
@ -33,7 +33,7 @@ use tracing::{debug, instrument};
|
|||
use ty::TypingMode;
|
||||
use {rustc_attr as attr, rustc_hir as hir};
|
||||
|
||||
use super::compare_impl_item::{check_type_bounds, compare_impl_method, compare_impl_ty};
|
||||
use super::compare_impl_item::check_type_bounds;
|
||||
use super::*;
|
||||
use crate::check::intrinsicck::InlineAsmCtxt;
|
||||
|
||||
|
@ -1044,18 +1044,23 @@ fn check_impl_items_against_trait<'tcx>(
|
|||
tcx.dcx().span_delayed_bug(tcx.def_span(impl_item), "missing associated item in trait");
|
||||
continue;
|
||||
};
|
||||
match ty_impl_item.kind {
|
||||
ty::AssocKind::Const => {
|
||||
tcx.ensure().compare_impl_const((
|
||||
impl_item.expect_local(),
|
||||
ty_impl_item.trait_item_def_id.unwrap(),
|
||||
));
|
||||
}
|
||||
ty::AssocKind::Fn => {
|
||||
compare_impl_method(tcx, ty_impl_item, ty_trait_item, trait_ref);
|
||||
}
|
||||
ty::AssocKind::Type => {
|
||||
compare_impl_ty(tcx, ty_impl_item, ty_trait_item, trait_ref);
|
||||
|
||||
let res = tcx.ensure().compare_impl_item(impl_item.expect_local());
|
||||
|
||||
if res.is_ok() {
|
||||
match ty_impl_item.kind {
|
||||
ty::AssocKind::Fn => {
|
||||
compare_impl_item::refine::check_refining_return_position_impl_trait_in_trait(
|
||||
tcx,
|
||||
ty_impl_item,
|
||||
ty_trait_item,
|
||||
tcx.impl_trait_ref(ty_impl_item.container_id(tcx))
|
||||
.unwrap()
|
||||
.instantiate_identity(),
|
||||
);
|
||||
}
|
||||
ty::AssocKind::Const => {}
|
||||
ty::AssocKind::Type => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,25 @@ use tracing::{debug, instrument};
|
|||
use super::potentially_plural_count;
|
||||
use crate::errors::{LifetimesOrBoundsMismatchOnTrait, MethodShouldReturnFuture};
|
||||
|
||||
mod refine;
|
||||
pub(super) mod refine;
|
||||
|
||||
/// Call the query `tcx.compare_impl_item()` directly instead.
|
||||
pub(super) fn compare_impl_item(
|
||||
tcx: TyCtxt<'_>,
|
||||
impl_item_def_id: LocalDefId,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let impl_item = tcx.associated_item(impl_item_def_id);
|
||||
let trait_item = tcx.associated_item(impl_item.trait_item_def_id.unwrap());
|
||||
let impl_trait_ref =
|
||||
tcx.impl_trait_ref(impl_item.container_id(tcx)).unwrap().instantiate_identity();
|
||||
debug!(?impl_trait_ref);
|
||||
|
||||
match impl_item.kind {
|
||||
ty::AssocKind::Fn => compare_impl_method(tcx, impl_item, trait_item, impl_trait_ref),
|
||||
ty::AssocKind::Type => compare_impl_ty(tcx, impl_item, trait_item, impl_trait_ref),
|
||||
ty::AssocKind::Const => compare_impl_const(tcx, impl_item, trait_item, impl_trait_ref),
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks that a method from an impl conforms to the signature of
|
||||
/// the same method as declared in the trait.
|
||||
|
@ -44,22 +62,15 @@ mod refine;
|
|||
/// - `trait_m`: the method in the trait
|
||||
/// - `impl_trait_ref`: the TraitRef corresponding to the trait implementation
|
||||
#[instrument(level = "debug", skip(tcx))]
|
||||
pub(super) fn compare_impl_method<'tcx>(
|
||||
fn compare_impl_method<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
impl_m: ty::AssocItem,
|
||||
trait_m: ty::AssocItem,
|
||||
impl_trait_ref: ty::TraitRef<'tcx>,
|
||||
) {
|
||||
let _: Result<_, ErrorGuaranteed> = try {
|
||||
check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, false)?;
|
||||
compare_method_predicate_entailment(tcx, impl_m, trait_m, impl_trait_ref)?;
|
||||
refine::check_refining_return_position_impl_trait_in_trait(
|
||||
tcx,
|
||||
impl_m,
|
||||
trait_m,
|
||||
impl_trait_ref,
|
||||
);
|
||||
};
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, false)?;
|
||||
compare_method_predicate_entailment(tcx, impl_m, trait_m, impl_trait_ref)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Checks a bunch of different properties of the impl/trait methods for
|
||||
|
@ -1721,17 +1732,12 @@ fn compare_generic_param_kinds<'tcx>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Use `tcx.compare_impl_const` instead
|
||||
pub(super) fn compare_impl_const_raw(
|
||||
tcx: TyCtxt<'_>,
|
||||
(impl_const_item_def, trait_const_item_def): (LocalDefId, DefId),
|
||||
fn compare_impl_const<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
impl_const_item: ty::AssocItem,
|
||||
trait_const_item: ty::AssocItem,
|
||||
impl_trait_ref: ty::TraitRef<'tcx>,
|
||||
) -> 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().instantiate_identity();
|
||||
debug!(?impl_trait_ref);
|
||||
|
||||
compare_number_of_generics(tcx, impl_const_item, trait_const_item, false)?;
|
||||
compare_generic_param_kinds(tcx, impl_const_item, trait_const_item, false)?;
|
||||
check_region_bounds_on_impl_item(tcx, impl_const_item, trait_const_item, false)?;
|
||||
|
@ -1862,19 +1868,17 @@ fn compare_const_predicate_entailment<'tcx>(
|
|||
}
|
||||
|
||||
#[instrument(level = "debug", skip(tcx))]
|
||||
pub(super) fn compare_impl_ty<'tcx>(
|
||||
fn compare_impl_ty<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
impl_ty: ty::AssocItem,
|
||||
trait_ty: ty::AssocItem,
|
||||
impl_trait_ref: ty::TraitRef<'tcx>,
|
||||
) {
|
||||
let _: Result<(), ErrorGuaranteed> = try {
|
||||
compare_number_of_generics(tcx, impl_ty, trait_ty, false)?;
|
||||
compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?;
|
||||
check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?;
|
||||
compare_type_predicate_entailment(tcx, impl_ty, trait_ty, impl_trait_ref)?;
|
||||
check_type_bounds(tcx, trait_ty, impl_ty, impl_trait_ref)?;
|
||||
};
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
compare_number_of_generics(tcx, impl_ty, trait_ty, false)?;
|
||||
compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?;
|
||||
check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?;
|
||||
compare_type_predicate_entailment(tcx, impl_ty, trait_ty, impl_trait_ref)?;
|
||||
check_type_bounds(tcx, trait_ty, impl_ty, impl_trait_ref)
|
||||
}
|
||||
|
||||
/// The equivalent of [compare_method_predicate_entailment], but for associated types
|
||||
|
|
|
@ -17,7 +17,7 @@ use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt;
|
|||
use rustc_trait_selection::traits::{ObligationCtxt, elaborate, normalize_param_env_or_error};
|
||||
|
||||
/// Check that an implementation does not refine an RPITIT from a trait method signature.
|
||||
pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
|
||||
pub(crate) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
impl_m: ty::AssocItem,
|
||||
trait_m: ty::AssocItem,
|
||||
|
|
|
@ -108,7 +108,7 @@ pub fn provide(providers: &mut Providers) {
|
|||
adt_async_destructor,
|
||||
region_scope_tree,
|
||||
collect_return_position_impl_trait_in_trait_tys,
|
||||
compare_impl_const: compare_impl_item::compare_impl_const_raw,
|
||||
compare_impl_item: compare_impl_item::compare_impl_item,
|
||||
check_coroutine_obligations: check::check_coroutine_obligations,
|
||||
..*providers
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue