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

Give existing deprecations an expiration date #1044

Merged
merged 6 commits into from
Nov 19, 2021
Merged
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
202 changes: 95 additions & 107 deletions src/frontend/Deprecation_analysis.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,47 @@ open Core_kernel
open Ast
open Middle

type t = Location_span.t * string

let deprecated_functions =
String.Map.of_alist_exn
[ ("multiply_log", "lmultiply"); ("binomial_coefficient_log", "lchoose")
; ("cov_exp_quad", "gp_exp_quad_cov") ]
[ ("multiply_log", ("lmultiply", "2.32.0"))
; ("binomial_coefficient_log", ("lchoose", "2.32.0"))
; ("cov_exp_quad", ("gp_exp_quad_cov", "2.32.0")) ]

let deprecated_odes =
String.Map.of_alist_exn
[ ("integrate_ode", "ode_rk45"); ("integrate_ode_rk45", "ode_rk45")
; ("integrate_ode_bdf", "ode_bdf"); ("integrate_ode_adams", "ode_adams") ]
[ ("integrate_ode", ("ode_rk45", "3.0"))
; ("integrate_ode_rk45", ("ode_rk45", "3.0"))
; ("integrate_ode_bdf", ("ode_bdf", "3.0"))
; ("integrate_ode_adams", ("ode_adams", "3.0")) ]

let deprecated_distributions =
String.Map.of_alist_exn
(List.concat_map Middle.Stan_math_signatures.distributions
~f:(fun (fnkinds, name, _, _) ->
List.filter_map fnkinds ~f:(function
| Lpdf -> Some (name ^ "_log", name ^ "_lpdf")
| Lpmf -> Some (name ^ "_log", name ^ "_lpmf")
| Cdf -> Some (name ^ "_cdf_log", name ^ "_lcdf")
| Ccdf -> Some (name ^ "_ccdf_log", name ^ "_lccdf")
| Rng | UnaryVectorized -> None ) ) )
(List.map
~f:(fun (x, y) -> (x, (y, "2.32.0")))
(List.concat_map Middle.Stan_math_signatures.distributions
~f:(fun (fnkinds, name, _, _) ->
List.filter_map fnkinds ~f:(function
| Lpdf -> Some (name ^ "_log", name ^ "_lpdf")
| Lpmf -> Some (name ^ "_log", name ^ "_lpmf")
| Cdf -> Some (name ^ "_cdf_log", name ^ "_lcdf")
| Ccdf -> Some (name ^ "_ccdf_log", name ^ "_lccdf")
| Rng | UnaryVectorized -> None ) ) ) )

let stan_lib_deprecations =
Map.merge_skewed deprecated_distributions deprecated_functions
~combine:(fun ~key x y ->
Common.FatalError.fatal_error_msg
[%message
"Common key in deprecation map"
(key : string)
(x : string * string)
(y : string * string)] )

let is_deprecated_distribution name =
Option.is_some (String.Map.find deprecated_distributions name)
Option.is_some (Map.find deprecated_distributions name)

let rename_deprecated map name =
Option.value ~default:name (String.Map.find map name)
Map.find map name |> Option.map ~f:fst |> Option.value ~default:name

let distribution_suffix name =
let open String in
Expand Down Expand Up @@ -74,114 +87,91 @@ let update_suffix name type_ =
else drop_suffix name 4 ^ "_lpmf"

