1
1
#![ feature( array_chunks) ]
2
2
#![ feature( box_patterns) ]
3
3
#![ feature( control_flow_enum) ]
4
+ #![ feature( exhaustive_patterns) ]
4
5
#![ feature( if_let_guard) ]
5
6
#![ feature( let_chains) ]
6
7
#![ feature( lint_reasons) ]
@@ -2618,13 +2619,80 @@ pub enum DefinedTy<'tcx> {
2618
2619
/// The context an expressions value is used in.
2619
2620
pub struct ExprUseCtxt < ' tcx > {
2620
2621
/// The parent node which consumes the value.
2621
- pub node : ExprUseNode < ' tcx > ,
2622
+ pub node : Node < ' tcx > ,
2623
+ /// The child id of the node the value came from.
2624
+ pub child_id : HirId ,
2622
2625
/// Any adjustments applied to the type.
2623
2626
pub adjustments : & ' tcx [ Adjustment < ' tcx > ] ,
2624
- /// Whether or not the type must unify with another code path.
2627
+ /// Whether the type must unify with another code path.
2625
2628
pub is_ty_unified : bool ,
2626
- /// Whether or not the value will be moved before it's used.
2629
+ /// Whether the value will be moved before it's used.
2627
2630
pub moved_before_use : bool ,
2631
+ /// Whether the use site has the same `SyntaxContext` as the value.
2632
+ pub same_ctxt : bool ,
2633
+ }
2634
+ impl < ' tcx > ExprUseCtxt < ' tcx > {
2635
+ pub fn use_node ( & self , cx : & LateContext < ' tcx > ) -> ExprUseNode < ' tcx > {
2636
+ match self . node {
2637
+ Node :: Local ( l) => ExprUseNode :: Local ( l) ,
2638
+ Node :: ExprField ( field) => ExprUseNode :: Field ( field) ,
2639
+
2640
+ Node :: Item ( & Item {
2641
+ kind : ItemKind :: Static ( ..) | ItemKind :: Const ( ..) ,
2642
+ owner_id,
2643
+ ..
2644
+ } )
2645
+ | Node :: TraitItem ( & TraitItem {
2646
+ kind : TraitItemKind :: Const ( ..) ,
2647
+ owner_id,
2648
+ ..
2649
+ } )
2650
+ | Node :: ImplItem ( & ImplItem {
2651
+ kind : ImplItemKind :: Const ( ..) ,
2652
+ owner_id,
2653
+ ..
2654
+ } ) => ExprUseNode :: ConstStatic ( owner_id) ,
2655
+
2656
+ Node :: Item ( & Item {
2657
+ kind : ItemKind :: Fn ( ..) ,
2658
+ owner_id,
2659
+ ..
2660
+ } )
2661
+ | Node :: TraitItem ( & TraitItem {
2662
+ kind : TraitItemKind :: Fn ( ..) ,
2663
+ owner_id,
2664
+ ..
2665
+ } )
2666
+ | Node :: ImplItem ( & ImplItem {
2667
+ kind : ImplItemKind :: Fn ( ..) ,
2668
+ owner_id,
2669
+ ..
2670
+ } ) => ExprUseNode :: Return ( owner_id) ,
2671
+
2672
+ Node :: Expr ( use_expr) => match use_expr. kind {
2673
+ ExprKind :: Ret ( _) => ExprUseNode :: Return ( OwnerId {
2674
+ def_id : cx. tcx . hir ( ) . body_owner_def_id ( cx. enclosing_body . unwrap ( ) ) ,
2675
+ } ) ,
2676
+
2677
+ ExprKind :: Closure ( closure) => ExprUseNode :: Return ( OwnerId { def_id : closure. def_id } ) ,
2678
+ ExprKind :: Call ( func, args) => match args. iter ( ) . position ( |arg| arg. hir_id == self . child_id ) {
2679
+ Some ( i) => ExprUseNode :: FnArg ( func, i) ,
2680
+ None => ExprUseNode :: Callee ,
2681
+ } ,
2682
+ ExprKind :: MethodCall ( name, _, args, _) => ExprUseNode :: MethodArg (
2683
+ use_expr. hir_id ,
2684
+ name. args ,
2685
+ args. iter ( )
2686
+ . position ( |arg| arg. hir_id == self . child_id )
2687
+ . map_or ( 0 , |i| i + 1 ) ,
2688
+ ) ,
2689
+ ExprKind :: Field ( _, name) => ExprUseNode :: FieldAccess ( name) ,
2690
+ ExprKind :: AddrOf ( kind, mutbl, _) => ExprUseNode :: AddrOf ( kind, mutbl) ,
2691
+ _ => ExprUseNode :: Other ,
2692
+ } ,
2693
+ _ => ExprUseNode :: Other ,
2694
+ }
2695
+ }
2628
2696
}
2629
2697
2630
2698
/// The node which consumes a value.
@@ -2645,7 +2713,8 @@ pub enum ExprUseNode<'tcx> {
2645
2713
Callee ,
2646
2714
/// Access of a field.
2647
2715
FieldAccess ( Ident ) ,
2648
- Expr ,
2716
+ /// Borrow expression.
2717
+ AddrOf ( ast:: BorrowKind , Mutability ) ,
2649
2718
Other ,
2650
2719
}
2651
2720
impl < ' tcx > ExprUseNode < ' tcx > {
@@ -2723,25 +2792,26 @@ impl<'tcx> ExprUseNode<'tcx> {
2723
2792
let sig = cx. tcx . fn_sig ( id) . skip_binder ( ) ;
2724
2793
Some ( DefinedTy :: Mir ( cx. tcx . param_env ( id) . and ( sig. input ( i) ) ) )
2725
2794
} ,
2726
- Self :: Local ( _) | Self :: FieldAccess ( ..) | Self :: Callee | Self :: Expr | Self :: Other => None ,
2795
+ Self :: Local ( _) | Self :: FieldAccess ( ..) | Self :: Callee | Self :: Other | Self :: AddrOf ( .. ) => None ,
2727
2796
}
2728
2797
}
2729
2798
}
2730
2799
2731
2800
/// Gets the context an expression's value is used in.
2732
- pub fn expr_use_ctxt < ' tcx > ( cx : & LateContext < ' tcx > , e : & ' tcx Expr < ' tcx > ) -> Option < ExprUseCtxt < ' tcx > > {
2801
+ pub fn expr_use_ctxt < ' tcx > ( cx : & LateContext < ' tcx > , e : & ' tcx Expr < ' tcx > ) -> ExprUseCtxt < ' tcx > {
2733
2802
let mut adjustments = [ ] . as_slice ( ) ;
2734
2803
let mut is_ty_unified = false ;
2735
2804
let mut moved_before_use = false ;
2805
+ let mut same_ctxt = true ;
2736
2806
let ctxt = e. span . ctxt ( ) ;
2737
- walk_to_expr_usage ( cx, e, & mut |parent_id, parent, child_id| {
2807
+ let node = walk_to_expr_usage ( cx, e, & mut |parent_id, parent, child_id| -> ControlFlow < ! > {
2738
2808
if adjustments. is_empty ( )
2739
2809
&& let Node :: Expr ( e) = cx. tcx . hir_node ( child_id)
2740
2810
{
2741
2811
adjustments = cx. typeck_results ( ) . expr_adjustments ( e) ;
2742
2812
}
2743
- if ! cx. tcx . hir ( ) . opt_span ( parent_id) . is_some_and ( |x| x . ctxt ( ) == ctxt ) {
2744
- return ControlFlow :: Break ( ( ) ) ;
2813
+ if let Some ( s ) = cx. tcx . hir ( ) . opt_span ( parent_id) {
2814
+ same_ctxt &= s . ctxt ( ) == ctxt ;
2745
2815
}
2746
2816
if let Node :: Expr ( e) = parent {
2747
2817
match e. kind {
@@ -2758,71 +2828,25 @@ pub fn expr_use_ctxt<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> Optio
2758
2828
}
2759
2829
}
2760
2830
ControlFlow :: Continue ( ( ) )
2761
- } ) ?
2762
- . continue_value ( )
2763
- . map ( |( use_node, child_id) | {
2764
- let node = match use_node {
2765
- Node :: Local ( l) => ExprUseNode :: Local ( l) ,
2766
- Node :: ExprField ( field) => ExprUseNode :: Field ( field) ,
2767
-
2768
- Node :: Item ( & Item {
2769
- kind : ItemKind :: Static ( ..) | ItemKind :: Const ( ..) ,
2770
- owner_id,
2771
- ..
2772
- } )
2773
- | Node :: TraitItem ( & TraitItem {
2774
- kind : TraitItemKind :: Const ( ..) ,
2775
- owner_id,
2776
- ..
2777
- } )
2778
- | Node :: ImplItem ( & ImplItem {
2779
- kind : ImplItemKind :: Const ( ..) ,
2780
- owner_id,
2781
- ..
2782
- } ) => ExprUseNode :: ConstStatic ( owner_id) ,
2783
-
2784
- Node :: Item ( & Item {
2785
- kind : ItemKind :: Fn ( ..) ,
2786
- owner_id,
2787
- ..
2788
- } )
2789
- | Node :: TraitItem ( & TraitItem {
2790
- kind : TraitItemKind :: Fn ( ..) ,
2791
- owner_id,
2792
- ..
2793
- } )
2794
- | Node :: ImplItem ( & ImplItem {
2795
- kind : ImplItemKind :: Fn ( ..) ,
2796
- owner_id,
2797
- ..
2798
- } ) => ExprUseNode :: Return ( owner_id) ,
2799
-
2800
- Node :: Expr ( use_expr) => match use_expr. kind {
2801
- ExprKind :: Ret ( _) => ExprUseNode :: Return ( OwnerId {
2802
- def_id : cx. tcx . hir ( ) . body_owner_def_id ( cx. enclosing_body . unwrap ( ) ) ,
2803
- } ) ,
2804
- ExprKind :: Closure ( closure) => ExprUseNode :: Return ( OwnerId { def_id : closure. def_id } ) ,
2805
- ExprKind :: Call ( func, args) => match args. iter ( ) . position ( |arg| arg. hir_id == child_id) {
2806
- Some ( i) => ExprUseNode :: FnArg ( func, i) ,
2807
- None => ExprUseNode :: Callee ,
2808
- } ,
2809
- ExprKind :: MethodCall ( name, _, args, _) => ExprUseNode :: MethodArg (
2810
- use_expr. hir_id ,
2811
- name. args ,
2812
- args. iter ( ) . position ( |arg| arg. hir_id == child_id) . map_or ( 0 , |i| i + 1 ) ,
2813
- ) ,
2814
- ExprKind :: Field ( child, name) if child. hir_id == e. hir_id => ExprUseNode :: FieldAccess ( name) ,
2815
- _ => ExprUseNode :: Expr ,
2816
- } ,
2817
- _ => ExprUseNode :: Other ,
2818
- } ;
2819
- ExprUseCtxt {
2831
+ } ) ;
2832
+ match node {
2833
+ Some ( ControlFlow :: Continue ( ( node, child_id) ) ) => ExprUseCtxt {
2820
2834
node,
2835
+ child_id,
2821
2836
adjustments,
2822
2837
is_ty_unified,
2823
2838
moved_before_use,
2824
- }
2825
- } )
2839
+ same_ctxt,
2840
+ } ,
2841
+ None => ExprUseCtxt {
2842
+ node : Node :: Crate ( cx. tcx . hir ( ) . root_module ( ) ) ,
2843
+ child_id : HirId :: INVALID ,
2844
+ adjustments : & [ ] ,
2845
+ is_ty_unified : true ,
2846
+ moved_before_use : true ,
2847
+ same_ctxt : false ,
2848
+ } ,
2849
+ }
2826
2850
}
2827
2851
2828
2852
/// Tokenizes the input while keeping the text associated with each token.
0 commit comments