Skip to content
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

Add [@@no_inline_let] annotation #3169

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ocaml/fstar-lib/generated/FStar_Parser_Const.ml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions ocaml/fstar-lib/generated/FStar_Syntax_Util.ml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 19 additions & 13 deletions ocaml/fstar-lib/generated/FStar_TypeChecker_Cfg.ml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/parser/FStar.Parser.Const.fst
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ let steps_unmeta = psconst "unmeta"
let deprecated_attr = pconst "deprecated"
let warn_on_use_attr = pconst "warn_on_use"
let inline_let_attr = p2l ["FStar"; "Pervasives"; "inline_let"]
let no_inline_let_attr = p2l ["FStar"; "Pervasives"; "no_inline_let"]
let rename_let_attr = p2l ["FStar"; "Pervasives"; "rename_let"]
let plugin_attr = p2l ["FStar"; "Pervasives"; "plugin"]
let tcnorm_attr = p2l ["FStar"; "Pervasives"; "tcnorm"]
Expand Down
1 change: 1 addition & 0 deletions src/syntax/FStar.Syntax.Util.fst
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,7 @@ let tac_opaque_attr = exp_string "tac_opaque"
let dm4f_bind_range_attr = fvar_const PC.dm4f_bind_range_attr
let tcdecltime_attr = fvar_const PC.tcdecltime_attr
let inline_let_attr = fvar_const PC.inline_let_attr
let no_inline_let_attr = fvar_const PC.no_inline_let_attr
let rename_let_attr = fvar_const PC.rename_let_attr

let t_ctx_uvar_and_sust = fvar_const PC.ctx_uvar_and_subst_lid
Expand Down
6 changes: 4 additions & 2 deletions src/typechecker/FStar.TypeChecker.Cfg.fst
Original file line number Diff line number Diff line change
Expand Up @@ -431,13 +431,15 @@ let should_reduce_local_let cfg lb =
else if cfg.steps.pure_subterms_within_computations &&
U.has_attribute lb.lbattrs PC.inline_let_attr
then true //1. we're extracting, and it's marked @inline_let
else if U.has_attribute lb.lbattrs PC.no_inline_let_attr
then false //Or, 2. do not unfold as it's explicitly marked as @no_inline_let
else
let n = Env.norm_eff_name cfg.tcenv lb.lbeff in
if U.is_pure_effect n &&
(cfg.normalize_pure_lets
|| U.has_attribute lb.lbattrs PC.inline_let_attr)
then true //Or, 2. it's pure and we either not extracting, or it's marked @inline_let
else U.is_ghost_effect n && //Or, 3. it's ghost and we're not extracting
then true //Or, 3. it's pure and we are either not extracting, or it's marked @inline_let
else U.is_ghost_effect n && //Or, 4. it's ghost and we're not extracting
not (cfg.steps.pure_subterms_within_computations)

let translate_norm_step = function
Expand Down
7 changes: 6 additions & 1 deletion tests/extraction/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ FSTAR_EXAMPLES=$(realpath ../../examples)
include $(FSTAR_EXAMPLES)/Makefile.include
include $(FSTAR_ULIB)/ml/Makefile.include

all: inline_let all_cmi Eta_expand.test Div.test
all: inline_let all_cmi Eta_expand.test Div.test no_inline_let

%.exe: %.fst | out
$(FSTAR) $(FSTAR_DEFAULT_ARGS) --odir out --codegen OCaml $<
Expand All @@ -25,6 +25,11 @@ inline_let: InlineLet.fst
egrep -A 10 test InlineLet.ml | grep -qs "17"
@touch $@

no_inline_let: NoInlineLet.fst
$(FSTAR) --codegen OCaml NoInlineLet.fst
diff -u --strip-trailing-cr NoInlineLet.ml.expected NoInlineLet.ml
@touch $@

all_cmi:
+$(MAKE) -C cmi all

Expand Down
15 changes: 15 additions & 0 deletions tests/extraction/NoInlineLet.fst
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module NoInlineLet
open FStar.Tactics

let test_no_inline (f: int): int =
(* this one shouldn't be inlined in tactics or extraction *)
[@@no_inline_let]
let x = f + 1 in
(* this one will be inlined by the norm tactic in the below test *)
let y = x + 2 in
y + y

[@@(postprocess_with (fun _ -> norm [delta_only [`%test_no_inline]]; trefl ()))]
let test_postprocess (f: int): int =
let x = test_no_inline f in
x
8 changes: 8 additions & 0 deletions tests/extraction/NoInlineLet.ml.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
open Prims
let (test_no_inline : Prims.int -> Prims.int) =
fun f ->
let x = f + Prims.int_one in let y = x + (Prims.of_int (2)) in y + y
let (test_postprocess : Prims.int -> Prims.int) =
fun f ->
let x = f + Prims.int_one in
(x + (Prims.of_int (2))) + (x + (Prims.of_int (2)))
2 changes: 2 additions & 0 deletions ulib/FStar.Pervasives.fst
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ let rec false_elim #_ _ = false_elim ()

let inline_let = ()

let no_inline_let = ()

let rename_let _ = ()

let plugin _ = ()
Expand Down
6 changes: 6 additions & 0 deletions ulib/FStar.Pervasives.fsti
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,12 @@ type __internal_ocaml_attributes =
size. *)
val inline_let : unit

(** The [no_inline_let] attribute on a local let-binding prevents the
normalizer from unfolding the definition of a local let-binding. This
attribute can be useful when processing definitions with tactics, as
otherwise the normalizer will eagerly unfold all pure definitions. *)
val no_inline_let : unit

(** The [rename_let] attribute support a form of metaprogramming for
the names of let-bound variables used in extracted code.

Expand Down