1
Fork 0

Move refinement check out of compare_impl_item

This commit is contained in:
Michael Goulet 2024-11-30 16:44:58 +00:00
parent a3623f20ae
commit 1e655ef213
5 changed files with 48 additions and 9 deletions

View file

@ -1045,7 +1045,24 @@ fn check_impl_items_against_trait<'tcx>(
continue;
};
let _ = tcx.ensure().compare_impl_item(impl_item.expect_local());
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 => {}
}
}
check_specialization_validity(
tcx,

View file

@ -33,7 +33,7 @@ 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(
@ -70,12 +70,6 @@ fn compare_impl_method<'tcx>(
) -> 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)?;
refine::check_refining_return_position_impl_trait_in_trait(
tcx,
impl_m,
trait_m,
impl_trait_ref,
);
Ok(())
}

View file

@ -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,

View file

@ -219,6 +219,8 @@ fn resolve_associated_item<'tcx>(
// We check that the impl item is compatible with the trait item
// because otherwise we may ICE in const eval due to type mismatches,
// signature incompatibilities, etc.
// NOTE: We could also only enforce this in `PostAnalysis`, which
// is what CTFE and MIR inlining would care about anyways.
if trait_item_id != leaf_def.item.def_id
&& let Some(leaf_def_item) = leaf_def.item.def_id.as_local()
{

View file

@ -0,0 +1,26 @@
//@ check-pass
// Make sure that refinement checking doesn't cause a cycle in `Instance::resolve`
// which calls `compare_impl_item`.
trait Foo {
fn test() -> impl IntoIterator<Item = ()> + Send;
}
struct A;
impl Foo for A {
fn test() -> impl IntoIterator<Item = ()> + Send {
B::test()
}
}
struct B;
impl Foo for B {
fn test() -> impl IntoIterator<Item = ()> + Send {
for () in A::test() {}
[]
}
}
fn main() {}