@@ -126,6 +126,18 @@ enum PatBoundCtx {
126
126
/// Each identifier must map to at most one distinct [`Res`].
127
127
type PatternBindings = SmallVec < [ ( PatBoundCtx , FxIndexMap < Ident , Res > ) ; 1 ] > ;
128
128
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
+
129
141
/// Does this the item (from the item rib scope) allow generic parameters?
130
142
#[ derive( Copy , Clone , Debug ) ]
131
143
pub ( crate ) enum HasGenericParams {
@@ -800,7 +812,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc
800
812
bug ! ( "encountered anon const without a manual call to `resolve_anon_const`: {constant:#?}" ) ;
801
813
}
802
814
fn visit_expr ( & mut self , expr : & ' ast Expr ) {
803
- self . resolve_expr ( expr, None ) ;
815
+ self . resolve_expr ( expr, None , IsBindingScope :: InNewRib ) ;
804
816
}
805
817
fn visit_pat ( & mut self , p : & ' ast Pat ) {
806
818
let prev = self . diag_metadata . current_pat ;
@@ -3791,7 +3803,9 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
3791
3803
fn resolve_arm ( & mut self , arm : & ' ast Arm ) {
3792
3804
self . with_rib ( ValueNS , RibKind :: Normal , |this| {
3793
3805
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
+ }
3795
3809
visit_opt ! ( this, visit_expr, & arm. body) ;
3796
3810
} ) ;
3797
3811
}
@@ -3933,7 +3947,9 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
3933
3947
let subpat_bindings = bindings. pop ( ) . unwrap ( ) . 1 ;
3934
3948
self . with_rib ( ValueNS , RibKind :: Normal , |this| {
3935
3949
* 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 ) ;
3937
3953
} ) ;
3938
3954
// Propagate the subpattern's bindings upwards.
3939
3955
// 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> {
4723
4739
. value
4724
4740
. is_potential_trivial_const_arg ( self . r . tcx . features ( ) . min_generic_const_args ( ) ) ;
4725
4741
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 )
4727
4743
} )
4728
4744
}
4729
4745
@@ -4767,12 +4783,17 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
4767
4783
}
4768
4784
4769
4785
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 ) ;
4771
4787
self . visit_ident ( & f. ident ) ;
4772
4788
walk_list ! ( self , visit_attribute, f. attrs. iter( ) ) ;
4773
4789
}
4774
4790
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
+ ) {
4776
4797
// First, record candidate traits for this expression if it could
4777
4798
// result in the invocation of a method call.
4778
4799
@@ -4821,7 +4842,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
4821
4842
ExprKind :: Break ( None , Some ( ref e) ) => {
4822
4843
// We use this instead of `visit::walk_expr` to keep the parent expr around for
4823
4844
// better diagnostics.
4824
- self . resolve_expr ( e, Some ( expr) ) ;
4845
+ self . resolve_expr ( e, Some ( expr) , IsBindingScope :: InNewRib ) ;
4825
4846
}
4826
4847
4827
4848
ExprKind :: Let ( ref pat, ref scrutinee, _, Recovered :: No ) => {
@@ -4847,16 +4868,21 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
4847
4868
}
4848
4869
4849
4870
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.
4852
4871
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
+ }
4854
4880
}
4855
4881
4856
4882
ExprKind :: If ( ref cond, ref then, ref opt_else) => {
4857
4883
self . with_rib ( ValueNS , RibKind :: Normal , |this| {
4858
4884
let old = this. diag_metadata . in_if_condition . replace ( cond) ;
4859
- this. visit_expr ( cond) ;
4885
+ this. resolve_expr ( cond, None , IsBindingScope :: InCurrentRib ) ;
4860
4886
this. diag_metadata . in_if_condition = old;
4861
4887
this. visit_block ( then) ;
4862
4888
} ) ;
@@ -4873,7 +4899,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
4873
4899
self . with_resolved_label ( label, expr. id , |this| {
4874
4900
this. with_rib ( ValueNS , RibKind :: Normal , |this| {
4875
4901
let old = this. diag_metadata . in_if_condition . replace ( cond) ;
4876
- this. visit_expr ( cond) ;
4902
+ this. resolve_expr ( cond, None , IsBindingScope :: InCurrentRib ) ;
4877
4903
this. diag_metadata . in_if_condition = old;
4878
4904
this. visit_block ( block) ;
4879
4905
} )
@@ -4888,22 +4914,42 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
4888
4914
} ) ;
4889
4915
}
4890
4916
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
+
4891
4937
ExprKind :: Block ( ref block, label) => self . resolve_labeled_block ( label, block. id , block) ,
4892
4938
4893
4939
// Equivalent to `visit::walk_expr` + passing some context to children.
4894
4940
ExprKind :: Field ( ref subexpression, _) => {
4895
- self . resolve_expr ( subexpression, Some ( expr) ) ;
4941
+ self . resolve_expr ( subexpression, Some ( expr) , IsBindingScope :: InNewRib ) ;
4896
4942
}
4897
4943
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 ) ;
4899
4945
for arg in args {
4900
- self . resolve_expr ( arg, None ) ;
4946
+ self . resolve_expr ( arg, None , IsBindingScope :: InNewRib ) ;
4901
4947
}
4902
4948
self . visit_path_segment ( seg) ;
4903
4949
}
4904
4950
4905
4951
ExprKind :: Call ( ref callee, ref arguments) => {
4906
- self . resolve_expr ( callee, Some ( expr) ) ;
4952
+ self . resolve_expr ( callee, Some ( expr) , IsBindingScope :: InNewRib ) ;
4907
4953
let const_args = self . r . legacy_const_generic_args ( callee) . unwrap_or_default ( ) ;
4908
4954
for ( idx, argument) in arguments. iter ( ) . enumerate ( ) {
4909
4955
// Constant arguments need to be treated as AnonConst since
@@ -4915,10 +4961,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
4915
4961
self . resolve_anon_const_manual (
4916
4962
is_trivial_const_arg,
4917
4963
AnonConstKind :: ConstArg ( IsRepeatExpr :: No ) ,
4918
- |this| this. resolve_expr ( argument, None ) ,
4964
+ |this| this. visit_expr ( argument) ,
4919
4965
) ;
4920
4966
} else {
4921
- self . resolve_expr ( argument, None ) ;
4967
+ self . visit_expr ( argument) ;
4922
4968
}
4923
4969
}
4924
4970
}
@@ -4951,7 +4997,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
4951
4997
self . resolve_anon_const ( ct, AnonConstKind :: InlineConst ) ;
4952
4998
}
4953
4999
ExprKind :: Index ( ref elem, ref idx, _) => {
4954
- self . resolve_expr ( elem, Some ( expr) ) ;
5000
+ self . resolve_expr ( elem, Some ( expr) , IsBindingScope :: InNewRib ) ;
4955
5001
self . visit_expr ( idx) ;
4956
5002
}
4957
5003
ExprKind :: Assign ( ref lhs, ref rhs, _) => {
@@ -4966,8 +5012,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
4966
5012
}
4967
5013
ExprKind :: Range ( Some ( ref start) , Some ( ref end) , RangeLimits :: HalfOpen ) => {
4968
5014
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 ) ;
4971
5017
self . diag_metadata . in_range = None ;
4972
5018
}
4973
5019
_ => {
0 commit comments