Skip to content

Commit 88d5f33

Browse files
authored
Merge pull request #1044 from stan-dev/deprecation-timelines-existing
Give existing deprecations an expiration date
2 parents 9802b07 + 8fda5b6 commit 88d5f33

29 files changed

Lines changed: 3713 additions & 1564 deletions

src/frontend/Deprecation_analysis.ml

Lines changed: 95 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,47 @@ open Core_kernel
22
open Ast
33
open Middle
44

5-
type t = Location_span.t * string
6-
75
let deprecated_functions =
86
String.Map.of_alist_exn
9-
[ ("multiply_log", "lmultiply"); ("binomial_coefficient_log", "lchoose")
10-
; ("cov_exp_quad", "gp_exp_quad_cov") ]
7+
[ ("multiply_log", ("lmultiply", "2.32.0"))
8+
; ("binomial_coefficient_log", ("lchoose", "2.32.0"))
9+
; ("cov_exp_quad", ("gp_exp_quad_cov", "2.32.0")) ]
1110

1211
let deprecated_odes =
1312
String.Map.of_alist_exn
14-
[ ("integrate_ode", "ode_rk45"); ("integrate_ode_rk45", "ode_rk45")
15-
; ("integrate_ode_bdf", "ode_bdf"); ("integrate_ode_adams", "ode_adams") ]
13+
[ ("integrate_ode", ("ode_rk45", "3.0"))
14+
; ("integrate_ode_rk45", ("ode_rk45", "3.0"))
15+
; ("integrate_ode_bdf", ("ode_bdf", "3.0"))
16+
; ("integrate_ode_adams", ("ode_adams", "3.0")) ]
1617

1718
let deprecated_distributions =
1819
String.Map.of_alist_exn
19-
(List.concat_map Middle.Stan_math_signatures.distributions
20-
~f:(fun (fnkinds, name, _, _) ->
21-
List.filter_map fnkinds ~f:(function
22-
| Lpdf -> Some (name ^ "_log", name ^ "_lpdf")
23-
| Lpmf -> Some (name ^ "_log", name ^ "_lpmf")
24-
| Cdf -> Some (name ^ "_cdf_log", name ^ "_lcdf")
25-
| Ccdf -> Some (name ^ "_ccdf_log", name ^ "_lccdf")
26-
| Rng | UnaryVectorized -> None ) ) )
20+
(List.map
21+
~f:(fun (x, y) -> (x, (y, "2.32.0")))
22+
(List.concat_map Middle.Stan_math_signatures.distributions
23+
~f:(fun (fnkinds, name, _, _) ->
24+
List.filter_map fnkinds ~f:(function
25+
| Lpdf -> Some (name ^ "_log", name ^ "_lpdf")
26+
| Lpmf -> Some (name ^ "_log", name ^ "_lpmf")
27+
| Cdf -> Some (name ^ "_cdf_log", name ^ "_lcdf")
28+
| Ccdf -> Some (name ^ "_ccdf_log", name ^ "_lccdf")
29+
| Rng | UnaryVectorized -> None ) ) ) )
30+
31+
let stan_lib_deprecations =
32+
Map.merge_skewed deprecated_distributions deprecated_functions
33+
~combine:(fun ~key x y ->
34+
Common.FatalError.fatal_error_msg
35+
[%message
36+
"Common key in deprecation map"
37+
(key : string)
38+
(x : string * string)
39+
(y : string * string)] )
2740

2841
let is_deprecated_distribution name =
29-
Option.is_some (String.Map.find deprecated_distributions name)
42+
Option.is_some (Map.find deprecated_distributions name)
3043

3144
let rename_deprecated map name =
32-
Option.value ~default:name (String.Map.find map name)
45+
Map.find map name |> Option.map ~f:fst |> Option.value ~default:name
3346

3447
let distribution_suffix name =
3548
let open String in
@@ -74,114 +87,91 @@ let update_suffix name type_ =
7487
else drop_suffix name 4 ^ "_lpmf"
7588

