Implement some basic ImportRef handling for builtins. (#3663)

I'm basically just nudging down the path I think is right here. Adding a
small bit more support, but also more tests to capture cases that I
think will need to be verified as working.

With diagnostics like "Value of type `<function>` is not callable.",
that's because it expects a FunctionDecl but is instead finding a
ImportRefUsed. I'll need to work out the necessary support for a
callable function.
This commit is contained in:
Jon Ross-Perkins
2024-01-30 17:38:38 +00:00
committed by GitHub
parent 3fa70de101
commit e583493e9f
19 changed files with 398 additions and 105 deletions
+1
View File
@@ -61,6 +61,7 @@ cc_library(
"//toolchain/parse:node_kind",
"//toolchain/parse:tree",
"//toolchain/parse:tree_node_location_translator",
"//toolchain/sem_ir:builtin_kind",
"//toolchain/sem_ir:file",
"//toolchain/sem_ir:ids",
"//toolchain/sem_ir:inst",
+29 -15
View File
@@ -15,6 +15,7 @@
#include "toolchain/check/inst_block_stack.h"
#include "toolchain/lex/tokenized_buffer.h"
#include "toolchain/parse/node_kind.h"
#include "toolchain/sem_ir/builtin_kind.h"
#include "toolchain/sem_ir/file.h"
#include "toolchain/sem_ir/ids.h"
#include "toolchain/sem_ir/inst.h"
@@ -227,22 +228,35 @@ auto Context::ResolveIfImportRefUnused(SemIR::InstId inst_id) -> void {
}
const SemIR::File& import_ir = *import_irs().Get(unused_inst->ir_id);
auto import_inst = import_ir.insts().Get(unused_inst->inst_id);
switch (import_inst.kind()) {
default:
// TODO: We need more type support. For now we inject an arbitrary
// invalid node that's unrelated to the underlying value. The TODO
// diagnostic is used since this section shouldn't typically be able to
// error.
TODO(Parse::NodeId::Invalid,
(llvm::Twine("TODO: ResolveIfImportRefUnused for ") +
import_inst.kind().name())
.str());
ReplaceInstBeforeConstantUse(
inst_id,
{SemIR::ImportRefUsed{SemIR::TypeId::Error, unused_inst->ir_id,
unused_inst->inst_id}});
break;
// If the type ID isn't a normal value, forward it directly.
if (!import_inst.type_id().is_valid()) {
ReplaceInstBeforeConstantUse(
inst_id,
{SemIR::ImportRefUsed{import_inst.type_id(), unused_inst->ir_id,
unused_inst->inst_id}});
return;
}
auto import_type_inst_id = import_ir.types().GetInstId(import_inst.type_id());
CARBON_CHECK(import_type_inst_id.is_valid());
// If the type of the instruction is a builtin, use it directly.
auto type_id = SemIR::TypeId::Invalid;
if (import_type_inst_id.is_builtin()) {
type_id = GetBuiltinType(import_type_inst_id.builtin_kind());
} else {
// TODO: This section probably needs to TryEvalInst for the type. Similar to
// GetTypeImpl, but in the context of import_ir.
TODO(Parse::NodeId::Invalid,
"TODO: ResolveIfImportRefUnused for non-builtin type");
type_id = SemIR::TypeId::Error;
}
// TODO: Add breadcrumbs for lowering.
ReplaceInstBeforeConstantUse(
inst_id, {SemIR::ImportRefUsed{type_id, unused_inst->ir_id,
unused_inst->inst_id}});
}
auto Context::LookupNameInDecl(Parse::NodeId /*parse_node*/,
+12 -8
View File
@@ -3,8 +3,6 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// CHECK:STDERR: b.carbon: ERROR: Semantics TODO: `TODO: ResolveIfImportRefUnused for ClassDecl`.
// CHECK:STDERR: b.carbon: ERROR: Semantics TODO: `TODO: ResolveIfImportRefUnused for ClassDecl`.
// --- a.carbon
@@ -26,7 +24,13 @@ library "b" api;
import library "a";
fn Run() {
// CHECK:STDERR: b.carbon:[[@LINE+3]]:10: ERROR: Expression cannot be used as a value.
// CHECK:STDERR: var x: Empty = {};
// CHECK:STDERR: ^~~~~
var x: Empty = {};
// CHECK:STDERR: b.carbon:[[@LINE+3]]:10: ERROR: Expression cannot be used as a value.
// CHECK:STDERR: var y: ForwardDeclared = {};
// CHECK:STDERR: ^~~~~~~~~~~~~~~
var y: ForwardDeclared = {};
y.F();
}
@@ -68,22 +72,22 @@ fn Run() {
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.Empty = %import_ref.1, .ForwardDeclared = %import_ref.2, .Run = %Run} [template]
// CHECK:STDOUT: %import_ref.1: <error> = import_ref ir1, inst+1, used
// CHECK:STDOUT: %import_ref.2: <error> = import_ref ir1, inst+4, used
// CHECK:STDOUT: %import_ref.1: invalid = import_ref ir1, inst+1, used
// CHECK:STDOUT: %import_ref.2: invalid = import_ref ir1, inst+4, used
// CHECK:STDOUT: %Run: <function> = fn_decl @Run [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Run() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Empty.ref: <error> = name_ref Empty, file.%import_ref.1
// CHECK:STDOUT: %Empty.ref: invalid = name_ref Empty, file.%import_ref.1
// CHECK:STDOUT: %x.var: ref <error> = var x
// CHECK:STDOUT: %x: ref <error> = bind_name x, %x.var
// CHECK:STDOUT: %.loc7: {} = struct_literal ()
// CHECK:STDOUT: %.loc10: {} = struct_literal ()
// CHECK:STDOUT: assign %x.var, <error>
// CHECK:STDOUT: %ForwardDeclared.ref: <error> = name_ref ForwardDeclared, file.%import_ref.2
// CHECK:STDOUT: %ForwardDeclared.ref: invalid = name_ref ForwardDeclared, file.%import_ref.2
// CHECK:STDOUT: %y.var: ref <error> = var y
// CHECK:STDOUT: %y: ref <error> = bind_name y, %y.var
// CHECK:STDOUT: %.loc8: {} = struct_literal ()
// CHECK:STDOUT: %.loc14: {} = struct_literal ()
// CHECK:STDOUT: assign %y.var, <error>
// CHECK:STDOUT: %y.ref: ref <error> = name_ref y, %y
// CHECK:STDOUT: return
+60
View File
@@ -0,0 +1,60 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// When there are no more cases that can hit a TODO, remove this test. Until
// then, update it whenever its target is implemented.
//
// AUTOUPDATE
// CHECK:STDERR: implicit.impl.carbon: ERROR: Semantics TODO: `TODO: ResolveIfImportRefUnused for non-builtin type`.
// --- implicit.carbon
package Implicit api;
fn F() -> const i32;
var a_ref: const i32 = F();
// --- implicit.impl.carbon
package Implicit impl;
var a: const i32 = a_ref;
// CHECK:STDOUT: --- implicit.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = const_type i32 [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.F = %F, .a_ref = %a_ref} [template]
// CHECK:STDOUT: %F: <function> = fn_decl @F [template]
// CHECK:STDOUT: %.loc6_12: type = const_type i32 [template = constants.%.1]
// CHECK:STDOUT: %a_ref.var: ref const i32 = var a_ref
// CHECK:STDOUT: %a_ref: ref const i32 = bind_name a_ref, %a_ref.var
// CHECK:STDOUT: %F.ref: <function> = name_ref F, %F [template = %F]
// CHECK:STDOUT: %.loc6_25: init const i32 = call %F.ref()
// CHECK:STDOUT: assign %a_ref.var, %.loc6_25
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F() -> const i32;
// CHECK:STDOUT:
// CHECK:STDOUT: --- implicit.impl.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = const_type i32 [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.F = %import_ref.1, .a_ref = %import_ref.2, .a = %a} [template]
// CHECK:STDOUT: %import_ref.1 = import_ref ir1, inst+4, unused
// CHECK:STDOUT: %import_ref.2: ref <error> = import_ref ir1, inst+7, used
// CHECK:STDOUT: %.loc4: type = const_type i32 [template = constants.%.1]
// CHECK:STDOUT: %a.var: ref const i32 = var a
// CHECK:STDOUT: %a: ref const i32 = bind_name a, %a.var
// CHECK:STDOUT: %a_ref.ref: ref <error> = name_ref a_ref, %import_ref.2
// CHECK:STDOUT: assign %a.var, <error>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -3,7 +3,6 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// CHECK:STDERR: b.carbon: ERROR: Semantics TODO: `TODO: ResolveIfImportRefUnused for FunctionDecl`.
// --- a.carbon
@@ -18,6 +17,9 @@ library "b" api;
import library "a";
fn Run() {
// CHECK:STDERR: b.carbon:[[@LINE+3]]:3: ERROR: Value of type `<function>` is not callable.
// CHECK:STDERR: F();
// CHECK:STDERR: ^~
F();
}
@@ -34,13 +36,13 @@ fn Run() {
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.F = %import_ref, .Run = %Run} [template]
// CHECK:STDOUT: %import_ref: <error> = import_ref ir1, inst+1, used
// CHECK:STDOUT: %import_ref: <function> = import_ref ir1, inst+1, used
// CHECK:STDOUT: %Run: <function> = fn_decl @Run [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Run() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %F.ref: <error> = name_ref F, file.%import_ref
// CHECK:STDOUT: %F.ref: <function> = name_ref F, file.%import_ref
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -3,7 +3,6 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// CHECK:STDERR: b.carbon: ERROR: Semantics TODO: `TODO: ResolveIfImportRefUnused for FunctionDecl`.
// --- a.carbon
@@ -18,6 +17,9 @@ library "b" api;
import library "a";
fn Run() {
// CHECK:STDERR: b.carbon:[[@LINE+3]]:3: ERROR: Value of type `<function>` is not callable.
// CHECK:STDERR: F();
// CHECK:STDERR: ^~
F();
}
@@ -37,13 +39,13 @@ fn Run() {
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.F = %import_ref, .Run = %Run} [template]
// CHECK:STDOUT: %import_ref: <error> = import_ref ir1, inst+1, used
// CHECK:STDOUT: %import_ref: <function> = import_ref ir1, inst+1, used
// CHECK:STDOUT: %Run: <function> = fn_decl @Run [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Run() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %F.ref: <error> = name_ref F, file.%import_ref
// CHECK:STDOUT: %F.ref: <function> = name_ref F, file.%import_ref
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -3,7 +3,6 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// CHECK:STDERR: conflict.carbon: ERROR: Semantics TODO: `TODO: ResolveIfImportRefUnused for FunctionDecl`.
// --- fn.carbon
@@ -46,7 +45,7 @@ fn NS.Foo();
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.NS = %import_ref} [template]
// CHECK:STDOUT: %import_ref: <error> = import_ref ir1, inst+1, used
// CHECK:STDOUT: %import_ref: <function> = import_ref ir1, inst+1, used
// CHECK:STDOUT: %.loc12: <namespace> = namespace {} [template]
// CHECK:STDOUT: %.loc20: <function> = fn_decl @.1 [template]
// CHECK:STDOUT: }
+34 -24
View File
@@ -3,8 +3,6 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// CHECK:STDERR: implicit.impl.carbon: ERROR: Semantics TODO: `TODO: ResolveIfImportRefUnused for FunctionDecl`.
// CHECK:STDERR: implicit.impl.carbon: ERROR: Semantics TODO: `TODO: ResolveIfImportRefUnused for FunctionDecl`.
// --- implicit.carbon
@@ -20,10 +18,22 @@ fn NS.ChildNS.B();
package Implicit impl;
// CHECK:STDERR: implicit.impl.carbon:[[@LINE+3]]:13: ERROR: Value of type `<function>` is not callable.
// CHECK:STDERR: var a: () = NS.A();
// CHECK:STDERR: ^~~~~
var a: () = NS.A();
// CHECK:STDERR: implicit.impl.carbon:[[@LINE+3]]:13: ERROR: Value of type `<function>` is not callable.
// CHECK:STDERR: var b: () = NS.ChildNS.B();
// CHECK:STDERR: ^~~~~~~~~~~~~
var b: () = NS.ChildNS.B();
// CHECK:STDERR: implicit.impl.carbon:[[@LINE+3]]:21: ERROR: Value of type `<function>` is not callable.
// CHECK:STDERR: var package_a: () = package.NS.A();
// CHECK:STDERR: ^~~~~~~~~~~~~
var package_a: () = package.NS.A();
// CHECK:STDERR: implicit.impl.carbon:[[@LINE+3]]:21: ERROR: Value of type `<function>` is not callable.
// CHECK:STDERR: var package_b: () = package.NS.ChildNS.B();
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~
var package_b: () = package.NS.ChildNS.B();
// CHECK:STDOUT: --- implicit.carbon
@@ -52,39 +62,39 @@ var package_b: () = package.NS.ChildNS.B();
// CHECK:STDOUT: %.2: <namespace> = namespace {.ChildNS = %.3, .A = %import_ref.3}, %import_ref.1 [template]
// CHECK:STDOUT: %import_ref.2: <namespace> = import_ref ir1, inst+2, used
// CHECK:STDOUT: %.3: <namespace> = namespace {.B = %import_ref.4}, %import_ref.2 [template]
// CHECK:STDOUT: %import_ref.3: <error> = import_ref ir1, inst+3, used
// CHECK:STDOUT: %import_ref.4: <error> = import_ref ir1, inst+4, used
// CHECK:STDOUT: %.loc4_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc4_9.2: type = converted %.loc4_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %import_ref.3: <function> = import_ref ir1, inst+3, used
// CHECK:STDOUT: %import_ref.4: <function> = import_ref ir1, inst+4, used
// CHECK:STDOUT: %.loc7_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc7_9.2: type = converted %.loc7_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %a.var: ref () = var a
// CHECK:STDOUT: %a: ref () = bind_name a, %a.var
// CHECK:STDOUT: %NS.ref.loc4: <namespace> = name_ref NS, %.2 [template = %.2]
// CHECK:STDOUT: %A.ref.loc4: <error> = name_ref A, %import_ref.3
// CHECK:STDOUT: %NS.ref.loc7: <namespace> = name_ref NS, %.2 [template = %.2]
// CHECK:STDOUT: %A.ref.loc7: <function> = name_ref A, %import_ref.3
// CHECK:STDOUT: assign %a.var, <error>
// CHECK:STDOUT: %.loc5_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc5_9.2: type = converted %.loc5_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %.loc11_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc11_9.2: type = converted %.loc11_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %b.var: ref () = var b
// CHECK:STDOUT: %b: ref () = bind_name b, %b.var
// CHECK:STDOUT: %NS.ref.loc5: <namespace> = name_ref NS, %.2 [template = %.2]
// CHECK:STDOUT: %ChildNS.ref.loc5: <namespace> = name_ref ChildNS, %.3 [template = %.3]
// CHECK:STDOUT: %B.ref.loc5: <error> = name_ref B, %import_ref.4
// CHECK:STDOUT: %NS.ref.loc11: <namespace> = name_ref NS, %.2 [template = %.2]
// CHECK:STDOUT: %ChildNS.ref.loc11: <namespace> = name_ref ChildNS, %.3 [template = %.3]
// CHECK:STDOUT: %B.ref.loc11: <function> = name_ref B, %import_ref.4
// CHECK:STDOUT: assign %b.var, <error>
// CHECK:STDOUT: %.loc7_17.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc7_17.2: type = converted %.loc7_17.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %.loc16_17.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc16_17.2: type = converted %.loc16_17.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %package_a.var: ref () = var package_a
// CHECK:STDOUT: %package_a: ref () = bind_name package_a, %package_a.var
// CHECK:STDOUT: %package.ref.loc7: <namespace> = name_ref package, package [template = package]
// CHECK:STDOUT: %NS.ref.loc7: <namespace> = name_ref NS, %.2 [template = %.2]
// CHECK:STDOUT: %A.ref.loc7: <error> = name_ref A, %import_ref.3
// CHECK:STDOUT: %package.ref.loc16: <namespace> = name_ref package, package [template = package]
// CHECK:STDOUT: %NS.ref.loc16: <namespace> = name_ref NS, %.2 [template = %.2]
// CHECK:STDOUT: %A.ref.loc16: <function> = name_ref A, %import_ref.3
// CHECK:STDOUT: assign %package_a.var, <error>
// CHECK:STDOUT: %.loc8_17.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc8_17.2: type = converted %.loc8_17.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %.loc20_17.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc20_17.2: type = converted %.loc20_17.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %package_b.var: ref () = var package_b
// CHECK:STDOUT: %package_b: ref () = bind_name package_b, %package_b.var
// CHECK:STDOUT: %package.ref.loc8: <namespace> = name_ref package, package [template = package]
// CHECK:STDOUT: %NS.ref.loc8: <namespace> = name_ref NS, %.2 [template = %.2]
// CHECK:STDOUT: %ChildNS.ref.loc8: <namespace> = name_ref ChildNS, %.3 [template = %.3]
// CHECK:STDOUT: %B.ref.loc8: <error> = name_ref B, %import_ref.4
// CHECK:STDOUT: %package.ref.loc20: <namespace> = name_ref package, package [template = package]
// CHECK:STDOUT: %NS.ref.loc20: <namespace> = name_ref NS, %.2 [template = %.2]
// CHECK:STDOUT: %ChildNS.ref.loc20: <namespace> = name_ref ChildNS, %.3 [template = %.3]
// CHECK:STDOUT: %B.ref.loc20: <function> = name_ref B, %import_ref.4
// CHECK:STDOUT: assign %package_b.var, <error>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -3,7 +3,6 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// CHECK:STDERR: e.carbon: ERROR: Semantics TODO: `TODO: ResolveIfImportRefUnused for FunctionDecl`.
// --- a.carbon
@@ -37,6 +36,9 @@ fn A.B.C.D() {};
package Same library "e" api;
import library "d";
// CHECK:STDERR: e.carbon:[[@LINE+3]]:13: ERROR: Value of type `<function>` is not callable.
// CHECK:STDERR: var e: () = A.B.C.D();
// CHECK:STDERR: ^~~~~~~~
var e: () = A.B.C.D();
// CHECK:STDOUT: --- a.carbon
@@ -98,15 +100,15 @@ var e: () = A.B.C.D();
// CHECK:STDOUT: %.3: <namespace> = namespace {.C = %.4}, %import_ref.2 [template]
// CHECK:STDOUT: %import_ref.3: <namespace> = import_ref ir1, inst+6, used
// CHECK:STDOUT: %.4: <namespace> = namespace {.D = %import_ref.4}, %import_ref.3 [template]
// CHECK:STDOUT: %import_ref.4: <error> = import_ref ir1, inst+7, used
// CHECK:STDOUT: %.loc5_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc5_9.2: type = converted %.loc5_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %import_ref.4: <function> = import_ref ir1, inst+7, used
// CHECK:STDOUT: %.loc8_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc8_9.2: type = converted %.loc8_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %e.var: ref () = var e
// CHECK:STDOUT: %e: ref () = bind_name e, %e.var
// CHECK:STDOUT: %A.ref: <namespace> = name_ref A, %.2 [template = %.2]
// CHECK:STDOUT: %B.ref: <namespace> = name_ref B, %.3 [template = %.3]
// CHECK:STDOUT: %C.ref: <namespace> = name_ref C, %.4 [template = %.4]
// CHECK:STDOUT: %D.ref: <error> = name_ref D, %import_ref.4
// CHECK:STDOUT: %D.ref: <function> = name_ref D, %import_ref.4
// CHECK:STDOUT: assign %e.var, <error>
// CHECK:STDOUT: }
// CHECK:STDOUT:
+19 -13
View File
@@ -3,9 +3,6 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// CHECK:STDERR: c.carbon: ERROR: Semantics TODO: `TODO: ResolveIfImportRefUnused for FunctionDecl`.
// CHECK:STDERR: c.carbon: ERROR: Semantics TODO: `TODO: ResolveIfImportRefUnused for FunctionDecl`.
// CHECK:STDERR: c.carbon: ERROR: Semantics TODO: `TODO: ResolveIfImportRefUnused for FunctionDecl`.
// --- a.carbon
@@ -39,8 +36,17 @@ namespace NS;
fn NS.C() {}
fn Run() {
// CHECK:STDERR: c.carbon:[[@LINE+3]]:3: ERROR: Value of type `<function>` is not callable.
// CHECK:STDERR: NS.A();
// CHECK:STDERR: ^~~~~
NS.A();
// CHECK:STDERR: c.carbon:[[@LINE+3]]:3: ERROR: Value of type `<function>` is not callable.
// CHECK:STDERR: NS.B1();
// CHECK:STDERR: ^~~~~~
NS.B1();
// CHECK:STDERR: c.carbon:[[@LINE+3]]:3: ERROR: Value of type `<function>` is not callable.
// CHECK:STDERR: NS.B2();
// CHECK:STDERR: ^~~~~~
NS.B2();
NS.C();
}
@@ -88,9 +94,9 @@ fn Run() {
// CHECK:STDOUT: package: <namespace> = namespace {.NS = %.loc7_13.1, .Run = %Run} [template]
// CHECK:STDOUT: %import_ref.1: <namespace> = import_ref ir1, inst+1, used
// CHECK:STDOUT: %.loc7_13.1: <namespace> = namespace {.A = %import_ref.2, .B1 = %import_ref.3, .B2 = %import_ref.4, .C = %C}, %import_ref.1 [template]
// CHECK:STDOUT: %import_ref.2: <error> = import_ref ir1, inst+2, used
// CHECK:STDOUT: %import_ref.3: <error> = import_ref ir2, inst+2, used
// CHECK:STDOUT: %import_ref.4: <error> = import_ref ir2, inst+5, used
// CHECK:STDOUT: %import_ref.2: <function> = import_ref ir1, inst+2, used
// CHECK:STDOUT: %import_ref.3: <function> = import_ref ir2, inst+2, used
// CHECK:STDOUT: %import_ref.4: <function> = import_ref ir2, inst+5, used
// CHECK:STDOUT: %.loc7_13.2: <namespace> = namespace {} [template]
// CHECK:STDOUT: %C: <function> = fn_decl @C [template]
// CHECK:STDOUT: %Run: <function> = fn_decl @Run [template]
@@ -103,15 +109,15 @@ fn Run() {
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Run() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %NS.ref.loc12: <namespace> = name_ref NS, file.%.loc7_13.1 [template = file.%.loc7_13.1]
// CHECK:STDOUT: %A.ref: <error> = name_ref A, file.%import_ref.2
// CHECK:STDOUT: %NS.ref.loc13: <namespace> = name_ref NS, file.%.loc7_13.1 [template = file.%.loc7_13.1]
// CHECK:STDOUT: %B1.ref: <error> = name_ref B1, file.%import_ref.3
// CHECK:STDOUT: %NS.ref.loc14: <namespace> = name_ref NS, file.%.loc7_13.1 [template = file.%.loc7_13.1]
// CHECK:STDOUT: %B2.ref: <error> = name_ref B2, file.%import_ref.4
// CHECK:STDOUT: %NS.ref.loc15: <namespace> = name_ref NS, file.%.loc7_13.1 [template = file.%.loc7_13.1]
// CHECK:STDOUT: %A.ref: <function> = name_ref A, file.%import_ref.2
// CHECK:STDOUT: %NS.ref.loc19: <namespace> = name_ref NS, file.%.loc7_13.1 [template = file.%.loc7_13.1]
// CHECK:STDOUT: %B1.ref: <function> = name_ref B1, file.%import_ref.3
// CHECK:STDOUT: %NS.ref.loc23: <namespace> = name_ref NS, file.%.loc7_13.1 [template = file.%.loc7_13.1]
// CHECK:STDOUT: %B2.ref: <function> = name_ref B2, file.%import_ref.4
// CHECK:STDOUT: %NS.ref.loc24: <namespace> = name_ref NS, file.%.loc7_13.1 [template = file.%.loc7_13.1]
// CHECK:STDOUT: %C.ref: <function> = name_ref C, file.%C [template = file.%C]
// CHECK:STDOUT: %.loc15: init () = call %C.ref()
// CHECK:STDOUT: %.loc24: init () = call %C.ref()
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -3,8 +3,6 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// CHECK:STDERR: implicit.impl.carbon: ERROR: Semantics TODO: `TODO: ResolveIfImportRefUnused for FunctionDecl`.
// CHECK:STDERR: same_package_importer.carbon: ERROR: Semantics TODO: `TODO: ResolveIfImportRefUnused for FunctionDecl`.
// --- implicit.carbon
@@ -16,8 +14,14 @@ fn A();
package Implicit impl;
// CHECK:STDERR: implicit.impl.carbon:[[@LINE+3]]:13: ERROR: Value of type `<function>` is not callable.
// CHECK:STDERR: var a: () = A();
// CHECK:STDERR: ^~
var a: () = A();
// CHECK:STDERR: implicit.impl.carbon:[[@LINE+3]]:21: ERROR: Value of type `<function>` is not callable.
// CHECK:STDERR: var package_a: () = package.A();
// CHECK:STDERR: ^~~~~~~~~~
var package_a: () = package.A();
// --- same_package.carbon
@@ -32,8 +36,14 @@ package SamePackage library "importer" api;
import library default;
// CHECK:STDERR: same_package_importer.carbon:[[@LINE+3]]:13: ERROR: Value of type `<function>` is not callable.
// CHECK:STDERR: var b: () = B();
// CHECK:STDERR: ^~
var b: () = B();
// CHECK:STDERR: same_package_importer.carbon:[[@LINE+3]]:21: ERROR: Value of type `<function>` is not callable.
// CHECK:STDERR: var package_b: () = package.B();
// CHECK:STDERR: ^~~~~~~~~~
var package_b: () = package.B();
// CHECK:STDOUT: --- implicit.carbon
@@ -53,19 +63,19 @@ var package_b: () = package.B();
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.A = %import_ref, .a = %a, .package_a = %package_a} [template]
// CHECK:STDOUT: %import_ref: <error> = import_ref ir1, inst+1, used
// CHECK:STDOUT: %.loc4_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc4_9.2: type = converted %.loc4_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %import_ref: <function> = import_ref ir1, inst+1, used
// CHECK:STDOUT: %.loc7_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc7_9.2: type = converted %.loc7_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %a.var: ref () = var a
// CHECK:STDOUT: %a: ref () = bind_name a, %a.var
// CHECK:STDOUT: %A.ref.loc4: <error> = name_ref A, %import_ref
// CHECK:STDOUT: %A.ref.loc7: <function> = name_ref A, %import_ref
// CHECK:STDOUT: assign %a.var, <error>
// CHECK:STDOUT: %.loc6_17.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc6_17.2: type = converted %.loc6_17.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %.loc12_17.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc12_17.2: type = converted %.loc12_17.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %package_a.var: ref () = var package_a
// CHECK:STDOUT: %package_a: ref () = bind_name package_a, %package_a.var
// CHECK:STDOUT: %package.ref: <namespace> = name_ref package, package [template = package]
// CHECK:STDOUT: %A.ref.loc6: <error> = name_ref A, %import_ref
// CHECK:STDOUT: %A.ref.loc12: <function> = name_ref A, %import_ref
// CHECK:STDOUT: assign %package_a.var, <error>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -86,19 +96,19 @@ var package_b: () = package.B();
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.B = %import_ref, .b = %b, .package_b = %package_b} [template]
// CHECK:STDOUT: %import_ref: <error> = import_ref ir1, inst+1, used
// CHECK:STDOUT: %.loc6_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc6_9.2: type = converted %.loc6_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %import_ref: <function> = import_ref ir1, inst+1, used
// CHECK:STDOUT: %.loc9_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc9_9.2: type = converted %.loc9_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %b.var: ref () = var b
// CHECK:STDOUT: %b: ref () = bind_name b, %b.var
// CHECK:STDOUT: %B.ref.loc6: <error> = name_ref B, %import_ref
// CHECK:STDOUT: %B.ref.loc9: <function> = name_ref B, %import_ref
// CHECK:STDOUT: assign %b.var, <error>
// CHECK:STDOUT: %.loc8_17.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc8_17.2: type = converted %.loc8_17.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %.loc14_17.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc14_17.2: type = converted %.loc14_17.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %package_b.var: ref () = var package_b
// CHECK:STDOUT: %package_b: ref () = bind_name package_b, %package_b.var
// CHECK:STDOUT: %package.ref: <namespace> = name_ref package, package [template = package]
// CHECK:STDOUT: %B.ref.loc8: <error> = name_ref B, %import_ref
// CHECK:STDOUT: %B.ref.loc14: <function> = name_ref B, %import_ref
// CHECK:STDOUT: assign %package_b.var, <error>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -0,0 +1,61 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// When there are no more cases that can hit a TODO, remove this test. Until
// then, update it whenever its target is implemented.
//
// AUTOUPDATE
// CHECK:STDERR: implicit.impl.carbon: ERROR: Semantics TODO: `TODO: ResolveIfImportRefUnused for non-builtin type`.
// --- implicit.carbon
package Implicit api;
var a_orig: i32 = 0;
var a_ref: i32* = &a_orig;
// --- implicit.impl.carbon
package Implicit impl;
var a: i32* = a_ref;
// CHECK:STDOUT: --- implicit.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: i32 = int_literal 0 [template]
// CHECK:STDOUT: %.2: type = ptr_type i32 [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.a_orig = %a_orig, .a_ref = %a_ref} [template]
// CHECK:STDOUT: %a_orig.var: ref i32 = var a_orig
// CHECK:STDOUT: %a_orig: ref i32 = bind_name a_orig, %a_orig.var
// CHECK:STDOUT: %.loc4: i32 = int_literal 0 [template = constants.%.1]
// CHECK:STDOUT: assign %a_orig.var, %.loc4
// CHECK:STDOUT: %.loc5_15: type = ptr_type i32 [template = constants.%.2]
// CHECK:STDOUT: %a_ref.var: ref i32* = var a_ref
// CHECK:STDOUT: %a_ref: ref i32* = bind_name a_ref, %a_ref.var
// CHECK:STDOUT: %a_orig.ref: ref i32 = name_ref a_orig, %a_orig
// CHECK:STDOUT: %.loc5_19: i32* = addr_of %a_orig.ref
// CHECK:STDOUT: assign %a_ref.var, %.loc5_19
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- implicit.impl.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = ptr_type i32 [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.a_orig = %import_ref.1, .a_ref = %import_ref.2, .a = %a} [template]
// CHECK:STDOUT: %import_ref.1 = import_ref ir1, inst+2, unused
// CHECK:STDOUT: %import_ref.2: ref <error> = import_ref ir1, inst+9, used
// CHECK:STDOUT: %.loc4: type = ptr_type i32 [template = constants.%.1]
// CHECK:STDOUT: %a.var: ref i32* = var a
// CHECK:STDOUT: %a: ref i32* = bind_name a, %a.var
// CHECK:STDOUT: %a_ref.ref: ref <error> = name_ref a_ref, %import_ref.2
// CHECK:STDOUT: assign %a.var, <error>
// CHECK:STDOUT: }
// CHECK:STDOUT:
+58
View File
@@ -0,0 +1,58 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// When there are no more cases that can hit a TODO, remove this test. Until
// then, update it whenever its target is implemented.
//
// AUTOUPDATE
// CHECK:STDERR: implicit.impl.carbon: ERROR: Semantics TODO: `TODO: ResolveIfImportRefUnused for non-builtin type`.
// --- implicit.carbon
package Implicit api;
var a_ref: {.a: i32} = {.a = 0};
// --- implicit.impl.carbon
package Implicit impl;
var a: {.a: i32} = a_ref;
// CHECK:STDOUT: --- implicit.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = struct_type {.a: i32} [template]
// CHECK:STDOUT: %.2: i32 = int_literal 0 [template]
// CHECK:STDOUT: %.3: {.a: i32} = struct_value (%.2) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.a_ref = %a_ref} [template]
// CHECK:STDOUT: %.loc4_20: type = struct_type {.a: i32} [template = constants.%.1]
// CHECK:STDOUT: %a_ref.var: ref {.a: i32} = var a_ref
// CHECK:STDOUT: %a_ref: ref {.a: i32} = bind_name a_ref, %a_ref.var
// CHECK:STDOUT: %.loc4_30: i32 = int_literal 0 [template = constants.%.2]
// CHECK:STDOUT: %.loc4_31.1: {.a: i32} = struct_literal (%.loc4_30)
// CHECK:STDOUT: %.loc4_31.2: init {.a: i32} = struct_init (%.loc4_30) to %a_ref.var [template = constants.%.3]
// CHECK:STDOUT: %.loc4_31.3: init {.a: i32} = converted %.loc4_31.1, %.loc4_31.2 [template = constants.%.3]
// CHECK:STDOUT: assign %a_ref.var, %.loc4_31.3
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- implicit.impl.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = struct_type {.a: i32} [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.a_ref = %import_ref, .a = %a} [template]
// CHECK:STDOUT: %import_ref: ref <error> = import_ref ir1, inst+6, used
// CHECK:STDOUT: %.loc4: type = struct_type {.a: i32} [template = constants.%.1]
// CHECK:STDOUT: %a.var: ref {.a: i32} = var a
// CHECK:STDOUT: %a: ref {.a: i32} = bind_name a, %a.var
// CHECK:STDOUT: %a_ref.ref: ref <error> = name_ref a_ref, %import_ref
// CHECK:STDOUT: assign %a.var, <error>
// CHECK:STDOUT: }
// CHECK:STDOUT:
+62
View File
@@ -0,0 +1,62 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// When there are no more cases that can hit a TODO, remove this test. Until
// then, update it whenever its target is implemented.
//
// AUTOUPDATE
// CHECK:STDERR: implicit.impl.carbon: ERROR: Semantics TODO: `TODO: ResolveIfImportRefUnused for non-builtin type`.
// --- implicit.carbon
package Implicit api;
var a_ref: (i32,) = (0,);
// --- implicit.impl.carbon
package Implicit impl;
var a: (i32,) = a_ref;
// CHECK:STDOUT: --- implicit.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type (type) [template]
// CHECK:STDOUT: %.2: type = tuple_type (i32) [template]
// CHECK:STDOUT: %.3: i32 = int_literal 0 [template]
// CHECK:STDOUT: %.4: (i32,) = tuple_value (%.3) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.a_ref = %a_ref} [template]
// CHECK:STDOUT: %.loc4_17.1: (type,) = tuple_literal (i32)
// CHECK:STDOUT: %.loc4_17.2: type = converted %.loc4_17.1, constants.%.2 [template = constants.%.2]
// CHECK:STDOUT: %a_ref.var: ref (i32,) = var a_ref
// CHECK:STDOUT: %a_ref: ref (i32,) = bind_name a_ref, %a_ref.var
// CHECK:STDOUT: %.loc4_22: i32 = int_literal 0 [template = constants.%.3]
// CHECK:STDOUT: %.loc4_24.1: (i32,) = tuple_literal (%.loc4_22)
// CHECK:STDOUT: %.loc4_24.2: init (i32,) = tuple_init (%.loc4_22) to %a_ref.var [template = constants.%.4]
// CHECK:STDOUT: %.loc4_24.3: init (i32,) = converted %.loc4_24.1, %.loc4_24.2 [template = constants.%.4]
// CHECK:STDOUT: assign %a_ref.var, %.loc4_24.3
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- implicit.impl.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type (type) [template]
// CHECK:STDOUT: %.2: type = tuple_type (i32) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.a_ref = %import_ref, .a = %a} [template]
// CHECK:STDOUT: %import_ref: ref <error> = import_ref ir1, inst+6, used
// CHECK:STDOUT: %.loc4_13.1: (type,) = tuple_literal (i32)
// CHECK:STDOUT: %.loc4_13.2: type = converted %.loc4_13.1, constants.%.2 [template = constants.%.2]
// CHECK:STDOUT: %a.var: ref (i32,) = var a
// CHECK:STDOUT: %a: ref (i32,) = bind_name a, %a.var
// CHECK:STDOUT: %a_ref.ref: ref <error> = name_ref a_ref, %import_ref
// CHECK:STDOUT: assign %a.var, <error>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -6,7 +6,6 @@
// then, update it whenever its target is implemented.
//
// AUTOUPDATE
// CHECK:STDERR: implicit.impl.carbon: ERROR: Semantics TODO: `TODO: ResolveIfImportRefUnused for BindName`.
// --- implicit.carbon
@@ -18,7 +17,7 @@ var a_ref: i32 = 0;
package Implicit impl;
var a: () = a_ref;
var a: i32 = a_ref;
// CHECK:STDOUT: --- implicit.carbon
// CHECK:STDOUT:
@@ -36,18 +35,13 @@ var a: () = a_ref;
// CHECK:STDOUT:
// CHECK:STDOUT: --- implicit.impl.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.a_ref = %import_ref, .a = %a} [template]
// CHECK:STDOUT: %import_ref: ref <error> = import_ref ir1, inst+2, used
// CHECK:STDOUT: %.loc4_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc4_9.2: type = converted %.loc4_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %a.var: ref () = var a
// CHECK:STDOUT: %a: ref () = bind_name a, %a.var
// CHECK:STDOUT: %a_ref.ref: ref <error> = name_ref a_ref, %import_ref
// CHECK:STDOUT: assign %a.var, <error>
// CHECK:STDOUT: %import_ref: ref i32 = import_ref ir1, inst+2, used
// CHECK:STDOUT: %a.var: ref i32 = var a
// CHECK:STDOUT: %a: ref i32 = bind_name a, %a.var
// CHECK:STDOUT: %a_ref.ref: ref i32 = name_ref a_ref, %import_ref
// CHECK:STDOUT: %.loc4: i32 = bind_value %a_ref.ref
// CHECK:STDOUT: assign %a.var, %.loc4
// CHECK:STDOUT: }
// CHECK:STDOUT:
+1
View File
@@ -94,6 +94,7 @@ cc_library(
":file",
":ids",
":inst_kind",
"//common:ostream",
"//toolchain/base:value_store",
"//toolchain/lex:tokenized_buffer",
"//toolchain/parse:tree",
+1 -1
View File
@@ -296,7 +296,7 @@ auto File::StringifyTypeExpr(InstId outer_inst_id) const -> std::string {
// Builtins have designated labels.
if (step.inst_id.is_builtin()) {
out << BuiltinKind::FromInt(step.inst_id.index).label();
out << step.inst_id.builtin_kind().label();
continue;
}
+2 -1
View File
@@ -4,6 +4,7 @@
#include "toolchain/sem_ir/formatter.h"
#include "common/ostream.h"
#include "llvm/ADT/Sequence.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
@@ -170,7 +171,7 @@ class InstNamer {
// Check for a builtin.
if (inst_id.is_builtin()) {
return BuiltinKind::FromInt(inst_id.index).label().str();
return inst_id.builtin_kind().label().str();
}
if (inst_id == InstId::PackageNamespace) {
+7 -1
View File
@@ -51,12 +51,18 @@ struct InstId : public IdBase, public Printable<InstId> {
return index < BuiltinKind::ValidCount;
}
// Returns the BuiltinKind. Requires is_builtin.
auto builtin_kind() const -> BuiltinKind {
CARBON_CHECK(is_builtin());
return BuiltinKind::FromInt(index);
}
auto Print(llvm::raw_ostream& out) const -> void {
out << "inst";
if (!is_valid()) {
IdBase::Print(out);
} else if (is_builtin()) {
out << BuiltinKind::FromInt(index);
out << builtin_kind();
} else {
// Use the `+` as a small reminder that this is a delta, rather than an
// absolute index.