Skip to content

Commit 3c4b5af

Browse files
committed
Rewrite build_reduced_graph_for_use_tree
1 parent 5934b06 commit 3c4b5af

34 files changed

+1975
-998
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: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,6 @@ resolve_ident_in_scope_but_it_is_desc =
210210
211211
resolve_implicit_elided_lifetimes_not_allowed_here = implicit elided lifetime not allowed here
212212
213-
resolve_imported_crate = `$crate` may not be imported
214-
215213
resolve_imported_macro_not_found = imported macro not found
216214
217215
resolve_imports_cannot_refer_to =
@@ -379,14 +377,6 @@ resolve_remove_surrounding_derive =
379377
380378
resolve_remove_unnecessary_import = remove unnecessary import
381379
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-
390380
resolve_self_imports_only_allowed_within =
391381
`self` imports are only allowed within a {"{"} {"}"} list
392382
@@ -466,8 +456,8 @@ resolve_unexpected_res_change_ty_to_const_param_sugg =
466456
resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg =
467457
if you meant to collect the rest of the slice in `{$ident}`, use the at operator
468458
469-
resolve_unnamed_crate_root_import =
470-
crate root imports need to be explicitly named: `use crate as name;`
459+
resolve_unnamed_import = imports need to be explicitly named
460+
resolve_unnamed_import_sugg = try renaming it with a name
471461
472462
resolve_unreachable_label =
473463
use of unreachable label `{$name}`

compiler/rustc_resolve/src/build_reduced_graph.rs

Lines changed: 76 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -564,97 +564,98 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
564564
let prefix = crate_root.into_iter().chain(prefix_iter).collect::<Vec<_>>();
565565
debug!("build_reduced_graph_for_use_tree: prefix={:?}", prefix);
566566

