mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 21:10:12 +01:00
Instead of the `call` instruction having a block with one argument per explicit argument, preceded optionally by `self` and followed optionally by a return slot, change the `call` to store only the *runtime* arguments. Store an index on the runtime parameters to make it easier to determine the correspondence between arguments and parameters in a call. Compile-time parameters, whether implicit or explicit, are no longer included in the call argument list. Instead, they're tracked only in the `specific_id` on the callee. For calls to generic classes and generic interfaces, it no longer makes sense to form a `call` instruction, given that the entirety of the result is determined by the `specific_id`, which is now formed when checking the call. Instead, the `call` instruction now only models function calls, and not calls to other kinds of parameterized entity names, and we create a `class_type` or `interface_type` instead of a `call` instruction to model these kinds of calls. Notionally the model here is that we're following the #3720 approach for calls, but for now we inline the `Call.Op` function when forming SemIR. We now also track the enclosing specific for a generic class or generic interface that appears within an enclosing generic. This is necessary in order for deduction of the inner generic parameters to not get confused by the outer generic parameters being absent. In order to not regress diagnostics, the template argument deduction mechanism has been extended to specify the name of the parameter we're deducing against when possible, and call arity mismatch errors are now diagnosed before performing deduction rather than afterwards.
161 lines
9.0 KiB
Plaintext
161 lines
9.0 KiB
Plaintext
// 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/array/fail_bound_overflow.carbon
|
|
// TIP: To dump output, run:
|
|
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/array/fail_bound_overflow.carbon
|
|
|
|
// TODO: Once we preserve the full value of integer literals in SemIR, check
|
|
// that we reject the array bound being too large.
|
|
|
|
// CHECK:STDERR: fail_bound_overflow.carbon:[[@LINE+4]]:14: ERROR: Integer literal with value 39999999999999999993 does not fit in i32.
|
|
// CHECK:STDERR: var a: [i32; 39999999999999999993];
|
|
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~
|
|
// CHECK:STDERR:
|
|
var a: [i32; 39999999999999999993];
|
|
|
|
// CHECK:STDERR: fail_bound_overflow.carbon:[[@LINE+10]]:9: ERROR: Cannot implicitly convert from `i32` to `type`.
|
|
// CHECK:STDERR: var b: [1; 39999999999999999993];
|
|
// CHECK:STDERR: ^
|
|
// CHECK:STDERR: fail_bound_overflow.carbon:[[@LINE+7]]:9: Type `i32` does not implement interface `ImplicitAs`.
|
|
// CHECK:STDERR: var b: [1; 39999999999999999993];
|
|
// CHECK:STDERR: ^
|
|
// CHECK:STDERR:
|
|
// CHECK:STDERR: fail_bound_overflow.carbon:[[@LINE+3]]:12: ERROR: Integer literal with value 39999999999999999993 does not fit in i32.
|
|
// CHECK:STDERR: var b: [1; 39999999999999999993];
|
|
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~
|
|
var b: [1; 39999999999999999993];
|
|
|
|
// CHECK:STDOUT: --- fail_bound_overflow.carbon
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: constants {
|
|
// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template]
|
|
// CHECK:STDOUT: %.1: type = tuple_type () [template]
|
|
// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template]
|
|
// CHECK:STDOUT: %.2: i32 = int_literal 1 [template]
|
|
// CHECK:STDOUT: %ImplicitAs.type: type = generic_interface_type @ImplicitAs [template]
|
|
// CHECK:STDOUT: %ImplicitAs: %ImplicitAs.type = struct_value () [template]
|
|
// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest 0 [symbolic]
|
|
// CHECK:STDOUT: %.3: type = interface_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic]
|
|
// CHECK:STDOUT: %Self.1: @ImplicitAs.%.1 (%.3) = bind_symbolic_name Self 1 [symbolic]
|
|
// CHECK:STDOUT: %Self.2: %.3 = bind_symbolic_name Self 1 [symbolic]
|
|
// CHECK:STDOUT: %Convert.type.1: type = fn_type @Convert, @ImplicitAs(%Dest) [symbolic]
|
|
// CHECK:STDOUT: %Convert.1: %Convert.type.1 = struct_value () [symbolic]
|
|
// CHECK:STDOUT: %.4: type = assoc_entity_type %.3, %Convert.type.1 [symbolic]
|
|
// CHECK:STDOUT: %.5: %.4 = assoc_entity element0, imports.%import_ref.6 [symbolic]
|
|
// CHECK:STDOUT: %.6: type = interface_type @ImplicitAs, @ImplicitAs(type) [template]
|
|
// CHECK:STDOUT: %Convert.type.2: type = fn_type @Convert, @ImplicitAs(type) [template]
|
|
// CHECK:STDOUT: %Convert.2: %Convert.type.2 = struct_value () [template]
|
|
// CHECK:STDOUT: %.7: type = assoc_entity_type %.6, %Convert.type.2 [template]
|
|
// CHECK:STDOUT: %.8: %.7 = assoc_entity element0, imports.%import_ref.6 [template]
|
|
// CHECK:STDOUT: %.9: %.4 = assoc_entity element0, imports.%import_ref.7 [symbolic]
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: imports {
|
|
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
|
|
// CHECK:STDOUT: .Int32 = %import_ref.1
|
|
// CHECK:STDOUT: .ImplicitAs = %import_ref.2
|
|
// CHECK:STDOUT: import Core//prelude
|
|
// CHECK:STDOUT: import Core//prelude/operators
|
|
// CHECK:STDOUT: import Core//prelude/types
|
|
// CHECK:STDOUT: import Core//prelude/operators/arithmetic
|
|
// CHECK:STDOUT: import Core//prelude/operators/as
|
|
// CHECK:STDOUT: import Core//prelude/operators/bitwise
|
|
// CHECK:STDOUT: import Core//prelude/operators/comparison
|
|
// CHECK:STDOUT: import Core//prelude/types/bool
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %import_ref.1: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32]
|
|
// CHECK:STDOUT: %import_ref.2: %ImplicitAs.type = import_ref Core//prelude/operators/as, inst+37, loaded [template = constants.%ImplicitAs]
|
|
// CHECK:STDOUT: %import_ref.3 = import_ref Core//prelude/operators/as, inst+42, unloaded
|
|
// CHECK:STDOUT: %import_ref.4: @ImplicitAs.%.2 (%.4) = import_ref Core//prelude/operators/as, inst+59, loaded [symbolic = @ImplicitAs.%.3 (constants.%.9)]
|
|
// CHECK:STDOUT: %import_ref.5 = import_ref Core//prelude/operators/as, inst+52, unloaded
|
|
// CHECK:STDOUT: %import_ref.6 = import_ref Core//prelude/operators/as, inst+52, unloaded
|
|
// CHECK:STDOUT: %import_ref.7 = import_ref Core//prelude/operators/as, inst+52, unloaded
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: file {
|
|
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
|
// CHECK:STDOUT: .Core = imports.%Core
|
|
// CHECK:STDOUT: .a = %a
|
|
// CHECK:STDOUT: .b = %b
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %Core.import = import Core
|
|
// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32]
|
|
// CHECK:STDOUT: %.loc18_9.1: type = value_of_initializer %int.make_type_32 [template = i32]
|
|
// CHECK:STDOUT: %.loc18_9.2: type = converted %int.make_type_32, %.loc18_9.1 [template = i32]
|
|
// CHECK:STDOUT: %.loc18_34: type = array_type <error>, i32 [template = <error>]
|
|
// CHECK:STDOUT: %a.var: ref <error> = var a
|
|
// CHECK:STDOUT: %a: ref <error> = bind_name a, %a.var
|
|
// CHECK:STDOUT: %.loc30_9.1: i32 = int_literal 1 [template = constants.%.2]
|
|
// CHECK:STDOUT: %.loc30_9.2: type = interface_type @ImplicitAs, @ImplicitAs(type) [template = constants.%.6]
|
|
// CHECK:STDOUT: %.loc30_9.3: %.7 = specific_constant imports.%import_ref.4, @ImplicitAs(type) [template = constants.%.8]
|
|
// CHECK:STDOUT: %Convert.ref: %.7 = name_ref Convert, %.loc30_9.3 [template = constants.%.8]
|
|
// CHECK:STDOUT: %.loc30_9.4: type = converted %.loc30_9.1, <error> [template = <error>]
|
|
// CHECK:STDOUT: %.loc30_32: type = array_type <error>, <error> [template = <error>]
|
|
// CHECK:STDOUT: %b.var: ref <error> = var b
|
|
// CHECK:STDOUT: %b: ref <error> = bind_name b, %b.var
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: generic interface @ImplicitAs(constants.%Dest: type) {
|
|
// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest 0 [symbolic = %Dest (constants.%Dest)]
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !definition:
|
|
// CHECK:STDOUT: %.1: type = interface_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic = %.1 (constants.%.3)]
|
|
// CHECK:STDOUT: %Self: %.3 = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.2)]
|
|
// CHECK:STDOUT: %Convert.type: type = fn_type @Convert, @ImplicitAs(%Dest) [symbolic = %Convert.type (constants.%Convert.type.1)]
|
|
// CHECK:STDOUT: %Convert: @ImplicitAs.%Convert.type (%Convert.type.1) = struct_value () [symbolic = %Convert (constants.%Convert.1)]
|
|
// CHECK:STDOUT: %.2: type = assoc_entity_type @ImplicitAs.%.1 (%.3), @ImplicitAs.%Convert.type (%Convert.type.1) [symbolic = %.2 (constants.%.4)]
|
|
// CHECK:STDOUT: %.3: @ImplicitAs.%.2 (%.4) = assoc_entity element0, imports.%import_ref.6 [symbolic = %.3 (constants.%.5)]
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: interface {
|
|
// CHECK:STDOUT: !members:
|
|
// CHECK:STDOUT: .Self = imports.%import_ref.3
|
|
// CHECK:STDOUT: .Convert = imports.%import_ref.4
|
|
// CHECK:STDOUT: witness = (imports.%import_ref.5)
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32";
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: generic fn @Convert(constants.%Dest: type, constants.%Self.1: @ImplicitAs.%.1 (%.3)) {
|
|
// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest 0 [symbolic = %Dest (constants.%Dest)]
|
|
// CHECK:STDOUT: %.1: type = interface_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic = %.1 (constants.%.3)]
|
|
// CHECK:STDOUT: %Self: %.3 = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.2)]
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn[%self: @Convert.%Self (%Self.2)]() -> @Convert.%Dest (%Dest);
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: specific @ImplicitAs(constants.%Dest) {
|
|
// CHECK:STDOUT: %Dest => constants.%Dest
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: specific @ImplicitAs(@ImplicitAs.%Dest) {
|
|
// CHECK:STDOUT: %Dest => constants.%Dest
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: specific @ImplicitAs(@Convert.%Dest) {
|
|
// CHECK:STDOUT: %Dest => constants.%Dest
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: specific @Convert(constants.%Dest, constants.%Self.1) {
|
|
// CHECK:STDOUT: %Dest => constants.%Dest
|
|
// CHECK:STDOUT: %.1 => constants.%.3
|
|
// CHECK:STDOUT: %Self => constants.%Self.1
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: specific @ImplicitAs(type) {
|
|
// CHECK:STDOUT: %Dest => type
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !definition:
|
|
// CHECK:STDOUT: %.1 => constants.%.6
|
|
// CHECK:STDOUT: %Self => constants.%Self.2
|
|
// CHECK:STDOUT: %Convert.type => constants.%Convert.type.2
|
|
// CHECK:STDOUT: %Convert => constants.%Convert.2
|
|
// CHECK:STDOUT: %.2 => constants.%.7
|
|
// CHECK:STDOUT: %.3 => constants.%.8
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|