Skip to content

Commit d1b3eb5

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

File tree

5 files changed

+46
-65
lines changed

5 files changed

+46
-65
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.ident));
134-
let prefix_start = prefix_iter().next();
135-
let starts_with_non_keyword = prefix_start.map_or(false, |ident| {
136-
!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(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: &[Ident]| {
159147
prefix.is_empty() ||
160148
prefix.len() == 1 && prefix[0].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<Ident>, Option<String>)> {
6969
// Replace first ident with `self` and check if that is valid.
7070
path[0].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<Ident>, Option<String>)> {
9393
// Replace first ident with `crate` and check if that is valid.
9494
path[0].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<Ident>, Option<String>)> {
124124
// Replace first ident with `crate` and check if that is valid.
125125
path[0].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].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: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1621,7 +1621,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
16211621
let hir::Path { ref segments, span, ref mut def } = *path;
16221622
let path: Vec<_> = segments.iter().map(|seg| seg.ident).collect();
16231623
// FIXME (Manishearth): Intra doc links won't get warned of epoch changes
1624-
match self.resolve_path_without_parent_scope(None, &path, Some(namespace), true, span,
1624+
match self.resolve_path_without_parent_scope(&path, Some(namespace), true, span,
16251625
CrateLint::No) {
16261626
PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
16271627
*def = module.def().unwrap(),
@@ -2409,7 +2409,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
24092409
let span = trait_ref.path.span;
24102410
if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
24112411
self.resolve_path_without_parent_scope(
2412-
None,
24132412
&path,
24142413
Some(TypeNS),
24152414
false,
@@ -2930,7 +2929,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
29302929
} else {
29312930
let mod_path = &path[..path.len() - 1];
29322931
let mod_prefix = match this.resolve_path_without_parent_scope(
2933-
None, mod_path, Some(TypeNS), false, span, CrateLint::No
2932+
mod_path, Some(TypeNS), false, span, CrateLint::No
29342933
) {
29352934
PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
29362935
module.def(),
@@ -3416,7 +3415,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
34163415
}
34173416

34183417
let result = match self.resolve_path_without_parent_scope(
3419-
None,
34203418
&path,
34213419
Some(ns),
34223420
true,
@@ -3463,7 +3461,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
34633461
path[0].name != keywords::DollarCrate.name() {
34643462
let unqualified_result = {
34653463
match self.resolve_path_without_parent_scope(
3466-
None,
34673464
&[*path.last().unwrap()],
34683465
Some(ns),
34693466
false,
@@ -3487,9 +3484,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
34873484

34883485
fn resolve_path_without_parent_scope(
34893486
&mut self,
3490-
base_module: Option<ModuleOrUniformRoot<'a>>,
34913487
path: &[Ident],
3492-
opt_ns: Option<Namespace>, // `None` indicates a module path
3488+
opt_ns: Option<Namespace>, // `None` indicates a module path in import
34933489
record_used: bool,
34943490
path_span: Span,
34953491
crate_lint: CrateLint,
@@ -3498,21 +3494,19 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
34983494
// other paths will do okay with parent module alone.
34993495
assert!(opt_ns != None && opt_ns != Some(MacroNS));
35003496
let parent_scope = ParentScope { module: self.current_module, ..self.dummy_parent_scope() };
3501-
self.resolve_path(base_module, path, opt_ns, &parent_scope,
3502-
record_used, path_span, crate_lint)
3497+
self.resolve_path(path, opt_ns, &parent_scope, record_used, path_span, crate_lint)
35033498
}
35043499

35053500
fn resolve_path(
35063501
&mut self,
3507-
base_module: Option<ModuleOrUniformRoot<'a>>,
35083502
path: &[Ident],
3509-
opt_ns: Option<Namespace>, // `None` indicates a module path
3503+
opt_ns: Option<Namespace>, // `None` indicates a module path in import
35103504
parent_scope: &ParentScope<'a>,
35113505
record_used: bool,
35123506
path_span: Span,
35133507
crate_lint: CrateLint,
35143508
) -> PathResult<'a> {
3515-
let mut module = base_module;
3509+
let mut module = None;
35163510
let mut allow_super = true;
35173511
let mut second_binding = None;
35183512
self.current_module = parent_scope.module;
@@ -3598,10 +3592,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
35983592

35993593
let binding = if let Some(module) = module {
36003594
self.resolve_ident_in_module(module, ident, ns, record_used, path_span)
3601-
} else if opt_ns == Some(MacroNS) {
3595+
} else if opt_ns.is_none() || opt_ns == Some(MacroNS) {
36023596
assert!(ns == TypeNS);
3603-
self.early_resolve_ident_in_lexical_scope(ident, ns, None, parent_scope,
3604-
record_used, record_used, path_span)
3597+
self.early_resolve_ident_in_lexical_scope(ident, ns, None, opt_ns.is_none(),
3598+
parent_scope, record_used, record_used,
3599+
path_span)
36053600
} else {
36063601
let record_used_id =
36073602
if record_used { crate_lint.node_id().or(Some(CRATE_NODE_ID)) } else { None };
@@ -3686,9 +3681,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
36863681

36873682
self.lint_if_path_starts_with_module(crate_lint, path, path_span, second_binding);
36883683

3689-
PathResult::Module(module.unwrap_or_else(|| {
3690-
span_bug!(path_span, "resolve_path: empty(?) path {:?} has no module", path);
3691-
}))
3684+
PathResult::Module(match module {
3685+
Some(module) => module,
3686+
None if path.is_empty() => ModuleOrUniformRoot::UniformRoot(keywords::Invalid.name()),
3687+
_ => span_bug!(path_span, "resolve_path: non-empty path `{:?}` has no module", path),
3688+
})
36923689
}
36933690

36943691
fn lint_if_path_starts_with_module(
@@ -3973,7 +3970,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
39733970
// Search in module.
39743971
let mod_path = &path[..path.len() - 1];
39753972
if let PathResult::Module(module) = self.resolve_path_without_parent_scope(
3976-
None, mod_path, Some(TypeNS), false, span, CrateLint::No
3973+
mod_path, Some(TypeNS), false, span, CrateLint::No
39773974
) {
39783975
if let ModuleOrUniformRoot::Module(module) = module {
39793976
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
@@ -473,7 +473,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
473473
}
474474

475475
if path.len() > 1 {
476-
let def = match self.resolve_path(None, &path, Some(MacroNS), parent_scope,
476+
let def = match self.resolve_path(&path, Some(MacroNS), parent_scope,
477477
false, path_span, CrateLint::No) {
478478
PathResult::NonModule(path_res) => match path_res.base_def() {
479479
Def::Err => Err(Determinacy::Determined),
@@ -502,7 +502,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
502502
def
503503
} else {
504504
let binding = self.early_resolve_ident_in_lexical_scope(
505-
path[0], MacroNS, Some(kind), parent_scope, false, force, path_span
505+
path[0], MacroNS, Some(kind), false, parent_scope, false, force, path_span
506506
);
507507
match binding {
508508
Ok(..) => {}
@@ -521,12 +521,13 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
521521
// This is a variation of `fn resolve_ident_in_lexical_scope` that can be run during
522522
// expansion and import resolution (perhaps they can be merged in the future).
523523
// The function is used for resolving initial segments of macro paths (e.g. `foo` in
524-
// `foo::bar!(); or `foo!();`) and can be used for "uniform path" imports in the future.
524+
// `foo::bar!(); or `foo!();`) and also for import paths on 2018 edition.
525525
crate fn early_resolve_ident_in_lexical_scope(
526526
&mut self,
527527
mut ident: Ident,
528528
ns: Namespace,
529-
kind: Option<MacroKind>,
529+
macro_kind: Option<MacroKind>,
530+
is_import: bool,
530531
parent_scope: &ParentScope<'a>,
531532
record_used: bool,
532533
force: bool,
@@ -600,6 +601,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
600601
}
601602

602603
assert!(force || !record_used); // `record_used` implies `force`
604+
assert!(macro_kind.is_none() || !is_import); // `is_import` implies no macro kind
603605
ident = ident.modern();
604606

605607
// This is *the* result, resolution from the scope closest to the resolved identifier.
@@ -784,7 +786,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
784786

785787
match result {
786788
Ok((binding, flags, ambig_flags)) => {
787-
if sub_namespace_mismatch(kind, binding.macro_kind()) {
789+
if sub_namespace_mismatch(macro_kind, binding.macro_kind()) {
788790
continue_search!();
789791
}
790792

@@ -796,7 +798,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
796798
= innermost_result {
797799
// Found another solution, if the first one was "weak", report an error.
798800
if binding.def() != innermost_binding.def() &&
799-
(innermost_binding.is_glob_import() ||
801+
(is_import ||
802+
innermost_binding.is_glob_import() ||
800803
innermost_binding.may_appear_after(parent_scope.expansion, binding) ||
801804
innermost_flags.intersects(ambig_flags) ||
802805
flags.intersects(innermost_ambig_flags) ||
@@ -830,7 +833,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
830833
}
831834

832835
let determinacy = Determinacy::determined(force);
833-
if determinacy == Determinacy::Determined && kind == Some(MacroKind::Attr) {
836+
if determinacy == Determinacy::Determined && macro_kind == Some(MacroKind::Attr) {
834837
// For single-segment attributes interpret determinate "no resolution" as a custom
835838
// attribute. (Lexical resolution implies the first segment and attr kind should imply
836839
// the last segment, so we are certainly working with a single-segment attribute here.)
@@ -850,7 +853,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
850853
let macro_resolutions =
851854
mem::replace(&mut *module.macro_resolutions.borrow_mut(), Vec::new());
852855
for (path, parent_scope, path_span) in macro_resolutions {
853-
match self.resolve_path(None, &path, Some(MacroNS), &parent_scope,
856+
match self.resolve_path(&path, Some(MacroNS), &parent_scope,
854857
true, path_span, CrateLint::No) {
855858
PathResult::NonModule(_) => {},
856859
PathResult::Failed(span, msg, _) => {
@@ -864,7 +867,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
864867
mem::replace(&mut *module.legacy_macro_resolutions.borrow_mut(), Vec::new());
865868
for (ident, kind, parent_scope, initial_binding) in legacy_macro_resolutions {
866869
let binding = self.early_resolve_ident_in_lexical_scope(
867-
ident, MacroNS, Some(kind), &parent_scope, true, true, ident.span
870+
ident, MacroNS, Some(kind), false, &parent_scope, true, true, ident.span
868871
);
869872
match binding {
870873
Ok(binding) => {
@@ -905,7 +908,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
905908
let builtin_attrs = mem::replace(&mut *module.builtin_attrs.borrow_mut(), Vec::new());
906909
for (ident, parent_scope) in builtin_attrs {
907910
let binding = self.early_resolve_ident_in_lexical_scope(
908-
ident, MacroNS, Some(MacroKind::Attr), &parent_scope, true, true, ident.span
911+
ident, MacroNS, Some(MacroKind::Attr), false, &parent_scope, true, true, ident.span
909912
);
910913
if let Ok(binding) = binding {
911914
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);
@@ -748,7 +744,6 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
748744
// while resolving its module path.
749745
directive.vis.set(ty::Visibility::Invisible);
750746
let result = self.resolve_path(
751-
Some(ModuleOrUniformRoot::UniformRoot(keywords::Invalid.name())),
752747
&directive.module_path[..],
753748
None,
754749
&directive.parent_scope,
@@ -827,7 +822,6 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
827822
let ImportDirective { ref module_path, span, .. } = *directive;
828823

829824
let module_result = self.resolve_path(
830-
Some(ModuleOrUniformRoot::UniformRoot(keywords::Invalid.name())),
831825
&module_path,
832826
None,
833827
&directive.parent_scope,

0 commit comments

Comments
 (0)