Skip to content

Commit e0d5fa0

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

File tree

10 files changed

+375
-93
lines changed

10 files changed

+375
-93
lines changed

compiler/rustc_resolve/messages.ftl

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -381,15 +381,6 @@ resolve_self_import_only_in_import_list_with_non_empty_prefix =
381381
`self` import can only appear in an import list with a non-empty prefix
382382
.label = can only appear in an import list with a non-empty prefix
383383
384-
resolve_self_imports_only_allowed_within =
385-
`self` imports are only allowed within a {"{"} {"}"} list
386-
387-
resolve_self_imports_only_allowed_within_multipart_suggestion =
388-
alternatively, use the multi-path `use` syntax to import `self`
389-
390-
resolve_self_imports_only_allowed_within_suggestion =
391-
consider importing the module directly
392-
393384
resolve_self_in_const_generic_ty =
394385
cannot use `Self` in const parameter type
395386
@@ -463,6 +454,9 @@ resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg =
463454
resolve_unnamed_crate_root_import =
464455
crate root imports need to be explicitly named: `use crate as name;`
465456
457+
resolve_unnamed_imports =
458+
imports need to be explicitly named: `use {$ident} as name;`
459+
466460
resolve_unreachable_label =
467461
use of unreachable label `{$name}`
468462
.label = unreachable label `{$name}`

compiler/rustc_resolve/src/build_reduced_graph.rs

Lines changed: 68 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -596,35 +596,72 @@ 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+
// Allow `use crate as name;`
601+
kw::Crate => {
602+
if !module_path.is_empty() {
603+
self.r.dcx().span_err(
604+
ident.span,
605+
"`crate` in paths can only be used in start position",
606+
);
607+
return;
608+
}
602609

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;
624610
if rename.is_none() {
625-
ident = source.ident;
611+
self.r
612+
.dcx()
613+
.emit_err(errors::UnnamedCrateRootImport { span: ident.span });
614+
return;
626615
}
627616
}
617+
// Allow `use super as name;`
618+
kw::Super => {
619+
if !module_path.is_empty() {
620+
self.r.dcx().span_err(
621+
ident.span,
622+
"`super` in paths can only be used in start position",
623+
);
624+
return;
625+
}
626+
627+
if rename.is_none() {
628+
self.r
629+
.dcx()
630+
.emit_err(errors::UnnamedImports { span: ident.span, ident });
631+
return;
632+
}
633+
634+
type_ns_only = true;
635+
}
636+
// Allow `use self as name;`, `use foo::self;` and `use foo::self as name;`
637+
kw::SelfLower => {
638+
if let Some(parent) = module_path.pop() {
639+
if parent.ident.name.is_path_segment_keyword() {
640+
self.r.report_error(
641+
source.ident.span,
642+
ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix,
643+
);
644+
return;
645+
}
646+
647+
let self_span = source.ident.span;
648+
source = parent;
649+
if rename.is_none() {
650+
ident = Ident::new(source.ident.name, self_span);
651+
}
652+
} else {
653+
if rename.is_none() {
654+
self.r.dcx().emit_err(errors::UnnamedImports {
655+
span: ident.span,
656+
ident,
657+
});
658+
return;
659+
}
660+
}
661+
type_ns_only = true;
662+
}
663+
kw::DollarCrate => {}
664+
_ => {}
628665
}
629666

630667
// Disallow `use $crate;`
@@ -708,6 +745,12 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
708745
}
709746

710747
e.emit();
748+
} else if let &[self_span] = &self_spans[..]
749+
&& prefix.len() == 1
750+
&& prefix[0].ident.name == kw::DollarCrate
751+
{
752+
// Disallow `use $crate::{self};`
753+
self.r.dcx().emit_err(errors::CrateImported { span: self_span });
711754
}
712755

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

