@@ -6,7 +6,7 @@ use std::borrow::Cow;
66
77use rustc_data_structures:: fx:: FxHashSet ;
88use rustc_index:: bit_set:: DenseBitSet ;
9- use rustc_middle:: mir:: visit:: { PlaceContext , Visitor } ;
9+ use rustc_middle:: mir:: visit:: { PlaceContext , VisitPlacesWith , Visitor } ;
1010use rustc_middle:: mir:: * ;
1111use rustc_middle:: ty:: TyCtxt ;
1212use rustc_mir_dataflow:: impls:: { MaybeStorageDead , MaybeStorageLive , always_storage_live_locals} ;
@@ -79,15 +79,40 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> {
7979 fn visit_statement ( & mut self , statement : & Statement < ' tcx > , location : Location ) {
8080 match & statement. kind {
8181 StatementKind :: Assign ( box ( dest, rvalue) ) => {
82- if let Rvalue :: Use ( Operand :: Copy ( src) | Operand :: Move ( src) ) = rvalue {
83- // The sides of an assignment must not alias. Currently this just checks whether
84- // the places are identical.
85- if dest == src {
86- self . fail (
87- location,
88- "encountered `Assign` statement with overlapping memory" ,
89- ) ;
90- }
82+ let forbid_aliasing = match rvalue {
83+ Rvalue :: Use ( ..)
84+ | Rvalue :: CopyForDeref ( ..)
85+ | Rvalue :: Repeat ( ..)
86+ | Rvalue :: Aggregate ( ..)
87+ | Rvalue :: Cast ( ..)
88+ | Rvalue :: ShallowInitBox ( ..)
89+ | Rvalue :: WrapUnsafeBinder ( ..) => true ,
90+ Rvalue :: ThreadLocalRef ( ..)
91+ | Rvalue :: NullaryOp ( ..)
92+ | Rvalue :: UnaryOp ( ..)
93+ | Rvalue :: BinaryOp ( ..)
94+ | Rvalue :: Ref ( ..)
95+ | Rvalue :: RawPtr ( ..)
96+ | Rvalue :: Len ( ..)
97+ | Rvalue :: Discriminant ( ..) => false ,
98+ } ;
99+ // The sides of an assignment must not alias.
100+ if forbid_aliasing {
101+ VisitPlacesWith ( |src : Place < ' tcx > , _| {
102+ if * dest == src
103+ || ( dest. local == src. local
104+ && !dest. is_indirect ( )
105+ && !src. is_indirect ( ) )
106+ {
107+ self . fail (
108+ location,
109+ format ! (
110+ "encountered `{statement:?}` statement with overlapping memory"
111+ ) ,
112+ ) ;
113+ }
114+ } )
115+ . visit_rvalue ( rvalue, location) ;
91116 }
92117 }
93118 StatementKind :: StorageLive ( local) => {
0 commit comments