@@ -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;
@@ -1533,95 +1520,6 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
15331520 DeconstructedPat :: new ( ctor, fields, pat. ty , pat. span )
15341521 }
15351522
1536- pub ( crate ) fn to_pat ( & self , cx : & MatchCheckCtxt < ' p , ' tcx > ) -> Pat < ' tcx > {
1537- let is_wildcard = |pat : & Pat < ' _ > | {
1538- matches ! ( pat. kind, PatKind :: Binding { subpattern: None , .. } | PatKind :: Wild )
1539- } ;
1540- let mut subpatterns = self . iter_fields ( ) . map ( |p| Box :: new ( p. to_pat ( cx) ) ) ;
1541- let kind = match & self . ctor {
1542- Single | Variant ( _) => match self . ty . kind ( ) {
1543- ty:: Tuple ( ..) => PatKind :: Leaf {
1544- subpatterns : subpatterns
1545- . enumerate ( )
1546- . map ( |( i, pattern) | FieldPat { field : FieldIdx :: new ( i) , pattern } )
1547- . collect ( ) ,
1548- } ,
1549- ty:: Adt ( adt_def, _) if adt_def. is_box ( ) => {
1550- // Without `box_patterns`, the only legal pattern of type `Box` is `_` (outside
1551- // of `std`). So this branch is only reachable when the feature is enabled and
1552- // the pattern is a box pattern.
1553- PatKind :: Deref { subpattern : subpatterns. next ( ) . unwrap ( ) }
1554- }
1555- ty:: Adt ( adt_def, args) => {
1556- let variant_index = self . ctor . variant_index_for_adt ( * adt_def) ;
1557- let variant = & adt_def. variant ( variant_index) ;
1558- let subpatterns = Fields :: list_variant_nonhidden_fields ( cx, self . ty , variant)
1559- . zip ( subpatterns)
1560- . map ( |( ( field, _ty) , pattern) | FieldPat { field, pattern } )
1561- . collect ( ) ;
1562-
1563- if adt_def. is_enum ( ) {
1564- PatKind :: Variant { adt_def : * adt_def, args, variant_index, subpatterns }
1565- } else {
1566- PatKind :: Leaf { subpatterns }
1567- }
1568- }
1569- // Note: given the expansion of `&str` patterns done in `expand_pattern`, we should
1570- // be careful to reconstruct the correct constant pattern here. However a string
1571- // literal pattern will never be reported as a non-exhaustiveness witness, so we
1572- // ignore this issue.
1573- ty:: Ref ( ..) => PatKind :: Deref { subpattern : subpatterns. next ( ) . unwrap ( ) } ,
1574- _ => bug ! ( "unexpected ctor for type {:?} {:?}" , self . ctor, self . ty) ,
1575- } ,
1576- Slice ( slice) => {
1577- match slice. kind {
1578- FixedLen ( _) => PatKind :: Slice {
1579- prefix : subpatterns. collect ( ) ,
1580- slice : None ,
1581- suffix : Box :: new ( [ ] ) ,
1582- } ,
1583- VarLen ( prefix, _) => {
1584- let mut subpatterns = subpatterns. peekable ( ) ;
1585- let mut prefix: Vec < _ > = subpatterns. by_ref ( ) . take ( prefix) . collect ( ) ;
1586- if slice. array_len . is_some ( ) {
1587- // Improves diagnostics a bit: if the type is a known-size array, instead
1588- // of reporting `[x, _, .., _, y]`, we prefer to report `[x, .., y]`.
1589- // This is incorrect if the size is not known, since `[_, ..]` captures
1590- // arrays of lengths `>= 1` whereas `[..]` captures any length.
1591- while !prefix. is_empty ( ) && is_wildcard ( prefix. last ( ) . unwrap ( ) ) {
1592- prefix. pop ( ) ;
1593- }
1594- while subpatterns. peek ( ) . is_some ( )
1595- && is_wildcard ( subpatterns. peek ( ) . unwrap ( ) )
1596- {
1597- subpatterns. next ( ) ;
1598- }
1599- }
1600- let suffix: Box < [ _ ] > = subpatterns. collect ( ) ;
1601- let wild = Pat :: wildcard_from_ty ( self . ty ) ;
1602- PatKind :: Slice {
1603- prefix : prefix. into_boxed_slice ( ) ,
1604- slice : Some ( Box :: new ( wild) ) ,
1605- suffix,
1606- }
1607- }
1608- }
1609- }
1610- & Str ( value) => PatKind :: Constant { value } ,
1611- IntRange ( range) => return range. to_pat ( cx. tcx , self . ty ) ,
1612- Wildcard | NonExhaustive | Hidden => PatKind :: Wild ,
1613- Missing { .. } => bug ! (
1614- "trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
1615- `Missing` should have been processed in `apply_constructors`"
1616- ) ,
1617- F32Range ( ..) | F64Range ( ..) | Opaque | Or => {
1618- bug ! ( "can't convert to pattern: {:?}" , self )
1619- }
1620- } ;
1621-
1622- Pat { ty : self . ty , span : DUMMY_SP , kind }
1623- }
1624-
16251523 pub ( super ) fn is_or_pat ( & self ) -> bool {
16261524 matches ! ( self . ctor, Or )
16271525 }
@@ -1804,3 +1702,131 @@ impl<'p, 'tcx> fmt::Debug for DeconstructedPat<'p, 'tcx> {
18041702 }
18051703 }
18061704}
1705+
1706+ /// Same idea as `DeconstructedPat`, except this is a fictitious pattern built up for diagnostics
1707+ /// purposes. As such they don't use interning and can be cloned.
1708+ #[ derive( Debug , Clone ) ]
1709+ pub ( crate ) struct WitnessPat < ' tcx > {
1710+ ctor : Constructor < ' tcx > ,
1711+ fields : Vec < WitnessPat < ' tcx > > ,
1712+ ty : Ty < ' tcx > ,
1713+ }
1714+
1715+ impl < ' tcx > WitnessPat < ' tcx > {
1716+ pub ( super ) fn new ( ctor : Constructor < ' tcx > , fields : Vec < Self > , ty : Ty < ' tcx > ) -> Self {
1717+ Self { ctor, fields, ty }
1718+ }
1719+ pub ( super ) fn wildcard ( ty : Ty < ' tcx > ) -> Self {
1720+ Self :: new ( Wildcard , Vec :: new ( ) , ty)
1721+ }
1722+
1723+ /// Construct a pattern that matches everything that starts with this constructor.
1724+ /// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern
1725+ /// `Some(_)`.
1726+ pub ( super ) fn wild_from_ctor ( pcx : & PatCtxt < ' _ , ' _ , ' tcx > , ctor : Constructor < ' tcx > ) -> Self {
1727+ // Reuse `Fields::wildcards` to get the types.
1728+ let fields = Fields :: wildcards ( pcx, & ctor)
1729+ . iter_patterns ( )
1730+ . map ( |deco_pat| Self :: wildcard ( deco_pat. ty ( ) ) )
1731+ . collect ( ) ;
1732+ Self :: new ( ctor, fields, pcx. ty )
1733+ }
1734+
1735+ pub ( super ) fn ctor ( & self ) -> & Constructor < ' tcx > {
1736+ & self . ctor
1737+ }
1738+ pub ( super ) fn ty ( & self ) -> Ty < ' tcx > {
1739+ self . ty
1740+ }
1741+
1742+ pub ( crate ) fn to_pat ( & self , cx : & MatchCheckCtxt < ' _ , ' tcx > ) -> Pat < ' tcx > {
1743+ let is_wildcard = |pat : & Pat < ' _ > | matches ! ( pat. kind, PatKind :: Wild ) ;
1744+ let mut subpatterns = self . iter_fields ( ) . map ( |p| Box :: new ( p. to_pat ( cx) ) ) ;
1745+ let kind = match & self . ctor {
1746+ Single | Variant ( _) => match self . ty . kind ( ) {
1747+ ty:: Tuple ( ..) => PatKind :: Leaf {
1748+ subpatterns : subpatterns
1749+ . enumerate ( )
1750+ . map ( |( i, pattern) | FieldPat { field : FieldIdx :: new ( i) , pattern } )
1751+ . collect ( ) ,
1752+ } ,
1753+ ty:: Adt ( adt_def, _) if adt_def. is_box ( ) => {
1754+ // Without `box_patterns`, the only legal pattern of type `Box` is `_` (outside
1755+ // of `std`). So this branch is only reachable when the feature is enabled and
1756+ // the pattern is a box pattern.
1757+ PatKind :: Deref { subpattern : subpatterns. next ( ) . unwrap ( ) }
1758+ }
1759+ ty:: Adt ( adt_def, args) => {
1760+ let variant_index = self . ctor . variant_index_for_adt ( * adt_def) ;
1761+ let variant = & adt_def. variant ( variant_index) ;
1762+ let subpatterns = Fields :: list_variant_nonhidden_fields ( cx, self . ty , variant)
1763+ . zip ( subpatterns)
1764+ . map ( |( ( field, _ty) , pattern) | FieldPat { field, pattern } )
1765+ . collect ( ) ;
1766+
1767+ if adt_def. is_enum ( ) {
1768+ PatKind :: Variant { adt_def : * adt_def, args, variant_index, subpatterns }
1769+ } else {
1770+ PatKind :: Leaf { subpatterns }
1771+ }
1772+ }
1773+ // Note: given the expansion of `&str` patterns done in `expand_pattern`, we should
1774+ // be careful to reconstruct the correct constant pattern here. However a string
1775+ // literal pattern will never be reported as a non-exhaustiveness witness, so we
1776+ // ignore this issue.
1777+ ty:: Ref ( ..) => PatKind :: Deref { subpattern : subpatterns. next ( ) . unwrap ( ) } ,
1778+ _ => bug ! ( "unexpected ctor for type {:?} {:?}" , self . ctor, self . ty) ,
1779+ } ,
1780+ Slice ( slice) => {
1781+ match slice. kind {
1782+ FixedLen ( _) => PatKind :: Slice {
1783+ prefix : subpatterns. collect ( ) ,
1784+ slice : None ,
1785+ suffix : Box :: new ( [ ] ) ,
1786+ } ,
1787+ VarLen ( prefix, _) => {
1788+ let mut subpatterns = subpatterns. peekable ( ) ;
1789+ let mut prefix: Vec < _ > = subpatterns. by_ref ( ) . take ( prefix) . collect ( ) ;
1790+ if slice. array_len . is_some ( ) {
1791+ // Improves diagnostics a bit: if the type is a known-size array, instead
1792+ // of reporting `[x, _, .., _, y]`, we prefer to report `[x, .., y]`.
1793+ // This is incorrect if the size is not known, since `[_, ..]` captures
1794+ // arrays of lengths `>= 1` whereas `[..]` captures any length.
1795+ while !prefix. is_empty ( ) && is_wildcard ( prefix. last ( ) . unwrap ( ) ) {
1796+ prefix. pop ( ) ;
1797+ }
1798+ while subpatterns. peek ( ) . is_some ( )
1799+ && is_wildcard ( subpatterns. peek ( ) . unwrap ( ) )
1800+ {
1801+ subpatterns. next ( ) ;
1802+ }
1803+ }
1804+ let suffix: Box < [ _ ] > = subpatterns. collect ( ) ;
1805+ let wild = Pat :: wildcard_from_ty ( self . ty ) ;
1806+ PatKind :: Slice {
1807+ prefix : prefix. into_boxed_slice ( ) ,
1808+ slice : Some ( Box :: new ( wild) ) ,
1809+ suffix,
1810+ }
1811+ }
1812+ }
1813+ }
1814+ & Str ( value) => PatKind :: Constant { value } ,
1815+ IntRange ( range) => return range. to_pat ( cx. tcx , self . ty ) ,
1816+ Wildcard | NonExhaustive | Hidden => PatKind :: Wild ,
1817+ Missing { .. } => bug ! (
1818+ "trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
1819+ `Missing` should have been processed in `apply_constructors`"
1820+ ) ,
1821+ F32Range ( ..) | F64Range ( ..) | Opaque | Or => {
1822+ bug ! ( "can't convert to pattern: {:?}" , self )
1823+ }
1824+ } ;
1825+
1826+ Pat { ty : self . ty , span : DUMMY_SP , kind }
1827+ }
1828+
1829+ pub ( super ) fn iter_fields < ' a > ( & ' a self ) -> impl Iterator < Item = & ' a WitnessPat < ' tcx > > {
1830+ self . fields . iter ( )
1831+ }
1832+ }
0 commit comments