7689
let find_udf_log_suffix = function
77-
| { stmt= FunDef {funname= {name; _}; arguments= (_, type_, _) :: _; _}
90+
| { stmt=
91+
FunDef
92+
{ funname= {name; _}
93+
; arguments= (_, ((UReal | UInt) as type_), _) :: _
94+
; _ }
7895
; smeta= _ }
7996
when String.is_suffix ~suffix:"_log" name ->
8097
Some (name, type_)
8198
| _ -> None
8299

83-
let rec collect_deprecated_expr deprecated_userdefined
84-
(acc : (Location_span.t * string) list)
100+
let rec collect_deprecated_expr (acc : (Location_span.t * string) list)
85101
({expr; emeta} : (typed_expr_meta, fun_kind) expr_with) :
86102
(Location_span.t * string) list =
87103
match expr with
88-
| GetLP ->
89-
acc
90-
@ [ ( emeta.loc
91-
, "The no-argument function `get_lp()` is deprecated. Use the \
92-
no-argument function `target()` instead." ) ]
93104
| FunApp (StanLib FnPlain, {name= "abs"; _}, [e])
94105
when Middle.UnsizedType.is_real_type e.emeta.type_ ->
95-
collect_deprecated_expr deprecated_userdefined
106+
collect_deprecated_expr
96107
( acc
97108
@ [ ( emeta.loc
98109
, "Use of the `abs` function with real-valued arguments is \
99-
deprecated; use functions `fabs` instead." ) ] )
110+
deprecated; use function `fabs` instead." ) ] )
100111
e
101112
| FunApp (StanLib FnPlain, {name= "if_else"; _}, l) ->
102113
acc
103114
@ [ ( emeta.loc
104-
, "The function `if_else` is deprecated. Use the conditional \
105-
operator (x ? y : z) instead." ) ]
106-
@ List.concat
107-
(List.map l ~f:(fun e ->
108-
collect_deprecated_expr deprecated_userdefined [] e ) )
109-
| FunApp (StanLib _, {name; _}, l) ->
115+
, "The function `if_else` is deprecated and will be removed in Stan \
116+
2.32.0. Use the conditional operator (x ? y : z) instead; this \
117+
can be automatically changed using stanc --print-canonical" ) ]
118+
@ List.concat_map l ~f:(fun e -> collect_deprecated_expr [] e)
119+
| FunApp ((StanLib _ | UserDefined _), {name; _}, l) ->
110120
let w =
111-
if Option.is_some (String.Map.find deprecated_distributions name) then
112-
[ ( emeta.loc
113-
, name ^ " is deprecated and will be removed in the future. Use "
114-
^ rename_deprecated deprecated_distributions name
115-
^ " instead." ) ]
116-
else if String.is_suffix name ~suffix:"_cdf" then
117-
[ ( emeta.loc
118-
, "Use of " ^ name
119-
^ " without a vertical bar (|) between the first two arguments \
120-
is deprecated." ) ]
121-
else if Option.is_some (String.Map.find deprecated_functions name) then
122-
[ ( emeta.loc
123-
, name ^ " is deprecated and will be removed in the future. Use "
124-
^ rename_deprecated deprecated_functions name
125-
^ " instead." ) ]
126-
else if Option.is_some (String.Map.find deprecated_odes name) then
127-
[ ( emeta.loc
128-
, name ^ " is deprecated and will be removed in the future. Use "
129-
^ rename_deprecated deprecated_odes name
130-
^ " instead. \n\
131-
The new interface is slightly different, see: \n\
132-
https://mc-stan.org/users/documentation/case-studies/convert_odes.html"
133-
) ]
134-
else [] in
135-
acc @ w
136-
@ List.concat
137-
(List.map l ~f:(fun e ->
138-
collect_deprecated_expr deprecated_userdefined [] e ) )
139-
| FunApp (UserDefined _, {name; _}, l) ->
140-
let w =
141-
let type_ = String.Map.find deprecated_userdefined name in
142-
if Option.is_some type_ then
143-
[ ( emeta.loc
144-
, "Use of the _log suffix in user defined function " ^ name
145-
^ " is deprecated, use "
146-
^ update_suffix name (Option.value_exn type_)
147-
^ " instead." ) ]
148-
else if String.is_suffix name ~suffix:"_cdf" then
149-
[ ( emeta.loc
150-
, "Use of " ^ name
151-
^ " without a vertical bar (|) between the first two arguments \
152-
is deprecated." ) ]
153-
else [] in
154-
acc @ w
155-
@ List.concat
156-
(List.map l ~f:(fun e ->
157-
collect_deprecated_expr deprecated_userdefined [] e ) )
158-
| _ ->
159-
fold_expression
160-
(collect_deprecated_expr deprecated_userdefined)
161-
(fun l _ -> l)
162-
acc expr
163-
164-
let collect_deprecated_lval deprecated_userdefined acc l =
165-
fold_lval_with
166-
(collect_deprecated_expr deprecated_userdefined)
167-
(fun x _ -> x)
168-
acc l
169-
170-
let rec collect_deprecated_stmt deprecated_userdefined
171-
(acc : (Location_span.t * string) list) {stmt; _} :
172-
(Location_span.t * string) list =
121+
match Map.find stan_lib_deprecations name with
122+
| Some (rename, version) ->
123+
[ ( emeta.loc
124+
, name ^ " is deprecated and will be removed in Stan " ^ version
125+
^ ". Use " ^ rename
126+
^ " instead. This can be automatically changed using stanc \
127+
--print-canonical" ) ]
128+
| _ when String.is_suffix name ~suffix:"_cdf" ->
129+
[ ( emeta.loc
130+
, "Use of " ^ name
131+
^ " without a vertical bar (|) between the first two arguments \
132+
of a CDF is deprecated and will be removed in Stan 2.32.0. \
133+
This can be automatically changed using stanc \
134+
--print-canonical" ) ]
135+
| _ -> (
136+
match Map.find deprecated_odes name with
137+
| Some (rename, version) ->
138+
[ ( emeta.loc
139+
, name ^ " is deprecated and will be removed in Stan " ^ version
140+
^ ". Use " ^ rename
141+
^ " instead. \n\
142+
The new interface is slightly different, see: \
143+
https://mc-stan.org/users/documentation/case-studies/convert_odes.html"
144+
) ]
145+
| _ -> [] ) in
146+
acc @ w @ List.concat_map l ~f:(fun e -> collect_deprecated_expr [] e)
147+
| _ -> fold_expression collect_deprecated_expr (fun l _ -> l) acc expr
148+
149+
let collect_deprecated_lval acc l =
150+
fold_lval_with collect_deprecated_expr (fun x _ -> x) acc l
151+
152+
let rec collect_deprecated_stmt (acc : (Location_span.t * string) list) {stmt; _}
153+
: (Location_span.t * string) list =
173154
match stmt with
174-
| IncrementLogProb e -> collect_deprecated_expr deprecated_userdefined acc e
175-
| Assignment {assign_lhs= l; assign_op= ArrowAssign; assign_rhs= e} ->
176-
acc
177-
@ collect_deprecated_lval deprecated_userdefined [] l
178-
@ collect_deprecated_expr deprecated_userdefined [] e
179-
| FunDef {body; _} -> collect_deprecated_stmt deprecated_userdefined acc body
155+
| FunDef
156+
{ body
157+
; funname= {name; id_loc}
158+
; arguments= (_, ((UReal | UInt) as type_), _) :: _
159+
; _ }
160+
when String.is_suffix ~suffix:"_log" name ->
161+
let acc =
162+
acc
163+
@ [ ( id_loc
164+
, "Use of the _log suffix in user defined probability functions is \
165+
deprecated and will be removed in Stan 2.32.0, use name '"
166+
^ update_suffix name type_
167+
^ "' instead if you intend on using this function in ~ \
168+
statements or calling unnormalized probability functions \
169+
inside of it." ) ] in
170+
collect_deprecated_stmt acc body
171+
| FunDef {body; _} -> collect_deprecated_stmt acc body
180172
| _ ->
181-
fold_statement
182-
(collect_deprecated_expr deprecated_userdefined)
183-
(collect_deprecated_stmt deprecated_userdefined)
184-
(collect_deprecated_lval deprecated_userdefined)
173+
fold_statement collect_deprecated_expr collect_deprecated_stmt
174+
collect_deprecated_lval
185175
(fun l _ -> l)
186176
acc stmt
187177

@@ -192,6 +182,4 @@ let collect_userdef_distributions program =
192182
|> String.Map.of_alist_exn
193183

194184
let collect_warnings (program : typed_program) =
195-
fold_program
196-
(collect_deprecated_stmt (collect_userdef_distributions program))
197-
[] program
185+
fold_program collect_deprecated_stmt [] program
Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
(** Utilities for emitting deprecation warnings and
2+
finding proper replacements for deprecated features
3+
*)
4+
15
open Core_kernel
26
open Ast
37

4-
type t = Warnings.t
5-
68
val find_udf_log_suffix :
79
typed_statement -> (string * Middle.UnsizedType.t) option
810

@@ -14,8 +16,8 @@ val collect_userdef_distributions :
1416
val distribution_suffix : string -> bool
1517
val without_suffix : string list -> string -> string
1618
val is_deprecated_distribution : string -> bool
17-
val deprecated_distributions : string String.Map.t
18-
val deprecated_functions : string String.Map.t
19-
val rename_deprecated : string String.Map.t -> string -> string
19+
val deprecated_distributions : (string * string) String.Map.t
20+
val deprecated_functions : (string * string) String.Map.t
21+
val rename_deprecated : (string * string) String.Map.t -> string -> string
2022
val userdef_distributions : untyped_statement block option -> string list
21-
val collect_warnings : typed_program -> t list
23+
val collect_warnings : typed_program -> Warnings.t list

src/frontend/Warnings.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ let pp ?printed_filename ppf (span, message) =
77
let loc_str =
88
if span = Location_span.empty then ""
99
else " in " ^ Location.to_string ?printed_filename span.begin_loc in
10-
Fmt.pf ppf "@[<hov>Warning%s: %s@]" loc_str message
10+
Fmt.pf ppf "@[<hov 4>Warning%s: %a@]" loc_str Fmt.text message
1111

1212
let pp_warnings ?printed_filename ppf warnings =
1313
if List.length warnings > 0 then
14-
Fmt.(pf ppf "@[<v>%a@]@." (list ~sep:cut (pp ?printed_filename)) warnings)
14+
Fmt.(pf ppf "@[<v>%a@]@\n" (list ~sep:cut (pp ?printed_filename)) warnings)

src/frontend/lexer.mll

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,12 @@ rule token = parse
6666
| "#" { lexer_logger "#comment" ;
6767
Input_warnings.deprecated "#"
6868
(lexbuf.lex_curr_p, "Comments beginning with \
69-
# are deprecated. \
70-
Please use // in place \
71-
of # for line \
72-
comments.") ;
69+
# are deprecated and this \
70+
syntax will be removed in \
71+
Stan 2.32.0. Use // to begin \
72+
line comments; this can be \
73+
done automatically using stanc \
74+
--auto-format") ;
7375
singleline_comment (lexbuf.lex_curr_p, Buffer.create 16) lexbuf;
7476
token lexbuf } (* deprecated *)
7577
(* Program blocks *)
@@ -177,16 +179,21 @@ rule token = parse
177179
Input_warnings.deprecated "<-"
178180
(lexbuf.lex_curr_p, "assignment operator <- \
179181
is deprecated in the \
180-
Stan language; use = \
181-
instead.") ;
182+
Stan language and will \
183+
be removed in Stan 2.32.0; \
184+
use = instead. This \
185+
can be done automatically \
186+
with stanc --print-canonical") ;
182187
Parser.ARROWASSIGN } (* deprecated *)
183188
| "increment_log_prob" { lexer_logger "increment_log_prob" ;
184189
Input_warnings.deprecated "increment_log_prob"
185190
(lexbuf.lex_curr_p, "increment_log_prob(...)\
186191
; is deprecated and \
187-
will be removed in the \
188-
future. Use target \
189-
+= ...; instead.") ;
192+
will be removed in Stan \
193+
2.32.0. Use target \
194+
+= ...; instead. This \
195+
can be done automatically \
196+
with stanc --print-canonical") ;
190197
Parser.INCREMENTLOGPROB } (* deprecated *)
191198
(* Effects *)
192199
| "print" { lexer_logger "print" ; Parser.PRINT }
@@ -204,9 +211,10 @@ rule token = parse
204211
Input_warnings.deprecated "get_lp"
205212
(lexbuf.lex_curr_p, "get_lp() function is \
206213
deprecated. It will be \
207-
removed in a future \
208-
release. Use target() \
209-
instead.") ;
214+
removed in Stan 2.32.0. \
215+
Use target() instead. \
216+
This can be done automatically \
217+
with stanc --print-canonical") ;
210218
Parser.GETLP } (* deprecated *)
211219
| string_literal as s { lexer_logger ("string_literal " ^ s) ;
212220
Parser.STRINGLITERAL (lexeme lexbuf) }

src/stanc/stanc.ml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ let options =
121121
, " Do not fail if a function is declared but not defined" )
122122
; ( "--allow_undefined"
123123
, Arg.Clear Typechecker.check_that_all_functions_have_definition
124-
, " Deprecated. Same as --allow-undefined." )
124+
, " Deprecated. Same as --allow-undefined. Will be removed in Stan 2.32.0"
125+
)
125126
; ( "--include-paths"
126127
, Arg.String
127128
(fun str ->
@@ -134,7 +135,8 @@ let options =
134135
Preprocessor.include_paths :=
135136
!Preprocessor.include_paths @ String.split_on_chars ~on:[','] str
136137
)
137-
, " Deprecated. Same as --include-paths." )
138+
, " Deprecated. Same as --include-paths. Will be removed in Stan 2.32.0"
139+
)
138140
; ( "--use-opencl"
139141
, Arg.Set Transform_Mir.use_opencl
140142
, " If set, try to use matrix_cl signatures." )
@@ -156,9 +158,13 @@ let print_deprecated_arg_warning =
156158
Array.mem ~equal:(fun x y -> String.is_prefix ~prefix:x y) Sys.argv arg
157159
in
158160
if arg_is_used "--allow_undefined" then
159-
eprintf "--allow_undefined is deprecated. Please use --allow-undefined.\n" ;
161+
eprintf
162+
"--allow_undefined is deprecated and will be removed in Stan 2.32.0. \
163+
Please use --allow-undefined.\n" ;
160164
if arg_is_used "--include_paths" then
161-
eprintf "--include_paths is deprecated. Please use --include-paths.\n"
165+
eprintf
166+
"--include_paths is deprecated and Will be removed in Stan 2.32.0. \
167+
Please use --include-paths.\n"
162168

163169
let model_file_err () =
164170
Arg.usage options ("Please specify one model_file.\n\n" ^ usage) ;

0 commit comments

Comments
 (0)