I was doing an analysis of all the C++ features that are disabled in DXC so that we can make sure that the HLSL language specification accurately reflects the state of DXC and we can make Clang match.
This led me to generating some really awful code…
Code hidden because it is awful and long...
struct S {
int X;
};
struct S1 : S {};
struct S2 : S1 {};
struct S3 : S2 {};
struct S4 : S3 {};
struct S5 : S4 {};
struct S6 : S5 {};
struct S7 : S6 {};
struct S8 : S7 {};
struct S9 : S8 {};
struct S10 : S9 {};
struct S11 : S10 {};
struct S12 : S11 {};
struct S13 : S12 {};
struct S14 : S13 {};
struct S15 : S14 {};
struct S16 : S15 {};
struct S17 : S16 {};
struct S18 : S17 {};
struct S19 : S18 {};
struct S20 : S19 {};
struct S21 : S20 {};
struct S22 : S21 {};
struct S23 : S22 {};
struct S24 : S23 {};
struct S25 : S24 {};
struct S26 : S25 {};
struct S27 : S26 {};
struct S28 : S27 {};
struct S29 : S28 {};
struct S30 : S29 {};
struct S31 : S30 {};
struct S32 : S31 {};
struct S33 : S32 {};
struct S34 : S33 {};
struct S35 : S34 {};
struct S36 : S35 {};
struct S37 : S36 {};
struct S38 : S37 {};
struct S39 : S38 {};
struct S40 : S39 {};
struct S41 : S40 {};
struct S42 : S41 {};
struct S43 : S42 {};
struct S44 : S43 {};
struct S45 : S44 {};
struct S46 : S45 {};
struct S47 : S46 {};
struct S48 : S47 {};
struct S49 : S48 {};
struct S50 : S49 {};
struct S51 : S50 {};
struct S52 : S51 {};
struct S53 : S52 {};
struct S54 : S53 {};
struct S55 : S54 {};
struct S56 : S55 {};
struct S57 : S56 {};
struct S58 : S57 {};
struct S59 : S58 {};
struct S60 : S59 {};
struct S61 : S60 {};
struct S62 : S61 {};
struct S63 : S62 {};
struct S64 : S63 {};
struct S65 : S64 {};
struct S66 : S65 {};
struct S67 : S66 {};
struct S68 : S67 {};
struct S69 : S68 {};
struct S70 : S69 {};
struct S71 : S70 {};
struct S72 : S71 {};
struct S73 : S72 {};
struct S74 : S73 {};
struct S75 : S74 {};
struct S76 : S75 {};
struct S77 : S76 {};
struct S78 : S77 {};
struct S79 : S78 {};
struct S80 : S79 {};
struct S81 : S80 {};
struct S82 : S81 {};
struct S83 : S82 {};
struct S84 : S83 {};
struct S85 : S84 {};
struct S86 : S85 {};
struct S87 : S86 {};
struct S88 : S87 {};
struct S89 : S88 {};
struct S90 : S89 {};
struct S91 : S90 {};
struct S92 : S91 {};
struct S93 : S92 {};
struct S94 : S93 {};
struct S95 : S94 {};
struct S96 : S95 {};
struct S97 : S96 {};
struct S98 : S97 {};
struct S99 : S98 {};
struct S100 : S99 {};
struct S101 : S100 {};
export int fn(int X) {
S101 s = {X};
return (int)s;
}
So, if you actually read that it should work, right? Like there’s nothing there that shouldn’t be legal (but please god tell me nobody would write it).

