The weirdest bug I’ve found in a compiler: MSVC 2017

There’s been discussion on cppitertools about the newest MSVC release (15.7) claiming to be fully standards compliant, which led me here.

The following code fails to compile under MSVC for one reason: the U on lines 4 and 5 is a different name than the T on lines 10 and 11, so the result of the static_assert condition on line 19 is false. (Note that I’m not using std::declval here for simplicity’s sake).

Don’t believe me? Here it is on godbolt, and here’s the same code with gcc, and the same code again with clang. (Note that godbolt doesn’t have the latest MSVC, but I’ve tested all of these with MSVC 15.7)

The exact same with only that U replaced with T on lines 4 and 5 compiles just fine.

You might be thinking: “maybe there’s something special about T that makes this work.” That’s not the case, it works no matter what the name is, just as long as it matches. Here’s the same code with Apple instead of T.

It gets even stranger. I accidentally compiled something I didn’t mean to, and now I’m even more confused.

The type alias is able to see the T typename somehow, when it shouldn’t be possible (godbolt):

It works even just using template <typename>. It works when templated on an int! It can see HasFunc's T!

However, to get func_type to work outside of a template, I still need to use T as the template parameter or something like tests::func_type<A>wouldn’t work.

The issue doesn’t seem to generalize well. For example this use in a function works fine:

I reported the bug, we’ll see what happens.

I’m lost. Goodnight everyone.