Skip to content

Commit 770580a

Browse files
committed
First attempt at moving from shared_ptr to unique_ptr
1 parent 549e9bb commit 770580a

934 files changed

Lines changed: 126502 additions & 45512 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/cpp_ind.ml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,7 @@ let pp_hdecl d =
583583
| Dtype (r, l, t) ->
584584
let name = pp_global Type r in
585585
let l = rename_tvars keywords l in
586+
let saved_method_ns = set_method_ns_for_locals () in
586587
let ids, def =
587588
match find_type_custom_opt r with
588589
| Some (ids, s) -> (pp_string_parameters ids, str " =" ++ spc () ++ str s)
@@ -594,6 +595,7 @@ let pp_hdecl d =
594595
else
595596
str " =" ++ spc () ++ pp_type false l t )
596597
in
598+
restore_method_self_ns saved_method_ns;
597599
pp_tydef l name def
598600
| Dterm (r, a, Tglob (ty, args, e)) when is_monad ty ->
599601
let defs =
@@ -719,6 +721,7 @@ let pp_hdecl_spec_only = function
719721
| Dtype (r, l, t) ->
720722
let name = pp_global Type r in
721723
let l = rename_tvars keywords l in
724+
let saved_method_ns = set_method_ns_for_locals () in
722725
let ids, def =
723726
match find_type_custom_opt r with
724727
| Some (ids, s) -> (pp_string_parameters ids, str " =" ++ spc () ++ str s)
@@ -730,6 +733,7 @@ let pp_hdecl_spec_only = function
730733
else
731734
str " =" ++ spc () ++ pp_type false l t )
732735
in
736+
restore_method_self_ns saved_method_ns;
733737
pp_tydef l name def
734738
| Dterm (r, _, _)
735739
when List.exists
@@ -778,6 +782,7 @@ let pp_spec = function
778782
| Stype (r, vl, ot) ->
779783
let name = pp_global_name Type r in
780784
let l = rename_tvars keywords vl in
785+
let saved_method_ns = set_method_ns_for_locals () in
781786
let ids, def =
782787
match find_type_custom_opt r with
783788
| Some (ids, s) -> (pp_string_parameters ids, str " =" ++ spc () ++ str s)
@@ -790,4 +795,5 @@ let pp_spec = function
790795
(ids, str " = std::any /* AXIOM TO BE REALIZED */")
791796
| Some t -> (ids, str " =" ++ spc () ++ pp_type false l t) )
792797
in
798+
restore_method_self_ns saved_method_ns;
793799
pp_tydef l name def

src/cpp_names.ml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,18 @@ let lookup_method_this_pos n =
513513
| Some (_, pos) -> Some pos
514514
| None -> None
515515

516+
(** Check if a method's receiver is a pointer type (coinductive/shared_ptr)
517+
rather than a value type. Returns true if the method's eponymous
518+
inductive is coinductive. For non-method refs, returns false. *)
519+
let method_receiver_is_ptr n =
520+
match is_registered_method n with
521+
| Some (epon_ref, _) -> Table.is_coinductive epon_ref
522+
| None ->
523+
(* Check local method_candidates: they include a GlobRef at element 2
524+
which is the eponymous type. For local candidates without eponymous info,
525+
default to false (value type). *)
526+
false
527+
516528
(** Helper module for tracking variable names *)
517529
(** Set of [Id.t] names for tracking variable identifiers. *)
518530
module IdSet = Set.Make (Names.Id)

src/cpp_print.ml

