Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
67feeeb
resolve: Stop generating uniform path canaries
petrochenkov Nov 3, 2018
e6739fe
resolve: Resolve multi-segment imports using in-scope resolution on 2…
petrochenkov Nov 3, 2018
9d7d9ad
resolve: Simplify ambiguity checking for built-in attributes
petrochenkov Nov 4, 2018
f0ea1c6
resolve: Improve diagnostics for resolution ambiguities
petrochenkov Nov 4, 2018
1cfd08c
resolve: More precise determinacy tracking during import/macro resolu…
petrochenkov Nov 7, 2018
07af4ec
resolve: Resolve single-segment imports using in-scope resolution on …
petrochenkov Nov 8, 2018
4c5d822
resolve: Check resolution consistency for import paths and multi-segm…
petrochenkov Nov 10, 2018
cfe8155
resolve: Recover "did you mean" suggestions in imports
petrochenkov Nov 11, 2018
cfd7629
resolve: Tweak some articles in ambiguity diagnostics
petrochenkov Nov 11, 2018
a38f903
Fix ICEs from imports of items not defined in modules
petrochenkov Nov 11, 2018
8e88c34
resolve: Reintroduce feature gate for uniform paths in imports
petrochenkov Nov 12, 2018
0e8a97f
resolve: Avoid marking `extern crate` items as used in certain cases
petrochenkov Nov 13, 2018
f492e94
resolve: Support resolving macros without leaving traces
petrochenkov Nov 13, 2018
4fc3c13
resolve: Avoid sentence breaks in diagnostics
petrochenkov Nov 13, 2018
a5f9bd0
resolve: Future-proof against imports referring to local variables an…
petrochenkov Nov 17, 2018
5946470
resolve: Refactor away `DeterminacyExt`
petrochenkov Nov 17, 2018
139d109
Add a couple more tests + address review comments
petrochenkov Nov 17, 2018
38025e0
Fix rebase
petrochenkov Nov 18, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
resolve: Stop generating uniform path canaries
  • Loading branch information
