From abfd44d8a3b13d56dc0c7904c35a8155a62f19fb Mon Sep 17 00:00:00 2001 From: Ellen Date: Sat, 17 Jul 2021 11:59:42 +0100 Subject: [PATCH] Comments --- compiler/rustc_typeck/src/collect.rs | 43 +++++++++++++++++++++-- compiler/rustc_typeck/src/outlives/mod.rs | 14 ++++++-- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 31cafb9d966..a2ac3e2555f 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1441,16 +1441,43 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { // of a const parameter type, e.g. `struct Foo` is not allowed. None } else if tcx.lazy_normalization() { - // Only provide backwards declared generics to cg defaults (#86580) if let Some(param_id) = tcx.hir().opt_const_param_default_param_hir_id(hir_id) { + // If the def_id we are calling generics_of on is an anon ct default i.e: + // + // struct Foo; + // ^^^ ^ ^^^^^^ def id of this anon const + // ^ ^ param_id + // ^ parent_def_id + // + // then we only want to return generics for params to the left of `N`. If we don't do that we + // end up with that const looking like: `ty::ConstKind::Unevaluated(def_id, substs: [N#0])`. + // + // This causes ICEs (#86580) when building the substs for Foo in `fn foo() -> Foo { .. }` as + // we substitute the defaults with the partially built substs when we build the substs. Subst'ing + // the `N#0` on the unevaluated const indexes into the empty substs we're in the process of building. + // + // We fix this by having this function return the parent's generics ourselves and truncating the + // generics to only include non-forward declared params (with the exception of the `Self` ty) + // + // For the above code example that means we want `substs: []` + // For the following struct def we want `substs: [N#0]` when generics_of is called on + // the def id of the `{ N + 1 }` anon const + // struct Foo; + // + // This has some implications for how we get the predicates available to the anon const + // see `explicit_predicates_of` for more information on this let generics = tcx.generics_of(parent_def_id.to_def_id()); let param_def = tcx.hir().local_def_id(param_id).to_def_id(); let param_def_idx = generics.param_def_id_to_index[¶m_def]; + // In the above example this would be .params[..N#0] let params = generics.params[..param_def_idx as usize].to_owned(); let param_def_id_to_index = params.iter().map(|param| (param.def_id, param.index)).collect(); return ty::Generics { + // we set the parent of these generics to be our parent's parent so that we + // dont end up with substs: [N, M, N] for the const default on a struct like this: + // struct Foo; parent: generics.parent, parent_count: generics.parent_count, params, @@ -2425,12 +2452,22 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat } } else { if matches!(def_kind, DefKind::AnonConst) && tcx.lazy_normalization() { - // Provide predicates of parent item of cg defaults manually as `generics_of` - // doesn't set the parent item as the parent for the generics (#86580) let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); if let Some(_) = tcx.hir().opt_const_param_default_param_hir_id(hir_id) { + // In `generics_of` we set the generics' parent to be our parent's parent which means that + // we lose out on the predicates of our actual parent if we dont return those predicates here. + // (See comment in `generics_of` for more information on why the parent shenanigans is necessary) + // + // struct Foo::ASSOC }>(T) where T: Trait; + // ^^^ ^^^^^^^^^^^^^^^^^^^^^^^ the def id we are calling + // ^^^ explicit_predicates_of on + // parent item we dont have set as the + // parent of generics returned by `generics_of` + // + // In the above code we want the anon const to have predicates in its param env for `T: Trait` let item_id = tcx.hir().get_parent_item(hir_id); let item_def_id = tcx.hir().local_def_id(item_id).to_def_id(); + // In the above code example we would be calling `explicit_predicates_of(Foo)` here return tcx.explicit_predicates_of(item_def_id); } } diff --git a/compiler/rustc_typeck/src/outlives/mod.rs b/compiler/rustc_typeck/src/outlives/mod.rs index 16d698fc8cb..70a2ba7fcd9 100644 --- a/compiler/rustc_typeck/src/outlives/mod.rs +++ b/compiler/rustc_typeck/src/outlives/mod.rs @@ -22,11 +22,21 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[(ty::Predicate if matches!(tcx.def_kind(item_def_id), hir::def::DefKind::AnonConst) && tcx.lazy_normalization() { - // Provide predicates of parent item of cg defaults manually as `generics_of` - // doesn't set the parent item as the parent for the generics (#86580) if let Some(_) = tcx.hir().opt_const_param_default_param_hir_id(id) { + // In `generics_of` we set the generics' parent to be our parent's parent which means that + // we lose out on the predicates of our actual parent if we dont return those predicates here. + // (See comment in `generics_of` for more information on why the parent shenanigans is necessary) + // + // struct Foo<'a, 'b, const N: usize = { ... }>(&'a &'b ()); + // ^^^ ^^^^^^^ the def id we are calling + // ^^^ inferred_outlives_of on + // parent item we dont have set as the + // parent of generics returned by `generics_of` + // + // In the above code we want the anon const to have predicates in its param env for `'b: 'a` let item_id = tcx.hir().get_parent_item(id); let item_def_id = tcx.hir().local_def_id(item_id).to_def_id(); + // In the above code example we would be calling `inferred_outlives_of(Foo)` here return tcx.inferred_outlives_of(item_def_id); } }