Stream: t-compiler

Topic: rustc vfs


Igor Matuszewski (Sep 19 2019 at 22:42, on Zulip):

Would there be any interest in supporting a VFS/overlay fs in rustc directly? One rationale was to execute cargo check but with in-memory text buffers rather than the files on disk itself. This led to reimplementation of own wrappers VFS in RLS and Rust Analyzer; if we support that directly we could drop the extra code on each side and execute rustc directly.

This would simplify one of the approaches mentioned in the rls/rust-analyzer planning meeting today, where we integrate cargo check directly to provide accurate errors in addition to quick IDE features by Rust Analyzer.
It also would technically allow us to decouple RLS completely from rustc if we were to reuse the existing save-analysis architecture.

cc @matklad @nikomatsakis (did I miss anyone?)
@Jeremy Fitzhardinge @Taylor Cramer would that be also useful in any scenario involving external build integration?

Igor Matuszewski (Sep 19 2019 at 22:42, on Zulip):

Issue at https://github.com/rust-lang/rust/issues/59976

simulacrum (Sep 19 2019 at 22:48, on Zulip):

@Igor Matuszewski Could you expand on "While it's possible to provide a FileLoader trait implementation when running rustc, it requires the user to run the compiler in-process."?

simulacrum (Sep 19 2019 at 22:48, on Zulip):

Why does it need to be run in-process?

simulacrum (Sep 19 2019 at 22:49, on Zulip):

I guess " This particular case could be side-stepped by implementing IPC for our VFS implementation that could be relayed to using our FileLoader trait and rustc shim (rls-rustc)." is the alternative to that? Though I'd imagine shared memory would work as well since presumably there's already some notion of locks

simulacrum (Sep 19 2019 at 22:50, on Zulip):

I personally feel though that this is pretty strongly out of scope for a rustc feature and it's not entirely clear to me why it can't be implemented outside and loaded in as a FileLoader impl -- maybe we can redesign FileLoader to make that more possible?

Igor Matuszewski (Sep 19 2019 at 23:17, on Zulip):

@simulacrum by in-process I meant that the trait is inherently on the rustc side and if someone wishes to use it then they have to opt into rustc_private anyway and wrap that around

Igor Matuszewski (Sep 19 2019 at 23:18, on Zulip):

shared memory or IPC works good but requires authoring a separate wrapper

simulacrum (Sep 19 2019 at 23:18, on Zulip):

hm, yes, but presumably that's not a problem for RLS etc?

Igor Matuszewski (Sep 19 2019 at 23:18, on Zulip):

I was wondering if it'd be possible to support something like a pathfile supplied to rustc which it'd use and fallback to the real disk file if not found in the patch

Igor Matuszewski (Sep 19 2019 at 23:19, on Zulip):

well no, it's not a problem per-se for RLS, we use the shim ourselves as of now

Igor Matuszewski (Sep 19 2019 at 23:19, on Zulip):

but I imagine Rust Analyzer can't use it since they want to support stable toolchain entirely

Igor Matuszewski (Sep 19 2019 at 23:20, on Zulip):

so the status quo remains that Rust Analyzer can only provide correct diagnostics if the files are saved

simulacrum (Sep 19 2019 at 23:20, on Zulip):

I would be not entirely opposed to the idea of trying to factor out the FileLoader trait into a crate that compiles on stable

Igor Matuszewski (Sep 19 2019 at 23:20, on Zulip):

and also RLS needs to ship its own version of the compiler, whereas I imagine it'd be good to imagine a way to just point it at the Rust toolchain (with minimum version of XYZ) and expect things to work

simulacrum (Sep 19 2019 at 23:20, on Zulip):

(obviously, we might need to issue breaking changes and coordinate updates, etc. -- but that all seems viable)

simulacrum (Sep 19 2019 at 23:21, on Zulip):

but given how platform-specific I imagine an virtual file system is, I'd rather not manage it ourselves

simulacrum (Sep 19 2019 at 23:21, on Zulip):

unless I'm wrong about it being platform specific?

Igor Matuszewski (Sep 19 2019 at 23:21, on Zulip):

the only bits I imagine can be quite hard are canonical version of the paths

Igor Matuszewski (Sep 19 2019 at 23:23, on Zulip):

FileLoader already has abs_path - it could be a function to transform all the paths given in a pathfile and always resolve files around these