let find_udf_log_suffix = function
| { stmt= FunDef {funname= {name; _}; arguments= (_, type_, _) :: _; _}
| { stmt=
FunDef
{ funname= {name; _}
; arguments= (_, ((UReal | UInt) as type_), _) :: _
; _ }
; smeta= _ }
when String.is_suffix ~suffix:"_log" name ->
Some (name, type_)
| _ -> None

let rec collect_deprecated_expr deprecated_userdefined
(acc : (Location_span.t * string) list)
let rec collect_deprecated_expr (acc : (Location_span.t * string) list)
({expr; emeta} : (typed_expr_meta, fun_kind) expr_with) :
(Location_span.t * string) list =
match expr with
| GetLP ->
acc
@ [ ( emeta.loc
, "The no-argument function `get_lp()` is deprecated. Use the \
no-argument function `target()` instead." ) ]
| FunApp (StanLib FnPlain, {name= "abs"; _}, [e])
when Middle.UnsizedType.is_real_type e.emeta.type_ ->
collect_deprecated_expr deprecated_userdefined
collect_deprecated_expr
( acc
@ [ ( emeta.loc
, "Use of the `abs` function with real-valued arguments is \
deprecated; use functions `fabs` instead." ) ] )
deprecated; use function `fabs` instead." ) ] )
e
| FunApp (StanLib FnPlain, {name= "if_else"; _}, l) ->
acc
@ [ ( emeta.loc
, "The function `if_else` is deprecated. Use the conditional \
operator (x ? y : z) instead." ) ]
@ List.concat
(List.map l ~f:(fun e ->
collect_deprecated_expr deprecated_userdefined [] e ) )
| FunApp (StanLib _, {name; _}, l) ->
, "The function `if_else` is deprecated and will be removed in Stan \
2.32.0. Use the conditional operator (x ? y : z) instead; this \
can be automatically changed using stanc --print-canonical" ) ]
@ List.concat_map l ~f:(fun e -> collect_deprecated_expr [] e)
| FunApp ((StanLib _ | UserDefined _), {name; _}, l) ->
let w =
if Option.is_some (String.Map.find deprecated_distributions name) then
[ ( emeta.loc
, name ^ " is deprecated and will be removed in the future. Use "
^ rename_deprecated deprecated_distributions name
^ " instead." ) ]
else if String.is_suffix name ~suffix:"_cdf" then
[ ( emeta.loc
, "Use of " ^ name
^ " without a vertical bar (|) between the first two arguments \
is deprecated." ) ]
else if Option.is_some (String.Map.find deprecated_functions name) then
[ ( emeta.loc
, name ^ " is deprecated and will be removed in the future. Use "
^ rename_deprecated deprecated_functions name
^ " instead." ) ]
else if Option.is_some (String.Map.find deprecated_odes name) then
[ ( emeta.loc
, name ^ " is deprecated and will be removed in the future. Use "
^ rename_deprecated deprecated_odes name
^ " instead. \n\
The new interface is slightly different, see: \n\
https://mc-stan.org/users/documentation/case-studies/convert_odes.html"
) ]
else [] in
acc @ w
@ List.concat
(List.map l ~f:(fun e ->
collect_deprecated_expr deprecated_userdefined [] e ) )
| FunApp (UserDefined _, {name; _}, l) ->
let w =
let type_ = String.Map.find deprecated_userdefined name in
if Option.is_some type_ then
[ ( emeta.loc
, "Use of the _log suffix in user defined function " ^ name
^ " is deprecated, use "
^ update_suffix name (Option.value_exn type_)
^ " instead." ) ]
else if String.is_suffix name ~suffix:"_cdf" then
[ ( emeta.loc
, "Use of " ^ name
^ " without a vertical bar (|) between the first two arguments \
is deprecated." ) ]
else [] in
acc @ w
@ List.concat
(List.map l ~f:(fun e ->
collect_deprecated_expr deprecated_userdefined [] e ) )
| _ ->
fold_expression
(collect_deprecated_expr deprecated_userdefined)
(fun l _ -> l)
acc expr

let collect_deprecated_lval deprecated_userdefined acc l =
fold_lval_with
(collect_deprecated_expr deprecated_userdefined)
(fun x _ -> x)
acc l

let rec collect_deprecated_stmt deprecated_userdefined
(acc : (Location_span.t * string) list) {stmt; _} :
(Location_span.t * string) list =
match Map.find stan_lib_deprecations name with
| Some (rename, version) ->
[ ( emeta.loc
, name ^ " is deprecated and will be removed in Stan " ^ version
^ ". Use " ^ rename
^ " instead. This can be automatically changed using stanc \
--print-canonical" ) ]
| _ when String.is_suffix name ~suffix:"_cdf" ->
[ ( emeta.loc
, "Use of " ^ name
^ " without a vertical bar (|) between the first two arguments \
of a CDF is deprecated and will be removed in Stan 2.32.0. \
This can be automatically changed using stanc \
--print-canonical" ) ]
| _ -> (
match Map.find deprecated_odes name with
| Some (rename, version) ->
[ ( emeta.loc
, name ^ " is deprecated and will be removed in Stan " ^ version
^ ". Use " ^ rename
^ " instead. \n\
The new interface is slightly different, see: \
https://mc-stan.org/users/documentation/case-studies/convert_odes.html"
) ]
| _ -> [] ) in
acc @ w @ List.concat_map l ~f:(fun e -> collect_deprecated_expr [] e)
| _ -> fold_expression collect_deprecated_expr (fun l _ -> l) acc expr

