-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
@import is too lenient with paths on windows #9786
Comments
Yes zig is vulnerable to this type of error because of the inconsistent handling of case sensitivity between Windows filesystems and nix ones. As far as I know, Windows is the only OS that uses case insensitive file systems. I'd propose that whenever zig performs an import on Windows, it verifies that the casing used to import matches the actual casing of the filename as stored on the filesystem (not just that the file exists or can be opened, because that is case insensitive). Without this, you could have projects that compile on Windows but don't compile on linux, i.e.
main.zig: const foo = @import("Foo.zig"); This would compile on Windows but not on linux. |
I agree, though it will be important that the error message reflects this properly. Windows users may expect the file lookup to be case insensitive, and be confused by "cannot find Foo.zig" when foo.zig exists. We'll need a special case error note on windows to mention that the casing is wrong. |
How does this work the other way around? Would a project which uses multiple files which only differ in case get screwed in windows but work on linux? Granted, making several several source files which only differ in case sounds like a terrible idea anyhow, and I doubr anyone would be doing that. |
[fyi] macos APFS (and HFS+) by default are case-insensitive. Files can equally be opened in mixed case. and if anyone cares, Apple's other operating systems (iOS, iPadOS, etc) actually use case-sensitive APFS. |
Yes actually. A while back I tried cloning the linux kernel repository on windows and it had at least 1 file that only differed in casing and git wasn't able to clone it. It's actually good that git was able to detect this issue instead of just overwriting the file with the contents of one of the actual files.
@mikdusan thanks for the info |
I think this would be a good reason to have an unmatched casing error present on all operating systems. Just good QOL |
FYI you can have case folding enabled on ext4 so @fivemoreminix's proposal to just error on imports with wrong casing seems to be the solution. it would also lead to fewer permutations of source code #7399 (comment) |
If it helps, I spent some time investigating these quirks for a file synchronization program a few years ago. IIRC, Windows also has another quirk where leading spaces are truncated, so A similar kind of problem can also manifest on some macOS filesystems, which have the equivalent of Windows' case-insensitivity but for Unicode normal forms. For example, here Windows will do the right thing and be precise with a UTF-8 filename in NFC form, but then macOS will go and match this NFC form also with its own custom NFD form, so you can have multiple filenames all mapping to the same NFD form. macOS will also do normalization and lose the original NFC form when the file is written, so there's no way to go back. The mapping table for this is proprietary and slightly different to how most Unicode libraries do NFD-to-NFC-to-NFD conversions so you can't always roundtrip it. It's important to know that these quirks are not actually OS-specific, it's a little worse than that—because they're filesystem-specific. For example, macOS can work with volumes that are form-insensitive or form-sensitive. Same I believe for Windows with respect to case. It all depends on the mount point. There is hope. The best way to tackle these is always to treat filenames as data, preserve filenames, preserve case, and preserve form. Never normalize when storing data. Keep data pristine at the highest resolution possible. You can downsample only for comparison, but not for storing, because once resolution is lost, you can never upsample. Here's the full guide I wrote about this, once upon a time for Node.js: https://nodejs.org/en/docs/guides/working-with-different-filesystems/ |
Looking back to this issue, we still have to decide what we want here. a) Working on non case sensitive file systems and importing the wrong casing leads to issues for most other developers. So we want to report this as an error. My suggestion would be to enable this check by default and have a compiler option to disable it, in the rare cases, where it does not work properly. If users report issues for certain file systems we might disable the check by default if we detect it. |
I can confirm that this bug is still present in 0.12.0-dev.1327+256ab68a9 file foo.zig : const Foo = @This();
a: u8 = 1,
b: u8 = 2,
pub fn add(self: Foo) u16 {
return self.a + self.b;
} file main.zig : const std = @import("std");
const Foo = @import("foo.zig");
const FOO = @import("FOO.zig");
test {
var foo = Foo{};
std.debug.print("{d}", .{FOO.add(foo)});
}
changing the FOO import to |
Minimal reproduction: root.zig:
a.zig:
I just hit this while turning files from using global variables to being a struct type. So I was changing the filename to match, but had missed an import. One of the variables was still global, and one usage used one type, while the other usage used a different type. Eg,
A.zig
|
@scottredig I wouldn't treat that any different to e.g. the same file being hard-linked multiple times. Or even just files with duplicate content! |
When specifying @import paths with upper/lowercase errors, the build breaks in a non-obvious way.
Here is a minimal example (full source in this repository : https://github.com/cark/zig_windows_issue)
File my_type.zig (all lowercase filename):
File my_user.zig (we're importing my_type):
It looks to me like windows is being helpful in accepting the capital Z in
my_type.Zig
, but the compiler identifies the types according to the filename specified in the @import.I'm guessing the same compilation would be instantly rejected on unix systems.
You will notice that the error message is particularly unhelpful. In a larger code base, it might be a pain to pinpoint the issue.
The text was updated successfully, but these errors were encountered: