Skip to content

Commit e181d80

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

File tree

8 files changed

+480
-27
lines changed

8 files changed

+480
-27
lines changed

compiler/rustc_resolve/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,9 @@ resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg =
463463
resolve_unnamed_crate_root_import =
464464
crate root imports need to be explicitly named: `use crate as name;`
465465
466+
resolve_unnamed_imports =
467+
imports need to be explicitly named: `use {$ident} as name;`
468+
466469
resolve_unreachable_label =
467470
use of unreachable label `{$name}`
468471
.label = unreachable label `{$name}`

compiler/rustc_resolve/src/build_reduced_graph.rs

Lines changed: 51 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -596,35 +596,47 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
596596
}
597597
}
598598
} else {
599-
// Disallow `self`
600-
if source.ident.name == kw::SelfLower {
601-
let parent = module_path.last();
599+
match source.ident.name {
600+
kw::Crate => {
601+
if !module_path.is_empty() {
602+
self.r.dcx().span_err(
603+
ident.span,
604+
"`crate` in paths can only be used in start position",
605+
);
606+
return;
607+
}
608+
}
609+
kw::Super => {
610+
type_ns_only = true;
611+
}
612+
kw::SelfLower => {
613+
if let Some(parent) = module_path.pop() {
614+
let span_with_rename = match rename {
615+
Some(rename) => source.ident.span.to(rename.span),
616+
None => source.ident.span,
617+
};
618+
619+
if parent.ident.name != kw::PathRoot {
620+
self.r.report_error(
621+
parent.ident.span.shrink_to_hi().to(source.ident.span),
622+
ResolutionError::SelfImportsOnlyAllowedWithin {
623+
root: false,
624+
span_with_rename,
625+
},
626+
);
627+
}
602628

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;`
622-
if let Some(parent) = module_path.pop() {
623-
source = parent;
624-
if rename.is_none() {
625-
ident = source.ident;
629+
let self_span = source.ident.span;
630+
source = parent;
631+
if rename.is_none() {
632+
ident = Ident::new(source.ident.name, self_span);
633+
}
626634
}
635+
636+
type_ns_only = true;
627637
}
638+
kw::DollarCrate => {}
639+
_ => {}
628640
}
629641

630642
// Disallow `use $crate;`
@@ -655,6 +667,13 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
655667

656668
if ident.name == kw::Crate {
657669
self.r.dcx().emit_err(errors::UnnamedCrateRootImport { span: ident.span });
670+
return;
671+
} else if source.ident.name == kw::PathRoot {
672+
self.r.dcx().span_err(ident.span, "{{root}} cannot be imported");
673+
return;
674+
} else if ident.is_path_segment_keyword() {
675+
self.r.dcx().emit_err(errors::UnnamedImports { span: ident.span, ident });
676+
return;
658677
}
659678

660679
let kind = ImportKind::Single {
@@ -708,6 +727,12 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
708727
}
709728

710729
e.emit();
730+
} else if let &[self_span] = &self_spans[..]
731+
&& prefix.len() == 1
732+
&& prefix[0].ident.name == kw::DollarCrate
733+
{
734+
// Disallow `use $crate::{self};`
735+
self.r.dcx().emit_err(errors::CrateImported { span: self_span });
711736
}
712737

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

compiler/rustc_resolve/src/errors.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,14 @@ pub(crate) struct UnnamedCrateRootImport {
898898
pub(crate) span: Span,
899899
}
900900

901+
#[derive(Diagnostic)]
902+
#[diag(resolve_unnamed_imports)]
903+
pub(crate) struct UnnamedImports {
904+
#[primary_span]
905+
pub(crate) span: Span,
906+
pub(crate) ident: Ident,
907+
}
908+
901909
#[derive(Diagnostic)]
902910
#[diag(resolve_macro_expanded_extern_crate_cannot_shadow_extern_arguments)]
903911
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

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: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
//@ edition: 2021
2+
3+
// mod x {
4+
// use super; // bad
5+
// use super as name; // good
6+
// use self; // bad
7+
// use self as name; // good
8+
// use crate; // bad
9+
// use crate as name; // good
10+
// use $crate; // bad
11+
// use $crate as name; // good
12+
13+
// mod foo;
14+
// use foo::crate; // bad
15+
// use crate::crate; // bad
16+
// use foo::super; // bad
17+
// use super::super; // bad
18+
// use foo::self; // good
19+
// use self::self; // bad
20+
// use self::self as name; // good
21+
// }
22+
23+
fn outer() {}
24+
25+
mod foo {
26+
pub mod bar {
27+
pub mod foobar {
28+
pub mod qux {
29+
pub use super::inner;
30+
}
31+
32+
pub fn inner() {}
33+
}
34+
35+
pub use crate as _crate; // Good
36+
use crate; //~ ERROR crate root imports need to be explicitly named: `use crate as name;`
37+
use ::crate; //~ ERROR `crate` in paths can only be used in start position
38+
use foobar::crate; //~ ERROR `crate` in paths can only be used in start position
39+
use crate::crate; //~ ERROR `crate` in paths can only be used in start position
40+
use super::crate; //~ ERROR `crate` in paths can only be used in start position
41+
use self::crate; //~ ERROR `crate` in paths can only be used in start position
42+
use ::crate as _crate2; //~ ERROR `crate` in paths can only be used in start position
43+
use foobar::crate as _crate3; //~ ERROR `crate` in paths can only be used in start position
44+
use crate::crate as _crate4; //~ ERROR `crate` in paths can only be used in start position
45+
use super::crate as _crate5; //~ ERROR `crate` in paths can only be used in start position
46+
use self::crate as _crate6; //~ ERROR `crate` in paths can only be used in start position
47+
48+
pub use super as _super; // Good
49+
pub use foobar::super as _super3; // Good
50+
pub use super::super as _super5; // Good
51+
pub use self::super as _super6; // Good
52+
use super; //~ ERROR imports need to be explicitly named: `use super as name;`
53+
use ::super; //~ ERROR imports need to be explicitly named: `use super as name;`
54+
use foobar::super; //~ ERROR imports need to be explicitly named: `use super as name;`
55+
use crate::super; //~ ERROR imports need to be explicitly named: `use super as name;`
56+
use super::super; //~ ERROR imports need to be explicitly named: `use super as name;`
57+
use self::super; //~ ERROR imports need to be explicitly named: `use super as name;`
58+
use ::super as _super2; //~ ERROR unresolved import `super`
59+
use crate::super as _super4; //~ ERROR unresolved import `crate::super`
60+
61+
pub use self as _self; // Good
62+
use self; //~ ERROR imports need to be explicitly named: `use self as name;`
63+
use ::self; //~ ERROR {{root}} cannot be imported
64+
pub use foobar::qux::self; //~ ERROR `self` imports are only allowed within a { } list
65+
use crate::self; //~ ERROR crate root imports need to be explicitly named: `use crate as name;`
66+
//~^ ERROR `self` imports are only allowed within a { } list
67+
use super::self; //~ ERROR imports need to be explicitly named: `use super as name;`
68+
//~^ ERROR `self` imports are only allowed within a { } list
69+
use self::self; //~ ERROR imports need to be explicitly named: `use self as name;`
70+
//~^ ERROR `self` imports are only allowed within a { } list
71+
use ::self as _self2; //~ ERROR {{root}} cannot be imported
72+
pub use foobar::self as _self3; //~ ERROR `self` imports are only allowed within a { } list
73+
pub use crate::self as _self4; //~ ERROR `self` imports are only allowed within a { } list
74+
pub use super::self as _self5; //~ ERROR `self` imports are only allowed within a { } list
75+
pub use self::self as _self6; //~ ERROR `self` imports are only allowed within a { } list
76+
}
77+
}
78+
79+
fn main() {
80+
foo::bar::_crate::outer();
81+
foo::bar::_crate::foo::bar::foobar::inner();
82+
83+
foo::bar::_super::bar::foobar::inner();
84+
foo::bar::_super3::foobar::qux::inner();
85+
foo::bar::_super5::outer();
86+
foo::bar::_super6::bar::foobar::inner();
87+
88+
foo::bar::_self::foobar::inner();
89+
// Belows work after recovery
90+
foo::bar::qux::inner();
91+
foo::bar::_self3::inner();
92+
foo::bar::_self4::outer();
93+
foo::bar::_self5::bar::foobar::inner();
94+
foo::bar::_self6::foobar::inner();
95+
}

0 commit comments

Comments
 (0)