Skip to content

Commit c30b1d1

Browse files
authored
Fix where crash when empty decl_name_stack (#4451)
Bug found by fuzzer. --------- Co-authored-by: Josh L <[email protected]>
1 parent df68bf9 commit c30b1d1

File tree

3 files changed

+229
-13
lines changed

3 files changed

+229
-13
lines changed

toolchain/check/handle_where.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ auto HandleParseNode(Context& context, Parse::WhereOperandId node_id) -> bool {
3434
// the `value_id` on the `BindSymbolicName`.
3535
auto entity_name_id = context.entity_names().Add(
3636
{.name_id = SemIR::NameId::PeriodSelf,
37-
.parent_scope_id = context.decl_name_stack().PeekParentScopeId(),
37+
.parent_scope_id = context.scope_stack().PeekNameScopeId(),
3838
.bind_index = context.scope_stack().AddCompileTimeBinding()});
3939
auto inst_id =
4040
context.AddInst(SemIR::LocIdAndInst::NoLoc<SemIR::BindSymbolicName>(

toolchain/check/testdata/where_expr/constraints.carbon

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,16 @@ fn NotEmptyStruct() {
158158
EmptyStruct(C);
159159
}
160160

161+
// --- let.carbon
162+
163+
library "[[@TEST_NAME]]";
164+
165+
interface A {}
166+
class D {}
167+
impl D as A {}
168+
// TODO: This should be a compile-time binding, once that is supported.
169+
let B: type where .Self impls A = D;
170+
161171
// CHECK:STDOUT: --- state_constraints.carbon
162172
// CHECK:STDOUT:
163173
// CHECK:STDOUT: constants {
@@ -1456,3 +1466,80 @@ fn NotEmptyStruct() {
14561466
// CHECK:STDOUT: %Y.patt.loc26_16.2 => constants.%Y
14571467
// CHECK:STDOUT: }
14581468
// CHECK:STDOUT:
1469+
// CHECK:STDOUT: --- let.carbon
1470+
// CHECK:STDOUT:
1471+
// CHECK:STDOUT: constants {
1472+
// CHECK:STDOUT: %A.type: type = interface_type @A [template]
1473+
// CHECK:STDOUT: %Self: %A.type = bind_symbolic_name Self, 0 [symbolic]
1474+
// CHECK:STDOUT: %D: type = class_type @D [template]
1475+
// CHECK:STDOUT: %.1: type = struct_type {} [template]
1476+
// CHECK:STDOUT: %.2: <witness> = complete_type_witness %.1 [template]
1477+
// CHECK:STDOUT: %.3: type = tuple_type () [template]
1478+
// CHECK:STDOUT: %.4: <witness> = interface_witness () [template]
1479+
// CHECK:STDOUT: %.Self: type = bind_symbolic_name .Self, 0 [symbolic]
1480+
// CHECK:STDOUT: }
1481+
// CHECK:STDOUT:
1482+
// CHECK:STDOUT: imports {
1483+
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
1484+
// CHECK:STDOUT: import Core//prelude
1485+
// CHECK:STDOUT: import Core//prelude/operators
1486+
// CHECK:STDOUT: import Core//prelude/types
1487+
// CHECK:STDOUT: import Core//prelude/operators/arithmetic
1488+
// CHECK:STDOUT: import Core//prelude/operators/as
1489+
// CHECK:STDOUT: import Core//prelude/operators/bitwise
1490+
// CHECK:STDOUT: import Core//prelude/operators/comparison
1491+
// CHECK:STDOUT: import Core//prelude/types/bool
1492+
// CHECK:STDOUT: }
1493+
// CHECK:STDOUT: }
1494+
// CHECK:STDOUT:
1495+
// CHECK:STDOUT: file {
1496+
// CHECK:STDOUT: package: <namespace> = namespace [template] {
1497+
// CHECK:STDOUT: .Core = imports.%Core
1498+
// CHECK:STDOUT: .A = %A.decl
1499+
// CHECK:STDOUT: .D = %D.decl
1500+
// CHECK:STDOUT: .B = @__global_init.%B
1501+
// CHECK:STDOUT: }
1502+
// CHECK:STDOUT: %Core.import = import Core
1503+
// CHECK:STDOUT: %A.decl: type = interface_decl @A [template = constants.%A.type] {} {}
1504+
// CHECK:STDOUT: %D.decl: type = class_decl @D [template = constants.%D] {} {}
1505+
// CHECK:STDOUT: impl_decl @impl [template] {} {
1506+
// CHECK:STDOUT: %D.ref: type = name_ref D, file.%D.decl [template = constants.%D]
1507+
// CHECK:STDOUT: %A.ref: type = name_ref A, file.%A.decl [template = constants.%A.type]
1508+
// CHECK:STDOUT: }
1509+
// CHECK:STDOUT: %.Self: type = bind_symbolic_name .Self, 0 [symbolic = constants.%.Self]
1510+
// CHECK:STDOUT: %.Self.ref: type = name_ref .Self, %.Self [symbolic = constants.%.Self]
1511+
// CHECK:STDOUT: %A.ref: type = name_ref A, %A.decl [template = constants.%A.type]
1512+
// CHECK:STDOUT: %.loc8: type = where_expr %.Self [template = type] {
1513+
// CHECK:STDOUT: requirement_impls %.Self.ref, %A.ref
1514+
// CHECK:STDOUT: }
1515+
// CHECK:STDOUT: }
1516+
// CHECK:STDOUT:
1517+
// CHECK:STDOUT: interface @A {
1518+
// CHECK:STDOUT: %Self: %A.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self]
1519+
// CHECK:STDOUT:
1520+
// CHECK:STDOUT: !members:
1521+
// CHECK:STDOUT: .Self = %Self
1522+
// CHECK:STDOUT: witness = ()
1523+
// CHECK:STDOUT: }
1524+
// CHECK:STDOUT:
1525+
// CHECK:STDOUT: impl @impl: %D.ref as %A.ref {
1526+
// CHECK:STDOUT: %.loc6: <witness> = interface_witness () [template = constants.%.4]
1527+
// CHECK:STDOUT:
1528+
// CHECK:STDOUT: !members:
1529+
// CHECK:STDOUT: witness = %.loc6
1530+
// CHECK:STDOUT: }
1531+
// CHECK:STDOUT:
1532+
// CHECK:STDOUT: class @D {
1533+
// CHECK:STDOUT: %.loc5: <witness> = complete_type_witness %.1 [template = constants.%.2]
1534+
// CHECK:STDOUT:
1535+
// CHECK:STDOUT: !members:
1536+
// CHECK:STDOUT: .Self = constants.%D
1537+
// CHECK:STDOUT: }
1538+
// CHECK:STDOUT:
1539+
// CHECK:STDOUT: fn @__global_init() {
1540+
// CHECK:STDOUT: !entry:
1541+
// CHECK:STDOUT: %D.ref: type = name_ref D, file.%D.decl [template = constants.%D]
1542+
// CHECK:STDOUT: %B: type = bind_name B, %D.ref
1543+
// CHECK:STDOUT: return
1544+
// CHECK:STDOUT: }
1545+
// CHECK:STDOUT:

toolchain/check/testdata/where_expr/fail_not_facet.carbon

Lines changed: 141 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,39 @@
1212

1313
library "[[@TEST_NAME]]";
1414

15-
// CHECK:STDERR: fail_left_where_not_facet.carbon:[[@LINE+3]]:10: error: left argument of `where` operator must be a facet type [WhereOnNonFacetType]
15+
// CHECK:STDERR: fail_left_where_not_facet.carbon:[[@LINE+4]]:10: error: left argument of `where` operator must be a facet type [WhereOnNonFacetType]
1616
// CHECK:STDERR: fn F(T:! i32 where .Self == bool);
1717
// CHECK:STDERR: ^~~
18+
// CHECK:STDERR:
1819
fn F(T:! i32 where .Self == bool);
1920

21+
// --- fail_left_where_unknown.carbon
22+
23+
library "[[@TEST_NAME]]";
24+
25+
// CHECK:STDERR: fail_left_where_unknown.carbon:[[@LINE+8]]:10: error: name `NOT_DECLARED` not found [NameNotFound]
26+
// CHECK:STDERR: fn G(U:! NOT_DECLARED where .Self == bool);
27+
// CHECK:STDERR: ^~~~~~~~~~~~
28+
// CHECK:STDERR:
29+
// CHECK:STDERR: fail_left_where_unknown.carbon:[[@LINE+4]]:10: error: left argument of `where` operator must be a facet type [WhereOnNonFacetType]
30+
// CHECK:STDERR: fn G(U:! NOT_DECLARED where .Self == bool);
31+
// CHECK:STDERR: ^~~~~~~~~~~~
32+
// CHECK:STDERR:
33+
fn G(U:! NOT_DECLARED where .Self == bool);
34+
35+
// --- fail_var.carbon
36+
37+
library "[[@TEST_NAME]]";
38+
39+
// CHECK:STDERR: fail_var.carbon:[[@LINE+7]]:8: error: name `e` not found [NameNotFound]
40+
// CHECK:STDERR: var v: e where .x = 3;
41+
// CHECK:STDERR: ^
42+
// CHECK:STDERR:
43+
// CHECK:STDERR: fail_var.carbon:[[@LINE+3]]:8: error: left argument of `where` operator must be a facet type [WhereOnNonFacetType]
44+
// CHECK:STDERR: var v: e where .x = 3;
45+
// CHECK:STDERR: ^
46+
var v: e where .x = 3;
47+
2048
// CHECK:STDOUT: --- fail_left_where_not_facet.carbon
2149
// CHECK:STDOUT:
2250
// CHECK:STDOUT: constants {
@@ -56,36 +84,137 @@ fn F(T:! i32 where .Self == bool);
5684
// CHECK:STDOUT: }
5785
// CHECK:STDOUT: %Core.import = import Core
5886
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {
59-
// CHECK:STDOUT: %T.patt.loc7_6.1: <error> = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc7_6.2 (constants.%T.patt)]
60-
// CHECK:STDOUT: %T.param_patt: <error> = value_param_pattern %T.patt.loc7_6.1, runtime_param<invalid> [symbolic = %T.patt.loc7_6.2 (constants.%T.patt)]
87+
// CHECK:STDOUT: %T.patt.loc8_6.1: <error> = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc8_6.2 (constants.%T.patt)]
88+
// CHECK:STDOUT: %T.param_patt: <error> = value_param_pattern %T.patt.loc8_6.1, runtime_param<invalid> [symbolic = %T.patt.loc8_6.2 (constants.%T.patt)]
6189
// CHECK:STDOUT: } {
6290
// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32]
63-
// CHECK:STDOUT: %.loc7_10.1: type = value_of_initializer %int.make_type_32 [template = i32]
64-
// CHECK:STDOUT: %.loc7_10.2: type = converted %int.make_type_32, %.loc7_10.1 [template = i32]
91+
// CHECK:STDOUT: %.loc8_10.1: type = value_of_initializer %int.make_type_32 [template = i32]
92+
// CHECK:STDOUT: %.loc8_10.2: type = converted %int.make_type_32, %.loc8_10.1 [template = i32]
6593
// CHECK:STDOUT: %.Self: <error> = bind_symbolic_name .Self, 0 [symbolic = constants.%.Self]
6694
// CHECK:STDOUT: %.Self.ref: <error> = name_ref .Self, %.Self [symbolic = constants.%.Self]
6795
// CHECK:STDOUT: %bool.make_type: init type = call constants.%Bool() [template = bool]
68-
// CHECK:STDOUT: %.loc7_14: type = where_expr %.Self [template = <error>] {
96+
// CHECK:STDOUT: %.loc8_14: type = where_expr %.Self [template = <error>] {
6997
// CHECK:STDOUT: requirement_equivalent %.Self.ref, %bool.make_type
7098
// CHECK:STDOUT: }
7199
// CHECK:STDOUT: %T.param: <error> = value_param runtime_param<invalid>
72-
// CHECK:STDOUT: %T.loc7_6.1: <error> = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc7_6.2 (constants.%T)]
100+
// CHECK:STDOUT: %T.loc8_6.1: <error> = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc8_6.2 (constants.%T)]
73101
// CHECK:STDOUT: }
74102
// CHECK:STDOUT: }
75103
// CHECK:STDOUT:
76104
// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32";
77105
// CHECK:STDOUT:
78106
// CHECK:STDOUT: fn @Bool() -> type = "bool.make_type";
79107
// CHECK:STDOUT:
80-
// CHECK:STDOUT: generic fn @F(%T.loc7_6.1: <error>) {
81-
// CHECK:STDOUT: %T.loc7_6.2: <error> = bind_symbolic_name T, 0 [symbolic = %T.loc7_6.2 (constants.%T)]
82-
// CHECK:STDOUT: %T.patt.loc7_6.2: <error> = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc7_6.2 (constants.%T.patt)]
108+
// CHECK:STDOUT: generic fn @F(%T.loc8_6.1: <error>) {
109+
// CHECK:STDOUT: %T.loc8_6.2: <error> = bind_symbolic_name T, 0 [symbolic = %T.loc8_6.2 (constants.%T)]
110+
// CHECK:STDOUT: %T.patt.loc8_6.2: <error> = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc8_6.2 (constants.%T.patt)]
83111
// CHECK:STDOUT:
84112
// CHECK:STDOUT: fn(%T.param_patt: <error>);
85113
// CHECK:STDOUT: }
86114
// CHECK:STDOUT:
87115
// CHECK:STDOUT: specific @F(constants.%T) {
88-
// CHECK:STDOUT: %T.loc7_6.2 => constants.%T
89-
// CHECK:STDOUT: %T.patt.loc7_6.2 => constants.%T
116+
// CHECK:STDOUT: %T.loc8_6.2 => constants.%T
117+
// CHECK:STDOUT: %T.patt.loc8_6.2 => constants.%T
118+
// CHECK:STDOUT: }
119+
// CHECK:STDOUT:
120+
// CHECK:STDOUT: --- fail_left_where_unknown.carbon
121+
// CHECK:STDOUT:
122+
// CHECK:STDOUT: constants {
123+
// CHECK:STDOUT: %.Self: <error> = bind_symbolic_name .Self, 0 [symbolic]
124+
// CHECK:STDOUT: %Bool.type: type = fn_type @Bool [template]
125+
// CHECK:STDOUT: %.1: type = tuple_type () [template]
126+
// CHECK:STDOUT: %Bool: %Bool.type = struct_value () [template]
127+
// CHECK:STDOUT: %U: <error> = bind_symbolic_name U, 0 [symbolic]
128+
// CHECK:STDOUT: %U.patt: <error> = symbolic_binding_pattern U, 0 [symbolic]
129+
// CHECK:STDOUT: %G.type: type = fn_type @G [template]
130+
// CHECK:STDOUT: %G: %G.type = struct_value () [template]
131+
// CHECK:STDOUT: }
132+
// CHECK:STDOUT:
133+
// CHECK:STDOUT: imports {
134+
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
135+
// CHECK:STDOUT: .Bool = %import_ref
136+
// CHECK:STDOUT: import Core//prelude
137+
// CHECK:STDOUT: import Core//prelude/operators
138+
// CHECK:STDOUT: import Core//prelude/types
139+
// CHECK:STDOUT: import Core//prelude/operators/arithmetic
140+
// CHECK:STDOUT: import Core//prelude/operators/as
141+
// CHECK:STDOUT: import Core//prelude/operators/bitwise
142+
// CHECK:STDOUT: import Core//prelude/operators/comparison
143+
// CHECK:STDOUT: import Core//prelude/types/bool
144+
// CHECK:STDOUT: }
145+
// CHECK:STDOUT: %import_ref: %Bool.type = import_ref Core//prelude/types/bool, inst+5, loaded [template = constants.%Bool]
146+
// CHECK:STDOUT: }
147+
// CHECK:STDOUT:
148+
// CHECK:STDOUT: file {
149+
// CHECK:STDOUT: package: <namespace> = namespace [template] {
150+
// CHECK:STDOUT: .Core = imports.%Core
151+
// CHECK:STDOUT: .G = %G.decl
152+
// CHECK:STDOUT: }
153+
// CHECK:STDOUT: %Core.import = import Core
154+
// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] {
155+
// CHECK:STDOUT: %U.patt.loc12_6.1: <error> = symbolic_binding_pattern U, 0 [symbolic = %U.patt.loc12_6.2 (constants.%U.patt)]
156+
// CHECK:STDOUT: %U.param_patt: <error> = value_param_pattern %U.patt.loc12_6.1, runtime_param<invalid> [symbolic = %U.patt.loc12_6.2 (constants.%U.patt)]
157+
// CHECK:STDOUT: } {
158+
// CHECK:STDOUT: %NOT_DECLARED.ref: <error> = name_ref NOT_DECLARED, <error> [template = <error>]
159+
// CHECK:STDOUT: %.Self: <error> = bind_symbolic_name .Self, 0 [symbolic = constants.%.Self]
160+
// CHECK:STDOUT: %.Self.ref: <error> = name_ref .Self, %.Self [symbolic = constants.%.Self]
161+
// CHECK:STDOUT: %bool.make_type: init type = call constants.%Bool() [template = bool]
162+
// CHECK:STDOUT: %.loc12: type = where_expr %.Self [template = <error>] {
163+
// CHECK:STDOUT: requirement_equivalent %.Self.ref, %bool.make_type
164+
// CHECK:STDOUT: }
165+
// CHECK:STDOUT: %U.param: <error> = value_param runtime_param<invalid>
166+
// CHECK:STDOUT: %U.loc12_6.1: <error> = bind_symbolic_name U, 0, %U.param [symbolic = %U.loc12_6.2 (constants.%U)]
167+
// CHECK:STDOUT: }
168+
// CHECK:STDOUT: }
169+
// CHECK:STDOUT:
170+
// CHECK:STDOUT: fn @Bool() -> type = "bool.make_type";
171+
// CHECK:STDOUT:
172+
// CHECK:STDOUT: generic fn @G(%U.loc12_6.1: <error>) {
173+
// CHECK:STDOUT: %U.loc12_6.2: <error> = bind_symbolic_name U, 0 [symbolic = %U.loc12_6.2 (constants.%U)]
174+
// CHECK:STDOUT: %U.patt.loc12_6.2: <error> = symbolic_binding_pattern U, 0 [symbolic = %U.patt.loc12_6.2 (constants.%U.patt)]
175+
// CHECK:STDOUT:
176+
// CHECK:STDOUT: fn(%U.param_patt: <error>);
177+
// CHECK:STDOUT: }
178+
// CHECK:STDOUT:
179+
// CHECK:STDOUT: specific @G(constants.%U) {
180+
// CHECK:STDOUT: %U.loc12_6.2 => constants.%U
181+
// CHECK:STDOUT: %U.patt.loc12_6.2 => constants.%U
182+
// CHECK:STDOUT: }
183+
// CHECK:STDOUT:
184+
// CHECK:STDOUT: --- fail_var.carbon
185+
// CHECK:STDOUT:
186+
// CHECK:STDOUT: constants {
187+
// CHECK:STDOUT: %.Self: <error> = bind_symbolic_name .Self, 0 [symbolic]
188+
// CHECK:STDOUT: %.1: i32 = int_literal 3 [template]
189+
// CHECK:STDOUT: }
190+
// CHECK:STDOUT:
191+
// CHECK:STDOUT: imports {
192+
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
193+
// CHECK:STDOUT: import Core//prelude
194+
// CHECK:STDOUT: import Core//prelude/operators
195+
// CHECK:STDOUT: import Core//prelude/types
196+
// CHECK:STDOUT: import Core//prelude/operators/arithmetic
197+
// CHECK:STDOUT: import Core//prelude/operators/as
198+
// CHECK:STDOUT: import Core//prelude/operators/bitwise
199+
// CHECK:STDOUT: import Core//prelude/operators/comparison
200+
// CHECK:STDOUT: import Core//prelude/types/bool
201+
// CHECK:STDOUT: }
202+
// CHECK:STDOUT: }
203+
// CHECK:STDOUT:
204+
// CHECK:STDOUT: file {
205+
// CHECK:STDOUT: package: <namespace> = namespace [template] {
206+
// CHECK:STDOUT: .Core = imports.%Core
207+
// CHECK:STDOUT: .v = %v
208+
// CHECK:STDOUT: }
209+
// CHECK:STDOUT: %Core.import = import Core
210+
// CHECK:STDOUT: %e.ref: <error> = name_ref e, <error> [template = <error>]
211+
// CHECK:STDOUT: %.Self: <error> = bind_symbolic_name .Self, 0 [symbolic = constants.%.Self]
212+
// CHECK:STDOUT: %.Self.ref: <error> = name_ref .Self, %.Self [symbolic = constants.%.Self]
213+
// CHECK:STDOUT: %.loc11_21: i32 = int_literal 3 [template = constants.%.1]
214+
// CHECK:STDOUT: %.loc11_10: type = where_expr %.Self [template = <error>] {
215+
// CHECK:STDOUT: requirement_rewrite <error>, <error>
216+
// CHECK:STDOUT: }
217+
// CHECK:STDOUT: %v.var: ref <error> = var v
218+
// CHECK:STDOUT: %v: ref <error> = bind_name v, %v.var
90219
// CHECK:STDOUT: }
91220
// CHECK:STDOUT:

0 commit comments

Comments
 (0)