mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-02 16:15:52 +01:00
Propagate error state in an `extend impl` declaration out to the enclosing scope. We can do this generically in `ApplyExtendImplAs` so we don't have to do it explicitly in other places. Collapse `DiagnoseExtendImplOutsideClass` into `ApplyExtendImplAs` as it had only the one caller and is very small, so this simplifies the code, making `ApplyExtendImplAs` a clear set of diagnostics. And push the construction of the SpecificConstant down into `ApplyExtendImplAs` so it is only constructed if it's needed, instead of constructing it and throwing it away in error cases. Ensure any error in the declaration results in the witness being an ErrorInst so the impl will not be used in impl lookup. This simplifies some branches by combining them into a single if statement. This is part of #6420 which is being split up into a chain of smaller PRs. It is based on #6467.
95 lines
4.5 KiB
Plaintext
95 lines
4.5 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_extend_partially_defined_interface.carbon
|
|
// TIP: To dump output, run:
|
|
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/fail_extend_partially_defined_interface.carbon
|
|
|
|
interface I {
|
|
class C {
|
|
// CHECK:STDERR: fail_extend_partially_defined_interface.carbon:[[@LINE+7]]:5: error: `extend impl as` incomplete facet type `I` [ExtendImplAsIncomplete]
|
|
// CHECK:STDERR: extend impl as I;
|
|
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
|
|
// CHECK:STDERR: fail_extend_partially_defined_interface.carbon:[[@LINE-5]]:1: note: interface is currently being defined [InterfaceIncompleteWithinDefinition]
|
|
// CHECK:STDERR: interface I {
|
|
// CHECK:STDERR: ^~~~~~~~~~~~~
|
|
// CHECK:STDERR:
|
|
extend impl as I;
|
|
}
|
|
}
|
|
|
|
// CHECK:STDOUT: --- fail_extend_partially_defined_interface.carbon
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: constants {
|
|
// CHECK:STDOUT: %I.type: type = facet_type <@I> [concrete]
|
|
// CHECK:STDOUT: %Self: %I.type = symbolic_binding Self, 0 [symbolic]
|
|
// CHECK:STDOUT: %C: type = class_type @C, @C(%Self) [symbolic]
|
|
// CHECK:STDOUT: %I.impl_witness: <witness> = impl_witness @C.%I.impl_witness_table, @C.as.I.impl(%Self) [symbolic]
|
|
// 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: .I = %I.decl
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: interface @I {
|
|
// CHECK:STDOUT: %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]
|
|
// CHECK:STDOUT: %C.decl: type = class_decl @C [symbolic = constants.%C] {} {}
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !members:
|
|
// CHECK:STDOUT: .Self = %Self
|
|
// CHECK:STDOUT: .C = %C.decl
|
|
// CHECK:STDOUT: .I = <poisoned>
|
|
// CHECK:STDOUT: witness = ()
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !requires:
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: generic impl @C.as.I.impl(@I.%Self: %I.type) {
|
|
// CHECK:STDOUT: %Self: %I.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self)]
|
|
// CHECK:STDOUT: %C: type = class_type @C, @C(%Self) [symbolic = %C (constants.%C)]
|
|
// CHECK:STDOUT: %I.impl_witness: <witness> = impl_witness @C.%I.impl_witness_table, @C.as.I.impl(%Self) [symbolic = %I.impl_witness (constants.%I.impl_witness)]
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: impl: %Self.ref as %I.ref;
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: generic class @C(@I.%Self: %I.type) {
|
|
// CHECK:STDOUT: !definition:
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: class {
|
|
// CHECK:STDOUT: impl_decl @C.as.I.impl [concrete] {} {
|
|
// CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%C [symbolic = %C (constants.%C)]
|
|
// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (), @C.as.I.impl [concrete]
|
|
// CHECK:STDOUT: %I.impl_witness: <witness> = impl_witness %I.impl_witness_table, @C.as.I.impl(constants.%Self) [symbolic = @C.as.I.impl.%I.impl_witness (constants.%I.impl_witness)]
|
|
// 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: .I = <poisoned>
|
|
// CHECK:STDOUT: has_error
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: specific @C(constants.%Self) {}
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: specific @C.as.I.impl(constants.%Self) {
|
|
// CHECK:STDOUT: %Self => constants.%Self
|
|
// CHECK:STDOUT: %C => constants.%C
|
|
// CHECK:STDOUT: %I.impl_witness => constants.%I.impl_witness
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|