Handle runtime implicit parameters, and self outside of methods (#4361)

Closes #4356, #4359

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
This commit is contained in:
josh11b
2024-10-03 20:24:28 +00:00
committed by GitHub
co-authored by Josh L
parent e617d64939
commit d6d70bf80d
12 changed files with 331 additions and 47 deletions
@@ -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
//
// AUTOUPDATE
// TIP: To test this file alone, run:
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/call/no_prelude/fail_explicit_self_param.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/no_prelude/fail_explicit_self_param.carbon
// CHECK:STDERR: fail_explicit_self_param.carbon:[[@LINE+3]]:6: error: `self` can only be declared in an implicit parameter list
// CHECK:STDERR: fn F(self: ());
// CHECK:STDERR: ^~~~~~~~
fn F(self: ());
fn Run() {
F(());
}
// CHECK:STDOUT: --- fail_explicit_self_param.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %F.type: type = fn_type @F [template]
// CHECK:STDOUT: %F: %F.type = struct_value () [template]
// CHECK:STDOUT: %Run.type: type = fn_type @Run [template]
// CHECK:STDOUT: %Run: %Run.type = struct_value () [template]
// CHECK:STDOUT: %tuple: %.1 = tuple_value () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .F = %F.decl
// CHECK:STDOUT: .Run = %Run.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {
// CHECK:STDOUT: %self.patt: %.1 = binding_pattern self
// CHECK:STDOUT: } {
// CHECK:STDOUT: %.loc14_13.1: %.1 = tuple_literal ()
// CHECK:STDOUT: %.loc14_13.2: type = converted %.loc14_13.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %self.param: %.1 = param self, runtime_param0
// CHECK:STDOUT: %self: %.1 = bind_name self, %self.param
// CHECK:STDOUT: }
// CHECK:STDOUT: %Run.decl: %Run.type = fn_decl @Run [template = constants.%Run] {} {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F(%self: %.1);
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Run() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F]
// CHECK:STDOUT: %.loc17_6: %.1 = tuple_literal ()
// CHECK:STDOUT: %tuple: %.1 = tuple_value () [template = constants.%tuple]
// CHECK:STDOUT: %.loc17_4: %.1 = converted %.loc17_6, %tuple [template = constants.%tuple]
// CHECK:STDOUT: %F.call: init %.1 = call %F.ref(%.loc17_4)
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -0,0 +1,54 @@
// 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
//
// AUTOUPDATE
// TIP: To test this file alone, run:
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/call/no_prelude/fail_runtime_implicit_param.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/no_prelude/fail_runtime_implicit_param.carbon
// CHECK:STDERR: fail_runtime_implicit_param.carbon:[[@LINE+3]]:6: error: implicit parameters of functions must be constant or `self`
// CHECK:STDERR: fn F[s: ()]();
// CHECK:STDERR: ^
fn F[s: ()]();
fn Run() {
F();
}
// CHECK:STDOUT: --- fail_runtime_implicit_param.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %F.type: type = fn_type @F [template]
// CHECK:STDOUT: %F: %F.type = struct_value () [template]
// CHECK:STDOUT: %Run.type: type = fn_type @Run [template]
// CHECK:STDOUT: %Run: %Run.type = struct_value () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .F = %F.decl
// CHECK:STDOUT: .Run = %Run.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {
// CHECK:STDOUT: %s.patt: %.1 = binding_pattern s
// CHECK:STDOUT: } {
// CHECK:STDOUT: %.loc14_10.1: %.1 = tuple_literal ()
// CHECK:STDOUT: %.loc14_10.2: type = converted %.loc14_10.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %s.param: %.1 = param s, runtime_param<invalid>
// CHECK:STDOUT: %s: %.1 = bind_name s, %s.param
// CHECK:STDOUT: }
// CHECK:STDOUT: %Run.decl: %Run.type = fn_decl @Run [template = constants.%Run] {} {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F[%base.param: <error>]();
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Run() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F]
// CHECK:STDOUT: %F.call: init %.1 = call %F.ref()
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -113,15 +113,15 @@ library "[[@TEST_NAME]]";
class C {}
alias D = C;
fn Foo[a: C]();
// CHECK:STDERR: fail_deduced_alias.carbon:[[@LINE+7]]:11: error: redeclaration syntax differs here
// CHECK:STDERR: fn Foo[a: D]() {}
// CHECK:STDERR: ^
// CHECK:STDERR: fail_deduced_alias.carbon:[[@LINE-4]]:11: note: comparing with previous declaration here
// CHECK:STDERR: fn Foo[a: C]();
// CHECK:STDERR: ^
fn Foo[a:! C]();
// CHECK:STDERR: fail_deduced_alias.carbon:[[@LINE+7]]:12: error: redeclaration syntax differs here
// CHECK:STDERR: fn Foo[a:! D]() {}
// CHECK:STDERR: ^
// CHECK:STDERR: fail_deduced_alias.carbon:[[@LINE-4]]:12: note: comparing with previous declaration here
// CHECK:STDERR: fn Foo[a:! C]();
// CHECK:STDERR: ^
// CHECK:STDERR:
fn Foo[a: D]() {}
fn Foo[a:! D]() {}
// --- todo_fail_alias_in_return.carbon
@@ -605,6 +605,7 @@ fn Foo(a: const (const C)) {}
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %.1: type = struct_type {} [template]
// CHECK:STDOUT: %.2: <witness> = complete_type_witness %.1 [template]
// CHECK:STDOUT: %a: %C = bind_symbolic_name a, 0 [symbolic]
// CHECK:STDOUT: %Foo.type: type = fn_type @Foo [template]
// CHECK:STDOUT: %.3: type = tuple_type () [template]
// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template]
@@ -623,18 +624,18 @@ fn Foo(a: const (const C)) {}
// CHECK:STDOUT: %C.ref: type = name_ref C, %C.decl [template = constants.%C]
// CHECK:STDOUT: %D: type = bind_alias D, %C.decl [template = constants.%C]
// CHECK:STDOUT: %Foo.decl: %Foo.type = fn_decl @Foo [template = constants.%Foo] {
// CHECK:STDOUT: %a.patt: %C = binding_pattern a
// CHECK:STDOUT: %a.patt: %C = symbolic_binding_pattern a, 0
// CHECK:STDOUT: } {
// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C]
// CHECK:STDOUT: %a.param: %C = param a, runtime_param0
// CHECK:STDOUT: %a: %C = bind_name a, %a.param
// CHECK:STDOUT: %a.param: %C = param a, runtime_param<invalid>
// CHECK:STDOUT: %a.loc7: %C = bind_symbolic_name a, 0, %a.param [symbolic = %a.1 (constants.%a)]
// CHECK:STDOUT: }
// CHECK:STDOUT: %.decl: %.type = fn_decl @.1 [template = constants.%.4] {
// CHECK:STDOUT: %a.patt: %C = binding_pattern a
// CHECK:STDOUT: %a.patt: %C = symbolic_binding_pattern a, 0
// CHECK:STDOUT: } {
// CHECK:STDOUT: %D.ref: type = name_ref D, file.%D [template = constants.%C]
// CHECK:STDOUT: %a.param: %C = param a, runtime_param0
// CHECK:STDOUT: %a: %C = bind_name a, %a.param
// CHECK:STDOUT: %a.param: %C = param a, runtime_param<invalid>
// CHECK:STDOUT: %a.loc15: %C = bind_symbolic_name a, 0, %a.param [symbolic = %a.1 (constants.%a)]
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -645,11 +646,29 @@ fn Foo(a: const (const C)) {}
// CHECK:STDOUT: .Self = constants.%C
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Foo[%a: %C]();
// CHECK:STDOUT: generic fn @Foo(%a.loc7: %C) {
// CHECK:STDOUT: %a.1: %C = bind_symbolic_name a, 0 [symbolic = %a.1 (constants.%a)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn @.1[%a: %C]() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: return
// CHECK:STDOUT: fn[%a.loc7: %C]();
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generic fn @.1(%a.loc15: %C) {
// CHECK:STDOUT: %a.1: %C = bind_symbolic_name a, 0 [symbolic = %a.1 (constants.%a)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT:
// CHECK:STDOUT: fn[%a.loc15: %C]() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Foo(constants.%a) {
// CHECK:STDOUT: %a.1 => constants.%a
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @.1(constants.%a) {
// CHECK:STDOUT: %a.1 => constants.%a
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- todo_fail_alias_in_return.carbon