petrochenkov committed Nov 18, 2018
commit 67feeebfadbb69b437281ad2e0b30b27289b436d
112 changes: 5 additions & 107 deletions src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,14 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
id: NodeId,
parent_prefix: &[Segment],
nested: bool,
mut uniform_paths_canary_emitted: bool,
// The whole `use` item
parent_scope: ParentScope<'a>,
item: &Item,
vis: ty::Visibility,
root_span: Span,
) {
debug!("build_reduced_graph_for_use_tree(parent_prefix={:?}, \
uniform_paths_canary_emitted={}, \
use_tree={:?}, nested={})",
parent_prefix, uniform_paths_canary_emitted, use_tree, nested);
debug!("build_reduced_graph_for_use_tree(parent_prefix={:?}, use_tree={:?}, nested={})",
parent_prefix, use_tree, nested);

let uniform_paths =
self.session.rust_2018() &&
Expand Down Expand Up @@ -158,101 +155,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
let prefix: Vec<_> = root.into_iter().chain(prefix_iter()).collect();

debug!("build_reduced_graph_for_use_tree: prefix={:?}", prefix);

// `#[feature(uniform_paths)]` allows an unqualified import path,
// e.g. `use x::...;` to resolve not just globally (`use ::x::...;`)
// but also relatively (`use self::x::...;`). To catch ambiguities
// that might arise from both of these being available and resolution
// silently picking one of them, an artificial `use self::x as _;`
// import is injected as a "canary", and an error is emitted if it
// successfully resolves while an `x` external crate exists.
//
// For each block scope around the `use` item, one special canary
// import of the form `use x as _;` is also injected, having its
// parent set to that scope; `resolve_imports` will only resolve
// it within its appropriate scope; if any of them successfully
// resolve, an ambiguity error is emitted, since the original
// import can't see the item in the block scope (`self::x` only
// looks in the enclosing module), but a non-`use` path could.
//
// Additionally, the canary might be able to catch limitations of the
// current implementation, where `::x` may be chosen due to `self::x`
// not existing, but `self::x` could appear later, from macro expansion.
//
// NB. The canary currently only errors if the `x::...` path *could*
// resolve as a relative path through the extern crate, i.e. `x` is
// in `extern_prelude`, *even though* `::x` might still forcefully
// load a non-`extern_prelude` crate.
// While always producing an ambiguity errors if `self::x` exists and
// a crate *could* be loaded, would be more conservative, imports for
// local modules named `test` (or less commonly, `syntax` or `log`),
// would need to be qualified (e.g. `self::test`), which is considered
// ergonomically unacceptable.
let emit_uniform_paths_canary =
!uniform_paths_canary_emitted &&
self.session.rust_2018() &&
starts_with_non_keyword;
if emit_uniform_paths_canary {
let source = prefix_start.unwrap();

// Helper closure to emit a canary with the given base path.
let emit = |this: &mut Self, base: Option<Segment>| {
let subclass = SingleImport {
target: Ident {
name: keywords::Underscore.name().gensymed(),
span: source.ident.span,
},
source: source.ident,
result: PerNS {
type_ns: Cell::new(Err(Undetermined)),
value_ns: Cell::new(Err(Undetermined)),
macro_ns: Cell::new(Err(Undetermined)),
},
type_ns_only: false,
};
this.add_import_directive(
base.into_iter().collect(),
subclass,
source.ident.span,
id,
root_span,
item.id,
ty::Visibility::Invisible,
parent_scope.clone(),
true, // is_uniform_paths_canary
);
};

// A single simple `self::x` canary.
emit(self, Some(Segment {
ident: Ident {
name: keywords::SelfValue.name(),
span: source.ident.span,
},
id: source.id
}));

// One special unprefixed canary per block scope around
// the import, to detect items unreachable by `self::x`.
let orig_current_module = self.current_module;
let mut span = source.ident.span.modern();
loop {
match self.current_module.kind {
ModuleKind::Block(..) => emit(self, None),
ModuleKind::Def(..) => break,
}
match self.hygienic_lexical_parent(self.current_module, &mut span) {
Some(module) => {
self.current_module = module;
}
None => break,
}
}
self.current_module = orig_current_module;

uniform_paths_canary_emitted = true;
}

let empty_for_self = |prefix: &[Segment]| {
prefix.is_empty() ||
prefix.len() == 1 && prefix[0].ident.name == keywords::CrateRoot.name()
Expand Down Expand Up @@ -350,7 +252,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
item.id,
vis,
parent_scope,
false, // is_uniform_paths_canary
);
}
ast::UseTreeKind::Glob => {
Expand All @@ -367,7 +268,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
item.id,
vis,
parent_scope,
false, // is_uniform_paths_canary
);
}
ast::UseTreeKind::Nested(ref items) => {
Expand Down Expand Up @@ -396,7 +296,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
for &(ref tree, id) in items {
self.build_reduced_graph_for_use_tree(
// This particular use tree
tree, id, &prefix, true, uniform_paths_canary_emitted,
tree, id, &prefix, true,
// The whole `use` item
parent_scope.clone(), item, vis, root_span,
);
Expand All @@ -420,7 +320,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
};
self.build_reduced_graph_for_use_tree(
// This particular use tree
&tree, id, &prefix, true, uniform_paths_canary_emitted,
&tree, id, &prefix, true,
// The whole `use` item
parent_scope.clone(), item, ty::Visibility::Invisible, root_span,
);
Expand All @@ -441,7 +341,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
ItemKind::Use(ref use_tree) => {
self.build_reduced_graph_for_use_tree(
// This particular use tree
use_tree, item.id, &[], false, false,
use_tree, item.id, &[], false,
// The whole `use` item
parent_scope, item, vis, use_tree.span,
);
Expand Down Expand Up @@ -492,7 +392,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
module_path: Vec::new(),
vis: Cell::new(vis),
used: Cell::new(used),
is_uniform_paths_canary: false,
});
self.potentially_unused_imports.push(directive);
let imported_binding = self.import(binding, directive);
Expand Down Expand Up @@ -905,7 +804,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
module_path: Vec::new(),
vis: Cell::new(ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))),
used: Cell::new(false),
is_uniform_paths_canary: false,
});

let allow_shadowing = parent_scope.expansion == Mark::root();
Expand Down
Loading