add query opaque_types_defined_by

This commit is contained in:
lcnr 2023-04-18 16:09:48 +02:00 committed by Oli Scherer
parent e2daccc4ac
commit 6ae803eedf
3 changed files with 91 additions and 0 deletions

View File

@ -236,6 +236,15 @@
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`.

View File

@ -33,6 +33,7 @@
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);

View File

@ -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 };
}