11#![ feature( array_chunks) ]
22#![ feature( box_patterns) ]
33#![ feature( control_flow_enum) ]
4+ #![ feature( exhaustive_patterns) ]
45#![ feature( if_let_guard) ]
56#![ feature( let_chains) ]
67#![ feature( lint_reasons) ]
@@ -2664,13 +2665,80 @@ pub enum DefinedTy<'tcx> {
26642665/// The context an expressions value is used in.
26652666pub struct ExprUseCtxt < ' tcx > {
26662667 /// 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 ,
26682671 /// Any adjustments applied to the type.
26692672 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.
26712674 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.
26732676 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+ }
26742742}
26752743
26762744/// The node which consumes a value.
@@ -2691,7 +2759,8 @@ pub enum ExprUseNode<'tcx> {
26912759 Callee ,
26922760 /// Access of a field.
26932761 FieldAccess ( Ident ) ,
2694- Expr ,
2762+ /// Borrow expression.
2763+ AddrOf ( ast:: BorrowKind , Mutability ) ,
26952764 Other ,
26962765}
26972766impl < ' tcx > ExprUseNode < ' tcx > {
@@ -2768,26 +2837,25 @@ impl<'tcx> ExprUseNode<'tcx> {
27682837 let sig = cx. tcx . fn_sig ( id) . skip_binder ( ) ;
27692838 Some ( DefinedTy :: Mir ( cx. tcx . param_env ( id) . and ( sig. input ( i) ) ) )
27702839 } ,
2771- Self :: LetStmt ( _) | Self :: FieldAccess ( ..) | Self :: Callee | Self :: Expr | Self :: Other => None ,
2840+ Self :: LetStmt ( _) | Self :: FieldAccess ( ..) | Self :: Callee | Self :: Other | Self :: AddrOf ( .. ) => None ,
27722841 }
27732842 }
27742843}
27752844
27762845/// 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 > {
27782847 let mut adjustments = [ ] . as_slice ( ) ;
27792848 let mut is_ty_unified = false ;
27802849 let mut moved_before_use = false ;
2850+ let mut same_ctxt = true ;
27812851 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 < ! > {
27832853 if adjustments. is_empty ( )
27842854 && let Node :: Expr ( e) = cx. tcx . hir_node ( child_id)
27852855 {
27862856 adjustments = cx. typeck_results ( ) . expr_adjustments ( e) ;
27872857 }
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;
27912859 if let Node :: Expr ( e) = parent {
27922860 match e. kind {
27932861 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
28032871 }
28042872 }
28052873 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 {
28652877 node,
2878+ child_id,
28662879 adjustments,
28672880 is_ty_unified,
28682881 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+ }
28712893}
28722894
28732895/// Tokenizes the input while keeping the text associated with each token.
0 commit comments