diff options
| author | Camille GILLOT <gillot.camille@gmail.com> | 2022-11-11 18:08:55 +0000 |
|---|---|---|
| committer | Camille GILLOT <gillot.camille@gmail.com> | 2022-11-13 09:01:29 +0000 |
| commit | c5949c8beedc290b2638e1ad9bd7c665edc9496a (patch) | |
| tree | 55238ef3fc54d0644d83b6aa6fb40704f910072f | |
| parent | 49a5aa4f0cd2e21f071067e7a0c53474ba9e86c6 (diff) | |
Create bidirectional bounds between original and duplicated parameters.
| -rw-r--r-- | compiler/rustc_ast_lowering/src/lib.rs | 18 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/check/wfcheck.rs | 29 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/collect/predicates_of.rs | 103 | ||||
| -rw-r--r-- | compiler/rustc_ty_utils/src/ty.rs | 5 | ||||
| -rw-r--r-- | src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr | 5 |
5 files changed, 94 insertions, 66 deletions
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index ff29d15f1b5..d10d1b0c731 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -61,8 +61,8 @@ use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_hir::definitions::DefPathData; use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate}; use rustc_index::vec::{Idx, IndexVec}; +use rustc_middle::span_bug; use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; -use rustc_middle::{bug, span_bug}; use rustc_session::parse::feature_err; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::DesugaringKind; @@ -1457,17 +1457,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // frequently opened issues show. let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None); - let opaque_ty_def_id = match origin { - hir::OpaqueTyOrigin::TyAlias => self.create_def( - self.current_hir_id_owner.def_id, - opaque_ty_node_id, - DefPathData::ImplTrait, - ), - hir::OpaqueTyOrigin::FnReturn(fn_def_id) => { - self.create_def(fn_def_id, opaque_ty_node_id, DefPathData::ImplTrait) - } - hir::OpaqueTyOrigin::AsyncFn(..) => bug!("unreachable"), - }; + let opaque_ty_def_id = self.create_def( + self.current_hir_id_owner.def_id, + opaque_ty_node_id, + DefPathData::ImplTrait, + ); debug!(?opaque_ty_def_id); // Contains the new lifetime definitions created for the TAIT (if any). diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 837ff0bdf3e..9cd721fb342 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1538,7 +1538,6 @@ fn check_fn_or_method<'tcx>( check_return_position_impl_trait_in_trait_bounds( tcx, - wfcx, def_id, sig.output(), hir_decl.output.span(), @@ -1574,9 +1573,9 @@ fn check_fn_or_method<'tcx>( /// Basically `check_associated_type_bounds`, but separated for now and should be /// deduplicated when RPITITs get lowered into real associated items. +#[tracing::instrument(level = "trace", skip(tcx))] fn check_return_position_impl_trait_in_trait_bounds<'tcx>( tcx: TyCtxt<'tcx>, - wfcx: &WfCheckingCtxt<'_, 'tcx>, fn_def_id: LocalDefId, fn_output: Ty<'tcx>, span: Span, @@ -1590,18 +1589,22 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>( && tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder && tcx.impl_trait_in_trait_parent(proj.item_def_id) == fn_def_id.to_def_id() { - let bounds = wfcx.tcx().explicit_item_bounds(proj.item_def_id); - let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| { - let normalized_bound = wfcx.normalize(span, None, bound); - traits::wf::predicate_obligations( - wfcx.infcx, - wfcx.param_env, - wfcx.body_id, - normalized_bound, - bound_span, - ) + // Create a new context, since we want the opaque's ParamEnv and not the parent's. + let span = tcx.def_span(proj.item_def_id); + enter_wf_checking_ctxt(tcx, span, proj.item_def_id.expect_local(), |wfcx| { + let bounds = wfcx.tcx().explicit_item_bounds(proj.item_def_id); + let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| { + let normalized_bound = wfcx.normalize(span, None, bound); + traits::wf::predicate_obligations( + wfcx.infcx, + wfcx.param_env, + wfcx.body_id, + normalized_bound, + bound_span, + ) + }); + wfcx.register_obligations(wf_obligations); }); - wfcx.register_obligations(wf_obligations); } } } diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 5f4127632e3..808391d12c4 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -84,40 +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 - } - ItemKind::TraitAlias(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::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, @@ -161,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>`). @@ -279,6 +270,54 @@ 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::RegionOutlives(ty::OutlivesPredicate( + orig_region, + dup_region, + ))) + .to_predicate(icx.tcx), + duplicate.span, + )); + predicates.push(( + ty::Binder::dummy(ty::PredicateKind::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), diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 99d3bda6ebf..57fe38724b9 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -108,12 +108,7 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] { /// See `ParamEnv` struct definition for details. fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { - // The param_env of an impl Trait type is its defining function's param_env - if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) { - return param_env(tcx, parent.to_def_id()); - } // Compute the bounds on Self and the type parameters. - let ty::InstantiatedPredicates { mut predicates, .. } = tcx.predicates_of(def_id).instantiate_identity(tcx); diff --git a/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr index 7747319c153..c19420bbb0c 100644 --- a/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr +++ b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr @@ -14,10 +14,7 @@ error[E0720]: cannot resolve opaque type --> $DIR/impl-fn-predefined-lifetimes.rs:4:35 | LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { - | ^^^^^^^^^^^^^^^ recursive opaque type -... -LL | |x| x - | ----- returning here with type `[closure@$DIR/impl-fn-predefined-lifetimes.rs:7:5: 7:8]` + | ^^^^^^^^^^^^^^^ cannot resolve opaque type error: aborting due to 2 previous errors |