compiler/rustc_resolve/src/diagnostics.rs

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -867,29 +867,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
867867
sub_unreachable,
868868
})
869869
}
870-
ResolutionError::SelfImportsOnlyAllowedWithin { root, span_with_rename } => {
871-
// None of the suggestions below would help with a case like `use self`.
872-
let (suggestion, mpart_suggestion) = if root {
873-
(None, None)
874-
} else {
875-
// use foo::bar::self -> foo::bar
876-
// use foo::bar::self as abc -> foo::bar as abc
877-
let suggestion = errs::SelfImportsOnlyAllowedWithinSuggestion { span };
878-
879-
// use foo::bar::self -> foo::bar::{self}
880-
// use foo::bar::self as abc -> foo::bar::{self as abc}
881-
let mpart_suggestion = errs::SelfImportsOnlyAllowedWithinMultipartSuggestion {
882-
multipart_start: span_with_rename.shrink_to_lo(),
883-
multipart_end: span_with_rename.shrink_to_hi(),
884-
};
885-
(Some(suggestion), Some(mpart_suggestion))
886-
};
887-
self.dcx().create_err(errs::SelfImportsOnlyAllowedWithin {
888-
span,
889-
suggestion,
890-
mpart_suggestion,
891-
})
892-
}
893870
ResolutionError::SelfImportCanOnlyAppearOnceInTheList => {
894871
self.dcx().create_err(errs::SelfImportCanOnlyAppearOnceInTheList { span })
895872
}

compiler/rustc_resolve/src/errors.rs

Lines changed: 8 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -272,40 +272,6 @@ pub(crate) struct AttemptToUseNonConstantValueInConstantWithoutSuggestion<'a> {
272272
pub(crate) suggestion: &'a str,
273273
}
274274

275-
#[derive(Diagnostic)]
276-
#[diag(resolve_self_imports_only_allowed_within, code = E0429)]
277-
pub(crate) struct SelfImportsOnlyAllowedWithin {
278-
#[primary_span]
279-
pub(crate) span: Span,
280-
#[subdiagnostic]
281-
pub(crate) suggestion: Option<SelfImportsOnlyAllowedWithinSuggestion>,
282-
#[subdiagnostic]
283-
pub(crate) mpart_suggestion: Option<SelfImportsOnlyAllowedWithinMultipartSuggestion>,
284-
}
285-
286-
#[derive(Subdiagnostic)]
287-
#[suggestion(
288-
resolve_self_imports_only_allowed_within_suggestion,
289-
code = "",
290-
applicability = "machine-applicable"
291-
)]
292-
pub(crate) struct SelfImportsOnlyAllowedWithinSuggestion {
293-
#[primary_span]
294-
pub(crate) span: Span,
295-
}
296-
297-
#[derive(Subdiagnostic)]
298-
#[multipart_suggestion(
299-
resolve_self_imports_only_allowed_within_multipart_suggestion,
300-
applicability = "machine-applicable"
301-
)]
302-
pub(crate) struct SelfImportsOnlyAllowedWithinMultipartSuggestion {
303-
#[suggestion_part(code = "{{")]
304-
pub(crate) multipart_start: Span,
305-
#[suggestion_part(code = "}}")]
306-
pub(crate) multipart_end: Span,
307-
}
308-
309275
#[derive(Diagnostic)]
310276
#[diag(resolve_binding_shadows_something_unacceptable, code = E0530)]
311277
pub(crate) struct BindingShadowsSomethingUnacceptable<'a> {
@@ -898,6 +864,14 @@ pub(crate) struct UnnamedCrateRootImport {
898864
pub(crate) span: Span,
899865
}
900866

867+
#[derive(Diagnostic)]
868+
#[diag(resolve_unnamed_imports)]
869+
pub(crate) struct UnnamedImports {
870+
#[primary_span]
871+
pub(crate) span: Span,
872+
pub(crate) ident: Ident,
873+
}
874+
901875
#[derive(Diagnostic)]
902876
#[diag(resolve_macro_expanded_extern_crate_cannot_shadow_extern_arguments)]
903877
pub(crate) struct MacroExpandedExternCrateCannotShadowExternArguments {

compiler/rustc_resolve/src/ident.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
869869
// FIXME: Implement these with renaming requirements so that e.g.
870870
// `use super;` doesn't work, but `use super as name;` does.
871871
// Fall through here to get an error from `early_resolve_...`.
872+
873+
if ident.name == kw::Super {
874+
if let Some(parent) = parent_scope.module.parent {
875+
return Ok(parent.self_binding.unwrap());
876+
}
877+
} else {
878+
return Ok(parent_scope.module.self_binding.unwrap());
879+
}
872880
}
873881
}
874882

