If I write a D file like this one: http://arsdnet.net/dcode/iface/test.d and you compile with dmd -c, you'll see it goes without errors; that's a valid D file. The language allows you to write function prototypes without implementations.
A .di file is just like that, it just has a different file name.
Then given main: http://arsdnet.net/dcode/main.d if you compile dmd main, it will automatically search for iface/test.d when it sees "import iface.test;", find that .d file, or the .di if you rename it but same thing, and get your interface definition.
dmd main will fail with a linker error, so we need to implement it: http://arsdnet.net/dcode/impl.d Note: the impl does NOT import the module, so it never checks the other file. Keeping the .di and .d files in sync is one of the tricky parts here, unless you auto-generate the interface file, as undefined methods would give linker errors, but the order of methods is important: it must match, and so do the list of variables if there's any public ones. Otherwise, the usage code and the implementation code won't agree on the class' layout.
Again, it does not check that automatically, the implementation file doesn't look at the "header" file at all, so this is a major difference from C++ where you write the header file once, then use it in both the usage program and the implementation file.
You'll notice that the implementation file also lists the class, etc., too. D doesn't support the void MyClass::add(int a) {}
syntax C++ has to write the method outside the class.
As far as I know, there's no way to force the implementation file to look for the header, if you put both on the command line, you get: "Error: module iface.test from file iface/test.d conflicts with another module test from file impl.d"
The way .di files are recommended to be used is to auto generate them with dmd -H. This reads the full implementation file and strips out the function bodies, leaving just the definitions. This part is probably the key thing when they say it is a feature of the compiler - the .di file is valid and standard D, but generated via a compiler option that doesn't necessarily need to be part of other compilers.