Dynamic associated type

Hi, I'm working on a file system abstraction and have run into an issue using GATs. My file system is made up of nodes and different file system implementations (e.g. fat32, ext4, proc). The file system implementations define structs for files, directories, etc. and then implement Node for them. Node takes a file system ZST as a generic to prevent mixing different file system nodes. However, the root directory will contain multiple different file system implementations (e.g. /home is fat32, /proc is a lazily computed file system that stores information about processes). Is it possible to encode this in the type system?

This was the idea I had:

trait FileSystem {
    /// Which file systems this file system can contain.
    type Allowed: FileSystem = Self;
}

struct Fat32;

impl FileSystem for Fat32 {}

struct Ext4;

impl FileSystem for Ext4 {}

struct Any;

impl FileSystem for Any {
    type Allowed = dyn FileSystem<Allowed = dyn FileSystem<Allowed = dyn FileSystem<Infinite>>>;
}

trait Node {
    type FileSystem: FileSystem;
    // Some methods e.g.
    fn parent(&self) -> Option<&dyn Node<FileSystem = Self::FileSystem::Allowed>>;
}

My complete example is here, but it contains quite a bit more code: fs.rs · GitHub

This can never work. Associated types will only let you specify a single type. If you want multiple, then you'll need something like this:

trait AllowsFileSystem<T> {}

Then writing this:

impl AllowsFileSystem<A> for B {}

Would mean that B allows file system A inside it. For example, to say that Ext4 may contain itself, you could write:

impl AllowsFileSystem<Ext4> for Ext4 {}

To say that Any allows everything, you can say:

struct Any;
impl<T: FileSystem> AllowsFileSystem<T> for Any {}
2 Likes