@@ -234,7 +234,14 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
234234 pats : & [ hir:: PatField < ' _ > ] ,
235235 ) {
236236 let variant = match self . typeck_results ( ) . node_type ( lhs. hir_id ) . kind ( ) {
237- ty:: Adt ( adt, _) => adt. variant_of_res ( res) ,
237+ ty:: Adt ( adt, _) => {
238+ // Marks the ADT live if its variant appears as the pattern,
239+ // considering cases when we have `let T(x) = foo()` and `fn foo<T>() -> T;`,
240+ // we will lose the liveness info of `T` cause we cannot mark it live when visiting `foo`.
241+ // Related issue: https://github.com/rust-lang/rust/issues/120770
242+ self . check_def_id ( adt. did ( ) ) ;
243+ adt. variant_of_res ( res)
244+ }
238245 _ => span_bug ! ( lhs. span, "non-ADT in struct pattern" ) ,
239246 } ;
240247 for pat in pats {
@@ -254,7 +261,11 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
254261 dotdot : hir:: DotDotPos ,
255262 ) {
256263 let variant = match self . typeck_results ( ) . node_type ( lhs. hir_id ) . kind ( ) {
257- ty:: Adt ( adt, _) => adt. variant_of_res ( res) ,
264+ ty:: Adt ( adt, _) => {
265+ // Marks the ADT live if its variant appears as the pattern
266+ self . check_def_id ( adt. did ( ) ) ;
267+ adt. variant_of_res ( res)
268+ }
258269 _ => {
259270 self . tcx . dcx ( ) . span_delayed_bug ( lhs. span , "non-ADT in tuple struct pattern" ) ;
260271 return ;
@@ -359,31 +370,6 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
359370 return false ;
360371 }
361372
362- // don't ignore impls for Enums and pub Structs whose methods don't have self receiver,
363- // cause external crate may call such methods to construct values of these types
364- if let Some ( local_impl_of) = impl_of. as_local ( )
365- && let Some ( local_def_id) = def_id. as_local ( )
366- && let Some ( fn_sig) =
367- self . tcx . hir_fn_sig_by_hir_id ( self . tcx . local_def_id_to_hir_id ( local_def_id) )
368- && matches ! ( fn_sig. decl. implicit_self, hir:: ImplicitSelfKind :: None )
369- && let TyKind :: Path ( QPath :: Resolved ( _, path) ) =
370- self . tcx . hir_expect_item ( local_impl_of) . expect_impl ( ) . self_ty . kind
371- && let Res :: Def ( def_kind, did) = path. res
372- {
373- match def_kind {
374- // for example, #[derive(Default)] pub struct T(i32);
375- // external crate can call T::default() to construct T,
376- // so that don't ignore impl Default for pub Enum and Structs
377- DefKind :: Struct | DefKind :: Union if self . tcx . visibility ( did) . is_public ( ) => {
378- return false ;
379- }
380- // don't ignore impl Default for Enums,
381- // cause we don't know which variant is constructed
382- DefKind :: Enum => return false ,
383- _ => ( ) ,
384- } ;
385- }
386-
387373 if let Some ( trait_of) = self . tcx . trait_id_of_impl ( impl_of)
388374 && self . tcx . has_attr ( trait_of, sym:: rustc_trivial_field_reads)
389375 {
@@ -494,38 +480,25 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
494480 impl_id : hir:: ItemId ,
495481 local_def_id : LocalDefId ,
496482 ) -> bool {
497- if self . should_ignore_item ( local_def_id. to_def_id ( ) ) {
498- return false ;
499- }
500-
501483 let trait_def_id = match self . tcx . def_kind ( local_def_id) {
502484 // assoc impl items of traits are live if the corresponding trait items are live
503- DefKind :: AssocFn => self . tcx . associated_item ( local_def_id) . trait_item_def_id ,
485+ DefKind :: AssocFn => self
486+ . tcx
487+ . associated_item ( local_def_id)
488+ . trait_item_def_id
489+ . and_then ( |def_id| def_id. as_local ( ) ) ,
504490 // impl items are live if the corresponding traits are live
505491 DefKind :: Impl { of_trait : true } => self
506492 . tcx
507493 . impl_trait_ref ( impl_id. owner_id . def_id )
508- . and_then ( |trait_ref| Some ( trait_ref. skip_binder ( ) . def_id ) ) ,
494+ . and_then ( |trait_ref| trait_ref. skip_binder ( ) . def_id . as_local ( ) ) ,
509495 _ => None ,
510496 } ;
511497
512- if let Some ( trait_def_id) = trait_def_id {
513- if let Some ( trait_def_id) = trait_def_id. as_local ( )
514- && !self . live_symbols . contains ( & trait_def_id)
515- {
516- return false ;
517- }
518-
519- // FIXME: legacy logic to check whether the function may construct `Self`,
520- // this can be removed after supporting marking ADTs appearing in patterns
521- // as live, then we can check private impls of public traits directly
522- if let Some ( fn_sig) =
523- self . tcx . hir_fn_sig_by_hir_id ( self . tcx . local_def_id_to_hir_id ( local_def_id) )
524- && matches ! ( fn_sig. decl. implicit_self, hir:: ImplicitSelfKind :: None )
525- && self . tcx . visibility ( trait_def_id) . is_public ( )
526- {
527- return true ;
528- }
498+ if let Some ( trait_def_id) = trait_def_id
499+ && !self . live_symbols . contains ( & trait_def_id)
500+ {
501+ return false ;
529502 }
530503
531504 // The impl or impl item is used if the corresponding trait or trait item is used and the ty is used.
@@ -635,6 +608,11 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
635608 fn visit_pat_expr ( & mut self , expr : & ' tcx rustc_hir:: PatExpr < ' tcx > ) {
636609 match & expr. kind {
637610 rustc_hir:: PatExprKind :: Path ( qpath) => {
611+ // mark the type of variant live when meeting E::V in expr
612+ if let ty:: Adt ( adt, _) = self . typeck_results ( ) . node_type ( expr. hir_id ) . kind ( ) {
613+ self . check_def_id ( adt. did ( ) ) ;
614+ }
615+
638616 let res = self . typeck_results ( ) . qpath_res ( qpath, expr. hir_id ) ;
639617 self . handle_res ( res) ;
640618 }
0 commit comments