Skip to content

Commit c5bb3f1

Browse files
committed
Rewrite build_reduced_graph_for_use_tree
1 parent 5934b06 commit c5bb3f1

27 files changed

+728
-916
lines changed

compiler/rustc_error_codes/src/error_codes/E0430.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
#### Note: this error code is no longer emitted by the compiler.
2+
13
The `self` import appears more than once in the list.
24

35
Erroneous code example:
46

5-
```compile_fail,E0430
7+
```ignore (error is no longer emitted)
68
use something::{self, self}; // error: `self` import can only appear once in
79
// the list
810
```

compiler/rustc_error_codes/src/error_codes/E0431.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
#### Note: this error code is no longer emitted by the compiler.
2+
13
An invalid `self` import was made.
24

35
Erroneous code example:
46

5-
```compile_fail,E0431
7+
```ignore (error is no longer emitted)
68
use {self}; // error: `self` import can only appear in an import list with a
79
// non-empty prefix
810
```

compiler/rustc_resolve/messages.ftl

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -379,14 +379,6 @@ resolve_remove_surrounding_derive =
379379
380380
resolve_remove_unnecessary_import = remove unnecessary import
381381
382-
resolve_self_import_can_only_appear_once_in_the_list =
383-
`self` import can only appear once in an import list
384-
.label = can only appear once in an import list
385-
386-
resolve_self_import_only_in_import_list_with_non_empty_prefix =
387-
`self` import can only appear in an import list with a non-empty prefix
388-
.label = can only appear in an import list with a non-empty prefix
389-
390382
resolve_self_imports_only_allowed_within =
391383
`self` imports are only allowed within a {"{"} {"}"} list
392384
@@ -469,6 +461,9 @@ resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg =
469461
resolve_unnamed_crate_root_import =
470462
crate root imports need to be explicitly named: `use crate as name;`
471463
464+
resolve_unnamed_super_or_self_import = imports need to be explicitly named
465+
resolve_unnamed_super_or_self_sugg_import = try renaming it with a name
466+
472467
resolve_unreachable_label =
473468
use of unreachable label `{$name}`
474469
.label = unreachable label `{$name}`

compiler/rustc_resolve/src/build_reduced_graph.rs

