Skip to content

Commit 4c0979f

Browse files
authored
Fix crash when importing an invalid impl (#5875)
Dropping this in with basic.carbon as an aspirational way to encourage more tests there. This currently crashes because `CollectCandidateImplsForQuery` tries building a type structure which cannot contain `ErrorInst`.
1 parent 6a3e222 commit 4c0979f

File tree

2 files changed

+41
-44
lines changed

2 files changed

+41
-44
lines changed

toolchain/check/testdata/impl/basic.carbon

Lines changed: 40 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3,50 +3,74 @@
33
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
44
//
55
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon
6-
// TODO: Add ranges and switch to "--dump-sem-ir-ranges=only".
7-
// EXTRA-ARGS: --dump-sem-ir-ranges=if-present
86
//
97
// AUTOUPDATE
108
// TIP: To test this file alone, run:
119
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/basic.carbon
1210
// TIP: To dump output, run:
1311
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/basic.carbon
1412

13+
// --- basic.carbon
14+
15+
library "[[@TEST_NAME]]";
16+
1517
interface Simple {
1618
fn F();
1719
}
1820

1921
class C {}
2022

23+
//@dump-sem-ir-begin
2124
impl C as Simple {
2225
fn F() {}
2326
}
27+
//@dump-sem-ir-end
28+
29+
// --- fail_invalid_impl.carbon
30+
31+
library "[[@TEST_NAME]]";
32+
33+
interface I {
34+
fn Op[self: Self]();
35+
}
36+
37+
class C {}
38+
39+
// This produces an invalid impl.
40+
// CHECK:STDERR: fail_invalid_impl.carbon:[[@LINE+4]]:6: error: name `Unknown` not found [NameNotFound]
41+
// CHECK:STDERR: impl Unknown as I {
42+
// CHECK:STDERR: ^~~~~~~
43+
// CHECK:STDERR:
44+
impl Unknown as I {
45+
fn Op[self: Self]() {}
46+
}
47+
48+
// --- fail_import_invalid_impl.carbon
49+
50+
library "[[@TEST_NAME]]";
51+
import library "invalid_impl";
52+
53+
fn F() {
54+
// This impl doesn't exist, but it still tests that we can ignore the
55+
// `impl Unknown as I` on import.
56+
// CHECK:STDERR: fail_import_invalid_impl.carbon:[[@LINE+4]]:3: error: cannot access member of interface `I` in type `type` that does not implement that interface [MissingImplInMemberAccess]
57+
// CHECK:STDERR: C.(I.Op)();
58+
// CHECK:STDERR: ^~~~~~~~
59+
// CHECK:STDERR:
60+
C.(I.Op)();
61+
}
2462

2563
// CHECK:STDOUT: --- basic.carbon
2664
// CHECK:STDOUT:
2765
// CHECK:STDOUT: constants {
2866
// CHECK:STDOUT: %Simple.type: type = facet_type <@Simple> [concrete]
29-
// CHECK:STDOUT: %Self: %Simple.type = bind_symbolic_name Self, 0 [symbolic]
30-
// CHECK:STDOUT: %Simple.F.type: type = fn_type @Simple.F [concrete]
31-
// CHECK:STDOUT: %Simple.F: %Simple.F.type = struct_value () [concrete]
32-
// CHECK:STDOUT: %Simple.assoc_type: type = assoc_entity_type @Simple [concrete]
33-
// CHECK:STDOUT: %assoc0: %Simple.assoc_type = assoc_entity element0, @Simple.%Simple.F.decl [concrete]
3467
// CHECK:STDOUT: %C: type = class_type @C [concrete]
35-
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
36-
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
3768
// CHECK:STDOUT: %Simple.impl_witness: <witness> = impl_witness file.%Simple.impl_witness_table [concrete]
3869
// CHECK:STDOUT: %C.as.Simple.impl.F.type: type = fn_type @C.as.Simple.impl.F [concrete]
3970
// CHECK:STDOUT: %C.as.Simple.impl.F: %C.as.Simple.impl.F.type = struct_value () [concrete]
40-
// CHECK:STDOUT: %Simple.facet: %Simple.type = facet_value %C, (%Simple.impl_witness) [concrete]
4171
// CHECK:STDOUT: }
4272
// CHECK:STDOUT:
4373
// CHECK:STDOUT: file {
44-
// CHECK:STDOUT: package: <namespace> = namespace [concrete] {
45-
// CHECK:STDOUT: .Simple = %Simple.decl
46-
// CHECK:STDOUT: .C = %C.decl
47-
// CHECK:STDOUT: }
48-
// CHECK:STDOUT: %Simple.decl: type = interface_decl @Simple [concrete = constants.%Simple.type] {} {}
49-
// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
5074
// CHECK:STDOUT: impl_decl @C.as.Simple.impl [concrete] {} {
5175
// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
5276
// CHECK:STDOUT: %Simple.ref: type = name_ref Simple, file.%Simple.decl [concrete = constants.%Simple.type]
@@ -55,17 +79,6 @@ impl C as Simple {
5579
// CHECK:STDOUT: %Simple.impl_witness: <witness> = impl_witness %Simple.impl_witness_table [concrete = constants.%Simple.impl_witness]
5680
// CHECK:STDOUT: }
5781
// CHECK:STDOUT:
58-
// CHECK:STDOUT: interface @Simple {
59-
// CHECK:STDOUT: %Self: %Simple.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self]
60-
// CHECK:STDOUT: %Simple.F.decl: %Simple.F.type = fn_decl @Simple.F [concrete = constants.%Simple.F] {} {}
61-
// CHECK:STDOUT: %assoc0: %Simple.assoc_type = assoc_entity element0, %Simple.F.decl [concrete = constants.%assoc0]
62-
// CHECK:STDOUT:
63-
// CHECK:STDOUT: !members:
64-
// CHECK:STDOUT: .Self = %Self
65-
// CHECK:STDOUT: .F = %assoc0
66-
// CHECK:STDOUT: witness = (%Simple.F.decl)
67-
// CHECK:STDOUT: }
68-
// CHECK:STDOUT:
6982
// CHECK:STDOUT: impl @C.as.Simple.impl: %C.ref as %Simple.ref {
7083
// CHECK:STDOUT: %C.as.Simple.impl.F.decl: %C.as.Simple.impl.F.type = fn_decl @C.as.Simple.impl.F [concrete = constants.%C.as.Simple.impl.F] {} {}
7184
// CHECK:STDOUT:
@@ -74,25 +87,8 @@ impl C as Simple {
7487
// CHECK:STDOUT: witness = file.%Simple.impl_witness
7588
// CHECK:STDOUT: }
7689
// CHECK:STDOUT:
77-
// CHECK:STDOUT: class @C {
78-
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type]
79-
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type]
80-
// CHECK:STDOUT: complete_type_witness = %complete_type
81-
// CHECK:STDOUT:
82-
// CHECK:STDOUT: !members:
83-
// CHECK:STDOUT: .Self = constants.%C
84-
// CHECK:STDOUT: }
85-
// CHECK:STDOUT:
86-
// CHECK:STDOUT: generic fn @Simple.F(@Simple.%Self: %Simple.type) {
87-
// CHECK:STDOUT: fn();
88-
// CHECK:STDOUT: }
89-
// CHECK:STDOUT:
9090
// CHECK:STDOUT: fn @C.as.Simple.impl.F() {
9191
// CHECK:STDOUT: !entry:
9292
// CHECK:STDOUT: return
9393
// CHECK:STDOUT: }
9494
// CHECK:STDOUT:
95-
// CHECK:STDOUT: specific @Simple.F(constants.%Self) {}
96-
// CHECK:STDOUT:
97-
// CHECK:STDOUT: specific @Simple.F(constants.%Simple.facet) {}
98-
// CHECK:STDOUT:

toolchain/sem_ir/type_iterator.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ auto TypeIterator::Next() -> Step {
7979

8080
case SemIR::AssociatedEntityType::Kind:
8181
case SemIR::BoolType::Kind:
82+
case SemIR::ErrorInst::Kind:
8283
case SemIR::FacetType::Kind:
8384
case SemIR::FloatType::Kind:
8485
case SemIR::FunctionType::Kind:

0 commit comments

Comments
 (0)