Skip to content

Commit 2e7e52e

Browse files
committed
detect when variants have the same name as an associated function
1 parent 975741c commit 2e7e52e

File tree

4 files changed

+54
-1
lines changed

4 files changed

+54
-1
lines changed

compiler/rustc_passes/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,9 @@ passes_duplicate_lang_item_crate_depends =
290290
.first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path}
291291
.second_definition_path = second definition in `{$crate_name}` loaded from {$path}
292292
293+
passes_enum_variant_same_name =
294+
it is impossible to refer to the {$descr} `{$dead_name}` because it is shadowed by this enum variant with the same name
295+
293296
passes_export_name =
294297
attribute should be applied to a free function, impl method or static
295298
.label = not a free function, impl method or static

compiler/rustc_passes/src/dead.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_errors::MultiSpan;
1414
use rustc_hir::def::{CtorOf, DefKind, Res};
1515
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
1616
use rustc_hir::intravisit::{self, Visitor};
17-
use rustc_hir::{self as hir, Node, PatKind, QPath, TyKind};
17+
use rustc_hir::{self as hir, ImplItem, ImplItemKind, Node, PatKind, QPath, TyKind};
1818
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
1919
use rustc_middle::middle::privacy::Level;
2020
use rustc_middle::query::Providers;
@@ -936,7 +936,9 @@ enum ShouldWarnAboutField {
936936

937937
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
938938
enum ReportOn {
939+
/// Report on something that hasn't got a proper name to refer to
939940
TupleField,
941+
/// Report on something that has got a name, which could be a field but also a method
940942
NamedField,
941943
}
942944

@@ -1061,6 +1063,31 @@ impl<'tcx> DeadVisitor<'tcx> {
10611063
None
10621064
};
10631065

1066+
let enum_variants_with_same_name = dead_codes
1067+
.iter()
1068+
.filter_map(|dead_item| {
1069+
if let Node::ImplItem(ImplItem {
1070+
kind: ImplItemKind::Fn(..) | ImplItemKind::Const(..),
1071+
..
1072+
}) = tcx.hir_node_by_def_id(dead_item.def_id)
1073+
&& let Some(impl_did) = tcx.opt_parent(dead_item.def_id.to_def_id())
1074+
&& let DefKind::Impl { of_trait: false } = tcx.def_kind(impl_did)
1075+
&& let ty::Adt(maybe_enum, _) = tcx.type_of(impl_did).skip_binder().kind()
1076+
&& maybe_enum.is_enum()
1077+
&& let Some(variant) =
1078+
maybe_enum.variants().iter().find(|i| i.name == dead_item.name)
1079+
{
1080+
Some(crate::errors::EnumVariantSameName {
1081+
descr: tcx.def_descr(dead_item.def_id.to_def_id()),
1082+
dead_name: dead_item.name,
1083+
variant_span: tcx.def_span(variant.def_id),
1084+
})
1085+
} else {
1086+
None
1087+
}
1088+
})
1089+
.collect();
1090+
10641091
let diag = match report_on {
10651092
ReportOn::TupleField => {
10661093
let tuple_fields = if let Some(parent_id) = parent_item
@@ -1114,6 +1141,7 @@ impl<'tcx> DeadVisitor<'tcx> {
11141141
name_list,
11151142
parent_info,
11161143
ignored_derived_impls,
1144+
enum_variants_with_same_name,
11171145
},
11181146
};
11191147

compiler/rustc_passes/src/errors.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,6 +1478,9 @@ pub(crate) enum MultipleDeadCodes<'tcx> {
14781478
participle: &'tcx str,
14791479
name_list: DiagSymbolList,
14801480
#[subdiagnostic]
1481+
// only on DeadCodes since it's never a problem for tuple struct fields
1482+
enum_variants_with_same_name: Vec<EnumVariantSameName<'tcx>>,
1483+
#[subdiagnostic]
14811484
parent_info: Option<ParentInfo<'tcx>>,
14821485
#[subdiagnostic]
14831486
ignored_derived_impls: Option<IgnoredDerivedImpls>,
@@ -1498,6 +1501,15 @@ pub(crate) enum MultipleDeadCodes<'tcx> {
14981501
},
14991502
}
15001503

1504+
#[derive(Subdiagnostic)]
1505+
#[note(passes_enum_variant_same_name)]
1506+
pub(crate) struct EnumVariantSameName<'tcx> {
1507+
#[primary_span]
1508+
pub variant_span: Span,
1509+
pub dead_name: Symbol,
1510+
pub descr: &'tcx str,
1511+
}
1512+
15011513
#[derive(Subdiagnostic)]
15021514
#[label(passes_parent_info)]
15031515
pub(crate) struct ParentInfo<'tcx> {

tests/ui/enum/dead-code-associated-function.stderr

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@ LL | fn F() {}
1010
LL | const C: () = ();
1111
| ^
1212
|
13+
note: it is impossible to refer to the associated function `F` because it is shadowed by this enum variant with the same name
14+
--> $DIR/dead-code-associated-function.rs:5:5
15+
|
16+
LL | F(),
17+
| ^
18+
note: it is impossible to refer to the associated constant `C` because it is shadowed by this enum variant with the same name
19+
--> $DIR/dead-code-associated-function.rs:6:5
20+
|
21+
LL | C(),
22+
| ^
1323
note: the lint level is defined here
1424
--> $DIR/dead-code-associated-function.rs:2:9
1525
|

0 commit comments

Comments
 (0)