@@ -88,6 +88,7 @@ struct TopInfo<'tcx> {
88
88
89
89
#[ derive( Copy , Clone ) ]
90
90
struct PatInfo < ' tcx > {
91
+ pinnedness : ast:: Pinnedness ,
91
92
binding_mode : ByRef ,
92
93
max_ref_mutbl : MutblCap ,
93
94
top_info : TopInfo < ' tcx > ,
@@ -302,6 +303,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
302
303
) {
303
304
let top_info = TopInfo { expected, origin_expr, span, hir_id : pat. hir_id } ;
304
305
let pat_info = PatInfo {
306
+ pinnedness : ast:: Pinnedness :: Not ,
305
307
binding_mode : ByRef :: No ,
306
308
max_ref_mutbl : MutblCap :: Mut ,
307
309
top_info,
@@ -400,11 +402,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
400
402
let pat_info = PatInfo { current_depth : old_pat_info. current_depth + 1 , ..old_pat_info } ;
401
403
402
404
match pat. kind {
403
- // Peel off a `&` or `&mut` from the scrutinee type. See the examples in
404
- // `tests/ui/rfcs/rfc-2005-default-binding-mode`.
405
+ // Peel off a `&`, `&mut`, `&pin const` or `&pin mut` from the scrutinee type.
406
+ // See the examples in `tests/ui/rfcs/rfc-2005-default-binding-mode`
407
+ // and `tests/ui/async-await/pin-ergonomics/project-pattern-match`.
405
408
_ if let AdjustMode :: Peel = adjust_mode
406
409
&& pat. default_binding_modes
407
- && let ty:: Ref ( _, inner_ty, inner_mutability) = * expected. kind ( ) =>
410
+ && let Some ( ( _, pinnedness, inner_ty, inner_mutability) ) =
411
+ expected. is_ref_or_pin_ref ( self . tcx ) =>
408
412
{
409
413
debug ! ( "inspecting {:?}" , expected) ;
410
414
@@ -428,6 +432,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
428
432
ByRef :: Yes ( Mutability :: Not ) => Mutability :: Not ,
429
433
} ) ;
430
434
435
+ let pinnedness = pinnedness. max ( pat_info. pinnedness ) ;
436
+
431
437
let mut max_ref_mutbl = pat_info. max_ref_mutbl ;
432
438
if self . downgrade_mut_inside_shared ( ) {
433
439
binding_mode = binding_mode. cap_ref_mutability ( max_ref_mutbl. as_mutbl ( ) ) ;
@@ -438,7 +444,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
438
444
debug ! ( "default binding mode is now {:?}" , binding_mode) ;
439
445
440
446
// Use the old pat info to keep `current_depth` to its old value.
441
- let new_pat_info = PatInfo { binding_mode, max_ref_mutbl, ..old_pat_info } ;
447
+ let new_pat_info =
448
+ PatInfo { pinnedness, binding_mode, max_ref_mutbl, ..old_pat_info } ;
442
449
// Recurse with the new expected type.
443
450
self . check_pat_inner ( pat, opt_path_res, adjust_mode, inner_ty, new_pat_info)
444
451
}
@@ -790,7 +797,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
790
797
expected : Ty < ' tcx > ,
791
798
pat_info : PatInfo < ' tcx > ,
792
799
) -> Ty < ' tcx > {
793
- let PatInfo { binding_mode : def_br, top_info : ti, .. } = pat_info;
800
+ let PatInfo { pinnedness , binding_mode : def_br, top_info : ti, .. } = pat_info;
794
801
795
802
// Determine the binding mode...
796
803
let bm = match user_bind_annot {
@@ -883,6 +890,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
883
890
ByRef :: No => expected, // As above, `T <: typeof(x)` is required, but we use equality, see (note_1).
884
891
} ;
885
892
893
+ // Wrapping the type into `Pin` if the pattern is pinned
894
+ let eq_ty = if pinnedness == ast:: Pinnedness :: Pinned {
895
+ Ty :: new_adt (
896
+ self . tcx ,
897
+ self . tcx . adt_def ( self . tcx . require_lang_item ( hir:: LangItem :: Pin , Some ( pat. span ) ) ) ,
898
+ self . tcx . mk_args ( & [ eq_ty. into ( ) ] ) ,
899
+ )
900
+ } else {
901
+ eq_ty
902
+ } ;
903
+
886
904
// We have a concrete type for the local, so we do not need to taint it and hide follow up errors *using* the local.
887
905
let _ = self . demand_eqtype_pat ( pat. span , eq_ty, local_ty, & ti) ;
888
906
@@ -1386,6 +1404,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1386
1404
for ( i, subpat) in subpats. iter ( ) . enumerate_and_adjust ( variant. fields . len ( ) , ddpos) {
1387
1405
let field = & variant. fields [ FieldIdx :: from_usize ( i) ] ;
1388
1406
let field_ty = self . field_ty ( subpat. span , field, args) ;
1407
+ // If the field is not marked as `#[pin]`, then remove the
1408
+ // pinnedness in `pat_info`.
1409
+ let pinnedness = pat_info. pinnedness . min ( field. pinnedness ) ;
1410
+ let pat_info = PatInfo { pinnedness, ..pat_info } ;
1389
1411
self . check_pat ( subpat, field_ty, pat_info) ;
1390
1412
1391
1413
self . tcx . check_stability (
@@ -1642,11 +1664,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1642
1664
for field in fields {
1643
1665
let span = field. span ;
1644
1666
let ident = tcx. adjust_ident ( field. ident , variant. def_id ) ;
1645
- let field_ty = match used_fields. entry ( ident) {
1667
+ let ( field_ty, pinnedness ) = match used_fields. entry ( ident) {
1646
1668
Occupied ( occupied) => {
1647
1669
let guar = self . error_field_already_bound ( span, field. ident , * occupied. get ( ) ) ;
1648
1670
result = Err ( guar) ;
1649
- Ty :: new_error ( tcx, guar)
1671
+ ( Ty :: new_error ( tcx, guar) , ast :: Pinnedness :: Not )
1650
1672
}
1651
1673
Vacant ( vacant) => {
1652
1674
vacant. insert ( span) ;
@@ -1655,15 +1677,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1655
1677
. map ( |( i, f) | {
1656
1678
self . write_field_index ( field. hir_id , * i) ;
1657
1679
self . tcx . check_stability ( f. did , Some ( field. hir_id ) , span, None ) ;
1658
- self . field_ty ( span, f, args)
1680
+ ( self . field_ty ( span, f, args) , f . pinnedness )
1659
1681
} )
1660
1682
. unwrap_or_else ( || {
1661
1683
inexistent_fields. push ( field) ;
1662
- Ty :: new_misc_error ( tcx)
1684
+ ( Ty :: new_misc_error ( tcx) , ast :: Pinnedness :: Not )
1663
1685
} )
1664
1686
}
1665
1687
} ;
1666
1688
1689
+ // If the field is not marked as `#[pin]`, then remove the
1690
+ // pinnedness in `pat_info`.
1691
+ let pinnedness = pat_info. pinnedness . min ( pinnedness) ;
1692
+ let pat_info = PatInfo { pinnedness, ..pat_info } ;
1667
1693
self . check_pat ( field. pat , field_ty, pat_info) ;
1668
1694
}
1669
1695
0 commit comments