mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-04 05:57:36 +00:00
Store a resolved def on hir::PathSegment
This commit is contained in:
parent
fc67d8fac4
commit
b49da276b3
@ -143,8 +143,13 @@ pub struct LoweringContext<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait Resolver {
|
pub trait Resolver {
|
||||||
/// Resolve a hir path generated by the lowerer when expanding `for`, `if let`, etc.
|
/// Resolve a path generated by the lowerer when expanding `for`, `if let`, etc.
|
||||||
fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool);
|
fn resolve_hir_path(
|
||||||
|
&mut self,
|
||||||
|
path: &ast::Path,
|
||||||
|
args: Option<P<hir::GenericArgs>>,
|
||||||
|
is_value: bool,
|
||||||
|
) -> hir::Path;
|
||||||
|
|
||||||
/// Obtain the resolution for a node id
|
/// Obtain the resolution for a node id
|
||||||
fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution>;
|
fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution>;
|
||||||
@ -163,7 +168,7 @@ pub trait Resolver {
|
|||||||
span: Span,
|
span: Span,
|
||||||
crate_root: Option<&str>,
|
crate_root: Option<&str>,
|
||||||
components: &[&str],
|
components: &[&str],
|
||||||
params: Option<P<hir::GenericArgs>>,
|
args: Option<P<hir::GenericArgs>>,
|
||||||
is_value: bool,
|
is_value: bool,
|
||||||
) -> hir::Path;
|
) -> hir::Path;
|
||||||
}
|
}
|
||||||
@ -1380,6 +1385,7 @@ impl<'a> LoweringContext<'a> {
|
|||||||
// does not actually exist in the AST.
|
// does not actually exist in the AST.
|
||||||
lctx.items.insert(exist_ty_id.node_id, exist_ty_item);
|
lctx.items.insert(exist_ty_id.node_id, exist_ty_item);
|
||||||
|
|
||||||
|
let def = Def::Existential(DefId::local(exist_ty_def_index));
|
||||||
// `impl Trait` now just becomes `Foo<'a, 'b, ..>`
|
// `impl Trait` now just becomes `Foo<'a, 'b, ..>`
|
||||||
hir::TyKind::Def(hir::ItemId { id: exist_ty_id.node_id }, lifetimes)
|
hir::TyKind::Def(hir::ItemId { id: exist_ty_id.node_id }, lifetimes)
|
||||||
})
|
})
|
||||||
@ -1852,8 +1858,10 @@ impl<'a> LoweringContext<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let def = self.expect_full_def(segment.id);
|
||||||
hir::PathSegment::new(
|
hir::PathSegment::new(
|
||||||
segment.ident,
|
segment.ident,
|
||||||
|
Some(def),
|
||||||
generic_args,
|
generic_args,
|
||||||
infer_types,
|
infer_types,
|
||||||
)
|
)
|
||||||
|
@ -347,6 +347,7 @@ impl fmt::Display for Path {
|
|||||||
pub struct PathSegment {
|
pub struct PathSegment {
|
||||||
/// The identifier portion of this path segment.
|
/// The identifier portion of this path segment.
|
||||||
pub ident: Ident,
|
pub ident: Ident,
|
||||||
|
pub def: Option<Def>,
|
||||||
|
|
||||||
/// Type/lifetime parameters attached to this path. They come in
|
/// Type/lifetime parameters attached to this path. They come in
|
||||||
/// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`. Note that
|
/// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`. Note that
|
||||||
@ -367,14 +368,16 @@ impl PathSegment {
|
|||||||
pub fn from_ident(ident: Ident) -> PathSegment {
|
pub fn from_ident(ident: Ident) -> PathSegment {
|
||||||
PathSegment {
|
PathSegment {
|
||||||
ident,
|
ident,
|
||||||
|
def: None,
|
||||||
infer_types: true,
|
infer_types: true,
|
||||||
args: None,
|
args: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(ident: Ident, args: GenericArgs, infer_types: bool) -> Self {
|
pub fn new(ident: Ident, def: Option<Def>, args: GenericArgs, infer_types: bool) -> Self {
|
||||||
PathSegment {
|
PathSegment {
|
||||||
ident,
|
ident,
|
||||||
|
def,
|
||||||
infer_types,
|
infer_types,
|
||||||
args: if args.is_empty() {
|
args: if args.is_empty() {
|
||||||
None
|
None
|
||||||
|
@ -174,6 +174,7 @@ impl_stable_hash_for!(struct hir::Path {
|
|||||||
|
|
||||||
impl_stable_hash_for!(struct hir::PathSegment {
|
impl_stable_hash_for!(struct hir::PathSegment {
|
||||||
ident -> (ident.name),
|
ident -> (ident.name),
|
||||||
|
def,
|
||||||
infer_types,
|
infer_types,
|
||||||
args
|
args
|
||||||
});
|
});
|
||||||
|
@ -141,7 +141,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||||||
let prefix_iter = || parent_prefix.iter().cloned()
|
let prefix_iter = || parent_prefix.iter().cloned()
|
||||||
.chain(use_tree.prefix.segments.iter().map(|seg| seg.ident));
|
.chain(use_tree.prefix.segments.iter().map(|seg| seg.ident));
|
||||||
let prefix_start = prefix_iter().next();
|
let prefix_start = prefix_iter().next();
|
||||||
let starts_with_non_keyword = prefix_start.map_or(false, |ident| {
|
let starts_with_non_keyword = prefix_start.map_or(false, |(ident, _)| {
|
||||||
!ident.is_path_segment_keyword()
|
!ident.is_path_segment_keyword()
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -202,13 +202,13 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||||||
let source = prefix_start.unwrap();
|
let source = prefix_start.unwrap();
|
||||||
|
|
||||||
// Helper closure to emit a canary with the given base path.
|
// Helper closure to emit a canary with the given base path.
|
||||||
let emit = |this: &mut Self, base: Option<Ident>| {
|
let emit = |this: &mut Self, base: Option<(Ident, Option<NodeId>)>| {
|
||||||
let subclass = SingleImport {
|
let subclass = SingleImport {
|
||||||
target: Ident {
|
target: Ident {
|
||||||
name: keywords::Underscore.name().gensymed(),
|
name: keywords::Underscore.name().gensymed(),
|
||||||
span: source.span,
|
span: source.0.span,
|
||||||
},
|
},
|
||||||
source,
|
source: source.0,
|
||||||
result: PerNS {
|
result: PerNS {
|
||||||
type_ns: Cell::new(Err(Undetermined)),
|
type_ns: Cell::new(Err(Undetermined)),
|
||||||
value_ns: Cell::new(Err(Undetermined)),
|
value_ns: Cell::new(Err(Undetermined)),
|
||||||
@ -219,7 +219,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||||||
this.add_import_directive(
|
this.add_import_directive(
|
||||||
base.into_iter().collect(),
|
base.into_iter().collect(),
|
||||||
subclass.clone(),
|
subclass.clone(),
|
||||||
source.span,
|
source.0.span,
|
||||||
id,
|
id,
|
||||||
root_use_tree.span,
|
root_use_tree.span,
|
||||||
root_id,
|
root_id,
|
||||||
@ -230,15 +230,15 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// A single simple `self::x` canary.
|
// A single simple `self::x` canary.
|
||||||
emit(self, Some(Ident {
|
emit(self, Some((Ident {
|
||||||
name: keywords::SelfValue.name(),
|
name: keywords::SelfValue.name(),
|
||||||
span: source.span,
|
span: source.0.span,
|
||||||
}));
|
}, source.1)));
|
||||||
|
|
||||||
// One special unprefixed canary per block scope around
|
// One special unprefixed canary per block scope around
|
||||||
// the import, to detect items unreachable by `self::x`.
|
// the import, to detect items unreachable by `self::x`.
|
||||||
let orig_current_module = self.current_module;
|
let orig_current_module = self.current_module;
|
||||||
let mut span = source.span.modern();
|
let mut span = source.0.span.modern();
|
||||||
loop {
|
loop {
|
||||||
match self.current_module.kind {
|
match self.current_module.kind {
|
||||||
ModuleKind::Block(..) => emit(self, None),
|
ModuleKind::Block(..) => emit(self, None),
|
||||||
@ -265,10 +265,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||||||
|
|
||||||
if nested {
|
if nested {
|
||||||
// Correctly handle `self`
|
// Correctly handle `self`
|
||||||
if source.name == keywords::SelfValue.name() {
|
if source.0.name == keywords::SelfValue.name() {
|
||||||
type_ns_only = true;
|
type_ns_only = true;
|
||||||
|
|
||||||
let empty_prefix = module_path.last().map_or(true, |ident| {
|
let empty_prefix = module_path.last().map_or(true, |(ident, _)| {
|
||||||
ident.name == keywords::CrateRoot.name()
|
ident.name == keywords::CrateRoot.name()
|
||||||
});
|
});
|
||||||
if empty_prefix {
|
if empty_prefix {
|
||||||
@ -284,20 +284,20 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||||||
// Replace `use foo::self;` with `use foo;`
|
// Replace `use foo::self;` with `use foo;`
|
||||||
source = module_path.pop().unwrap();
|
source = module_path.pop().unwrap();
|
||||||
if rename.is_none() {
|
if rename.is_none() {
|
||||||
ident = source;
|
ident = source.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Disallow `self`
|
// Disallow `self`
|
||||||
if source.name == keywords::SelfValue.name() {
|
if source.0.name == keywords::SelfValue.name() {
|
||||||
resolve_error(self,
|
resolve_error(self,
|
||||||
use_tree.span,
|
use_tree.span,
|
||||||
ResolutionError::SelfImportsOnlyAllowedWithin);
|
ResolutionError::SelfImportsOnlyAllowedWithin);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disallow `use $crate;`
|
// Disallow `use $crate;`
|
||||||
if source.name == keywords::DollarCrate.name() && module_path.is_empty() {
|
if source.0.name == keywords::DollarCrate.name() && module_path.is_empty() {
|
||||||
let crate_root = self.resolve_crate_root(source);
|
let crate_root = self.resolve_crate_root(source.0);
|
||||||
let crate_name = match crate_root.kind {
|
let crate_name = match crate_root.kind {
|
||||||
ModuleKind::Def(_, name) => name,
|
ModuleKind::Def(_, name) => name,
|
||||||
ModuleKind::Block(..) => unreachable!(),
|
ModuleKind::Block(..) => unreachable!(),
|
||||||
@ -307,11 +307,11 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||||||
// while the current crate doesn't have a valid `crate_name`.
|
// while the current crate doesn't have a valid `crate_name`.
|
||||||
if crate_name != keywords::Invalid.name() {
|
if crate_name != keywords::Invalid.name() {
|
||||||
// `crate_name` should not be interpreted as relative.
|
// `crate_name` should not be interpreted as relative.
|
||||||
module_path.push(Ident {
|
module_path.push((Ident {
|
||||||
name: keywords::CrateRoot.name(),
|
name: keywords::CrateRoot.name(),
|
||||||
span: source.span,
|
span: source.0.span,
|
||||||
});
|
}, Some(self.session.next_node_id())));
|
||||||
source.name = crate_name;
|
source.0.name = crate_name;
|
||||||
}
|
}
|
||||||
if rename.is_none() {
|
if rename.is_none() {
|
||||||
ident.name = crate_name;
|
ident.name = crate_name;
|
||||||
@ -332,7 +332,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||||||
|
|
||||||
let subclass = SingleImport {
|
let subclass = SingleImport {
|
||||||
target: ident,
|
target: ident,
|
||||||
source,
|
source: source.0,
|
||||||
result: PerNS {
|
result: PerNS {
|
||||||
type_ns: Cell::new(Err(Undetermined)),
|
type_ns: Cell::new(Err(Undetermined)),
|
||||||
value_ns: Cell::new(Err(Undetermined)),
|
value_ns: Cell::new(Err(Undetermined)),
|
||||||
@ -393,6 +393,17 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for &(ref tree, id) in items {
|
for &(ref tree, id) in items {
|
||||||
|
let prefix = ast::Path {
|
||||||
|
segments: module_path.iter()
|
||||||
|
.map(|ident| {
|
||||||
|
let mut seg = ast::PathSegment::from_ident(ident.0);
|
||||||
|
seg.id = self.session.next_node_id();
|
||||||
|
seg
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
span: path.span,
|
||||||
|
};
|
||||||
|
|
||||||
self.build_reduced_graph_for_use_tree(
|
self.build_reduced_graph_for_use_tree(
|
||||||
root_use_tree,
|
root_use_tree,
|
||||||
root_id,
|
root_id,
|
||||||
|
@ -1534,8 +1534,13 @@ impl<'a, 'b: 'a, 'cl: 'b> ty::DefIdTree for &'a Resolver<'b, 'cl> {
|
|||||||
/// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that
|
/// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that
|
||||||
/// the resolver is no longer needed as all the relevant information is inline.
|
/// the resolver is no longer needed as all the relevant information is inline.
|
||||||
impl<'a, 'cl> hir::lowering::Resolver for Resolver<'a, 'cl> {
|
impl<'a, 'cl> hir::lowering::Resolver for Resolver<'a, 'cl> {
|
||||||
fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool) {
|
fn resolve_hir_path(
|
||||||
self.resolve_hir_path_cb(path, is_value,
|
&mut self,
|
||||||
|
path: &ast::Path,
|
||||||
|
args: Option<P<hir::GenericArgs>>,
|
||||||
|
is_value: bool,
|
||||||
|
) -> hir::Path {
|
||||||
|
self.resolve_hir_path_cb(path, args, is_value,
|
||||||
|resolver, span, error| resolve_error(resolver, span, error))
|
|resolver, span, error| resolve_error(resolver, span, error))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1547,30 +1552,20 @@ impl<'a, 'cl> hir::lowering::Resolver for Resolver<'a, 'cl> {
|
|||||||
args: Option<P<hir::GenericArgs>>,
|
args: Option<P<hir::GenericArgs>>,
|
||||||
is_value: bool
|
is_value: bool
|
||||||
) -> hir::Path {
|
) -> hir::Path {
|
||||||
let mut segments = iter::once(keywords::CrateRoot.ident())
|
let segments = iter::once(keywords::CrateRoot.ident())
|
||||||
.chain(
|
.chain(
|
||||||
crate_root.into_iter()
|
crate_root.into_iter()
|
||||||
.chain(components.iter().cloned())
|
.chain(components.iter().cloned())
|
||||||
.map(Ident::from_str)
|
.map(Ident::from_str)
|
||||||
).map(hir::PathSegment::from_ident).collect::<Vec<_>>();
|
).map(|i| self.new_ast_path_segment(i)).collect::<Vec<_>>();
|
||||||
|
|
||||||
if let Some(args) = args {
|
|
||||||
let ident = segments.last().unwrap().ident;
|
|
||||||
*segments.last_mut().unwrap() = hir::PathSegment {
|
|
||||||
ident,
|
|
||||||
args: Some(args),
|
|
||||||
infer_types: true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut path = hir::Path {
|
let path = ast::Path {
|
||||||
span,
|
span,
|
||||||
def: Def::Err,
|
segments,
|
||||||
segments: segments.into(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.resolve_hir_path(&mut path, is_value);
|
self.resolve_hir_path(&path, args, is_value)
|
||||||
path
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution> {
|
fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution> {
|
||||||
@ -1596,23 +1591,27 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
|||||||
use std::iter;
|
use std::iter;
|
||||||
let mut errored = false;
|
let mut errored = false;
|
||||||
|
|
||||||
let mut path = if path_str.starts_with("::") {
|
let path = if path_str.starts_with("::") {
|
||||||
hir::Path {
|
ast::Path {
|
||||||
span,
|
span,
|
||||||
def: Def::Err,
|
segments: iter::once(keywords::CrateRoot.ident())
|
||||||
segments: iter::once(keywords::CrateRoot.ident()).chain({
|
.chain({
|
||||||
path_str.split("::").skip(1).map(Ident::from_str)
|
path_str.split("::").skip(1).map(Ident::from_str)
|
||||||
}).map(hir::PathSegment::from_ident).collect(),
|
})
|
||||||
|
.map(|i| self.new_ast_path_segment(i))
|
||||||
|
.collect(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
hir::Path {
|
ast::Path {
|
||||||
span,
|
span,
|
||||||
def: Def::Err,
|
segments: path_str
|
||||||
segments: path_str.split("::").map(Ident::from_str)
|
.split("::")
|
||||||
.map(hir::PathSegment::from_ident).collect(),
|
.map(Ident::from_str)
|
||||||
|
.map(|i| self.new_ast_path_segment(i))
|
||||||
|
.collect(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.resolve_hir_path_cb(&mut path, is_value, |_, _, _| errored = true);
|
let path = self.resolve_hir_path_cb(&path, None, is_value, |_, _, _| errored = true);
|
||||||
if errored || path.def == Def::Err {
|
if errored || path.def == Def::Err {
|
||||||
Err(())
|
Err(())
|
||||||
} else {
|
} else {
|
||||||
@ -1621,16 +1620,23 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// resolve_hir_path, but takes a callback in case there was an error
|
/// resolve_hir_path, but takes a callback in case there was an error
|
||||||
fn resolve_hir_path_cb<F>(&mut self, path: &mut hir::Path, is_value: bool, error_callback: F)
|
fn resolve_hir_path_cb<F>(
|
||||||
|
&mut self,
|
||||||
|
path: &ast::Path,
|
||||||
|
args: Option<P<hir::GenericArgs>>,
|
||||||
|
is_value: bool,
|
||||||
|
error_callback: F,
|
||||||
|
) -> hir::Path
|
||||||
where F: for<'c, 'b> FnOnce(&'c mut Resolver, Span, ResolutionError<'b>)
|
where F: for<'c, 'b> FnOnce(&'c mut Resolver, Span, ResolutionError<'b>)
|
||||||
{
|
{
|
||||||
let namespace = if is_value { ValueNS } else { TypeNS };
|
let namespace = if is_value { ValueNS } else { TypeNS };
|
||||||
let hir::Path { ref segments, span, ref mut def } = *path;
|
let span = path.span;
|
||||||
let path: Vec<_> = segments.iter().map(|seg| seg.ident).collect();
|
let segments = &path.segments;
|
||||||
|
let path: Vec<_> = segments.iter().map(|seg| (seg.ident, Some(seg.id))).collect();
|
||||||
// FIXME (Manishearth): Intra doc links won't get warned of epoch changes
|
// FIXME (Manishearth): Intra doc links won't get warned of epoch changes
|
||||||
match self.resolve_path(None, &path, Some(namespace), true, span, CrateLint::No) {
|
let def = match self.resolve_path(None, &path, Some(namespace), true, span, CrateLint::No) {
|
||||||
PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
|
PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
|
||||||
*def = module.def().unwrap(),
|
module.def().unwrap(),
|
||||||
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 =>
|
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 =>
|
||||||
*def = path_res.base_def(),
|
*def = path_res.base_def(),
|
||||||
PathResult::NonModule(..) =>
|
PathResult::NonModule(..) =>
|
||||||
@ -1648,9 +1654,28 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
|||||||
PathResult::Indeterminate => unreachable!(),
|
PathResult::Indeterminate => unreachable!(),
|
||||||
PathResult::Failed(span, msg, _) => {
|
PathResult::Failed(span, msg, _) => {
|
||||||
error_callback(self, span, ResolutionError::FailedToResolve(&msg));
|
error_callback(self, span, ResolutionError::FailedToResolve(&msg));
|
||||||
|
Def::Err
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut segments: Vec<_> = segments.iter().map(|seg| {
|
||||||
|
let mut hir_seg = hir::PathSegment::from_ident(seg.ident);
|
||||||
|
hir_seg.def = Some(self.def_map.get(&seg.id).map_or(Def::Err, |p| p.base_def()));
|
||||||
|
hir_seg
|
||||||
|
}).collect();
|
||||||
|
segments.last_mut().unwrap().args = args;
|
||||||
|
hir::Path {
|
||||||
|
span,
|
||||||
|
def,
|
||||||
|
segments: segments.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn new_ast_path_segment(&self, ident: Ident) -> ast::PathSegment {
|
||||||
|
let mut seg = ast::PathSegment::from_ident(ident);
|
||||||
|
seg.id = self.session.next_node_id();
|
||||||
|
seg
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
||||||
@ -2458,7 +2483,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
let mut new_id = None;
|
let mut new_id = None;
|
||||||
if let Some(trait_ref) = opt_trait_ref {
|
if let Some(trait_ref) = opt_trait_ref {
|
||||||
let path: Vec<_> = trait_ref.path.segments.iter()
|
let path: Vec<_> = trait_ref.path.segments.iter()
|
||||||
.map(|seg| seg.ident)
|
.map(|seg| (seg.ident, Some(seg.id)))
|
||||||
.collect();
|
.collect();
|
||||||
let def = self.smart_resolve_path_fragment(
|
let def = self.smart_resolve_path_fragment(
|
||||||
trait_ref.ref_id,
|
trait_ref.ref_id,
|
||||||
@ -2956,7 +2981,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
crate_lint: CrateLint
|
crate_lint: CrateLint
|
||||||
) -> PathResolution {
|
) -> PathResolution {
|
||||||
let segments = &path.segments.iter()
|
let segments = &path.segments.iter()
|
||||||
.map(|seg| seg.ident)
|
.map(|seg| (seg.ident, Some(seg.id)))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
self.smart_resolve_path_fragment(id, qself, segments, path.span, source, crate_lint)
|
self.smart_resolve_path_fragment(id, qself, segments, path.span, source, crate_lint)
|
||||||
}
|
}
|
||||||
@ -2964,12 +2989,12 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
fn smart_resolve_path_fragment(&mut self,
|
fn smart_resolve_path_fragment(&mut self,
|
||||||
id: NodeId,
|
id: NodeId,
|
||||||
qself: Option<&QSelf>,
|
qself: Option<&QSelf>,
|
||||||
path: &[Ident],
|
path: &[(Ident, Option<NodeId>)],
|
||||||
span: Span,
|
span: Span,
|
||||||
source: PathSource,
|
source: PathSource,
|
||||||
crate_lint: CrateLint)
|
crate_lint: CrateLint)
|
||||||
-> PathResolution {
|
-> PathResolution {
|
||||||
let ident_span = path.last().map_or(span, |ident| ident.span);
|
let ident_span = path.last().map_or(span, |ident| ident.0.span);
|
||||||
let ns = source.namespace();
|
let ns = source.namespace();
|
||||||
let is_expected = &|def| source.is_expected(def);
|
let is_expected = &|def| source.is_expected(def);
|
||||||
let is_enum_variant = &|def| if let Def::Variant(..) = def { true } else { false };
|
let is_enum_variant = &|def| if let Def::Variant(..) = def { true } else { false };
|
||||||
@ -2979,17 +3004,17 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
// Make the base error.
|
// Make the base error.
|
||||||
let expected = source.descr_expected();
|
let expected = source.descr_expected();
|
||||||
let path_str = names_to_string(path);
|
let path_str = names_to_string(path);
|
||||||
let item_str = path.last().unwrap();
|
let item_str = path.last().unwrap().0;
|
||||||
let code = source.error_code(def.is_some());
|
let code = source.error_code(def.is_some());
|
||||||
let (base_msg, fallback_label, base_span) = if let Some(def) = def {
|
let (base_msg, fallback_label, base_span) = if let Some(def) = def {
|
||||||
(format!("expected {}, found {} `{}`", expected, def.kind_name(), path_str),
|
(format!("expected {}, found {} `{}`", expected, def.kind_name(), path_str),
|
||||||
format!("not a {}", expected),
|
format!("not a {}", expected),
|
||||||
span)
|
span)
|
||||||
} else {
|
} else {
|
||||||
let item_span = path.last().unwrap().span;
|
let item_span = path.last().unwrap().0.span;
|
||||||
let (mod_prefix, mod_str) = if path.len() == 1 {
|
let (mod_prefix, mod_str) = if path.len() == 1 {
|
||||||
(String::new(), "this scope".to_string())
|
(String::new(), "this scope".to_string())
|
||||||
} else if path.len() == 2 && path[0].name == keywords::CrateRoot.name() {
|
} else if path.len() == 2 && path[0].0.name == keywords::CrateRoot.name() {
|
||||||
(String::new(), "the crate root".to_string())
|
(String::new(), "the crate root".to_string())
|
||||||
} else {
|
} else {
|
||||||
let mod_path = &path[..path.len() - 1];
|
let mod_path = &path[..path.len() - 1];
|
||||||
@ -2999,7 +3024,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
module.def(),
|
module.def(),
|
||||||
_ => None,
|
_ => None,
|
||||||
}.map_or(String::new(), |def| format!("{} ", def.kind_name()));
|
}.map_or(String::new(), |def| format!("{} ", def.kind_name()));
|
||||||
(mod_prefix, format!("`{}`", names_to_string(mod_path)))
|
(mod_prefix, format!("`{}`", names_and_ids_to_string(mod_path)))
|
||||||
};
|
};
|
||||||
(format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str),
|
(format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str),
|
||||||
format!("not found in {}", mod_str),
|
format!("not found in {}", mod_str),
|
||||||
@ -3045,7 +3070,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Try to lookup the name in more relaxed fashion for better error reporting.
|
// Try to lookup the name in more relaxed fashion for better error reporting.
|
||||||
let ident = *path.last().unwrap();
|
let ident = path.last().unwrap().0;
|
||||||
let candidates = this.lookup_import_candidates(ident.name, ns, is_expected);
|
let candidates = this.lookup_import_candidates(ident.name, ns, is_expected);
|
||||||
if candidates.is_empty() && is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) {
|
if candidates.is_empty() && is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) {
|
||||||
let enum_candidates =
|
let enum_candidates =
|
||||||
@ -3072,7 +3097,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
}
|
}
|
||||||
if path.len() == 1 && this.self_type_is_available(span) {
|
if path.len() == 1 && this.self_type_is_available(span) {
|
||||||
if let Some(candidate) = this.lookup_assoc_candidate(ident, ns, is_expected) {
|
if let Some(candidate) = this.lookup_assoc_candidate(ident, ns, is_expected) {
|
||||||
let self_is_available = this.self_value_is_available(path[0].span, span);
|
let self_is_available = this.self_value_is_available(path[0].0.span, span);
|
||||||
match candidate {
|
match candidate {
|
||||||
AssocSuggestion::Field => {
|
AssocSuggestion::Field => {
|
||||||
err.span_suggestion_with_applicability(
|
err.span_suggestion_with_applicability(
|
||||||
@ -3307,7 +3332,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
// or `<T>::A::B`. If `B` should be resolved in value namespace then
|
// or `<T>::A::B`. If `B` should be resolved in value namespace then
|
||||||
// it needs to be added to the trait map.
|
// it needs to be added to the trait map.
|
||||||
if ns == ValueNS {
|
if ns == ValueNS {
|
||||||
let item_name = *path.last().unwrap();
|
let item_name = path.last().unwrap().0;
|
||||||
let traits = self.get_traits_containing_item(item_name, ns);
|
let traits = self.get_traits_containing_item(item_name, ns);
|
||||||
self.trait_map.insert(id, traits);
|
self.trait_map.insert(id, traits);
|
||||||
}
|
}
|
||||||
@ -3377,7 +3402,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
fn resolve_qpath_anywhere(&mut self,
|
fn resolve_qpath_anywhere(&mut self,
|
||||||
id: NodeId,
|
id: NodeId,
|
||||||
qself: Option<&QSelf>,
|
qself: Option<&QSelf>,
|
||||||
path: &[Ident],
|
path: &[(Ident, Option<NodeId>)],
|
||||||
primary_ns: Namespace,
|
primary_ns: Namespace,
|
||||||
span: Span,
|
span: Span,
|
||||||
defer_to_typeck: bool,
|
defer_to_typeck: bool,
|
||||||
@ -3399,10 +3424,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if primary_ns != MacroNS &&
|
if primary_ns != MacroNS &&
|
||||||
(self.macro_names.contains(&path[0].modern()) ||
|
(self.macro_names.contains(&path[0].0.modern()) ||
|
||||||
self.builtin_macros.get(&path[0].name).cloned()
|
self.builtin_macros.get(&path[0].0.name).cloned()
|
||||||
.and_then(NameBinding::macro_kind) == Some(MacroKind::Bang) ||
|
.and_then(NameBinding::macro_kind) == Some(MacroKind::Bang) ||
|
||||||
self.macro_use_prelude.get(&path[0].name).cloned()
|
self.macro_use_prelude.get(&path[0].0.name).cloned()
|
||||||
.and_then(NameBinding::macro_kind) == Some(MacroKind::Bang)) {
|
.and_then(NameBinding::macro_kind) == Some(MacroKind::Bang)) {
|
||||||
// Return some dummy definition, it's enough for error reporting.
|
// Return some dummy definition, it's enough for error reporting.
|
||||||
return Some(
|
return Some(
|
||||||
@ -3416,7 +3441,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
fn resolve_qpath(&mut self,
|
fn resolve_qpath(&mut self,
|
||||||
id: NodeId,
|
id: NodeId,
|
||||||
qself: Option<&QSelf>,
|
qself: Option<&QSelf>,
|
||||||
path: &[Ident],
|
path: &[(Ident, Option<NodeId>)],
|
||||||
ns: Namespace,
|
ns: Namespace,
|
||||||
span: Span,
|
span: Span,
|
||||||
global_by_default: bool,
|
global_by_default: bool,
|
||||||
@ -3506,8 +3531,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
PathResult::Failed(..)
|
PathResult::Failed(..)
|
||||||
if (ns == TypeNS || path.len() > 1) &&
|
if (ns == TypeNS || path.len() > 1) &&
|
||||||
self.primitive_type_table.primitive_types
|
self.primitive_type_table.primitive_types
|
||||||
.contains_key(&path[0].name) => {
|
.contains_key(&path[0].0.name) => {
|
||||||
let prim = self.primitive_type_table.primitive_types[&path[0].name];
|
let prim = self.primitive_type_table.primitive_types[&path[0].0.name];
|
||||||
PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.len() - 1)
|
PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.len() - 1)
|
||||||
}
|
}
|
||||||
PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
|
PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
|
||||||
@ -3522,8 +3547,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if path.len() > 1 && !global_by_default && result.base_def() != Def::Err &&
|
if path.len() > 1 && !global_by_default && result.base_def() != Def::Err &&
|
||||||
path[0].name != keywords::CrateRoot.name() &&
|
path[0].0.name != keywords::CrateRoot.name() &&
|
||||||
path[0].name != keywords::DollarCrate.name() {
|
path[0].0.name != keywords::DollarCrate.name() {
|
||||||
let unqualified_result = {
|
let unqualified_result = {
|
||||||
match self.resolve_path(
|
match self.resolve_path(
|
||||||
None,
|
None,
|
||||||
@ -3551,7 +3576,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
fn resolve_path(
|
fn resolve_path(
|
||||||
&mut self,
|
&mut self,
|
||||||
base_module: Option<ModuleOrUniformRoot<'a>>,
|
base_module: Option<ModuleOrUniformRoot<'a>>,
|
||||||
path: &[Ident],
|
path: &[(Ident, Option<NodeId>)],
|
||||||
opt_ns: Option<Namespace>, // `None` indicates a module path
|
opt_ns: Option<Namespace>, // `None` indicates a module path
|
||||||
record_used: bool,
|
record_used: bool,
|
||||||
path_span: Span,
|
path_span: Span,
|
||||||
@ -3587,7 +3612,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
crate_lint,
|
crate_lint,
|
||||||
);
|
);
|
||||||
|
|
||||||
for (i, &ident) in path.iter().enumerate() {
|
for (i, &(ident, id)) in path.iter().enumerate() {
|
||||||
debug!("resolve_path ident {} {:?}", i, ident);
|
debug!("resolve_path ident {} {:?}", i, ident);
|
||||||
let is_last = i == path.len() - 1;
|
let is_last = i == path.len() - 1;
|
||||||
let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
|
let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
|
||||||
@ -3648,7 +3673,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
} else {
|
} else {
|
||||||
format!("`{}`", name)
|
format!("`{}`", name)
|
||||||
};
|
};
|
||||||
let msg = if i == 1 && path[0].name == keywords::CrateRoot.name() {
|
let msg = if i == 1 && path[0].0.name == keywords::CrateRoot.name() {
|
||||||
format!("global paths cannot start with {}", name_str)
|
format!("global paths cannot start with {}", name_str)
|
||||||
} else {
|
} else {
|
||||||
format!("{} in paths can only be used in start position", name_str)
|
format!("{} in paths can only be used in start position", name_str)
|
||||||
@ -3688,6 +3713,12 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(def);
|
let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(def);
|
||||||
if let Some(next_module) = binding.module() {
|
if let Some(next_module) = binding.module() {
|
||||||
module = Some(ModuleOrUniformRoot::Module(next_module));
|
module = Some(ModuleOrUniformRoot::Module(next_module));
|
||||||
|
if !is_last && record_used {
|
||||||
|
if let Some(id) = id {
|
||||||
|
assert!(id != ast::DUMMY_NODE_ID, "Trying to resolve dummy id");
|
||||||
|
self.record_def(id, PathResolution::new(def));
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if def == Def::ToolMod && i + 1 != path.len() {
|
} else if def == Def::ToolMod && i + 1 != path.len() {
|
||||||
let def = Def::NonMacroAttr(NonMacroAttrKind::Tool);
|
let def = Def::NonMacroAttr(NonMacroAttrKind::Tool);
|
||||||
return PathResult::NonModule(PathResolution::new(def));
|
return PathResult::NonModule(PathResolution::new(def));
|
||||||
@ -3737,7 +3768,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
} else if i == 0 {
|
} else if i == 0 {
|
||||||
format!("Use of undeclared type or module `{}`", ident)
|
format!("Use of undeclared type or module `{}`", ident)
|
||||||
} else {
|
} else {
|
||||||
format!("Could not find `{}` in `{}`", ident, path[i - 1])
|
format!("Could not find `{}` in `{}`", ident, path[i - 1].0)
|
||||||
};
|
};
|
||||||
return PathResult::Failed(ident.span, msg, is_last);
|
return PathResult::Failed(ident.span, msg, is_last);
|
||||||
}
|
}
|
||||||
@ -3755,7 +3786,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
fn lint_if_path_starts_with_module(
|
fn lint_if_path_starts_with_module(
|
||||||
&self,
|
&self,
|
||||||
crate_lint: CrateLint,
|
crate_lint: CrateLint,
|
||||||
path: &[Ident],
|
path: &[(Ident, Option<NodeId>)],
|
||||||
path_span: Span,
|
path_span: Span,
|
||||||
second_binding: Option<&NameBinding>,
|
second_binding: Option<&NameBinding>,
|
||||||
) {
|
) {
|
||||||
@ -3772,7 +3803,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let first_name = match path.get(0) {
|
let first_name = match path.get(0) {
|
||||||
Some(ident) => ident.name,
|
Some(ident) => ident.0.name,
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3784,7 +3815,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
|
|
||||||
match path.get(1) {
|
match path.get(1) {
|
||||||
// If this import looks like `crate::...` it's already good
|
// If this import looks like `crate::...` it's already good
|
||||||
Some(ident) if ident.name == keywords::Crate.name() => return,
|
Some((ident, _)) if ident.name == keywords::Crate.name() => return,
|
||||||
// Otherwise go below to see if it's an extern crate
|
// Otherwise go below to see if it's an extern crate
|
||||||
Some(_) => {}
|
Some(_) => {}
|
||||||
// If the path has length one (and it's `CrateRoot` most likely)
|
// If the path has length one (and it's `CrateRoot` most likely)
|
||||||
@ -3977,7 +4008,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_typo_candidate<FilterFn>(&mut self,
|
fn lookup_typo_candidate<FilterFn>(&mut self,
|
||||||
path: &[Ident],
|
path: &[(Ident, Option<NodeId>)],
|
||||||
ns: Namespace,
|
ns: Namespace,
|
||||||
filter_fn: FilterFn,
|
filter_fn: FilterFn,
|
||||||
span: Span)
|
span: Span)
|
||||||
@ -4041,7 +4072,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = path[path.len() - 1].name;
|
let name = path[path.len() - 1].0.name;
|
||||||
// Make sure error reporting is deterministic.
|
// Make sure error reporting is deterministic.
|
||||||
names.sort_by_cached_key(|name| name.as_str());
|
names.sort_by_cached_key(|name| name.as_str());
|
||||||
match find_best_match_for_name(names.iter(), &name.as_str(), None) {
|
match find_best_match_for_name(names.iter(), &name.as_str(), None) {
|
||||||
@ -4558,7 +4589,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
ast::VisibilityKind::Restricted { ref path, id, .. } => {
|
ast::VisibilityKind::Restricted { ref path, id, .. } => {
|
||||||
// Visibilities are resolved as global by default, add starting root segment.
|
// Visibilities are resolved as global by default, add starting root segment.
|
||||||
let segments = path.make_root().iter().chain(path.segments.iter())
|
let segments = path.make_root().iter().chain(path.segments.iter())
|
||||||
.map(|seg| seg.ident)
|
.map(|seg| (seg.ident, Some(seg.id)))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let def = self.smart_resolve_path_fragment(
|
let def = self.smart_resolve_path_fragment(
|
||||||
id,
|
id,
|
||||||
@ -4851,12 +4882,12 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_self_type(path: &[Ident], namespace: Namespace) -> bool {
|
fn is_self_type(path: &[(Ident, Option<NodeId>)], namespace: Namespace) -> bool {
|
||||||
namespace == TypeNS && path.len() == 1 && path[0].name == keywords::SelfType.name()
|
namespace == TypeNS && path.len() == 1 && path[0].0.name == keywords::SelfType.name()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_self_value(path: &[Ident], namespace: Namespace) -> bool {
|
fn is_self_value(path: &[(Ident, Option<NodeId>)], namespace: Namespace) -> bool {
|
||||||
namespace == ValueNS && path.len() == 1 && path[0].name == keywords::SelfValue.name()
|
namespace == ValueNS && path.len() == 1 && path[0].0.name == keywords::SelfValue.name()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn names_to_string(idents: &[Ident]) -> String {
|
fn names_to_string(idents: &[Ident]) -> String {
|
||||||
@ -4872,6 +4903,12 @@ fn names_to_string(idents: &[Ident]) -> String {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn names_and_ids_to_string(segments: &[(Ident, Option<NodeId>)]) -> String {
|
||||||
|
names_to_string(&segments.iter()
|
||||||
|
.map(|seg| seg.0)
|
||||||
|
.collect::<Vec<_>>())
|
||||||
|
}
|
||||||
|
|
||||||
fn path_names_to_string(path: &Path) -> String {
|
fn path_names_to_string(path: &Path) -> String {
|
||||||
names_to_string(&path.segments.iter()
|
names_to_string(&path.segments.iter()
|
||||||
.map(|seg| seg.ident)
|
.map(|seg| seg.ident)
|
||||||
|
@ -462,13 +462,13 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||||||
force: bool,
|
force: bool,
|
||||||
) -> Result<Def, Determinacy> {
|
) -> Result<Def, Determinacy> {
|
||||||
let ast::Path { ref segments, span } = *path;
|
let ast::Path { ref segments, span } = *path;
|
||||||
let mut path: Vec<_> = segments.iter().map(|seg| seg.ident).collect();
|
let mut path: Vec<_> = segments.iter().map(|seg| (seg.ident, Some(seg.id))).collect();
|
||||||
|
|
||||||
// Possibly apply the macro helper hack
|
// Possibly apply the macro helper hack
|
||||||
if kind == MacroKind::Bang && path.len() == 1 &&
|
if kind == MacroKind::Bang && path.len() == 1 &&
|
||||||
path[0].span.ctxt().outer().expn_info().map_or(false, |info| info.local_inner_macros) {
|
path[0].0.span.ctxt().outer().expn_info().map_or(false, |info| info.local_inner_macros) {
|
||||||
let root = Ident::new(keywords::DollarCrate.name(), path[0].span);
|
let root = Ident::new(keywords::DollarCrate.name(), path[0].0.span);
|
||||||
path.insert(0, root);
|
path.insert(0, (root, None));
|
||||||
}
|
}
|
||||||
|
|
||||||
if path.len() > 1 {
|
if path.len() > 1 {
|
||||||
@ -496,12 +496,16 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
parent_scope.module.macro_resolutions.borrow_mut()
|
parent_scope.module.macro_resolutions.borrow_mut()
|
||||||
.push((path.into_boxed_slice(), span));
|
.push((path
|
||||||
|
.iter()
|
||||||
|
.map(|(ident, _)| *ident)
|
||||||
|
.collect::<Vec<Ident>>()
|
||||||
|
.into_boxed_slice(), span));
|
||||||
|
|
||||||
def
|
def
|
||||||
} else {
|
} else {
|
||||||
let binding = self.early_resolve_ident_in_lexical_scope(
|
let binding = self.early_resolve_ident_in_lexical_scope(
|
||||||
path[0], MacroNS, Some(kind), parent_scope, false, force, span
|
path[0].0, MacroNS, Some(kind), parent_scope, false, force, span
|
||||||
);
|
);
|
||||||
match binding {
|
match binding {
|
||||||
Ok(..) => {}
|
Ok(..) => {}
|
||||||
@ -510,7 +514,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
parent_scope.module.legacy_macro_resolutions.borrow_mut()
|
parent_scope.module.legacy_macro_resolutions.borrow_mut()
|
||||||
.push((path[0], kind, parent_scope.clone(), binding.ok()));
|
.push((path[0].0, kind, parent_scope.clone(), binding.ok()));
|
||||||
|
|
||||||
binding.map(|binding| binding.def_ignoring_ambiguity())
|
binding.map(|binding| binding.def_ignoring_ambiguity())
|
||||||
}
|
}
|
||||||
@ -846,6 +850,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||||||
pub fn finalize_current_module_macro_resolutions(&mut self) {
|
pub fn finalize_current_module_macro_resolutions(&mut self) {
|
||||||
let module = self.current_module;
|
let module = self.current_module;
|
||||||
for &(ref path, span) in module.macro_resolutions.borrow().iter() {
|
for &(ref path, span) in module.macro_resolutions.borrow().iter() {
|
||||||
|
let path = path
|
||||||
|
.iter()
|
||||||
|
.map(|ident| (*ident, None))
|
||||||
|
.collect::<Vec<(Ident, Option<ast::NodeId>)>>();
|
||||||
match self.resolve_path(None, &path, Some(MacroNS), true, span, CrateLint::No) {
|
match self.resolve_path(None, &path, Some(MacroNS), true, span, CrateLint::No) {
|
||||||
PathResult::NonModule(_) => {},
|
PathResult::NonModule(_) => {},
|
||||||
PathResult::Failed(span, msg, _) => {
|
PathResult::Failed(span, msg, _) => {
|
||||||
@ -938,7 +946,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let ident = Ident::new(Symbol::intern(name), span);
|
let ident = Ident::new(Symbol::intern(name), span);
|
||||||
self.lookup_typo_candidate(&[ident], MacroNS, is_macro, span)
|
self.lookup_typo_candidate(&[(ident, None)], MacroNS, is_macro, span)
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(suggestion) = suggestion {
|
if let Some(suggestion) = suggestion {
|
||||||
|
@ -14,7 +14,7 @@ use {AmbiguityError, CrateLint, Module, ModuleOrUniformRoot, PerNS};
|
|||||||
use Namespace::{self, TypeNS, MacroNS};
|
use Namespace::{self, TypeNS, MacroNS};
|
||||||
use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
|
use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
|
||||||
use Resolver;
|
use Resolver;
|
||||||
use {names_to_string, module_to_string};
|
use {names_to_string, names_and_ids_to_string, module_to_string};
|
||||||
use {resolve_error, ResolutionError};
|
use {resolve_error, ResolutionError};
|
||||||
|
|
||||||
use rustc_data_structures::ptr_key::PtrKey;
|
use rustc_data_structures::ptr_key::PtrKey;
|
||||||
@ -89,7 +89,7 @@ pub struct ImportDirective<'a> {
|
|||||||
pub root_span: Span,
|
pub root_span: Span,
|
||||||
|
|
||||||
pub parent: Module<'a>,
|
pub parent: Module<'a>,
|
||||||
pub module_path: Vec<Ident>,
|
pub module_path: Vec<(Ident, Option<NodeId>)>,
|
||||||
/// The resolution of `module_path`.
|
/// The resolution of `module_path`.
|
||||||
pub imported_module: Cell<Option<ModuleOrUniformRoot<'a>>>,
|
pub imported_module: Cell<Option<ModuleOrUniformRoot<'a>>>,
|
||||||
pub subclass: ImportDirectiveSubclass<'a>,
|
pub subclass: ImportDirectiveSubclass<'a>,
|
||||||
@ -393,7 +393,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
|||||||
|
|
||||||
// Add an import directive to the current module.
|
// Add an import directive to the current module.
|
||||||
pub fn add_import_directive(&mut self,
|
pub fn add_import_directive(&mut self,
|
||||||
module_path: Vec<Ident>,
|
module_path: Vec<(Ident, Option<NodeId>)>,
|
||||||
subclass: ImportDirectiveSubclass<'a>,
|
subclass: ImportDirectiveSubclass<'a>,
|
||||||
span: Span,
|
span: Span,
|
||||||
id: NodeId,
|
id: NodeId,
|
||||||
@ -679,7 +679,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
|||||||
|
|
||||||
let has_explicit_self =
|
let has_explicit_self =
|
||||||
!import.module_path.is_empty() &&
|
!import.module_path.is_empty() &&
|
||||||
import.module_path[0].name == keywords::SelfValue.name();
|
import.module_path[0].0.name == keywords::SelfValue.name();
|
||||||
|
|
||||||
self.per_ns(|_, ns| {
|
self.per_ns(|_, ns| {
|
||||||
if let Some(result) = result[ns].get().ok() {
|
if let Some(result) = result[ns].get().ok() {
|
||||||
@ -728,9 +728,11 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
|||||||
self.throw_unresolved_import_error(empty_vec, None);
|
self.throw_unresolved_import_error(empty_vec, None);
|
||||||
}
|
}
|
||||||
if !seen_spans.contains(&span) {
|
if !seen_spans.contains(&span) {
|
||||||
let path = import_path_to_string(&import.module_path[..],
|
let path = import_path_to_string(
|
||||||
&import.subclass,
|
&import.module_path.iter().map(|(ident, _)| *ident).collect::<Vec<_>>(),
|
||||||
span);
|
&import.subclass,
|
||||||
|
span,
|
||||||
|
);
|
||||||
error_vec.push((span, path, err));
|
error_vec.push((span, path, err));
|
||||||
seen_spans.insert(span);
|
seen_spans.insert(span);
|
||||||
prev_root_id = import.root_id;
|
prev_root_id = import.root_id;
|
||||||
@ -851,7 +853,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
|||||||
/// If successful, the resolved bindings are written into the module.
|
/// If successful, the resolved bindings are written into the module.
|
||||||
fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool {
|
fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool {
|
||||||
debug!("(resolving import for module) resolving import `{}::...` in `{}`",
|
debug!("(resolving import for module) resolving import `{}::...` in `{}`",
|
||||||
names_to_string(&directive.module_path[..]),
|
names_and_ids_to_string(&directive.module_path[..]),
|
||||||
module_to_string(self.current_module).unwrap_or_else(|| "???".to_string()));
|
module_to_string(self.current_module).unwrap_or_else(|| "???".to_string()));
|
||||||
|
|
||||||
self.current_module = directive.parent;
|
self.current_module = directive.parent;
|
||||||
@ -982,7 +984,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
|||||||
// HACK(eddyb) `lint_if_path_starts_with_module` needs at least
|
// HACK(eddyb) `lint_if_path_starts_with_module` needs at least
|
||||||
// 2 segments, so the `resolve_path` above won't trigger it.
|
// 2 segments, so the `resolve_path` above won't trigger it.
|
||||||
let mut full_path = module_path.clone();
|
let mut full_path = module_path.clone();
|
||||||
full_path.push(keywords::Invalid.ident());
|
full_path.push((keywords::Invalid.ident(), None));
|
||||||
self.lint_if_path_starts_with_module(
|
self.lint_if_path_starts_with_module(
|
||||||
directive.crate_lint(),
|
directive.crate_lint(),
|
||||||
&full_path,
|
&full_path,
|
||||||
@ -1146,7 +1148,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
|||||||
// HACK(eddyb) `lint_if_path_starts_with_module` needs at least
|
// HACK(eddyb) `lint_if_path_starts_with_module` needs at least
|
||||||
// 2 segments, so the `resolve_path` above won't trigger it.
|
// 2 segments, so the `resolve_path` above won't trigger it.
|
||||||
let mut full_path = module_path.clone();
|
let mut full_path = module_path.clone();
|
||||||
full_path.push(ident);
|
full_path.push((ident, None));
|
||||||
self.per_ns(|this, ns| {
|
self.per_ns(|this, ns| {
|
||||||
if let Ok(binding) = result[ns].get() {
|
if let Ok(binding) = result[ns].get() {
|
||||||
this.lint_if_path_starts_with_module(
|
this.lint_if_path_starts_with_module(
|
||||||
@ -1288,7 +1290,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
|||||||
let resolutions = imported_module.parent.expect("parent should exist")
|
let resolutions = imported_module.parent.expect("parent should exist")
|
||||||
.resolutions.borrow();
|
.resolutions.borrow();
|
||||||
let enum_path_segment_index = directive.module_path.len() - 1;
|
let enum_path_segment_index = directive.module_path.len() - 1;
|
||||||
let enum_ident = directive.module_path[enum_path_segment_index];
|
let enum_ident = directive.module_path[enum_path_segment_index].0;
|
||||||
|
|
||||||
let enum_resolution = resolutions.get(&(enum_ident, TypeNS))
|
let enum_resolution = resolutions.get(&(enum_ident, TypeNS))
|
||||||
.expect("resolution should exist");
|
.expect("resolution should exist");
|
||||||
@ -1311,6 +1313,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
|||||||
"consider making the enum public",
|
"consider making the enum public",
|
||||||
suggestion);
|
suggestion);
|
||||||
err.emit();
|
err.emit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,7 @@ impl PathSegment {
|
|||||||
pub fn crate_root(span: Span) -> Self {
|
pub fn crate_root(span: Span) -> Self {
|
||||||
PathSegment {
|
PathSegment {
|
||||||
ident: Ident::new(keywords::CrateRoot.name(), span),
|
ident: Ident::new(keywords::CrateRoot.name(), span),
|
||||||
id: CRATE_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
args: None,
|
args: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user