diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 16ec935ba1ad..c78151271c17 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -85,10 +85,7 @@ impl<'tcx> Const<'tcx> { _ => expr, }; - use hir::{ - def::DefKind::ConstParam, def::Res, ExprKind, GenericParam, GenericParamKind, Node, - Path, QPath, - }; + use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath}; let val = match expr.kind { ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => { // Find the name and index of the const parameter by indexing the generics of @@ -103,33 +100,7 @@ impl<'tcx> Const<'tcx> { } _ => ty::ConstKind::Unevaluated(ty::Unevaluated { def: def.to_global(), - substs: { - let ct_hir_id = tcx.hir().local_def_id_to_hir_id(def.did); - let parent_id = tcx.hir().get_parent_node(ct_hir_id); - match tcx.hir().get(parent_id) { - // If this anon ct is a cg default we should only provide non-fwd declared params - // https://github.com/rust-lang/rust/issues/83938 - Node::GenericParam(GenericParam { - hir_id: param_id, - kind: GenericParamKind::Const { .. }, - .. - }) => { - let item_id = tcx.hir().get_parent_node(*param_id); - let item_def_id = tcx.hir().local_def_id(item_id); - let generics = tcx.generics_of(item_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]; - let substs = generics - .params - .iter() - .map(|param| tcx.mk_param_from_def(param)) - .take(param_def_idx as usize) - .collect::>(); - tcx.intern_substs(&substs) - } - _ => InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), - } - }, + substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), promoted: None, }), }; diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 583ba9392f06..924a0b8410a1 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1441,6 +1441,32 @@ 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 (#83938) + if let Node::GenericParam(GenericParam { + hir_id: param_id, + kind: GenericParamKind::Const { .. }, + .. + }) = tcx.hir().get(tcx.hir().get_parent_node(hir_id)) + { + let item_id = tcx.hir().get_parent_node(*param_id); + let item_def_id = tcx.hir().local_def_id(item_id); + let generics = tcx.generics_of(item_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]; + 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 { + parent: generics.parent, + parent_count: generics.parent_count, + params, + param_def_id_to_index, + has_self: generics.has_self, + has_late_bound_regions: generics.has_late_bound_regions, + }; + } + // HACK(eddyb) this provides the correct generics when // `feature(const_generics)` is enabled, so that const expressions // used with const generics, e.g. `Foo<{N+1}>`, can work at all. @@ -2359,7 +2385,8 @@ fn trait_explicit_predicates_and_bounds( } fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { - if let DefKind::Trait = tcx.def_kind(def_id) { + let def_kind = tcx.def_kind(def_id); + if let DefKind::Trait = def_kind { // Remove bounds on associated types from the predicates, they will be // returned by `explicit_item_bounds`. let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id.expect_local()); @@ -2404,6 +2431,21 @@ 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 return a parent for the generics + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + if let Node::GenericParam(hir::GenericParam { + hir_id: param_id, + kind: hir::GenericParamKind::Const { .. }, + .. + }) = tcx.hir().get(tcx.hir().get_parent_node(hir_id)) + { + let item_id = tcx.hir().get_parent_node(*param_id); + let item_def_id = tcx.hir().local_def_id(item_id).to_def_id(); + return tcx.explicit_predicates_of(item_def_id); + } + } gather_explicit_predicates_of(tcx, def_id) } } diff --git a/compiler/rustc_typeck/src/outlives/mod.rs b/compiler/rustc_typeck/src/outlives/mod.rs index d7eb31c2abef..c2f8525f7aba 100644 --- a/compiler/rustc_typeck/src/outlives/mod.rs +++ b/compiler/rustc_typeck/src/outlives/mod.rs @@ -20,6 +20,22 @@ pub fn provide(providers: &mut Providers) { fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[(ty::Predicate<'_>, Span)] { let id = tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local()); + if matches!(tcx.def_kind(item_def_id), hir::def::DefKind::AnonConst) && tcx.lazy_normalization() + { + // Provide inferred outlive preds of parent item of cg defaults manually + // as generics_of doesn't return a parent for the generics + if let Node::GenericParam(hir::GenericParam { + hir_id: param_id, + kind: hir::GenericParamKind::Const { .. }, + .. + }) = tcx.hir().get(tcx.hir().get_parent_node(id)) + { + let item_id = tcx.hir().get_parent_node(*param_id); + let item_def_id = tcx.hir().local_def_id(item_id).to_def_id(); + return tcx.inferred_outlives_of(item_def_id); + } + } + match tcx.hir().get(id) { Node::Item(item) => match item.kind { hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..) => { diff --git a/src/test/ui/const-generics/defaults/cec-build-subst-ice.stderr b/src/test/ui/const-generics/defaults/cec-build-subst-ice.stderr index 0508007412c7..30a01d48c4c8 100644 --- a/src/test/ui/const-generics/defaults/cec-build-subst-ice.stderr +++ b/src/test/ui/const-generics/defaults/cec-build-subst-ice.stderr @@ -8,5 +8,14 @@ LL | pub fn foo() -> Bar { loop {} } | = help: try adding a `where` bound using this expression: `where [(); { N + 1 }]:` -error: aborting due to previous error +error: unconstrained generic constant + --> $DIR/cec-build-subst-ice.rs:15:8 + | +LL | type Alias = [T; NP]; + | ---------- required by this bound in `Alias::{constant#0}` +LL | fn alias(_: [T; N], _: T) +LL | -> Alias + | ^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); {N+1usize}]:`