diff --git a/src/parser.zig b/src/parser.zig index 7a51ae4..d3df6f1 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -1415,11 +1415,16 @@ pub const Parser = struct { // unchanged. The legacy prefix `#foreign` form still works via the // `is_foreign` argument; interplay/diagnostics for combining them is Phase 4. var is_foreign_eff = is_foreign; - if (self.current.tag == .kw_extern) { - is_foreign_eff = true; - self.advance(); - } else if (self.current.tag == .kw_export) { - is_foreign_eff = false; + if (self.current.tag == .kw_extern or self.current.tag == .kw_export) { + // Prefix `#foreign` and the postfix `extern`/`export` keyword are two + // spellings of the same linkage axis — combining them is contradictory + // (`#foreign`=import vs `export`=define) or redundant (`#foreign … extern`). + // Reject at the postfix keyword rather than let it silently override. + if (is_foreign) { + const kw = if (self.current.tag == .kw_export) "export" else "extern"; + return self.failFmt("conflicting linkage: prefix '#foreign' cannot be combined with postfix '{s}'; use either '#foreign' or postfix 'extern'/'export', not both", .{kw}); + } + is_foreign_eff = self.current.tag == .kw_extern; self.advance(); }