diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_borrowck/src/region_infer/opaque_types.rs | 23 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/mod.rs | 32 |
2 files changed, 43 insertions, 12 deletions
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 49f7242cd83..4958e2c1ade 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -179,7 +179,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // Next, insert universal regions from args, so we can translate regions that appear // in them but are not subject to member constraints, for instance closure args. - let universal_args = infcx.tcx.fold_regions(args, |region, _| { + let universal_key = opaque_type_key.fold_captured_lifetime_args(infcx.tcx, |region| { if let ty::RePlaceholder(..) = region.kind() { // Higher kinded regions don't need remapping, they don't refer to anything outside of this the args. return region; @@ -187,6 +187,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { let vid = self.to_region_vid(region); to_universal_region(vid, &mut arg_regions) }); + let universal_args = universal_key.args; debug!(?universal_args); debug!(?arg_regions); @@ -431,23 +432,21 @@ fn check_opaque_type_well_formed<'tcx>( } } -fn check_opaque_type_parameter_valid( - tcx: TyCtxt<'_>, - opaque_type_key: OpaqueTypeKey<'_>, +fn check_opaque_type_parameter_valid<'tcx>( + tcx: TyCtxt<'tcx>, + opaque_type_key: OpaqueTypeKey<'tcx>, span: Span, ) -> Result<(), ErrorGuaranteed> { let opaque_ty_hir = tcx.hir().expect_item(opaque_type_key.def_id); - let (parent, is_ty_alias) = match opaque_ty_hir.expect_opaque_ty().origin { + let (_parent, is_ty_alias) = match opaque_ty_hir.expect_opaque_ty().origin { OpaqueTyOrigin::TyAlias { parent, .. } => (parent, true), OpaqueTyOrigin::AsyncFn(parent) | OpaqueTyOrigin::FnReturn(parent) => (parent, false), }; - let parent_generics = tcx.generics_of(parent); + let opaque_generics = tcx.generics_of(opaque_type_key.def_id); let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default(); - // Only check the parent generics, which will ignore any of the - // duplicated lifetime args that come from reifying late-bounds. - for (i, arg) in opaque_type_key.args.iter().take(parent_generics.count()).enumerate() { + for (i, arg) in opaque_type_key.iter_captured_args(tcx) { let arg_is_param = match arg.unpack() { GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)), GenericArgKind::Lifetime(lt) if is_ty_alias => { @@ -464,7 +463,7 @@ fn check_opaque_type_parameter_valid( seen_params.entry(arg).or_default().push(i); } else { // Prevent `fn foo() -> Foo<u32>` from being defining. - let opaque_param = parent_generics.param_at(i, tcx); + let opaque_param = opaque_generics.param_at(i, tcx); let kind = opaque_param.kind.descr(); return Err(tcx.dcx().emit_err(NonGenericOpaqueTypeParam { @@ -478,10 +477,10 @@ fn check_opaque_type_parameter_valid( for (_, indices) in seen_params { if indices.len() > 1 { - let descr = parent_generics.param_at(indices[0], tcx).kind.descr(); + let descr = opaque_generics.param_at(indices[0], tcx).kind.descr(); let spans: Vec<_> = indices .into_iter() - .map(|i| tcx.def_span(parent_generics.param_at(i, tcx).def_id)) + .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id)) .collect(); #[allow(rustc::diagnostic_outside_of_impl)] #[allow(rustc::untranslatable_diagnostic)] diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 6ce53ccc8cd..0be1a1ab39d 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -832,6 +832,38 @@ pub struct OpaqueTypeKey<'tcx> { pub args: GenericArgsRef<'tcx>, } +impl<'tcx> OpaqueTypeKey<'tcx> { + pub fn iter_captured_args( + self, + tcx: TyCtxt<'tcx>, + ) -> impl Iterator<Item = (usize, GenericArg<'tcx>)> { + std::iter::zip(self.args, tcx.variances_of(self.def_id)).enumerate().filter_map( + |(i, (arg, v))| match (arg.unpack(), v) { + (_, ty::Invariant) => Some((i, arg)), + (ty::GenericArgKind::Lifetime(_), ty::Bivariant) => None, + _ => bug!("unexpected opaque type arg variance"), + }, + ) + } + + pub fn fold_captured_lifetime_args( + self, + tcx: TyCtxt<'tcx>, + mut f: impl FnMut(Region<'tcx>) -> Region<'tcx>, + ) -> Self { + let Self { def_id, args } = self; + let args = std::iter::zip(args, tcx.variances_of(def_id)).map(|(arg, v)| { + match (arg.unpack(), v) { + (ty::GenericArgKind::Lifetime(_), ty::Bivariant) => arg, + (ty::GenericArgKind::Lifetime(lt), _) => f(lt).into(), + _ => arg, + } + }); + let args = tcx.mk_args_from_iter(args); + Self { def_id, args } + } +} + #[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)] pub struct OpaqueHiddenType<'tcx> { /// The span of this particular definition of the opaque type. So |
