Skip to content

Commit e6739fe

Browse files
committed
resolve: Resolve multi-segment imports using in-scope resolution on 2018 edition
1 parent 67feeeb commit e6739fe

File tree

5 files changed

+47
-66
lines changed

5 files changed

+47
-66
lines changed

src/librustc_resolve/build_reduced_graph.rs

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -125,36 +125,24 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
125125
debug!("build_reduced_graph_for_use_tree(parent_prefix={:?}, use_tree={:?}, nested={})",
126126
parent_prefix, use_tree, nested);
127127

128-
let uniform_paths =
129-
self.session.rust_2018() &&
130-
self.session.features_untracked().uniform_paths;
131-
132-
let prefix_iter = || parent_prefix.iter().cloned()
133-
.chain(use_tree.prefix.segments.iter().map(|seg| seg.into()));
134-
let prefix_start = prefix_iter().next();
135-
let starts_with_non_keyword = prefix_start.map_or(false, |seg| {
136-
!seg.ident.is_path_segment_keyword()
137-
});
138-
139-
// Imports are resolved as global by default, prepend `CrateRoot`,
140-
// unless `#![feature(uniform_paths)]` is enabled.
141-
let inject_crate_root =
142-
!uniform_paths &&
143-
match use_tree.kind {
144-
// HACK(eddyb) special-case `use *` to mean `use ::*`.
145-
ast::UseTreeKind::Glob if prefix_start.is_none() => true,
146-
_ => starts_with_non_keyword,
147-
};
148-
let root = if inject_crate_root {
149-
let span = use_tree.prefix.span.shrink_to_lo();
150-
Some(Segment::from_ident(Ident::new(keywords::CrateRoot.name(), span)))
128+
let mut prefix_iter = parent_prefix.iter().cloned()
129+
.chain(use_tree.prefix.segments.iter().map(|seg| seg.ident)).peekable();
130+
131+
// On 2015 edition imports are resolved as crate-relative by default,
132+
// so prefixes are prepended with crate root segment if necessary.
133+
// The root is prepended lazily, when the first non-empty prefix or terminating glob
134+
// appears, so imports in braced groups can have roots prepended independently.
135+
let is_glob = if let ast::UseTreeKind::Glob = use_tree.kind { true } else { false };
136+
let crate_root = if !self.session.rust_2018() &&
137+
prefix_iter.peek().map_or(is_glob, |ident| !ident.is_path_segment_keyword()) {
138+
Some(Ident::new(keywords::CrateRoot.name(), use_tree.prefix.span.shrink_to_lo()))
151139
} else {
152140
None
153141
};
154142

155-
let prefix: Vec<_> = root.into_iter().chain(prefix_iter()).collect();
156-
143+
let prefix = crate_root.into_iter().chain(prefix_iter).collect::<Vec<_>>();
157144
debug!("build_reduced_graph_for_use_tree: prefix={:?}", prefix);
145+
158146
let empty_for_self = |prefix: &[Segment]| {
159147
prefix.is_empty() ||
160148
prefix.len() == 1 && prefix[0].ident.name == keywords::CrateRoot.name()

src/librustc_resolve/error_reporting.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
6868
) -> Option<(Vec<Segment>, Option<String>)> {
6969
// Replace first ident with `self` and check if that is valid.
7070
path[0].ident.name = keywords::SelfValue.name();
71-
let result = self.resolve_path(None, &path, None, parent_scope, false, span, CrateLint::No);
71+
let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No);
7272
debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result);
7373
if let PathResult::Module(..) = result {
7474
Some((path, None))
@@ -92,7 +92,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
9292
) -> Option<(Vec<Segment>, Option<String>)> {
9393
// Replace first ident with `crate` and check if that is valid.
9494
path[0].ident.name = keywords::Crate.name();
95-
let result = self.resolve_path(None, &path, None, parent_scope, false, span, CrateLint::No);
95+
let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No);
9696
debug!("make_missing_crate_suggestion: path={:?} result={:?}", path, result);
9797
if let PathResult::Module(..) = result {
9898
Some((
@@ -123,7 +123,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
123123
) -> Option<(Vec<Segment>, Option<String>)> {
124124
// Replace first ident with `crate` and check if that is valid.
125125
path[0].ident.name = keywords::Super.name();
126-
let result = self.resolve_path(None, &path, None, parent_scope, false, span, CrateLint::No);
126+
let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No);
127127
debug!("make_missing_super_suggestion: path={:?} result={:?}", path, result);
128128
if let PathResult::Module(..) = result {
129129
Some((path, None))
@@ -164,8 +164,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
164164
// Replace the first after root (a placeholder we inserted) with a crate name
165165
// and check if that is valid.
166166
path[1].ident.name = *name;
167-
let result =
168-
self.resolve_path(None, &path, None, parent_scope, false, span, CrateLint::No);
167+
let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No);
169168
debug!("make_external_crate_suggestion: name={:?} path={:?} result={:?}",
170169
name, path, result);
171170
if let PathResult::Module(..) = result {

src/librustc_resolve/lib.rs

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1661,8 +1661,8 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
16611661
let segments = &path.segments;
16621662
let path = Segment::from_path(&path);
16631663
// FIXME (Manishearth): Intra doc links won't get warned of epoch changes
1664-
let def = match self.resolve_path_without_parent_scope(None, &path, Some(namespace),
1665-
true, span, CrateLint::No) {
1664+
match self.resolve_path_without_parent_scope(&path, Some(namespace), true, span,
1665+
CrateLint::No) {
16661666
PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
16671667
module.def().unwrap(),
16681668
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 =>
@@ -2466,7 +2466,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
24662466
let span = trait_ref.path.span;
24672467
if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
24682468
self.resolve_path_without_parent_scope(
2469-
None,
24702469
&path,
24712470
Some(TypeNS),
24722471
false,
@@ -2991,7 +2990,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
29912990
} else {
29922991
let mod_path = &path[..path.len() - 1];
29932992
let mod_prefix = match this.resolve_path_without_parent_scope(
2994-
None, mod_path, Some(TypeNS), false, span, CrateLint::No
2993+
mod_path, Some(TypeNS), false, span, CrateLint::No
29952994
) {
29962995
PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
29972996
module.def(),
@@ -3480,7 +3479,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
34803479
}
34813480

34823481
let result = match self.resolve_path_without_parent_scope(
3483-
None,
34843482
&path,
34853483
Some(ns),
34863484
true,
@@ -3527,7 +3525,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
35273525
path[0].ident.name != keywords::DollarCrate.name() {
35283526
let unqualified_result = {
35293527
match self.resolve_path_without_parent_scope(
3530-
None,
35313528
&[*path.last().unwrap()],
35323529
Some(ns),
35333530
false,
@@ -3551,9 +3548,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
35513548

35523549
fn resolve_path_without_parent_scope(
35533550
&mut self,
3554-
base_module: Option<ModuleOrUniformRoot<'a>>,
35553551
path: &[Segment],
3556-
opt_ns: Option<Namespace>, // `None` indicates a module path
3552+
opt_ns: Option<Namespace>, // `None` indicates a module path in import
35573553
record_used: bool,
35583554
path_span: Span,
35593555
crate_lint: CrateLint,
@@ -3562,21 +3558,19 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
35623558
// other paths will do okay with parent module alone.
35633559
assert!(opt_ns != None && opt_ns != Some(MacroNS));
35643560
let parent_scope = ParentScope { module: self.current_module, ..self.dummy_parent_scope() };
3565-
self.resolve_path(base_module, path, opt_ns, &parent_scope,
3566-
record_used, path_span, crate_lint)
3561+
self.resolve_path(path, opt_ns, &parent_scope, record_used, path_span, crate_lint)
35673562
}
35683563

35693564
fn resolve_path(
35703565
&mut self,
3571-
base_module: Option<ModuleOrUniformRoot<'a>>,
35723566
path: &[Segment],
3573-
opt_ns: Option<Namespace>, // `None` indicates a module path
3567+
opt_ns: Option<Namespace>, // `None` indicates a module path in import
35743568
parent_scope: &ParentScope<'a>,
35753569
record_used: bool,
35763570
path_span: Span,
35773571
crate_lint: CrateLint,
35783572
) -> PathResult<'a> {
3579-
let mut module = base_module;
3573+
let mut module = None;
35803574
let mut allow_super = true;
35813575
let mut second_binding = None;
35823576
self.current_module = parent_scope.module;
@@ -3673,10 +3667,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
36733667

36743668
let binding = if let Some(module) = module {
36753669
self.resolve_ident_in_module(module, ident, ns, record_used, path_span)
3676-
} else if opt_ns == Some(MacroNS) {
3670+
} else if opt_ns.is_none() || opt_ns == Some(MacroNS) {
36773671
assert!(ns == TypeNS);
3678-
self.early_resolve_ident_in_lexical_scope(ident, ns, None, parent_scope,
3679-
record_used, record_used, path_span)
3672+
self.early_resolve_ident_in_lexical_scope(ident, ns, None, opt_ns.is_none(),
3673+
parent_scope, record_used, record_used,
3674+
path_span)
36803675
} else {
36813676
let record_used_id =
36823677
if record_used { crate_lint.node_id().or(Some(CRATE_NODE_ID)) } else { None };
@@ -3763,9 +3758,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
37633758

37643759
self.lint_if_path_starts_with_module(crate_lint, path, path_span, second_binding);
37653760

3766-
PathResult::Module(module.unwrap_or_else(|| {
3767-
span_bug!(path_span, "resolve_path: empty(?) path {:?} has no module", path);
3768-
}))
3761+
PathResult::Module(match module {
3762+
Some(module) => module,
3763+
None if path.is_empty() => ModuleOrUniformRoot::UniformRoot(keywords::Invalid.name()),
3764+
_ => span_bug!(path_span, "resolve_path: non-empty path `{:?}` has no module", path),
3765+
})
37693766
}
37703767

37713768
fn lint_if_path_starts_with_module(
@@ -4050,7 +4047,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
40504047
// Search in module.
40514048
let mod_path = &path[..path.len() - 1];
40524049
if let PathResult::Module(module) = self.resolve_path_without_parent_scope(
4053-
None, mod_path, Some(TypeNS), false, span, CrateLint::No
4050+
mod_path, Some(TypeNS), false, span, CrateLint::No
40544051
) {
40554052
if let ModuleOrUniformRoot::Module(module) = module {
40564053
add_module_candidates(module, &mut names);

src/librustc_resolve/macros.rs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
477477
}
478478

479479
if path.len() > 1 {
480-
let def = match self.resolve_path(None, &path, Some(MacroNS), parent_scope,
480+
let def = match self.resolve_path(&path, Some(MacroNS), parent_scope,
481481
false, path_span, CrateLint::No) {
482482
PathResult::NonModule(path_res) => match path_res.base_def() {
483483
Def::Err => Err(Determinacy::Determined),
@@ -506,7 +506,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
506506
def
507507
} else {
508508
let binding = self.early_resolve_ident_in_lexical_scope(
509-
path[0].ident, MacroNS, Some(kind), parent_scope, false, force, path_span
509+
path[0].ident, MacroNS, Some(kind), false, parent_scope, false, force, path_span
510510
);
511511
match binding {
512512
Ok(..) => {}
@@ -525,12 +525,13 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
525525
// This is a variation of `fn resolve_ident_in_lexical_scope` that can be run during
526526
// expansion and import resolution (perhaps they can be merged in the future).
527527
// The function is used for resolving initial segments of macro paths (e.g. `foo` in
528-
// `foo::bar!(); or `foo!();`) and can be used for "uniform path" imports in the future.
528+
// `foo::bar!(); or `foo!();`) and also for import paths on 2018 edition.
529529
crate fn early_resolve_ident_in_lexical_scope(
530530
&mut self,
531531
mut ident: Ident,
532532
ns: Namespace,
533-
kind: Option<MacroKind>,
533+
macro_kind: Option<MacroKind>,
534+
is_import: bool,
534535
parent_scope: &ParentScope<'a>,
535536
record_used: bool,
536537
force: bool,
@@ -604,6 +605,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
604605
}
605606

606607
assert!(force || !record_used); // `record_used` implies `force`
608+
assert!(macro_kind.is_none() || !is_import); // `is_import` implies no macro kind
607609
ident = ident.modern();
608610

609611
// This is *the* result, resolution from the scope closest to the resolved identifier.
@@ -792,7 +794,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
792794

793795
match result {
794796
Ok((binding, flags, ambig_flags)) => {
795-
if sub_namespace_mismatch(kind, binding.macro_kind()) {
797+
if sub_namespace_mismatch(macro_kind, binding.macro_kind()) {
796798
continue_search!();
797799
}
798800

@@ -804,7 +806,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
804806
= innermost_result {
805807
// Found another solution, if the first one was "weak", report an error.
806808
if binding.def() != innermost_binding.def() &&
807-
(innermost_binding.is_glob_import() ||
809+
(is_import ||
810+
innermost_binding.is_glob_import() ||
808811
innermost_binding.may_appear_after(parent_scope.expansion, binding) ||
809812
innermost_flags.intersects(ambig_flags) ||
810813
flags.intersects(innermost_ambig_flags) ||
@@ -838,7 +841,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
838841
}
839842

840843
let determinacy = Determinacy::determined(force);
841-
if determinacy == Determinacy::Determined && kind == Some(MacroKind::Attr) {
844+
if determinacy == Determinacy::Determined && macro_kind == Some(MacroKind::Attr) {
842845
// For single-segment attributes interpret determinate "no resolution" as a custom
843846
// attribute. (Lexical resolution implies the first segment and attr kind should imply
844847
// the last segment, so we are certainly working with a single-segment attribute here.)
@@ -860,7 +863,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
860863
for (mut path, parent_scope, path_span) in macro_resolutions {
861864
// FIXME: Path resolution will ICE if segment IDs present.
862865
for seg in &mut path { seg.id = None; }
863-
match self.resolve_path(None, &path, Some(MacroNS), &parent_scope,
866+
match self.resolve_path(&path, Some(MacroNS), &parent_scope,
864867
true, path_span, CrateLint::No) {
865868
PathResult::NonModule(_) => {},
866869
PathResult::Failed(span, msg, _) => {
@@ -874,7 +877,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
874877
mem::replace(&mut *module.legacy_macro_resolutions.borrow_mut(), Vec::new());
875878
for (ident, kind, parent_scope, initial_binding) in legacy_macro_resolutions {
876879
let binding = self.early_resolve_ident_in_lexical_scope(
877-
ident, MacroNS, Some(kind), &parent_scope, true, true, ident.span
880+
ident, MacroNS, Some(kind), false, &parent_scope, true, true, ident.span
878881
);
879882
match binding {
880883
Ok(binding) => {
@@ -915,7 +918,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
915918
let builtin_attrs = mem::replace(&mut *module.builtin_attrs.borrow_mut(), Vec::new());
916919
for (ident, parent_scope) in builtin_attrs {
917920
let binding = self.early_resolve_ident_in_lexical_scope(
918-
ident, MacroNS, Some(MacroKind::Attr), &parent_scope, true, true, ident.span
921+
ident, MacroNS, Some(MacroKind::Attr), false, &parent_scope, true, true, ident.span
919922
);
920923
if let Ok(binding) = binding {
921924
if binding.def_ignoring_ambiguity() !=

src/librustc_resolve/resolve_imports.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -152,10 +152,6 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
152152
let can_be_relative = !ident.is_path_segment_keyword() &&
153153
root == keywords::Invalid.name();
154154
if can_be_relative {
155-
// Relative paths should only get here if the feature-gate is on.
156-
assert!(self.session.rust_2018() &&
157-
self.session.features_untracked().uniform_paths);
158-
159155
// Try first to resolve relatively.
160156
let mut ctxt = ident.span.ctxt().modern();
161157
let self_module = self.resolve_self(&mut ctxt, self.current_module);
@@ -750,7 +746,6 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
750746
// while resolving its module path.
751747
directive.vis.set(ty::Visibility::Invisible);
752748
let result = self.resolve_path(
753-
Some(ModuleOrUniformRoot::UniformRoot(keywords::Invalid.name())),
754749
&directive.module_path[..],
755750
None,
756751
&directive.parent_scope,
@@ -829,7 +824,6 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
829824
let ImportDirective { ref module_path, span, .. } = *directive;
830825

831826
let module_result = self.resolve_path(
832-
Some(ModuleOrUniformRoot::UniformRoot(keywords::Invalid.name())),
833827
&module_path,
834828
None,
835829
&directive.parent_scope,

0 commit comments

Comments
 (0)