Skip to content

Commit

Permalink
Auto merge of #134501 - lcnr:member-constraints-yeet, r=oli-obk
Browse files Browse the repository at this point in the history
handle member constraints directly in the mir type checker

cleaner, faster, easier to change going forward :> fixes #109654

r? `@oli-obk` `@compiler-errors`
  • Loading branch information
bors committed Dec 21, 2024
2 parents 54dcff1 + 9792cf0 commit 9bd5f33
Show file tree
Hide file tree
Showing 15 changed files with 392 additions and 499 deletions.
52 changes: 24 additions & 28 deletions compiler/rustc_borrowck/src/member_constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ use std::ops::Index;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxIndexMap;
use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::infer::MemberConstraint;
use rustc_middle::ty::{self, Ty};
use rustc_span::Span;
use tracing::debug;
use tracing::instrument;

/// Compactly stores a set of `R0 member of [R1...Rn]` constraints,
/// indexed by the region `R0`.
Expand All @@ -23,7 +22,7 @@ where
/// Stores the data about each `R0 member of [R1..Rn]` constraint.
/// These are organized into a linked list, so each constraint
/// contains the index of the next constraint with the same `R0`.
constraints: IndexVec<NllMemberConstraintIndex, NllMemberConstraint<'tcx>>,
constraints: IndexVec<NllMemberConstraintIndex, MemberConstraint<'tcx>>,

/// Stores the `R1..Rn` regions for *all* sets. For any given
/// constraint, we keep two indices so that we can pull out a
Expand All @@ -33,7 +32,7 @@ where

/// Represents a `R0 member of [R1..Rn]` constraint
#[derive(Debug)]
pub(crate) struct NllMemberConstraint<'tcx> {
pub(crate) struct MemberConstraint<'tcx> {
next_constraint: Option<NllMemberConstraintIndex>,

/// The span where the hidden type was instantiated.
Expand Down Expand Up @@ -70,37 +69,34 @@ impl Default for MemberConstraintSet<'_, ty::RegionVid> {
}

