Skip to content

Commit e0e7cf3

Browse files
committed
rustc_resolve: only prepend CrateRoot to a non-keyword segment.
1 parent 24ef47b commit e0e7cf3

File tree

2 files changed

+49
-43
lines changed

2 files changed

+49
-43
lines changed

src/librustc_resolve/build_reduced_graph.rs

+37-41
Original file line numberDiff line numberDiff line change
@@ -120,26 +120,48 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
120120
use_tree: &ast::UseTree,
121121
id: NodeId,
122122
vis: ty::Visibility,
123-
prefix: &ast::Path,
123+
parent_prefix: &[Ident],
124124
mut uniform_paths_canary_emitted: bool,
125125
nested: bool,
126126
item: &Item,
127127
expansion: Mark,
128128
) {
129-
debug!("build_reduced_graph_for_use_tree(prefix={:?}, \
129+
debug!("build_reduced_graph_for_use_tree(parent_prefix={:?}, \
130130
uniform_paths_canary_emitted={}, \
131131
use_tree={:?}, nested={})",
132-
prefix, uniform_paths_canary_emitted, use_tree, nested);
132+
parent_prefix, uniform_paths_canary_emitted, use_tree, nested);
133133

134134
let is_prelude = attr::contains_name(&item.attrs, "prelude_import");
135-
let path = &use_tree.prefix;
135+
let uniform_paths =
136+
self.session.rust_2018() &&
137+
self.session.features_untracked().uniform_paths;
138+
139+
let prefix_iter = || parent_prefix.iter().cloned()
140+
.chain(use_tree.prefix.segments.iter().map(|seg| seg.ident));
141+
let prefix_start = prefix_iter().nth(0);
142+
let starts_with_non_keyword = prefix_start.map_or(false, |ident| {
143+
!ident.is_path_segment_keyword()
144+
});
145+
146+
// Imports are resolved as global by default, prepend `CrateRoot`,
147+
// unless `#![feature(uniform_paths)]` is enabled.
148+
let inject_crate_root =
149+
!uniform_paths &&
150+
match use_tree.kind {
151+
// HACK(eddyb) special-case `use *` to mean `use ::*`.
152+
ast::UseTreeKind::Glob if prefix_start.is_none() => true,
153+
_ => starts_with_non_keyword,
154+
};
155+
let root = if inject_crate_root {
156+
let span = use_tree.prefix.span.shrink_to_lo();
157+
Some(Ident::new(keywords::CrateRoot.name(), span))
158+
} else {
159+
None
160+
};
136161

137-
let mut module_path: Vec<_> = prefix.segments.iter()
138-
.chain(path.segments.iter())
139-
.map(|seg| seg.ident)
140-
.collect();
162+
let prefix: Vec<_> = root.into_iter().chain(prefix_iter()).collect();
141163

142-
debug!("build_reduced_graph_for_use_tree: module_path={:?}", module_path);
164+
debug!("build_reduced_graph_for_use_tree: prefix={:?}", prefix);
143165

144166
// `#[feature(uniform_paths)]` allows an unqualified import path,
145167
// e.g. `use x::...;` to resolve not just globally (`use ::x::...;`)
@@ -172,15 +194,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
172194
// ergonomically unacceptable.
173195
let emit_uniform_paths_canary =
174196
!uniform_paths_canary_emitted &&
175-
module_path.get(0).map_or(false, |ident| {
176-
!ident.is_path_segment_keyword()
177-
});
197+
uniform_paths &&
198+
starts_with_non_keyword;
178199
if emit_uniform_paths_canary {
179-
// Relative paths should only get here if the feature-gate is on.
180-
assert!(self.session.rust_2018() &&
181-
self.session.features_untracked().uniform_paths);
182-
183-
let source = module_path[0];
200+
let source = prefix_start.unwrap();
184201

185202
// HACK(eddyb) For `use x::{self, ...};`, use the ID of the
186203
// `self` nested import for the canary. This allows the
@@ -256,6 +273,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
256273
match use_tree.kind {
257274
ast::UseTreeKind::Simple(rename, ..) => {
258275
let mut ident = use_tree.ident();
276+
let mut module_path = prefix;
259277
let mut source = module_path.pop().unwrap();
260278
let mut type_ns_only = false;
261279

@@ -354,7 +372,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
354372
max_vis: Cell::new(ty::Visibility::Invisible),
355373
};
356374
self.add_import_directive(
357-
module_path,
375+
prefix,
358376
subclass,
359377
use_tree.span,
360378
id,
@@ -366,13 +384,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
366384
);
367385
}
368386
ast::UseTreeKind::Nested(ref items) => {
369-
let prefix = ast::Path {
370-
segments: module_path.into_iter()
371-
.map(|ident| ast::PathSegment::from_ident(ident))
372-
.collect(),
373-
span: path.span,
374-
};
375-
376387
// Ensure there is at most one `self` in the list
377388
let self_spans = items.iter().filter_map(|&(ref use_tree, _)| {
378389
if let ast::UseTreeKind::Simple(..) = use_tree.kind {
@@ -422,28 +433,13 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
422433

423434
match item.node {
424435
ItemKind::Use(ref use_tree) => {
425-
let uniform_paths =
426-
self.session.rust_2018() &&
427-
self.session.features_untracked().uniform_paths;
428-
// Imports are resolved as global by default, add starting root segment.
429-
let root = if !uniform_paths {
430-
use_tree.prefix.make_root()
431-
} else {
432-
// Except when `#![feature(uniform_paths)]` is on.
433-
None
434-
};
435-
let prefix = ast::Path {
436-
segments: root.into_iter().collect(),
437-
span: use_tree.span,
438-
};
439-
440436
self.build_reduced_graph_for_use_tree(
441437
use_tree,
442438
item.id,
443439
use_tree,
444440
item.id,
445441
vis,
446-
&prefix,
442+
&[],
447443
false, // uniform_paths_canary_emitted
448444
false,
449445
item,

src/test/ui/run-pass/rfcs/rfc-2126-crate-paths/crate-path-absolute.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ mod m {
2323
pub(in crate::m) struct S;
2424
}
2525

26-
mod n
27-
{
26+
mod n {
2827
use crate::m::f;
2928
use crate as root;
3029
pub fn check() {
@@ -34,9 +33,20 @@ mod n
3433
}
3534
}
3635

36+
mod p {
37+
use {super::f, crate::m::g, self::root::m::h};
38+
use crate as root;
39+
pub fn check() {
40+
assert_eq!(f(), 1);
41+
assert_eq!(g(), 2);
42+
assert_eq!(h(), 3);
43+
}
44+
}
45+
3746
fn main() {
3847
assert_eq!(f(), 1);
3948
assert_eq!(crate::m::g(), 2);
4049
assert_eq!(root::m::h(), 3);
4150
n::check();
51+
p::check();
4252
}

0 commit comments

Comments
 (0)