summaryrefslogtreecommitdiffstats
path: root/vendor/chalk-solve-0.87.0/src/infer/test.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/chalk-solve-0.87.0/src/infer/test.rs')
-rw-r--r--vendor/chalk-solve-0.87.0/src/infer/test.rs422
1 files changed, 422 insertions, 0 deletions
diff --git a/vendor/chalk-solve-0.87.0/src/infer/test.rs b/vendor/chalk-solve-0.87.0/src/infer/test.rs
new file mode 100644
index 000000000..2ac35f027
--- /dev/null
+++ b/vendor/chalk-solve-0.87.0/src/infer/test.rs
@@ -0,0 +1,422 @@
+#![cfg(test)]
+
+use super::unify::RelationResult;
+use super::*;
+use chalk_integration::interner::ChalkIr;
+use chalk_integration::{arg, lifetime, ty};
+
+// We just use a vec of 20 `Invariant`, since this is zipped and no substs are
+// longer than this
+#[derive(Debug)]
+struct TestDatabase;
+impl UnificationDatabase<ChalkIr> for TestDatabase {
+ fn fn_def_variance(&self, _fn_def_id: FnDefId<ChalkIr>) -> Variances<ChalkIr> {
+ Variances::from_iter(ChalkIr, [Variance::Invariant; 20].iter().copied())
+ }
+
+ fn adt_variance(&self, _adt_id: AdtId<ChalkIr>) -> Variances<ChalkIr> {
+ Variances::from_iter(ChalkIr, [Variance::Invariant; 20].iter().copied())
+ }
+}
+
+#[test]
+fn universe_error() {
+ // exists(A -> forall(X -> A = X)) ---> error
+ let interner = ChalkIr;
+ let mut table: InferenceTable<ChalkIr> = InferenceTable::new();
+ let environment0 = Environment::new(interner);
+ let a = table.new_variable(U0).to_ty(interner);
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &a,
+ &ty!(placeholder 1),
+ )
+ .unwrap_err();
+}
+
+#[test]
+fn cycle_error() {
+ // exists(A -> A = foo A) ---> error
+ let interner = ChalkIr;
+ let mut table: InferenceTable<ChalkIr> = InferenceTable::new();
+ let environment0 = Environment::new(interner);
+ let a = table.new_variable(U0).to_ty(interner);
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &a,
+ &ty!(apply (item 0) (expr a)),
+ )
+ .unwrap_err();
+
+ // exists(A -> A = for<'a> A)
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &a,
+ &ty!(function 1 (infer 0)),
+ )
+ .unwrap_err();
+}
+
+#[test]
+fn cycle_indirect() {
+ // exists(A -> A = foo B, A = B) ---> error
+ let interner = ChalkIr;
+ let mut table: InferenceTable<ChalkIr> = InferenceTable::new();
+ let environment0 = Environment::new(interner);
+ let a = table.new_variable(U0).to_ty(interner);
+ let b = table.new_variable(U0).to_ty(interner);
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &a,
+ &ty!(apply (item 0) (expr b)),
+ )
+ .unwrap();
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &a,
+ &b,
+ )
+ .unwrap_err();
+}
+
+#[test]
+fn universe_error_indirect_1() {
+ // exists(A -> forall(X -> exists(B -> B = X, A = B))) ---> error
+ let interner = ChalkIr;
+ let mut table: InferenceTable<ChalkIr> = InferenceTable::new();
+ let environment0 = Environment::new(interner);
+ let a = table.new_variable(U0).to_ty(interner);
+ let b = table.new_variable(U1).to_ty(interner);
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &b,
+ &ty!(placeholder 1),
+ )
+ .unwrap();
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &a,
+ &b,
+ )
+ .unwrap_err();
+}
+
+#[test]
+fn universe_error_indirect_2() {
+ // exists(A -> forall(X -> exists(B -> B = A, B = X))) ---> error
+ let interner = ChalkIr;
+ let mut table: InferenceTable<ChalkIr> = InferenceTable::new();
+ let environment0 = Environment::new(interner);
+ let a = table.new_variable(U0).to_ty(interner);
+ let b = table.new_variable(U1).to_ty(interner);
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &a,
+ &b,
+ )
+ .unwrap();
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &b,
+ &ty!(placeholder 1),
+ )
+ .unwrap_err();
+}
+
+#[test]
+fn universe_promote() {
+ // exists(A -> forall(X -> exists(B -> A = foo(B), A = foo(i32)))) ---> OK
+ let interner = ChalkIr;
+ let mut table: InferenceTable<ChalkIr> = InferenceTable::new();
+ let environment0 = Environment::new(interner);
+ let a = table.new_variable(U0).to_ty(interner);
+ let b = table.new_variable(U1).to_ty(interner);
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &a,
+ &ty!(apply (item 0) (expr b)),
+ )
+ .unwrap();
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &a,
+ &ty!(apply (item 0) (apply (item 1))),
+ )
+ .unwrap();
+}
+
+#[test]
+fn universe_promote_bad() {
+ // exists(A -> forall(X -> exists(B -> A = foo(B), B = X))) ---> error
+ let interner = ChalkIr;
+ let mut table: InferenceTable<ChalkIr> = InferenceTable::new();
+ let environment0 = Environment::new(interner);
+ let a = table.new_variable(U0).to_ty(interner);
+ let b = table.new_variable(U1).to_ty(interner);
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &a,
+ &ty!(apply (item 0) (expr b)),
+ )
+ .unwrap();
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &b,
+ &ty!(placeholder 1),
+ )
+ .unwrap_err();
+}
+
+#[test]
+fn projection_eq() {
+ // exists(A -> A = Item0<<A as Item1>::foo>)
+ // ^^^^^^^^^^^^ Can A repeat here? For now,
+ // we say no, but it's an interesting question.
+ let interner = ChalkIr;
+ let mut table: InferenceTable<ChalkIr> = InferenceTable::new();
+ let environment0 = Environment::new(interner);
+ let a = table.new_variable(U0).to_ty(interner);
+
+ // expect an error ("cycle during unification")
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &a,
+ &ty!(apply (item 0) (projection (item 1) (expr a))),
+ )
+ .unwrap_err();
+}
+
+const U0: UniverseIndex = UniverseIndex { counter: 0 };
+const U1: UniverseIndex = UniverseIndex { counter: 1 };
+const U2: UniverseIndex = UniverseIndex { counter: 2 };
+
+fn make_table() -> InferenceTable<ChalkIr> {
+ let mut table: InferenceTable<ChalkIr> = InferenceTable::new();
+ let _ = table.new_universe(); // U1
+ let _ = table.new_universe(); // U2
+ table
+}
+
+#[test]
+fn quantify_simple() {
+ let interner = ChalkIr;
+ let mut table = make_table();
+ let _ = table.new_variable(U0);
+ let _ = table.new_variable(U1);
+ let _ = table.new_variable(U2);
+
+ assert_eq!(
+ table
+ .canonicalize(interner, ty!(apply (item 0) (infer 2) (infer 1) (infer 0)))
+ .quantified,
+ Canonical {
+ value: ty!(apply (item 0) (bound 0) (bound 1) (bound 2)),
+ binders: CanonicalVarKinds::from_iter(
+ interner,
+ vec![
+ CanonicalVarKind::new(VariableKind::Ty(TyVariableKind::General), U2),
+ CanonicalVarKind::new(VariableKind::Ty(TyVariableKind::General), U1),
+ CanonicalVarKind::new(VariableKind::Ty(TyVariableKind::General), U0),
+ ]
+ ),
+ }
+ );
+}
+
+#[test]
+fn quantify_bound() {
+ let interner = ChalkIr;
+ let mut table = make_table();
+ let environment0 = Environment::new(interner);
+
+ let v0 = table.new_variable(U0).to_ty(interner);
+ let v1 = table.new_variable(U1).to_ty(interner);
+ let v2a = table.new_variable(U2).to_ty(interner);
+ let v2b = table.new_variable(U2).to_ty(interner);
+
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &v2b,
+ &ty!(apply (item 1) (expr v1) (expr v0)),
+ )
+ .unwrap();
+
+ assert_eq!(
+ table
+ .canonicalize(
+ interner,
+ ty!(apply (item 0) (expr v2b) (expr v2a) (expr v1) (expr v0))
+ )
+ .quantified,
+ Canonical {
+ value: ty!(apply (item 0) (apply (item 1) (bound 0) (bound 1)) (bound 2) (bound 0) (bound 1)),
+ binders: CanonicalVarKinds::from_iter(
+ interner,
+ vec![
+ CanonicalVarKind::new(VariableKind::Ty(TyVariableKind::General), U1),
+ CanonicalVarKind::new(VariableKind::Ty(TyVariableKind::General), U0),
+ CanonicalVarKind::new(VariableKind::Ty(TyVariableKind::General), U2),
+ ]
+ ),
+ }
+ );
+}
+
+#[test]
+fn quantify_ty_under_binder() {
+ let interner = ChalkIr;
+ let mut table = make_table();
+ let v0 = table.new_variable(U0);
+ let v1 = table.new_variable(U0);
+ let _r2 = table.new_variable(U0);
+
+ // Unify v0 and v1.
+ let environment0 = Environment::new(interner);
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &v0.to_ty(interner),
+ &v1.to_ty(interner),
+ )
+ .unwrap();
+
+ // Here: the `function` introduces 3 binders, so in the result,
+ // `(bound 3)` references the first canonicalized inference
+ // variable. -- note that `infer 0` and `infer 1` have been
+ // unified above, as well.
+ assert_eq!(
+ table
+ .canonicalize(
+ interner,
+ ty!(function 3 (apply (item 0) (bound 1) (infer 0) (infer 1) (lifetime (infer 2))))
+ )
+ .quantified,
+ Canonical {
+ value: ty!(function 3 (apply (item 0) (bound 1) (bound 1 0) (bound 1 0) (lifetime (bound 1 1)))),
+ binders: CanonicalVarKinds::from_iter(
+ interner,
+ vec![
+ CanonicalVarKind::new(VariableKind::Ty(TyVariableKind::General), U0),
+ CanonicalVarKind::new(VariableKind::Lifetime, U0)
+ ]
+ ),
+ }
+ );
+}
+
+#[test]
+fn lifetime_constraint_indirect() {
+ let interner = ChalkIr;
+ let mut table: InferenceTable<ChalkIr> = InferenceTable::new();
+ let _ = table.new_universe(); // U1
+
+ let _t_0 = table.new_variable(U0);
+ let _l_1 = table.new_variable(U1);
+
+ let environment0 = Environment::new(interner);
+
+ // Here, we unify '?1 (the lifetime variable in universe 1) with
+ // '!1.
+ let t_a = ty!(apply (item 0) (lifetime (placeholder 1)));
+ let t_b = ty!(apply (item 0) (lifetime (infer 1)));
+ let RelationResult { goals } = table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &t_a,
+ &t_b,
+ )
+ .unwrap();
+ assert!(goals.is_empty());
+
+ // Here, we try to unify `?0` (the type variable in universe 0)
+ // with something that involves `'?1`. Since `'?1` has been
+ // unified with `'!1`, and `'!1` is not visible from universe 0,
+ // we will replace `'!1` with a new variable `'?2` and introduce a
+ // (likely unsatisfiable) constraint relating them.
+ let t_c = ty!(infer 0);
+ let RelationResult { goals } = table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &t_c,
+ &t_b,
+ )
+ .unwrap();
+ assert_eq!(goals.len(), 2);
+ assert_eq!(
+ format!("{:?}", goals[0]),
+ "InEnvironment { environment: Env([]), goal: \'?2: \'!1_0 }",
+ );
+ assert_eq!(
+ format!("{:?}", goals[1]),
+ "InEnvironment { environment: Env([]), goal: \'!1_0: \'?2 }",
+ );
+}