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
74 changes: 28 additions & 46 deletions compiler/rustc_resolve/src/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,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, Res, ResolutionError,
Resolver, Segment, Used, VisResolutionError, errors,
Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, Res, Resolver, Segment, Used,
VisResolutionError, errors,
};

impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
Expand Down Expand Up @@ -549,18 +549,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 @@ -629,30 +627,8 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
let mut module_path = prefix;
let source = module_path.pop().unwrap();

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

// Suggest `use prefix::{self};` for `use prefix::self;`
if source.ident.name == kw::SelfLower
&& let Some(parent) = module_path.last()
&& !type_ns_only
&& (parent.ident.name != kw::PathRoot
|| self.r.path_root_is_crate_root(parent.ident))
{
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,
},
);
}

// If the identifier is `self` without a rename,
// then it is replaced with the parent identifier.
let ident = if source.ident.name == kw::SelfLower
&& rename.is_none()
&& let Some(parent) = module_path.last()
Expand Down Expand Up @@ -706,30 +682,36 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
self.r.dcx().span_err(use_tree.span(), "extern prelude cannot be imported");
return;
}
_ => {}
_ => (),
}

// Deny `use ...::self::source [as target];` or `use ...::self::self [as target];`,
// but allow `use self::source [as target];` and `use self::self as target;`.
if let Some(parent) = module_path.last()
&& parent.ident.name == kw::SelfLower
&& module_path.len() > 1
Comment thread
mu001999 marked this conversation as resolved.
{
self.r.dcx().span_err(
parent.ident.span,
"`self` in paths can only be used in start position or last position",
);
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 @@ -386,9 +386,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 @@ -913,29 +910,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 @@ -301,40 +301,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 @@ -998,7 +964,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
12 changes: 11 additions & 1 deletion compiler/rustc_resolve/src/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1838,8 +1838,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
}

let allow_trailing_self = is_last && name == kw::SelfLower;

// 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 All @@ -1859,6 +1861,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
format!("global paths cannot start with {name_str}"),
"cannot start with this".to_string(),
)
} else if name == kw::SelfLower {
(
format!(
"`self` in paths can only be used in start position or last position"
),
"can only be used in path start position or last position"
.to_string(),
)
} else {
(
format!("{name_str} in paths can only be used in start position"),
Expand Down
Loading
Loading