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/E0430.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#### Note: this error code is no longer emitted by the compiler.

The `self` import appears more than once in the list.

Erroneous code example:

```compile_fail,E0430
```ignore (error is no longer emitted)
use something::{self, self}; // error: `self` import can only appear once in
// the list
```
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_error_codes/src/error_codes/E0431.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#### Note: this error code is no longer emitted by the compiler.

An invalid `self` import was made.

Erroneous code example:

```compile_fail,E0431
```ignore (error is no longer emitted)
use {self}; // error: `self` import can only appear in an import list with a
// non-empty prefix
```
Expand Down
11 changes: 3 additions & 8 deletions compiler/rustc_resolve/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -373,14 +373,6 @@ resolve_remove_surrounding_derive =

resolve_remove_unnecessary_import = remove unnecessary import

resolve_self_import_can_only_appear_once_in_the_list =
`self` import can only appear once in an import list
.label = can only appear once in an import list

resolve_self_import_only_in_import_list_with_non_empty_prefix =
`self` import can only appear in an import list with a non-empty prefix
.label = can only appear in an import list with a non-empty prefix

resolve_self_imports_only_allowed_within =
`self` imports are only allowed within a {"{"} {"}"} list

Expand Down Expand Up @@ -463,6 +455,9 @@ resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg =
resolve_unnamed_crate_root_import =
crate root imports need to be explicitly named: `use crate as name;`

resolve_unnamed_super_or_self_import = imports need to be explicitly named
resolve_unnamed_super_or_self_sugg_import = try renaming it with a name

resolve_unreachable_label =
use of unreachable label `{$name}`
.label = unreachable label `{$name}`
Expand Down
160 changes: 81 additions & 79 deletions compiler/rustc_resolve/src/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -572,63 +572,54 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
let mut ident = use_tree.ident();
let mut module_path = prefix;
let mut source = module_path.pop().unwrap();
let mut type_ns_only = false;

