mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-03 22:02:51 +01:00
Give TupleLiteral and StructLiteral a constant value, if their contents have constant values. Their constant values are TupleValue and StructValue respectively. This supports their ability to convert to a constant type (or facet type). This way when deduce finds a TupleLiteral as the argument to a _symbolic_ facet type, it can also find a constant value to use for that argument. This allows deduction to move onto step two, where it can substitute into the symbolic parameter from previous deduced arguments, and then perform the conversion from the TupleValue to the desired facet type. Allow `PerformBuiltinConversion()` to convert from a canonical TupleValue or StructValue to `type` instead of only from literals. Then, also support conversion from a symbolic binding of type TupleType or StructType to `type`.
291 lines
14 KiB
Plaintext
291 lines
14 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
|
|
//
|
|
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon
|
|
// TODO: Add ranges and switch to "--dump-sem-ir-ranges=only".
|
|
// EXTRA-ARGS: --dump-sem-ir-ranges=if-present
|
|
//
|
|
// AUTOUPDATE
|
|
// TIP: To test this file alone, run:
|
|
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/fail_undefined_interface.carbon
|
|
// TIP: To dump output, run:
|
|
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/fail_undefined_interface.carbon
|
|
|
|
// --- fail_empty_struct.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
interface I;
|
|
// CHECK:STDERR: fail_empty_struct.carbon:[[@LINE+7]]:1: error: definition of impl as incomplete facet type `I` [ImplAsIncompleteFacetTypeDefinition]
|
|
// CHECK:STDERR: impl {} as I {}
|
|
// CHECK:STDERR: ^~~~~~~~~~~~~~
|
|
// CHECK:STDERR: fail_empty_struct.carbon:[[@LINE-4]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]
|
|
// CHECK:STDERR: interface I;
|
|
// CHECK:STDERR: ^~~~~~~~~~~~
|
|
// CHECK:STDERR:
|
|
impl {} as I {}
|
|
|
|
// --- fail_class.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
interface J;
|
|
class C {}
|
|
// CHECK:STDERR: fail_class.carbon:[[@LINE+7]]:1: error: definition of impl as incomplete facet type `J` [ImplAsIncompleteFacetTypeDefinition]
|
|
// CHECK:STDERR: impl C as J {}
|
|
// CHECK:STDERR: ^~~~~~~~~~~~~
|
|
// CHECK:STDERR: fail_class.carbon:[[@LINE-5]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]
|
|
// CHECK:STDERR: interface J;
|
|
// CHECK:STDERR: ^~~~~~~~~~~~
|
|
// CHECK:STDERR:
|
|
impl C as J {}
|
|
|
|
// --- fail_incomplete_where.carbon
|
|
library "[[@TEST_NAME]]";
|
|
|
|
class C {}
|
|
|
|
interface I {}
|
|
interface Incomplete;
|
|
|
|
// CHECK:STDERR: fail_incomplete_where.carbon:[[@LINE+7]]:1: error: definition of impl as incomplete facet type `I where .Self impls Incomplete` [ImplAsIncompleteFacetTypeDefinition]
|
|
// CHECK:STDERR: impl C as I where .Self impls Incomplete {}
|
|
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// CHECK:STDERR: fail_incomplete_where.carbon:[[@LINE-5]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]
|
|
// CHECK:STDERR: interface Incomplete;
|
|
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~
|
|
// CHECK:STDERR:
|
|
impl C as I where .Self impls Incomplete {}
|
|
|
|
// --- fail_declaration_incomplete_where_rewrite.carbon
|
|
library "[[@TEST_NAME]]";
|
|
|
|
class C {}
|
|
|
|
interface J { let T:! type; }
|
|
interface Incomplete;
|
|
|
|
// CHECK:STDERR: fail_declaration_incomplete_where_rewrite.carbon:[[@LINE+7]]:1: error: declaration of impl as incomplete facet type `J where .Self impls Incomplete and .(J.T) = ()` with rewrites [ImplAsIncompleteFacetTypeRewrites]
|
|
// CHECK:STDERR: impl C as J where .Self impls Incomplete and .T = ();
|
|
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// CHECK:STDERR: fail_declaration_incomplete_where_rewrite.carbon:[[@LINE-5]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]
|
|
// CHECK:STDERR: interface Incomplete;
|
|
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~
|
|
// CHECK:STDERR:
|
|
impl C as J where .Self impls Incomplete and .T = ();
|
|
|
|
// CHECK:STDOUT: --- fail_empty_struct.carbon
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: constants {
|
|
// CHECK:STDOUT: %I.type: type = facet_type <@I> [concrete]
|
|
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
|
|
// CHECK:STDOUT: %empty_struct: %empty_struct_type = struct_value () [concrete]
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: file {
|
|
// CHECK:STDOUT: package: <namespace> = namespace [concrete] {
|
|
// CHECK:STDOUT: .I = %I.decl
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}
|
|
// CHECK:STDOUT: impl_decl @empty_struct_type.as.I.impl [concrete] {} {
|
|
// CHECK:STDOUT: %.loc12_7.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
|
|
// CHECK:STDOUT: %.loc12_7.2: type = converted %.loc12_7.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
|
|
// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: interface @I;
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: impl @empty_struct_type.as.I.impl: %.loc12_7.2 as %I.ref {
|
|
// CHECK:STDOUT: !members:
|
|
// CHECK:STDOUT: witness = <error>
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: --- fail_class.carbon
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: constants {
|
|
// CHECK:STDOUT: %J.type: type = facet_type <@J> [concrete]
|
|
// CHECK:STDOUT: %C: type = class_type @C [concrete]
|
|
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
|
|
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: file {
|
|
// CHECK:STDOUT: package: <namespace> = namespace [concrete] {
|
|
// CHECK:STDOUT: .J = %J.decl
|
|
// CHECK:STDOUT: .C = %C.decl
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %J.decl: type = interface_decl @J [concrete = constants.%J.type] {} {}
|
|
// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
|
|
// CHECK:STDOUT: impl_decl @C.as.J.impl [concrete] {} {
|
|
// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
|
|
// CHECK:STDOUT: %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type]
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: interface @J;
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: impl @C.as.J.impl: %C.ref as %J.ref {
|
|
// CHECK:STDOUT: !members:
|
|
// CHECK:STDOUT: witness = <error>
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: class @C {
|
|
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]
|
|
// CHECK:STDOUT: complete_type_witness = %complete_type
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !members:
|
|
// CHECK:STDOUT: .Self = constants.%C
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: --- fail_incomplete_where.carbon
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: constants {
|
|
// CHECK:STDOUT: %C: type = class_type @C [concrete]
|
|
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
|
|
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
|
|
// CHECK:STDOUT: %I.type: type = facet_type <@I> [concrete]
|
|
// CHECK:STDOUT: %Self: %I.type = symbolic_binding Self, 0 [symbolic]
|
|
// CHECK:STDOUT: %Incomplete.type: type = facet_type <@Incomplete> [concrete]
|
|
// CHECK:STDOUT: %.Self: %I.type = symbolic_binding .Self [symbolic_self]
|
|
// CHECK:STDOUT: %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self [symbolic_self]
|
|
// CHECK:STDOUT: %I_where.type: type = facet_type <@I where .Self impls @Incomplete> [concrete]
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: file {
|
|
// CHECK:STDOUT: package: <namespace> = namespace [concrete] {
|
|
// CHECK:STDOUT: .C = %C.decl
|
|
// CHECK:STDOUT: .I = %I.decl
|
|
// CHECK:STDOUT: .Incomplete = %Incomplete.decl
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
|
|
// CHECK:STDOUT: %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}
|
|
// CHECK:STDOUT: %Incomplete.decl: type = interface_decl @Incomplete [concrete = constants.%Incomplete.type] {} {}
|
|
// CHECK:STDOUT: impl_decl @C.as.I.impl [concrete] {} {
|
|
// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
|
|
// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]
|
|
// CHECK:STDOUT: %.Self: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self]
|
|
// CHECK:STDOUT: %.Self.ref: %I.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self]
|
|
// CHECK:STDOUT: %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete.decl [concrete = constants.%Incomplete.type]
|
|
// CHECK:STDOUT: %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.binding.as_type]
|
|
// CHECK:STDOUT: %.loc15_19: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.binding.as_type]
|
|
// CHECK:STDOUT: %.loc15_13: type = where_expr %.Self [concrete = constants.%I_where.type] {
|
|
// CHECK:STDOUT: requirement_base_facet_type constants.%I.type
|
|
// CHECK:STDOUT: requirement_impls %.loc15_19, %Incomplete.ref
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: interface @I {
|
|
// CHECK:STDOUT: %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !members:
|
|
// CHECK:STDOUT: .Self = %Self
|
|
// CHECK:STDOUT: witness = ()
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !requires:
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: interface @Incomplete;
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: impl @C.as.I.impl: %C.ref as %.loc15_13 {
|
|
// CHECK:STDOUT: !members:
|
|
// CHECK:STDOUT: witness = <error>
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: class @C {
|
|
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]
|
|
// CHECK:STDOUT: complete_type_witness = %complete_type
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !members:
|
|
// CHECK:STDOUT: .Self = constants.%C
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: --- fail_declaration_incomplete_where_rewrite.carbon
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: constants {
|
|
// CHECK:STDOUT: %C: type = class_type @C [concrete]
|
|
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
|
|
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
|
|
// CHECK:STDOUT: %J.type: type = facet_type <@J> [concrete]
|
|
// CHECK:STDOUT: %Self: %J.type = symbolic_binding Self, 0 [symbolic]
|
|
// CHECK:STDOUT: %J.assoc_type: type = assoc_entity_type @J [concrete]
|
|
// CHECK:STDOUT: %assoc0: %J.assoc_type = assoc_entity element0, @J.%T [concrete]
|
|
// CHECK:STDOUT: %Incomplete.type: type = facet_type <@Incomplete> [concrete]
|
|
// CHECK:STDOUT: %.Self: %J.type = symbolic_binding .Self [symbolic_self]
|
|
// CHECK:STDOUT: %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self [symbolic_self]
|
|
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
|
|
// CHECK:STDOUT: %J.lookup_impl_witness: <witness> = lookup_impl_witness %.Self, @J [symbolic_self]
|
|
// CHECK:STDOUT: %impl.elem0: type = impl_witness_access %J.lookup_impl_witness, element0 [symbolic_self]
|
|
// CHECK:STDOUT: %empty_tuple: %empty_tuple.type = tuple_value () [concrete]
|
|
// CHECK:STDOUT: %J_where.type: type = facet_type <@J where .Self impls @Incomplete and %impl.elem0 = %empty_tuple.type> [concrete]
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: file {
|
|
// CHECK:STDOUT: package: <namespace> = namespace [concrete] {
|
|
// CHECK:STDOUT: .C = %C.decl
|
|
// CHECK:STDOUT: .J = %J.decl
|
|
// CHECK:STDOUT: .Incomplete = %Incomplete.decl
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
|
|
// CHECK:STDOUT: %J.decl: type = interface_decl @J [concrete = constants.%J.type] {} {}
|
|
// CHECK:STDOUT: %Incomplete.decl: type = interface_decl @Incomplete [concrete = constants.%Incomplete.type] {} {}
|
|
// CHECK:STDOUT: impl_decl @C.as.J.impl [concrete] {} {
|
|
// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
|
|
// CHECK:STDOUT: %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type]
|
|
// CHECK:STDOUT: %.Self: %J.type = symbolic_binding .Self [symbolic_self = constants.%.Self]
|
|
// CHECK:STDOUT: %.Self.ref.loc15_19: %J.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self]
|
|
// CHECK:STDOUT: %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete.decl [concrete = constants.%Incomplete.type]
|
|
// CHECK:STDOUT: %.Self.as_type.loc15_19: type = facet_access_type %.Self.ref.loc15_19 [symbolic_self = constants.%.Self.binding.as_type]
|
|
// CHECK:STDOUT: %.loc15_19: type = converted %.Self.ref.loc15_19, %.Self.as_type.loc15_19 [symbolic_self = constants.%.Self.binding.as_type]
|
|
// CHECK:STDOUT: %.Self.ref.loc15_46: %J.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self]
|
|
// CHECK:STDOUT: %T.ref: %J.assoc_type = name_ref T, @T.%assoc0 [concrete = constants.%assoc0]
|
|
// CHECK:STDOUT: %.Self.as_type.loc15_46: type = facet_access_type %.Self.ref.loc15_46 [symbolic_self = constants.%.Self.binding.as_type]
|
|
// CHECK:STDOUT: %.loc15_46: type = converted %.Self.ref.loc15_46, %.Self.as_type.loc15_46 [symbolic_self = constants.%.Self.binding.as_type]
|
|
// CHECK:STDOUT: %impl.elem0: type = impl_witness_access constants.%J.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
|
|
// CHECK:STDOUT: %.loc15_52.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
|
|
// CHECK:STDOUT: %.loc15_52.2: type = converted %.loc15_52.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
|
|
// CHECK:STDOUT: %.loc15_13: type = where_expr %.Self [concrete = constants.%J_where.type] {
|
|
// CHECK:STDOUT: requirement_base_facet_type constants.%J.type
|
|
// CHECK:STDOUT: requirement_impls %.loc15_19, %Incomplete.ref
|
|
// CHECK:STDOUT: requirement_rewrite %impl.elem0, %.loc15_52.2
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: interface @J {
|
|
// CHECK:STDOUT: %Self: %J.type = symbolic_binding Self, 0 [symbolic = constants.%Self]
|
|
// CHECK:STDOUT: %T: type = assoc_const_decl @T [concrete] {
|
|
// CHECK:STDOUT: %assoc0: %J.assoc_type = assoc_entity element0, @J.%T [concrete = constants.%assoc0]
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !members:
|
|
// CHECK:STDOUT: .Self = %Self
|
|
// CHECK:STDOUT: .T = @T.%assoc0
|
|
// CHECK:STDOUT: witness = (%T)
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !requires:
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: interface @Incomplete;
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: generic assoc_const @T(@J.%Self: %J.type) {
|
|
// CHECK:STDOUT: assoc_const T:! type;
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: impl @C.as.J.impl: %C.ref as %.loc15_13;
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: class @C {
|
|
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]
|
|
// CHECK:STDOUT: complete_type_witness = %complete_type
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !members:
|
|
// CHECK:STDOUT: .Self = constants.%C
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: specific @T(constants.%Self) {}
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: specific @T(constants.%.Self) {}
|
|
// CHECK:STDOUT:
|