Commit 7873e4f588

Andrew Kelley <andrew@ziglang.org>
2021-05-12 02:44:19
stage2: lookupIdentifier can return error.AnalysisFailed
This avoids causing false positive compile errors when, for example, a file had ZIR errors, and then code tried to look up a public decl from the failed file.
1 parent cbbc7cc
Changed files (2)
src/Module.zig
@@ -3096,7 +3096,6 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
             try mod.analyzeExport(&block_scope.base, export_src, mem.spanZ(decl.name), decl);
         }
 
-
         return type_changed;
     }
 }
@@ -3881,10 +3880,14 @@ pub fn getNextAnonNameIndex(mod: *Module) usize {
 /// This looks up a bare identifier in the given scope. This will walk up the tree of namespaces
 /// in scope and check each one for the identifier.
 /// TODO emit a compile error if more than one decl would be matched.
-pub fn lookupIdentifier(mod: *Module, scope: *Scope, ident_name: []const u8) ?*Decl {
+pub fn lookupIdentifier(
+    mod: *Module,
+    scope: *Scope,
+    ident_name: []const u8,
+) error{AnalysisFail}!?*Decl {
     var namespace = scope.namespace();
     while (true) {
-        if (mod.lookupInNamespace(namespace, ident_name, false)) |decl| {
+        if (try mod.lookupInNamespace(namespace, ident_name, false)) |decl| {
             return decl;
         }
         namespace = namespace.parent orelse break;
@@ -3899,7 +3902,12 @@ pub fn lookupInNamespace(
     namespace: *Scope.Namespace,
     ident_name: []const u8,
     only_pub_usingnamespaces: bool,
-) ?*Decl {
+) error{AnalysisFail}!?*Decl {
+    const owner_decl = namespace.getDecl();
+    if (owner_decl.analysis == .file_failure) {
+        return error.AnalysisFail;
+    }
+
     // TODO the decl doing the looking up needs to create a decl dependency
     // TODO implement usingnamespace
     if (namespace.decls.get(ident_name)) |decl| {
src/Sema.zig
@@ -2044,7 +2044,7 @@ fn zirDeclVal(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError
 
 fn lookupIdentifier(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, name: []const u8) !*Decl {
     const mod = sema.mod;
-    const decl = mod.lookupIdentifier(&sema.namespace.base, name) orelse {
+    const decl = (try mod.lookupIdentifier(&sema.namespace.base, name)) orelse {
         // TODO insert a "dependency on the non-existence of a decl" here to make this
         // compile error go away when the decl is introduced. This data should be in a global
         // sparse map since it is only relevant when a compile error occurs.
@@ -4359,7 +4359,7 @@ fn zirHasDecl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError
         "expected struct, enum, union, or opaque, found '{}'",
         .{container_type},
     );
-    if (mod.lookupInNamespace(namespace, decl_name, true)) |decl| {
+    if (try mod.lookupInNamespace(namespace, decl_name, true)) |decl| {
         if (decl.is_pub or decl.namespace.file_scope == block.base.namespace().file_scope) {
             return mod.constBool(arena, src, true);
         }
@@ -6279,7 +6279,7 @@ fn analyzeNamespaceLookup(
 ) InnerError!?*Inst {
     const mod = sema.mod;
     const gpa = sema.gpa;
-    if (mod.lookupInNamespace(namespace, decl_name, true)) |decl| {
+    if (try mod.lookupInNamespace(namespace, decl_name, true)) |decl| {
         if (!decl.is_pub and decl.namespace.file_scope != block.getFileScope()) {
             const msg = msg: {
                 const msg = try mod.errMsg(&block.base, src, "'{s}' is not marked 'pub'", .{