@@ -273,25 +273,47 @@ module Splits = struct
273273 (* Unlocks better comparisons in many cases *)
274274 let norm e =
275275 let exception NotConstant in
276- let rec norm (e : MiniRust.expr ) =
276+ let rec is_zero e =
277+ try norm e = 0
278+ with NotConstant -> false
279+
280+ and norm (e : MiniRust.expr ) =
277281 (* This function assumes no overflow on index comparisons... FIXME *)
278282 match e with
279283 | As (e , _ ) ->
280284 norm e
285+
286+ | MethodCall (e1, [ " wrapping_add" ], [ e2 ])
287+ | Call (Operator (Add | AddW ), _ , [ e1; e2 ]) when is_zero e1 ->
288+ norm e2
289+
290+ | MethodCall (e1, [ " wrapping_add" ], [ e2 ])
291+ | Call (Operator (Add | AddW ), _ , [ e1; e2 ]) when is_zero e2 ->
292+ norm e1
293+
281294 | MethodCall (e1, [ " wrapping_add" ], [ e2 ])
282295 | Call (Operator (Add | AddW ), _ , [ e1; e2 ]) ->
283296 norm e1 + norm e2
297+
298+ | MethodCall (e1, [ " wrapping_mul" ], [ e2 ])
299+ | Call (Operator (Mult | MultW ), _ , [ e1; e2 ]) when is_zero e1 || is_zero e2 ->
300+ 0
301+
284302 | MethodCall (e1, [ " wrapping_mul" ], [ e2 ])
285303 | Call (Operator (Mult | MultW ), _ , [ e1; e2 ]) ->
286304 norm e1 * norm e2
305+
287306 | MethodCall (e1, [ " wrapping_sub" ], [ e2 ])
288307 | Call (Operator (Sub | SubW ), _ , [ e1; e2 ]) ->
289308 norm e1 - norm e2
309+
290310 | MethodCall (e1, [ " wrapping_div" ], [ e2 ])
291311 | Call (Operator (Div | DivW ), _ , [ e1; e2 ]) ->
292312 norm e1 / norm e2
313+
293314 | Constant (_ , c ) ->
294315 int_of_string c
316+
295317 | _ ->
296318 raise NotConstant
297319 in
@@ -650,9 +672,9 @@ let field_type env (e: Ast.expr) f =
650672 [fn_t_ret] corresponds to the return type of the function we are currently
651673 translating, and is used for EReturn nodes.
652674 *)
653- let rec translate_expr (env : env ) (fn_t_ret : MiniRust.typ ) (e : Ast.expr ) : env * MiniRust.expr =
675+ let rec translate_expr (env : env ) ? context (fn_t_ret : MiniRust.typ ) (e : Ast.expr ) : env * MiniRust.expr =
654676 (* KPrint.bprintf "translate_expr: %a : %a\n" PrintAst.Ops.pexpr e PrintAst.Ops.ptyp e.typ; *)
655- translate_expr_with_type env fn_t_ret e (translate_type env e.typ)
677+ translate_expr_with_type env ?context fn_t_ret e (translate_type env e.typ)
656678
657679and translate_expr_list (env : env ) (fn_t_ret : MiniRust.typ ) (es : Ast.expr list ) : env * MiniRust.expr list =
658680 let env, acc =
@@ -697,7 +719,7 @@ and translate_array (env: env) (fn_t_ret: MiniRust.typ) is_toplevel (init: Ast.e
697719
698720(* However, generally, we will have a type provided by the context that may
699721 necessitate the insertion of conversions *)
700- and translate_expr_with_type (env : env ) (fn_t_ret : MiniRust.typ ) (e : Ast.expr ) (t_ret : MiniRust.typ ): env * MiniRust.expr =
722+ and translate_expr_with_type (env : env ) ?( context = `Other ) (fn_t_ret : MiniRust.typ ) (e : Ast.expr ) (t_ret : MiniRust.typ ): env * MiniRust.expr =
701723 (* KPrint.bprintf "translate_expr_with_type: %a @@ %a\n" PrintMiniRust.ptyp t_ret PrintAst.Ops.pexpr e; *)
702724
703725 let erase_borrow_kind_info = (object (self )
@@ -732,10 +754,16 @@ and translate_expr_with_type (env: env) (fn_t_ret: MiniRust.typ) (e: Ast.expr) (
732754 Constant (SizeT , x)
733755 | _ , Constant UInt32 , Constant SizeT ->
734756 As (x, Constant SizeT )
757+
735758 | _ , Function (_ , _ , ts , t ), Function (_ , _ , ts' , t' ) when ts = ts' && t = t' ->
736759 (* The type annotations coming from Ast do not feature polymorphic binders in types, but we
737760 do retain them in our Function type -- so we need to relax the comparison here *)
738- x
761+ begin match e.node with
762+ | EQualified _ when context <> `CallHead ->
763+ As (x, t_ret)
764+ | _ ->
765+ x
766+ end
739767
740768 (* More conversions due to box-ing types. *)
741769 | _ , Ref (_ , _ , Slice _ ), App (Name (["Box" ], _ ), [Slice _ ]) ->
@@ -850,9 +878,12 @@ and translate_expr_with_type (env: env) (fn_t_ret: MiniRust.typ) (e: Ast.expr) (
850878 | EAny -> failwith " Unexpected EAny"
851879 | EAbort (_ , s ) ->
852880 env, Panic (Stdlib.Option. value ~default: " " s)
853- | EIgnore _ ->
854- failwith " unexpected: EIgnore"
855- | EApp ({ node = EOp (o , _ ); _ } , es ) when H. is_wrapping_operator o ->
881+ | EIgnore e ->
882+ let t = translate_type env e.typ in
883+ let env, e = translate_expr env fn_t_ret e in
884+ let binding: MiniRust. binding = { name = " _" ; typ = t; mut = false ; ref = false } in
885+ env, Let (binding, Some e, Unit )
886+ | EApp ({ node = EOp (o , w ); _ } , es ) when H. is_wrapping_operator o && not (Constant. is_float w) ->
856887 let w = Helpers. assert_tint (List. hd es).typ in
857888 let env, es = translate_expr_list env fn_t_ret es in
858889 env, possibly_convert (MethodCall (List. hd es, [ H. wrapping_operator o ], List. tl es)) (Constant w)
@@ -915,7 +946,7 @@ and translate_expr_with_type (env: env) (fn_t_ret: MiniRust.typ) (e: Ast.expr) (
915946 | [ { typ = TUnit ; node; _ } ] -> assert (node = EUnit ); []
916947 | _ -> es
917948 in
918- let env, e = translate_expr env fn_t_ret e in
949+ let env, e = translate_expr env ~context: `CallHead fn_t_ret e in
919950 let ts = List. map (translate_type env) ts in
920951 let env, es = translate_expr_list env fn_t_ret es in
921952 env, Call (e, ts, es)
@@ -934,7 +965,7 @@ and translate_expr_with_type (env: env) (fn_t_ret: MiniRust.typ) (e: Ast.expr) (
934965 | _ -> es, snd (Helpers. flatten_arrow e0.typ)
935966 in
936967 (* KPrint.bprintf "Translating arguments to call %a\n" PrintAst.Ops.pexpr e0; *)
937- let env, e0 = translate_expr env fn_t_ret e0 in
968+ let env, e0 = translate_expr env ~context: `CallHead fn_t_ret e0 in
938969 let env, es = translate_expr_list_with_types env fn_t_ret es (List. map (translate_type env) ts) in
939970 env, possibly_convert (Call (e0, [] , es)) (translate_type env e.typ)
940971
@@ -1072,6 +1103,7 @@ and translate_expr_with_type (env: env) (fn_t_ret: MiniRust.typ) (e: Ast.expr) (
10721103 sub-environments since their variables go out of scope? *)
10731104 env, IfThenElse (e1, e2, e3)
10741105 | ESequence _ ->
1106+ (* `sequence_to_let` eliminates all sequences *)
10751107 failwith " unexpected: ESequence"
10761108 | EAssign (e1 , e2 ) ->
10771109 let lvalue_type = match e1.node with
@@ -1346,7 +1378,12 @@ and translate_pat env (p: Ast.pattern): MiniRust.pat =
13461378 ) field_names pats)
13471379 | PUnit -> failwith " TODO: PUnit"
13481380 | PBool _ -> failwith " TODO: PBool"
1349- | PEnum _ -> failwith " TODO: PEnum"
1381+ | PEnum cons ->
1382+ (* Same as constructors, above, since enums and variants are the same in Rust (`enum`
1383+ keyword). *)
1384+ let lid = Helpers. assert_tlid p.typ in
1385+ let name = lookup_type env lid in
1386+ StructP (`Variant (name, snd cons), [] )
13501387 | PTuple ps ->
13511388 TupleP (List. map (translate_pat env) ps)
13521389 | PDeref _ -> failwith " TODO: PDeref"
@@ -1370,7 +1407,20 @@ let is_handled_primitively = function
13701407
13711408(* In Rust, like in C, all the declarations from the current module are in
13721409 * scope immediately. This requires us to duplicate a little bit of work. *)
1373- let bind_decl env (d : Ast.decl ): env =
1410+ let bind_type_decl env (d : Ast.decl ): env =
1411+ match d with
1412+ | DType (lid , _flags , _ , _ , _decl ) ->
1413+ if LidMap. mem lid env.types then
1414+ (* Name already assigned thanks to a forward declaration *)
1415+ env
1416+ else
1417+ let env, name = translate_lid env lid in
1418+ let env = push_type env lid name in
1419+ env
1420+ | _ ->
1421+ env
1422+
1423+ let bind_non_type_decl env (d : Ast.decl ): env =
13741424 match d with
13751425 | DFunction (_ , _ , _ , _ , _ , lid , _ , _ ) when is_handled_primitively lid ->
13761426 env
@@ -1429,17 +1479,9 @@ let bind_decl env (d: Ast.decl): env =
14291479 let name = translate_unknown_lid lid in
14301480 push_decl env lid (name, make_poly (translate_type_with_config env {default_config with keep_mut = true } t) type_parameters)
14311481
1432- | DType (lid , _flags , _ , _ , decl ) ->
1433- let env, name =
1434- if LidMap. mem lid env.types then
1435- (* Name already assigned thanks to a forward declaration *)
1436- env, lookup_type env lid
1437- else
1438- let env, name = translate_lid env lid in
1439- let env = push_type env lid name in
1440- env, name
1441- in
1442- match decl with
1482+ | DType (lid , _ , _ , _ , decl ) ->
1483+ let name = lookup_type env lid in
1484+ begin match decl with
14431485 | Flat fields ->
14441486 (* These sets are mutually exclusive, so we don't box *and* introduce a
14451487 lifetime at the same time *)
@@ -1454,6 +1496,8 @@ let bind_decl env (d: Ast.decl): env =
14541496 in
14551497 let fields = List. map (fun (f , (t , _m )) ->
14561498 let f = Option. get f in
1499+ (* let open PrintAst.Ops in *)
1500+ (* KPrint.bprintf "%a: field %s has type %a\n" plid lid f ptyp t; *)
14571501 { MiniRust. name = f; visibility = Some Pub ; typ = translate_type_with_config env { box; lifetime; keep_mut = false } t }
14581502 ) fields in
14591503 { env with
@@ -1479,6 +1523,7 @@ let bind_decl env (d: Ast.decl): env =
14791523 ) env branches
14801524 | _ ->
14811525 env
1526+ end
14821527
14831528let translate_meta attributes flags =
14841529 let comments = List. filter_map (function Common. Comment c -> Some c | _ -> None ) flags in
@@ -1595,7 +1640,11 @@ let translate_decl env { derives; attributes; static; no_mangle; _ } (d: Ast.dec
15951640 | Enum idents ->
15961641 (* TODO: enum cases with set values *)
15971642 (* No need to do name binding here since there are entirely resolved via the type name. *)
1598- let items = List. map (fun (i , v ) -> assert (v = None ); snd i, None ) idents in
1643+ let items = List. map (fun (i , (v : Z.t option )) ->
1644+ snd i, match v with
1645+ | None -> MiniRust. Unit None
1646+ | Some c -> Unit (Some c)
1647+ ) idents in
15991648 Some (Enumeration { name; meta; items; derives; generic_params = [] })
16001649 | Abbrev t ->
16011650 let has_inner_pointer = has_pointer env t in
@@ -1619,7 +1668,7 @@ let translate_decl env { derives; attributes; static; no_mangle; _ } (d: Ast.dec
16191668 let items = List. map (fun (cons , _ ) ->
16201669 let fields = DataTypeMap. find (`Variant (lid, cons)) env.struct_fields in
16211670 let fields = List. map (fun (x : MiniRust.struct_field ) -> { x with visibility = None }) fields in
1622- cons, Some fields
1671+ cons, if fields = [] then MiniRust. Unit None else MiniRust. Struct fields
16231672 ) branches in
16241673 Some (Enumeration { name; meta; items; derives; generic_params })
16251674 | Union _ ->
@@ -1807,10 +1856,24 @@ let translate_files_with_metadata files metadata =
18071856 | _ -> true
18081857 ) decls in
18091858
1859+ (* Step 0.5: bind all *type* declarations so that types are in scope for adding functions in the
1860+ environment (with their types) *)
1861+ let env = List. fold_left (fun env d ->
1862+ try
1863+ bind_type_decl env d
1864+ with e ->
1865+ (* We do not increase failures as this will be counted below. *)
1866+ KPrint. bprintf " %sERROR translating type of %a: %s%s\n %s\n " Ansi. red
1867+ PrintAst.Ops. plid (Ast. lid_of_decl d)
1868+ (Printexc. to_string e) Ansi. reset
1869+ (Printexc. get_backtrace () );
1870+ env
1871+ ) env decls in
1872+
18101873 (* Step 1: bind all declarations and add them to the environment with their types *)
18111874 let env = List. fold_left (fun env d ->
18121875 try
1813- bind_decl env d
1876+ bind_non_type_decl env d
18141877 with e ->
18151878 (* We do not increase failures as this will be counted below. *)
18161879 KPrint. bprintf " %sERROR translating type of %a: %s%s\n %s\n " Ansi. red
0 commit comments