Skip to content

Commit 1f257bd

Browse files
committed
resolve: Make sure macros and imports are resolved in full parent scope
Slightly simplify `fn build_reduced_graph_for_use_tree`
1 parent acdbd06 commit 1f257bd

File tree

5 files changed

+83
-86
lines changed

5 files changed

+83
-86
lines changed

src/librustc_resolve/build_reduced_graph.rs

+21-33
Original file line numberDiff line numberDiff line change
@@ -111,23 +111,23 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
111111

112112
fn build_reduced_graph_for_use_tree(
113113
&mut self,
114-
root_use_tree: &ast::UseTree,
115-
root_id: NodeId,
114+
// This particular use tree
116115
use_tree: &ast::UseTree,
117116
id: NodeId,
118-
vis: ty::Visibility,
119117
parent_prefix: &[Segment],
120-
mut uniform_paths_canary_emitted: bool,
121118
nested: bool,
122-
item: &Item,
119+
mut uniform_paths_canary_emitted: bool,
120+
// The whole `use` item
123121
parent_scope: ParentScope<'a>,
122+
item: &Item,
123+
vis: ty::Visibility,
124+
root_span: Span,
124125
) {
125126
debug!("build_reduced_graph_for_use_tree(parent_prefix={:?}, \
126127
uniform_paths_canary_emitted={}, \
127128
use_tree={:?}, nested={})",
128129
parent_prefix, uniform_paths_canary_emitted, use_tree, nested);
129130

