https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109531
--- Comment #11 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Better don't reuse U for two different parameters: template <class> using A = int *; template <class T, template <class> class U> struct B { typedef U <typename T::type> type; }; struct C { typedef int *type; }; template <class T> struct D { D <C> foo () { return D <C> (); } template <template <class> class V> V <typename T::type> bar (); }; struct E { typedef int type; }; D <B <E, A>> d; The ICE is on (gdb) p debug_tree (*entry) <bound_template_template_parm 0x7fffea2f01f8 V type_0 type_6 VOID align:8 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7fffea2f01f8 args <tree_vec 0x7fffea2f10c0 length:1 elt:0 <pointer_type 0x7fffea2ed1f8 type type <integer_type 0x7fffea14f5e8 int> unsigned DI size <integer_cst 0x7fffea12cfc0 constant 64> unit-size <integer_cst 0x7fffea12cfd8 constant 8> align:64 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7fffea157b28>> index 0 level 1 orig_level 2 chain <type_decl 0x7fffea2ebed8 V>> $14 = void (gdb) p debug_tree (comparable) <bound_template_template_parm 0x7fffea2f8540 V type_0 type_6 VOID align:8 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7fffea2eda80 args <tree_vec 0x7fffea2f16a0 length:1 elt:0 <pointer_type 0x7fffea2f87e0 type type <integer_type 0x7fffea14f5e8 int> unsigned DI size <integer_cst 0x7fffea12cfc0 constant 64> unit-size <integer_cst 0x7fffea12cfd8 constant 8> align:64 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7fffea157b28>> index 0 level 1 orig_level 2 chain <type_decl 0x7fffea2f2850 V>> $15 = void Both of these BOUND_TEMPLATE_TEMPLARE_PARMs are created in #4 0x0000000001462bbc in copy_node (node=<bound_template_template_parm 0x7fffea2eda80 V>) at ../../gcc/tree.cc:1334 #5 0x00000000005d9d68 in copy_type (type=<bound_template_template_parm 0x7fffea2eda80 V>) at ../../gcc/cp/lex.cc:1067 #6 0x0000000000767b5f in tsubst (t=<bound_template_template_parm 0x7fffea2eda80 V>, args=<tree_vec 0x7fffea2cec60>, complain=1, in_decl=<function_decl 0x7fffea2da700 bar>) at ../../gcc/cp/pt.cc:16262 #7 0x0000000000765155 in tsubst_function_type (t=<method_type 0x7fffea2edbd0>, args=<tree_vec 0x7fffea2cec60>, complain=1, in_decl=<function_decl 0x7fffea2da700 bar>) at ../../gcc/cp/pt.cc:15649 #8 0x00000000007687af in tsubst (t=<method_type 0x7fffea2edbd0>, args=<tree_vec 0x7fffea2cec60>, complain=1, in_decl=<function_decl 0x7fffea2da700 bar>) at ../../gcc/cp/pt.cc:16468 #9 0x000000000075afd2 in tsubst_function_decl (t=<function_decl 0x7fffea2da700 bar>, args=<tree_vec 0x7fffea2cec60>, complain=1, lambda_fntype=<tree 0x0>) at ../../gcc/cp/pt.cc:14419 #10 0x000000000075df67 in tsubst_template_decl (t=<template_decl 0x7ffff7ffa700 bar>, args=<tree_vec 0x7fffea2cec60>, complain=1, lambda_fntype=<tree 0x0>) at ../../gcc/cp/pt.cc:14730 #11 0x00000000007613a1 in tsubst_decl (t=<template_decl 0x7ffff7ffa700 bar>, args=<tree_vec 0x7fffea2cec60>, complain=1) at ../../gcc/cp/pt.cc:14892 #12 0x0000000000765f8e in tsubst (t=<template_decl 0x7ffff7ffa700 bar>, args=<tree_vec 0x7fffea2cec60>, complain=1, in_decl=<tree 0x0>) at ../../gcc/cp/pt.cc:15933 and #4 0x0000000001462bbc in copy_node (node=<bound_template_template_parm 0x7fffea2eda80 V>) at ../../gcc/tree.cc:1334 #5 0x00000000005d9d68 in copy_type (type=<bound_template_template_parm 0x7fffea2eda80 V>) at ../../gcc/cp/lex.cc:1067 #6 0x0000000000767b5f in tsubst (t=<bound_template_template_parm 0x7fffea2eda80 V>, args=<tree_vec 0x7fffea2f1400>, complain=1, in_decl=<function_decl 0x7fffea2da700 bar>) at ../../gcc/cp/pt.cc:16262 #7 0x0000000000765155 in tsubst_function_type (t=<method_type 0x7fffea2edbd0>, args=<tree_vec 0x7fffea2f1400>, complain=1, in_decl=<function_decl 0x7fffea2da700 bar>) at ../../gcc/cp/pt.cc:15649 #8 0x00000000007687af in tsubst (t=<method_type 0x7fffea2edbd0>, args=<tree_vec 0x7fffea2f1400>, complain=1, in_decl=<function_decl 0x7fffea2da700 bar>) at ../../gcc/cp/pt.cc:16468 #9 0x000000000075afd2 in tsubst_function_decl (t=<function_decl 0x7fffea2da700 bar>, args=<tree_vec 0x7fffea2f1400>, complain=1, lambda_fntype=<tree 0x0>) at ../../gcc/cp/pt.cc:14419 #10 0x000000000075df67 in tsubst_template_decl (t=<template_decl 0x7ffff7ffa700 bar>, args=<tree_vec 0x7fffea2f1400>, complain=1, lambda_fntype=<tree 0x0>) at ../../gcc/cp/pt.cc:14730 #11 0x00000000007613a1 in tsubst_decl (t=<template_decl 0x7ffff7ffa700 bar>, args=<tree_vec 0x7fffea2f1400>, complain=1) at ../../gcc/cp/pt.cc:14892 #12 0x0000000000765f8e in tsubst (t=<template_decl 0x7ffff7ffa700 bar>, args=<tree_vec 0x7fffea2f1400>, complain=1, in_decl=<tree 0x0>) at ../../gcc/cp/pt.cc:15933 The first one being bar instantiation with C arg, the latter with B arg. When hashing those, the difference is in if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM) val = iterative_hash_template_arg (TYPE_TI_ARGS (t), val); which is a TREE_VEC containing <pointer_type 0x7fffea2ed1f8 type type <integer_type 0x7fffea14f5e8 int public type_6 SI size <integer_cst 0x7fffea151210 constant 32> unit-size <integer_cst 0x7fffea151228 constant 4> align:32 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7fffea14f5e8 precision:32 min <integer_cst 0x7fffea1511c8 -2147483648> max <integer_cst 0x7fffea1511e0 2147483647> pointer_to_this <pointer_type 0x7fffea157b28>> unsigned DI size <integer_cst 0x7fffea12cfc0 type <integer_type 0x7fffea14f0a8 bitsizetype> constant 64> unit-size <integer_cst 0x7fffea12cfd8 type <integer_type 0x7fffea14f000 sizetype> constant 8> align:64 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7fffea157b28> in one case and <pointer_type 0x7fffea2f87e0 type type <integer_type 0x7fffea14f5e8 int public type_6 SI size <integer_cst 0x7fffea151210 constant 32> unit-size <integer_cst 0x7fffea151228 constant 4> align:32 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7fffea14f5e8 precision:32 min <integer_cst 0x7fffea1511c8 -2147483648> max <integer_cst 0x7fffea1511e0 2147483647> pointer_to_this <pointer_type 0x7fffea157b28>> unsigned DI size <integer_cst 0x7fffea12cfc0 type <integer_type 0x7fffea14f0a8 bitsizetype> constant 64> unit-size <integer_cst 0x7fffea12cfd8 type <integer_type 0x7fffea14f000 sizetype> constant 8> align:64 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7fffea157b28> in another. In the second case it triggers if (tree ats = alias_template_specialization_p (arg, nt_transparent)) { // We want an alias specialization that survived strip_typedefs // to hash differently from its TYPE_CANONICAL, to avoid hash // collisions that compare as different in template_args_equal. // These could be dependent specializations that strip_typedefs // left alone, or untouched specializations because // coerce_template_parms returns the unconverted template // arguments if it sees incomplete argument packs. tree ti = TYPE_ALIAS_TEMPLATE_INFO (ats); return hash_tmpl_and_args (TI_TEMPLATE (ti), TI_ARGS (ti)); } in iterative_hash_template_arg, while in the first case it doesn't and it gets default: if (tree canonical = TYPE_CANONICAL (arg)) val = iterative_hash_object (TYPE_HASH (canonical), val); and so they hash differently. But apparently structural_comptypes thinks they are equal.