Skip to content

Commit e317ae4

Browse files
committed
Rewrite build_reduced_graph_for_use_tree
1 parent 11d2046 commit e317ae4

File tree

8 files changed

+1043
-118
lines changed

8 files changed

+1043
-118
lines changed

compiler/rustc_resolve/messages.ftl

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -373,14 +373,6 @@ resolve_remove_surrounding_derive =
373373
374374
resolve_remove_unnecessary_import = remove unnecessary import
375375
376-
resolve_self_import_can_only_appear_once_in_the_list =
377-
`self` import can only appear once in an import list
378-
.label = can only appear once in an import list
379-
380-
resolve_self_import_only_in_import_list_with_non_empty_prefix =
381-
`self` import can only appear in an import list with a non-empty prefix
382-
.label = can only appear in an import list with a non-empty prefix
383-
384376
resolve_self_imports_only_allowed_within =
385377
`self` imports are only allowed within a {"{"} {"}"} list
386378
@@ -463,6 +455,9 @@ resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg =
463455
resolve_unnamed_crate_root_import =
464456
crate root imports need to be explicitly named: `use crate as name;`
465457
458+
resolve_unnamed_super_or_self_import = imports need to be explicitly named
459+
resolve_unnamed_super_or_self_sugg_import = try renaming it with a name
460+
466461
resolve_unreachable_label =
467462
use of unreachable label `{$name}`
468463
.label = unreachable label `{$name}`

compiler/rustc_resolve/src/build_reduced_graph.rs

