Skip to content

Commit 8b21630

Browse files
committed
WIP: rewrite build_reduced_graph_for_use_tree
1 parent 11d2046 commit 8b21630

File tree

10 files changed

+629
-67
lines changed

10 files changed

+629
-67
lines changed

compiler/rustc_resolve/messages.ftl

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -377,10 +377,6 @@ resolve_self_import_can_only_appear_once_in_the_list =
377377
`self` import can only appear once in an import list
378378
.label = can only appear once in an import list
379379
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-
384380
resolve_self_imports_only_allowed_within =
385381
`self` imports are only allowed within a {"{"} {"}"} list
386382
@@ -463,6 +459,9 @@ resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg =
463459
resolve_unnamed_crate_root_import =
464460
crate root imports need to be explicitly named: `use crate as name;`
465461
462+
resolve_unnamed_imports =
463+
imports need to be explicitly named: `use {$ident} as name;`
464+
466465
resolve_unreachable_label =
467466
use of unreachable label `{$name}`
468467
.label = unreachable label `{$name}`

compiler/rustc_resolve/src/build_reduced_graph.rs

Lines changed: 54 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -574,61 +574,54 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
574574
let mut source = module_path.pop().unwrap();
575575
let mut type_ns_only = false;
576576

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,
577+
match source.ident.name {
578+
kw::Crate => {
579+
if !module_path.is_empty() {
580+
self.r.dcx().span_err(
581+
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::Super => {
588+
type_ns_only = true;
589+
}
590+
kw::SelfLower => {
622591
if let Some(parent) = module_path.pop() {
592+
let span_with_rename = match rename {
593+
Some(rename) => source.ident.span.to(rename.span),
594+
None => source.ident.span,
595+
};
596+
597+
if !nested && parent.ident.name != kw::PathRoot {
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
}
613+
614+
type_ns_only = true;
628615
}
616+
kw::DollarCrate => {
617+
if !module_path.is_empty() {
618+
self.r.dcx().span_err(
619+
ident.span,
620+
"`$crate` in paths can only be used in start position",
621+
);
622+
return;
623+
}
629624

630-
// Disallow `use $crate;`
631-
if source.ident.name == kw::DollarCrate && module_path.is_empty() {
632625
let crate_root = self.r.resolve_crate_root(source.ident);
633626
let crate_name = match crate_root.kind {
634627
ModuleKind::Def(.., name) => name,
@@ -645,16 +638,22 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
645638
));
646639
source.ident.name = crate_name;
647640
}
648-
if rename.is_none() {
649-
ident.name = sym::dummy;
650-
}
651-
652-
self.r.dcx().emit_err(errors::CrateImported { span: item.span });
653641
}
642+
_ => {}
654643
}
655644

656645
if ident.name == kw::Crate {
657646
self.r.dcx().emit_err(errors::UnnamedCrateRootImport { span: ident.span });
647+
return;
648+
} else if ident.name == kw::DollarCrate {
649+
self.r.dcx().emit_err(errors::CrateImported { span: item.span });
650+
return;
651+
} else if source.ident.name == kw::PathRoot {
652+
self.r.dcx().span_err(ident.span, "{{root}} cannot be imported");
653+
return;
654+
} else if ident.is_path_segment_keyword() {
655+
self.r.dcx().emit_err(errors::UnnamedImports { span: ident.span, ident });
656+
return;
658657
}
659658

660659
let kind = ImportKind::Single {
@@ -708,6 +707,12 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
708707
}
709708

710709
e.emit();
710+
} else if let &[self_span] = &self_spans[..]
711+
&& prefix.len() == 1
712+
&& prefix[0].ident.name == kw::DollarCrate
713+
{
714+
// Disallow `use $crate::{self};`
715+
self.r.dcx().emit_err(errors::CrateImported { span: self_span });
711716
}
712717

713718
for &(ref tree, id) in items {

compiler/rustc_resolve/src/diagnostics.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -893,9 +893,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
893893
ResolutionError::SelfImportCanOnlyAppearOnceInTheList => {
894894
self.dcx().create_err(errs::SelfImportCanOnlyAppearOnceInTheList { span })
895895
}
896-
ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => {
897-
self.dcx().create_err(errs::SelfImportOnlyInImportListWithNonEmptyPrefix { span })
898-
}
899896
ResolutionError::FailedToResolve { segment, label, suggestion, module } => {
900897
let mut err =
901898
struct_span_code_err!(self.dcx(), span, E0433, "failed to resolve: {label}");

compiler/rustc_resolve/src/errors.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -212,14 +212,6 @@ pub(crate) struct SelfImportCanOnlyAppearOnceInTheList {
212212
pub(crate) span: Span,
213213
}
214214

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-
223215
#[derive(Diagnostic)]
224216
#[diag(resolve_cannot_capture_dynamic_environment_in_fn_item, code = E0434)]
225217
#[help]
@@ -898,6 +890,14 @@ pub(crate) struct UnnamedCrateRootImport {
898890
pub(crate) span: Span,
899891
}
900892

893+
#[derive(Diagnostic)]
894+
#[diag(resolve_unnamed_imports)]
895+
pub(crate) struct UnnamedImports {
896+
#[primary_span]
897+
pub(crate) span: Span,
898+
pub(crate) ident: Ident,
899+
}
900+
901901
#[derive(Diagnostic)]
902902
#[diag(resolve_macro_expanded_extern_crate_cannot_shadow_extern_arguments)]
903903
pub(crate) struct MacroExpandedExternCrateCannotShadowExternArguments {

compiler/rustc_resolve/src/ident.rs

Lines changed: 19 additions & 1 deletion
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(
@@ -869,6 +879,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
869879
// FIXME: Implement these with renaming requirements so that e.g.
870880
// `use super;` doesn't work, but `use super as name;` does.
871881
// Fall through here to get an error from `early_resolve_...`.
882+
883+
if ident.name == kw::Super {
884+
if let Some(parent) = parent_scope.module.parent {
885+
return Ok(parent.self_binding.unwrap());
886+
}
887+
} else {
888+
return Ok(parent_scope.module.self_binding.unwrap());
889+
}
872890
}
873891
}
874892

compiler/rustc_resolve/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,8 +265,6 @@ enum ResolutionError<'ra> {
265265
SelfImportsOnlyAllowedWithin { root: bool, span_with_rename: Span },
266266
/// Error E0430: `self` import can only appear once in the list.
267267
SelfImportCanOnlyAppearOnceInTheList,
268-
/// Error E0431: `self` import can only appear in an import list with a non-empty prefix.
269-
SelfImportOnlyInImportListWithNonEmptyPrefix,
270268
/// Error E0433: failed to resolve.
271269
FailedToResolve {
272270
segment: Option<Symbol>,
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
macro_rules! foo {
2+
() => {
3+
use $crate::{self}; //~ ERROR `$crate` may not be imported
4+
};
5+
}
6+
7+
foo!();
8+
9+
fn main() {}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error: `$crate` may not be imported
2+
--> $DIR/use-dollar-crate-self.rs:3:22
3+
|
4+
LL | use $crate::{self};
5+
| ^^^^
6+
...
7+
LL | foo!();
8+
| ------ in this macro invocation
9+
|
10+
= note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
12+
error: aborting due to 1 previous error
13+
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
//@ edition: 2021
2+
3+
macro_rules! macro_dollar_crate {
4+
($m: ident) => {
5+
pub use $crate as _dollar_crate; // Good
6+
use $crate; //~ ERROR `$crate` may not be imported
7+
use ::$crate; //~ ERROR `$crate` in paths can only be used in start position
8+
use $m::$crate; //~ ERROR `$crate` in paths can only be used in start position
9+
use crate::$crate; //~ ERROR `$crate` in paths can only be used in start position
10+
use super::$crate; //~ ERROR `$crate` in paths can only be used in start position
11+
use self::$crate; //~ ERROR `$crate` in paths can only be used in start position
12+
use $crate::$crate; //~ ERROR `$crate` in paths can only be used in start position
13+
use ::$crate as _dollar_crate2; //~ ERROR `$crate` in paths can only be used in start position
14+
use $m::$crate as _dollar_crate3; //~ ERROR `$crate` in paths can only be used in start position
15+
use crate::$crate as _dollar_crate4; //~ ERROR `$crate` in paths can only be used in start position
16+
use super::$crate as _dollar_crate5; //~ ERROR `$crate` in paths can only be used in start position
17+
use self::$crate as _dollar_crate6; //~ ERROR `$crate` in paths can only be used in start position
18+
use $crate::$crate as _dollar_crate7; //~ ERROR `$crate` in paths can only be used in start position
19+
}
20+
}
21+
22+
fn outer() {}
23+
24+
mod foo {
25+
pub mod bar {
26+
pub mod foobar {
27+
pub mod qux {
28+
pub use super::inner;
29+
}
30+
31+
pub fn inner() {}
32+
}
33+
34+
macro_dollar_crate!(foobar);
35+
36+
pub use crate as _crate; // Good
37+
use crate; //~ ERROR crate root imports need to be explicitly named: `use crate as name;`
38+
use ::crate; //~ ERROR `crate` in paths can only be used in start position
39+
use foobar::crate; //~ ERROR `crate` in paths can only be used in start position
40+
use crate::crate; //~ ERROR `crate` in paths can only be used in start position
41+
use super::crate; //~ ERROR `crate` in paths can only be used in start position
42+
use self::crate; //~ ERROR `crate` in paths can only be used in start position
43+
use ::crate as _crate2; //~ ERROR `crate` in paths can only be used in start position
44+
use foobar::crate as _crate3; //~ ERROR `crate` in paths can only be used in start position
45+
use crate::crate as _crate4; //~ ERROR `crate` in paths can only be used in start position
46+
use super::crate as _crate5; //~ ERROR `crate` in paths can only be used in start position
47+
use self::crate as _crate6; //~ ERROR `crate` in paths can only be used in start position
48+
49+
pub use super as _super; // Good
50+
pub use foobar::super as _super3; // Good
51+
pub use super::super as _super5; // Good
52+
pub use self::super as _super6; // Good
53+
use super; //~ ERROR imports need to be explicitly named: `use super as name;`
54+
use ::super; //~ ERROR imports need to be explicitly named: `use super as name;`
55+
use foobar::super; //~ ERROR imports need to be explicitly named: `use super as name;`
56+
use crate::super; //~ ERROR imports need to be explicitly named: `use super as name;`
57+
use super::super; //~ ERROR imports need to be explicitly named: `use super as name;`
58+
use self::super; //~ ERROR imports need to be explicitly named: `use super as name;`
59+
use ::super as _super2; //~ ERROR unresolved import `super`
60+
use crate::super as _super4; //~ ERROR unresolved import `crate::super`
61+
62+
pub use self as _self; // Good
63+
use self; //~ ERROR imports need to be explicitly named: `use self as name;`
64+
use ::self; //~ ERROR {{root}} cannot be imported
65+
pub use foobar::qux::self; //~ ERROR `self` imports are only allowed within a { } list
66+
use crate::self; //~ ERROR crate root imports need to be explicitly named: `use crate as name;`
67+
//~^ ERROR `self` imports are only allowed within a { } list
68+
use super::self; //~ ERROR imports need to be explicitly named: `use super as name;`
69+
//~^ ERROR `self` imports are only allowed within a { } list
70+
use self::self; //~ ERROR imports need to be explicitly named: `use self as name;`
71+
//~^ ERROR `self` imports are only allowed within a { } list
72+
use ::self as _self2; //~ ERROR {{root}} cannot be imported
73+
pub use foobar::self as _self3; //~ ERROR `self` imports are only allowed within a { } list
74+
pub use crate::self as _self4; //~ ERROR `self` imports are only allowed within a { } list
75+
pub use super::self as _self5; //~ ERROR `self` imports are only allowed within a { } list
76+
pub use self::self as _self6; //~ ERROR `self` imports are only allowed within a { } list
77+
}
78+
}
79+
80+
fn main() {
81+
foo::bar::_dollar_crate::outer();
82+
83+
foo::bar::_crate::outer();
84+
foo::bar::_crate::foo::bar::foobar::inner();
85+
86+
foo::bar::_super::bar::foobar::inner();
87+
foo::bar::_super3::foobar::qux::inner();
88+
foo::bar::_super5::outer();
89+
foo::bar::_super6::bar::foobar::inner();
90+
91+
foo::bar::_self::foobar::inner();
92+
// Belows work after recovery
93+
foo::bar::qux::inner();
94+
foo::bar::_self3::inner();
95+
foo::bar::_self4::outer();
96+
foo::bar::_self5::bar::foobar::inner();
97+
foo::bar::_self6::foobar::inner();
98+
}

0 commit comments

Comments
 (0)