Igor Matuszewski (Sep 19 2019 at 23:23, on Zulip):

other than that, we need to be able to load a String under a given path in rustc and not much else, thankfully

simulacrum (Sep 19 2019 at 23:28, on Zulip):

hm, so then this might be easier than I expected

simulacrum (Sep 19 2019 at 23:29, on Zulip):

if this is just "I want to make rustc load paths with root X instead of /" then that seems viable to implement as an unstable (and maybe on the road to stabilization) flag

simulacrum (Sep 19 2019 at 23:29, on Zulip):

Is it that simple, or am I missing something?

Igor Matuszewski (Sep 19 2019 at 23:36, on Zulip):

@simulacrum it's more of a "hey rustc, when compiling as you do normally, please consider file "src/some/module.rs" to have contents of "XYZ" instead of the actual one on the disk, thanks"

Igor Matuszewski (Sep 19 2019 at 23:37, on Zulip):

I mean, technically you could do that if for every compilation you create a tempdir, copy everything over and only patch the relevant bits yourself but that's seems very unpractical somehow

simulacrum (Sep 19 2019 at 23:37, on Zulip):

hm, how would you expect to provide the contents?

simulacrum (Sep 19 2019 at 23:38, on Zulip):

Passing them as a flag doesn't seem viable :)

Igor Matuszewski (Sep 19 2019 at 23:38, on Zulip):

