Move refinement check out of compare_impl_item
This commit is contained in:
parent
a3623f20ae
commit
1e655ef213
5 changed files with 48 additions and 9 deletions
|
@ -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,
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
26
tests/ui/impl-trait/in-trait/refine-cycle.rs
Normal file
26
tests/ui/impl-trait/in-trait/refine-cycle.rs
Normal 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() {}
|
Loading…
Add table
Add a link
Reference in a new issue