compiler/rustc_resolve/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,6 @@ enum ResolutionError<'ra> {
261261
IdentifierBoundMoreThanOnceInSamePattern(Ident),
262262
/// Error E0426: use of undeclared label.
263263
UndeclaredLabel { name: Symbol, suggestion: Option<LabelSuggestion> },
264-
/// Error E0429: `self` imports are only allowed within a `{ }` list.
265-
SelfImportsOnlyAllowedWithin { root: bool, span_with_rename: Span },
266264
/// Error E0430: `self` import can only appear once in the list.
267265
SelfImportCanOnlyAppearOnceInTheList,
268266
/// Error E0431: `self` import can only appear in an import list with a non-empty prefix.
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: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
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
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
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 bar() {}
24+
25+
mod foo {
26+
pub mod bar {
27+
pub mod foobar {
28+
pub fn bar() {}
29+
}
30+
}
31+
32+
pub use crate as _crate; // Good
33+
use crate; //~ ERROR crate root imports need to be explicitly named: `use crate as name;`
34+
use ::crate; //~ ERROR `crate` in paths can only be used in start position
35+
use bar::crate; //~ ERROR `crate` in paths can only be used in start position
36+
use crate::crate; //~ ERROR `crate` in paths can only be used in start position
37+
use super::crate; //~ ERROR `crate` in paths can only be used in start position
38+
use self::crate; //~ ERROR `crate` in paths can only be used in start position
39+
use ::crate as _crate2; //~ ERROR `crate` in paths can only be used in start position
40+
use bar::crate as _crate3; //~ ERROR `crate` in paths can only be used in start position
41+
use crate::crate as _crate4; //~ ERROR `crate` in paths can only be used in start position
42+
use super::crate as _crate5; //~ ERROR `crate` in paths can only be used in start position
43+
use self::crate as _crate6; //~ ERROR `crate` in paths can only be used in start position
44+
45+
pub use super as _super; // Good
46+
use super; //~ ERROR imports need to be explicitly named: `use super as name;`
47+
use ::super; //~ ERROR `super` in paths can only be used in start position
48+
use bar::super; //~ ERROR `super` in paths can only be used in start position
49+
use crate::super; //~ ERROR `super` in paths can only be used in start position
50+
use super::super; //~ ERROR `super` in paths can only be used in start position
51+
use self::super; //~ ERROR `super` in paths can only be used in start position
52+
use ::super as _super2; //~ ERROR `super` in paths can only be used in start position
53+
use bar::super as _super3; //~ ERROR `super` in paths can only be used in start position
54+
use crate::super as _super4; //~ ERROR `super` in paths can only be used in start position
55+
use super::super as _super5; //~ ERROR `super` in paths can only be used in start position
56+
use bar::super as _super6; //~ ERROR `super` in paths can only be used in start position
57+
58+
pub use self as _self; // Good
59+
use self; //~ ERROR imports need to be explicitly named: `use self as name;`
60+
use ::self; //~ ERROR `self` import can only appear in an import list with a non-empty prefix
61+
pub use bar::foobar::self; // Good
62+
use crate::self; //~ ERROR `self` import can only appear in an import list with a non-empty prefix
63+
use super::self; //~ ERROR `self` import can only appear in an import list with a non-empty prefix
64+
use self::self; //~ ERROR `self` import can only appear in an import list with a non-empty prefix
65+
use ::self as _self2; //~ ERROR `self` import can only appear in an import list with a non-empty prefix
66+
pub use bar::self as _self3; // Good
67+
use crate::self as _self4; //~ ERROR `self` import can only appear in an import list with a non-empty prefix
68+
use super::self as _self5; //~ ERROR `self` import can only appear in an import list with a non-empty prefix
69+
use self::self as _self6; //~ ERROR `self` import can only appear in an import list with a non-empty prefix
70+
}
71+
72+
fn main() {
73+
foo::_crate::bar();
74+
foo::_super::bar();
75+
foo::_self::bar::foobar::bar();
76+
foo::foobar::bar();
77+
foo::_self3::foobar::bar();
78+
}

0 commit comments

Comments
 (0)