I've looked into this further, and I now understand what's going on. It turns out that modules inside modules isn't the only way to trigger the problem. It's actually related to module caching.
Say you have ModuleLoader A which loads Module A and ModuleLoader B which loads Module B. ModuleLoader A is at the top-level of the application. ModuleLoader B is inside Module A.
If you load Module A, then load Module B, setting applicationDomain on both ModuleLoaders to be "new ApplicationDomain(ApplicationDomain.currentDomain)", moduleLoaderB.applicationDomain contains the definitions of all classes in the top-level application as well as those in Module A and Module B.
If you then unload Module A (moduleLoaderA.unloadModule()), then use the module loaders to load Module A and Module B again, moduleLoaderB.applicationDomain contain NO class definitions.
Inside Module B, however, the ApplicationDomain.currentDomain DOES contain the correct class definitions. But if you try to access Module B's applicationDomain by using moduleLoaderB.applicationdomain (e.g., which you might do from inside Module A to pass the applicationDomain to Tide), then you will be unable to access any class definitions inside Module B.
HERE'S THE REASON THIS HAPPENS:
When you tell Flex to load Module B the second time, it does NOT load it again using Loader.load(). Instead it creates a copy of it from its cache which *uses whatever applicationDomain you assigned to it originally*! This means the applicationDomain you created for it the second time never gets used and contains no class definitions!
HERE'S HOW TO FIX IT:
Option 1:
Unload Module B before loading it the second time. For example, call moduleLoaderB.unloadModule(). This will allow you to set the applicationDomain again the second time you load it.
Option 2:
Keep a reference to the original applicationDomain lying around somewhere and pass it to Tide the second time you load the module.
Gabriel