and might break some relative path "upwards" (some code may depend on the cargo OUT_DIR, so you'd need to analyze the project layout and so on, not pretty)

Igor Matuszewski (Sep 19 2019 at 23:38, on Zulip):

I guess the simplest would be to pass it a path to a patchfile which would contain only the patched bits?

Igor Matuszewski (Sep 19 2019 at 23:38, on Zulip):

JSON comes to mind, obviously

Igor Matuszewski (Sep 19 2019 at 23:39, on Zulip):

and it'd probably be good not to use the actual diffs because then rustc would need to know how to apply them, be careful for the files not to change while it compiles and so on

simulacrum (Sep 19 2019 at 23:40, on Zulip):

I guess to me it seems like this is a pretty hard thing to implement in a sort of decoupled way

simulacrum (Sep 19 2019 at 23:40, on Zulip):

which makes it a poor candidate for stability in general

simulacrum (Sep 19 2019 at 23:40, on Zulip):

(since it seems like it'd be somewhat prone to wanting to change)

Igor Matuszewski (Sep 19 2019 at 23:40, on Zulip):

I know, it is =( it sort of just promotes FileLoader to CLI

simulacrum (Sep 19 2019 at 23:40, on Zulip):

yeah, that seems.. not great

Igor Matuszewski (Sep 19 2019 at 23:40, on Zulip):

(which is kind of what we want, not sure about alternatives that don't require to ship/wrap rustc themselves)

simulacrum (Sep 19 2019 at 23:41, on Zulip):

hm, so maybe one alternative would be to run some binary on each file load?

simulacrum (Sep 19 2019 at 23:41, on Zulip):

basically like the "default" is cat

Igor Matuszewski (Sep 19 2019 at 23:41, on Zulip):

like a 'proc macro' but for loaded files?

simulacrum (Sep 19 2019 at 23:41, on Zulip):

well, I was thinking more .. just a binary

simulacrum (Sep 19 2019 at 23:41, on Zulip):

like, not a shared object or anything

Igor Matuszewski (Sep 19 2019 at 23:41, on Zulip):

okay

simulacrum (Sep 19 2019 at 23:41, on Zulip):

is that too high overhead?

Igor Matuszewski (Sep 19 2019 at 23:41, on Zulip):

hm

Igor Matuszewski (Sep 19 2019 at 23:42, on Zulip):

not sure, haven't measured

Igor Matuszewski (Sep 19 2019 at 23:42, on Zulip):

you'd have to spawn a process for every read file

simulacrum (Sep 19 2019 at 23:42, on Zulip):

sure, yeah -- well, you could imagine some structure where e.g. we ban null bytes or something and can pass more than one

simulacrum (Sep 19 2019 at 23:42, on Zulip):

(or just full JSON RPC, but I'd rather not)

Igor Matuszewski (Sep 19 2019 at 23:42, on Zulip):

that seems extensible

Igor Matuszewski (Sep 19 2019 at 23:42, on Zulip):

like a file pre-processor

simulacrum (Sep 19 2019 at 23:43, on Zulip):

yeah, we could even do something like "rustc will run $cmd --format-version=1 $filepath"

Igor Matuszewski (Sep 19 2019 at 23:43, on Zulip):

D: just imagined a QT moc-style preprocessing

simulacrum (Sep 19 2019 at 23:43, on Zulip):

I don't know anything about that :)

Igor Matuszewski (Sep 19 2019 at 23:44, on Zulip):

that seems... too? powerful

Igor Matuszewski (Sep 19 2019 at 23:44, on Zulip):

it's extensible but I'm not sure if someone would abuse it anyhow?

Igor Matuszewski (Sep 19 2019 at 23:44, on Zulip):

maybe I'm going in a wrong direction, sorry about that

Igor Matuszewski (Sep 19 2019 at 23:45, on Zulip):

it seems powerful and would solve this use-case, yeah

simulacrum (Sep 19 2019 at 23:45, on Zulip):

heh, no worries -- I personally would imagine this to be pretty high overhead though

simulacrum (Sep 19 2019 at 23:46, on Zulip):

largely though I don't see any other way for us to accept the file contents

simulacrum (Sep 19 2019 at 23:46, on Zulip):

like, if we're to do it on stable we want some pretty straightforward way to do so

Igor Matuszewski (Sep 19 2019 at 23:47, on Zulip):

on the 'too powerful' note, one could even call a C preprocessor on top of each file

Igor Matuszewski (Sep 19 2019 at 23:47, on Zulip):

which is interesting

simulacrum (Sep 19 2019 at 23:47, on Zulip):

you're not wrong, but that seems like "okay, sure" - you could do the same with a proc macro today

simulacrum (Sep 19 2019 at 23:47, on Zulip):

#![foo] atop the crate or module and replace all the tokens

Igor Matuszewski (Sep 19 2019 at 23:48, on Zulip):

that is true

simulacrum (Sep 19 2019 at 23:48, on Zulip):

somewhat more limited because input must tokenize as Rust I believe, but that's pretty flexible

Igor Matuszewski (Sep 19 2019 at 23:49, on Zulip):

well, that'd be one way to do it :sweat_smile: I'm wondering what would be the performance overhead of that, though

simulacrum (Sep 19 2019 at 23:52, on Zulip):

in theory one can do this today, right? Like, y'all already wrap rustc so trialing this wouldn't be too hard

Igor Matuszewski (Sep 20 2019 at 00:11, on Zulip):

Yup

Igor Matuszewski (Sep 20 2019 at 00:11, on Zulip):

@matklad got any thoughts on that?

simulacrum (Sep 20 2019 at 00:12, on Zulip):

(mostly to see if this is at all viable, and then if it is, we can probably land it as unstable pretty easily; it might need an RFC to be stabilized though -- not sure if an FCP is enough there. It might be)

matklad (Sep 20 2019 at 06:53, on Zulip):

Hello!

So, I think there are two threads here:

I am very skeptical of the first one: looks like FileLoader is exactly what rustc currently needs, and it's only a trait. I don't see a benefit of moving it outside. rust-analyzer and rls need something different, and that hopefully can be shared, irrespective of rustc, but design space there is large. I am not to happy about current VFS implementations neither in rls, nor in rust-analyzer. I have a rough plan for better VFS for rust-analyzer, if it works, the result should be sharable between rls and rust-analyzer.

I would like to see the second one, as it allows us to run cargo check without saving files to disk. The most important question here is stability. As this is intended to help IDEs, it's important that it works on stable, but it also should be an internal interface that no one should use. Can we have #[doc(hidden)] flags for rustc? I think we can: for one, RUST_BOOTSTRAP is one, and it is a much greater stabilization hazard than the proposed. If there's a constraint that we want to design this feature such that it is stable for realz, I think that maybe it's not worth it: the IDE can just save files before calling cargo check or the like. IntelliJ does this.

I am not sure what is the right interface for IPC-ish vfs inside rustc. I don't like idea of passing a map of modified files as a json flag, as it might be hard to figure out which of modified files are relevant to rustc (that is, how IDE should figured out that there's no need to pass .cpp files)? I don't like the idea of shelling out to new external process to read every file, as it suffers from the opposite problem: most files are just fine as they are on disk, so this creates needless overhead.

I'd love a pipe-based IPC: basically, we pass VFS_FILE_DESCRIPTOR=92 env var, and then we shuffle something stupid like bincode or newline separate JSON over it. Not sure how cross-platform pipes are. Not sure how this should work with concurrent rustc invocations.

matklad (Sep 20 2019 at 07:02, on Zulip):

Apparently, IntelliJ would also be interested in this, so cc @Vlad :-) This makes my ideas of "stable, do not use this" interface more questionable, but I still think that it would be good to phrase this as: this API is doc-hidden, only selected set of tools (rust-analyzer, RLS, IntelliJ) are allowed to use it, API can break between releases of the compiler.

Igor Matuszewski (Sep 20 2019 at 07:18, on Zulip):

for the record I meant to tackle the second of the point you listed here =)

simulacrum (Sep 20 2019 at 10:52, on Zulip):

@matklad I would personally object pretty strongly to what I think you're suggesting - stabilizing something "just for IDEs" doesn't seem viable to me, even if it is done via a env variable or so. I would definitely want that to go through RFC process to elaborate why we think it's okay to break the IDE use case but not others (if I'm understanding you correctly that we'd allow use in stable, but still reserve the right to break it)

matklad (Sep 20 2019 at 10:56, on Zulip):

Agree that it should go via RFC process, as its a departure from stability guarantees. The short reason why I think is ok is that IDEs have to track unstable features and compiler versions anyway (as std uses unstable), and that I don't see any other important consumers of this feature.

matklad (Sep 20 2019 at 10:58, on Zulip):

(to give a concrete example, changing sysroot crate graph definitely breaks IntelliJ, because it manually tracks deps between sysroot crates)

nikomatsakis (Sep 26 2019 at 13:47, on Zulip):

I tend to think it may also be viable to have a function that is avaiable "on stable" but documented as being exempted from the standard stability guarantees (and suitably hidden, etc)

simulacrum (Sep 26 2019 at 13:49, on Zulip):

hm, sure, but I think that probably doesn't buy us much? I presume RLS etc want actual stability :)

nikomatsakis (Sep 26 2019 at 13:49, on Zulip):

why?

nikomatsakis (Sep 26 2019 at 13:49, on Zulip):

we issue an RLS version per rustc release, right?

nikomatsakis (Sep 26 2019 at 13:50, on Zulip):

I imagine anyway it would be documented as "this may be changed betwen rust releases, but we make an effort to coordinate with known users" and the expectation would be that it's "mostly stable"

nikomatsakis (Sep 26 2019 at 13:50, on Zulip):

anyway, i'm not sure if that's a good idea, but I think that for tools integration we may want to consider things like that

simulacrum (Sep 26 2019 at 13:50, on Zulip):

hm, maybe RLS is not a good example -- since we do build that in tree. But I think @matklad was saying that e.g. rust-analyzer wants to compile on arbitrary stable/nightly etc

nikomatsakis (Sep 26 2019 at 13:50, on Zulip):

yeah, it would mean the rust-analyzer has to be used with a "matched" version of rust

nikomatsakis (Sep 26 2019 at 13:51, on Zulip):

(though it could be built with any, sounds like?)

nikomatsakis (Sep 26 2019 at 13:51, on Zulip):

I thought that was what @matklad was requesting, but maybe I misunderstood

simulacrum (Sep 26 2019 at 13:52, on Zulip):

I understood as "used" -- unless the function is like extern "C" or something we can't really support the 'build but not used' due to ABI differences, right?

nikomatsakis (Sep 26 2019 at 14:00, on Zulip):

true

nikomatsakis (Sep 26 2019 at 14:00, on Zulip):

anyway it does seem "icky"

nikomatsakis (Sep 26 2019 at 14:00, on Zulip):

butI thought maybe matklad was referring to some IPC-based sol'n?

nikomatsakis (Sep 26 2019 at 14:00, on Zulip):

tbh I didn't read all the details :)

nikomatsakis (Sep 26 2019 at 14:00, on Zulip):

/me too many messages right now

matklad (Sep 26 2019 at 14:47, on Zulip):

@simulacrum rust-analyzer does not link to rustc, by design, so ABI is completely irrelevant. That is, rust-analyzer is just a vanilla binary crate, which builds on the latest stable, and I prefer to keep it so for forseable future.

"what compiler/cargo can you use together with rust-analyzer, for developing your code?" is another question. The current policy is roughtly "any compiler older that X", where X is some constant that exists, is strictly grater than 1.0.0, but whose precise value is unknown to me. That is, we just assume that certain Cargo flags exists (most notably, cargo metadata which introduce somewhere around 1.10-ish). We definitely do not make a promise to work with arbitrary old rustc

simulacrum (Sep 26 2019 at 14:48, on Zulip):

I was responding to Niko's proposal of a function (which then means ABI)

matklad (Sep 26 2019 at 14:49, on Zulip):

Ah, yeah, I got confused, that's definitelly IPC we need, and not a function.

nikomatsakis (Sep 26 2019 at 14:57, on Zulip):

I was responding to Niko's proposal of a function (which then means ABI)

really I meant IPC anyway :)

nikomatsakis (Sep 26 2019 at 14:57, on Zulip):

what I meant is: we can offer some interface and say "this interface exists, but the data that passes through it is unstable"

nikomatsakis (Sep 26 2019 at 14:57, on Zulip):

we've done that before...

nikomatsakis (Sep 26 2019 at 14:57, on Zulip):

...it seems better if it's IPC than the set of arguments etc on a fn, but it's the same principle isn't it?

simulacrum (Sep 26 2019 at 14:57, on Zulip):

Yes, I think that's true. We can definitely do that -- I was uncertain how helpful that'd be to RLA folks though.

eddyb (Sep 26 2019 at 15:00, on Zulip):

(deleted)

eddyb (Sep 26 2019 at 15:00, on Zulip):

(deleted)

eddyb (Sep 26 2019 at 15:01, on Zulip):

(deleted)

eddyb (Sep 26 2019 at 15:03, on Zulip):

oops I failed basic reading comprehension upthread

matklad (Sep 26 2019 at 15:05, on Zulip):

I think it would be helpful yeah, for both rust-analyzer and maybe IntelliJ Rust, exactly because they explicitly track "several recent stables".

matklad (Sep 26 2019 at 15:06, on Zulip):

Specifically, this is the range of rusts that is guaranteed to work with IntelliJ: https://github.com/intellij-rust/intellij-rust/blob/06c94f051859492ceacc1e4b32a8125da112fddb/.travis.yml#L13-L15

matklad (Sep 26 2019 at 15:07, on Zulip):

(and ide authors are ok with implementing version checks on their side, so breaking iface abruptly between two versions is also ok)

matklad (Sep 26 2019 at 15:20, on Zulip):

I don't like idea of passing a map of modified files as a json flag, as it might be hard to figure out which of modified files are relevant to rustc (that is, how IDE should figured out that there's no need to pass .cpp files)?

