That's an awfully broad question. I'm no expert in DMD, but I do dabble in the source code often.
I'd start here: https://wiki.dlang.org/DMD_Source_Guide The information there is old but still relevant.
This is my mental model and understanding
source code --> lexer.d --> tokesn
tokens --> parse.d --> expressions (see expression.d)
expressions --> expressionsem.d --> lowered expressions
lowered expressions --> e2ir --> intermediate representation (I'm awufully vauge on this)
After that it's in the backend, and that's pretty much a black box to me.
That, however, is a gross oversimplification. If you want to browse the code that implements the semantic phase you'll want to look at any file of the form xxxsem.d (e.g. dsymbolsem.d, expressionsem.d, typesem.d). For the task at hand, issue 16486, you'll probably find the fix somewhere in there, but don't quote me on that. Search for functions with `resolve` in the name. Though the fix may also reside in one of the `visit` methods of one of the visitors in those files.
Tracing with `printf` is your friend, which is why you see so many commented `printf` statements in the source code. You should be able to print out almost anything with with the `toChars()` method (e.g. `printf("%s\n", whatever.toChars());`)
Mike