1
Fork 0

Add variances to RPITITs

This commit is contained in:
Michael Goulet 2024-09-29 13:41:13 -04:00 committed by Jubilee Young
parent b7297ac440
commit a7dc98733d
21 changed files with 242 additions and 169 deletions

View file

@ -5,6 +5,7 @@
use itertools::Itertools;
use rustc_arena::DroplessArena;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::query::Providers;
@ -63,8 +64,29 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
let crate_map = tcx.crate_variances(());
return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
}
DefKind::AssocTy => match tcx.opt_rpitit_info(item_def_id.to_def_id()) {
Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
return variance_of_opaque(
tcx,
opaque_def_id.expect_local(),
ForceCaptureTraitArgs::Yes,
);
}
None | Some(ty::ImplTraitInTraitData::Impl { .. }) => {}
},
DefKind::OpaqueTy => {
return variance_of_opaque(tcx, item_def_id);
let force_capture_trait_args = if let hir::OpaqueTyOrigin::FnReturn {
parent: _,
in_trait_or_impl: Some(hir::RpitContext::Trait),
} =
tcx.hir_node_by_def_id(item_def_id).expect_opaque_ty().origin
{
ForceCaptureTraitArgs::Yes
} else {
ForceCaptureTraitArgs::No
};
return variance_of_opaque(tcx, item_def_id, force_capture_trait_args);
}
_ => {}
}
@ -73,8 +95,18 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
span_bug!(tcx.def_span(item_def_id), "asked to compute variance for wrong kind of item");
}
#[derive(Debug, Copy, Clone)]
enum ForceCaptureTraitArgs {
Yes,
No,
}
#[instrument(level = "trace", skip(tcx), ret)]
fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
fn variance_of_opaque(
tcx: TyCtxt<'_>,
item_def_id: LocalDefId,
force_capture_trait_args: ForceCaptureTraitArgs,
) -> &[ty::Variance] {
let generics = tcx.generics_of(item_def_id);
// Opaque types may only use regions that are bound. So for
@ -115,9 +147,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
#[instrument(level = "trace", skip(self), ret)]
fn visit_ty(&mut self, t: Ty<'tcx>) {
match t.kind() {
ty::Alias(_, ty::AliasTy { def_id, args, .. })
if matches!(self.tcx.def_kind(*def_id), DefKind::OpaqueTy) =>
{
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
self.visit_opaque(*def_id, args);
}
_ => t.super_visit_with(self),
@ -135,6 +165,15 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
let mut generics = generics;
while let Some(def_id) = generics.parent {
generics = tcx.generics_of(def_id);
// Don't mark trait params generic if we're in an RPITIT.
if matches!(force_capture_trait_args, ForceCaptureTraitArgs::Yes)
&& generics.parent.is_none()
{
debug_assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
break;
}
for param in &generics.own_params {
match param.kind {
ty::GenericParamDefKind::Lifetime => {