|
| 1 | +use rustc_hir::{def::DefKind, def_id::LocalDefId}; |
| 2 | +use rustc_middle::ty::util::CheckRegions; |
| 3 | +use rustc_middle::ty::{self, Ty, TyCtxt}; |
| 4 | +use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; |
| 5 | +use rustc_type_ir::AliasKind; |
| 6 | +use std::ops::ControlFlow; |
| 7 | + |
| 8 | +struct OpaqueTypeCollector<'tcx> { |
| 9 | + tcx: TyCtxt<'tcx>, |
| 10 | + opaques: Vec<LocalDefId>, |
| 11 | +} |
| 12 | + |
| 13 | +impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> { |
| 14 | + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> { |
| 15 | + match t.kind() { |
| 16 | + ty::Alias(AliasKind::Opaque, alias_ty) => { |
| 17 | + if let Some(def_id) = alias_ty.def_id.as_local() { |
| 18 | + if self |
| 19 | + .tcx |
| 20 | + .uses_unique_generic_params(alias_ty.substs, CheckRegions::OnlyEarlyBound) |
| 21 | + .is_ok() |
| 22 | + { |
| 23 | + self.opaques.push(def_id); |
| 24 | + return ControlFlow::Continue(()); |
| 25 | + } else { |
| 26 | + warn!(?t, "opaque types with non-unique params in sig: {t:?}"); |
| 27 | + } |
| 28 | + } |
| 29 | + } |
| 30 | + _ => {} |
| 31 | + } |
| 32 | + t.super_visit_with(self) |
| 33 | + } |
| 34 | +} |
| 35 | + |
| 36 | +fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [LocalDefId] { |
| 37 | + // FIXME(type_alias_impl_trait): This is definitely still wrong except for RPIT. |
| 38 | + match tcx.def_kind(item) { |
| 39 | + DefKind::Fn | DefKind::AssocFn => { |
| 40 | + let sig = tcx.fn_sig(item).subst_identity(); |
| 41 | + let mut collector = OpaqueTypeCollector { tcx, opaques: Vec::new() }; |
| 42 | + sig.visit_with(&mut collector); |
| 43 | + tcx.arena.alloc_from_iter(collector.opaques) |
| 44 | + } |
| 45 | + DefKind::Mod |
| 46 | + | DefKind::Struct |
| 47 | + | DefKind::Union |
| 48 | + | DefKind::Enum |
| 49 | + | DefKind::Variant |
| 50 | + | DefKind::Trait |
| 51 | + | DefKind::TyAlias |
| 52 | + | DefKind::ForeignTy |
| 53 | + | DefKind::TraitAlias |
| 54 | + | DefKind::AssocTy |
| 55 | + | DefKind::TyParam |
| 56 | + | DefKind::Const |
| 57 | + | DefKind::ConstParam |
| 58 | + | DefKind::Static(_) |
| 59 | + | DefKind::Ctor(_, _) |
| 60 | + | DefKind::AssocConst |
| 61 | + | DefKind::Macro(_) |
| 62 | + | DefKind::ExternCrate |
| 63 | + | DefKind::Use |
| 64 | + | DefKind::ForeignMod |
| 65 | + | DefKind::AnonConst |
| 66 | + | DefKind::InlineConst |
| 67 | + | DefKind::OpaqueTy |
| 68 | + | DefKind::ImplTraitPlaceholder |
| 69 | + | DefKind::Field |
| 70 | + | DefKind::LifetimeParam |
| 71 | + | DefKind::GlobalAsm |
| 72 | + | DefKind::Impl { .. } |
| 73 | + | DefKind::Closure |
| 74 | + | DefKind::Generator => &[], |
| 75 | + } |
| 76 | +} |
| 77 | + |
| 78 | +pub(super) fn provide(providers: &mut ty::query::Providers) { |
| 79 | + *providers = ty::query::Providers { opaque_types_defined_by, ..*providers }; |
| 80 | +} |
0 commit comments