@@ -48,6 +48,7 @@ use rustc_mir_dataflow::points::DenseLocationMap;
4848use rustc_mir_dataflow:: { Analysis , EntryStates , Results , ResultsVisitor , visit_results} ;
4949use rustc_session:: lint:: builtin:: { TAIL_EXPR_DROP_ORDER , UNUSED_MUT } ;
5050use rustc_span:: { ErrorGuaranteed , Span , Symbol } ;
51+ use rustc_trait_selection:: infer:: InferCtxtExt ;
5152use smallvec:: SmallVec ;
5253use tracing:: { debug, instrument} ;
5354
@@ -486,6 +487,7 @@ fn borrowck_check_region_constraints<'tcx>(
486487 used_mut : Default :: default ( ) ,
487488 used_mut_upvars : SmallVec :: new ( ) ,
488489 borrow_set : & borrow_set,
490+ pin_set : & pin_set,
489491 upvars : & [ ] ,
490492 local_names : OnceCell :: from ( IndexVec :: from_elem ( None , & promoted_body. local_decls ) ) ,
491493 region_names : RefCell :: default ( ) ,
@@ -525,6 +527,7 @@ fn borrowck_check_region_constraints<'tcx>(
525527 used_mut : Default :: default ( ) ,
526528 used_mut_upvars : SmallVec :: new ( ) ,
527529 borrow_set : & borrow_set,
530+ pin_set : & pin_set,
528531 upvars : tcx. closure_captures ( def) ,
529532 local_names : OnceCell :: new ( ) ,
530533 region_names : RefCell :: default ( ) ,
@@ -771,6 +774,9 @@ pub(crate) struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
771774 /// The set of borrows extracted from the MIR
772775 borrow_set : & ' a BorrowSet < ' tcx > ,
773776
777+ /// The set of pins extracted from the MIR
778+ pin_set : & ' a PinSet < ' tcx > ,
779+
774780 /// Information about upvars not necessarily preserved in types or MIR
775781 upvars : & ' tcx [ & ' tcx ty:: CapturedPlace < ' tcx > ] ,
776782
@@ -1243,8 +1249,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
12431249 location,
12441250 ) ;
12451251 let conflict_error = self . check_access_for_conflict ( location, place_span, sd, rw, state) ;
1252+ let pin_conflict_error =
1253+ self . check_access_for_pin_conflict ( location, place_span, sd, rw, state) ;
12461254
1247- if conflict_error || mutability_error {
1255+ if conflict_error || mutability_error || pin_conflict_error {
12481256 debug ! ( "access_place: logging error place_span=`{:?}` kind=`{:?}`" , place_span, kind) ;
12491257 self . access_place_error_reported . insert ( ( place_span. 0 , place_span. 1 ) ) ;
12501258 }
@@ -1268,6 +1276,77 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
12681276 }
12691277 }
12701278
1279+ fn pins_in_scope < ' s > (
1280+ & self ,
1281+ _location : Location ,
1282+ state : & ' s BorrowckDomain ,
1283+ ) -> & ' s MixedBitSet < PinIndex > {
1284+ & state. pins
1285+ }
1286+
1287+ #[ instrument( level = "debug" , skip( self , state) ) ]
1288+ fn check_access_for_pin_conflict (
1289+ & mut self ,
1290+ location : Location ,
1291+ place_span : ( Place < ' tcx > , Span ) ,
1292+ sd : AccessDepth ,
1293+ rw : ReadOrWrite ,
1294+ state : & BorrowckDomain ,
1295+ ) -> bool {
1296+ use ReadOrWrite :: Write ;
1297+ use WriteKind :: { Move , MutableBorrow } ;
1298+
1299+ // Early return: only check Move and MutableBorrow operations
1300+ let is_violating_access = matches ! ( rw, Write ( Move ) | Write ( MutableBorrow ( _) ) ) ;
1301+ if !is_violating_access {
1302+ return false ;
1303+ }
1304+
1305+ let mut error_reported = false ;
1306+ let pins_in_scope = self . pins_in_scope ( location, state) ;
1307+
1308+ // Check each active pin for conflicts
1309+ for pin_index in pins_in_scope. iter ( ) {
1310+ let pin_data = & self . pin_set [ pin_index] ;
1311+
1312+ // Check if accessed place conflicts with pinned place
1313+ if places_conflict (
1314+ self . infcx . tcx ,
1315+ self . body ,
1316+ pin_data. pinned_place ,
1317+ place_span. 0 ,
1318+ PlaceConflictBias :: Overlap ,
1319+ ) {
1320+ // Get the type of the pinned place (Pin<Ptr>)
1321+ let pinned_ty = pin_data. pinned_place . ty ( self . body , self . infcx . tcx ) . ty ;
1322+
1323+ // Extract the pointee type from Pin<&[mut] T> to get T
1324+ if let Some ( pointee_ty) = pinned_ty. builtin_deref ( true ) {
1325+ // Check if the pointee type implements Unpin
1326+ let unpin_trait = self . infcx . tcx . lang_items ( ) . unpin_trait ( ) ;
1327+ if let Some ( unpin_trait) = unpin_trait {
1328+ let param_env = self . infcx . tcx . param_env (
1329+ self . body . source . def_id ( )
1330+ ) ;
1331+ let ty_is_unpin = self . infcx . type_implements_trait (
1332+ unpin_trait,
1333+ [ pointee_ty] ,
1334+ param_env,
1335+ ) . must_apply_modulo_regions ( ) ;
1336+
1337+ // Only report violation if the type does NOT implement Unpin
1338+ if !ty_is_unpin {
1339+ error_reported = true ;
1340+ self . report_pin_violation ( location, place_span, pin_data, rw) ;
1341+ }
1342+ }
1343+ }
1344+ }
1345+ }
1346+
1347+ error_reported
1348+ }
1349+
12711350 #[ instrument( level = "debug" , skip( self , state) ) ]
12721351 fn check_access_for_conflict (
12731352 & mut self ,
0 commit comments