Actually, a nice middle ground here could be to pass a list of potentially modified path prefixes. Passing / would cause rustc to query every for file, passing /path/to/my-project would cause it to ask for files in your project, but not in the crates.io. That gets rid of a nasty edge case where you have a huge number of modified files, but rustc is going to read only a dozen of them, as you probably can compress that huge number to one common prefix

Igor Matuszewski (Oct 01 2019 at 14:08, on Zulip):

@matklad I'm not sure I understand - I proposed the (made up) --modified-files JSON as an alternative to IPC-based solution

Igor Matuszewski (Oct 01 2019 at 14:10, on Zulip):

In general, the modified fileset will only be as big as the set of files you have currently modified-but-not-saved in the editor.

I don't expect it to be too big to make a difference; the only scenario I can see that is when a user treats VS Code (or any IDE) like an OS and has opened multiple workspaces at once and thus potentially also has multiple big, modified files.

Even then, I guess we could kind of only store patches, which I believe would solve the file size case but might introduce more cost/complexity at the IDE/rustc side to calculate/apply the patches

matklad (Oct 01 2019 at 15:17, on Zulip):

@Igor Matuszewski i am slightly suspicious of the assumption that "the set of modified files is small". I believe that it's true in at least 99% of cases, but it would be cool if the solution didn't fundamentally depend on this. For something like IntelliJ, the set of dirty files might be pretty large I think. But I am ready to admit that this might be over-engineering :)

