summaryrefslogtreecommitdiff
path: root/compiler/InterpreterLoops.ml
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/InterpreterLoops.ml')
-rw-r--r--compiler/InterpreterLoops.ml67
1 files changed, 52 insertions, 15 deletions
diff --git a/compiler/InterpreterLoops.ml b/compiler/InterpreterLoops.ml
index 1228ae99..6c574a94 100644
--- a/compiler/InterpreterLoops.ml
+++ b/compiler/InterpreterLoops.ml
@@ -145,8 +145,8 @@ let compute_abs_borrows_loans_maps (no_duplicates : bool)
(* Process those normally *)
super#visit_aborrow_content abs_id bc
| AIgnoredMutBorrow (_, child)
- | AEndedIgnoredMutBorrow
- { child; given_back_loans_proj = _; given_back_meta = _ } ->
+ | AEndedIgnoredMutBorrow { child; given_back = _; given_back_meta = _ }
+ ->
(* Ignore the id of the borrow, if there is *)
self#visit_typed_avalue abs_id child
| AEndedMutBorrow _ | AEndedSharedBorrow ->
@@ -390,7 +390,11 @@ let rec match_types (match_distinct_types : 'r T.ty -> 'r T.ty -> 'r T.ty)
Ref (r, ty, k)
| _ -> match_distinct_types ty0 ty1
-(** See {!Match} *)
+(** See {!Match}.
+
+ This module contains specialized match functions to instantiate the generic
+ {!Match} functor.
+ *)
module type Matcher = sig
val match_etys : T.ety -> T.ety -> T.ety
val match_rtys : T.rty -> T.rty -> T.rty
@@ -553,6 +557,14 @@ end
etc.
We use it for joins, to check if two environments are convertible, etc.
+
+ The functor is parameterized by a {!Matcher}, which implements the
+ non-generic part of the match. More precisely, the role of {!Match} is two
+ provide generic functions which recursively match two values (by recursively
+ matching the fields of ADT values for instance). When it does need to match
+ values in a non-trivial manner (if two ADT values don't have the same
+ variant for instance) it calls the corresponding specialized function from
+ {!Matcher}.
*)
module Match (M : Matcher) = struct
(** Match two values.
@@ -750,6 +762,20 @@ module type MatchJoinState = sig
val nabs : V.abs list ref
end
+(** A matcher for loop joins (we use loop joins to compute fixed points).
+
+ See the explanations for {!Match}.
+
+ In case of loop joins:
+ - we match *concrete* values
+ - we check that the "fixed" abstractions (the abstractions to be framed
+ - i.e., the abstractions which are the same in the two environments to
+ join) are equal
+ - we keep the abstractions which are not in the frame, then merge those
+ together (if they have borrows/loans in common) later
+ The join matcher is used to match the *concrete* values only. For this
+ reason, we fail on the functions which match avalues.
+ *)
module MakeJoinMatcher (S : MatchJoinState) : Matcher = struct
(** Small utility *)
let push_abs (abs : V.abs) : unit = S.nabs := abs :: !S.nabs
@@ -1011,6 +1037,9 @@ module MakeJoinMatcher (S : MatchJoinState) : Matcher = struct
(* Return [Bottom] *)
mk_bottom v.V.ty
+ (* As explained in comments: we don't use the join matcher to join avalues,
+ only concrete values *)
+
let match_distinct_aadts _ _ _ _ _ = raise (Failure "Unreachable")
let match_ashared_borrows _ _ _ _ = raise (Failure "Unreachable")
let match_amut_borrows _ _ _ _ _ _ _ _ = raise (Failure "Unreachable")
@@ -1038,14 +1067,26 @@ let collapse_ctx_with_merge (loop_id : V.LoopId.id) (old_ids : ids_sets)
end in
let module JM = MakeJoinMatcher (S) in
let module M = Match (JM) in
- (* TODO: why not simply call: M.match_type_avalues? (or move this code to
- MakeJoinMatcher?) *)
+ (* Functions to match avalues (see {!merge_duplicates_funcs}).
+
+ Those functions are used to merge borrows/loans with the *same ids*.
+
+ They will always be called on destructured avalues (whose children are
+ [AIgnored] - we enforce that through sanity checks). We rely on the join
+ matcher [JM] to match the concrete values (for shared loans for instance).
+ Note that the join matcher doesn't implement match functions for avalues
+ (see the comments in {!MakeJoinMatcher}.
+ *)
let merge_amut_borrows id ty0 child0 _ty1 child1 =
(* Sanity checks *)
assert (is_aignored child0.V.value);
assert (is_aignored child1.V.value);
- (* Same remarks as for [merge_amut_loans] *)
+ (* We need to pick a type for the avalue. The types on the left and on the
+ right may use different regions: it doesn't really matter (here, we pick
+ the one from the left), because we will merge those regions together
+ anyway (see the comments for {!merge_abstractions}).
+ *)
let ty = ty0 in
let child = child0 in
let value = V.ABorrow (V.AMutBorrow (id, child)) in
@@ -1057,7 +1098,7 @@ let collapse_ctx_with_merge (loop_id : V.LoopId.id) (old_ids : ids_sets)
assert (not (ty_has_borrows ctx.type_context.type_infos ty0));
assert (not (ty_has_borrows ctx.type_context.type_infos ty1));
- (* Same remarks as for [merge_amut_loans] *)
+ (* Same remarks as for [merge_amut_borrows] *)
let ty = ty0 in
let value = V.ABorrow (V.ASharedBorrow id) in
{ V.value; ty }
@@ -1067,12 +1108,7 @@ let collapse_ctx_with_merge (loop_id : V.LoopId.id) (old_ids : ids_sets)
(* Sanity checks *)
assert (is_aignored child0.V.value);
assert (is_aignored child1.V.value);
- (* We simply need to introduce an [AMutLoan]. Some remarks:
- - the child is [AIgnored]
- - we need to pick some types. The types on the left and on the right
- may use different regions: it doesn't really matter (here, we pick
- the ones from the left).
- *)
+ (* Same remarks as for [merge_amut_borrows] *)
let ty = ty0 in
let child = child0 in
let value = V.ALoan (V.AMutLoan (id, child)) in
@@ -1083,9 +1119,10 @@ let collapse_ctx_with_merge (loop_id : V.LoopId.id) (old_ids : ids_sets)
(* Sanity checks *)
assert (is_aignored child0.V.value);
assert (is_aignored child1.V.value);
- (* Same remarks as for [merge_amut_loans].
+ (* Same remarks as for [merge_amut_borrows].
- This time, however, we need to merge the shared values.
+ This time we need to also merge the shared values. We rely on the
+ join matcher [JM] to do so.
*)
assert (not (value_has_loans_or_borrows ctx sv0.V.value));
assert (not (value_has_loans_or_borrows ctx sv1.V.value));