anchor.diff:      in
       norm cfg env (Meta(env,metadata, head.pos)::stack) head
   
  -and do_reify_monadic fallback cfg env stack (head : term) (m : monad_name) (t : typ) : term =
  +and do_reify_monadic fallback cfg env stack (top : term) (m : monad_name) (t : typ) : term =
       (* Precondition: the stack head is an App (reify, ...) *)
       begin match stack with
       | App (_, {n=Tm_constant FC.Const_reify}, _, _) :: _ -> ()
       | _ -> failwith (BU.format1 "INTERNAL ERROR: do_reify_monadic: bad stack: %s" (stack_to_string stack))
       end;
  -    let head0 = head in
  -    let head = U.unascribe head in
  -    log cfg (fun () -> BU.print2 "Reifying: (%s) %s\n" (Print.tag_of_term head) (Print.term_to_string head));
  -    let head = U.unmeta_safe head in
  -    match (SS.compress head).n with
  +    let top0 = top in
  +    let top = U.unascribe top in
  +    log cfg (fun () -> BU.print2 "Reifying: (%s) %s\n" (Print.tag_of_term top) (Print.term_to_string top));
  +    let top = U.unmeta_safe top in
  +    match (SS.compress top).n with
       | Tm_let ((false, [lb]), body) ->
         (* ****************************************************************************)
         (* Monadic binding                                                            *)
  
positive.code:           in
  
            match is_return lb.lbdef with
            (* We are in the case where [head] = [bind (return e) (fun x -> body)] *)
            (* which can be optimised to a non-monadic let-binding [let x = e in body] *)
            | Some e ->
              let lb = {lb with lbeff=PC.effect_PURE_lid; lbdef=e} in
              norm cfg env (List.tl stack) (S.mk (Tm_let((false, [lb]), U.mk_reify body)) None head.pos)
            | None ->
              if (match is_return body with Some ({n=Tm_bvar y}) -> S.bv_eq x y | _ -> false)
              then
                (* We are in the case where [head] = [bind e (fun x -> return x)] *)
                (* which can be optimised to just keeping normalizing [e] with a reify on the stack *)
                norm cfg env stack lb.lbdef
              else (
                (* TODO : optimize [bind (bind e1 e2) e3] into [bind e1 (bind e2 e3)] *)
                (* Rewriting binds in that direction would be better for exception-like monad *)
                (* since we wouldn't rematch on an already raised exception *)
                let rng = head.pos in
  
                let head = U.mk_reify <| lb.lbdef in
                let body = U.mk_reify <| body in
  
negative.code:             | Tm_meta (e0, Meta_monadic_lift(m1, m2, t')) -> not (U.is_pure_effect m1)
              | _ -> false
            in
            if BU.for_some is_arg_impure ((as_arg head)::args) then
              Errors.log_issue top.pos
                               (Errors.Warning_Defensive,
                                BU.format1 "Incompatibility between typechecker and normalizer; \
                                            this monadic application contains impure terms %s\n"
                                            (Print.term_to_string top))
          end;
  
          (* GM: I'm really suspicious of this code, I tried to change it the least
           * when trying to fixing it but these two seem super weird. Why 2 of them?
           * Why is it not calling rebuild? I'm gonna keep it for now. *)
          let fallback1 () =
              log cfg (fun () -> BU.print2 "Reified (2) <%s> to %s\n" (Print.term_to_string top0) "");
              norm cfg env (List.tl stack) (U.mk_reify top)
          in
          let fallback2 () =
              log cfg (fun () -> BU.print2 "Reified (3) <%s> to %s\n" (Print.term_to_string top0) "");
              norm cfg env (List.tl stack) (mk (Tm_meta (top, Meta_monadic(m, t))) top0.pos)
          in
  
          (* This application case is only interesting for fully-applied dm4f actions. Otherwise,
           * we just continue rebuilding. *)
          begin match (U.un_uinst head).n with
          | Tm_fvar fv ->
              let lid = S.lid_of_fv fv in
              let qninfo = Env.lookup_qname cfg.tcenv lid in
  