To solve this "perfectly", I think we need to things:

Hence my idea about communicating the set of paths to the compiler which it might need to pull from the client.

Igor Matuszewski (Oct 01 2019 at 19:27, on Zulip):

Oh, so it's an optimization of the IPC case rather than of the "overlayfs" approach, I see

Igor Matuszewski (Oct 01 2019 at 19:28, on Zulip):

it definitely makes sense in that case

Igor Matuszewski (Oct 01 2019 at 19:28, on Zulip):

in that specific case you might as well send a list of the modified files a priori rather than a specific prefix

Igor Matuszewski (Oct 01 2019 at 19:30, on Zulip):

since sending prefix only isn't as fine-grained and if someone's concerned with the combined length of the modified files' paths then it's possible you should be concerned with different problems... :stuck_out_tongue_wink:

Igor Matuszewski (Oct 01 2019 at 19:31, on Zulip):

however that still requires agreeing to a stable-ish IPC mechanism which still requires some plumbing on the client/server side

Igor Matuszewski (Oct 01 2019 at 19:45, on Zulip):

okay this is steering into a bit of a madman territory but what if we combine both of the approaches and allow a bit of flexibility:
We could allow (in TS):

type Fileset = Array<{ file: string; contents: Contents }>;
type Contents = { kind: 'text'; value: string; } | { kind: 'command'; value: Command; } | { kind: 'diff'; value: string; };
type Command = string; // or something that denotes a spawnable command
Igor Matuszewski (Oct 01 2019 at 19:46, on Zulip):

