-
Notifications
You must be signed in to change notification settings - Fork 235
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for dependent pattern matching #2256
Conversation
@@ -1004,32 +1004,89 @@ and tc_maybe_toplevel_term env (e:term) : term (* type-checked | |||
check_inner_let_rec env top | |||
|
|||
and tc_match (env : Env.env) (top : term) : term * lcomp * guard_t = | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc @nikswamy , the main change in the PR
@@ -208,7 +208,7 @@ let rec inspect_ln (t:term) : term_view = | |||
| BU.Inl bv -> Tv_Let (true, lb.lbattrs, bv, lb.lbdef, t2) | |||
end | |||
|
|||
| Tm_match (t, brs) -> | |||
| Tm_match (t, _, brs) -> //AR: TODO: expose the annotation in the reflection API |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be great to address this now, otherwise we'll forget and not do it until a user complains about it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
src/syntax/FStar.Syntax.Print.fs
Outdated
(match asc_opt with | ||
| None -> "" | ||
| Some (asc, tacopt) -> | ||
U.format2 "ret %s%s " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
returns
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, thanks for the catch!
Env.set_expected_typ env res_t, res_t, Env.conj_guard g1 g in | ||
| Tm_match(e1, ret_opt, eqns) -> //ret_opt is the return annotation | ||
let e1, c1, g1 = tc_term | ||
({(env |> Env.clear_expected_typ |> fst) with instantiate_imp = true}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May be a bit more abstract to write it as
env |> Env.clear_expected_typ |> fst |> instantiate_both
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, thanks!
| Some (t_or_c, None) -> | ||
//typecheck the return annotation and unset expected type in the env if exists | ||
//the branch typechecking (tc_eqn) will typecheck the branch with an ascription | ||
let env, _ = Env.clear_expected_typ env in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we check that if an expected type is set in the environment, then the type in the returns annotation is compatible with the environment's expected type?
Otherwise, I wonder what would happen if we had something like
(match x returns t with ...) <: t'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do it at the end of tc_match
, I have also added a comment here to that effect.
| Some asc -> | ||
asc | ||
|> SS.subst_ascription [NT (scrutinee, norm_pat_exp)] | ||
|> U.ascribe branch_exp in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than adding an ascription node and then removing it, couldn't we just set the Env.expected_typ?
Some pros/cons:
- That would mean we don't disturb the syntax of the term to typecheck it
- We don't re-typecheck the annotated returns clause
- But, currently, we only support Env.expected_typ rather than Env.expected_effect. Can we add support for Env.expected_comp_type so that we can handle both cases of a returns annotation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, agreed, would be great to have Env.expected_comp
. As we discussed offline, we can take it up separately.
Overview
This PR introduces support for dependent pattern matching in F*. With SMT support available in deciding the relations between types, we haven't felt much need for it. However, in Steel like DSLs where typing relations are mostly handled using unification, we have been working around using handwritten
cond
combinator (that too only for boolean), and using them. For example,Steel.Effect.fsti
defines:which is then used in
Steel.Primitive.ForkJoin
as follows:where
join_case_true
andjoin_case_false
are hoisted to the top-level to get better unification etc.With this PR, we can now annotate
match
andif
with areturning
annotation that supplies a computation type, and get the same effect. So the code inSteel.Primitive.ForkJoin
can now be written as 6b94c39.How does it work
When typechecking
where
C
is a computation type annotation, we typechecke_i
as:I.e. with an expected computation type
C
where the scrutineex
has been substituted by the patternP_i
. After typechecking the branches, the final computation type for thematch
expression isC
.In our small example above, we will typecheck the
then
branch with expected computation type as(St b)[true/b]
i.e.St true
, and similarly for theelse
branch. The computed and expected computation types for the branches are then syntactically same, and hence no smt is required.Syntax etc.
Both
match
andif
can now be optionally annotated withreturns C
orreturns t
:and
Enhancements
While the current PR state is enough for examples such as
Steel.Primitive.ForkJoin
, it can be enhanced on the lines ofas
andin
annotations in Coq.returning
annotation, the scrutinee must be a variable. This restriction can go with anas
annotation.in
annotations.