Lines changed: 71 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -572,63 +572,54 @@ 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 = matches!(source.ident.name, kw::Super | kw::SelfLower);
576+
577+
match source.ident.name {
578+
kw::Crate => {
579+
if !module_path.is_empty() {
580+
self.r.dcx().span_err(
581+
source.ident.span,
582+
"`crate` in paths can only be used in start position",
586583
);
587584
return;
588585
}
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);
596-
}
597586
}
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;`
587+
kw::SelfLower => {
622588
if let Some(parent) = module_path.pop() {
589+
let span_with_rename = match rename {
590+
Some(rename) => source.ident.span.to(rename.span),
591+
None => source.ident.span,
592+
};
593+
594+
// Suggest `use prefix::{self};` for `use prefix::self;`
595+
if parent.ident.name != kw::PathRoot
596+
&& (!nested || use_tree.prefix.segments.len() > 1)
597+
{
598+
self.r.report_error(
599+
parent.ident.span.shrink_to_hi().to(source.ident.span),
600+
ResolutionError::SelfImportsOnlyAllowedWithin {
601+
root: false,
602+
span_with_rename,
603+
},
604+
);
605+
}
606+
607+
let self_span = source.ident.span;
623608
source = parent;
624609
if rename.is_none() {
625-
ident = source.ident;
610+
ident = Ident::new(source.ident.name, self_span);
626611
}
627612
}
628613
}
614+
kw::DollarCrate => {
615+
if !module_path.is_empty() {
616+
self.r.dcx().span_err(
617+
source.ident.span,
618+
"`$crate` in paths can only be used in start position",
619+
);
620+
return;
621+
}
629622

630-
// Disallow `use $crate;`
631-
if source.ident.name == kw::DollarCrate && module_path.is_empty() {
632623
let crate_root = self.r.resolve_crate_root(source.ident);
633624
let crate_name = match crate_root.kind {
634625
ModuleKind::Def(.., name) => name,
@@ -645,16 +636,43 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
645636
));
646637
source.ident.name = crate_name;
647638
}
648-
if rename.is_none() {
649-
ident.name = sym::dummy;
650-
}
651-
652-
self.r.dcx().emit_err(errors::CrateImported { span: item.span });
653639
}
640+
_ => {}
641+
}
642+
643+
// Deny `use ::{self};`
644+
if source.ident.name == kw::PathRoot {
645+
self.r.dcx().span_err(use_tree.span, "crate root cannot be imported");
646+
return;
654647
}
655648

656-
if ident.name == kw::Crate {
657-
self.r.dcx().emit_err(errors::UnnamedCrateRootImport { span: ident.span });
649+
match ident.name {
650+
// Deny `use crate;` and `use crate::{self};`
651+
kw::Crate => {
652+
self.r.dcx().emit_err(errors::UnnamedCrateRootImport { span: ident.span });
653+
return;
654+
}
655+
// Deny `use $crate;` and `use $crate::{self};`
656+
kw::DollarCrate => {
657+
self.r.dcx().emit_err(errors::CrateImported { span: ident.span });
658+
return;
659+
}
660+
// Deny `use super;`, `use super::{self};`, `use self;` and `use self::{self};`
661+
kw::Super | kw::SelfLower => {
662+
let ident = use_tree.ident();
663+
let sugg = if ident.name == kw::SelfLower
664+
&& (!nested || use_tree.prefix.segments.len() > 1)
665+
{
666+
None
667+
} else {
668+
Some(errors::UnnamedSuperOrSelfImportSugg { span: ident.span, ident })
669+
};
670+
self.r
671+
.dcx()
672+
.emit_err(errors::UnnamedSuperOrSelfImport { span: ident.span, sugg });
673+
return;
674+
}
675+
_ => (),
658676
}
659677

660678
let kind = ImportKind::Single {
@@ -684,32 +702,6 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
684702
}
685703
}
686704
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-
713705
for &(ref tree, id) in items {
714706
self.build_reduced_graph_for_use_tree(
715707
// This particular use tree

compiler/rustc_resolve/src/diagnostics.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -890,12 +890,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
890890
mpart_suggestion,
891891
})
892892
}
893-
ResolutionError::SelfImportCanOnlyAppearOnceInTheList => {
894-
self.dcx().create_err(errs::SelfImportCanOnlyAppearOnceInTheList { span })
895-
}
896-
ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => {
897-
self.dcx().create_err(errs::SelfImportOnlyInImportListWithNonEmptyPrefix { span })
898-
}
899893
ResolutionError::FailedToResolve { segment, label, suggestion, module } => {
900894
let mut err =
901895
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
@@ -204,22 +204,6 @@ pub(crate) struct UnreachableLabelWithSimilarNameExists {
204204
pub(crate) ident_span: Span,
205205
}
206206

207-
#[derive(Diagnostic)]
208-
#[diag(resolve_self_import_can_only_appear_once_in_the_list, code = E0430)]
209-
pub(crate) struct SelfImportCanOnlyAppearOnceInTheList {
210-
#[primary_span]
211-
#[label]
212-
pub(crate) span: Span,
213-
}
214-
215-
#[derive(Diagnostic)]
216-
#[diag(resolve_self_import_only_in_import_list_with_non_empty_prefix, code = E0431)]
217-
pub(crate) struct SelfImportOnlyInImportListWithNonEmptyPrefix {
218-
#[primary_span]
219-
#[label]
220-
pub(crate) span: Span,
221-
}
222-
223207
#[derive(Diagnostic)]
224208
#[diag(resolve_cannot_capture_dynamic_environment_in_fn_item, code = E0434)]
225209
#[help]
@@ -898,6 +882,27 @@ pub(crate) struct UnnamedCrateRootImport {
898882
pub(crate) span: Span,
899883
}
900884

885+
#[derive(Subdiagnostic)]
886+
#[multipart_suggestion(
887+
resolve_unnamed_super_or_self_sugg_import,
888+
applicability = "maybe-incorrect",
889+
style = "verbose"
890+
)]
891+
pub(crate) struct UnnamedSuperOrSelfImportSugg {
892+
#[suggestion_part(code = "{ident} as name")]
893+
pub(crate) span: Span,
894+
pub(crate) ident: Ident,
895+
}
896+
897+
#[derive(Diagnostic)]
898+
#[diag(resolve_unnamed_super_or_self_import)]
899+
pub(crate) struct UnnamedSuperOrSelfImport {
900+
#[primary_span]
901+
pub(crate) span: Span,
902+
#[subdiagnostic]
903+
pub(crate) sugg: Option<UnnamedSuperOrSelfImportSugg>,
904+
}
905+
901906
#[derive(Diagnostic)]
902907
#[diag(resolve_macro_expanded_extern_crate_cannot_shadow_extern_arguments)]
903908
pub(crate) struct MacroExpandedExternCrateCannotShadowExternArguments {

compiler/rustc_resolve/src/ident.rs

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

compiler/rustc_resolve/src/lib.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,6 @@ enum ResolutionError<'ra> {
263263
UndeclaredLabel { name: Symbol, suggestion: Option<LabelSuggestion> },
264264
/// Error E0429: `self` imports are only allowed within a `{ }` list.
265265
SelfImportsOnlyAllowedWithin { root: bool, span_with_rename: Span },
266-
/// Error E0430: `self` import can only appear once in the list.
267-
SelfImportCanOnlyAppearOnceInTheList,
268-
/// Error E0431: `self` import can only appear in an import list with a non-empty prefix.
269-
SelfImportOnlyInImportListWithNonEmptyPrefix,
270266
/// Error E0433: failed to resolve.
271267
FailedToResolve {
272268
segment: Option<Symbol>,

0 commit comments

Comments
 (0)