anchor.diff:      FieldUpdatings = string:join(Overwritings ++ SeqAddings ++ MsgMergings,
                                    UpdateCommaSep),
       FnIndent = flength("~p(", [MergeFn]),
  -    [f("~p(Prev, undefined) -> Prev;~n", [MergeFn]),
  -     f("~p(undefined, New) -> New;~n", [MergeFn]),
  +    [[[f("~p(Prev, undefined) -> Prev;~n", [MergeFn]),
  +       f("~p(undefined, New) -> New;~n", [MergeFn])]
  +      || occurs_as_optional_submsg(MsgName, AnRes)],
        f("~p(#~p{~s},~n", [MergeFn, MsgName, PFieldMatchings]),
        indent(FnIndent, f("#~p{~s}) ->~n", [MsgName, NFieldMatchings])),
        f("    #~p{~s}.~n~n", [MsgName, FieldUpdatings])].
  +
  +occurs_as_optional_submsg(MsgName, #anres{msg_occurrences=Occurrences}=AnRes) ->
  +    %% Note: order of evaluation below is important (the exprs of `andalso'):
  +    %% Messages are present in Occurrences only if they are sub-messages
  +    can_occur_as_sub_msg(MsgName, AnRes) andalso
  +        lists:member(optional, dict:fetch(MsgName, Occurrences)).
   
   format_field_skippers(MsgName) ->
       [format_varint_skipper(MsgName),
  
positive.code: 
  -record(anres, %% result of analysis
          {
            used_types     :: set(),
            known_msg_size :: dict() %% MsgName() --> Size | undefined
          }).
  
  
  
negative.code: 
  analyze_defs(Defs) ->
      #anres{used_types      = find_used_types(Defs),
             known_msg_size  = find_msgsizes_known_at_compile_time(Defs),
             msg_occurrences = find_msg_occurrences(Defs)}.
  
  find_used_types(Defs) ->
      fold_msg_fields(fun(_MsgName, #field{type=Type}, Acc) ->
  