@@ -234,7 +234,14 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
234
234
pats : & [ hir:: PatField < ' _ > ] ,
235
235
) {
236
236
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
+ }
238
245
_ => span_bug ! ( lhs. span, "non-ADT in struct pattern" ) ,
239
246
} ;
240
247
for pat in pats {
@@ -254,7 +261,11 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
254
261
dotdot : hir:: DotDotPos ,
255
262
) {
256
263
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
+ }
258
269
_ => {
259
270
self . tcx . dcx ( ) . span_delayed_bug ( lhs. span , "non-ADT in tuple struct pattern" ) ;
260
271
return ;
@@ -359,31 +370,6 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
359
370
return false ;
360
371
}
361
372
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
-
387
373
if let Some ( trait_of) = self . tcx . trait_id_of_impl ( impl_of)
388
374
&& self . tcx . has_attr ( trait_of, sym:: rustc_trivial_field_reads)
389
375
{
@@ -494,38 +480,25 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
494
480
impl_id : hir:: ItemId ,
495
481
local_def_id : LocalDefId ,
496
482
) -> bool {
497
- if self . should_ignore_item ( local_def_id. to_def_id ( ) ) {
498
- return false ;
499
- }
500
-
501
483
let trait_def_id = match self . tcx . def_kind ( local_def_id) {
502
484
// 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 ( ) ) ,
504
490
// impl items are live if the corresponding traits are live
505
491
DefKind :: Impl { of_trait : true } => self
506
492
. tcx
507
493
. 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 ( ) ) ,
509
495
_ => None ,
510
496
} ;
511
497
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 ;
529
502
}
530
503
531
504
// 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> {
635
608
fn visit_pat_expr ( & mut self , expr : & ' tcx rustc_hir:: PatExpr < ' tcx > ) {
636
609
match & expr. kind {
637
610
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
+
638
616
let res = self . typeck_results ( ) . qpath_res ( qpath, expr. hir_id ) ;
639
617
self . handle_res ( res) ;
640
618
}
0 commit comments