about summary refs log tree commit diff
diff options
context:
space:
mode:
authorlcnr <rust@lcnr.de>2023-04-18 16:09:48 +0200
committerOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2023-05-12 10:26:07 +0000
commit6ae803eedfeb57944cd0d2930d9a8b7a606baf4a (patch)
tree2f61c61689f81c0bf35f1de007982c325114855a
parente2daccc4acbb7a3150e1aef32f8cbe2736e5bd99 (diff)
downloadrust-6ae803eedfeb57944cd0d2930d9a8b7a606baf4a.tar.gz
rust-6ae803eedfeb57944cd0d2930d9a8b7a606baf4a.zip
add `query opaque_types_defined_by`
-rw-r--r--compiler/rustc_middle/src/query/mod.rs9
-rw-r--r--compiler/rustc_ty_utils/src/lib.rs2
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs80
3 files changed, 91 insertions, 0 deletions
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 9fad2816b0d..5acdd68e60e 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -236,6 +236,15 @@ rustc_queries! {
         cache_on_disk_if { key.is_local() }
     }
 
+    query opaque_types_defined_by(
+        key: LocalDefId
+    ) -> &'tcx [LocalDefId] {
+        desc {
+            |tcx| "computing the opaque types defined by `{}`",
+            tcx.def_path_str(key.to_def_id())
+        }
+    }
+
     /// Returns the list of bounds that can be used for
     /// `SelectionCandidate::ProjectionCandidate(_)` and
     /// `ProjectionTyCandidate::TraitDef`.
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
index 73a2f6af579..8306c5ae493 100644
--- a/compiler/rustc_ty_utils/src/lib.rs
+++ b/compiler/rustc_ty_utils/src/lib.rs
@@ -33,6 +33,7 @@ pub mod instance;
 mod layout;
 mod layout_sanity_check;
 mod needs_drop;
+mod opaque_types;
 pub mod representability;
 mod structural_match;
 mod ty;
@@ -47,6 +48,7 @@ pub fn provide(providers: &mut Providers) {
     implied_bounds::provide(providers);
     layout::provide(providers);
     needs_drop::provide(providers);
+    opaque_types::provide(providers);
     representability::provide(providers);
     ty::provide(providers);
     instance::provide(providers);
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
new file mode 100644
index 00000000000..cdb8e4a439d
--- /dev/null
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -0,0 +1,80 @@
+use rustc_hir::{def::DefKind, def_id::LocalDefId};
+use rustc_middle::ty::util::CheckRegions;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
+use rustc_type_ir::AliasKind;
+use std::ops::ControlFlow;
+
+struct OpaqueTypeCollector<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    opaques: Vec<LocalDefId>,
+}
+
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> {
+        match t.kind() {
+            ty::Alias(AliasKind::Opaque, alias_ty) => {
+                if let Some(def_id) = alias_ty.def_id.as_local() {
+                    if self
+                        .tcx
+                        .uses_unique_generic_params(alias_ty.substs, CheckRegions::OnlyEarlyBound)
+                        .is_ok()
+                    {
+                        self.opaques.push(def_id);
+                        return ControlFlow::Continue(());
+                    } else {
+                        warn!(?t, "opaque types with non-unique params in sig: {t:?}");
+                    }
+                }
+            }
+            _ => {}
+        }
+        t.super_visit_with(self)
+    }
+}
+
+fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [LocalDefId] {
+    // FIXME(type_alias_impl_trait): This is definitely still wrong except for RPIT.
+    match tcx.def_kind(item) {
+        DefKind::Fn | DefKind::AssocFn => {
+            let sig = tcx.fn_sig(item).subst_identity();
+            let mut collector = OpaqueTypeCollector { tcx, opaques: Vec::new() };
+            sig.visit_with(&mut collector);
+            tcx.arena.alloc_from_iter(collector.opaques)
+        }
+        DefKind::Mod
+        | DefKind::Struct
+        | DefKind::Union
+        | DefKind::Enum
+        | DefKind::Variant
+        | DefKind::Trait
+        | DefKind::TyAlias
+        | DefKind::ForeignTy
+        | DefKind::TraitAlias
+        | DefKind::AssocTy
+        | DefKind::TyParam
+        | DefKind::Const
+        | DefKind::ConstParam
+        | DefKind::Static(_)
+        | DefKind::Ctor(_, _)
+        | DefKind::AssocConst
+        | DefKind::Macro(_)
+        | DefKind::ExternCrate
+        | DefKind::Use
+        | DefKind::ForeignMod
+        | DefKind::AnonConst
+        | DefKind::InlineConst
+        | DefKind::OpaqueTy
+        | DefKind::ImplTraitPlaceholder
+        | DefKind::Field
+        | DefKind::LifetimeParam
+        | DefKind::GlobalAsm
+        | DefKind::Impl { .. }
+        | DefKind::Closure
+        | DefKind::Generator => &[],
+    }
+}
+
+pub(super) fn provide(providers: &mut ty::query::Providers) {
+    *providers = ty::query::Providers { opaque_types_defined_by, ..*providers };
+}