summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_typeck/src/variance/solve.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:11:38 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:12:43 +0000
commitcf94bdc0742c13e2a0cac864c478b8626b266e1b (patch)
tree044670aa50cc5e2b4229aa0b6b3df6676730c0a6 /compiler/rustc_typeck/src/variance/solve.rs
parentAdding debian version 1.65.0+dfsg1-2. (diff)
downloadrustc-cf94bdc0742c13e2a0cac864c478b8626b266e1b.tar.xz
rustc-cf94bdc0742c13e2a0cac864c478b8626b266e1b.zip
Merging upstream version 1.66.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_typeck/src/variance/solve.rs')
-rw-r--r--compiler/rustc_typeck/src/variance/solve.rs135
1 files changed, 0 insertions, 135 deletions
diff --git a/compiler/rustc_typeck/src/variance/solve.rs b/compiler/rustc_typeck/src/variance/solve.rs
deleted file mode 100644
index 97aca621a..000000000
--- a/compiler/rustc_typeck/src/variance/solve.rs
+++ /dev/null
@@ -1,135 +0,0 @@
-//! Constraint solving
-//!
-//! The final phase iterates over the constraints, refining the variance
-//! for each inferred until a fixed point is reached. This will be the
-//! optimal solution to the constraints. The final variance for each
-//! inferred is then written into the `variance_map` in the tcx.
-
-use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::def_id::DefId;
-use rustc_middle::ty;
-
-use super::constraints::*;
-use super::terms::VarianceTerm::*;
-use super::terms::*;
-use super::xform::*;
-
-struct SolveContext<'a, 'tcx> {
- terms_cx: TermsContext<'a, 'tcx>,
- constraints: Vec<Constraint<'a>>,
-
- // Maps from an InferredIndex to the inferred value for that variable.
- solutions: Vec<ty::Variance>,
-}
-
-pub fn solve_constraints<'tcx>(
- constraints_cx: ConstraintContext<'_, 'tcx>,
-) -> ty::CrateVariancesMap<'tcx> {
- let ConstraintContext { terms_cx, constraints, .. } = constraints_cx;
-
- let mut solutions = vec![ty::Bivariant; terms_cx.inferred_terms.len()];
- for &(id, ref variances) in &terms_cx.lang_items {
- let InferredIndex(start) = terms_cx.inferred_starts[&id];
- for (i, &variance) in variances.iter().enumerate() {
- solutions[start + i] = variance;
- }
- }
-
- let mut solutions_cx = SolveContext { terms_cx, constraints, solutions };
- solutions_cx.solve();
- let variances = solutions_cx.create_map();
-
- ty::CrateVariancesMap { variances }
-}
-
-impl<'a, 'tcx> SolveContext<'a, 'tcx> {
- fn solve(&mut self) {
- // Propagate constraints until a fixed point is reached. Note
- // that the maximum number of iterations is 2C where C is the
- // number of constraints (each variable can change values at most
- // twice). Since number of constraints is linear in size of the
- // input, so is the inference process.
- let mut changed = true;
- while changed {
- changed = false;
-
- for constraint in &self.constraints {
- let Constraint { inferred, variance: term } = *constraint;
- let InferredIndex(inferred) = inferred;
- let variance = self.evaluate(term);
- let old_value = self.solutions[inferred];
- let new_value = glb(variance, old_value);
- if old_value != new_value {
- debug!(
- "updating inferred {} \
- from {:?} to {:?} due to {:?}",
- inferred, old_value, new_value, term
- );
-
- self.solutions[inferred] = new_value;
- changed = true;
- }
- }
- }
- }
-
- fn enforce_const_invariance(&self, generics: &ty::Generics, variances: &mut [ty::Variance]) {
- let tcx = self.terms_cx.tcx;
-
- // Make all const parameters invariant.
- for param in generics.params.iter() {
- if let ty::GenericParamDefKind::Const { .. } = param.kind {
- variances[param.index as usize] = ty::Invariant;
- }
- }
-
- // Make all the const parameters in the parent invariant (recursively).
- if let Some(def_id) = generics.parent {
- self.enforce_const_invariance(tcx.generics_of(def_id), variances);
- }
- }
-
- fn create_map(&self) -> FxHashMap<DefId, &'tcx [ty::Variance]> {
- let tcx = self.terms_cx.tcx;
-
- let solutions = &self.solutions;
- self.terms_cx
- .inferred_starts
- .iter()
- .map(|(&def_id, &InferredIndex(start))| {
- let generics = tcx.generics_of(def_id);
- let count = generics.count();
-
- let variances = tcx.arena.alloc_slice(&solutions[start..(start + count)]);
-
- // Const parameters are always invariant.
- self.enforce_const_invariance(generics, variances);
-
- // Functions are permitted to have unused generic parameters: make those invariant.
- if let ty::FnDef(..) = tcx.type_of(def_id).kind() {
- for variance in variances.iter_mut() {
- if *variance == ty::Bivariant {
- *variance = ty::Invariant;
- }
- }
- }
-
- (def_id.to_def_id(), &*variances)
- })
- .collect()
- }
-
- fn evaluate(&self, term: VarianceTermPtr<'a>) -> ty::Variance {
- match *term {
- ConstantTerm(v) => v,
-
- TransformTerm(t1, t2) => {
- let v1 = self.evaluate(t1);
- let v2 = self.evaluate(t2);
- v1.xform(v2)
- }
-
- InferredTerm(InferredIndex(index)) => self.solutions[index],
- }
- }
-}