lang: reject dir-vs-file ambiguous #import
An extensionless import path that names a directory next to a same-named
.sx file ('modules/std' with both modules/std.sx and modules/std/ present)
no longer silently resolves to the directory — it errors and asks for the
explicit .sx spelling. Exemption: a file importing its own companion
directory (X.sx importing X/, the multi-file test layout) stays legal —
the sibling file is the importer itself, so the directory is the only
sensible target.
This commit is contained in:
@@ -1074,7 +1074,32 @@ pub fn resolveImports(
|
||||
try cache.put(resolved_path, result);
|
||||
break :blk result;
|
||||
} else |_| {
|
||||
// File read failed — try as directory import
|
||||
// File read failed — try as directory import. An extensionless
|
||||
// path that names a directory next to a same-named `.sx` file
|
||||
// is ambiguous: require the explicit `.sx` spelling for the
|
||||
// file rather than silently picking the directory. Exception:
|
||||
// when the sibling `.sx` is the importing file itself (a test
|
||||
// importing its own companion directory), the directory is the
|
||||
// only sensible target.
|
||||
const sibling_sx = try std.fmt.allocPrint(allocator, "{s}.sx", .{resolved_path});
|
||||
const sibling_exists = if (std.mem.eql(u8, sibling_sx, file_path))
|
||||
false
|
||||
else if (std.Io.Dir.readFileAlloc(.cwd(), io, sibling_sx, allocator, .limited(10 * 1024 * 1024))) |_|
|
||||
true
|
||||
else |_|
|
||||
false;
|
||||
if (sibling_exists) {
|
||||
const is_dir = if (std.Io.Dir.openDir(.cwd(), io, resolved_path, .{})) |d| dir_blk: {
|
||||
d.close(io);
|
||||
break :dir_blk true;
|
||||
} else |_| false;
|
||||
if (is_dir) {
|
||||
if (diagnostics) |diags| {
|
||||
diags.addFmt(.err, decl.span, "ambiguous import '{s}': both a file '{s}.sx' and a directory '{s}' exist — write \"{s}.sx\" to import the file", .{ imp.path, imp.path, imp.path, imp.path });
|
||||
}
|
||||
return error.ImportError;
|
||||
}
|
||||
}
|
||||
const result = resolveDirectoryImport(allocator, io, resolved_path, chain, cache, source_map, diagnostics, decl.span, stdlib_paths, import_graph, flat_import_graph, comptime_ctx) catch {
|
||||
if (diagnostics) |diags| {
|
||||
diags.addFmt(.err, decl.span, "cannot read import '{s}' (not a file or directory)", .{resolved_path});
|
||||
|
||||
Reference in New Issue
Block a user