1
Fork 0

Avoid fetching the opaque type origin when only "is this in the defining scope" is actually needed

This commit is contained in:
Oli Scherer 2024-03-14 11:40:28 +00:00
parent ba5f0418af
commit 7cfa521931
5 changed files with 16 additions and 27 deletions

View file

@ -730,8 +730,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
for ty in ret_ty.walk() { for ty in ret_ty.walk() {
if let ty::GenericArgKind::Type(ty) = ty.unpack() if let ty::GenericArgKind::Type(ty) = ty.unpack()
&& let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *ty.kind() && let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *ty.kind()
&& let Some(def_id) = def_id.as_local() && self.can_define_opaque_ty(def_id)
&& self.opaque_type_origin(def_id).is_some()
{ {
return None; return None;
} }

View file

@ -244,7 +244,7 @@ pub struct InferCtxt<'tcx> {
pub tcx: TyCtxt<'tcx>, pub tcx: TyCtxt<'tcx>,
/// The `DefIds` of the opaque types that may have their hidden types constrained. /// The `DefIds` of the opaque types that may have their hidden types constrained.
pub defining_opaque_types: &'tcx ty::List<LocalDefId>, defining_opaque_types: &'tcx ty::List<LocalDefId>,
/// Whether this inference context should care about region obligations in /// Whether this inference context should care about region obligations in
/// the root universe. Most notably, this is used during hir typeck as region /// the root universe. Most notably, this is used during hir typeck as region
@ -1232,6 +1232,12 @@ impl<'tcx> InferCtxt<'tcx> {
self.inner.borrow().opaque_type_storage.opaque_types.clone() self.inner.borrow().opaque_type_storage.opaque_types.clone()
} }
#[inline(always)]
pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool {
let Some(id) = id.into().as_local() else { return false };
self.defining_opaque_types.contains(&id)
}
pub fn ty_to_string(&self, t: Ty<'tcx>) -> String { pub fn ty_to_string(&self, t: Ty<'tcx>) -> String {
self.resolve_vars_if_possible(t).to_string() self.resolve_vars_if_possible(t).to_string()
} }

View file

@ -4,7 +4,6 @@ use crate::errors::OpaqueHiddenTypeDiag;
use crate::infer::{InferCtxt, InferOk}; use crate::infer::{InferCtxt, InferOk};
use crate::traits::{self, PredicateObligation}; use crate::traits::{self, PredicateObligation};
use hir::def_id::{DefId, LocalDefId}; use hir::def_id::{DefId, LocalDefId};
use hir::OpaqueTyOrigin;
use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_hir as hir; use rustc_hir as hir;
@ -54,16 +53,13 @@ impl<'tcx> InferCtxt<'tcx> {
} }
let mut obligations = vec![]; let mut obligations = vec![];
let replace_opaque_type = |def_id: DefId| {
def_id.as_local().is_some_and(|def_id| self.opaque_type_origin(def_id).is_some())
};
let value = value.fold_with(&mut BottomUpFolder { let value = value.fold_with(&mut BottomUpFolder {
tcx: self.tcx, tcx: self.tcx,
lt_op: |lt| lt, lt_op: |lt| lt,
ct_op: |ct| ct, ct_op: |ct| ct,
ty_op: |ty| match *ty.kind() { ty_op: |ty| match *ty.kind() {
ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })
if replace_opaque_type(def_id) && !ty.has_escaping_bound_vars() => if self.can_define_opaque_ty(def_id) && !ty.has_escaping_bound_vars() =>
{ {
let def_span = self.tcx.def_span(def_id); let def_span = self.tcx.def_span(def_id);
let span = if span.contains(def_span) { def_span } else { span }; let span = if span.contains(def_span) { def_span } else { span };
@ -140,7 +136,7 @@ impl<'tcx> InferCtxt<'tcx> {
// let x = || foo(); // returns the Opaque assoc with `foo` // let x = || foo(); // returns the Opaque assoc with `foo`
// } // }
// ``` // ```
if self.opaque_type_origin(def_id).is_none() { if !self.can_define_opaque_ty(def_id) {
return None; return None;
} }
@ -150,8 +146,8 @@ impl<'tcx> InferCtxt<'tcx> {
// no one encounters it in practice. // no one encounters it in practice.
// It does occur however in `fn fut() -> impl Future<Output = i32> { async { 42 } }`, // It does occur however in `fn fut() -> impl Future<Output = i32> { async { 42 } }`,
// where it is of no concern, so we only check for TAITs. // where it is of no concern, so we only check for TAITs.
if let Some(OpaqueTyOrigin::TyAlias { .. }) = if self.can_define_opaque_ty(b_def_id)
b_def_id.as_local().and_then(|b_def_id| self.opaque_type_origin(b_def_id)) && self.tcx.is_type_alias_impl_trait(b_def_id)
{ {
self.tcx.dcx().emit_err(OpaqueHiddenTypeDiag { self.tcx.dcx().emit_err(OpaqueHiddenTypeDiag {
span: cause.span, span: cause.span,
@ -363,15 +359,6 @@ impl<'tcx> InferCtxt<'tcx> {
op: |r| self.member_constraint(opaque_type_key, span, concrete_ty, r, &choice_regions), op: |r| self.member_constraint(opaque_type_key, span, concrete_ty, r, &choice_regions),
}); });
} }
/// Returns the origin of the opaque type `def_id` if we're currently
/// in its defining scope.
#[instrument(skip(self), level = "trace", ret)]
pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option<OpaqueTyOrigin> {
let origin = self.tcx.opaque_type_origin(def_id);
self.defining_opaque_types.contains(&def_id).then_some(origin)
}
} }
/// Visitor that requires that (almost) all regions in the type visited outlive /// Visitor that requires that (almost) all regions in the type visited outlive

View file

@ -1,5 +1,5 @@
use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::DefId;
use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::at::ToTrace;
use rustc_infer::infer::canonical::CanonicalVarValues; use rustc_infer::infer::canonical::CanonicalVarValues;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@ -935,8 +935,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
} }
} }
pub(super) fn can_define_opaque_ty(&self, def_id: LocalDefId) -> bool { pub(super) fn can_define_opaque_ty(&self, def_id: impl Into<DefId>) -> bool {
self.infcx.opaque_type_origin(def_id).is_some() self.infcx.can_define_opaque_ty(def_id)
} }
pub(super) fn insert_hidden_type( pub(super) fn insert_hidden_type(

View file

@ -155,10 +155,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() { if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() {
if matches!(goal.param_env.reveal(), Reveal::All) if matches!(goal.param_env.reveal(), Reveal::All)
|| matches!(ecx.solver_mode(), SolverMode::Coherence) || matches!(ecx.solver_mode(), SolverMode::Coherence)
|| opaque_ty || ecx.can_define_opaque_ty(opaque_ty.def_id)
.def_id
.as_local()
.is_some_and(|def_id| ecx.can_define_opaque_ty(def_id))
{ {
return Err(NoSolution); return Err(NoSolution);
} }