Skip to content

Commit b5789fe

Browse files
authored
Merge pull request #200 from tiif/refactor_int_is_ty
Refactor `ty_is_int`
2 parents 8b130f7 + 130f628 commit b5789fe

File tree

21 files changed

+344
-253
lines changed

21 files changed

+344
-253
lines changed

crates/formality-check/src/lib.rs

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@
33
use std::{collections::VecDeque, fmt::Debug};
44

55
use anyhow::bail;
6-
use formality_core::Set;
7-
use formality_prove::{is_definitely_not_proveable, Decls, Env};
6+
use formality_core::{ProvenSet, Set};
7+
use formality_prove::{is_definitely_not_proveable, Constraints, Decls, Env};
88
use formality_rust::{
99
grammar::{Crate, CrateItem, Program, Test, TestBoundData},
1010
prove::ToWcs,
1111
};
12-
use formality_types::grammar::{CrateId, Fallible, Wcs};
12+
use formality_types::{
13+
grammar::{CrateId, Fallible, Wcs},
14+
rust::Visit,
15+
};
1316

1417
mod mini_rust_check;
1518

@@ -134,18 +137,36 @@ impl Check<'_> {
134137
goal: impl ToWcs + Debug,
135138
) -> Fallible<()> {
136139
let goal: Wcs = goal.to_wcs();
140+
self.prove_judgment(env, assumptions, goal.to_wcs(), formality_prove::prove)
141+
}
142+
143+
fn prove_judgment<G>(
144+
&self,
145+
env: &Env,
146+
assumptions: impl ToWcs,
147+
goal: G,
148+
judgment_fn: impl FnOnce(Decls, Env, Wcs, G) -> ProvenSet<Constraints>,
149+
) -> Fallible<()>
150+
where
151+
G: Debug + Visit + Clone,
152+
{
137153
let assumptions: Wcs = assumptions.to_wcs();
138154

139155
assert!(env.only_universal_variables());
140156
assert!(env.encloses((&assumptions, &goal)));
141157

142-
let cs = formality_prove::prove(self.decls, env, &assumptions, &goal);
158+
let cs = judgment_fn(
159+
self.decls.clone(),
160+
env.clone(),
161+
assumptions.clone(),
162+
goal.clone(),
163+
);
143164
let cs = cs.into_set()?;
144165
if cs.iter().any(|c| c.unconditionally_true()) {
145166
return Ok(());
146167
}
147168

148-
bail!("failed to prove {goal:?} given {assumptions:?}, got {cs:?}")
169+
bail!("failed to prove `{goal:?}` given `{assumptions:?}`: got {cs:?}")
149170
}
150171

151172
#[tracing::instrument(level = "Debug", skip(self, assumptions, goal))]

crates/formality-check/src/mini_rust_check.rs

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
use std::iter::zip;
22

3-
use formality_core::{Fallible, Map, Upcast};
4-
use formality_prove::Env;
3+
use formality_core::{judgment_fn, Fallible, Map, Upcast};
4+
use formality_prove::{prove_normalize, Constraints, Decls, Env};
55
use formality_rust::grammar::minirust::ArgumentExpression::{ByValue, InPlace};
66
use formality_rust::grammar::minirust::PlaceExpression::Local;
77
use formality_rust::grammar::minirust::ValueExpression::{Constant, Fn, Load};
88
use formality_rust::grammar::minirust::{
9-
self, ty_is_int, ArgumentExpression, BasicBlock, BbId, LocalId, PlaceExpression,
10-
ValueExpression,
9+
self, ArgumentExpression, BasicBlock, BbId, LocalId, PlaceExpression, ValueExpression,
1110
};
1211
use formality_rust::grammar::FnBoundData;
13-
use formality_types::grammar::{CrateId, FnId};
12+
use formality_types::grammar::{CrateId, FnId, Parameter, RigidName, RigidTy};
1413
use formality_types::grammar::{Relation, Ty, Wcs};
1514

1615
use crate::{Check, CrateItem};
@@ -229,9 +228,7 @@ impl Check<'_> {
229228
// Check if the value is well-formed.
230229
let value_ty = self.check_value(typeck_env, switch_value).unwrap();
231230

232-
if !ty_is_int(value_ty) {
233-
bail!("The value used for switch must be an int.");
234-
}
231+
self.prove_judgment(&typeck_env.env, &fn_assumptions, value_ty, ty_is_int)?;
235232

