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) ]
@@ -2664,13 +2665,80 @@ pub enum DefinedTy<'tcx> {
2664
2665
/// The context an expressions value is used in.
2665
2666
pub struct ExprUseCtxt < ' tcx > {
2666
2667
/// The parent node which consumes the value.
2667
- pub node : ExprUseNode < ' tcx > ,
2668
+ pub node : Node < ' tcx > ,
2669
+ /// The child id of the node the value came from.
2670
+ pub child_id : HirId ,
2668
2671
/// Any adjustments applied to the type.
2669
2672
pub adjustments : & ' tcx [ Adjustment < ' tcx > ] ,
2670
- /// Whether or not the type must unify with another code path.
2673
+ /// Whether the type must unify with another code path.
2671
2674
pub is_ty_unified : bool ,
2672
- /// Whether or not the value will be moved before it's used.
2675
+ /// Whether the value will be moved before it's used.
2673
2676
pub moved_before_use : bool ,
2677
+ /// Whether the use site has the same `SyntaxContext` as the value.
2678
+ pub same_ctxt : bool ,
2679
+ }
2680
+ impl < ' tcx > ExprUseCtxt < ' tcx > {
2681
+ pub fn use_node ( & self , cx : & LateContext < ' tcx > ) -> ExprUseNode < ' tcx > {
2682
+ match self . node {
2683
+ Node :: LetStmt ( l) => ExprUseNode :: LetStmt ( l) ,
2684
+ Node :: ExprField ( field) => ExprUseNode :: Field ( field) ,
2685
+
2686
+ Node :: Item ( & Item {
2687
+ kind : ItemKind :: Static ( ..) | ItemKind :: Const ( ..) ,
2688
+ owner_id,
2689
+ ..
2690
+ } )
2691
+ | Node :: TraitItem ( & TraitItem {
2692
+ kind : TraitItemKind :: Const ( ..) ,
2693
+ owner_id,
2694
+ ..
2695
+ } )
2696
+ | Node :: ImplItem ( & ImplItem {
2697
+ kind : ImplItemKind :: Const ( ..) ,
2698
+ owner_id,
2699
+ ..
2700
+ } ) => ExprUseNode :: ConstStatic ( owner_id) ,
2701
+
2702
+ Node :: Item ( & Item {
2703
+ kind : ItemKind :: Fn ( ..) ,
2704
+ owner_id,
2705
+ ..
2706
+ } )
2707
+ | Node :: TraitItem ( & TraitItem {
2708
+ kind : TraitItemKind :: Fn ( ..) ,
2709
+ owner_id,
2710
+ ..
2711
+ } )
2712
+ | Node :: ImplItem ( & ImplItem {
2713
+ kind : ImplItemKind :: Fn ( ..) ,
2714
+ owner_id,
2715
+ ..
2716
+ } ) => ExprUseNode :: Return ( owner_id) ,
2717
+
2718
+ Node :: Expr ( use_expr) => match use_expr. kind {
2719
+ ExprKind :: Ret ( _) => ExprUseNode :: Return ( OwnerId {
2720
+ def_id : cx. tcx . hir ( ) . body_owner_def_id ( cx. enclosing_body . unwrap ( ) ) ,
2721
+ } ) ,
2722
+
2723
+ ExprKind :: Closure ( closure) => ExprUseNode :: Return ( OwnerId { def_id : closure. def_id } ) ,
2724
+ ExprKind :: Call ( func, args) => match args. iter ( ) . position ( |arg| arg. hir_id == self . child_id ) {
2725
+ Some ( i) => ExprUseNode :: FnArg ( func, i) ,
2726
+ None => ExprUseNode :: Callee ,
2727
+ } ,
2728
+ ExprKind :: MethodCall ( name, _, args, _) => ExprUseNode :: MethodArg (
2729
+ use_expr. hir_id ,
2730
+ name. args ,
2731
+ args. iter ( )
2732
+ . position ( |arg| arg. hir_id == self . child_id )
2733
+ . map_or ( 0 , |i| i + 1 ) ,
2734
+ ) ,
2735
+ ExprKind :: Field ( _, name) => ExprUseNode :: FieldAccess ( name) ,
2736
+ ExprKind :: AddrOf ( kind, mutbl, _) => ExprUseNode :: AddrOf ( kind, mutbl) ,
2737
+ _ => ExprUseNode :: Other ,
2738
+ } ,
2739
+ _ => ExprUseNode :: Other ,
2740
+ }
2741
+ }
2674
2742
}
2675
2743
2676
2744
/// The node which consumes a value.
@@ -2691,7 +2759,8 @@ pub enum ExprUseNode<'tcx> {
2691
2759
Callee ,
2692
2760
/// Access of a field.
2693
2761
FieldAccess ( Ident ) ,
2694
- Expr ,
2762
+ /// Borrow expression.
2763
+ AddrOf ( ast:: BorrowKind , Mutability ) ,
2695
2764
Other ,
2696
2765
}
2697
2766
impl < ' tcx > ExprUseNode < ' tcx > {
@@ -2768,26 +2837,25 @@ impl<'tcx> ExprUseNode<'tcx> {
2768
2837
let sig = cx. tcx . fn_sig ( id) . skip_binder ( ) ;
2769
2838
Some ( DefinedTy :: Mir ( cx. tcx . param_env ( id) . and ( sig. input ( i) ) ) )
2770
2839
} ,
2771
- Self :: LetStmt ( _) | Self :: FieldAccess ( ..) | Self :: Callee | Self :: Expr | Self :: Other => None ,
2840
+ Self :: LetStmt ( _) | Self :: FieldAccess ( ..) | Self :: Callee | Self :: Other | Self :: AddrOf ( .. ) => None ,
2772
2841
}
2773
2842
}
2774
2843
}
2775
2844
2776
2845
/// Gets the context an expression's value is used in.
2777
- pub fn expr_use_ctxt < ' tcx > ( cx : & LateContext < ' tcx > , e : & ' tcx Expr < ' tcx > ) -> Option < ExprUseCtxt < ' tcx > > {
2846
+ pub fn expr_use_ctxt < ' tcx > ( cx : & LateContext < ' tcx > , e : & ' tcx Expr < ' tcx > ) -> ExprUseCtxt < ' tcx > {
2778
2847
let mut adjustments = [ ] . as_slice ( ) ;
2779
2848
let mut is_ty_unified = false ;
2780
2849
let mut moved_before_use = false ;
2850
+ let mut same_ctxt = true ;
2781
2851
let ctxt = e. span . ctxt ( ) ;
2782
- walk_to_expr_usage ( cx, e, & mut |parent_id, parent, child_id| {
2852
+ let node = walk_to_expr_usage ( cx, e, & mut |parent_id, parent, child_id| -> ControlFlow < ! > {
2783
2853
if adjustments. is_empty ( )
2784
2854
&& let Node :: Expr ( e) = cx. tcx . hir_node ( child_id)
2785
2855
{
2786
2856
adjustments = cx. typeck_results ( ) . expr_adjustments ( e) ;
2787
2857
}
2788
- if cx. tcx . hir ( ) . span ( parent_id) . ctxt ( ) != ctxt {
2789
- return ControlFlow :: Break ( ( ) ) ;
2790
- }
2858
+ same_ctxt &= cx. tcx . hir ( ) . span ( parent_id) . ctxt ( ) == ctxt;
2791
2859
if let Node :: Expr ( e) = parent {
2792
2860
match e. kind {
2793
2861
ExprKind :: If ( e, _, _) | ExprKind :: Match ( e, _, _) if e. hir_id != child_id => {
@@ -2803,71 +2871,25 @@ pub fn expr_use_ctxt<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> Optio
2803
2871
}
2804
2872
}
2805
2873
ControlFlow :: Continue ( ( ) )
2806
- } ) ?
2807
- . continue_value ( )
2808
- . map ( |( use_node, child_id) | {
2809
- let node = match use_node {
2810
- Node :: LetStmt ( l) => ExprUseNode :: LetStmt ( l) ,
2811
- Node :: ExprField ( field) => ExprUseNode :: Field ( field) ,
2812
-
2813
- Node :: Item ( & Item {
2814
- kind : ItemKind :: Static ( ..) | ItemKind :: Const ( ..) ,
2815
- owner_id,
2816
- ..
2817
- } )
2818
- | Node :: TraitItem ( & TraitItem {
2819
- kind : TraitItemKind :: Const ( ..) ,
2820
- owner_id,
2821
- ..
2822
- } )
2823
- | Node :: ImplItem ( & ImplItem {
2824
- kind : ImplItemKind :: Const ( ..) ,
2825
- owner_id,
2826
- ..
2827
- } ) => ExprUseNode :: ConstStatic ( owner_id) ,
2828
-
2829
- Node :: Item ( & Item {
2830
- kind : ItemKind :: Fn ( ..) ,
2831
- owner_id,
2832
- ..
2833
- } )
2834
- | Node :: TraitItem ( & TraitItem {
2835
- kind : TraitItemKind :: Fn ( ..) ,
2836
- owner_id,
2837
- ..
2838
- } )
2839
- | Node :: ImplItem ( & ImplItem {
2840
- kind : ImplItemKind :: Fn ( ..) ,
2841
- owner_id,
2842
- ..
2843
- } ) => ExprUseNode :: Return ( owner_id) ,
2844
-
2845
- Node :: Expr ( use_expr) => match use_expr. kind {
2846
- ExprKind :: Ret ( _) => ExprUseNode :: Return ( OwnerId {
2847
- def_id : cx. tcx . hir ( ) . body_owner_def_id ( cx. enclosing_body . unwrap ( ) ) ,
2848
- } ) ,
2849
- ExprKind :: Closure ( closure) => ExprUseNode :: Return ( OwnerId { def_id : closure. def_id } ) ,
2850
- ExprKind :: Call ( func, args) => match args. iter ( ) . position ( |arg| arg. hir_id == child_id) {
2851
- Some ( i) => ExprUseNode :: FnArg ( func, i) ,
2852
- None => ExprUseNode :: Callee ,
2853
- } ,
2854
- ExprKind :: MethodCall ( name, _, args, _) => ExprUseNode :: MethodArg (
2855
- use_expr. hir_id ,
2856
- name. args ,
2857
- args. iter ( ) . position ( |arg| arg. hir_id == child_id) . map_or ( 0 , |i| i + 1 ) ,
2858
- ) ,
2859
- ExprKind :: Field ( child, name) if child. hir_id == e. hir_id => ExprUseNode :: FieldAccess ( name) ,
2860
- _ => ExprUseNode :: Expr ,
2861
- } ,
2862
- _ => ExprUseNode :: Other ,
2863
- } ;
2864
- ExprUseCtxt {
2874
+ } ) ;
2875
+ match node {
2876
+ Some ( ControlFlow :: Continue ( ( node, child_id) ) ) => ExprUseCtxt {
2865
2877
node,
2878
+ child_id,
2866
2879
adjustments,
2867
2880
is_ty_unified,
2868
2881
moved_before_use,
2869
- }
2870
- } )
2882
+ same_ctxt,
2883
+ } ,
2884
+ None => ExprUseCtxt {
2885
+ node : Node :: Crate ( cx. tcx . hir ( ) . root_module ( ) ) ,
2886
+ child_id : HirId :: INVALID ,
2887
+ adjustments : & [ ] ,
2888
+ is_ty_unified : true ,
2889
+ moved_before_use : true ,
2890
+ same_ctxt : false ,
2891
+ } ,
2892
+ }
2871
2893
}
2872
2894
2873
2895
/// Tokenizes the input while keeping the text associated with each token.
0 commit comments