Skip to content

Commit 6ae803e

Browse files
lcnroli-obk
authored andcommitted
add query opaque_types_defined_by
1 parent e2daccc commit 6ae803e

File tree

3 files changed

+91
-0
lines changed

3 files changed

+91
-0
lines changed

compiler/rustc_middle/src/query/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,15 @@ rustc_queries! {
236236
cache_on_disk_if { key.is_local() }
237237
}
238238

239+
query opaque_types_defined_by(
240+
key: LocalDefId
241+
) -> &'tcx [LocalDefId] {
242+
desc {
243+
|tcx| "computing the opaque types defined by `{}`",
244+
tcx.def_path_str(key.to_def_id())
245+
}
246+
}
247+
239248
/// Returns the list of bounds that can be used for
240249
/// `SelectionCandidate::ProjectionCandidate(_)` and
241250
/// `ProjectionTyCandidate::TraitDef`.

compiler/rustc_ty_utils/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ pub mod instance;
3333
mod layout;
3434
mod layout_sanity_check;
3535
mod needs_drop;
36+
mod opaque_types;
3637
pub mod representability;
3738
mod structural_match;
3839
mod ty;
@@ -47,6 +48,7 @@ pub fn provide(providers: &mut Providers) {
4748
implied_bounds::provide(providers);
4849
layout::provide(providers);
4950
needs_drop::provide(providers);
51+
opaque_types::provide(providers);
5052
representability::provide(providers);
5153
ty::provide(providers);
5254
instance::provide(providers);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
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

Comments
 (0)