567-
let empty_for_self = |prefix: &[Segment]| {
568-
prefix.is_empty() || prefix.len() == 1 && prefix[0].ident.name == kw::PathRoot
569-
};
570567
match use_tree.kind {
571568
ast::UseTreeKind::Simple(rename) => {
572569
let mut ident = use_tree.ident();
573570
let mut module_path = prefix;
574571
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;
581572

582-
if empty_for_self(&module_path) {
583-
self.r.report_error(
584-
use_tree.span,
585-
ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix,
573+
// `true` for `...::{self [as target]}` imports, `false` otherwise.
574+
let type_ns_only = nested
575+
&& source.ident.name == kw::SelfLower
576+
&& use_tree.prefix.segments.len() == 1;
577+
578+
match source.ident.name {
579+
kw::DollarCrate => {
580+
if !module_path.is_empty() {
581+
self.r.dcx().span_err(
582+
source.ident.span,
583+
"`$crate` in paths can only be used in start position",
586584
);
587585
return;
588586
}
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);
587+
}
588+
kw::Crate => {
589+
if !module_path.is_empty() {
590+
self.r.dcx().span_err(
591+
source.ident.span,
592+
"`crate` in paths can only be used in start position",
593+
);
594+
return;
596595
}
597596
}
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;`
597+
kw::Super => {
598+
if module_path.iter().any(|seg| seg.ident.name != kw::Super) {
599+
self.r.dcx().span_err(
600+
source.ident.span,
601+
"`super` in paths can only be used in start position or after another `super`",
602+
);
603+
return;
604+
}
605+
}
606+
kw::SelfLower => {
622607
if let Some(parent) = module_path.pop() {
608+
// Suggest `use prefix::{self};` for `use prefix::self;`
609+
if !type_ns_only
610+
&& (parent.ident.name != kw::PathRoot
611+
|| self.r.path_root_is_crate_root(parent.ident))
612+
{
613+
let span_with_rename = match rename {
614+
Some(rename) => source.ident.span.to(rename.span),
615+
None => source.ident.span,
616+
};
617+
618+
self.r.report_error(
619+
parent.ident.span.shrink_to_hi().to(source.ident.span),
620+
ResolutionError::SelfImportsOnlyAllowedWithin {
621+
root: parent.ident.name == kw::PathRoot,
622+
span_with_rename,
623+
},
624+
);
625+
}
626+
627+
let self_span = source.ident.span;
623628
source = parent;
624629
if rename.is_none() {
625-
ident = source.ident;
630+
ident = Ident::new(source.ident.name, self_span);
626631
}
627632
}
628633
}
634+
_ => {}
635+
}
629636

630-
// Disallow `use $crate;`
631-
if source.ident.name == kw::DollarCrate && module_path.is_empty() {
632-
let crate_root = self.r.resolve_crate_root(source.ident);
633-
let crate_name = match crate_root.kind {
634-
ModuleKind::Def(.., name) => name,
635-
ModuleKind::Block => unreachable!(),
636-
};
637-
// HACK(eddyb) unclear how good this is, but keeping `$crate`
638-
// in `source` breaks `tests/ui/imports/import-crate-var.rs`,
639-
// while the current crate doesn't have a valid `crate_name`.
640-
if let Some(crate_name) = crate_name {
641-
// `crate_name` should not be interpreted as relative.
642-
module_path.push(Segment::from_ident_and_id(
643-
Ident::new(kw::PathRoot, source.ident.span),
644-
self.r.next_node_id(),
645-
));
646-
source.ident.name = crate_name;
647-
}
648-
if rename.is_none() {
649-
ident.name = sym::dummy;
650-
}
651-
652-
self.r.dcx().emit_err(errors::CrateImported { span: item.span });
653-
}
637+
// Deny `use ::{self};` after edition 2015
638+
if source.ident.name == kw::PathRoot
639+
&& !self.r.path_root_is_crate_root(source.ident)
640+
{
641+
self.r.dcx().span_err(use_tree.span, "extern prelude cannot be imported");
642+
return;
654643
}
655644

656-
if ident.name == kw::Crate {
657-
self.r.dcx().emit_err(errors::UnnamedCrateRootImport { span: ident.span });
645+
// Deny importing path-kw without renaming
646+
if rename.is_none() && ident.is_path_segment_keyword() {
647+
let ident = use_tree.ident();
648+
649+
// Don't suggest `use xx::self as name;` for `use xx::self;`
650+
// But it's OK to suggest `use xx::{self as name};` for `use xx::{self};`
651+
let sugg = if !type_ns_only && ident.name == kw::SelfLower {
652+
None
653+
} else {
654+
Some(errors::UnnamedImportSugg { span: ident.span, ident })
655+
};
656+
657+
self.r.dcx().emit_err(errors::UnnamedImport { span: ident.span, sugg });
658+
return;
658659
}
659660

660661
let kind = ImportKind::Single {
@@ -684,32 +685,6 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
684685
}
685686
}
686687
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-
713688
for &(ref tree, id) in items {
714689
self.build_reduced_graph_for_use_tree(
715690
// This particular use tree
@@ -721,7 +696,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
721696
// Empty groups `a::b::{}` are turned into synthetic `self` imports
722697
// `a::b::c::{self as _}`, so that their prefixes are correctly
723698
// resolved and checked for privacy/stability/etc.
724-
if items.is_empty() && !empty_for_self(&prefix) {
699+
if items.is_empty()
700+
&& !prefix.is_empty()
701+
&& (prefix.len() > 1 || prefix[0].ident.name != kw::PathRoot)
702+
{
725703
let new_span = prefix[prefix.len() - 1].ident.span;
726704
let tree = ast::UseTree {
727705
prefix: ast::Path::from_ident(Ident::new(kw::SelfLower, new_span)),

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: 16 additions & 25 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]
@@ -610,13 +594,6 @@ pub(crate) struct MacroExpandedMacroExportsAccessedByAbsolutePaths {
610594
pub definition: Span,
611595
}
612596

613-
#[derive(Diagnostic)]
614-
#[diag(resolve_imported_crate)]
615-
pub(crate) struct CrateImported {
616-
#[primary_span]
617-
pub(crate) span: Span,
618-
}
619-
620597
#[derive(Diagnostic)]
621598
#[diag(resolve_macro_use_extern_crate_self)]
622599
pub(crate) struct MacroUseExternCrateSelf {
@@ -919,11 +896,25 @@ pub(crate) struct ArgumentsMacroUseNotAllowed {
919896
pub(crate) span: Span,
920897
}
921898

899+
#[derive(Subdiagnostic)]
900+
#[multipart_suggestion(
901+
resolve_unnamed_import_sugg,
902+
applicability = "maybe-incorrect",
903+
style = "verbose"
904+
)]
905+
pub(crate) struct UnnamedImportSugg {
906+
#[suggestion_part(code = "{ident} as name")]
907+
pub(crate) span: Span,
908+
pub(crate) ident: Ident,
909+
}
910+
922911
#[derive(Diagnostic)]
923-
#[diag(resolve_unnamed_crate_root_import)]
924-
pub(crate) struct UnnamedCrateRootImport {
912+
#[diag(resolve_unnamed_import)]
913+
pub(crate) struct UnnamedImport {
925914
#[primary_span]
926915
pub(crate) span: Span,
916+
#[subdiagnostic]
917+
pub(crate) sugg: Option<UnnamedImportSugg>,
927918
}
928919

929920
#[derive(Diagnostic)]

0 commit comments

Comments
 (0)