@@ -36,6 +36,7 @@ use rustc_span::edit_distance::find_best_match_for_name;
3636use rustc_span:: hygiene:: DesugaringKind ;
3737use rustc_span:: { Ident , Span , Spanned , Symbol , kw, sym} ;
3838use rustc_trait_selection:: infer:: InferCtxtExt ;
39+ use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt as _;
3940use rustc_trait_selection:: traits:: { self , ObligationCauseCode , ObligationCtxt } ;
4041use tracing:: { debug, instrument, trace} ;
4142
@@ -531,6 +532,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
531532 let ty = self . structurally_resolve_type ( span, ty) ;
532533 if let Some ( adt) = ty. ty_adt_def ( )
533534 && !adt. is_pin_project ( )
535+ && self . type_known_to_not_be_unpin ( ty, span)
534536 {
535537 let def_span = self . tcx . hir_span_if_local ( adt. did ( ) ) ;
536538 let sugg_span = def_span. map ( |span| span. shrink_to_lo ( ) ) ;
@@ -542,6 +544,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
542544 }
543545 }
544546
547+ fn type_known_to_not_be_unpin ( & self , ty : Ty < ' tcx > , span : Span ) -> bool {
548+ if ty. has_param ( ) || ty. has_infer ( ) || ty. has_aliases ( ) || ty. has_placeholders ( ) {
549+ return false ;
550+ }
551+
552+ let unpin_def_id = self . tcx . require_lang_item ( LangItem :: Unpin , span) ;
553+ let trait_ref = ty:: TraitRef :: new ( self . tcx , unpin_def_id, [ ty] ) ;
554+ let obligation =
555+ traits:: Obligation :: new ( self . tcx , self . misc ( span) , self . param_env , trait_ref) ;
556+ self . evaluate_obligation ( & obligation) . is_ok_and ( |result| !result. may_apply ( ) )
557+ }
558+
545559 /// Does this expression refer to a place that either:
546560 /// * Is based on a local or static.
547561 /// * Contains a dereference
0 commit comments