@@ -1613,8 +1613,10 @@ pub enum StatementKind<'tcx> {
16131613 Assign ( Place < ' tcx > , Rvalue < ' tcx > ) ,
16141614
16151615 /// This represents all the reading that a pattern match may do
1616- /// (e.g. inspecting constants and discriminant values).
1617- ReadForMatch ( Place < ' tcx > ) ,
1616+ /// (e.g. inspecting constants and discriminant values), and the
1617+ /// kind of pattern it comes from. This is in order to adapt potential
1618+ /// error messages to these specific patterns.
1619+ FakeRead ( FakeReadCause , Place < ' tcx > ) ,
16181620
16191621 /// Write the discriminant for a variant to the enum Place.
16201622 SetDiscriminant {
@@ -1662,6 +1664,31 @@ pub enum StatementKind<'tcx> {
16621664 Nop ,
16631665}
16641666
1667+ /// The `FakeReadCause` describes the type of pattern why a `FakeRead` statement exists.
1668+ #[ derive( Copy , Clone , RustcEncodable , RustcDecodable , Debug ) ]
1669+ pub enum FakeReadCause {
1670+ /// Inject a fake read of the borrowed input at the start of each arm's
1671+ /// pattern testing code.
1672+ ///
1673+ /// This should ensure that you cannot change the variant for an enum
1674+ /// while you are in the midst of matching on it.
1675+ ForMatch ,
1676+
1677+ /// Officially, the semantics of
1678+ ///
1679+ /// `let pattern = <expr>;`
1680+ ///
1681+ /// is that `<expr>` is evaluated into a temporary and then this temporary is
1682+ /// into the pattern.
1683+ ///
1684+ /// However, if we see the simple pattern `let var = <expr>`, we optimize this to
1685+ /// evaluate `<expr>` directly into the variable `var`. This is mostly unobservable,
1686+ /// but in some cases it can affect the borrow checker, as in #53695.
1687+ /// Therefore, we insert a "fake read" here to ensure that we get
1688+ /// appropriate errors.
1689+ ForLet ,
1690+ }
1691+
16651692/// The `ValidationOp` describes what happens with each of the operands of a
16661693/// `Validate` statement.
16671694#[ derive( Copy , Clone , RustcEncodable , RustcDecodable , PartialEq , Eq ) ]
@@ -1718,7 +1745,7 @@ impl<'tcx> Debug for Statement<'tcx> {
17181745 use self :: StatementKind :: * ;
17191746 match self . kind {
17201747 Assign ( ref place, ref rv) => write ! ( fmt, "{:?} = {:?}" , place, rv) ,
1721- ReadForMatch ( ref place) => write ! ( fmt, "ReadForMatch ({:?})" , place) ,
1748+ FakeRead ( ref cause , ref place) => write ! ( fmt, "FakeRead ({:?}, {:?})" , cause , place) ,
17221749 // (reuse lifetime rendering policy from ppaux.)
17231750 EndRegion ( ref ce) => write ! ( fmt, "EndRegion({})" , ty:: ReScope ( * ce) ) ,
17241751 Validate ( ref op, ref places) => write ! ( fmt, "Validate({:?}, {:?})" , op, places) ,
@@ -2585,6 +2612,7 @@ CloneTypeFoldableAndLiftImpls! {
25852612 Mutability ,
25862613 SourceInfo ,
25872614 UpvarDecl ,
2615+ FakeReadCause ,
25882616 ValidationOp ,
25892617 SourceScope ,
25902618 SourceScopeData ,
@@ -2651,7 +2679,7 @@ BraceStructTypeFoldableImpl! {
26512679EnumTypeFoldableImpl ! {
26522680 impl <' tcx> TypeFoldable <' tcx> for StatementKind <' tcx> {
26532681 ( StatementKind :: Assign ) ( a, b) ,
2654- ( StatementKind :: ReadForMatch ) ( place) ,
2682+ ( StatementKind :: FakeRead ) ( cause , place) ,
26552683 ( StatementKind :: SetDiscriminant ) { place, variant_index } ,
26562684 ( StatementKind :: StorageLive ) ( a) ,
26572685 ( StatementKind :: StorageDead ) ( a) ,
0 commit comments