summaryrefslogtreecommitdiffstats
path: root/vendor/chalk-solve-0.87.0/src/coherence
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /vendor/chalk-solve-0.87.0/src/coherence
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz
rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/chalk-solve-0.87.0/src/coherence')
-rw-r--r--vendor/chalk-solve-0.87.0/src/coherence/orphan.rs44
-rw-r--r--vendor/chalk-solve-0.87.0/src/coherence/solve.rs260
2 files changed, 0 insertions, 304 deletions
diff --git a/vendor/chalk-solve-0.87.0/src/coherence/orphan.rs b/vendor/chalk-solve-0.87.0/src/coherence/orphan.rs
deleted file mode 100644
index f8e06b901..000000000
--- a/vendor/chalk-solve-0.87.0/src/coherence/orphan.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-use crate::coherence::CoherenceError;
-use crate::ext::GoalExt;
-use crate::solve::Solver;
-use crate::RustIrDatabase;
-use chalk_ir::cast::*;
-use chalk_ir::interner::Interner;
-use chalk_ir::*;
-use tracing::{debug, instrument};
-
-// Test if a local impl violates the orphan rules.
-//
-// For `impl<T> Trait for MyType<T>` we generate:
-//
-// forall<T> { LocalImplAllowed(MyType<T>: Trait) }
-//
-// This must be provable in order to pass the orphan check.
-#[instrument(level = "debug", skip(db, solver))]
-pub fn perform_orphan_check<I: Interner>(
- db: &dyn RustIrDatabase<I>,
- solver: &mut dyn Solver<I>,
- impl_id: ImplId<I>,
-) -> Result<(), CoherenceError<I>> {
- let impl_datum = db.impl_datum(impl_id);
- debug!(?impl_datum);
-
- let impl_allowed: Goal<I> = impl_datum
- .binders
- .map_ref(|bound_impl| {
- // Ignoring the polarization of the impl's polarized trait ref
- DomainGoal::LocalImplAllowed(bound_impl.trait_ref.clone())
- })
- .cast(db.interner());
-
- let canonical_goal = &impl_allowed.into_closed_goal(db.interner());
- let is_allowed = solver.solve(db, canonical_goal).is_some();
- debug!("overlaps = {:?}", is_allowed);
-
- if !is_allowed {
- let trait_id = impl_datum.trait_id();
- return Err(CoherenceError::FailedOrphanCheck(trait_id));
- }
-
- Ok(())
-}
diff --git a/vendor/chalk-solve-0.87.0/src/coherence/solve.rs b/vendor/chalk-solve-0.87.0/src/coherence/solve.rs
deleted file mode 100644
index 57dd81061..000000000
--- a/vendor/chalk-solve-0.87.0/src/coherence/solve.rs
+++ /dev/null
@@ -1,260 +0,0 @@
-use crate::coherence::{CoherenceError, CoherenceSolver};
-use crate::debug_span;
-use crate::ext::*;
-use crate::rust_ir::*;
-use crate::{goal_builder::GoalBuilder, Solution};
-use chalk_ir::cast::*;
-use chalk_ir::fold::shift::Shift;
-use chalk_ir::interner::Interner;
-use chalk_ir::*;
-use itertools::Itertools;
-use tracing::{debug, instrument};
-
-impl<I: Interner> CoherenceSolver<'_, I> {
- pub(super) fn visit_specializations_of_trait(
- &self,
- mut record_specialization: impl FnMut(ImplId<I>, ImplId<I>),
- ) -> Result<(), CoherenceError<I>> {
- // Ignore impls for marker traits as they are allowed to overlap.
- let trait_datum = self.db.trait_datum(self.trait_id);
- if trait_datum.flags.marker {
- return Ok(());
- }
-
- // Iterate over every pair of impls for the same trait.
- let impls = self.db.local_impls_to_coherence_check(self.trait_id);
- for (l_id, r_id) in impls.into_iter().tuple_combinations() {
- let lhs = &self.db.impl_datum(l_id);
- let rhs = &self.db.impl_datum(r_id);
-
- // Two negative impls never overlap.
- if !lhs.is_positive() && !rhs.is_positive() {
- continue;
- }
-
- // Check if the impls overlap, then if they do, check if one specializes
- // the other. Note that specialization can only run one way - if both
- // specialization checks return *either* true or false, that's an error.
- if !self.disjoint(lhs, rhs) {
- match (self.specializes(l_id, r_id), self.specializes(r_id, l_id)) {
- (true, false) => record_specialization(l_id, r_id),
- (false, true) => record_specialization(r_id, l_id),
- (_, _) => {
- return Err(CoherenceError::OverlappingImpls(self.trait_id));
- }
- }
- }
- }
-
- Ok(())
- }
-
- // Test if the set of types that these two impls apply to overlap. If the test succeeds, these
- // two impls are disjoint.
- //
- // We combine the binders of the two impls & treat them as existential quantifiers. Then we
- // attempt to unify the input types to the trait provided by each impl, as well as prove that
- // the where clauses from both impls all hold. At the end, we apply the `compatible` modality
- // and negate the query. Negating the query means that we are asking chalk to prove that no
- // such overlapping impl exists. By applying `compatible { G }`, chalk attempts to prove that
- // "there exists a compatible world where G is provable." When we negate compatible, it turns
- // into the statement "for all compatible worlds, G is not provable." This is exactly what we
- // want since we want to ensure that there is no overlap in *all* compatible worlds, not just
- // that there is no overlap in *some* compatible world.
- //
- // Examples:
- //
- // Impls:
- // impl<T> Foo for T { } // rhs
- // impl Foo for i32 { } // lhs
- // Generates:
- // not { compatible { exists<T> { exists<> { T = i32 } } } }
- //
- // Impls:
- // impl<T1, U> Foo<T1> for Vec<U> { } // rhs
- // impl<T2> Foo<T2> for Vec<i32> { } // lhs
- // Generates:
- // not { compatible { exists<T1, U> { exists<T2> { Vec<U> = Vec<i32>, T1 = T2 } } } }
- //
- // Impls:
- // impl<T> Foo for Vec<T> where T: Bar { }
- // impl<U> Foo for Vec<U> where U: Baz { }
- // Generates:
- // not { compatible { exists<T> { exists<U> { Vec<T> = Vec<U>, T: Bar, U: Baz } } } }
- //
- #[instrument(level = "debug", skip(self))]
- fn disjoint(&self, lhs: &ImplDatum<I>, rhs: &ImplDatum<I>) -> bool {
- let interner = self.db.interner();
-
- let (lhs_binders, lhs_bound) = lhs.binders.as_ref().into();
- let (rhs_binders, rhs_bound) = rhs.binders.as_ref().into();
-
- // Upshift the rhs variables in params to account for the joined binders
- let lhs_params = lhs_bound
- .trait_ref
- .substitution
- .as_slice(interner)
- .iter()
- .cloned();
- let rhs_params = rhs_bound
- .trait_ref
- .substitution
- .as_slice(interner)
- .iter()
- .map(|param| param.clone().shifted_in(interner));
-
- // Create an equality goal for every input type the trait, attempting
- // to unify the inputs to both impls with one another
- let params_goals = lhs_params
- .zip(rhs_params)
- .map(|(a, b)| GoalData::EqGoal(EqGoal { a, b }).intern(interner));
-
- // Upshift the rhs variables in where clauses
- let lhs_where_clauses = lhs_bound.where_clauses.iter().cloned();
- let rhs_where_clauses = rhs_bound
- .where_clauses
- .iter()
- .map(|wc| wc.clone().shifted_in(interner));
-
- // Create a goal for each clause in both where clauses
- let wc_goals = lhs_where_clauses
- .chain(rhs_where_clauses)
- .map(|wc| wc.cast(interner));
-
- // Join all the goals we've created together with And, then quantify them
- // over the joined binders. This is our query.
- let goal = Box::new(Goal::all(interner, params_goals.chain(wc_goals)))
- .quantify(interner, QuantifierKind::Exists, lhs_binders)
- .quantify(interner, QuantifierKind::Exists, rhs_binders)
- .compatible(interner)
- .negate(interner);
-
- let canonical_goal = &goal.into_closed_goal(interner);
- let mut fresh_solver = (self.solver_builder)();
- let solution = fresh_solver.solve(self.db, canonical_goal);
- let result = match solution {
- // Goal was proven with a unique solution, so no impl was found that causes these two
- // to overlap
- Some(Solution::Unique(_)) => true,
- // Goal was ambiguous, so there *may* be overlap
- Some(Solution::Ambig(_)) |
- // Goal cannot be proven, so there is some impl that causes overlap
- None => false,
- };
- debug!("overlaps: result = {:?}", result);
- result
- }
-
- // Creates a goal which, if provable, means "more special" impl specializes the "less special" one.
- //
- // # General rule
- //
- // Given the more special impl:
- //
- // ```ignore
- // impl<P0..Pn> SomeTrait<T1..Tm> for T0 where WC_more
- // ```
- //
- // and less special impl
- //
- // ```ignore
- // impl<Q0..Qo> SomeTrait<U1..Um> for U0 where WC_less
- // ```
- //
- // create the goal:
- //
- // ```ignore
- // forall<P0..Pn> {
- // if (WC_more) {}
- // exists<Q0..Qo> {
- // T0 = U0, ..., Tm = Um,
- // WC_less
- // }
- // }
- // }
- // ```
- //
- // # Example
- //
- // Given:
- //
- // * more: `impl<T: Clone> Foo for Vec<T>`
- // * less: `impl<U: Clone> Foo for U`
- //
- // Resulting goal:
- //
- // ```ignore
- // forall<T> {
- // if (T: Clone) {
- // exists<U> {
- // Vec<T> = U, U: Clone
- // }
- // }
- // }
- // ```
- #[instrument(level = "debug", skip(self))]
- fn specializes(&self, less_special_id: ImplId<I>, more_special_id: ImplId<I>) -> bool {
- let more_special = &self.db.impl_datum(more_special_id);
- let less_special = &self.db.impl_datum(less_special_id);
- debug_span!("specializes", ?less_special, ?more_special);
-
- let interner = self.db.interner();
-
- let gb = &mut GoalBuilder::new(self.db);
-
- // forall<P0..Pn> { ... }
- let goal = gb.forall(
- &more_special.binders,
- less_special_id,
- |gb, _, more_special_impl, less_special_id| {
- // if (WC_more) { ... }
- gb.implies(more_special_impl.where_clauses.iter().cloned(), |gb| {
- let less_special = &gb.db().impl_datum(less_special_id);
-
- // exists<Q0..Qn> { ... }
- gb.exists(
- &less_special.binders,
- more_special_impl.trait_ref.clone(),
- |gb, _, less_special_impl, more_special_trait_ref| {
- let interner = gb.interner();
-
- // T0 = U0, ..., Tm = Um
- let params_goals = more_special_trait_ref
- .substitution
- .as_slice(interner)
- .iter()
- .cloned()
- .zip(
- less_special_impl
- .trait_ref
- .substitution
- .as_slice(interner)
- .iter()
- .cloned(),
- )
- .map(|(a, b)| GoalData::EqGoal(EqGoal { a, b }).intern(interner));
-
- // <less_special_wc_goals> = where clauses from the less special impl
- let less_special_wc_goals = less_special_impl
- .where_clauses
- .iter()
- .cloned()
- .casted(interner);
-
- // <equality_goals> && WC_less
- gb.all(params_goals.chain(less_special_wc_goals))
- },
- )
- })
- },
- );
-
- let canonical_goal = &goal.into_closed_goal(interner);
- let mut fresh_solver = (self.solver_builder)();
- let result = fresh_solver.has_unique_solution(self.db, canonical_goal);
-
- debug!("specializes: result = {:?}", result);
-
- result
- }
-}