anchor.diff:          true ->
             List = lists:zip(ArgNames, ArgTypes),
             TmpV = dict:from_list(List),
  -          t_from_form(Type, [TypeName|TypeNames], ET, M, MR, TmpV);
  +          t_from_form(Type, [TypeName|TypeNames], ET, M, MR, TmpV, D, L1);
           false ->
  -          t_any()
  +          {t_any(), L1}
         end;
       {opaque, {Module, Type, ArgNames}} ->
         TypeName = {opaque, Module, Name, ArgsLen}, % 'type' would do...
  -      Rep =
  +      {Rep, L3} =
           case can_unfold_more(TypeName, TypeNames) of
             true ->
               List = lists:zip(ArgNames, ArgTypes),
               TmpV = dict:from_list(List),
  -            t_from_form(Type, [TypeName|TypeNames], ET, M, MR, TmpV);
  -          false -> t_any()
  +            t_from_form(Type, [TypeName|TypeNames], ET, M, MR, TmpV, D, L1);
  +          false -> {t_any(), L1}
           end,
         Args2 = [subst_all_vars_to_any(ArgType) || ArgType <- ArgTypes],
  -      skip_opaque_alias(Rep, Module, Name, Args2);
  +      {skip_opaque_alias(Rep, Module, Name, Args2), L3};
       error ->
         Msg = io_lib:format("Unable to find type ~w/~w\n", [Name, ArgsLen]),
         throw({error, Msg})
     end.
   
  -forms_to_types(Forms, TypeNames, ET, M, MR, V) ->
  -  t_list_from_form(Forms, TypeNames, ET, M, MR, V).
  -
   skip_opaque_alias(?opaque(_) = T, _Mod, _Name, _Args) -> T;
   skip_opaque_alias(T, Module, Name, Args) ->
     t_opaque(Module, Name, Args, T).
   
  -solve_remote_type(RemMod, Name, Args, TypeNames, ET, M, MR, V) ->
  -  ArgTypes = t_list_from_form(Args, TypeNames, ET, M, MR, V),
  -  ArgsLen = length(Args),
  -  RemType = {type, RemMod, Name, ArgsLen},
  -  case dict:find(RemMod, MR) of
  -    error when ET =:= replace_by_none ->
  -      t_none();
  -    error ->
  -      self() ! {self(), ext_types, {RemMod, Name, ArgsLen}},
  -      t_any();
  -    {ok, RemDict} ->
  -      MFA = {RemMod, Name, ArgsLen},
  -      case sets:is_element(MFA, ET) of
  -        true ->
  -          case lookup_type(Name, ArgsLen, RemDict) of
  -            {type, {_Mod, Type, ArgNames}} ->
  -              case can_unfold_more(RemType, TypeNames) of
  -                true ->
  +remote_from_form(RemMod, Name, Args, TypeNames, ET, M, MR, V, D, L) ->
  +  {ArgTypes, L1} = list_from_form(Args, TypeNames, ET, M, MR, V, D, L),
  +  if
  +    ET =:= replace_by_none ->
  +      {t_none(), L1};
  +    true ->
  +      ArgsLen = length(Args),
  +      RemType = {type, RemMod, Name, ArgsLen},
  +      case dict:find(RemMod, MR) of
  +        error ->
  +          self() ! {self(), ext_types, {RemMod, Name, ArgsLen}},
  +          {t_any(), L1};
  +        {ok, RemDict} ->
  +          MFA = {RemMod, Name, ArgsLen},
  +          case sets:is_element(MFA, ET) of
  +            true ->
  +              case lookup_type(Name, ArgsLen, RemDict) of
  +                {type, {_Mod, Type, ArgNames}} ->
  +                  case can_unfold_more(RemType, TypeNames) of
  +                    true ->
  +                      List = lists:zip(ArgNames, ArgTypes),
  +                      TmpVarDict = dict:from_list(List),
  +                      NewTypeNames = [RemType|TypeNames],
  +                      t_from_form(Type, NewTypeNames, ET,
  +                                  RemMod, MR, TmpVarDict, D, L1);
  +                    false ->
  +                      {t_any(), L1}
  +                  end;
  +                {opaque, {Mod, Type, ArgNames}} ->
                     List = lists:zip(ArgNames, ArgTypes),
                     TmpVarDict = dict:from_list(List),
  -                  NewTypeNames = [RemType|TypeNames],
  -                  t_from_form(Type, NewTypeNames, ET,
  -                              RemMod, MR, TmpVarDict);
  -                false ->
  -                  t_any()
  +                  {NewRep, L2} =
  +                    case can_unfold_more(RemType, TypeNames) of
  +                      true ->
  +                        NewTypeNames = [RemType|TypeNames],
  +                        t_from_form(Type, NewTypeNames, ET,
  +                                    RemMod, MR, TmpVarDict, D, L1);
  +                      false ->
  +                        {t_any(), L1}
  +                    end,
  +                  {skip_opaque_alias(NewRep, Mod, Name, ArgTypes), L2};
  +                error ->
  +                  Msg = io_lib:format("Unable to find remote type ~w:~w()\n",
  +                                      [RemMod, Name]),
  +                  throw({error, Msg})
                 end;
  -            {opaque, {Mod, Type, ArgNames}} ->
  -              List = lists:zip(ArgNames, ArgTypes),
  -              TmpVarDict = dict:from_list(List),
  -              NewRep =
  -                case can_unfold_more(RemType, TypeNames) of
  -                  true ->
  -                    NewTypeNames = [RemType|TypeNames],
  -		    t_from_form(Type, NewTypeNames, ET,
  -                                RemMod, MR, TmpVarDict);
  -                  false ->
  -		    t_any()
  -                end,
  -              skip_opaque_alias(NewRep, Mod, Name, ArgTypes);
  -            error ->
  -              Msg = io_lib:format("Unable to find remote type ~w:~w()\n",
  -                                  [RemMod, Name]),
  -              throw({error, Msg})
  -          end;
  -        false when ET =:= replace_by_none ->
  -          t_none();
  -        false ->
  -          self() ! {self(), ext_types, {RemMod, Name, ArgsLen}},
  -          t_any()
  +            false ->
  +              self() ! {self(), ext_types, {RemMod, Name, ArgsLen}},
  +              {t_any(), L1}
  +          end
         end
     end.
   
  -record_from_form({atom, _, Name}, ModFields, TypeNames, ET, M, MR, V) ->
  +record_from_form({atom, _, Name}, ModFields, TypeNames, ET, M, MR, V, D, L) ->
     case can_unfold_more({record, Name}, TypeNames) of
       true ->
         {ok, R} = dict:find(M, MR),
         case lookup_record(Name, R) of
           {ok, DeclFields} ->
             NewTypeNames = [{record, Name}|TypeNames],
  -          GetModRec = get_mod_record(ModFields, DeclFields,
  -                                        NewTypeNames, ET, M, MR, V),
  +          {GetModRec, L1} = get_mod_record(ModFields, DeclFields,
  +                                           NewTypeNames, ET, M, MR, V, D, L),
             case GetModRec of
               {error, FieldName} ->
                 throw({error, io_lib:format("Illegal declaration of #~w{~w}\n",
                                             [Name, FieldName])});
               {ok, NewFields} ->
  -              NewFields1 =
  +              {NewFields1, L2} =
                   fields_from_form(NewFields, NewTypeNames, ET, M, MR,
  -                                 dict:new()),
  -              t_tuple(
  -                 [t_atom(Name)|[Type
  -                                || {_FieldName, Type} <- NewFields1]])
  +                                 dict:new(), D, L1),
  +              Rec = t_tuple(
  +                      [t_atom(Name)|[Type
  +                                     || {_FieldName, Type} <- NewFields1]]),
  +              {Rec, L2}
             end;
           error ->
             throw({error, io_lib:format("Unknown record #~w{}\n", [Name])})
         end;
       false ->
  -       t_any()
  +       {t_any(), L}
     end.
   
  -get_mod_record([], DeclFields, _TypeNames, _ET, _M, _MR, _V) ->
  -  {ok, DeclFields};
  -get_mod_record(ModFields, DeclFields, TypeNames, ET, M, MR, V) ->
  +get_mod_record([], DeclFields, _TypeNames, _ET, _M, _MR, _V, _D, L) ->
  +  {{ok, DeclFields}, L};
  +get_mod_record(ModFields, DeclFields, TypeNames, ET, M, MR, V, D, L) ->
     DeclFieldsDict = lists:keysort(1, DeclFields),
  -  ModFieldsDict = build_field_dict(ModFields, TypeNames, ET, M, MR, V),
  +  {ModFieldsDict, L1} =
  +    build_field_dict(ModFields, TypeNames, ET, M, MR, V, D, L),
     case get_mod_record_types(DeclFieldsDict, ModFieldsDict, []) of
  -    {error, _FieldName} = Error -> Error;
  +    {error, _FieldName} = Error -> {Error, L1};
       {ok, FinalKeyDict} ->
  -      {ok, [lists:keyfind(FieldName, 1, FinalKeyDict)
  -             || {FieldName, _, _} <- DeclFields]}
  +      Fields = [lists:keyfind(FieldName, 1, FinalKeyDict)
  +             || {FieldName, _, _} <- DeclFields],
  +      {{ok, Fields}, L1}
     end.
   
  -build_field_dict(FieldTypes, TypeNames, ET, M, MR, V) ->
  -  L = [{Name, Type, t_from_form(Type, TypeNames, ET, M, MR, V)}
  -         || {type, _, field_type, [{atom, _, Name}, Type]} <- FieldTypes],
  -  lists:keysort(1, L).
  +build_field_dict(FieldTypes, TypeNames, ET, M, MR, V, D, L) ->
  +  build_field_dict(FieldTypes, TypeNames, ET, M, MR, V, D, L, []).
  +
  +build_field_dict([{type, _, field_type, [{atom, _, Name}, Type]}|Left],
  +		 TypeNames, ET, M, MR, V, D, L, Acc) ->
  +  {T, L1} = t_from_form(Type, TypeNames, ET, M, MR, V, D, L - 1),
  +  %% The cached record field type (DeclType) in
  +  %% get_mod_record_types()), was created with a similar call as TT.
  +  %% Using T for the subtype test does not work since any() is not
  +  %% always a subset of the field type.
  +  TT = t_from_form(Type, ET, M, MR, V),
  +  NewAcc = [{Name, Type, T, TT}|Acc],
  +  {Dict, L2} =
  +    build_field_dict(Left, TypeNames, ET, M, MR, V, D, L1, NewAcc),
  +  {Dict, L2};
  +build_field_dict([], _TypeNames, _ET, _M, _MR, _V, _D, L, Acc) ->
  +  {lists:keysort(1, Acc), L}.
   
   get_mod_record_types([{FieldName, _Abstr, DeclType}|Left1],
  -                        [{FieldName, TypeForm, ModType}|Left2], Acc) ->
  -  ModTypeNoVars = subst_all_vars_to_any(ModType),
  +                     [{FieldName, TypeForm, ModType, ModTypeTest}|Left2],
  +                     Acc) ->
  +  ModTypeNoVars = subst_all_vars_to_any(ModTypeTest),
     case t_is_subtype(ModTypeNoVars, DeclType) of
       false -> {error, FieldName};
       true -> get_mod_record_types(Left1, Left2,
  -                              [{FieldName, TypeForm, DeclType}|Acc])
  +                              [{FieldName, TypeForm, ModType}|Acc])
     end;
   get_mod_record_types([{FieldName1, _Abstr, _DeclType} = DT|Left1],
  -                  [{FieldName2, _FormType, _ModType}|_] = List2,
  -                  Acc) when FieldName1 < FieldName2 ->
  +                     [{FieldName2, _FormType, _ModType, _TT}|_] = List2,
  +                     Acc) when FieldName1 < FieldName2 ->
     get_mod_record_types(Left1, List2, [DT|Acc]);
   get_mod_record_types(Left1, [], Acc) ->
     {ok, lists:keysort(1, Left1++Acc)};
  -get_mod_record_types(_, [{FieldName2, _FormType, _ModType}|_], _Acc) ->
  +get_mod_record_types(_, [{FieldName2, _FormType, _ModType, _TT}|_], _Acc) ->
     {error, FieldName2}.
   
  -fields_from_form(Fields, TypeNames, ET, M, MR, V) ->
  -  [{Name, t_from_form(Abstr, TypeNames, ET, M, MR, V)}
  -     || {Name, Abstr, _Type} <- Fields].
  -
  -t_list_from_form(Forms, TypeNames, ET, M, MR, V) ->
  -  [t_from_form(Form, TypeNames, ET, M, MR, V) || Form <- Forms].
  +%% It is important to create a limited version of the record type
  +%% since nested record types can otherwise easily result in huge
  +%% terms.
  +fields_from_form([], _TypeNames, _ET, _M, _MR, _V, _D, L) ->
  +  {[], L};
  +fields_from_form([{Name, Abstr, _Type}|Tail], TypeNames, ET, M, MR,
  +                 V, D, L) ->
  +  {T, L1} = t_from_form(Abstr, TypeNames, ET, M, MR, V, D, L),
  +  {F, L2} = fields_from_form(Tail, TypeNames, ET, M, MR, V, D, L1),
  +  {[{Name, T}|F], L2}.
  +
  +list_from_form([], _TypeNames, _ET, _M, _MR, _V, _D, L) ->
  +  {[], L};
  +list_from_form([H|Tail], TypeNames, ET, M, MR, V, D, L) ->
  +  {H1, L1} = t_from_form(H, TypeNames, ET, M, MR, V, D, L - 1),
  +  {T1, L2} = list_from_form(Tail, TypeNames, ET, M, MR, V, D, L1),
  +  {[H1|T1], L2}.
   
   -spec t_var_names([erl_type()]) -> [atom()].
   
  
positive.code:                   module(), mod_records(), var_table()) -> erl_type().
  
  t_from_form(Form, ExpTypes, Module, RecDict, VarDict) ->
    t_from_form(Form, [], ExpTypes, Module, RecDict, VarDict).
  
  %% All uses of external types are replaced by none().
  -spec t_from_form_without_remote(parse_form(), type_table()) -> erl_type().
  
  t_from_form_without_remote(Form, TypeTable) ->
    Module = mod,
    RecDict = dict:from_list([{Module, TypeTable}]),
    ExpTypes = replace_by_none,
    t_from_form(Form, [], ExpTypes, Module, RecDict, dict:new()).
  
  -spec t_from_form(parse_form(), type_names(),
                    sets:set(mfa()) | 'replace_by_none',
                    module(), mod_records(), var_table()) -> erl_type().
  
  %% If there is something wrong with parse_form()
  %% throw({error, io_lib:chars()} is called;
  
negative.code: %%
  
  -define(REC_TYPE_LIMIT, 2).
  -define(EXPAND_DEPTH, 16).
  -define(EXPAND_LIMIT, 10000).
  
  -define(TUPLE_TAG_LIMIT, 5).
  -define(TUPLE_ARITY_LIMIT, 8).
  