Skip to content

Commit 48029ef

Browse files
committed
Support self appear at the end of any paths, and lint redundant self
1 parent d3e8bd9 commit 48029ef

6 files changed

Lines changed: 94 additions & 92 deletions

File tree

compiler/rustc_error_codes/src/error_codes/E0429.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
#### Note: this error code is no longer emitted by the compiler.
2+
13
The `self` keyword cannot appear alone as the last segment in a `use`
24
declaration.
35

46
Erroneous code example:
57

6-
```compile_fail,E0429
8+
```ignore (error is no longer emitted)
79
use std::fmt::self; // error: `self` imports are only allowed within a { } list
810
```
911

compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ declare_lint_pass! {
8686
PUB_USE_OF_PRIVATE_EXTERN_CRATE,
8787
REDUNDANT_IMPORTS,
8888
REDUNDANT_LIFETIMES,
89+
REDUNDANT_SELF,
8990
REFINING_IMPL_TRAIT_INTERNAL,
9091
REFINING_IMPL_TRAIT_REACHABLE,
9192
RENAMED_AND_REMOVED_LINTS,
@@ -1759,6 +1760,28 @@ declare_lint! {
17591760
"detects lifetime parameters that are redundant because they are equal to some other named lifetime"
17601761
}
17611762

1763+
declare_lint! {
1764+
/// The `redundant_self` lint detects unnecessary `self` in `use` imports.
1765+
///
1766+
/// ### Example
1767+
///
1768+
/// ```rust,compile_fail
1769+
/// use foo::self;
1770+
/// use foo::self as bar;
1771+
/// use foo::{self};
1772+
/// use foo::{self as bar};
1773+
/// ```
1774+
///
1775+
/// {{produces}}
1776+
///
1777+
/// ### Explanation
1778+
///
1779+
/// The `self` segment is redundant in these forms and can be removed.
1780+
pub REDUNDANT_SELF,
1781+
Warn,
1782+
"detects redundant `self` in imports",
1783+
}
1784+
17621785
declare_lint! {
17631786
/// The `tyvar_behind_raw_pointer` lint detects raw pointer to an
17641787
/// inference variable.

compiler/rustc_resolve/src/build_reduced_graph.rs

Lines changed: 48 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use rustc_metadata::creader::LoadedMacro;
2525
use rustc_middle::metadata::{ModChild, Reexport};
2626
use rustc_middle::ty::{Feed, Visibility};
2727
use rustc_middle::{bug, span_bug};
28+
use rustc_session::lint::builtin::REDUNDANT_SELF;
2829
use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind};
2930
use rustc_span::{Ident, Span, Symbol, kw, sym};
3031
use thin_vec::ThinVec;
@@ -37,8 +38,8 @@ use crate::macros::{MacroRulesDecl, MacroRulesScope, MacroRulesScopeRef};
3738
use crate::ref_mut::CmCell;
3839
use crate::{
3940
BindingKey, Decl, DeclData, DeclKind, ExternPreludeEntry, Finalize, IdentKey, MacroData,
40-
Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, ResolutionError, Resolver,
41-
Segment, Used, VisResolutionError, errors,
41+
Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, Resolver, Segment, Used,
42+
VisResolutionError, errors,
4243
};
4344

4445
type Res = def::Res<NodeId>;
@@ -626,8 +627,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
626627
let mut module_path = prefix;
627628
let mut source = module_path.pop().unwrap();
628629

629-
// `true` for `...::{self [as target]}` imports, `false` otherwise.
630-
let type_ns_only = nested && source.ident.name == kw::SelfLower;
630+
let type_ns_only = source.ident.name == kw::SelfLower;
631631

