Skip to content

Commit 5f95957

Browse files
committed
Prove ConstHasType predicates
1 parent 87c5746 commit 5f95957

File tree

5 files changed

+47
-10
lines changed

5 files changed

+47
-10
lines changed

crates/formality-prove/src/prove/prove_wc.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,5 +114,12 @@ judgment_fn! {
114114
----------------------------- ("trait ref is local")
115115
(prove_wc(decls, env, assumptions, Relation::WellFormed(p)) => c)
116116
)
117+
118+
(
119+
(if ct.as_value().is_some())
120+
(prove(decls, env, assumptions, Wcs::all_eq(vec![ct.as_value().unwrap().1], vec![ty])) => c)
121+
----------------------------- ("const has ty")
122+
(prove_wc(decls, env, assumptions, Predicate::ConstHasType(ct, ty)) => c)
123+
)
117124
}
118125
}

crates/formality-rust/src/prove.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ use formality_types::{
99
cast::{To, Upcast, Upcasted},
1010
collections::Set,
1111
grammar::{
12-
fresh_bound_var, AdtId, AliasTy, Binder, ParameterKind, Predicate, Relation, TraitId, Ty,
13-
Wc, Wcs, PR,
12+
fresh_bound_var, AdtId, AliasTy, Binder, ConstData, ParameterKind, Predicate, Relation,
13+
TraitId, Ty, Wc, Wcs, PR,
1414
},
1515
seq,
1616
};
@@ -386,9 +386,12 @@ impl ToWcs for WhereClause {
386386
.map(|wc| Wc::for_all(&vars, wc))
387387
.collect()
388388
}
389-
WhereClauseData::TypeOfConst(ct, ty) => {
390-
Predicate::ConstHasType(ct.clone(), ty.clone()).upcast()
391-
}
389+
WhereClauseData::TypeOfConst(ct, ty) => match ct.data() {
390+
// Concrete constants must have equal types
391+
ConstData::Value(_, t) => Relation::eq(ty, t).upcast(),
392+
// Generic constants must have where bounds constraining their type
393+
ConstData::Variable(_) => Predicate::ConstHasType(ct.clone(), ty.clone()).upcast(),
394+
},
392395
}
393396
}
394397
}

crates/formality-types/src/grammar/consts.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ impl Const {
3232
ConstData::Variable(var) => Some(var.clone()),
3333
}
3434
}
35+
36+
pub fn as_value(&self) -> Option<(ValTree, Ty)> {
37+
match self.data() {
38+
ConstData::Value(v, t) => Some((v.clone(), t.clone())),
39+
ConstData::Variable(_) => None,
40+
}
41+
}
3542
}
3643

3744
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Visit)]

crates/formality-types/src/grammar/formulas.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ pub enum Skeleton {
9393
impl Predicate {
9494
/// Separate an atomic predicate into the "skeleton" (which can be compared for equality using `==`)
9595
/// and the parameters (which must be related).
96+
#[tracing::instrument(level = "trace", ret)]
9697
pub fn debone(&self) -> (Skeleton, Vec<Parameter>) {
9798
match self {
9899
Predicate::IsImplemented(TraitRef {
@@ -171,6 +172,7 @@ impl Relation {
171172
Self::Sub(p1.upcast(), p2.upcast())
172173
}
173174

175+
#[tracing::instrument(level = "trace", ret)]
174176
pub fn debone(&self) -> (Skeleton, Vec<Parameter>) {
175177
match self {
176178
Relation::Equals(a, b) => (Skeleton::Equals, vec![a.clone(), b.clone()]),

tests/consts.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,8 @@ fn test_ok() {
2323
#[test]
2424
fn test_holds() {
2525
expect_test::expect![[r#"
26-
Err(
27-
Error {
28-
context: "check_trait_impl(impl <> Foo < const 0_(rigid (scalar bool)) > for (rigid (scalar u32)) where [] { })",
29-
source: "failed to prove {Foo((rigid (scalar u32)), const 0_(rigid (scalar bool)))} given {}, got {}",
30-
},
26+
Ok(
27+
(),
3128
)
3229
"#]]
3330
.assert_debug_eq(&test_program_ok(
@@ -61,3 +58,24 @@ fn test_mismatch() {
6158
]",
6259
));
6360
}
61+
62+
#[test]
63+
fn test_generic_mismatch() {
64+
expect_test::expect![[r#"
65+
Err(
66+
Error {
67+
context: "check_trait_impl(impl <const> Foo < const ^const0_0 > for (rigid (scalar u32)) where [type_of_const ^const0_0 is (rigid (scalar u32))] { })",
68+
source: "failed to prove {Foo((rigid (scalar u32)), const !const_1)} given {@ ConstHasType(!const_1 , (rigid (scalar u32)))}, got {}",
69+
},
70+
)
71+
"#]]
72+
.assert_debug_eq(&test_program_ok(
73+
"[
74+
crate Foo {
75+
trait Foo<const C> where [type_of_const C is bool] {}
76+
77+
impl<const C> Foo<const C> for u32 where [type_of_const C is u32] {}
78+
}
79+
]",
80+
));
81+
}

0 commit comments

Comments
 (0)