Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion compiler/rustc_error_codes/src/error_codes/E0429.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#### Note: this error code is no longer emitted by the compiler.

The `self` keyword cannot appear alone as the last segment in a `use`
declaration.

Erroneous code example:

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

Expand Down
107 changes: 51 additions & 56 deletions compiler/rustc_resolve/src/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ use crate::macros::{MacroRulesDecl, MacroRulesScope, MacroRulesScopeRef};
use crate::ref_mut::CmCell;
use crate::{
BindingKey, Decl, DeclData, DeclKind, ExternPreludeEntry, Finalize, IdentKey, MacroData,
Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, ResolutionError, Resolver,
Segment, Used, VisResolutionError, errors,
Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, Resolver, Segment, Used,
VisResolutionError, errors,
};

type Res = def::Res<NodeId>;
Expand Down Expand Up @@ -548,18 +548,16 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {

self.r.indeterminate_imports.push(import);
match import.kind {
ImportKind::Single { target, type_ns_only, .. } => {
ImportKind::Single { target, .. } => {
// Don't add underscore imports to `single_imports`
// because they cannot define any usable names.
if target.name != kw::Underscore {
self.r.per_ns(|this, ns| {
if !type_ns_only || ns == TypeNS {
let key = BindingKey::new(IdentKey::new(target), ns);
this.resolution_or_default(current_module, key, target.span)
.borrow_mut(this)
.single_imports
.insert(import);
}
let key = BindingKey::new(IdentKey::new(target), ns);
this.resolution_or_default(current_module, key, target.span)
.borrow_mut(this)
.single_imports
.insert(import);
});
}
}
Expand Down Expand Up @@ -622,42 +620,39 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {

match use_tree.kind {
ast::UseTreeKind::Simple(rename) => {
let mut ident = use_tree.ident();
let mut module_path = prefix;
let mut source = module_path.pop().unwrap();

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

if source.ident.name == kw::SelfLower
&& let Some(parent) = module_path.pop()
{
// Suggest `use prefix::{self};` for `use prefix::self;`
if !type_ns_only
&& (parent.ident.name != kw::PathRoot
|| self.r.path_root_is_crate_root(parent.ident))
let source = module_path.pop().unwrap();

let multi_trailing_self = source.ident.name == kw::SelfLower
&& module_path
.last()
.map(|parent| parent.ident.name == kw::SelfLower)
.unwrap_or(false);

// Normalize `foo::self::self` to `foo::self`
if multi_trailing_self {
module_path.pop();
while let Some(parent) = module_path.last()
&& parent.ident.name == kw::SelfLower
{
let span_with_rename = match rename {
Some(rename) => source.ident.span.to(rename.span),
None => source.ident.span,
};

self.r.report_error(
parent.ident.span.shrink_to_hi().to(source.ident.span),
ResolutionError::SelfImportsOnlyAllowedWithin {
root: parent.ident.name == kw::PathRoot,
span_with_rename,
},
);
module_path.pop();
}
}

let self_span = source.ident.span;
source = parent;
if rename.is_none() {
ident = Ident::new(source.ident.name, self_span);
}
// Deny `use foo::self::self [as target];` but allow `use self::self as target;`
if multi_trailing_self && !module_path.is_empty() {
self.r.dcx().span_err(source.ident.span, "too many trailing `self` keywords");
}

let ident = if source.ident.name == kw::SelfLower
&& rename.is_none()
&& let Some(parent) = module_path.last()
{
Ident::new(parent.ident.name, source.ident.span)
} else {
use_tree.ident()
};

match source.ident.name {
kw::DollarCrate => {
if !module_path.is_empty() {
Expand Down Expand Up @@ -693,35 +688,35 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
return;
}
}
// Deny `use ::{self};` after edition 2015
kw::PathRoot if !self.r.path_root_is_crate_root(source.ident) => {
self.r.dcx().span_err(use_tree.span, "extern prelude cannot be imported");
return;
kw::SelfLower => {
// Deny `use ::{self};` after edition 2015
if let Some(parent) = module_path.last()
&& parent.ident.name == kw::PathRoot
&& !self.r.path_root_is_crate_root(parent.ident)
{
self.r
.dcx()
.span_err(use_tree.span, "extern prelude cannot be imported");
return;
}
}
_ => {}
_ => (),
}

// Deny importing path-kw without renaming
if rename.is_none() && ident.is_path_segment_keyword() {
let ident = use_tree.ident();

// Don't suggest `use xx::self as name;` for `use xx::self;`
// But it's OK to suggest `use xx::{self as name};` for `use xx::{self};`
let sugg = if !type_ns_only && ident.name == kw::SelfLower {
None
} else {
Some(errors::UnnamedImportSugg { span: ident.span, ident })
};

self.r.dcx().emit_err(errors::UnnamedImport { span: ident.span, sugg });
self.r.dcx().emit_err(errors::UnnamedImport {
span: ident.span,
sugg: errors::UnnamedImportSugg { span: ident.span, ident },
});
return;
}

let kind = ImportKind::Single {
source: source.ident,
target: ident,
decls: Default::default(),
type_ns_only,
nested,
id,
};
Expand Down
26 changes: 0 additions & 26 deletions compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,9 +369,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let mut suggestion = None;
let mut span = binding_span;
match import.kind {
ImportKind::Single { type_ns_only: true, .. } => {
suggestion = Some(format!("self as {suggested_name}"))
}
ImportKind::Single { source, .. } => {
if let Some(pos) = source.span.hi().0.checked_sub(binding_span.lo().0)
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(binding_span)
Expand Down Expand Up @@ -870,29 +867,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
sub_unreachable,
})
}
ResolutionError::SelfImportsOnlyAllowedWithin { root, span_with_rename } => {
// None of the suggestions below would help with a case like `use self`.
let (suggestion, mpart_suggestion) = if root {
(None, None)
} else {
// use foo::bar::self -> foo::bar
// use foo::bar::self as abc -> foo::bar as abc
let suggestion = errs::SelfImportsOnlyAllowedWithinSuggestion { span };

// use foo::bar::self -> foo::bar::{self}
// use foo::bar::self as abc -> foo::bar::{self as abc}
let mpart_suggestion = errs::SelfImportsOnlyAllowedWithinMultipartSuggestion {
multipart_start: span_with_rename.shrink_to_lo(),
multipart_end: span_with_rename.shrink_to_hi(),
};
(Some(suggestion), Some(mpart_suggestion))
};
self.dcx().create_err(errs::SelfImportsOnlyAllowedWithin {
span,
suggestion,
mpart_suggestion,
})
}
ResolutionError::FailedToResolve { segment, label, suggestion, module, message } => {
let mut err = struct_span_code_err!(self.dcx(), span, E0433, "{message}");
err.span_label(span, label);
Expand Down
36 changes: 1 addition & 35 deletions compiler/rustc_resolve/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,40 +300,6 @@ pub(crate) struct AttemptToUseNonConstantValueInConstantWithoutSuggestion<'a> {
pub(crate) suggestion: &'a str,
}

#[derive(Diagnostic)]
#[diag("`self` imports are only allowed within a {\"{\"} {\"}\"} list", code = E0429)]
pub(crate) struct SelfImportsOnlyAllowedWithin {
#[primary_span]
pub(crate) span: Span,
#[subdiagnostic]
pub(crate) suggestion: Option<SelfImportsOnlyAllowedWithinSuggestion>,
#[subdiagnostic]
pub(crate) mpart_suggestion: Option<SelfImportsOnlyAllowedWithinMultipartSuggestion>,
}

#[derive(Subdiagnostic)]
#[suggestion(
"consider importing the module directly",
code = "",
applicability = "machine-applicable"
)]
pub(crate) struct SelfImportsOnlyAllowedWithinSuggestion {
#[primary_span]
pub(crate) span: Span,
}

#[derive(Subdiagnostic)]
#[multipart_suggestion(
"alternatively, use the multi-path `use` syntax to import `self`",
applicability = "machine-applicable"
)]
pub(crate) struct SelfImportsOnlyAllowedWithinMultipartSuggestion {
#[suggestion_part(code = "{{")]
pub(crate) multipart_start: Span,
#[suggestion_part(code = "}}")]
pub(crate) multipart_end: Span,
}

#[derive(Diagnostic)]
#[diag("{$shadowing_binding}s cannot shadow {$shadowed_binding}s", code = E0530)]
pub(crate) struct BindingShadowsSomethingUnacceptable<'a> {
Expand Down Expand Up @@ -978,7 +944,7 @@ pub(crate) struct UnnamedImport {
#[primary_span]
pub(crate) span: Span,
#[subdiagnostic]
pub(crate) sugg: Option<UnnamedImportSugg>,
pub(crate) sugg: UnnamedImportSugg,
}

#[derive(Diagnostic)]
Expand Down
28 changes: 20 additions & 8 deletions compiler/rustc_resolve/src/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -953,12 +953,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
) -> Result<Decl<'ra>, Determinacy> {
match module {
ModuleOrUniformRoot::Module(module) => {
if ns == TypeNS
&& ident.name == kw::Super
&& let Some(module) =
self.resolve_super_in_module(ident, Some(module), parent_scope)
{
return Ok(module.self_decl.unwrap());
if ns == TypeNS {
if ident.name == kw::SelfLower {
return Ok(module.self_decl.unwrap());
}
if ident.name == kw::Super
&& let Some(module) =
self.resolve_super_in_module(ident, Some(module), parent_scope)
{
return Ok(module.self_decl.unwrap());
}
}

let (ident_key, def) = IdentKey::new_adjusted(ident, module.expansion);
Expand Down Expand Up @@ -1018,7 +1022,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
{
let module = self.resolve_crate_root(ident);
return Ok(module.self_decl.unwrap());
} else if ident.name == kw::Super || ident.name == kw::SelfLower {
} else if ident.name == kw::Super {
// FIXME: Implement these with renaming requirements so that e.g.
// `use super;` doesn't work, but `use super as name;` does.
// Fall through here to get an error from `early_resolve_...`.
Expand Down Expand Up @@ -1827,6 +1831,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
},
);
}

if segment_idx == 0 {
if name == kw::SelfLower {
let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0();
Expand Down Expand Up @@ -1862,8 +1867,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
}

// Support `...::self`, but deny `::self` after edition 2018
let allow_trailing_self = is_last
&& name == kw::SelfLower
&& segment_idx > 0
&& (path[segment_idx - 1].ident.name != kw::PathRoot
|| self.path_root_is_crate_root(path[segment_idx - 1].ident));

// Report special messages for path segment keywords in wrong positions.
if ident.is_path_segment_keyword() && segment_idx != 0 {
if ident.is_path_segment_keyword() && segment_idx != 0 && !allow_trailing_self {
return PathResult::failed(
ident,
false,
Expand Down
Loading
Loading