diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:18:32 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:18:32 +0000 |
commit | 4547b622d8d29df964fa2914213088b148c498fc (patch) | |
tree | 9fc6b25f3c3add6b745be9a2400a6e96140046e9 /compiler/rustc_hir_analysis/src/collect/predicates_of.rs | |
parent | Releasing progress-linux version 1.66.0+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-4547b622d8d29df964fa2914213088b148c498fc.tar.xz rustc-4547b622d8d29df964fa2914213088b148c498fc.zip |
Merging upstream version 1.67.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | compiler/rustc_hir_analysis/src/collect/predicates_of.rs | 191 |
1 files changed, 118 insertions, 73 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 2e84e1d01..45e241f4e 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -84,60 +84,30 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP Node::ImplItem(item) => item.generics, - Node::Item(item) => { - match item.kind { - ItemKind::Impl(ref impl_) => { - if impl_.defaultness.is_default() { - is_default_impl_trait = tcx.impl_trait_ref(def_id).map(ty::Binder::dummy); - } - &impl_.generics - } - ItemKind::Fn(.., ref generics, _) - | ItemKind::TyAlias(_, ref generics) - | ItemKind::Enum(_, ref generics) - | ItemKind::Struct(_, ref generics) - | ItemKind::Union(_, ref generics) => *generics, - - ItemKind::Trait(_, _, ref generics, ..) => { - is_trait = Some(ty::TraitRef::identity(tcx, def_id)); - *generics + Node::Item(item) => match item.kind { + ItemKind::Impl(ref impl_) => { + if impl_.defaultness.is_default() { + is_default_impl_trait = tcx.impl_trait_ref(def_id).map(ty::Binder::dummy); } - ItemKind::TraitAlias(ref generics, _) => { - is_trait = Some(ty::TraitRef::identity(tcx, def_id)); - *generics - } - ItemKind::OpaqueTy(OpaqueTy { - origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..), - .. - }) => { - // return-position impl trait - // - // We don't inherit predicates from the parent here: - // If we have, say `fn f<'a, T: 'a>() -> impl Sized {}` - // then the return type is `f::<'static, T>::{{opaque}}`. - // - // If we inherited the predicates of `f` then we would - // require that `T: 'static` to show that the return - // type is well-formed. - // - // The only way to have something with this opaque type - // is from the return type of the containing function, - // which will ensure that the function's predicates - // hold. - return ty::GenericPredicates { parent: None, predicates: &[] }; - } - ItemKind::OpaqueTy(OpaqueTy { - ref generics, - origin: hir::OpaqueTyOrigin::TyAlias, - .. - }) => { - // type-alias impl trait - generics - } - - _ => NO_GENERICS, + &impl_.generics } - } + ItemKind::Fn(.., ref generics, _) + | ItemKind::TyAlias(_, ref generics) + | ItemKind::Enum(_, ref generics) + | ItemKind::Struct(_, ref generics) + | ItemKind::Union(_, ref generics) => *generics, + + ItemKind::Trait(_, _, ref generics, ..) => { + is_trait = Some(ty::TraitRef::identity(tcx, def_id)); + *generics + } + ItemKind::TraitAlias(ref generics, _) => { + is_trait = Some(ty::TraitRef::identity(tcx, def_id)); + *generics + } + ItemKind::OpaqueTy(OpaqueTy { ref generics, .. }) => generics, + _ => NO_GENERICS, + }, Node::ForeignItem(item) => match item.kind { ForeignItemKind::Static(..) => NO_GENERICS, @@ -181,6 +151,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP trace!(?predicates); trace!(?ast_generics); + trace!(?generics); // Collect the predicates that were written inline by the user on each // type parameter (e.g., `<T: Foo>`). @@ -199,7 +170,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP &icx, &mut bounds, &[], - Some((param.hir_id, ast_generics.predicates)), + Some((param.def_id, ast_generics.predicates)), param.span, ); trace!(?bounds); @@ -258,12 +229,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP predicates.extend(region_pred.bounds.iter().map(|bound| { let (r2, span) = match bound { hir::GenericBound::Outlives(lt) => { - (<dyn AstConv<'_>>::ast_region_to_region(&icx, lt, None), lt.span) + (<dyn AstConv<'_>>::ast_region_to_region(&icx, lt, None), lt.ident.span) } _ => bug!(), }; - let pred = ty::Binder::dummy(ty::PredicateKind::RegionOutlives( - ty::OutlivesPredicate(r1, r2), + let pred = ty::Binder::dummy(ty::PredicateKind::Clause( + ty::Clause::RegionOutlives(ty::OutlivesPredicate(r1, r2)), )) .to_predicate(icx.tcx); @@ -299,6 +270,52 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP ); } + // Opaque types duplicate some of their generic parameters. + // We create bi-directional Outlives predicates between the original + // and the duplicated parameter, to ensure that they do not get out of sync. + if let Node::Item(&Item { kind: ItemKind::OpaqueTy(..), .. }) = node { + let opaque_ty_id = tcx.hir().get_parent_node(hir_id); + let opaque_ty_node = tcx.hir().get(opaque_ty_id); + let Node::Ty(&Ty { kind: TyKind::OpaqueDef(_, lifetimes, _), .. }) = opaque_ty_node else { + bug!("unexpected {opaque_ty_node:?}") + }; + debug!(?lifetimes); + for (arg, duplicate) in std::iter::zip(lifetimes, ast_generics.params) { + let hir::GenericArg::Lifetime(arg) = arg else { bug!() }; + let orig_region = <dyn AstConv<'_>>::ast_region_to_region(&icx, &arg, None); + if !matches!(orig_region.kind(), ty::ReEarlyBound(..)) { + // Only early-bound regions can point to the original generic parameter. + continue; + } + + let hir::GenericParamKind::Lifetime { .. } = duplicate.kind else { continue }; + let dup_def = tcx.hir().local_def_id(duplicate.hir_id).to_def_id(); + + let Some(dup_index) = generics.param_def_id_to_index(tcx, dup_def) else { bug!() }; + + let dup_region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { + def_id: dup_def, + index: dup_index, + name: duplicate.name.ident().name, + })); + predicates.push(( + ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::RegionOutlives( + ty::OutlivesPredicate(orig_region, dup_region), + ))) + .to_predicate(icx.tcx), + duplicate.span, + )); + predicates.push(( + ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::RegionOutlives( + ty::OutlivesPredicate(dup_region, orig_region), + ))) + .to_predicate(icx.tcx), + duplicate.span, + )); + } + debug!(?predicates); + } + ty::GenericPredicates { parent: generics.parent, predicates: tcx.arena.alloc_from_iter(predicates), @@ -316,10 +333,9 @@ fn const_evaluatable_predicates_of<'tcx>( impl<'tcx> intravisit::Visitor<'tcx> for ConstCollector<'tcx> { fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) { - let def_id = self.tcx.hir().local_def_id(c.hir_id); - let ct = ty::Const::from_anon_const(self.tcx, def_id); + let ct = ty::Const::from_anon_const(self.tcx, c.def_id); if let ty::ConstKind::Unevaluated(_) = ct.kind() { - let span = self.tcx.hir().span(c.hir_id); + let span = self.tcx.def_span(c.def_id); self.preds.insert(( ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct)) .to_predicate(self.tcx), @@ -408,11 +424,13 @@ pub(super) fn explicit_predicates_of<'tcx>( .iter() .copied() .filter(|(pred, _)| match pred.kind().skip_binder() { - ty::PredicateKind::Trait(tr) => !is_assoc_item_ty(tr.self_ty()), - ty::PredicateKind::Projection(proj) => { + ty::PredicateKind::Clause(ty::Clause::Trait(tr)) => !is_assoc_item_ty(tr.self_ty()), + ty::PredicateKind::Clause(ty::Clause::Projection(proj)) => { !is_assoc_item_ty(proj.projection_ty.self_ty()) } - ty::PredicateKind::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0), + ty::PredicateKind::Clause(ty::Clause::TypeOutlives(outlives)) => { + !is_assoc_item_ty(outlives.0) + } _ => true, }) .collect(); @@ -427,7 +445,9 @@ pub(super) fn explicit_predicates_of<'tcx>( } else { if matches!(def_kind, DefKind::AnonConst) && tcx.lazy_normalization() { let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - if tcx.hir().opt_const_param_default_param_hir_id(hir_id).is_some() { + let parent_def_id = tcx.hir().get_parent_item(hir_id); + + if tcx.hir().opt_const_param_default_param_def_id(hir_id).is_some() { // 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) @@ -439,8 +459,33 @@ pub(super) fn explicit_predicates_of<'tcx>( // 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_def_id = tcx.hir().get_parent_item(hir_id); - // In the above code example we would be calling `explicit_predicates_of(Foo)` here + // and we would be calling `explicit_predicates_of(Foo)` here + return tcx.explicit_predicates_of(parent_def_id); + } + + let parent_def_kind = tcx.def_kind(parent_def_id); + if matches!(parent_def_kind, DefKind::OpaqueTy) { + // In `instantiate_identity` we inherit the predicates of our parent. + // However, opaque types do not have a parent (see `gather_explicit_predicates_of`), which means + // that we lose out on the predicates of our actual parent if we dont return those predicates here. + // + // + // fn foo<T: Trait>() -> impl Iterator<Output = Another<{ <T as Trait>::ASSOC }> > { todo!() } + // ^^^^^^^^^^^^^^^^^^^ the def id we are calling + // explicit_predicates_of on + // + // In the above code we want the anon const to have predicates in its param env for `T: Trait`. + // However, the anon const cannot inherit predicates from its parent since it's opaque. + // + // To fix this, we call `explicit_predicates_of` directly on `foo`, the parent's parent. + + // In the above example this is `foo::{opaque#0}` or `impl Iterator` + let parent_hir_id = tcx.hir().local_def_id_to_hir_id(parent_def_id.def_id); + + // In the above example this is the function `foo` + let item_def_id = tcx.hir().get_parent_item(parent_hir_id); + + // In the above code example we would be calling `explicit_predicates_of(foo)` here return tcx.explicit_predicates_of(item_def_id); } } @@ -504,7 +549,7 @@ pub(super) fn super_predicates_that_define_assoc_type( let is_trait_alias = tcx.is_trait_alias(trait_def_id); let superbounds2 = icx.type_parameter_bounds_in_generics( generics, - item.hir_id(), + item.owner_id.def_id, self_param_ty, OnlySelfBounds(!is_trait_alias), assoc_name, @@ -521,7 +566,9 @@ pub(super) fn super_predicates_that_define_assoc_type( // which will, in turn, reach indirect supertraits. for &(pred, span) in superbounds { debug!("superbound: {:?}", pred); - if let ty::PredicateKind::Trait(bound) = pred.kind().skip_binder() { + if let ty::PredicateKind::Clause(ty::Clause::Trait(bound)) = + pred.kind().skip_binder() + { tcx.at(span).super_predicates_of(bound.def_id()); } } @@ -614,14 +661,14 @@ pub(super) fn type_param_predicates( let extra_predicates = extend.into_iter().chain( icx.type_parameter_bounds_in_generics( ast_generics, - param_id, + def_id, ty, OnlySelfBounds(true), Some(assoc_name), ) .into_iter() .filter(|(predicate, _)| match predicate.kind().skip_binder() { - ty::PredicateKind::Trait(data) => data.self_ty().is_param(index), + ty::PredicateKind::Clause(ty::Clause::Trait(data)) => data.self_ty().is_param(index), _ => false, }), ); @@ -639,13 +686,11 @@ impl<'tcx> ItemCtxt<'tcx> { fn type_parameter_bounds_in_generics( &self, ast_generics: &'tcx hir::Generics<'tcx>, - param_id: hir::HirId, + param_def_id: LocalDefId, ty: Ty<'tcx>, only_self_bounds: OnlySelfBounds, assoc_name: Option<Ident>, ) -> Vec<(ty::Predicate<'tcx>, Span)> { - let param_def_id = self.tcx.hir().local_def_id(param_id).to_def_id(); - trace!(?param_def_id); ast_generics .predicates .iter() @@ -654,7 +699,7 @@ impl<'tcx> ItemCtxt<'tcx> { _ => None, }) .flat_map(|bp| { - let bt = if bp.is_param_bound(param_def_id) { + let bt = if bp.is_param_bound(param_def_id.to_def_id()) { Some(ty) } else if !only_self_bounds.0 { Some(self.to_ty(bp.bounded_ty)) |