Lines changed: 153 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,13 @@ let lambda_needs_capture
107107
let rec collect_from_expr (refs, decls) e =
108108
match e with
109109
| CPPvar id -> (IdSet.add id refs, decls)
110+
| CPPderef e -> collect_from_expr (refs, decls) e
111+
| CPPraw s
112+
when String.length s > 3
113+
&& String.sub s 0 2 = "(*"
114+
&& s.[String.length s - 1] = ')' ->
115+
let name = String.sub s 2 (String.length s - 3) in
116+
(try (IdSet.add (Id.of_string name) refs, decls) with _ -> (refs, decls))
110117
| CPPthis | CPPshared_from_this _ ->
111118
uses_this := true;
112119
(refs, decls)
@@ -802,7 +809,9 @@ and pp_cpp_expr env args t =
802809
| None -> false )
803810
| None -> false ->
804811
let method_name = Id.of_string (Common.pp_global_name Term x) in
805-
str "[](const auto &_x) { return _x->"
812+
let accessor = if method_receiver_is_ptr x then "->" else "." in
813+
str "[](const auto &_x) { return _x"
814+
++ str accessor
806815
++ Id.print method_name
807816
++ str "(); }"
808817
| CPPglob (x, tys, _) ->
@@ -979,8 +988,22 @@ and pp_cpp_expr env args t =
979988
( str "template ",
980989
str "<" ++ pp_list (pp_cpp_type false []) filtered_tys ++ str ">" )
981990
in
982-
obj_s
983-
++ str "->"
991+
(* Coinductive types are shared_ptr → use arrow.
992+
Value types → use dot. unique_ptr pattern match fields
993+
are auto-dereferenced at binding time, so variables holding
994+
inductives are always value types (T or const T&). *)
995+
let use_arrow = method_receiver_is_ptr n in
996+
let accessor = if use_arrow then "->" else "." in
997+
(* Parenthesize deref expressions for correct precedence. *)
998+
let obj_pp =
999+
if not use_arrow then
1000+
match this_arg with
1001+
| CPPderef _ -> str "(" ++ obj_s ++ str ")"
1002+
| _ -> obj_s
1003+
else obj_s
1004+
in
1005+
obj_pp
1006+
++ str accessor
9841007
++ template_kw
9851008
++ Id.print method_name
9861009
++ ty_args_s
@@ -997,7 +1020,7 @@ and pp_cpp_expr env args t =
9971020
| CPPfun_call (f, ts) ->
9981021
let args_s = pp_list (pp_cpp_expr env args) (List.rev ts) in
9991022
pp_cpp_expr env args f ++ str "(" ++ args_s ++ str ")"
1000-
| CPPderef e -> str "*" ++ pp_cpp_expr env args e
1023+
| CPPderef e -> str "*(" ++ pp_cpp_expr env args e ++ str ")"
10011024
| CPPmove e ->
10021025
require_header "utility";
10031026
str (sn ()).move ++ str "(" ++ pp_cpp_expr env args e ++ str ")"
@@ -1010,6 +1033,49 @@ and pp_cpp_expr env args t =
10101033
++ str ")"
10111034
| CPPlambda (params, ret_ty, body, capture_by_value) ->
10121035
let needs_capture, uses_this = lambda_needs_capture params body in
1036+
let body_derefs_var =
1037+
let found = ref false in
1038+
let rec scan_expr = function
1039+
| CPPderef (CPPvar id) when String.equal (Id.to_string id) "_self" ->
1040+
()
1041+
| CPPderef _ -> found := true
1042+
| e ->
1043+
iter_expr_children
1044+
~on_expr:scan_expr
1045+
~on_stmts:(List.iter scan_stmt)
1046+
e
1047+
and scan_stmt s =
1048+
iter_stmt_children
1049+
~on_expr:scan_expr
1050+
~on_stmts:(List.iter scan_stmt)
1051+
s
1052+
in
1053+
List.iter scan_stmt body;
1054+
!found
1055+
in
1056+
let rec type_contains_unique_ptr = function
1057+
| Tunique_ptr _ -> true
1058+
| Tshared_ptr t | Tref t | Tptr t | Tmod (_, t) -> type_contains_unique_ptr t
1059+
| Tglob (_, ts, _) | Tid (_, ts) | Tid_external (_, ts)
1060+
|Tvariant ts | Tnamespace (_, Tglob (_, ts, _)) ->
1061+
List.exists type_contains_unique_ptr ts
1062+
| Tfun (dom, cod) ->
1063+
List.exists type_contains_unique_ptr dom || type_contains_unique_ptr cod
1064+
| Tnamespace (_, t) | Tqualified (t, _) -> type_contains_unique_ptr t
1065+
| _ -> false
1066+
in
1067+
let capture_by_value =
1068+
capture_by_value
1069+
&& not body_derefs_var
1070+
&& not
1071+
( List.exists
1072+
(fun (ty, _) -> type_contains_unique_ptr ty)
1073+
params
1074+
||
1075+
match ret_ty with
1076+
| Some ty -> type_contains_unique_ptr ty
1077+
| None -> false )
1078+
in
10131079
let capture_str =
10141080
if not needs_capture then
10151081
str "[]("
@@ -1114,8 +1180,17 @@ and pp_cpp_expr env args t =
11141180
| _ -> str "<" ++ pp_list (pp_cpp_type false []) tys ++ str ">"
11151181
in
11161182
Id.print id ++ templates ++ str "{" ++ es_s ++ str "}"
1117-
| CPPget (e, id) -> pp_cpp_expr env args e ++ str "." ++ Id.print id
1118-
| CPPget' (e, id) -> pp_cpp_expr env args e ++ str "->" ++ pp_global Type id
1183+
| CPPget (e, id) ->
1184+
( match e with
1185+
| CPPderef _ | CPPraw _ ->
1186+
str "(" ++ pp_cpp_expr env args e ++ str ")." ++ Id.print id
1187+
| _ -> pp_cpp_expr env args e ++ str "." ++ Id.print id )
1188+
| CPPget' (e, id) ->
1189+
(* Record field access: use "." since records are value types. *)
1190+
( match e with
1191+
| CPPderef _ | CPPraw _ ->
1192+
str "(" ++ pp_cpp_expr env args e ++ str ")." ++ pp_global Type id
1193+
| _ -> pp_cpp_expr env args e ++ str "." ++ pp_global Type id )
11191194
| CPPstring s -> str ("\"" ^ Pstring.to_string s ^ "\"")
11201195
| CPPparray (elems, _) ->
11211196
str "{" ++ pp_list (pp_cpp_expr env args) (Array.to_list elems) ++ str "}"
@@ -1205,6 +1280,10 @@ and pp_cpp_expr env args t =
12051280
( match e with
12061281
| CPPmove inner ->
12071282
str (sn ()).move ++ str "(" ++ pp_cpp_expr env args inner ++ str "." ++ Id.print id ++ str ")"
1283+
| CPPderef _ ->
1284+
str "(" ++ pp_cpp_expr env args e ++ str ")." ++ Id.print id
1285+
| CPPraw s when String.length s > 0 && s.[0] = '*' ->
1286+
str "(" ++ pp_cpp_expr env args e ++ str ")." ++ Id.print id
12081287
| _ ->
12091288
pp_cpp_expr env args e ++ str "." ++ Id.print id )
12101289
| CPParrow (e, id) ->
@@ -1240,7 +1319,12 @@ and pp_cpp_expr env args t =
12401319
let full_name = capitalize_enum_qualified (str_global Type ind) ind in
12411320
str full_name ++ str "::" ++ Id.print ctor
12421321
(* Low-level constructs for reuse optimization *)
1243-
| CPPraw code -> str code
1322+
| CPPraw code ->
1323+
str
1324+
(Str.global_replace
1325+
(Str.regexp_string "*(this).")
1326+
"(*(this))."
1327+
code)
12441328
| CPPbinop (op, lhs, rhs) ->
12451329
(* Parenthesize && subexpressions inside || to avoid
12461330
-Wlogical-op-parentheses warnings. *)
@@ -1281,11 +1365,18 @@ and pp_cpp_stmt env args = function
12811365
++ str msg
12821366
++ str "\");"
12831367
| Sreturn (Some e) ->
1284-
(* Strip std::move from return statements — C++ applies implicit move
1285-
on local variables in return statements. Explicit std::move prevents
1286-
NRVO (Named Return Value Optimization) and triggers
1287-
-Wpessimizing-move / -Wredundant-move warnings. *)
1288-
let e = match e with CPPmove inner -> inner | _ -> e in
1368+
(* Strip std::move from return statements when the inner expression is a
1369+
plain variable — C++ applies implicit move on local variables in return
1370+
statements. Explicit std::move prevents NRVO and triggers
1371+
-Wpessimizing-move / -Wredundant-move.
1372+
Keep std::move for non-variable expressions like *_head (dereference of
1373+
shared_ptr) where explicit move is required. *)
1374+
let e = match e with
1375+
| CPPmove (CPPvar _ as inner) -> inner
1376+
| CPPmove ((CPPfun_call _ | CPPmethod_call _ | CPPstruct _ | CPPstructmk _
1377+
| CPPstruct_id _) as inner) -> inner
1378+
| _ -> e
1379+
in
12891380
str "return " ++ pp_cpp_expr env args e ++ str ";"
12901381
| Sdecl (id, ty) ->
12911382
pp_cpp_type false [] ty ++ str " " ++ Id.print id ++ str ";"
@@ -1546,38 +1637,52 @@ and pp_cpp_stmt env args = function
15461637
| [] ->
15471638
( match br.smb_var with
15481639
| Some var_id ->
1549-
str "const auto& " ++ Id.print var_id
1550-
++ str " = " ++ str (sn ()).get ++ str "<"
1551-
++ pp_cpp_type false [] br.smb_ctor_type ++ str ">("
1552-
++ scrut_var_pp ++ str ");"
1640+
if br.smb_is_owned then
1641+
str "auto " ++ Id.print var_id
1642+
++ str " = std::move(" ++ str (sn ()).get ++ str "<"
1643+
++ pp_cpp_type false [] br.smb_ctor_type ++ str ">("
1644+
++ scrut_var_pp ++ str "));"
1645+
else
1646+
str "const auto& " ++ Id.print var_id
1647+
++ str " = " ++ str (sn ()).get ++ str "<"
1648+
++ pp_cpp_type false [] br.smb_ctor_type ++ str ">("
1649+
++ scrut_var_pp ++ str ");"
15531650
| None -> mt () )
15541651
in
1555-
(* Extract the scrutinee object expression from [CPPmethod_call(obj, "v", [])].
1556-
Bind it with [auto&&] to extend any temporary's lifetime, then
1557-
reconstruct the variant accessor as [_svN->v()].
1558-
Falls back to the raw scrutinee expression when the pattern doesn't match. *)
1559-
let first_scrut =
1652+
(* Extract the scrutinee object expression from the variant accessor.
1653+
Handles both [CPPmethod_call(obj, "v", [])] (pointer: [obj->v()])
1654+
and [CPPfun_call(CPPmember(obj, "v"), [])] (value: [obj.v()]).
1655+
Bind temporaries with [auto&&] to extend lifetime, then reconstruct
1656+
the accessor. *)
1657+
let first_br =
15601658
match branches with
1561-
| br :: _ -> br.smb_scrutinee
1659+
| br :: _ -> br
15621660
| [] -> CErrors.anomaly (Pp.str "Smatch with empty branch list")
15631661
in
1662+
let first_scrut = first_br.smb_scrutinee in
1663+
let is_value_type = first_br.smb_is_value_type in
15641664
let scrut_obj_opt =
15651665
match first_scrut with
15661666
| CPPmethod_call (obj, v_id, []) when Id.to_string v_id = "v" ->
15671667
Some obj
1668+
| CPPfun_call (CPPmember (obj, v_id), []) when Id.to_string v_id = "v" ->
1669+
Some obj
15681670
| _ -> None
15691671
in
1672+
let v_access name =
1673+
if is_value_type then name ^ ".v()" else name ^ "->v()"
1674+
in
15701675
let scrut_binding_pp, scrut_var_pp, scrut_obj_pp =
15711676
match scrut_obj_opt with
15721677
| Some (CPPvar id) ->
15731678
let name = Id.to_string id in
1574-
(mt (), str (name ^ "->v()"), str name)
1679+
(mt (), str (v_access name), str name)
15751680
| Some CPPthis ->
15761681
(mt (), str "this->v()", str "(*this)")
15771682
| Some obj_expr ->
15781683
let obj_pp = pp_scrut obj_expr in
15791684
( str ("auto&& " ^ sv_name ^ " = ") ++ obj_pp ++ str ";" ++ fnl (),
1580-
str (sv_name ^ "->v()"), str sv_name )
1685+
str (v_access sv_name), str sv_name )
15811686
| None ->
15821687
( match first_scrut with
15831688
| CPPvar id ->
@@ -1699,6 +1804,26 @@ and is_constexpr_type = function
16991804
| Tfun _ -> false (* std::function uses type erasure *)
17001805
| Tdecltype _ -> false
17011806
| Tglob (r, _, _) when is_axiom_type_ref r -> false
1807+
| Tglob (GlobRef.IndRef (kn, i), _, _) ->
1808+
(* Value-type inductives with recursive fields contain shared_ptr
1809+
internally, making them non-literal. Check ip_types of each
1810+
constructor for self-references (same MutInd). *)
1811+
let has_recursive_field =
1812+
let rec check_ctor j =
1813+
let cref = GlobRef.ConstructRef ((kn, i), j) in
1814+
match Table.get_ctor_ip_types_opt cref with
1815+
| None -> false
1816+
| Some tys ->
1817+
List.exists (fun ty ->
1818+
match ty with
1819+
| Miniml.Tglob (GlobRef.IndRef (kn2, _), _, _) ->
1820+
MutInd.CanOrd.equal kn kn2
1821+
| _ -> false) tys
1822+
|| check_ctor (j + 1)
1823+
in
1824+
(try check_ctor 1 with Not_found -> false)
1825+
in
1826+
not has_recursive_field
17021827
| Tmod (_, t) | Tref t | Tptr t -> is_constexpr_type t
17031828
| Tvariant tys -> List.for_all is_constexpr_type tys
17041829
| Tglob (_, tys, _) -> List.for_all is_constexpr_type tys
@@ -2020,7 +2145,10 @@ let rec pp_cpp_field ?(struct_name : Pp.t option) env = function
20202145
let params_s =
20212146
pp_list
20222147
(fun (id, ty) ->
2023-
if not (Id.Set.mem id used_ids) then pp_cpp_type false [] ty
2148+
if
2149+
(not (Id.Set.mem id used_ids))
2150+
&& not (String.equal (Id.to_string mf_name) "operator=")
2151+
then pp_cpp_type false [] ty
20242152
else pp_cpp_type false [] ty ++ str " " ++ Id.print id)
20252153
mf_params
20262154
in

0 commit comments

Comments
 (0)