632632
match source.ident.name {
633633
kw::DollarCrate => {
@@ -666,22 +666,19 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
666666
}
667667
kw::SelfLower => {
668668
if let Some(parent) = module_path.pop() {
669-
// Suggest `use prefix::{self};` for `use prefix::self;`
670-
if !type_ns_only
671-
&& (parent.ident.name != kw::PathRoot
672-
|| self.r.path_root_is_crate_root(parent.ident))
673-
{
674-
let span_with_rename = match rename {
675-
Some(rename) => source.ident.span.to(rename.span),
676-
None => source.ident.span,
677-
};
678-
679-
self.r.report_error(
680-
parent.ident.span.shrink_to_hi().to(source.ident.span),
681-
ResolutionError::SelfImportsOnlyAllowedWithin {
682-
root: parent.ident.name == kw::PathRoot,
683-
span_with_rename,
684-
},
669+
// `true` for `...::{self [as target]}` imports, `false` otherwise.
670+
let nested_self = nested
671+
&& source.ident.name == kw::SelfLower
672+
&& use_tree.prefix.segments.len() == 1;
673+
674+
// Lint `use ...::self [as target];`
675+
if !nested_self && parent.ident.name != kw::PathRoot {
676+
let span = parent.ident.span.shrink_to_hi().to(source.ident.span);
677+
self.r.lint_buffer().buffer_lint(
678+
REDUNDANT_SELF,
679+
item.id,
680+
source.ident.span,
681+
errors::RedundantSelfDiag::Remove { span },
685682
);
686683
}
687684

@@ -706,16 +703,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
706703
// Deny importing path-kw without renaming
707704
if rename.is_none() && ident.is_path_segment_keyword() {
708705
let ident = use_tree.ident();
709-
710-
// Don't suggest `use xx::self as name;` for `use xx::self;`
711-
// But it's OK to suggest `use xx::{self as name};` for `use xx::{self};`
712-
let sugg = if !type_ns_only && ident.name == kw::SelfLower {
713-
None
714-
} else {
715-
Some(errors::UnnamedImportSugg { span: ident.span, ident })
716-
};
717-
718-
self.r.dcx().emit_err(errors::UnnamedImport { span: ident.span, sugg });
706+
self.r.dcx().emit_err(errors::UnnamedImport {
707+
span: ident.span,
708+
sugg: errors::UnnamedImportSugg { span: ident.span, ident },
709+
});
719710
return;
720711
}
721712

@@ -745,7 +736,33 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
745736
}
746737
}
747738
}
748-
ast::UseTreeKind::Nested { ref items, .. } => {
739+
ast::UseTreeKind::Nested { ref items, span } => {
740+
// Lint `use ...::{self [as target]};`
741+
if let Some(parent) = prefix.last()
742+
&& parent.ident.name != kw::PathRoot
743+
&& let [(tree, _)] = &items[..]
744+
&& let ast::UseTreeKind::Simple(rename) = tree.kind
745+
&& let [segment] = &tree.prefix.segments[..]
746+
&& segment.ident.name == kw::SelfLower
747+
{
748+
let span = parent.ident.span.shrink_to_hi().to(span);
749+
if let Some(rename) = rename {
750+
self.r.lint_buffer().buffer_lint(
751+
REDUNDANT_SELF,
752+
item.id,
753+
segment.ident.span,
754+
errors::RedundantSelfDiag::Replace { span, rename },
755+
);
756+
} else {
757+
self.r.lint_buffer().buffer_lint(
758+
REDUNDANT_SELF,
759+
item.id,
760+
segment.ident.span,
761+
errors::RedundantSelfDiag::Remove { span },
762+
);
763+
}
764+
}
765+
749766
for &(ref tree, id) in items {
750767
self.build_reduced_graph_for_use_tree(
751768
// This particular use tree

compiler/rustc_resolve/src/diagnostics.rs

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -870,29 +870,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
870870
sub_unreachable,
871871
})
872872
}
873-
ResolutionError::SelfImportsOnlyAllowedWithin { root, span_with_rename } => {
874-
// None of the suggestions below would help with a case like `use self`.
875-
let (suggestion, mpart_suggestion) = if root {
876-
(None, None)
877-
} else {
878-
// use foo::bar::self -> foo::bar
879-
// use foo::bar::self as abc -> foo::bar as abc
880-
let suggestion = errs::SelfImportsOnlyAllowedWithinSuggestion { span };
881-
882-
// use foo::bar::self -> foo::bar::{self}
883-
// use foo::bar::self as abc -> foo::bar::{self as abc}
884-
let mpart_suggestion = errs::SelfImportsOnlyAllowedWithinMultipartSuggestion {
885-
multipart_start: span_with_rename.shrink_to_lo(),
886-
multipart_end: span_with_rename.shrink_to_hi(),
887-
};
888-
(Some(suggestion), Some(mpart_suggestion))
889-
};
890-
self.dcx().create_err(errs::SelfImportsOnlyAllowedWithin {
891-
span,
892-
suggestion,
893-
mpart_suggestion,
894-
})
895-
}
896873
ResolutionError::FailedToResolve { segment, label, suggestion, module, message } => {
897874
let mut err = struct_span_code_err!(self.dcx(), span, E0433, "{message}");
898875
err.span_label(span, label);

compiler/rustc_resolve/src/errors.rs

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -300,40 +300,6 @@ pub(crate) struct AttemptToUseNonConstantValueInConstantWithoutSuggestion<'a> {
300300
pub(crate) suggestion: &'a str,
301301
}
302302

303-
#[derive(Diagnostic)]
304-
#[diag("`self` imports are only allowed within a {\"{\"} {\"}\"} list", code = E0429)]
305-
pub(crate) struct SelfImportsOnlyAllowedWithin {
306-
#[primary_span]
307-
pub(crate) span: Span,
308-
#[subdiagnostic]
309-
pub(crate) suggestion: Option<SelfImportsOnlyAllowedWithinSuggestion>,
310-
#[subdiagnostic]
311-
pub(crate) mpart_suggestion: Option<SelfImportsOnlyAllowedWithinMultipartSuggestion>,
312-
}
313-
314-
#[derive(Subdiagnostic)]
315-
#[suggestion(
316-
"consider importing the module directly",
317-
code = "",
318-
applicability = "machine-applicable"
319-
)]
320-
pub(crate) struct SelfImportsOnlyAllowedWithinSuggestion {
321-
#[primary_span]
322-
pub(crate) span: Span,
323-
}
324-
325-
#[derive(Subdiagnostic)]
326-
#[multipart_suggestion(
327-
"alternatively, use the multi-path `use` syntax to import `self`",
328-
applicability = "machine-applicable"
329-
)]
330-
pub(crate) struct SelfImportsOnlyAllowedWithinMultipartSuggestion {
331-
#[suggestion_part(code = "{{")]
332-
pub(crate) multipart_start: Span,
333-
#[suggestion_part(code = "}}")]
334-
pub(crate) multipart_end: Span,
335-
}
336-
337303
#[derive(Diagnostic)]
338304
#[diag("{$shadowing_binding}s cannot shadow {$shadowed_binding}s", code = E0530)]
339305
pub(crate) struct BindingShadowsSomethingUnacceptable<'a> {
@@ -968,7 +934,7 @@ pub(crate) struct UnnamedImport {
968934
#[primary_span]
969935
pub(crate) span: Span,
970936
#[subdiagnostic]
971-
pub(crate) sugg: Option<UnnamedImportSugg>,
937+
pub(crate) sugg: UnnamedImportSugg,
972938
}
973939