130-
let is_prelude = attr::contains_name(&item.attrs, "prelude_import");
131131
let uniform_paths =
132132
self.session.rust_2018() &&
133133
self.session.features_untracked().uniform_paths;
@@ -215,8 +215,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
215215
subclass,
216216
source.ident.span,
217217
id,
218-
root_use_tree.span,
219-
root_id,
218+
root_span,
219+
item.id,
220220
ty::Visibility::Invisible,
221221
parent_scope.clone(),
222222
true, // is_uniform_paths_canary
@@ -345,25 +345,25 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
345345
subclass,
346346
use_tree.span,
347347
id,
348-
root_use_tree.span,
349-
root_id,
348+
root_span,
349+
item.id,
350350
vis,
351351
parent_scope,
352352
false, // is_uniform_paths_canary
353353
);
354354
}
355355
ast::UseTreeKind::Glob => {
356356
let subclass = GlobImport {
357-
is_prelude,
357+
is_prelude: attr::contains_name(&item.attrs, "prelude_import"),
358358
max_vis: Cell::new(ty::Visibility::Invisible),
359359
};
360360
self.add_import_directive(
361361
prefix,
362362
subclass,
363363
use_tree.span,
364364
id,
365-
root_use_tree.span,
366-
root_id,
365+
root_span,
366+
item.id,
367367
vis,
368368
parent_scope,
369369
false, // is_uniform_paths_canary
@@ -394,16 +394,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
394394

395395
for &(ref tree, id) in items {
396396
self.build_reduced_graph_for_use_tree(
397-
root_use_tree,
398-
root_id,
399-
tree,
400-
id,
401-
vis,
402-
&prefix,
403-
uniform_paths_canary_emitted,
404-
true,
405-
item,
406-
parent_scope.clone(),
397+
// This particular use tree
398+
tree, id, &prefix, true, uniform_paths_canary_emitted,
399+
// The whole `use` item
400+
parent_scope.clone(), item, vis, root_span,
407401
);
408402
}
409403
}
@@ -421,16 +415,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
421415
match item.node {
422416
ItemKind::Use(ref use_tree) => {
423417
self.build_reduced_graph_for_use_tree(
424-
use_tree,
425-
item.id,
426-
use_tree,
427-
item.id,
428-
vis,
429-
&[],
430-
false, // uniform_paths_canary_emitted
431-
false,
432-
item,
433-
parent_scope,
418+
// This particular use tree
419+
use_tree, item.id, &[], false, false,
420+
// The whole `use` item
421+
parent_scope, item, vis, use_tree.span,
434422
);
435423
}
436424

src/librustc_resolve/error_reporting.rs

+22-13
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
use {CrateLint, PathResult, Segment};
12+
use macros::ParentScope;
1213

1314
use std::collections::BTreeSet;
1415

@@ -23,7 +24,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
2324
pub(crate) fn make_path_suggestion(
2425
&mut self,
2526
span: Span,
26-
path: Vec<Segment>
27+
path: Vec<Segment>,
28+
parent_scope: &ParentScope<'b>,
2729
) -> Option<Vec<Segment>> {
2830
debug!("make_path_suggestion: span={:?} path={:?}", span, path);
2931
// If we don't have a path to suggest changes to, then return.
@@ -40,10 +42,12 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
4042
(Some(fst), Some(snd)) if !is_special(fst.ident) && !is_special(snd.ident) => {
4143
debug!("make_path_suggestion: fst={:?} snd={:?}", fst, snd);
4244

43-
self.make_missing_self_suggestion(span, path.clone())
44-
.or_else(|| self.make_missing_crate_suggestion(span, path.clone()))
45-
.or_else(|| self.make_missing_super_suggestion(span, path.clone()))
46-
.or_else(|| self.make_external_crate_suggestion(span, path))
45+
self.make_missing_self_suggestion(span, path.clone(), parent_scope)
46+
.or_else(|| self.make_missing_crate_suggestion(span, path.clone(),
47+
parent_scope))
48+
.or_else(|| self.make_missing_super_suggestion(span, path.clone(),
49+
parent_scope))
50+
.or_else(|| self.make_external_crate_suggestion(span, path, parent_scope))
4751
},
4852
_ => None,
4953
}
@@ -59,11 +63,12 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
5963
fn make_missing_self_suggestion(
6064
&mut self,
6165
span: Span,
62-
mut path: Vec<Segment>
66+
mut path: Vec<Segment>,
67+
parent_scope: &ParentScope<'b>,
6368
) -> Option<Vec<Segment>> {
6469
// Replace first ident with `self` and check if that is valid.
6570
path[0].ident.name = keywords::SelfValue.name();
66-
let result = self.resolve_path(None, &path, None, false, span, CrateLint::No);
71+
let result = self.resolve_path(None, &path, None, parent_scope, false, span, CrateLint::No);
6772
debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result);
6873
if let PathResult::Module(..) = result {
6974
Some(path)
@@ -82,11 +87,12 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
8287
fn make_missing_crate_suggestion(
8388
&mut self,
8489
span: Span,
85-
mut path: Vec<Segment>
90+
mut path: Vec<Segment>,
91+
parent_scope: &ParentScope<'b>,
8692
) -> Option<Vec<Segment>> {
8793
// Replace first ident with `crate` and check if that is valid.
8894
path[0].ident.name = keywords::Crate.name();
89-
let result = self.resolve_path(None, &path, None, false, span, CrateLint::No);
95+
let result = self.resolve_path(None, &path, None, parent_scope, false, span, CrateLint::No);
9096
debug!("make_missing_crate_suggestion: path={:?} result={:?}", path, result);
9197
if let PathResult::Module(..) = result {
9298
Some(path)
@@ -105,11 +111,12 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
105111
fn make_missing_super_suggestion(
106112
&mut self,
107113
span: Span,
108-
mut path: Vec<Segment>
114+
mut path: Vec<Segment>,
115+
parent_scope: &ParentScope<'b>,
109116
) -> Option<Vec<Segment>> {
110117
// Replace first ident with `crate` and check if that is valid.
111118
path[0].ident.name = keywords::Super.name();
112-
let result = self.resolve_path(None, &path, None, false, span, CrateLint::No);
119+
let result = self.resolve_path(None, &path, None, parent_scope, false, span, CrateLint::No);
113120
debug!("make_missing_super_suggestion: path={:?} result={:?}", path, result);
114121
if let PathResult::Module(..) = result {
115122
Some(path)
@@ -131,7 +138,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
131138
fn make_external_crate_suggestion(
132139
&mut self,
133140
span: Span,
134-
mut path: Vec<Segment>
141+
mut path: Vec<Segment>,
142+
parent_scope: &ParentScope<'b>,
135143
) -> Option<Vec<Segment>> {
136144
// Need to clone else we can't call `resolve_path` without a borrow error. We also store
137145
// into a `BTreeMap` so we can get consistent ordering (and therefore the same diagnostic)
@@ -149,7 +157,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
149157
// Replace the first after root (a placeholder we inserted) with a crate name
150158
// and check if that is valid.
151159
path[1].ident.name = *name;
152-
let result = self.resolve_path(None, &path, None, false, span, CrateLint::No);
160+
let result =
161+
self.resolve_path(None, &path, None, parent_scope, false, span, CrateLint::No);
153162
debug!("make_external_crate_suggestion: name={:?} path={:?} result={:?}",
154163
name, path, result);
155164
if let PathResult::Module(..) = result {

src/librustc_resolve/lib.rs

+22-25
Original file line numberDiff line numberDiff line change
@@ -1054,7 +1054,7 @@ pub struct ModuleData<'a> {
10541054
resolutions: RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>,
10551055
legacy_macro_resolutions: RefCell<Vec<(Ident, MacroKind, ParentScope<'a>,
10561056
Option<&'a NameBinding<'a>>)>>,
1057-
macro_resolutions: RefCell<Vec<(Box<[Ident]>, Span)>>,
1057+
macro_resolutions: RefCell<Vec<(Vec<Segment>, ParentScope<'a>, Span)>>,
10581058
builtin_attrs: RefCell<Vec<(Ident, ParentScope<'a>)>>,
10591059

10601060
// Macro invocations that can expand into items in this module.
@@ -1668,22 +1668,15 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
16681668
let segments = &path.segments;
16691669
let path = Segment::from_path(&path);
16701670
// FIXME (Manishearth): Intra doc links won't get warned of epoch changes
1671-
let def = match self.resolve_path(None, &path, Some(namespace), true, span, CrateLint::No) {
1671+
let def = match self.resolve_path_without_parent_scope(None, &path, Some(namespace),
1672+
true, span, CrateLint::No) {
16721673
PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
16731674
module.def().unwrap(),
16741675
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 =>
16751676
path_res.base_def(),
16761677
PathResult::NonModule(..) => {
1677-
if let PathResult::Failed(span, msg, _) = self.resolve_path(
1678-
None,
1679-
&path,
1680-
None,
1681-
true,
1682-
span,
1683-
CrateLint::No,
1684-
) {
1685-
error_callback(self, span, ResolutionError::FailedToResolve(&msg));
1686-
}
1678+
let msg = "type-relative paths are not supported in this context";
1679+
error_callback(self, span, ResolutionError::FailedToResolve(msg));
16871680
Def::Err
16881681
}
16891682
PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) |
@@ -2530,10 +2523,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
25302523
new_id = Some(def.def_id());
25312524
let span = trait_ref.path.span;
25322525
if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
2533-
self.resolve_path(
2526+
self.resolve_path_without_parent_scope(
25342527
None,
25352528
&path,
2536-
None,
2529+
Some(TypeNS),
25372530
false,
25382531
span,
25392532
CrateLint::SimplePath(trait_ref.ref_id),
@@ -3055,8 +3048,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
30553048
(String::new(), "the crate root".to_string())
30563049
} else {
30573050
let mod_path = &path[..path.len() - 1];
3058-
let mod_prefix = match this.resolve_path(None, mod_path, Some(TypeNS),
3059-
false, span, CrateLint::No) {
3051+
let mod_prefix = match this.resolve_path_without_parent_scope(
3052+
None, mod_path, Some(TypeNS), false, span, CrateLint::No
3053+
) {
30603054
PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
30613055
module.def(),
30623056
_ => None,
@@ -3540,7 +3534,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
35403534
));
35413535
}
35423536

3543-
let result = match self.resolve_path(
3537+
let result = match self.resolve_path_without_parent_scope(
35443538
None,
35453539
&path,
35463540
Some(ns),
@@ -3587,7 +3581,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
35873581
path[0].ident.name != keywords::CrateRoot.name() &&
35883582
path[0].ident.name != keywords::DollarCrate.name() {
35893583
let unqualified_result = {
3590-
match self.resolve_path(
3584+
match self.resolve_path_without_parent_scope(
35913585
None,
35923586
&[*path.last().unwrap()],
35933587
Some(ns),
@@ -3610,7 +3604,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
36103604
Some(result)
36113605
}
36123606

3613-
fn resolve_path(
3607+
fn resolve_path_without_parent_scope(
36143608
&mut self,
36153609
base_module: Option<ModuleOrUniformRoot<'a>>,
36163610
path: &[Segment],
@@ -3619,12 +3613,15 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
36193613
path_span: Span,
36203614
crate_lint: CrateLint,
36213615
) -> PathResult<'a> {
3616+
// Macro and import paths must have full parent scope available during resolution,
3617+
// other paths will do okay with parent module alone.
3618+
assert!(opt_ns != None && opt_ns != Some(MacroNS));
36223619
let parent_scope = ParentScope { module: self.current_module, ..self.dummy_parent_scope() };
3623-
self.resolve_path_with_parent_scope(base_module, path, opt_ns, &parent_scope,
3624-
record_used, path_span, crate_lint)
3620+
self.resolve_path(base_module, path, opt_ns, &parent_scope,
3621+
record_used, path_span, crate_lint)
36253622
}
36263623

3627-
fn resolve_path_with_parent_scope(
3624+
fn resolve_path(
36283625
&mut self,
36293626
base_module: Option<ModuleOrUniformRoot<'a>>,
36303627
path: &[Segment],
@@ -3820,7 +3817,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
38203817
PathResult::Module(module.unwrap_or_else(|| {
38213818
span_bug!(path_span, "resolve_path: empty(?) path {:?} has no module", path);
38223819
}))
3823-
38243820
}
38253821

38263822
fn lint_if_path_starts_with_module(
@@ -4104,8 +4100,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
41044100
} else {
41054101
// Search in module.
41064102
let mod_path = &path[..path.len() - 1];
4107-
if let PathResult::Module(module) = self.resolve_path(None, mod_path, Some(TypeNS),
4108-
false, span, CrateLint::No) {
4103+
if let PathResult::Module(module) = self.resolve_path_without_parent_scope(
4104+
None, mod_path, Some(TypeNS), false, span, CrateLint::No
4105+
) {
41094106
if let ModuleOrUniformRoot::Module(module) = module {
41104107
add_module_candidates(module, &mut names);
41114108
}

0 commit comments

Comments
 (0)