Lines changed: 89 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -572,63 +572,63 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
572572
let mut ident = use_tree.ident();
573573
let mut module_path = prefix;
574574
let mut source = module_path.pop().unwrap();
575-
let mut type_ns_only = false;
576-
577-
if nested {
578-
// Correctly handle `self`
579-
if source.ident.name == kw::SelfLower {
580-
type_ns_only = true;
581-
582-
if empty_for_self(&module_path) {
583-
self.r.report_error(
584-
use_tree.span,
585-
ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix,
575+
let type_ns_only = nested
576+
&& source.ident.name == kw::SelfLower
577+
&& use_tree.prefix.segments.len() == 1;
578+
579+
match source.ident.name {
580+
kw::Crate => {
581+
if !module_path.is_empty() {
582+
self.r.dcx().span_err(
583+
source.ident.span,
584+
"`crate` in paths can only be used in start position",
586585
);
587586
return;
588587
}
589-
590-
// Replace `use foo::{ self };` with `use foo;`
591-
let self_span = source.ident.span;
592-
source = module_path.pop().unwrap();
593-
if rename.is_none() {
594-
// Keep the span of `self`, but the name of `foo`
595-
ident = Ident::new(source.ident.name, self_span);
588+
}
589+
kw::Super => {
590+
if module_path.iter().any(|seg| seg.ident.name != kw::Super) {
591+
self.r.dcx().span_err(
592+
source.ident.span,
593+
"`super` in paths can only be used in start position or after another `super`",
594+
);
595+
return;
596596
}
597597
}
598-
} else {
599-
// Disallow `self`
600-
if source.ident.name == kw::SelfLower {
601-
let parent = module_path.last();
602-
603-
let span = match parent {
604-
// only `::self` from `use foo::self as bar`
605-
Some(seg) => seg.ident.span.shrink_to_hi().to(source.ident.span),
606-
None => source.ident.span,
607-
};
608-
let span_with_rename = match rename {
609-
// only `self as bar` from `use foo::self as bar`
610-
Some(rename) => source.ident.span.to(rename.span),
611-
None => source.ident.span,
612-
};
613-
self.r.report_error(
614-
span,
615-
ResolutionError::SelfImportsOnlyAllowedWithin {
616-
root: parent.is_none(),
617-
span_with_rename,
618-
},
619-
);
620-
621-
// Error recovery: replace `use foo::self;` with `use foo;`
598+
kw::SelfLower => {
622599
if let Some(parent) = module_path.pop() {
600+
let span_with_rename = match rename {
601+
Some(rename) => source.ident.span.to(rename.span),
602+
None => source.ident.span,
603+
};
604+
605+
// Suggest `use prefix::{self};` for `use prefix::self;`
606+
if !type_ns_only && parent.ident.name != kw::PathRoot {
607+
self.r.report_error(
608+
parent.ident.span.shrink_to_hi().to(source.ident.span),
609+
ResolutionError::SelfImportsOnlyAllowedWithin {
610+
root: false,
611+
span_with_rename,
612+
},
613+
);
614+
}
615+
616+
let self_span = source.ident.span;
623617
source = parent;
624618
if rename.is_none() {
625-
ident = source.ident;
619+
ident = Ident::new(source.ident.name, self_span);
626620
}
627621
}
628622
}
623+
kw::DollarCrate => {
624+
if !module_path.is_empty() {
625+
self.r.dcx().span_err(
626+
source.ident.span,
627+
"`$crate` in paths can only be used in start position",
628+
);
629+
return;
630+
}
629631

630-
// Disallow `use $crate;`
631-
if source.ident.name == kw::DollarCrate && module_path.is_empty() {
632632
let crate_root = self.r.resolve_crate_root(source.ident);
633633
let crate_name = match crate_root.kind {
634634
ModuleKind::Def(.., name) => name,
@@ -645,16 +645,53 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
645645
));
646646
source.ident.name = crate_name;
647647
}
648-
if rename.is_none() {
649-
ident.name = sym::dummy;
650-
}
651-
652-
self.r.dcx().emit_err(errors::CrateImported { span: item.span });
653648
}
649+
_ => {}
654650
}
655651

656-
if ident.name == kw::Crate {
657-
self.r.dcx().emit_err(errors::UnnamedCrateRootImport { span: ident.span });
652+
// Deny `use ::{self};`
653+
if source.ident.name == kw::PathRoot {
654+
self.r.dcx().span_err(use_tree.span, "crate root cannot be imported");
655+
return;
656+
}
657+
658+
if rename.is_none() {
659+
match ident.name {
660+
// Deny `use crate;` and `use crate::{self};`
661+
kw::Crate => {
662+
self.r
663+
.dcx()
664+
.emit_err(errors::UnnamedCrateRootImport { span: ident.span });
665+
return;
666+
}
667+
// Deny `use $crate;` and `use $crate::{self};`
668+
kw::DollarCrate => {
669+
self.r.dcx().emit_err(errors::CrateImported { span: ident.span });
670+
return;
671+
}
672+
// Deny `use super;`, `use super::{self};`, `use self;` and `use self::{self};`
673+
kw::Super | kw::SelfLower => {
674+
let ident = use_tree.ident();
675+
676+
// Don't suggest `use super::self as name;` for `use super::self;`
677+
// But it's OK to suggest `use super::{self as name};` for `use super::{self};`
678+
let sugg = if !type_ns_only && ident.name == kw::SelfLower {
679+
None
680+
} else {
681+
Some(errors::UnnamedSuperOrSelfImportSugg {
682+
span: ident.span,
683+
ident,
684+
})
685+
};
686+
687+
self.r.dcx().emit_err(errors::UnnamedSuperOrSelfImport {
688+
span: ident.span,
689+
sugg,
690+
});
691+
return;
692+
}
693+
_ => (),
694+
}
658695
}
659696

660697
let kind = ImportKind::Single {
@@ -684,32 +721,6 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
684721
}
685722
}
686723
ast::UseTreeKind::Nested { ref items, .. } => {
687-
// Ensure there is at most one `self` in the list
688-
let self_spans = items
689-
.iter()
690-
.filter_map(|(use_tree, _)| {
691-
if let ast::UseTreeKind::Simple(..) = use_tree.kind
692-
&& use_tree.ident().name == kw::SelfLower
693-
{
694-
return Some(use_tree.span);
695-
}
696-
697-
None
698-
})
699-
.collect::<Vec<_>>();
700-
if self_spans.len() > 1 {
701-
let mut e = self.r.into_struct_error(
702-
self_spans[0],
703-
ResolutionError::SelfImportCanOnlyAppearOnceInTheList,
704-
);
705-
706-
for other_span in self_spans.iter().skip(1) {
707-
e.span_label(*other_span, "another `self` import appears here");
708-
}
709-
710-
e.emit();
711-
}
712-
713724
for &(ref tree, id) in items {
714725
self.build_reduced_graph_for_use_tree(
715726
// This particular use tree

compiler/rustc_resolve/src/diagnostics.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -901,12 +901,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
901901
mpart_suggestion,
902902
})
903903
}
904-
ResolutionError::SelfImportCanOnlyAppearOnceInTheList => {
905-
self.dcx().create_err(errs::SelfImportCanOnlyAppearOnceInTheList { span })
906-
}
907-
ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => {
908-
self.dcx().create_err(errs::SelfImportOnlyInImportListWithNonEmptyPrefix { span })
909-
}
910904
ResolutionError::FailedToResolve { segment, label, suggestion, module } => {
911905
let mut err =
912906
struct_span_code_err!(self.dcx(), span, E0433, "failed to resolve: {label}");

compiler/rustc_resolve/src/errors.rs

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -232,22 +232,6 @@ pub(crate) struct UnreachableLabelWithSimilarNameExists {
232232
pub(crate) ident_span: Span,
233233
}
234234

235-
#[derive(Diagnostic)]
236-
#[diag(resolve_self_import_can_only_appear_once_in_the_list, code = E0430)]
237-
pub(crate) struct SelfImportCanOnlyAppearOnceInTheList {
238-
#[primary_span]
239-
#[label]
240-
pub(crate) span: Span,
241-
}
242-
243-
#[derive(Diagnostic)]
244-
#[diag(resolve_self_import_only_in_import_list_with_non_empty_prefix, code = E0431)]
245-
pub(crate) struct SelfImportOnlyInImportListWithNonEmptyPrefix {
246-
#[primary_span]
247-
#[label]
248-
pub(crate) span: Span,
249-
}
250-
251235
#[derive(Diagnostic)]
252236
#[diag(resolve_cannot_capture_dynamic_environment_in_fn_item, code = E0434)]
253237
#[help]
@@ -926,6 +910,27 @@ pub(crate) struct UnnamedCrateRootImport {
926910
pub(crate) span: Span,
927911
}
928912

913+
#[derive(Subdiagnostic)]
914+
#[multipart_suggestion(
915+
resolve_unnamed_super_or_self_sugg_import,
916+
applicability = "maybe-incorrect",
917+
style = "verbose"
918+
)]
919+
pub(crate) struct UnnamedSuperOrSelfImportSugg {
920+
#[suggestion_part(code = "{ident} as name")]
921+
pub(crate) span: Span,
922+
pub(crate) ident: Ident,
923+
}
924+
925+
#[derive(Diagnostic)]
926+
#[diag(resolve_unnamed_super_or_self_import)]
927+
pub(crate) struct UnnamedSuperOrSelfImport {
928+
#[primary_span]
929+
pub(crate) span: Span,
930+
#[subdiagnostic]
931+
pub(crate) sugg: Option<UnnamedSuperOrSelfImportSugg>,
932+
}
933+
929934
#[derive(Diagnostic)]
930935
#[diag(resolve_macro_expanded_extern_crate_cannot_shadow_extern_arguments)]
931936
pub(crate) struct MacroExpandedExternCrateCannotShadowExternArguments {

compiler/rustc_resolve/src/ident.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -829,7 +829,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
829829
ignore_import: Option<Import<'ra>>,
830830
) -> Result<NameBinding<'ra>, (Determinacy, Weak)> {
831831
let module = match module {
832-
ModuleOrUniformRoot::Module(module) => module,
832+
ModuleOrUniformRoot::Module(module) => {
833+
if ns == TypeNS {
834+
if ident.name == kw::Super {
835+
if let Some(parent) = module.parent {
836+
return Ok(parent.self_binding.unwrap());
837+
}
838+
}
839+
}
840+
841+
module
842+
}
833843
ModuleOrUniformRoot::ModuleAndExternPrelude(module) => {
834844
assert_eq!(shadowing, Shadowing::Unrestricted);
835845
let binding = self.resolve_ident_in_scope_set(
@@ -866,10 +876,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
866876
if ident.name == kw::Crate || ident.name == kw::DollarCrate {
867877
let module = self.resolve_crate_root(ident);
868878
return Ok(module.self_binding.unwrap());
869-
} else if ident.name == kw::Super || ident.name == kw::SelfLower {
870-
// FIXME: Implement these with renaming requirements so that e.g.
871-
// `use super;` doesn't work, but `use super as name;` does.
872-
// Fall through here to get an error from `early_resolve_...`.
879+
} else if ident.name == kw::Super {
880+
if let Some(parent) = parent_scope.module.parent {
881+
return Ok(parent.self_binding.unwrap());
882+
}
883+
} else if ident.name == kw::SelfLower {
884+
return Ok(parent_scope.module.self_binding.unwrap());
873885
}
874886
}
875887

compiler/rustc_resolve/src/lib.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -267,10 +267,6 @@ enum ResolutionError<'ra> {
267267
UndeclaredLabel { name: Symbol, suggestion: Option<LabelSuggestion> },
268268
/// Error E0429: `self` imports are only allowed within a `{ }` list.
269269
SelfImportsOnlyAllowedWithin { root: bool, span_with_rename: Span },
270-
/// Error E0430: `self` import can only appear once in the list.
271-
SelfImportCanOnlyAppearOnceInTheList,
272-
/// Error E0431: `self` import can only appear in an import list with a non-empty prefix.
273-
SelfImportOnlyInImportListWithNonEmptyPrefix,
274270
/// Error E0433: failed to resolve.
275271
FailedToResolve {
276272
segment: Option<Symbol>,

tests/ui/delegation/target-expr-pass.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ struct S(F); //~ WARN struct `S` is never constructed
2525
impl Trait for S {
2626
reuse <F as Trait>::bar {
2727
#[allow(unused_imports)]
28-
use self::to_reuse::{foo, inner::self};
28+
use self::to_reuse::{foo, inner::{self}};
2929
let x = foo(12);
3030
assert_eq!(x, 12);
3131
&self.0

tests/ui/dollar-crate/dollar-crate-is-keyword-2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ mod a {}
22

33
macro_rules! m {
44
() => {
5-
use a::$crate; //~ ERROR unresolved import `a::$crate`
5+
use a::$crate; //~ ERROR `$crate` in paths can only be used in start position
66
use a::$crate::b; //~ ERROR `$crate` in paths can only be used in start position
77
type A = a::$crate; //~ ERROR `$crate` in paths can only be used in start position
88
}

0 commit comments

Comments
 (0)