@@ -48,10 +48,13 @@ class MatchContext {
48
48
SemIR::InstId pattern_id;
49
49
// `None` when processing the callee side.
50
50
SemIR::InstId scrutinee_id;
51
+ // Whether we are in a context where plain bindings are reference bindings.
52
+ // This happens in var patterns.
53
+ bool ref_binding_context;
51
54
52
55
auto Print (llvm::raw_ostream& out) const -> void {
53
56
out << " {pattern_id: " << pattern_id << " , scrutinee_id: " << scrutinee_id
54
- << " }" ;
57
+ << " , ref_binding_context: " << ref_binding_context << " }" ;
55
58
}
56
59
};
57
60
@@ -224,10 +227,18 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
224
227
InsertHere (context, type_expr_region_id);
225
228
auto value_id = SemIR::InstId::None;
226
229
if (kind_ == MatchKind::Local) {
230
+ auto conversion_kind = entry.ref_binding_context
231
+ ? ConversionTarget::DurableRef
232
+ : ConversionTarget::Value;
233
+ if (!bind_name_id.has_value ()) {
234
+ // TODO: Is this appropriate, or should we perform a conversion based on
235
+ // whether the `_` binding is a value or ref binding first, and then
236
+ // separately discard the initializer for a `_` binding?
237
+ conversion_kind = ConversionTarget::Discarded;
238
+ }
227
239
value_id =
228
240
Convert (context, SemIR::LocId (entry.scrutinee_id ), entry.scrutinee_id ,
229
- {.kind = bind_name_id.has_value () ? ConversionTarget::ValueOrRef
230
- : ConversionTarget::Discarded,
241
+ {.kind = conversion_kind,
231
242
.type_id = context.insts ().Get (bind_name_id).type_id ()});
232
243
} else {
233
244
// In a function call, conversion is handled while matching the enclosing
@@ -253,7 +264,8 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
253
264
// the caller side of the pattern, so we traverse without emitting any
254
265
// insts.
255
266
AddWork ({.pattern_id = addr_pattern.inner_id ,
256
- .scrutinee_id = SemIR::InstId::None});
267
+ .scrutinee_id = SemIR::InstId::None,
268
+ .ref_binding_context = false });
257
269
return ;
258
270
}
259
271
CARBON_CHECK (entry.scrutinee_id .has_value ());
@@ -279,13 +291,16 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
279
291
context, SemIR::LocId (scrutinee_ref_id),
280
292
{.type_id = GetPointerType (context, scrutinee_ref_type_inst_id),
281
293
.lvalue_id = scrutinee_ref_id});
282
- AddWork ({.pattern_id = addr_pattern.inner_id , .scrutinee_id = new_scrutinee});
294
+ AddWork ({.pattern_id = addr_pattern.inner_id ,
295
+ .scrutinee_id = new_scrutinee,
296
+ .ref_binding_context = false });
283
297
}
284
298
285
299
auto MatchContext::DoEmitPatternMatch (Context& context,
286
300
SemIR::ValueParamPattern param_pattern,
287
301
SemIR::InstId pattern_inst_id,
288
302
WorkItem entry) -> void {
303
+ CARBON_CHECK (!entry.ref_binding_context );
289
304
switch (kind_) {
290
305
case MatchKind::Caller: {
291
306
CARBON_CHECK (
@@ -320,7 +335,8 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
320
335
.pretty_name_id = SemIR::GetPrettyNameFromPatternId (
321
336
context.sem_ir (), entry.pattern_id )});
322
337
AddWork ({.pattern_id = param_pattern.subpattern_id ,
323
- .scrutinee_id = param_id});
338
+ .scrutinee_id = param_id,
339
+ .ref_binding_context = entry.ref_binding_context });
324
340
results_.push_back (param_id);
325
341
break ;
326
342
}
@@ -334,6 +350,7 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
334
350
SemIR::RefParamPattern param_pattern,
335
351
SemIR::InstId pattern_inst_id,
336
352
WorkItem entry) -> void {
353
+ CARBON_CHECK (entry.ref_binding_context );
337
354
switch (kind_) {
338
355
case MatchKind::Caller: {
339
356
CARBON_CHECK (
@@ -362,7 +379,8 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
362
379
.pretty_name_id = SemIR::GetPrettyNameFromPatternId (
363
380
context.sem_ir (), entry.pattern_id )});
364
381
AddWork ({.pattern_id = param_pattern.subpattern_id ,
365
- .scrutinee_id = param_id});
382
+ .scrutinee_id = param_id,
383
+ .ref_binding_context = entry.ref_binding_context });
366
384
results_.push_back (param_id);
367
385
break ;
368
386
}
@@ -376,6 +394,7 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
376
394
SemIR::OutParamPattern param_pattern,
377
395
SemIR::InstId pattern_inst_id,
378
396
WorkItem entry) -> void {
397
+ CARBON_CHECK (!entry.ref_binding_context );
379
398
switch (kind_) {
380
399
case MatchKind::Caller: {
381
400
CARBON_CHECK (
@@ -408,7 +427,8 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
408
427
.pretty_name_id = SemIR::GetPrettyNameFromPatternId (
409
428
context.sem_ir (), entry.pattern_id )});
410
429
AddWork ({.pattern_id = param_pattern.subpattern_id ,
411
- .scrutinee_id = param_id});
430
+ .scrutinee_id = param_id,
431
+ .ref_binding_context = entry.ref_binding_context });
412
432
results_.push_back (param_id);
413
433
break ;
414
434
}
@@ -447,7 +467,8 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
447
467
// the caller side of the pattern, so we traverse without emitting any
448
468
// insts.
449
469
AddWork ({.pattern_id = var_pattern.subpattern_id ,
450
- .scrutinee_id = SemIR::InstId::None});
470
+ .scrutinee_id = SemIR::InstId::None,
471
+ .ref_binding_context = true });
451
472
return ;
452
473
}
453
474
case MatchKind::Local: {
@@ -481,8 +502,9 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
481
502
AddInst<SemIR::Assign>(context, SemIR::LocId (pattern_inst_id),
482
503
{.lhs_id = storage_id, .rhs_id = init_id});
483
504
}
484
- AddWork (
485
- {.pattern_id = var_pattern.subpattern_id , .scrutinee_id = storage_id});
505
+ AddWork ({.pattern_id = var_pattern.subpattern_id ,
506
+ .scrutinee_id = storage_id,
507
+ .ref_binding_context = true });
486
508
if (context.scope_stack ().PeekIndex () == ScopeIndex::Package) {
487
509
context.global_init ().Suspend ();
488
510
}
@@ -500,8 +522,9 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
500
522
[&](llvm::ArrayRef<SemIR::InstId> subscrutinee_ids) {
501
523
for (auto [subpattern_id, subscrutinee_id] :
502
524
llvm::reverse (llvm::zip (subpattern_ids, subscrutinee_ids))) {
503
- AddWork (
504
- {.pattern_id = subpattern_id, .scrutinee_id = subscrutinee_id});
525
+ AddWork ({.pattern_id = subpattern_id,
526
+ .scrutinee_id = subscrutinee_id,
527
+ .ref_binding_context = entry.ref_binding_context });
505
528
}
506
529
};
507
530
if (!entry.scrutinee_id .has_value ()) {
@@ -627,22 +650,25 @@ auto CalleePatternMatch(Context& context,
627
650
// in the original order.
628
651
if (return_slot_pattern_id.has_value ()) {
629
652
match.AddWork ({.pattern_id = return_slot_pattern_id,
630
- .scrutinee_id = SemIR::InstId::None});
653
+ .scrutinee_id = SemIR::InstId::None,
654
+ .ref_binding_context = false });
631
655
}
632
656
633
657
if (param_patterns_id.has_value ()) {
634
658
for (SemIR::InstId inst_id :
635
659
llvm::reverse (context.inst_blocks ().Get (param_patterns_id))) {
636
- match.AddWork (
637
- {.pattern_id = inst_id, .scrutinee_id = SemIR::InstId::None});
660
+ match.AddWork ({.pattern_id = inst_id,
661
+ .scrutinee_id = SemIR::InstId::None,
662
+ .ref_binding_context = false });
638
663
}
639
664
}
640
665
641
666
if (implicit_param_patterns_id.has_value ()) {
642
667
for (SemIR::InstId inst_id :
643
668
llvm::reverse (context.inst_blocks ().Get (implicit_param_patterns_id))) {
644
- match.AddWork (
645
- {.pattern_id = inst_id, .scrutinee_id = SemIR::InstId::None});
669
+ match.AddWork ({.pattern_id = inst_id,
670
+ .scrutinee_id = SemIR::InstId::None,
671
+ .ref_binding_context = false });
646
672
}
647
673
}
648
674
@@ -663,17 +689,22 @@ auto CallerPatternMatch(Context& context, SemIR::SpecificId specific_id,
663
689
if (return_slot_arg_id.has_value ()) {
664
690
CARBON_CHECK (return_slot_pattern_id.has_value ());
665
691
match.AddWork ({.pattern_id = return_slot_pattern_id,
666
- .scrutinee_id = return_slot_arg_id});
692
+ .scrutinee_id = return_slot_arg_id,
693
+ .ref_binding_context = false });
667
694
}
668
695
669
696
// Check type conversions per-element.
670
697
for (auto [arg_id, param_pattern_id] : llvm::reverse (llvm::zip_equal (
671
698
arg_refs, context.inst_blocks ().GetOrEmpty (param_patterns_id)))) {
672
- match.AddWork ({.pattern_id = param_pattern_id, .scrutinee_id = arg_id});
699
+ match.AddWork ({.pattern_id = param_pattern_id,
700
+ .scrutinee_id = arg_id,
701
+ .ref_binding_context = false });
673
702
}
674
703
675
704
if (self_pattern_id.has_value ()) {
676
- match.AddWork ({.pattern_id = self_pattern_id, .scrutinee_id = self_arg_id});
705
+ match.AddWork ({.pattern_id = self_pattern_id,
706
+ .scrutinee_id = self_arg_id,
707
+ .ref_binding_context = false });
677
708
}
678
709
679
710
return match.DoWork (context);
@@ -682,7 +713,9 @@ auto CallerPatternMatch(Context& context, SemIR::SpecificId specific_id,
682
713
auto LocalPatternMatch (Context& context, SemIR::InstId pattern_id,
683
714
SemIR::InstId scrutinee_id) -> void {
684
715
MatchContext match (MatchKind::Local);
685
- match.AddWork ({.pattern_id = pattern_id, .scrutinee_id = scrutinee_id});
716
+ match.AddWork ({.pattern_id = pattern_id,
717
+ .scrutinee_id = scrutinee_id,
718
+ .ref_binding_context = false });
686
719
match.DoWork (context);
687
720
}
688
721
0 commit comments