impl<'tcx> MemberConstraintSet<'tcx, ty::RegionVid> {
pub(crate) fn is_empty(&self) -> bool {
self.constraints.is_empty()
}

/// Pushes a member constraint into the set.
///
/// The input member constraint `m_c` is in the form produced by
/// the `rustc_middle::infer` code.
///
/// The `to_region_vid` callback fn is used to convert the regions
/// within into `RegionVid` format -- it typically consults the
/// `UniversalRegions` data structure that is known to the caller
/// (but which this code is unaware of).
pub(crate) fn push_constraint(
#[instrument(level = "debug", skip(self))]
pub(crate) fn add_member_constraint(
&mut self,
m_c: &MemberConstraint<'tcx>,
mut to_region_vid: impl FnMut(ty::Region<'tcx>) -> ty::RegionVid,
key: ty::OpaqueTypeKey<'tcx>,
hidden_ty: Ty<'tcx>,
definition_span: Span,
member_region_vid: ty::RegionVid,
choice_regions: &[ty::RegionVid],
) {
debug!("push_constraint(m_c={:?})", m_c);
let member_region_vid: ty::RegionVid = to_region_vid(m_c.member_region);
let next_constraint = self.first_constraints.get(&member_region_vid).cloned();
let start_index = self.choice_regions.len();
let end_index = start_index + m_c.choice_regions.len();
debug!("push_constraint: member_region_vid={:?}", member_region_vid);
let constraint_index = self.constraints.push(NllMemberConstraint {
self.choice_regions.extend(choice_regions);
let end_index = self.choice_regions.len();
let constraint_index = self.constraints.push(MemberConstraint {
next_constraint,
member_region_vid,
definition_span: m_c.definition_span,
hidden_ty: m_c.hidden_ty,
key: m_c.key,
definition_span,
hidden_ty,
key,
start_index,
end_index,
});
self.first_constraints.insert(member_region_vid, constraint_index);
self.choice_regions.extend(m_c.choice_regions.iter().map(|&r| to_region_vid(r)));
}
}

Expand Down Expand Up @@ -182,7 +178,7 @@ where
/// R0 member of [R1..Rn]
/// ```
pub(crate) fn choice_regions(&self, pci: NllMemberConstraintIndex) -> &[ty::RegionVid] {
let NllMemberConstraint { start_index, end_index, .. } = &self.constraints[pci];
let MemberConstraint { start_index, end_index, .. } = &self.constraints[pci];
&self.choice_regions[*start_index..*end_index]
}
}
Expand All @@ -191,9 +187,9 @@ impl<'tcx, R> Index<NllMemberConstraintIndex> for MemberConstraintSet<'tcx, R>
where
R: Copy + Eq,
{
type Output = NllMemberConstraint<'tcx>;
type Output = MemberConstraint<'tcx>;

fn index(&self, i: NllMemberConstraintIndex) -> &NllMemberConstraint<'tcx> {
fn index(&self, i: NllMemberConstraintIndex) -> &MemberConstraint<'tcx> {
&self.constraints[i]
}
}
Expand All @@ -215,7 +211,7 @@ where
/// target_list: A -> B -> C -> D -> E -> F -> (None)
/// ```
fn append_list(
constraints: &mut IndexSlice<NllMemberConstraintIndex, NllMemberConstraint<'_>>,
constraints: &mut IndexSlice<NllMemberConstraintIndex, MemberConstraint<'_>>,
target_list: NllMemberConstraintIndex,
source_list: NllMemberConstraintIndex,
) {
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_borrowck/src/region_infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// Given a universal region in scope on the MIR, returns the
/// corresponding index.
///
/// (Panics if `r` is not a registered universal region.)
/// Panics if `r` is not a registered universal region, most notably
/// if it is a placeholder. Handling placeholders requires access to the
/// `MirTypeckRegionConstraints`.
pub(crate) fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
self.universal_regions().to_region_vid(r)
}
Expand Down
21 changes: 3 additions & 18 deletions compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,17 +77,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {

#[instrument(skip(self), level = "debug")]
pub(super) fn convert_all(&mut self, query_constraints: &QueryRegionConstraints<'tcx>) {
let QueryRegionConstraints { outlives, member_constraints } = query_constraints;

// Annoying: to invoke `self.to_region_vid`, we need access to
// `self.constraints`, but we also want to be mutating
// `self.member_constraints`. For now, just swap out the value
// we want and replace at the end.
let mut tmp = std::mem::take(&mut self.constraints.member_constraints);
for member_constraint in member_constraints {
tmp.push_constraint(member_constraint, |r| self.to_region_vid(r));
}
self.constraints.member_constraints = tmp;
let QueryRegionConstraints { outlives } = query_constraints;

for &(predicate, constraint_category) in outlives {
self.convert(predicate, constraint_category);
Expand Down Expand Up @@ -295,13 +285,8 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {

match result {
Ok(TypeOpOutput { output: ty, constraints, .. }) => {
if let Some(constraints) = constraints {
assert!(
constraints.member_constraints.is_empty(),
"no member constraints expected from normalizing: {:#?}",
constraints.member_constraints
);
next_outlives_predicates.extend(constraints.outlives.iter().copied());
if let Some(QueryRegionConstraints { outlives }) = constraints {
next_outlives_predicates.extend(outlives.iter().copied());
}
ty
}
Expand Down
61 changes: 12 additions & 49 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,7 @@ use rustc_mir_dataflow::points::DenseLocationMap;
use rustc_span::def_id::CRATE_DEF_ID;
use rustc_span::source_map::Spanned;
use rustc_span::{DUMMY_SP, Span, sym};
use rustc_trait_selection::traits::query::type_op::custom::{
CustomTypeOp, scrape_region_constraints,
};
use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
use tracing::{debug, instrument, trace};

Expand Down Expand Up @@ -89,6 +87,7 @@ mod constraint_conversion;
pub(crate) mod free_region_relations;
mod input_output;
pub(crate) mod liveness;
mod opaque_types;
mod relate_tys;

/// Type checks the given `mir` in the context of the inference
Expand Down Expand Up @@ -179,52 +178,8 @@ pub(crate) fn type_check<'a, 'tcx>(

liveness::generate(&mut typeck, body, &elements, flow_inits, move_data);

let opaque_type_values = infcx
.take_opaque_types()
.into_iter()
.map(|(opaque_type_key, decl)| {
let _: Result<_, ErrorGuaranteed> = typeck.fully_perform_op(
Locations::All(body.span),
ConstraintCategory::OpaqueType,
CustomTypeOp::new(
|ocx| {
ocx.infcx.register_member_constraints(
opaque_type_key,
decl.hidden_type.ty,
decl.hidden_type.span,
);
Ok(())
},
"opaque_type_map",
),
);
let hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind());
if hidden_type.has_non_region_infer() {
infcx.dcx().span_bug(
decl.hidden_type.span,
format!("could not resolve {:#?}", hidden_type.ty.kind()),
);
}

// Convert all regions to nll vars.
let (opaque_type_key, hidden_type) =
fold_regions(infcx.tcx, (opaque_type_key, hidden_type), |region, _| {
match region.kind() {
ty::ReVar(_) => region,
ty::RePlaceholder(placeholder) => {
typeck.constraints.placeholder_region(infcx, placeholder)
}
_ => ty::Region::new_var(
infcx.tcx,
typeck.universal_regions.to_region_vid(region),
),
}
});

(opaque_type_key, hidden_type)
})
.collect();
let opaque_type_values =
opaque_types::take_opaques_and_register_member_constraints(&mut typeck);

MirTypeckResults { constraints, universal_region_relations, opaque_type_values }
}
Expand Down Expand Up @@ -955,6 +910,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.body
}

fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> RegionVid {
if let ty::RePlaceholder(placeholder) = r.kind() {
self.constraints.placeholder_region(self.infcx, placeholder).as_var()
} else {
self.universal_regions.to_region_vid(r)
}
}

fn unsized_feature_enabled(&self) -> bool {
let features = self.tcx().features();
features.unsized_locals() || features.unsized_fn_params()
Expand Down
Loading

0 comments on commit 9bd5f33

Please sign in to comment.