974940
#[derive(Diagnostic)]
@@ -1565,3 +1531,22 @@ impl<'a> LintDiagnostic<'a, ()> for Ambiguity {
15651531
self.decorate(diag);
15661532
}
15671533
}
1534+
1535+
#[derive(LintDiagnostic)]
1536+
pub(crate) enum RedundantSelfDiag {
1537+
#[diag("unnecessary `self`")]
1538+
Remove {
1539+
#[suggestion("consider removing this", code = "", applicability = "machine-applicable")]
1540+
span: Span,
1541+
},
1542+
#[diag("unnecessary `self`")]
1543+
Replace {
1544+
#[suggestion(
1545+
"consider replacing this with",
1546+
code = " as {rename}",
1547+
applicability = "machine-applicable"
1548+
)]
1549+
span: Span,
1550+
rename: Ident,
1551+
},
1552+
}

compiler/rustc_resolve/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,6 @@ enum ResolutionError<'ra> {
272272
IdentifierBoundMoreThanOnceInSamePattern(Ident),
273273
/// Error E0426: use of undeclared label.
274274
UndeclaredLabel { name: Symbol, suggestion: Option<LabelSuggestion> },
275-
/// Error E0429: `self` imports are only allowed within a `{ }` list.
276-
SelfImportsOnlyAllowedWithin { root: bool, span_with_rename: Span },
277275
/// Error E0433: failed to resolve.
278276
FailedToResolve {
279277
segment: Symbol,

0 commit comments

Comments
 (0)