let collect_deprecated_lval acc l =
fold_lval_with collect_deprecated_expr (fun x _ -> x) acc l

let rec collect_deprecated_stmt (acc : (Location_span.t * string) list) {stmt; _}
: (Location_span.t * string) list =
match stmt with
| IncrementLogProb e -> collect_deprecated_expr deprecated_userdefined acc e
| Assignment {assign_lhs= l; assign_op= ArrowAssign; assign_rhs= e} ->
acc
@ collect_deprecated_lval deprecated_userdefined [] l
@ collect_deprecated_expr deprecated_userdefined [] e
| FunDef {body; _} -> collect_deprecated_stmt deprecated_userdefined acc body
| FunDef
{ body
; funname= {name; id_loc}
; arguments= (_, ((UReal | UInt) as type_), _) :: _
; _ }
when String.is_suffix ~suffix:"_log" name ->
let acc =
acc
@ [ ( id_loc
, "Use of the _log suffix in user defined probability functions is \
deprecated and will be removed in Stan 2.32.0, use name '"
^ update_suffix name type_
^ "' instead if you intend on using this function in ~ \
statements or calling unnormalized probability functions \
inside of it." ) ] in
collect_deprecated_stmt acc body
| FunDef {body; _} -> collect_deprecated_stmt acc body
| _ ->
fold_statement
(collect_deprecated_expr deprecated_userdefined)
(collect_deprecated_stmt deprecated_userdefined)
(collect_deprecated_lval deprecated_userdefined)
fold_statement collect_deprecated_expr collect_deprecated_stmt
collect_deprecated_lval
(fun l _ -> l)
acc stmt

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

let collect_warnings (program : typed_program) =
fold_program
(collect_deprecated_stmt (collect_userdef_distributions program))
[] program
fold_program collect_deprecated_stmt [] program
14 changes: 8 additions & 6 deletions src/frontend/Deprecation_analysis.mli
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
(** Utilities for emitting deprecation warnings and
finding proper replacements for deprecated features
*)

open Core_kernel
open Ast

type t = Warnings.t

val find_udf_log_suffix :
typed_statement -> (string * Middle.UnsizedType.t) option

Expand All @@ -14,8 +16,8 @@ val collect_userdef_distributions :
val distribution_suffix : string -> bool
val without_suffix : string list -> string -> string
val is_deprecated_distribution : string -> bool
val deprecated_distributions : string String.Map.t
val deprecated_functions : string String.Map.t
val rename_deprecated : string String.Map.t -> string -> string
val deprecated_distributions : (string * string) String.Map.t
val deprecated_functions : (string * string) String.Map.t
val rename_deprecated : (string * string) String.Map.t -> string -> string
val userdef_distributions : untyped_statement block option -> string list
val collect_warnings : typed_program -> t list
val collect_warnings : typed_program -> Warnings.t list
4 changes: 2 additions & 2 deletions src/frontend/Warnings.ml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ let pp ?printed_filename ppf (span, message) =
let loc_str =
if span = Location_span.empty then ""
else " in " ^ Location.to_string ?printed_filename span.begin_loc in
Fmt.pf ppf "@[<hov>Warning%s: %s@]" loc_str message
Fmt.pf ppf "@[<hov 4>Warning%s: %a@]" loc_str Fmt.text message