236233
// Ensure all bbid are valid.
237234
for switch_target in switch_targets {
@@ -374,3 +371,34 @@ struct TypeckEnv {
374371
/// declared in the current crate.
375372
crate_id: CrateId,
376373
}
374+
375+
judgment_fn! {
376+
fn ty_is_int(
377+
_decls: Decls,
378+
env: Env,
379+
assumptions: Wcs,
380+
ty: Parameter,
381+
) => Constraints {
382+
debug(assumptions, ty, env)
383+
// If the type that we are currently checking is rigid, check if it is an int.
384+
// If the type can be normalized, normalize until rigid then check if it is an int.
385+
// For the rest of the case, it should fail.
386+
387+
(
388+
(prove_normalize(&decl, &env, &assumptions, ty) => (c1, p))!
389+
(let assumptions = c1.substitution().apply(&assumptions))
390+
(ty_is_int(&decl, &env, assumptions, p) => c2)
391+
----------------------------- ("alias_ty is int")
392+
(ty_is_int(decl, env, assumptions, ty) => c2)
393+
)
394+
395+
(
396+
(if id.is_int())
397+
----------------------------- ("rigid_ty is int")
398+
(ty_is_int(_decls, _env, _assumptions, RigidTy {name: RigidName::ScalarId(id), parameters: _}) => Constraints::none(env))
399+
)
400+
401+
}
402+
}
403+
404+
mod test;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Decide how to do this test -- should it be a unit test?
2+
// Can it be an integration test?
3+
4+
// const TEST_TY_IS_INT: &str = "[
5+
// crate test {
6+
// trait Id {
7+
// type This: [];
8+
// }
9+
10+
// impl<ty T> Id for T {
11+
// type This = T;
12+
// }
13+
// }
14+
// ]";
15+
16+
// #[test]
17+
// fn test_ty_is_int() {
18+
// test_where_clause(
19+
// TEST_TY_IS_INT,
20+
// "{} => { <u16 as Id>::This = u16 }",
21+
// )
22+
// .assert_ok(expect_test::expect!["{Constraints { env: Env { variables: [], bias: Soundness, pending: [] }, known_true: true, substitution: {} }}"]);
23+
24+
// test_where_clause(
25+
// TEST_TY_IS_INT,
26+
// "{} => { @is_int(<u16 as Id>::This) }",
27+
// )
28+
// .assert_ok(expect_test::expect!["{Constraints { env: Env { variables: [], bias: Soundness, pending: [] }, known_true: true, substitution: {} }}"]);
29+
// }

crates/formality-prove/src/lib.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
//! This crate contains the trait proving + type inference logic.
2+
//! It correpsonds loosely to the `InferenceContext` and trait solving (fulfillment context, etc)
3+
//! in the Rust compiler.
4+
//!
5+
//! The base operations we export are:
6+
//!
7+
//! * [`prove`][] -- prove a set of where-clauses to be true
8+
//! * [`prove_normalize`][] -- normalize a type one step (typically used in a recursive setup)
9+
110
// Defines the language used by derive(term) and friends.
211
use formality_types::rust::FormalityLang;
312

@@ -7,6 +16,7 @@ mod prove;
716

817
pub use decls::*;
918
pub use prove::prove;
19+
pub use prove::prove_normalize::prove_normalize;
1020
pub use prove::Constraints;
1121
pub use prove::{is_definitely_not_proveable, may_not_be_provable, negation_via_failure};
1222
pub use prove::{Bias, Env};

crates/formality-prove/src/prove.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ mod minimize;
66
mod negation;
77
mod prove_after;
88
mod prove_eq;
9-
mod prove_normalize;
9+
pub mod prove_normalize;
1010
mod prove_via;
1111
mod prove_wc;
1212
mod prove_wc_list;

crates/formality-prove/src/prove/minimize/test.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@ fn minimize_a() {
1717
let (env, subst) = env.existential_substitution(&term);
1818
let term = term.instantiate_with(&subst).unwrap();
1919

20-
expect!["(Env { variables: [?ty_1, ?ty_2, ?ty_3], bias: Soundness }, [?ty_1, ?ty_3])"]
21-
.assert_eq(&format!("{:?}", (&env, &term)));
20+
expect![
21+
"(Env { variables: [?ty_1, ?ty_2, ?ty_3], bias: Soundness, pending: [] }, [?ty_1, ?ty_3])"
22+
]
23+
.assert_eq(&format!("{:?}", (&env, &term)));
2224

2325
let (mut env_min, term_min, m) = minimize(env, term);
2426

25-
expect!["(Env { variables: [?ty_0, ?ty_1], bias: Soundness }, [?ty_0, ?ty_1])"]
27+
expect!["(Env { variables: [?ty_0, ?ty_1], bias: Soundness, pending: [] }, [?ty_0, ?ty_1])"]
2628
.assert_eq(&format!("{:?}", (&env_min, &term_min)));
2729

2830
let ty0 = term_min[0].as_variable().unwrap();
@@ -51,6 +53,7 @@ fn minimize_a() {
5153
?ty_3,
5254
],
5355
bias: Soundness,
56+
pending: [],
5457
},
5558
known_true: true,
5659
substitution: {

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ use crate::{
1414
use super::constraints::Constraints;
1515

1616
judgment_fn! {
17+
/// Normalize `p` one step, returning a set of constraints and a new parameter `q` that is
18+
/// semantically equivalent to `p`. e.g., if p is `<Vec<T> as IntoIterator>::Item`, this would
19+
/// return `T`.
1720
pub fn prove_normalize(
1821
_decls: Decls,
1922
env: Env,

crates/formality-prove/src/test/adt_wf.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ fn well_formed_adt() {
3232
env: Env {
3333
variables: [],
3434
bias: Soundness,
35+
pending: [],
3536
},
3637
known_true: true,
3738
substitution: {},
@@ -51,21 +52,21 @@ fn not_well_formed_adt() {
5152
assumptions,
5253
Relation::WellFormed(goal),
5354
).assert_err(expect![[r#"
54-
judgment `prove { goal: {@ wf(X<u64>)}, assumptions: {}, env: Env { variables: [], bias: Soundness }, decls: decls(222, [trait Foo <ty> ], [impl Foo(u32)], [], [], [], [adt X <ty> where {Foo(^ty0_0)}], {}, {}) }` failed at the following rule(s):
55+
judgment `prove { goal: {@ wf(X<u64>)}, assumptions: {}, env: Env { variables: [], bias: Soundness, pending: [] }, decls: decls(222, [trait Foo <ty> ], [impl Foo(u32)], [], [], [], [adt X <ty> where {Foo(^ty0_0)}], {}, {}) }` failed at the following rule(s):
5556
failed at (src/file.rs:LL:CC) because
56-
judgment `prove_wc_list { goal: {@ wf(X<u64>)}, assumptions: {}, env: Env { variables: [], bias: Soundness } }` failed at the following rule(s):
57+
judgment `prove_wc_list { goal: {@ wf(X<u64>)}, assumptions: {}, env: Env { variables: [], bias: Soundness, pending: [] } }` failed at the following rule(s):
5758
the rule "some" failed at step #0 (src/file.rs:LL:CC) because
58-
judgment `prove_wc { goal: @ wf(X<u64>), assumptions: {}, env: Env { variables: [], bias: Soundness } }` failed at the following rule(s):
59+
judgment `prove_wc { goal: @ wf(X<u64>), assumptions: {}, env: Env { variables: [], bias: Soundness, pending: [] } }` failed at the following rule(s):
5960
the rule "parameter well formed" failed at step #0 (src/file.rs:LL:CC) because
60-
judgment `prove_wf { goal: X<u64>, assumptions: {}, env: Env { variables: [], bias: Soundness } }` failed at the following rule(s):
61+
judgment `prove_wf { goal: X<u64>, assumptions: {}, env: Env { variables: [], bias: Soundness, pending: [] } }` failed at the following rule(s):
6162
the rule "ADT" failed at step #3 (src/file.rs:LL:CC) because
62-
judgment `prove_after { constraints: Constraints { env: Env { variables: [], bias: Soundness }, known_true: true, substitution: {} }, goal: {Foo(u64)}, assumptions: {} }` failed at the following rule(s):
63+
judgment `prove_after { constraints: Constraints { env: Env { variables: [], bias: Soundness, pending: [] }, known_true: true, substitution: {} }, goal: {Foo(u64)}, assumptions: {} }` failed at the following rule(s):
6364
the rule "prove_after" failed at step #1 (src/file.rs:LL:CC) because
64-
judgment `prove { goal: {Foo(u64)}, assumptions: {}, env: Env { variables: [], bias: Soundness }, decls: decls(222, [trait Foo <ty> ], [impl Foo(u32)], [], [], [], [adt X <ty> where {Foo(^ty0_0)}], {}, {}) }` failed at the following rule(s):
65+
judgment `prove { goal: {Foo(u64)}, assumptions: {}, env: Env { variables: [], bias: Soundness, pending: [] }, decls: decls(222, [trait Foo <ty> ], [impl Foo(u32)], [], [], [], [adt X <ty> where {Foo(^ty0_0)}], {}, {}) }` failed at the following rule(s):
6566
failed at (src/file.rs:LL:CC) because
66-
judgment `prove_wc_list { goal: {Foo(u64)}, assumptions: {}, env: Env { variables: [], bias: Soundness } }` failed at the following rule(s):
67+
judgment `prove_wc_list { goal: {Foo(u64)}, assumptions: {}, env: Env { variables: [], bias: Soundness, pending: [] } }` failed at the following rule(s):
6768
the rule "some" failed at step #0 (src/file.rs:LL:CC) because
68-
judgment `prove_wc { goal: Foo(u64), assumptions: {}, env: Env { variables: [], bias: Soundness } }` failed at the following rule(s):
69+
judgment `prove_wc { goal: Foo(u64), assumptions: {}, env: Env { variables: [], bias: Soundness, pending: [] } }` failed at the following rule(s):
6970
the rule "trait implied bound" failed at step #0 (src/file.rs:LL:CC) because
7071
expression evaluated to an empty collection: `decls.trait_invariants()`"#]]);
7172
}

0 commit comments

Comments
 (0)