anchor.diff:  local_types(Es) ->
       local_defs2(get_elem(localdef, Es)).
   
  +-define(LOCAL_TYPES, edoc_local_defs).
  +
   local_defs2([]) -> [];
   local_defs2(Es) ->
  +    case collect_local_types(Es) of
  +        [] -> local_defs3(Es);
  +        LocalTypes ->
  +            ?LOCAL_TYPES = ets:new(?LOCAL_TYPES, [named_table]),
  +            true = ets:insert(?LOCAL_TYPES, LocalTypes),
  +            try
  +                local_defs3(Es)
  +            after
  +                ets:delete(?LOCAL_TYPES)
  +            end
  +    end.
  +
  +local_defs3(Es) ->
       {type,[?NL | [{v, localdef2(E)} || E <- Es]]}.
  +
  +%% Does not work well for parametrized types.
  +collect_local_types(Es) ->
  +    lists:append([collect_local_type(E) || E <- Es]).
  +
  +collect_local_type(#xmlElement{content = Es}) ->
  +    case get_elem(typevar, Es) of
  +        [] ->
  +            [{t_abstype(get_content(abstype, Es))}];
  +        [_] ->
  +            []
  +    end.
   
   %% Like localdef/1, but does not use label_anchor/2 -- we don't want any
   %% markers or em tags in <v> tag, plain text only!
  +%% When used stand-alone, EDoc generates links to local types. An ETS
  +%% table holds local types, to avoid generating links to them.
   localdef2(#xmlElement{content = Es}) ->
  -    case get_elem(typevar, Es) of
  -	[] -> 
  -	    t_utype(get_elem(type, Es));
  -	[V] ->
  -	    t_var(V) ++ [" = "] ++ t_utype(get_elem(type, Es))
  -    end.
  +    Var = case get_elem(typevar, Es) of
  +              [] ->
  +		  [t_abstype(get_content(abstype, Es))];
  +              [V] ->
  +                  t_var(V)
  +          end,
  +    Var ++ [" = "] ++ t_utype(get_elem(type, Es)).
   
   type_name(#xmlElement{content = Es}) ->
       t_name(get_elem(erlangName, get_content(typedef, Es))).
  
positive.code:     t_tuple(Es);
  t_type([#xmlElement{name = 'fun', content = Es}]) ->
      t_fun(Es);
  t_type([#xmlElement{name = abstype, content = Es}]) ->
      t_abstype(Es);
  t_type([#xmlElement{name = union, content = Es}]) ->
      t_union(Es);
  t_type([#xmlElement{name = record, content = Es}]) ->
  
negative.code:     end.
  
  t_utype([E]) ->
      flatten_type(t_utype_elem(E)).
  
  %% Make sure see also are top elements of lists.
  flatten_type(T) ->
      [case is_integer(E) of
           true -> [E];
           false -> E
       end || E <- lists:flatten(T)].
  
  t_utype_elem(E=#xmlElement{content = Es}) ->
      case get_attrval(name, E) of
  