if nested {
// Correctly handle `self`
if source.ident.name == kw::SelfLower {
type_ns_only = true;

if empty_for_self(&module_path) {
self.r.report_error(
use_tree.span,
ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix,
let type_ns_only = nested
&& source.ident.name == kw::SelfLower
&& use_tree.prefix.segments.len() == 1;

match source.ident.name {
kw::Crate => {
if !module_path.is_empty() {
self.r.dcx().span_err(
source.ident.span,
"`crate` in paths can only be used in start position",
);
return;
}

// Replace `use foo::{ self };` with `use foo;`
let self_span = source.ident.span;
source = module_path.pop().unwrap();
if rename.is_none() {
// Keep the span of `self`, but the name of `foo`
ident = Ident::new(source.ident.name, self_span);
}
}
} else {
// Disallow `self`
if source.ident.name == kw::SelfLower {
let parent = module_path.last();

let span = match parent {
// only `::self` from `use foo::self as bar`
Some(seg) => seg.ident.span.shrink_to_hi().to(source.ident.span),
None => source.ident.span,
};
let span_with_rename = match rename {
// only `self as bar` from `use foo::self as bar`
Some(rename) => source.ident.span.to(rename.span),
None => source.ident.span,
};
self.r.report_error(
span,
ResolutionError::SelfImportsOnlyAllowedWithin {
root: parent.is_none(),
span_with_rename,
},
);

// Error recovery: replace `use foo::self;` with `use foo;`
kw::SelfLower => {
if let Some(parent) = module_path.pop() {
let span_with_rename = match rename {
Some(rename) => source.ident.span.to(rename.span),
None => source.ident.span,
};

// Suggest `use prefix::{self};` for `use prefix::self;`
if !type_ns_only && parent.ident.name != kw::PathRoot {
self.r.report_error(
parent.ident.span.shrink_to_hi().to(source.ident.span),
ResolutionError::SelfImportsOnlyAllowedWithin {
root: false,
span_with_rename,
},
);
}

let self_span = source.ident.span;
source = parent;
if rename.is_none() {
ident = source.ident;
ident = Ident::new(source.ident.name, self_span);
}
}
}
kw::DollarCrate => {
if !module_path.is_empty() {
self.r.dcx().span_err(
source.ident.span,
"`$crate` in paths can only be used in start position",
);
return;
}

// Disallow `use $crate;`
if source.ident.name == kw::DollarCrate && module_path.is_empty() {
let crate_root = self.r.resolve_crate_root(source.ident);
let crate_name = match crate_root.kind {
ModuleKind::Def(.., name) => name,
Expand All @@ -645,16 +636,53 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
));
source.ident.name = crate_name;
}
if rename.is_none() {
ident.name = sym::dummy;
}

self.r.dcx().emit_err(errors::CrateImported { span: item.span });
}
_ => {}
}

if ident.name == kw::Crate {
self.r.dcx().emit_err(errors::UnnamedCrateRootImport { span: ident.span });
// Deny `use ::{self};`
if source.ident.name == kw::PathRoot {
self.r.dcx().span_err(use_tree.span, "crate root cannot be imported");
return;
}

if rename.is_none() {
match ident.name {
// Deny `use crate;` and `use crate::{self};`
kw::Crate => {
self.r
.dcx()
.emit_err(errors::UnnamedCrateRootImport { span: ident.span });
return;
}
// Deny `use $crate;` and `use $crate::{self};`
kw::DollarCrate => {
self.r.dcx().emit_err(errors::CrateImported { span: ident.span });
return;
}
// Deny `use super;`, `use super::{self};`, `use self;` and `use self::{self};`
kw::Super | kw::SelfLower => {
let ident = use_tree.ident();

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

self.r.dcx().emit_err(errors::UnnamedSuperOrSelfImport {
span: ident.span,
sugg,
});
return;
}
_ => (),
}
}

let kind = ImportKind::Single {
Expand Down Expand Up @@ -684,32 +712,6 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
}
}
ast::UseTreeKind::Nested { ref items, .. } => {
// Ensure there is at most one `self` in the list
let self_spans = items
.iter()
.filter_map(|(use_tree, _)| {
if let ast::UseTreeKind::Simple(..) = use_tree.kind
&& use_tree.ident().name == kw::SelfLower
{
return Some(use_tree.span);
}

None
})
.collect::<Vec<_>>();
if self_spans.len() > 1 {
let mut e = self.r.into_struct_error(
self_spans[0],
ResolutionError::SelfImportCanOnlyAppearOnceInTheList,
);

for other_span in self_spans.iter().skip(1) {
e.span_label(*other_span, "another `self` import appears here");
}

e.emit();
}

for &(ref tree, id) in items {
self.build_reduced_graph_for_use_tree(
// This particular use tree
Expand Down
6 changes: 0 additions & 6 deletions compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -890,12 +890,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
mpart_suggestion,
})
}
ResolutionError::SelfImportCanOnlyAppearOnceInTheList => {
self.dcx().create_err(errs::SelfImportCanOnlyAppearOnceInTheList { span })
}
ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => {
self.dcx().create_err(errs::SelfImportOnlyInImportListWithNonEmptyPrefix { span })
}
ResolutionError::FailedToResolve { segment, label, suggestion, module } => {
let mut err =
struct_span_code_err!(self.dcx(), span, E0433, "failed to resolve: {label}");
Expand Down
37 changes: 21 additions & 16 deletions compiler/rustc_resolve/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,22 +204,6 @@ pub(crate) struct UnreachableLabelWithSimilarNameExists {
pub(crate) ident_span: Span,
}

#[derive(Diagnostic)]
#[diag(resolve_self_import_can_only_appear_once_in_the_list, code = E0430)]
pub(crate) struct SelfImportCanOnlyAppearOnceInTheList {
#[primary_span]
#[label]
pub(crate) span: Span,
}

#[derive(Diagnostic)]
#[diag(resolve_self_import_only_in_import_list_with_non_empty_prefix, code = E0431)]
pub(crate) struct SelfImportOnlyInImportListWithNonEmptyPrefix {
#[primary_span]
#[label]
pub(crate) span: Span,
}

#[derive(Diagnostic)]
#[diag(resolve_cannot_capture_dynamic_environment_in_fn_item, code = E0434)]
#[help]
Expand Down Expand Up @@ -898,6 +882,27 @@ pub(crate) struct UnnamedCrateRootImport {
pub(crate) span: Span,
}

#[derive(Subdiagnostic)]
#[multipart_suggestion(
resolve_unnamed_super_or_self_sugg_import,
applicability = "maybe-incorrect",
style = "verbose"
)]
pub(crate) struct UnnamedSuperOrSelfImportSugg {
#[suggestion_part(code = "{ident} as name")]
pub(crate) span: Span,
pub(crate) ident: Ident,
}

#[derive(Diagnostic)]
#[diag(resolve_unnamed_super_or_self_import)]
pub(crate) struct UnnamedSuperOrSelfImport {
#[primary_span]
pub(crate) span: Span,
#[subdiagnostic]
pub(crate) sugg: Option<UnnamedSuperOrSelfImportSugg>,
}

#[derive(Diagnostic)]
#[diag(resolve_macro_expanded_extern_crate_cannot_shadow_extern_arguments)]
pub(crate) struct MacroExpandedExternCrateCannotShadowExternArguments {
Expand Down
22 changes: 17 additions & 5 deletions compiler/rustc_resolve/src/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -828,7 +828,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ignore_import: Option<Import<'ra>>,
) -> Result<NameBinding<'ra>, (Determinacy, Weak)> {
let module = match module {
ModuleOrUniformRoot::Module(module) => module,
ModuleOrUniformRoot::Module(module) => {
if ns == TypeNS {
if ident.name == kw::Super {
if let Some(parent) = module.parent {
return Ok(parent.self_binding.unwrap());
}
}
}

module
}
ModuleOrUniformRoot::ModuleAndExternPrelude(module) => {
assert_eq!(shadowing, Shadowing::Unrestricted);
let binding = self.resolve_ident_in_scope_set(
Expand Down Expand Up @@ -865,10 +875,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
if ident.name == kw::Crate || ident.name == kw::DollarCrate {
let module = self.resolve_crate_root(ident);
return Ok(module.self_binding.unwrap());
} else if ident.name == kw::Super || ident.name == kw::SelfLower {
// 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_...`.
} else if ident.name == kw::Super {
if let Some(parent) = parent_scope.module.parent {
return Ok(parent.self_binding.unwrap());
}
} else if ident.name == kw::SelfLower {
return Ok(parent_scope.module.self_binding.unwrap());
}
}

Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,10 +263,6 @@ enum ResolutionError<'ra> {
UndeclaredLabel { name: Symbol, suggestion: Option<LabelSuggestion> },
/// Error E0429: `self` imports are only allowed within a `{ }` list.
SelfImportsOnlyAllowedWithin { root: bool, span_with_rename: Span },
/// Error E0430: `self` import can only appear once in the list.
SelfImportCanOnlyAppearOnceInTheList,
/// Error E0431: `self` import can only appear in an import list with a non-empty prefix.
SelfImportOnlyInImportListWithNonEmptyPrefix,
/// Error E0433: failed to resolve.
FailedToResolve {
segment: Option<Symbol>,
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/delegation/target-expr-pass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ struct S(F); //~ WARN struct `S` is never constructed
impl Trait for S {
reuse <F as Trait>::bar {
#[allow(unused_imports)]
use self::to_reuse::{foo, inner::self};
use self::to_reuse::{foo, inner::{self}};
let x = foo(12);
assert_eq!(x, 12);
&self.0
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/dollar-crate/dollar-crate-is-keyword-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ mod a {}

macro_rules! m {
() => {
use a::$crate; //~ ERROR unresolved import `a::$crate`
use a::$crate; //~ ERROR `$crate` in paths can only be used in start position
use a::$crate::b; //~ ERROR `$crate` in paths can only be used in start position
type A = a::$crate; //~ ERROR `$crate` in paths can only be used in start position
}
Expand Down
Loading
Loading