Change:
<!-- Thank you for filing a regression report! A regression is something that changed between versions of Rust but was not supposed to. Please provide a short summary of the regression, along with any information you feel is relevant to replicate it. --Error <codeerror[E0391] cycle detected when computing when has a significant destructor</codeoccurs when warn/deny lint on rust beta and nightly with a certain code snippet. On rust stable, it compiles without any issues. Looks like an issue of rustc (). I tried this code: It compiles successfully on stable or with : But with this lint warned (or denied) it does not compile on rust beta and on rust nightly with error: : <!-- Provide the version you are using that has the regression. --: <!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. modify labels: +regression-from-stable-to-{channel} -regression-untriaged --<!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
Bisects to , CC Although this is a regression from stable to beta, there's not enough time for it to get fixed before release.
Oops. Yeah, i read the error message and immediately knew what was going on. I can hopefully get a patch up for this tomorrow. claim
label regression-from-stable-to-stable, -regression-from-stable-to-beta
Assigning priority as discussed in the of the Prioritization Working Group. label -I-prioritize +P-high

Discussion:
fn with_query_cache<'tcx>( tcx: TyCtxt<'tcx>, iter: impl IntoIterator<Item = Ty<'tcx>>, <del> only_significant: bool, </del> ) -> NeedsDropResult<Vec<Ty<'tcx>>> { iter.into_iter().try_fold(Vec::new(), |mut vec, subty| { match subty.kind() { ty::Adt(adt_id, subst) => { <del> for subty in if only_significant { tcx.adt_significant_drop_tys(adt_id.did)? } else { tcx.adt_drop_tys(adt_id.did)? } { </del> <ins> for subty in tcx.adt_drop_tys(adt_id.did)? { </ins> vec.push(subty.subst(tcx, subst)); } }

// Since the destructor is insignificant, we just want to make sure all of // the passed in type parameters are also insignificant. // Eg: Vec<T> dtor is insignificant when T=i32 but significant when T=Mutex. <del> with_query_cache(tcx, substs.types(), only_significant) </del> <ins> Ok(substs.types().collect()) </ins> } } } else if adt_def.is_union() { debug!("drop_tys_helper: `{:?}` is a union", adt_def); Ok(Vec::new()) } else { <del> with_query_cache( tcx, adt_def.all_fields().map(|field| { let r = tcx.type_of(field.did).subst(tcx, substs); debug!( "drop_tys_helper: Subst into {:?} with {:?} gettng {:?}", field, substs, r ); r }), only_significant, ) </del> <ins> let field_tys = adt_def.all_fields().map(|field| { let r = tcx.type_of(field.did).subst(tcx, substs); debug!("drop_tys_helper: Subst into {:?} with {:?} gettng {:?}", field, substs, r); r }); if only_significant { // We can't recurse through the query system here because we might induce a cycle Ok(field_tys.collect()) } else { // We can use the query system if we consider all drops significant. In that case, // ADTs are `needs_drop` exactly if they `impl Drop` or if any of their "transitive" // fields do. There can be no cycles here, because ADTs cannot contain themselves as // fields. with_query_cache(tcx, field_tys) } </ins> } .map(|v| v.into_iter()) };

<ins> // ICEs if checking if there is a significant destructor causes a query cycle // check-pass #![warn(rust_2021_incompatible_closure_captures)] pub struct Foo(Bar); pub struct Bar(Baz); pub struct Baz(Vec<Foo>); impl Foo { pub fn baz(self, v: Baz) -> Baz { (|| v)() } } fn main() {} </ins>