Uplift ExternalConstraintData

This commit is contained in:
Michael Goulet 2024-06-14 15:16:47 -04:00
parent f93ee19fd7
commit 9d207cfbc8
7 changed files with 79 additions and 43 deletions

View File

@ -110,7 +110,7 @@ macro_rules! arena_types {
rustc_hir::def_id::DefId,
rustc_middle::ty::EarlyBinder<'tcx, rustc_middle::ty::Ty<'tcx>>
>,
[] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<'tcx>,
[] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<rustc_middle::ty::TyCtxt<'tcx>>,
[] predefined_opaques_in_body: rustc_middle::traits::solve::PredefinedOpaquesData<'tcx>,
[decode] doc_link_resolutions: rustc_hir::def::DocLinkResMap,
[] stripped_cfg_items: rustc_ast::expand::StrippedCfgItem,

View File

@ -1,6 +1,6 @@
use rustc_ast_ir::try_visit;
use rustc_data_structures::intern::Interned;
use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
use rustc_macros::HashStable;
use rustc_type_ir as ir;
pub use rustc_type_ir::solve::*;
@ -37,37 +37,18 @@ impl<'tcx> std::ops::Deref for PredefinedOpaques<'tcx> {
}
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, HashStable)]
pub struct ExternalConstraints<'tcx>(pub(crate) Interned<'tcx, ExternalConstraintsData<'tcx>>);
pub struct ExternalConstraints<'tcx>(
pub(crate) Interned<'tcx, ExternalConstraintsData<TyCtxt<'tcx>>>,
);
impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> {
type Target = ExternalConstraintsData<'tcx>;
type Target = ExternalConstraintsData<TyCtxt<'tcx>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
/// Additional constraints returned on success.
#[derive(Debug, PartialEq, Eq, Clone, Hash, HashStable, Default, TypeVisitable, TypeFoldable)]
pub struct ExternalConstraintsData<'tcx> {
// FIXME: implement this.
pub region_constraints: Vec<ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>>,
pub opaque_types: Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>,
pub normalization_nested_goals: NestedNormalizationGoals<'tcx>,
}
#[derive(Debug, PartialEq, Eq, Clone, Hash, HashStable, Default, TypeVisitable, TypeFoldable)]
pub struct NestedNormalizationGoals<'tcx>(pub Vec<(GoalSource, Goal<'tcx, ty::Predicate<'tcx>>)>);
impl<'tcx> NestedNormalizationGoals<'tcx> {
pub fn empty() -> Self {
NestedNormalizationGoals(vec![])
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
// FIXME: Having to clone `region_constraints` for folding feels bad and
// probably isn't great wrt performance.
//

View File

@ -88,6 +88,7 @@ use std::ops::{Bound, Deref};
#[allow(rustc::usage_of_ty_tykind)]
impl<'tcx> Interner for TyCtxt<'tcx> {
type DefId = DefId;
type LocalDefId = LocalDefId;
type AdtDef = ty::AdtDef<'tcx>;
type GenericArgs = ty::GenericArgsRef<'tcx>;
@ -382,7 +383,7 @@ pub struct CtxtInterners<'tcx> {
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
layout: InternedSet<'tcx, LayoutS<FieldIdx, VariantIdx>>,
adt_def: InternedSet<'tcx, AdtDefData>,
external_constraints: InternedSet<'tcx, ExternalConstraintsData<'tcx>>,
external_constraints: InternedSet<'tcx, ExternalConstraintsData<TyCtxt<'tcx>>>,
predefined_opaques_in_body: InternedSet<'tcx, PredefinedOpaquesData<'tcx>>,
fields: InternedSet<'tcx, List<FieldIdx>>,
local_def_ids: InternedSet<'tcx, List<LocalDefId>>,
@ -2093,7 +2094,7 @@ direct_interners! {
const_allocation: pub mk_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
layout: pub mk_layout(LayoutS<FieldIdx, VariantIdx>): Layout -> Layout<'tcx>,
adt_def: pub mk_adt_def_from_data(AdtDefData): AdtDef -> AdtDef<'tcx>,
external_constraints: pub mk_external_constraints(ExternalConstraintsData<'tcx>):
external_constraints: pub mk_external_constraints(ExternalConstraintsData<TyCtxt<'tcx>>):
ExternalConstraints -> ExternalConstraints<'tcx>,
predefined_opaques_in_body: pub mk_predefined_opaques_in_body(PredefinedOpaquesData<'tcx>):
PredefinedOpaques -> PredefinedOpaques<'tcx>,

View File

@ -14,6 +14,7 @@ use crate::solve::{
inspect, response_no_constraints_raw, CanonicalResponse, QueryResult, Response,
};
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::LocalDefId;
use rustc_index::IndexVec;
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
@ -178,8 +179,8 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
fn compute_external_query_constraints(
&self,
certainty: Certainty,
normalization_nested_goals: NestedNormalizationGoals<'tcx>,
) -> ExternalConstraintsData<'tcx> {
normalization_nested_goals: NestedNormalizationGoals<TyCtxt<'tcx>>,
) -> ExternalConstraintsData<TyCtxt<'tcx>> {
// We only return region constraints once the certainty is `Yes`. This
// is necessary as we may drop nested goals on ambiguity, which may result
// in unconstrained inference variables in the region constraints. It also
@ -213,13 +214,20 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
Default::default()
};
let mut opaque_types = self.infcx.clone_opaque_types_for_query_response();
// Only return opaque type keys for newly-defined opaques
opaque_types.retain(|(a, _)| {
self.predefined_opaques_in_body.opaque_types.iter().all(|(pa, _)| pa != a)
});
ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals }
ExternalConstraintsData {
region_constraints,
opaque_types: self
.infcx
.clone_opaque_types_for_query_response()
.into_iter()
// Only return *newly defined* opaque types.
.filter(|(a, _)| {
self.predefined_opaques_in_body.opaque_types.iter().all(|(pa, _)| pa != a)
})
.map(|(key, value)| (key.def_id, key.args, value))
.collect(),
normalization_nested_goals,
}
}
/// After calling a canonical query, we apply the constraints returned
@ -235,7 +243,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
param_env: ty::ParamEnv<'tcx>,
original_values: Vec<ty::GenericArg<'tcx>>,
response: CanonicalResponse<'tcx>,
) -> (NestedNormalizationGoals<'tcx>, Certainty) {
) -> (NestedNormalizationGoals<TyCtxt<'tcx>>, Certainty) {
let instantiation = Self::compute_query_response_instantiation_values(
self.infcx,
&original_values,
@ -385,10 +393,14 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
}
}
fn register_new_opaque_types(&mut self, opaque_types: &[(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)]) {
for &(key, ty) in opaque_types {
fn register_new_opaque_types(
&mut self,
opaque_types: &[(LocalDefId, ty::GenericArgsRef<'tcx>, Ty<'tcx>)],
) {
for &(def_id, args, ty) in opaque_types {
let hidden_ty = ty::OpaqueHiddenType { ty, span: DUMMY_SP };
self.infcx.inject_new_hidden_type_unchecked(key, hidden_ty);
self.infcx
.inject_new_hidden_type_unchecked(ty::OpaqueTypeKey { def_id, args }, hidden_ty);
}
}
}

View File

@ -337,7 +337,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
goal_evaluation_kind: GoalEvaluationKind,
_source: GoalSource,
goal: Goal<'tcx, ty::Predicate<'tcx>>,
) -> Result<(NestedNormalizationGoals<'tcx>, bool, Certainty), NoSolution> {
) -> Result<(NestedNormalizationGoals<TyCtxt<'tcx>>, bool, Certainty), NoSolution> {
let (orig_values, canonical_goal) = self.canonicalize_goal(goal);
let mut goal_evaluation =
self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind);
@ -380,7 +380,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
param_env: ty::ParamEnv<'tcx>,
original_values: Vec<ty::GenericArg<'tcx>>,
response: CanonicalResponse<'tcx>,
) -> (NestedNormalizationGoals<'tcx>, Certainty, bool) {
) -> (NestedNormalizationGoals<TyCtxt<'tcx>>, Certainty, bool) {
if let Certainty::Maybe(MaybeCause::Overflow { .. }) = response.value.certainty {
return (NestedNormalizationGoals::empty(), response.value.certainty, false);
}

View File

@ -29,6 +29,7 @@ pub trait Interner:
+ IrPrint<ty::FnSig<Self>>
{
type DefId: Copy + Debug + Hash + Eq + TypeFoldable<Self>;
type LocalDefId: Copy + Debug + Hash + Eq + TypeFoldable<Self>;
type AdtDef: AdtDef<Self>;
type GenericArgs: GenericArgs<Self>;

View File

@ -7,7 +7,7 @@ use std::hash::Hash;
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
use crate::{Canonical, CanonicalVarValues, Interner, Upcast};
use crate::{self as ty, Canonical, CanonicalVarValues, Interner, Upcast};
/// Depending on the stage of compilation, we want projection to be
/// more or less conservative.
@ -254,6 +254,47 @@ pub struct Response<I: Interner> {
pub external_constraints: I::ExternalConstraints,
}
/// Additional constraints returned on success.
#[derive(derivative::Derivative)]
#[derivative(
Clone(bound = ""),
Hash(bound = ""),
PartialEq(bound = ""),
Eq(bound = ""),
Debug(bound = ""),
Default(bound = "")
)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
pub struct ExternalConstraintsData<I: Interner> {
pub region_constraints: Vec<ty::OutlivesPredicate<I, I::GenericArg>>,
pub opaque_types: Vec<(I::LocalDefId, I::GenericArgs, I::Ty)>,
pub normalization_nested_goals: NestedNormalizationGoals<I>,
}
#[derive(derivative::Derivative)]
#[derivative(
Clone(bound = ""),
Hash(bound = ""),
PartialEq(bound = ""),
Eq(bound = ""),
Debug(bound = ""),
Default(bound = "")
)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
pub struct NestedNormalizationGoals<I: Interner>(pub Vec<(GoalSource, Goal<I, I::Predicate>)>);
impl<I: Interner> NestedNormalizationGoals<I> {
pub fn empty() -> Self {
NestedNormalizationGoals(vec![])
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
pub enum Certainty {