(let's say that diff is experimental and should be left out initially)

Igor Matuszewski (Oct 01 2019 at 19:47, on Zulip):

this could support passing entire file patches or if IPC approach is desired, the LS can prepare such fileset that it leaves all of the IPC/plumbing details to that client

Igor Matuszewski (Oct 01 2019 at 19:47, on Zulip):

one implementation might be to spawn and connect to an previously prepared IPC server to serve only that file

Igor Matuszewski (Oct 01 2019 at 19:48, on Zulip):

with this the cost of implementation is relatively low on the rustc side - either read patched files or just spawn a command

Igor Matuszewski (Oct 01 2019 at 19:48, on Zulip):

and if the LS wants to do anything fancy with IPC then sure

Igor Matuszewski (Oct 01 2019 at 19:49, on Zulip):

one could imagine having an IPC-enabled VFS with immutable data structure with snapshots identifiable by IDs where you could invoke something like vfs-client <snapshot-id> <file-path>

Igor Matuszewski (Oct 01 2019 at 19:50, on Zulip):

or the server could spawn an IPC VFS instance for a specific snapshot and you would know that you need to do something like vfs-client --fd=92 <file-path>or anything similar

Igor Matuszewski (Oct 01 2019 at 19:51, on Zulip):

the only thing this would suck is when basically everything is dirty and you need to invoke a command for each of the files listed to get the contents, but that was our starting point and as you're saying we shouldn't really assume every file is dirty (and rather tell rustc upfront)

Igor Matuszewski (Oct 01 2019 at 19:51, on Zulip):

@matklad what do you think?

matklad (Oct 01 2019 at 19:56, on Zulip):

I think that, even long-term, diff is probably not a good idea. As far as I understand, there's no really a way to make two processes, to agree on the contents of file on disk, so diff solutions will inevitable be prone to "someone modifed the file in the meantime, so the diff doesn't make sence" problem.

matklad (Oct 01 2019 at 19:57, on Zulip):

At the same time, I don't think that sending the whole file over the wire is a problem: compiler does O(N) processing on it anyway.

matklad (Oct 01 2019 at 19:58, on Zulip):

Not sure about "external command / file-in-place" flexibility. I suspect that we might just start with only kind: 'text' and then figure out that its enough

Igor Matuszewski (Oct 01 2019 at 20:17, on Zulip):

well that is true, it's in fact more deterministic to send the file in a ready state or a command that's supposed to guarantee that as well

Igor Matuszewski (Oct 01 2019 at 23:29, on Zulip):

Well, do you think it's PR-worthy?

Igor Matuszewski (Oct 01 2019 at 23:30, on Zulip):

we might as well start with something :shrug:

Igor Matuszewski (Oct 01 2019 at 23:30, on Zulip):

I assume RA and intelliJ would be more interested in the VFS implementation itself rather than the "overlayfs"?

Igor Matuszewski (Oct 01 2019 at 23:30, on Zulip):

(in terms of unifying IDE work)

Last update: Nov 16 2019 at 01:05UTC