let pp_warnings ?printed_filename ppf warnings =
if List.length warnings > 0 then
Fmt.(pf ppf "@[<v>%a@]@." (list ~sep:cut (pp ?printed_filename)) warnings)
Fmt.(pf ppf "@[<v>%a@]@\n" (list ~sep:cut (pp ?printed_filename)) warnings)
32 changes: 20 additions & 12 deletions src/frontend/lexer.mll
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,12 @@ rule token = parse
| "#" { lexer_logger "#comment" ;
Input_warnings.deprecated "#"
(lexbuf.lex_curr_p, "Comments beginning with \
# are deprecated. \
Please use // in place \
of # for line \
comments.") ;
# are deprecated and this \
syntax will be removed in \
Stan 2.32.0. Use // to begin \
line comments; this can be \
done automatically using stanc \
--auto-format") ;
singleline_comment (lexbuf.lex_curr_p, Buffer.create 16) lexbuf;
token lexbuf } (* deprecated *)
(* Program blocks *)
Expand Down Expand Up @@ -177,16 +179,21 @@ rule token = parse
Input_warnings.deprecated "<-"
(lexbuf.lex_curr_p, "assignment operator <- \
is deprecated in the \
Stan language; use = \
instead.") ;
Stan language and will \
be removed in Stan 2.32.0; \
use = instead. This \
can be done automatically \
with stanc --print-canonical") ;
Parser.ARROWASSIGN } (* deprecated *)
| "increment_log_prob" { lexer_logger "increment_log_prob" ;
Input_warnings.deprecated "increment_log_prob"
(lexbuf.lex_curr_p, "increment_log_prob(...)\
; is deprecated and \
will be removed in the \
future. Use target \
+= ...; instead.") ;
will be removed in Stan \
2.32.0. Use target \
+= ...; instead. This \
can be done automatically \
with stanc --print-canonical") ;
Parser.INCREMENTLOGPROB } (* deprecated *)
(* Effects *)
| "print" { lexer_logger "print" ; Parser.PRINT }
Expand All @@ -204,9 +211,10 @@ rule token = parse
Input_warnings.deprecated "get_lp"
(lexbuf.lex_curr_p, "get_lp() function is \
deprecated. It will be \
removed in a future \
release. Use target() \
instead.") ;
removed in Stan 2.32.0. \
Use target() instead. \
This can be done automatically \
with stanc --print-canonical") ;
Parser.GETLP } (* deprecated *)
| string_literal as s { lexer_logger ("string_literal " ^ s) ;
Parser.STRINGLITERAL (lexeme lexbuf) }
Expand Down
14 changes: 10 additions & 4 deletions src/stanc/stanc.ml
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ let options =
, " Do not fail if a function is declared but not defined" )
; ( "--allow_undefined"
, Arg.Clear Typechecker.check_that_all_functions_have_definition
, " Deprecated. Same as --allow-undefined." )
, " Deprecated. Same as --allow-undefined. Will be removed in Stan 2.32.0"
)
; ( "--include-paths"
, Arg.String
(fun str ->
Expand All @@ -134,7 +135,8 @@ let options =
Preprocessor.include_paths :=
!Preprocessor.include_paths @ String.split_on_chars ~on:[','] str
)
, " Deprecated. Same as --include-paths." )
, " Deprecated. Same as --include-paths. Will be removed in Stan 2.32.0"
)
; ( "--use-opencl"
, Arg.Set Transform_Mir.use_opencl
, " If set, try to use matrix_cl signatures." )
Expand All @@ -156,9 +158,13 @@ let print_deprecated_arg_warning =
Array.mem ~equal:(fun x y -> String.is_prefix ~prefix:x y) Sys.argv arg
in
if arg_is_used "--allow_undefined" then
eprintf "--allow_undefined is deprecated. Please use --allow-undefined.\n" ;
eprintf
"--allow_undefined is deprecated and will be removed in Stan 2.32.0. \
Please use --allow-undefined.\n" ;
if arg_is_used "--include_paths" then
eprintf "--include_paths is deprecated. Please use --include-paths.\n"
eprintf
"--include_paths is deprecated and Will be removed in Stan 2.32.0. \
Please use --include-paths.\n"

let model_file_err () =
Arg.usage options ("Please specify one model_file.\n\n" ^ usage) ;
Expand Down
Loading