Hello,
Just wondering why we can't have the same filename in two different folders. Something like this won't compile:
folder 1/file.swift
folder 2/file.swift
There was a note, Filenames are used to distinguish private declarations with the same name, but I suppose maybe it can use the relative paths to the project?
This isn't a compiler restriction and is not related to compiler features in any way, as far as I know. Would you mind filing an issue for it on this page? Issues · apple/swift-package-manager · GitHub
The main issue with ideas like "paths relative to the project" is that the compiler has no notion of a "project". It just takes a list of files from the command line and processes them, and they could be located anywhere on the filesystem. The closest thing is has is the current working directory (either inferred or passed via -working-directory). But even then, there's nothing that prevents it from accepting files that are outside of that directory.
There's probably a solution here, but it's more complex than it seems at first because it's easy to imagine situations where just moving a source file without making any other changes to its content could change a bunch of the generated symbols, which is a problem for build caching. Today, only a file's content, its basename, and the module name contribute to the names of those symbols.
Is this actually a problem? Since the filename is only used for symbols that are private to the file, it seems like the symbols changing couldn’t change the semantic result.
The semantic result isn't all that matters; build systems might see that the output has changed and perform unnecessary rebuilds of downstream dependencies. As a general principle, it's always a good idea to reduce the amount of external state that can affect the output of your build.
It really feels preposterous that this issue isn’t a higher priority. This is the kind of thing that if I knew about before I learned Swift, I would have assumed Swift was not worth learning. It ought to be embarrassing for people, but when my work is embarrassing to me I try to fix it.
I’ve made a proposal on the SPM issue that is probably really dumb, at least for the #fileID reason mentioned, and I’m more than happy to hear about why it won’t work, but the intellectual dishonesty of saying there is nothing that can be done is pretty hard to take. It seems to me that there are multiple paths to fixing this, and everyone would rather make it someone else’s problem.
The fact I've played with more than a dozen languages and build systems, with Swift being the only one I've seen with that issue so far, also adds to the feeling of dishonesty.
While I don't think this is a major issue (pretty much nothing forces you to use specific file names), I also have a minor dislike when tooling forces specific and (seemingly) arbitrary restrictions on file organization. It's the same reason I bristle when people suggest things like a folderprivate access level, because there's no such thing as a "folder" as far as the compiler is concerned.
I could imagine something like this working: a new flag like -source-root-directory and the strings used for private discrimination could be the relative paths from that root instead of just the basename. Build systems could then pass a relevant root directory that guarantees uniqueness for any source files that it can reach for a particular compilation: SwiftPM could pass the package root, Bazel could pass the workspace root, etc.
There are still some interactions I haven't thought all the way through (what would #fileID evaluate to? Build systems would still need to be able to disambiguate outputs like .o files).
That would sort of defeat one of the key features of #fileID over the old #file/#filePath, which is that it wouldn't leak details of your build machine's file system structure in the resulting binary. Not as severe as showing the full absolute path, but it could still be a security concern.
I agree that leaking absolute paths is certainly not a good idea as it can reveal critical information.
I don't see how a module-relative path could be exploited?
Maybe a flag to tune the behaviour of #fileID? That way you could choose a strategy of either (I imagine) complete secrecy, leak filenames or leak module path and you'd only "pay for what you use"?
For the mangling issue with ABI-minded libraries, wasn't there an attribute that allowed specifying the specific mangled name you wanted?
I don't entirely believe this as a "key feature". #fileID's documentation details such a potentially possible module disambiguation, so such a concern probably isn't novel and, arguably, properly resilient tooling would have taken this into account.
Regardless, I think the community/ecosystem would benefit far better from same file names - even at the small cost of breaking changes for some tooling.
Perhaps it's possible to make it a "breaking change" only if there are same-named files involved? So it won't actually break anything as the same-named file situation is currently impossible.