diff options
Diffstat (limited to 'compiler/rustc_passes/src/dead.rs')
| -rw-r--r-- | compiler/rustc_passes/src/dead.rs | 40 |
1 files changed, 28 insertions, 12 deletions
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 9c475c9fbf4..78fbcc1f406 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -278,10 +278,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { pats: &[hir::PatField<'_>], ) { let variant = match self.typeck_results().node_type(lhs.hir_id).kind() { - ty::Adt(adt, _) => { - self.check_def_id(adt.did()); - adt.variant_of_res(res) - } + ty::Adt(adt, _) => adt.variant_of_res(res), _ => span_bug!(lhs.span, "non-ADT in struct pattern"), }; for pat in pats { @@ -301,10 +298,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { dotdot: hir::DotDotPos, ) { let variant = match self.typeck_results().node_type(lhs.hir_id).kind() { - ty::Adt(adt, _) => { - self.check_def_id(adt.did()); - adt.variant_of_res(res) - } + ty::Adt(adt, _) => adt.variant_of_res(res), _ => { self.tcx.dcx().span_delayed_bug(lhs.span, "non-ADT in tuple struct pattern"); return; @@ -409,6 +403,31 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { return false; } + // don't ignore impls for Enums and pub Structs whose methods don't have self receiver, + // cause external crate may call such methods to construct values of these types + if let Some(local_impl_of) = impl_of.as_local() + && let Some(local_def_id) = def_id.as_local() + && let Some(fn_sig) = + self.tcx.hir().fn_sig_by_hir_id(self.tcx.local_def_id_to_hir_id(local_def_id)) + && matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None) + && let TyKind::Path(hir::QPath::Resolved(_, path)) = + self.tcx.hir().expect_item(local_impl_of).expect_impl().self_ty.kind + && let Res::Def(def_kind, did) = path.res + { + match def_kind { + // for example, #[derive(Default)] pub struct T(i32); + // external crate can call T::default() to construct T, + // so that don't ignore impl Default for pub Enum and Structs + DefKind::Struct | DefKind::Union if self.tcx.visibility(did).is_public() => { + return false; + } + // don't ignore impl Default for Enums, + // cause we don't know which variant is constructed + DefKind::Enum => return false, + _ => (), + }; + } + if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of) && self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads) { @@ -672,9 +691,6 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { self.handle_field_pattern_match(pat, res, fields); } PatKind::Path(ref qpath) => { - if let ty::Adt(adt, _) = self.typeck_results().node_type(pat.hir_id).kind() { - self.check_def_id(adt.did()); - } let res = self.typeck_results().qpath_res(qpath, pat.hir_id); self.handle_res(res); } @@ -830,7 +846,7 @@ fn check_item<'tcx>( // mark the method live if the self_ty is public, // or the method is public and may construct self if tcx.visibility(local_def_id).is_public() - && (ty_and_all_fields_are_public || (ty_is_public && may_construct_self)) + && (ty_and_all_fields_are_public || may_construct_self) { // if the impl item is public, // and the ty may be constructed or can be constructed in foreign crates, |
