@@ -126,6 +126,18 @@ enum PatBoundCtx {
126126/// Each identifier must map to at most one distinct [`Res`].
127127type PatternBindings = SmallVec < [ ( PatBoundCtx , FxIndexMap < Ident , Res > ) ; 1 ] > ;
128128
129+ /// In what scope should `is` expressions introduce bindings? See RFC 3573 for more details.
130+ enum IsBindingScope {
131+ /// `is` expressions at the top-level of an `if` or `while` condition introduce their bindings
132+ /// within the condition's rib, so that they are in scope in the expression's success block.
133+ /// Likewise, within an `&&`-chain outside of an `if` or `while`, `is` expressions' bindings are
134+ /// in scope for the remainder of the `&&`-chain.
135+ InCurrentRib ,
136+ /// Indicates that an `&&` or `is` expression will need to introduce a new rib for `is`
137+ /// expressions' bindings.
138+ InNewRib ,
139+ }
140+
129141/// Does this the item (from the item rib scope) allow generic parameters?
130142#[ derive( Copy , Clone , Debug ) ]
131143pub ( crate ) enum HasGenericParams {
@@ -800,7 +812,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc
800812 bug ! ( "encountered anon const without a manual call to `resolve_anon_const`: {constant:#?}" ) ;
801813 }
802814 fn visit_expr ( & mut self , expr : & ' ast Expr ) {
803- self . resolve_expr ( expr, None ) ;
815+ self . resolve_expr ( expr, None , IsBindingScope :: InNewRib ) ;
804816 }
805817 fn visit_pat ( & mut self , p : & ' ast Pat ) {
806818 let prev = self . diag_metadata . current_pat ;
@@ -3791,7 +3803,9 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
37913803 fn resolve_arm ( & mut self , arm : & ' ast Arm ) {
37923804 self . with_rib ( ValueNS , RibKind :: Normal , |this| {
37933805 this. resolve_pattern_top ( & arm. pat , PatternSource :: Match ) ;
3794- visit_opt ! ( this, visit_expr, & arm. guard) ;
3806+ if let Some ( guard) = & arm. guard {
3807+ this. resolve_expr ( guard, None , IsBindingScope :: InCurrentRib )
3808+ }
37953809 visit_opt ! ( this, visit_expr, & arm. body) ;
37963810 } ) ;
37973811 }
@@ -3933,7 +3947,9 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
39333947 let subpat_bindings = bindings. pop ( ) . unwrap ( ) . 1 ;
39343948 self . with_rib ( ValueNS , RibKind :: Normal , |this| {
39353949 * this. innermost_rib_bindings ( ValueNS ) = subpat_bindings. clone ( ) ;
3936- this. resolve_expr ( guard, None ) ;
3950+ // FIXME(guard_patterns): For `is` guards, we'll want to call `resolve_expr`
3951+ // with `IsBindingScope::InCurrentRib`.
3952+ this. resolve_expr ( guard, None , IsBindingScope :: InNewRib ) ;
39373953 } ) ;
39383954 // Propagate the subpattern's bindings upwards.
39393955 // FIXME(guard_patterns): For `if let` guards, we'll also need to get the
@@ -4723,7 +4739,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
47234739 . value
47244740 . is_potential_trivial_const_arg ( self . r . tcx . features ( ) . min_generic_const_args ( ) ) ;
47254741 self . resolve_anon_const_manual ( is_trivial_const_arg, anon_const_kind, |this| {
4726- this. resolve_expr ( & constant. value , None )
4742+ this. visit_expr ( & constant. value )
47274743 } )
47284744 }
47294745
@@ -4767,12 +4783,17 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
47674783 }
47684784
47694785 fn resolve_expr_field ( & mut self , f : & ' ast ExprField , e : & ' ast Expr ) {
4770- self . resolve_expr ( & f. expr , Some ( e) ) ;
4786+ self . resolve_expr ( & f. expr , Some ( e) , IsBindingScope :: InNewRib ) ;
47714787 self . visit_ident ( & f. ident ) ;
47724788 walk_list ! ( self , visit_attribute, f. attrs. iter( ) ) ;
47734789 }
47744790
4775- fn resolve_expr ( & mut self , expr : & ' ast Expr , parent : Option < & ' ast Expr > ) {
4791+ fn resolve_expr (
4792+ & mut self ,
4793+ expr : & ' ast Expr ,
4794+ parent : Option < & ' ast Expr > ,
4795+ is_binding_scope : IsBindingScope ,
4796+ ) {
47764797 // First, record candidate traits for this expression if it could
47774798 // result in the invocation of a method call.
47784799
@@ -4821,7 +4842,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
48214842 ExprKind :: Break ( None , Some ( ref e) ) => {
48224843 // We use this instead of `visit::walk_expr` to keep the parent expr around for
48234844 // better diagnostics.
4824- self . resolve_expr ( e, Some ( expr) ) ;
4845+ self . resolve_expr ( e, Some ( expr) , IsBindingScope :: InNewRib ) ;
48254846 }
48264847
48274848 ExprKind :: Let ( ref pat, ref scrutinee, _, Recovered :: No ) => {
@@ -4847,16 +4868,21 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
48474868 }
48484869
48494870 ExprKind :: Is ( ref scrutinee, ref pat) => {
4850- // TODO: handle `is` outside of `if`/`while`: we'll need to introduce a new rib for
4851- // the `is`'s `&&`-chain.
48524871 self . visit_expr ( scrutinee) ;
4853- self . resolve_pattern_top ( pat, PatternSource :: Is ) ;
4872+ match is_binding_scope {
4873+ IsBindingScope :: InCurrentRib => {
4874+ self . resolve_pattern_top ( pat, PatternSource :: Is )
4875+ }
4876+ IsBindingScope :: InNewRib => self . with_rib ( ValueNS , RibKind :: Normal , |this| {
4877+ this. resolve_pattern_top ( pat, PatternSource :: Is )
4878+ } ) ,
4879+ }
48544880 }
48554881
48564882 ExprKind :: If ( ref cond, ref then, ref opt_else) => {
48574883 self . with_rib ( ValueNS , RibKind :: Normal , |this| {
48584884 let old = this. diag_metadata . in_if_condition . replace ( cond) ;
4859- this. visit_expr ( cond) ;
4885+ this. resolve_expr ( cond, None , IsBindingScope :: InCurrentRib ) ;
48604886 this. diag_metadata . in_if_condition = old;
48614887 this. visit_block ( then) ;
48624888 } ) ;
@@ -4873,7 +4899,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
48734899 self . with_resolved_label ( label, expr. id , |this| {
48744900 this. with_rib ( ValueNS , RibKind :: Normal , |this| {
48754901 let old = this. diag_metadata . in_if_condition . replace ( cond) ;
4876- this. visit_expr ( cond) ;
4902+ this. resolve_expr ( cond, None , IsBindingScope :: InCurrentRib ) ;
48774903 this. diag_metadata . in_if_condition = old;
48784904 this. visit_block ( block) ;
48794905 } )
@@ -4888,22 +4914,42 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
48884914 } ) ;
48894915 }
48904916
4917+ ExprKind :: Binary ( BinOp { node : BinOpKind :: And , .. } , ref lhs, ref rhs) => {
4918+ match is_binding_scope {
4919+ // At the top level of an `&&`-chain, we introduce a new rib to restrict `is`
4920+ // expressions' bindings' lexical scope to that `&&`-chain.
4921+ IsBindingScope :: InNewRib if lhs. has_expr_is ( ) || rhs. has_expr_is ( ) => self
4922+ . with_rib ( ValueNS , RibKind :: Normal , |this| {
4923+ this. resolve_expr ( lhs, None , IsBindingScope :: InCurrentRib ) ;
4924+ this. resolve_expr ( rhs, None , IsBindingScope :: InCurrentRib ) ;
4925+ } ) ,
4926+ // Inside an `&&`-chain, we use the `&&`-chain's rib.
4927+ // We also avoid introducing a new rib if the `&&`-chain has no `is`
4928+ // expressions, to reduce the number of diagnostics emitted for malformed
4929+ // `let` chains such as `(let x = true) && x`.
4930+ IsBindingScope :: InCurrentRib | IsBindingScope :: InNewRib => {
4931+ self . resolve_expr ( lhs, None , IsBindingScope :: InCurrentRib ) ;
4932+ self . resolve_expr ( rhs, None , IsBindingScope :: InCurrentRib ) ;
4933+ }
4934+ }
4935+ }
4936+
48914937 ExprKind :: Block ( ref block, label) => self . resolve_labeled_block ( label, block. id , block) ,
48924938
48934939 // Equivalent to `visit::walk_expr` + passing some context to children.
48944940 ExprKind :: Field ( ref subexpression, _) => {
4895- self . resolve_expr ( subexpression, Some ( expr) ) ;
4941+ self . resolve_expr ( subexpression, Some ( expr) , IsBindingScope :: InNewRib ) ;
48964942 }
48974943 ExprKind :: MethodCall ( box MethodCall { ref seg, ref receiver, ref args, .. } ) => {
4898- self . resolve_expr ( receiver, Some ( expr) ) ;
4944+ self . resolve_expr ( receiver, Some ( expr) , IsBindingScope :: InNewRib ) ;
48994945 for arg in args {
4900- self . resolve_expr ( arg, None ) ;
4946+ self . resolve_expr ( arg, None , IsBindingScope :: InNewRib ) ;
49014947 }
49024948 self . visit_path_segment ( seg) ;
49034949 }
49044950
49054951 ExprKind :: Call ( ref callee, ref arguments) => {
4906- self . resolve_expr ( callee, Some ( expr) ) ;
4952+ self . resolve_expr ( callee, Some ( expr) , IsBindingScope :: InNewRib ) ;
49074953 let const_args = self . r . legacy_const_generic_args ( callee) . unwrap_or_default ( ) ;
49084954 for ( idx, argument) in arguments. iter ( ) . enumerate ( ) {
49094955 // Constant arguments need to be treated as AnonConst since
@@ -4915,10 +4961,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
49154961 self . resolve_anon_const_manual (
49164962 is_trivial_const_arg,
49174963 AnonConstKind :: ConstArg ( IsRepeatExpr :: No ) ,
4918- |this| this. resolve_expr ( argument, None ) ,
4964+ |this| this. visit_expr ( argument) ,
49194965 ) ;
49204966 } else {
4921- self . resolve_expr ( argument, None ) ;
4967+ self . visit_expr ( argument) ;
49224968 }
49234969 }
49244970 }
@@ -4951,7 +4997,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
49514997 self . resolve_anon_const ( ct, AnonConstKind :: InlineConst ) ;
49524998 }
49534999 ExprKind :: Index ( ref elem, ref idx, _) => {
4954- self . resolve_expr ( elem, Some ( expr) ) ;
5000+ self . resolve_expr ( elem, Some ( expr) , IsBindingScope :: InNewRib ) ;
49555001 self . visit_expr ( idx) ;
49565002 }
49575003 ExprKind :: Assign ( ref lhs, ref rhs, _) => {
@@ -4966,8 +5012,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
49665012 }
49675013 ExprKind :: Range ( Some ( ref start) , Some ( ref end) , RangeLimits :: HalfOpen ) => {
49685014 self . diag_metadata . in_range = Some ( ( start, end) ) ;
4969- self . resolve_expr ( start, Some ( expr) ) ;
4970- self . resolve_expr ( end, Some ( expr) ) ;
5015+ self . resolve_expr ( start, Some ( expr) , IsBindingScope :: InNewRib ) ;
5016+ self . resolve_expr ( end, Some ( expr) , IsBindingScope :: InNewRib ) ;
49715017 self . diag_metadata . in_range = None ;
49725018 }
49735019 _ => {
0 commit comments