@@ -1312,9 +1312,10 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
13121312
13131313/// Values and patterns can be represented as a constructor applied to some fields. This represents
13141314/// a pattern in this form.
1315- /// This also keeps track of whether the pattern has been found reachable during analysis. For this
1316- /// reason we should be careful not to clone patterns for which we care about that. Use
1317- /// `clone_and_forget_reachability` if you're sure.
1315+ /// This also uses interior mutability to keep track of whether the pattern has been found reachable
1316+ /// during analysis. For this reason they cannot be cloned.
1317+ /// A `DeconstructedPat` will almost always come from user input; the only exception are some
1318+ /// `Wildcard`s introduced during specialization.
13181319pub ( crate ) struct DeconstructedPat < ' p , ' tcx > {
13191320 ctor : Constructor < ' tcx > ,
13201321 fields : Fields < ' p , ' tcx > ,
@@ -1337,20 +1338,6 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
13371338 DeconstructedPat { ctor, fields, ty, span, reachable : Cell :: new ( false ) }
13381339 }
13391340
1340- /// Construct a pattern that matches everything that starts with this constructor.
1341- /// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern
1342- /// `Some(_)`.
1343- pub ( super ) fn wild_from_ctor ( pcx : & PatCtxt < ' _ , ' p , ' tcx > , ctor : Constructor < ' tcx > ) -> Self {
1344- let fields = Fields :: wildcards ( pcx, & ctor) ;
1345- DeconstructedPat :: new ( ctor, fields, pcx. ty , pcx. span )
1346- }
1347-
1348- /// Clone this value. This method emphasizes that cloning loses reachability information and
1349- /// should be done carefully.
1350- pub ( super ) fn clone_and_forget_reachability ( & self ) -> Self {
1351- DeconstructedPat :: new ( self . ctor . clone ( ) , self . fields , self . ty , self . span )
1352- }
1353-
13541341 pub ( crate ) fn from_pat ( cx : & MatchCheckCtxt < ' p , ' tcx > , pat : & Pat < ' tcx > ) -> Self {
13551342 let mkpat = |pat| DeconstructedPat :: from_pat ( cx, pat) ;
13561343 let ctor;
@@ -1529,95 +1516,6 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
15291516 DeconstructedPat :: new ( ctor, fields, pat. ty , pat. span )
15301517 }
15311518
1532- pub ( crate ) fn to_pat ( & self , cx : & MatchCheckCtxt < ' p , ' tcx > ) -> Pat < ' tcx > {
1533- let is_wildcard = |pat : & Pat < ' _ > | {
1534- matches ! ( pat. kind, PatKind :: Binding { subpattern: None , .. } | PatKind :: Wild )
1535- } ;
1536- let mut subpatterns = self . iter_fields ( ) . map ( |p| Box :: new ( p. to_pat ( cx) ) ) ;
1537- let kind = match & self . ctor {
1538- Single | Variant ( _) => match self . ty . kind ( ) {
1539- ty:: Tuple ( ..) => PatKind :: Leaf {
1540- subpatterns : subpatterns
1541- . enumerate ( )
1542- . map ( |( i, pattern) | FieldPat { field : FieldIdx :: new ( i) , pattern } )
1543- . collect ( ) ,
1544- } ,
1545- ty:: Adt ( adt_def, _) if adt_def. is_box ( ) => {
1546- // Without `box_patterns`, the only legal pattern of type `Box` is `_` (outside
1547- // of `std`). So this branch is only reachable when the feature is enabled and
1548- // the pattern is a box pattern.
1549- PatKind :: Deref { subpattern : subpatterns. next ( ) . unwrap ( ) }
1550- }
1551- ty:: Adt ( adt_def, args) => {
1552- let variant_index = self . ctor . variant_index_for_adt ( * adt_def) ;
1553- let variant = & adt_def. variant ( variant_index) ;
1554- let subpatterns = Fields :: list_variant_nonhidden_fields ( cx, self . ty , variant)
1555- . zip ( subpatterns)
1556- . map ( |( ( field, _ty) , pattern) | FieldPat { field, pattern } )
1557- . collect ( ) ;
1558-
1559- if adt_def. is_enum ( ) {
1560- PatKind :: Variant { adt_def : * adt_def, args, variant_index, subpatterns }
1561- } else {
1562- PatKind :: Leaf { subpatterns }
1563- }
1564- }
1565- // Note: given the expansion of `&str` patterns done in `expand_pattern`, we should
1566- // be careful to reconstruct the correct constant pattern here. However a string
1567- // literal pattern will never be reported as a non-exhaustiveness witness, so we
1568- // ignore this issue.
1569- ty:: Ref ( ..) => PatKind :: Deref { subpattern : subpatterns. next ( ) . unwrap ( ) } ,
1570- _ => bug ! ( "unexpected ctor for type {:?} {:?}" , self . ctor, self . ty) ,
1571- } ,
1572- Slice ( slice) => {
1573- match slice. kind {
1574- FixedLen ( _) => PatKind :: Slice {
1575- prefix : subpatterns. collect ( ) ,
1576- slice : None ,
1577- suffix : Box :: new ( [ ] ) ,
1578- } ,
1579- VarLen ( prefix, _) => {
1580- let mut subpatterns = subpatterns. peekable ( ) ;
1581- let mut prefix: Vec < _ > = subpatterns. by_ref ( ) . take ( prefix) . collect ( ) ;
1582- if slice. array_len . is_some ( ) {
1583- // Improves diagnostics a bit: if the type is a known-size array, instead
1584- // of reporting `[x, _, .., _, y]`, we prefer to report `[x, .., y]`.
1585- // This is incorrect if the size is not known, since `[_, ..]` captures
1586- // arrays of lengths `>= 1` whereas `[..]` captures any length.
1587- while !prefix. is_empty ( ) && is_wildcard ( prefix. last ( ) . unwrap ( ) ) {
1588- prefix. pop ( ) ;
1589- }
1590- while subpatterns. peek ( ) . is_some ( )
1591- && is_wildcard ( subpatterns. peek ( ) . unwrap ( ) )
1592- {
1593- subpatterns. next ( ) ;
1594- }
1595- }
1596- let suffix: Box < [ _ ] > = subpatterns. collect ( ) ;
1597- let wild = Pat :: wildcard_from_ty ( self . ty ) ;
1598- PatKind :: Slice {
1599- prefix : prefix. into_boxed_slice ( ) ,
1600- slice : Some ( Box :: new ( wild) ) ,
1601- suffix,
1602- }
1603- }
1604- }
1605- }
1606- & Str ( value) => PatKind :: Constant { value } ,
1607- IntRange ( range) => return range. to_pat ( cx. tcx , self . ty ) ,
1608- Wildcard | NonExhaustive | Hidden => PatKind :: Wild ,
1609- Missing { .. } => bug ! (
1610- "trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
1611- `Missing` should have been processed in `apply_constructors`"
1612- ) ,
1613- F32Range ( ..) | F64Range ( ..) | Opaque | Or => {
1614- bug ! ( "can't convert to pattern: {:?}" , self )
1615- }
1616- } ;
1617-
1618- Pat { ty : self . ty , span : DUMMY_SP , kind }
1619- }
1620-
16211519 pub ( super ) fn is_or_pat ( & self ) -> bool {
16221520 matches ! ( self . ctor, Or )
16231521 }
@@ -1800,3 +1698,131 @@ impl<'p, 'tcx> fmt::Debug for DeconstructedPat<'p, 'tcx> {
18001698 }
18011699 }
18021700}
1701+
1702+ /// Same idea as `DeconstructedPat`, except this is a fictitious pattern built up for diagnostics
1703+ /// purposes. As such they don't use interning and can be cloned.
1704+ #[ derive( Debug , Clone ) ]
1705+ pub ( crate ) struct WitnessPat < ' tcx > {
1706+ ctor : Constructor < ' tcx > ,
1707+ fields : Vec < WitnessPat < ' tcx > > ,
1708+ ty : Ty < ' tcx > ,
1709+ }
1710+
1711+ impl < ' tcx > WitnessPat < ' tcx > {
1712+ pub ( super ) fn new ( ctor : Constructor < ' tcx > , fields : Vec < Self > , ty : Ty < ' tcx > ) -> Self {
1713+ Self { ctor, fields, ty }
1714+ }
1715+ pub ( super ) fn wildcard ( ty : Ty < ' tcx > ) -> Self {
1716+ Self :: new ( Wildcard , Vec :: new ( ) , ty)
1717+ }
1718+
1719+ /// Construct a pattern that matches everything that starts with this constructor.
1720+ /// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern
1721+ /// `Some(_)`.
1722+ pub ( super ) fn wild_from_ctor ( pcx : & PatCtxt < ' _ , ' _ , ' tcx > , ctor : Constructor < ' tcx > ) -> Self {
1723+ // Reuse `Fields::wildcards` to get the types.
1724+ let fields = Fields :: wildcards ( pcx, & ctor)
1725+ . iter_patterns ( )
1726+ . map ( |deco_pat| Self :: wildcard ( deco_pat. ty ( ) ) )
1727+ . collect ( ) ;
1728+ Self :: new ( ctor, fields, pcx. ty )
1729+ }
1730+
1731+ pub ( super ) fn ctor ( & self ) -> & Constructor < ' tcx > {
1732+ & self . ctor
1733+ }
1734+ pub ( super ) fn ty ( & self ) -> Ty < ' tcx > {
1735+ self . ty
1736+ }
1737+
1738+ pub ( crate ) fn to_pat ( & self , cx : & MatchCheckCtxt < ' _ , ' tcx > ) -> Pat < ' tcx > {
1739+ let is_wildcard = |pat : & Pat < ' _ > | matches ! ( pat. kind, PatKind :: Wild ) ;
1740+ let mut subpatterns = self . iter_fields ( ) . map ( |p| Box :: new ( p. to_pat ( cx) ) ) ;
1741+ let kind = match & self . ctor {
1742+ Single | Variant ( _) => match self . ty . kind ( ) {
1743+ ty:: Tuple ( ..) => PatKind :: Leaf {
1744+ subpatterns : subpatterns
1745+ . enumerate ( )
1746+ . map ( |( i, pattern) | FieldPat { field : FieldIdx :: new ( i) , pattern } )
1747+ . collect ( ) ,
1748+ } ,
1749+ ty:: Adt ( adt_def, _) if adt_def. is_box ( ) => {
1750+ // Without `box_patterns`, the only legal pattern of type `Box` is `_` (outside
1751+ // of `std`). So this branch is only reachable when the feature is enabled and
1752+ // the pattern is a box pattern.
1753+ PatKind :: Deref { subpattern : subpatterns. next ( ) . unwrap ( ) }
1754+ }
1755+ ty:: Adt ( adt_def, args) => {
1756+ let variant_index = self . ctor . variant_index_for_adt ( * adt_def) ;
1757+ let variant = & adt_def. variant ( variant_index) ;
1758+ let subpatterns = Fields :: list_variant_nonhidden_fields ( cx, self . ty , variant)
1759+ . zip ( subpatterns)
1760+ . map ( |( ( field, _ty) , pattern) | FieldPat { field, pattern } )
1761+ . collect ( ) ;
1762+
1763+ if adt_def. is_enum ( ) {
1764+ PatKind :: Variant { adt_def : * adt_def, args, variant_index, subpatterns }
1765+ } else {
1766+ PatKind :: Leaf { subpatterns }
1767+ }
1768+ }
1769+ // Note: given the expansion of `&str` patterns done in `expand_pattern`, we should
1770+ // be careful to reconstruct the correct constant pattern here. However a string
1771+ // literal pattern will never be reported as a non-exhaustiveness witness, so we
1772+ // ignore this issue.
1773+ ty:: Ref ( ..) => PatKind :: Deref { subpattern : subpatterns. next ( ) . unwrap ( ) } ,
1774+ _ => bug ! ( "unexpected ctor for type {:?} {:?}" , self . ctor, self . ty) ,
1775+ } ,
1776+ Slice ( slice) => {
1777+ match slice. kind {
1778+ FixedLen ( _) => PatKind :: Slice {
1779+ prefix : subpatterns. collect ( ) ,
1780+ slice : None ,
1781+ suffix : Box :: new ( [ ] ) ,
1782+ } ,
1783+ VarLen ( prefix, _) => {
1784+ let mut subpatterns = subpatterns. peekable ( ) ;
1785+ let mut prefix: Vec < _ > = subpatterns. by_ref ( ) . take ( prefix) . collect ( ) ;
1786+ if slice. array_len . is_some ( ) {
1787+ // Improves diagnostics a bit: if the type is a known-size array, instead
1788+ // of reporting `[x, _, .., _, y]`, we prefer to report `[x, .., y]`.
1789+ // This is incorrect if the size is not known, since `[_, ..]` captures
1790+ // arrays of lengths `>= 1` whereas `[..]` captures any length.
1791+ while !prefix. is_empty ( ) && is_wildcard ( prefix. last ( ) . unwrap ( ) ) {
1792+ prefix. pop ( ) ;
1793+ }
1794+ while subpatterns. peek ( ) . is_some ( )
1795+ && is_wildcard ( subpatterns. peek ( ) . unwrap ( ) )
1796+ {
1797+ subpatterns. next ( ) ;
1798+ }
1799+ }
1800+ let suffix: Box < [ _ ] > = subpatterns. collect ( ) ;
1801+ let wild = Pat :: wildcard_from_ty ( self . ty ) ;
1802+ PatKind :: Slice {
1803+ prefix : prefix. into_boxed_slice ( ) ,
1804+ slice : Some ( Box :: new ( wild) ) ,
1805+ suffix,
1806+ }
1807+ }
1808+ }
1809+ }
1810+ & Str ( value) => PatKind :: Constant { value } ,
1811+ IntRange ( range) => return range. to_pat ( cx. tcx , self . ty ) ,
1812+ Wildcard | NonExhaustive | Hidden => PatKind :: Wild ,
1813+ Missing { .. } => bug ! (
1814+ "trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
1815+ `Missing` should have been processed in `apply_constructors`"
1816+ ) ,
1817+ F32Range ( ..) | F64Range ( ..) | Opaque | Or => {
1818+ bug ! ( "can't convert to pattern: {:?}" , self )
1819+ }
1820+ } ;
1821+
1822+ Pat { ty : self . ty , span : DUMMY_SP , kind }
1823+ }
1824+
1825+ pub ( super ) fn iter_fields < ' a > ( & ' a self ) -> impl Iterator < Item = & ' a WitnessPat < ' tcx > > {
1826+ self . fields . iter ( )
1827+ }
1828+ }
0 commit comments