This code came into being because I came across an odd error string:
compiler failed to analyze type %0, try using types with less nesting
This inspired me to figure out what causes that error to occur, and with a little help from my friend Claude… We have the crime against HLSL that is the code above.
And in case you think this might be just an inheritance problem and nobody should ever use inheritance like that right? Well… it also happens with composition:
Code hidden because it is awful and long...
struct S {
int X;
};
struct S1 { S base; };
struct S2 { S1 base; };
struct S3 { S2 base; };
struct S4 { S3 base; };
struct S5 { S4 base; };
struct S6 { S5 base; };
struct S7 { S6 base; };
struct S8 { S7 base; };
struct S9 { S8 base; };
struct S10 { S9 base; };
struct S11 { S10 base; };
struct S12 { S11 base; };
struct S13 { S12 base; };
struct S14 { S13 base; };
struct S15 { S14 base; };
struct S16 { S15 base; };
struct S17 { S16 base; };
struct S18 { S17 base; };
struct S19 { S18 base; };
struct S20 { S19 base; };
struct S21 { S20 base; };
struct S22 { S21 base; };
struct S23 { S22 base; };
struct S24 { S23 base; };
struct S25 { S24 base; };
struct S26 { S25 base; };
struct S27 { S26 base; };
struct S28 { S27 base; };
struct S29 { S28 base; };
struct S30 { S29 base; };
struct S31 { S30 base; };
struct S32 { S31 base; };
struct S33 { S32 base; };
struct S34 { S33 base; };
struct S35 { S34 base; };
struct S36 { S35 base; };
struct S37 { S36 base; };
struct S38 { S37 base; };
struct S39 { S38 base; };
struct S40 { S39 base; };
struct S41 { S40 base; };
struct S42 { S41 base; };
struct S43 { S42 base; };
struct S44 { S43 base; };
struct S45 { S44 base; };
struct S46 { S45 base; };
struct S47 { S46 base; };
struct S48 { S47 base; };
struct S49 { S48 base; };
struct S50 { S49 base; };
struct S51 { S50 base; };
struct S52 { S51 base; };
struct S53 { S52 base; };
struct S54 { S53 base; };
struct S55 { S54 base; };
struct S56 { S55 base; };
struct S57 { S56 base; };
struct S58 { S57 base; };
struct S59 { S58 base; };
struct S60 { S59 base; };
struct S61 { S60 base; };
struct S62 { S61 base; };
struct S63 { S62 base; };
struct S64 { S63 base; };
struct S65 { S64 base; };
struct S66 { S65 base; };
struct S67 { S66 base; };
struct S68 { S67 base; };
struct S69 { S68 base; };
struct S70 { S69 base; };
struct S71 { S70 base; };
struct S72 { S71 base; };
struct S73 { S72 base; };
struct S74 { S73 base; };
struct S75 { S74 base; };
struct S76 { S75 base; };
struct S77 { S76 base; };
struct S78 { S77 base; };
struct S79 { S78 base; };
struct S80 { S79 base; };
struct S81 { S80 base; };
struct S82 { S81 base; };
struct S83 { S82 base; };
struct S84 { S83 base; };
struct S85 { S84 base; };
struct S86 { S85 base; };
struct S87 { S86 base; };
struct S88 { S87 base; };
struct S89 { S88 base; };
struct S90 { S89 base; };
struct S91 { S90 base; };
struct S92 { S91 base; };
struct S93 { S92 base; };
struct S94 { S93 base; };
struct S95 { S94 base; };
struct S96 { S95 base; };
struct S97 { S96 base; };
struct S98 { S97 base; };
struct S99 { S98 base; };
struct S100 { S99 base; };
struct S101 { S100 base; };
export int fn(int X) {
S101 s = {X};
return (int)s;
}
So, let’s dig into this.
The language behavior that comes into play here is type “flattening” as DXC calls it. The basic idea is that all types in HLSL can be decomposed into a sequential ordering of scalar values. This is important in GPU programming because ultimately most of your data structures will be split up into constituent parts and spread across registers on the GPU.
Where things get a bit weird is that in HLSL any two types that have “compatible scalar layouts” can be converted to each other. The draft language spec has some complicated words to describe this:

DXC emits this error because the algorithm that performs type flattening is recursive, and the compiler bails out instead of recursing to absurd degrees. This of course, is probably reasonable, and I suspect next to nobody has ever hit this error.
Clang’s implementation isn’t recursive in the same way so we haven’t imposed this restriction, so Clang will in fact compile my terrible code.