Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
2df1ceb0
R
Rust
项目概览
int
/
Rust
大约 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
2df1ceb0
编写于
3月 16, 2015
作者:
N
Nick Cameron
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
resolve: factor out resolve imports to its own module
上级
432011d1
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
1118 addition
and
1063 deletion
+1118
-1063
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/build_reduced_graph.rs
+8
-7
src/librustc_resolve/lib.rs
src/librustc_resolve/lib.rs
+85
-1053
src/librustc_resolve/record_exports.rs
src/librustc_resolve/record_exports.rs
+4
-3
src/librustc_resolve/resolve_imports.rs
src/librustc_resolve/resolve_imports.rs
+1021
-0
未找到文件。
src/librustc_resolve/build_reduced_graph.rs
浏览文件 @
2df1ceb0
...
...
@@ -14,16 +14,17 @@
//! any imports resolved.
use
{
DefModifiers
,
PUBLIC
,
IMPORTABLE
};
use
ImportDirective
;
use
ImportDirectiveSubclass
::{
self
,
SingleImport
,
GlobImport
};
use
ImportResolution
;
use
resolve_imports
::
ImportDirective
;
use
resolve_imports
::
ImportDirectiveSubclass
::{
self
,
SingleImport
,
GlobImport
};
use
resolve_imports
::
ImportResolution
;
use
Module
;
use
ModuleKind
::
*
;
use
Namespace
::{
TypeNS
,
ValueNS
};
use
NameBindings
;
use
{
names_to_string
,
module_to_string
};
use
ParentLink
::{
self
,
ModuleParentLink
,
BlockParentLink
};
use
Resolver
;
use
Shadowable
;
use
resolve_imports
::
Shadowable
;
use
TypeNsDef
;
use
self
::
DuplicateCheckingMode
::
*
;
...
...
@@ -381,7 +382,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
false
,
true
));
debug!
(
"(build reduced graph for item) found extern `{}`"
,
self
.
module_to_string
(
&*
external_module
));
module_to_string
(
&*
external_module
));
self
.check_for_conflicts_between_external_crates
(
&**
parent
,
name
,
sp
);
parent
.external_module_children
.borrow_mut
()
.insert
(
name
,
external_module
.clone
());
...
...
@@ -836,7 +837,7 @@ fn build_reduced_graph_for_external_crate_def(&mut self,
/// Builds the reduced graph rooted at the given external module.
fn
populate_external_module
(
&
mut
self
,
module
:
&
Rc
<
Module
>
)
{
debug!
(
"(populating external module) attempting to populate {}"
,
self
.
module_to_string
(
&**
module
));
module_to_string
(
&**
module
));
let
def_id
=
match
module
.def_id
.get
()
{
None
=>
{
...
...
@@ -903,7 +904,7 @@ fn build_import_directive(&mut self,
match
subclass
{
SingleImport
(
target
,
_
)
=>
{
debug!
(
"(building import directive) building import directive: {}::{}"
,
self
.
names_to_string
(
&
module_
.imports
.borrow
()
.last
()
.unwrap
()
.module_path
),
names_to_string
(
&
module_
.imports
.borrow
()
.last
()
.unwrap
()
.module_path
),
token
::
get_name
(
target
));
let
mut
import_resolutions
=
module_
.import_resolutions
.borrow_mut
();
...
...
src/librustc_resolve/lib.rs
浏览文件 @
2df1ceb0
// Copyright 2012-201
4
The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-201
5
The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
...
...
@@ -38,7 +38,6 @@
use
self
::
Namespace
::
*
;
use
self
::
NamespaceResult
::
*
;
use
self
::
NameDefinition
::
*
;
use
self
::
ImportDirectiveSubclass
::
*
;
use
self
::
ResolveResult
::
*
;
use
self
::
FallbackSuggestion
::
*
;
use
self
::
TypeParameters
::
*
;
...
...
@@ -98,6 +97,10 @@
use
std
::
rc
::{
Rc
,
Weak
};
use
std
::
usize
;
use
resolve_imports
::{
Target
,
ImportDirective
,
ImportResolution
};
use
resolve_imports
::
Shadowable
;
// NB: This module needs to be declared first so diagnostics are
// registered before they are used.
pub
mod
diagnostics
;
...
...
@@ -105,6 +108,7 @@
mod
check_unused
;
mod
record_exports
;
mod
build_reduced_graph
;
mod
resolve_imports
;
#[derive(Copy)]
struct
BindingInfo
{
...
...
@@ -253,13 +257,6 @@ fn visit_fn(&mut self,
}
}
/// Contains data for specific types of import directives.
#[derive(Copy,Debug)]
enum
ImportDirectiveSubclass
{
SingleImport
(
Name
/* target */
,
Name
/* source */
),
GlobImport
}
type
ErrorMessage
=
Option
<
(
Span
,
String
)
>
;
enum
ResolveResult
<
T
>
{
...
...
@@ -366,146 +363,6 @@ fn new(kind: RibKind) -> Rib {
}
}
/// Whether an import can be shadowed by another import.
#[derive(Debug,PartialEq,Clone,Copy)]
enum
Shadowable
{
Always
,
Never
}
/// One import directive.
#[derive(Debug)]
struct
ImportDirective
{
module_path
:
Vec
<
Name
>
,
subclass
:
ImportDirectiveSubclass
,
span
:
Span
,
id
:
NodeId
,
is_public
:
bool
,
// see note in ImportResolution about how to use this
shadowable
:
Shadowable
,
}
impl
ImportDirective
{
fn
new
(
module_path
:
Vec
<
Name
>
,
subclass
:
ImportDirectiveSubclass
,
span
:
Span
,
id
:
NodeId
,
is_public
:
bool
,
shadowable
:
Shadowable
)
->
ImportDirective
{
ImportDirective
{
module_path
:
module_path
,
subclass
:
subclass
,
span
:
span
,
id
:
id
,
is_public
:
is_public
,
shadowable
:
shadowable
,
}
}
}
/// The item that an import resolves to.
#[derive(Clone,Debug)]
struct
Target
{
target_module
:
Rc
<
Module
>
,
bindings
:
Rc
<
NameBindings
>
,
shadowable
:
Shadowable
,
}
impl
Target
{
fn
new
(
target_module
:
Rc
<
Module
>
,
bindings
:
Rc
<
NameBindings
>
,
shadowable
:
Shadowable
)
->
Target
{
Target
{
target_module
:
target_module
,
bindings
:
bindings
,
shadowable
:
shadowable
,
}
}
}
/// An ImportResolution represents a particular `use` directive.
#[derive(Debug)]
struct
ImportResolution
{
/// Whether this resolution came from a `use` or a `pub use`. Note that this
/// should *not* be used whenever resolution is being performed. Privacy
/// testing occurs during a later phase of compilation.
is_public
:
bool
,
// The number of outstanding references to this name. When this reaches
// zero, outside modules can count on the targets being correct. Before
// then, all bets are off; future imports could override this name.
// Note that this is usually either 0 or 1 - shadowing is forbidden the only
// way outstanding_references is > 1 in a legal program is if the name is
// used in both namespaces.
outstanding_references
:
uint
,
/// The value that this `use` directive names, if there is one.
value_target
:
Option
<
Target
>
,
/// The source node of the `use` directive leading to the value target
/// being non-none
value_id
:
NodeId
,
/// The type that this `use` directive names, if there is one.
type_target
:
Option
<
Target
>
,
/// The source node of the `use` directive leading to the type target
/// being non-none
type_id
:
NodeId
,
}
impl
ImportResolution
{
fn
new
(
id
:
NodeId
,
is_public
:
bool
)
->
ImportResolution
{
ImportResolution
{
type_id
:
id
,
value_id
:
id
,
outstanding_references
:
0
,
value_target
:
None
,
type_target
:
None
,
is_public
:
is_public
,
}
}
fn
target_for_namespace
(
&
self
,
namespace
:
Namespace
)
->
Option
<
Target
>
{
match
namespace
{
TypeNS
=>
self
.type_target
.clone
(),
ValueNS
=>
self
.value_target
.clone
(),
}
}
fn
id
(
&
self
,
namespace
:
Namespace
)
->
NodeId
{
match
namespace
{
TypeNS
=>
self
.type_id
,
ValueNS
=>
self
.value_id
,
}
}
fn
shadowable
(
&
self
,
namespace
:
Namespace
)
->
Shadowable
{
let
target
=
self
.target_for_namespace
(
namespace
);
if
target
.is_none
()
{
return
Shadowable
::
Always
;
}
target
.unwrap
()
.shadowable
}
fn
set_target_and_id
(
&
mut
self
,
namespace
:
Namespace
,
target
:
Option
<
Target
>
,
id
:
NodeId
)
{
match
namespace
{
TypeNS
=>
{
self
.type_target
=
target
;
self
.type_id
=
id
;
}
ValueNS
=>
{
self
.value_target
=
target
;
self
.value_id
=
id
;
}
}
}
}
/// The link from a module up to its nearest parent node.
#[derive(Clone,Debug)]
enum
ParentLink
{
...
...
@@ -978,7 +835,6 @@ enum FallbackChecks {
OnlyTraitAndStatics
}
impl
<
'a
,
'tcx
>
Resolver
<
'a
,
'tcx
>
{
fn
new
(
session
:
&
'a
Session
,
ast_map
:
&
'a
ast_map
::
Map
<
'tcx
>
,
...
...
@@ -1038,151 +894,6 @@ fn new(session: &'a Session,
}
}
// Import resolution
//
// This is a fixed-point algorithm. We resolve imports until our efforts
// are stymied by an unresolved import; then we bail out of the current
// module and continue. We terminate successfully once no more imports
// remain or unsuccessfully when no forward progress in resolving imports
// is made.
/// Resolves all imports for the crate. This method performs the fixed-
/// point iteration.
fn
resolve_imports
(
&
mut
self
)
{
let
mut
i
=
0
;
let
mut
prev_unresolved_imports
=
0
;
loop
{
debug!
(
"(resolving imports) iteration {}, {} imports left"
,
i
,
self
.unresolved_imports
);
let
module_root
=
self
.graph_root
.get_module
();
self
.resolve_imports_for_module_subtree
(
module_root
.clone
());
if
self
.unresolved_imports
==
0
{
debug!
(
"(resolving imports) success"
);
break
;
}
if
self
.unresolved_imports
==
prev_unresolved_imports
{
self
.report_unresolved_imports
(
module_root
);
break
;
}
i
+=
1
;
prev_unresolved_imports
=
self
.unresolved_imports
;
}
}
/// Attempts to resolve imports for the given module and all of its
/// submodules.
fn
resolve_imports_for_module_subtree
(
&
mut
self
,
module_
:
Rc
<
Module
>
)
{
debug!
(
"(resolving imports for module subtree) resolving {}"
,
self
.module_to_string
(
&*
module_
));
let
orig_module
=
replace
(
&
mut
self
.current_module
,
module_
.clone
());
self
.resolve_imports_for_module
(
module_
.clone
());
self
.current_module
=
orig_module
;
build_reduced_graph
::
populate_module_if_necessary
(
self
,
&
module_
);
for
(
_
,
child_node
)
in
&*
module_
.children
.borrow
()
{
match
child_node
.get_module_if_available
()
{
None
=>
{
// Nothing to do.
}
Some
(
child_module
)
=>
{
self
.resolve_imports_for_module_subtree
(
child_module
);
}
}
}
for
(
_
,
child_module
)
in
&*
module_
.anonymous_children
.borrow
()
{
self
.resolve_imports_for_module_subtree
(
child_module
.clone
());
}
}
/// Attempts to resolve imports for the given module only.
fn
resolve_imports_for_module
(
&
mut
self
,
module
:
Rc
<
Module
>
)
{
if
module
.all_imports_resolved
()
{
debug!
(
"(resolving imports for module) all imports resolved for
\
{}"
,
self
.module_to_string
(
&*
module
));
return
;
}
let
imports
=
module
.imports
.borrow
();
let
import_count
=
imports
.len
();
while
module
.resolved_import_count
.get
()
<
import_count
{
let
import_index
=
module
.resolved_import_count
.get
();
let
import_directive
=
&
(
*
imports
)[
import_index
];
match
self
.resolve_import_for_module
(
module
.clone
(),
import_directive
)
{
Failed
(
err
)
=>
{
let
(
span
,
help
)
=
match
err
{
Some
((
span
,
msg
))
=>
(
span
,
format!
(
". {}"
,
msg
)),
None
=>
(
import_directive
.span
,
String
::
new
())
};
let
msg
=
format!
(
"unresolved import `{}`{}"
,
self
.import_path_to_string
(
&
import_directive
.module_path
,
import_directive
.subclass
),
help
);
self
.resolve_error
(
span
,
&
msg
[
..
]);
}
Indeterminate
=>
break
,
// Bail out. We'll come around next time.
Success
(())
=>
()
// Good. Continue.
}
module
.resolved_import_count
.set
(
module
.resolved_import_count
.get
()
+
1
);
}
}
fn
names_to_string
(
&
self
,
names
:
&
[
Name
])
->
String
{
let
mut
first
=
true
;
let
mut
result
=
String
::
new
();
for
name
in
names
{
if
first
{
first
=
false
}
else
{
result
.push_str
(
"::"
)
}
result
.push_str
(
&
token
::
get_name
(
*
name
));
};
result
}
fn
path_names_to_string
(
&
self
,
path
:
&
Path
,
depth
:
usize
)
->
String
{
let
names
:
Vec
<
ast
::
Name
>
=
path
.segments
[
..
path
.segments
.len
()
-
depth
]
.iter
()
.map
(|
seg
|
seg
.identifier.name
)
.collect
();
self
.names_to_string
(
&
names
[
..
])
}
fn
import_directive_subclass_to_string
(
&
mut
self
,
subclass
:
ImportDirectiveSubclass
)
->
String
{
match
subclass
{
SingleImport
(
_
,
source
)
=>
{
token
::
get_name
(
source
)
.to_string
()
}
GlobImport
=>
"*"
.to_string
()
}
}
fn
import_path_to_string
(
&
mut
self
,
names
:
&
[
Name
],
subclass
:
ImportDirectiveSubclass
)
->
String
{
if
names
.is_empty
()
{
self
.import_directive_subclass_to_string
(
subclass
)
}
else
{
(
format!
(
"{}::{}"
,
self
.names_to_string
(
names
),
self
.import_directive_subclass_to_string
(
subclass
)))
.to_string
()
}
}
#[inline]
fn
record_import_use
(
&
mut
self
,
import_id
:
NodeId
,
name
:
Name
)
{
if
!
self
.make_glob_map
{
...
...
@@ -1206,102 +917,6 @@ fn get_trait_name(&self, did: DefId) -> Name {
}
}
/// Attempts to resolve the given import. The return value indicates
/// failure if we're certain the name does not exist, indeterminate if we
/// don't know whether the name exists at the moment due to other
/// currently-unresolved imports, or success if we know the name exists.
/// If successful, the resolved bindings are written into the module.
fn
resolve_import_for_module
(
&
mut
self
,
module_
:
Rc
<
Module
>
,
import_directive
:
&
ImportDirective
)
->
ResolveResult
<
()
>
{
let
mut
resolution_result
=
Failed
(
None
);
let
module_path
=
&
import_directive
.module_path
;
debug!
(
"(resolving import for module) resolving import `{}::...` in `{}`"
,
self
.names_to_string
(
&
module_path
[
..
]),
self
.module_to_string
(
&*
module_
));
// First, resolve the module path for the directive, if necessary.
let
container
=
if
module_path
.len
()
==
0
{
// Use the crate root.
Some
((
self
.graph_root
.get_module
(),
LastMod
(
AllPublic
)))
}
else
{
match
self
.resolve_module_path
(
module_
.clone
(),
&
module_path
[
..
],
DontUseLexicalScope
,
import_directive
.span
,
ImportSearch
)
{
Failed
(
err
)
=>
{
resolution_result
=
Failed
(
err
);
None
},
Indeterminate
=>
{
resolution_result
=
Indeterminate
;
None
}
Success
(
container
)
=>
Some
(
container
),
}
};
match
container
{
None
=>
{}
Some
((
containing_module
,
lp
))
=>
{
// We found the module that the target is contained
// within. Attempt to resolve the import within it.
match
import_directive
.subclass
{
SingleImport
(
target
,
source
)
=>
{
resolution_result
=
self
.resolve_single_import
(
&
module_
,
containing_module
,
target
,
source
,
import_directive
,
lp
);
}
GlobImport
=>
{
resolution_result
=
self
.resolve_glob_import
(
&
module_
,
containing_module
,
import_directive
,
lp
);
}
}
}
}
// Decrement the count of unresolved imports.
match
resolution_result
{
Success
(())
=>
{
assert
!
(
self
.unresolved_imports
>=
1
);
self
.unresolved_imports
-=
1
;
}
_
=>
{
// Nothing to do here; just return the error.
}
}
// Decrement the count of unresolved globs if necessary. But only if
// the resolution result is indeterminate -- otherwise we'll stop
// processing imports here. (See the loop in
// resolve_imports_for_module).
if
!
resolution_result
.indeterminate
()
{
match
import_directive
.subclass
{
GlobImport
=>
{
assert
!
(
module_
.glob_count
.get
()
>=
1
);
module_
.glob_count
.set
(
module_
.glob_count
.get
()
-
1
);
}
SingleImport
(
..
)
=>
{
// Ignore.
}
}
}
return
resolution_result
;
}
fn
create_name_bindings_from_module
(
module
:
Rc
<
Module
>
)
->
NameBindings
{
NameBindings
{
type_def
:
RefCell
::
new
(
Some
(
TypeNsDef
{
...
...
@@ -1314,612 +929,6 @@ fn create_name_bindings_from_module(module: Rc<Module>) -> NameBindings {
}
}
fn
resolve_single_import
(
&
mut
self
,
module_
:
&
Module
,
target_module
:
Rc
<
Module
>
,
target
:
Name
,
source
:
Name
,
directive
:
&
ImportDirective
,
lp
:
LastPrivate
)
->
ResolveResult
<
()
>
{
debug!
(
"(resolving single import) resolving `{}` = `{}::{}` from
\
`{}` id {}, last private {:?}"
,
token
::
get_name
(
target
),
self
.module_to_string
(
&*
target_module
),
token
::
get_name
(
source
),
self
.module_to_string
(
module_
),
directive
.id
,
lp
);
let
lp
=
match
lp
{
LastMod
(
lp
)
=>
lp
,
LastImport
{
..
}
=>
{
self
.session
.span_bug
(
directive
.span
,
"not expecting Import here, must be LastMod"
)
}
};
// We need to resolve both namespaces for this to succeed.
//
let
mut
value_result
=
UnknownResult
;
let
mut
type_result
=
UnknownResult
;
// Search for direct children of the containing module.
build_reduced_graph
::
populate_module_if_necessary
(
self
,
&
target_module
);
match
target_module
.children
.borrow
()
.get
(
&
source
)
{
None
=>
{
// Continue.
}
Some
(
ref
child_name_bindings
)
=>
{
// pub_err makes sure we don't give the same error twice.
let
mut
pub_err
=
false
;
if
child_name_bindings
.defined_in_namespace
(
ValueNS
)
{
debug!
(
"(resolving single import) found value binding"
);
value_result
=
BoundResult
(
target_module
.clone
(),
(
*
child_name_bindings
)
.clone
());
if
directive
.is_public
&&
!
child_name_bindings
.is_public
(
ValueNS
)
{
let
msg
=
format!
(
"`{}` is private"
,
token
::
get_name
(
source
));
span_err!
(
self
.session
,
directive
.span
,
E0364
,
"{}"
,
&
msg
);
pub_err
=
true
;
}
}
if
child_name_bindings
.defined_in_namespace
(
TypeNS
)
{
debug!
(
"(resolving single import) found type binding"
);
type_result
=
BoundResult
(
target_module
.clone
(),
(
*
child_name_bindings
)
.clone
());
if
!
pub_err
&&
directive
.is_public
&&
!
child_name_bindings
.is_public
(
TypeNS
)
{
let
msg
=
format!
(
"`{}` is private"
,
token
::
get_name
(
source
));
span_err!
(
self
.session
,
directive
.span
,
E0365
,
"{}"
,
&
msg
);
}
}
}
}
// Unless we managed to find a result in both namespaces (unlikely),
// search imports as well.
let
mut
value_used_reexport
=
false
;
let
mut
type_used_reexport
=
false
;
match
(
value_result
.clone
(),
type_result
.clone
())
{
(
BoundResult
(
..
),
BoundResult
(
..
))
=>
{}
// Continue.
_
=>
{
// If there is an unresolved glob at this point in the
// containing module, bail out. We don't know enough to be
// able to resolve this import.
if
target_module
.glob_count
.get
()
>
0
{
debug!
(
"(resolving single import) unresolved glob;
\
bailing out"
);
return
Indeterminate
;
}
// Now search the exported imports within the containing module.
match
target_module
.import_resolutions
.borrow
()
.get
(
&
source
)
{
None
=>
{
debug!
(
"(resolving single import) no import"
);
// The containing module definitely doesn't have an
// exported import with the name in question. We can
// therefore accurately report that the names are
// unbound.
if
value_result
.is_unknown
()
{
value_result
=
UnboundResult
;
}
if
type_result
.is_unknown
()
{
type_result
=
UnboundResult
;
}
}
Some
(
import_resolution
)
if
import_resolution
.outstanding_references
==
0
=>
{
fn
get_binding
(
this
:
&
mut
Resolver
,
import_resolution
:
&
ImportResolution
,
namespace
:
Namespace
,
source
:
&
Name
)
->
NamespaceResult
{
// Import resolutions must be declared with "pub"
// in order to be exported.
if
!
import_resolution
.is_public
{
return
UnboundResult
;
}
match
import_resolution
.target_for_namespace
(
namespace
)
{
None
=>
{
return
UnboundResult
;
}
Some
(
Target
{
target_module
,
bindings
,
shadowable
:
_
})
=>
{
debug!
(
"(resolving single import) found
\
import in ns {:?}"
,
namespace
);
let
id
=
import_resolution
.id
(
namespace
);
// track used imports and extern crates as well
this
.used_imports
.insert
((
id
,
namespace
));
this
.record_import_use
(
id
,
*
source
);
match
target_module
.def_id
.get
()
{
Some
(
DefId
{
krate
:
kid
,
..
})
=>
{
this
.used_crates
.insert
(
kid
);
},
_
=>
{}
}
return
BoundResult
(
target_module
,
bindings
);
}
}
}
// The name is an import which has been fully
// resolved. We can, therefore, just follow it.
if
value_result
.is_unknown
()
{
value_result
=
get_binding
(
self
,
import_resolution
,
ValueNS
,
&
source
);
value_used_reexport
=
import_resolution
.is_public
;
}
if
type_result
.is_unknown
()
{
type_result
=
get_binding
(
self
,
import_resolution
,
TypeNS
,
&
source
);
type_used_reexport
=
import_resolution
.is_public
;
}
}
Some
(
_
)
=>
{
// If target_module is the same module whose import we are resolving
// and there it has an unresolved import with the same name as `source`,
// then the user is actually trying to import an item that is declared
// in the same scope
//
// e.g
// use self::submodule;
// pub mod submodule;
//
// In this case we continue as if we resolved the import and let the
// check_for_conflicts_between_imports_and_items call below handle
// the conflict
match
(
module_
.def_id
.get
(),
target_module
.def_id
.get
())
{
(
Some
(
id1
),
Some
(
id2
))
if
id1
==
id2
=>
{
if
value_result
.is_unknown
()
{
value_result
=
UnboundResult
;
}
if
type_result
.is_unknown
()
{
type_result
=
UnboundResult
;
}
}
_
=>
{
// The import is unresolved. Bail out.
debug!
(
"(resolving single import) unresolved import;
\
bailing out"
);
return
Indeterminate
;
}
}
}
}
}
}
let
mut
value_used_public
=
false
;
let
mut
type_used_public
=
false
;
// If we didn't find a result in the type namespace, search the
// external modules.
match
type_result
{
BoundResult
(
..
)
=>
{}
_
=>
{
match
target_module
.external_module_children
.borrow_mut
()
.get
(
&
source
)
.cloned
()
{
None
=>
{}
// Continue.
Some
(
module
)
=>
{
debug!
(
"(resolving single import) found external module"
);
// track the module as used.
match
module
.def_id
.get
()
{
Some
(
DefId
{
krate
:
kid
,
..
})
=>
{
self
.used_crates
.insert
(
kid
);
},
_
=>
{}
}
let
name_bindings
=
Rc
::
new
(
Resolver
::
create_name_bindings_from_module
(
module
));
type_result
=
BoundResult
(
target_module
.clone
(),
name_bindings
);
type_used_public
=
true
;
}
}
}
}
// We've successfully resolved the import. Write the results in.
let
mut
import_resolutions
=
module_
.import_resolutions
.borrow_mut
();
let
import_resolution
=
&
mut
(
*
import_resolutions
)[
target
];
{
let
mut
check_and_write_import
=
|
namespace
,
result
:
&
_
,
used_public
:
&
mut
bool
|
{
let
namespace_name
=
match
namespace
{
TypeNS
=>
"type"
,
ValueNS
=>
"value"
,
};
match
*
result
{
BoundResult
(
ref
target_module
,
ref
name_bindings
)
=>
{
debug!
(
"(resolving single import) found {:?} target: {:?}"
,
namespace_name
,
name_bindings
.def_for_namespace
(
namespace
));
self
.check_for_conflicting_import
(
&
import_resolution
.target_for_namespace
(
namespace
),
directive
.span
,
target
,
namespace
);
self
.check_that_import_is_importable
(
&**
name_bindings
,
directive
.span
,
target
,
namespace
);
let
target
=
Some
(
Target
::
new
(
target_module
.clone
(),
name_bindings
.clone
(),
directive
.shadowable
));
import_resolution
.set_target_and_id
(
namespace
,
target
,
directive
.id
);
import_resolution
.is_public
=
directive
.is_public
;
*
used_public
=
name_bindings
.defined_in_public_namespace
(
namespace
);
}
UnboundResult
=>
{
/* Continue. */
}
UnknownResult
=>
{
panic!
(
"{:?} result should be known at this point"
,
namespace_name
);
}
}
};
check_and_write_import
(
ValueNS
,
&
value_result
,
&
mut
value_used_public
);
check_and_write_import
(
TypeNS
,
&
type_result
,
&
mut
type_used_public
);
}
self
.check_for_conflicts_between_imports_and_items
(
module_
,
import_resolution
,
directive
.span
,
target
);
if
value_result
.is_unbound
()
&&
type_result
.is_unbound
()
{
let
msg
=
format!
(
"There is no `{}` in `{}`"
,
token
::
get_name
(
source
),
self
.module_to_string
(
&
target_module
));
return
Failed
(
Some
((
directive
.span
,
msg
)));
}
let
value_used_public
=
value_used_reexport
||
value_used_public
;
let
type_used_public
=
type_used_reexport
||
type_used_public
;
assert
!
(
import_resolution
.outstanding_references
>=
1
);
import_resolution
.outstanding_references
-=
1
;
// Record what this import resolves to for later uses in documentation,
// this may resolve to either a value or a type, but for documentation
// purposes it's good enough to just favor one over the other.
let
value_def_and_priv
=
import_resolution
.value_target
.as_ref
()
.map
(|
target
|
{
let
def
=
target
.bindings
.def_for_namespace
(
ValueNS
)
.unwrap
();
(
def
,
if
value_used_public
{
lp
}
else
{
DependsOn
(
def
.def_id
())
})
});
let
type_def_and_priv
=
import_resolution
.type_target
.as_ref
()
.map
(|
target
|
{
let
def
=
target
.bindings
.def_for_namespace
(
TypeNS
)
.unwrap
();
(
def
,
if
type_used_public
{
lp
}
else
{
DependsOn
(
def
.def_id
())
})
});
let
import_lp
=
LastImport
{
value_priv
:
value_def_and_priv
.map
(|(
_
,
p
)|
p
),
value_used
:
Used
,
type_priv
:
type_def_and_priv
.map
(|(
_
,
p
)|
p
),
type_used
:
Used
};
if
let
Some
((
def
,
_
))
=
value_def_and_priv
{
self
.def_map
.borrow_mut
()
.insert
(
directive
.id
,
PathResolution
{
base_def
:
def
,
last_private
:
import_lp
,
depth
:
0
});
}
if
let
Some
((
def
,
_
))
=
type_def_and_priv
{
self
.def_map
.borrow_mut
()
.insert
(
directive
.id
,
PathResolution
{
base_def
:
def
,
last_private
:
import_lp
,
depth
:
0
});
}
debug!
(
"(resolving single import) successfully resolved import"
);
return
Success
(());
}
// Resolves a glob import. Note that this function cannot fail; it either
// succeeds or bails out (as importing * from an empty module or a module
// that exports nothing is valid). target_module is the module we are
// actually importing, i.e., `foo` in `use foo::*`.
fn
resolve_glob_import
(
&
mut
self
,
module_
:
&
Module
,
target_module
:
Rc
<
Module
>
,
import_directive
:
&
ImportDirective
,
lp
:
LastPrivate
)
->
ResolveResult
<
()
>
{
let
id
=
import_directive
.id
;
let
is_public
=
import_directive
.is_public
;
// This function works in a highly imperative manner; it eagerly adds
// everything it can to the list of import resolutions of the module
// node.
debug!
(
"(resolving glob import) resolving glob import {}"
,
id
);
// We must bail out if the node has unresolved imports of any kind
// (including globs).
if
!
(
*
target_module
)
.all_imports_resolved
()
{
debug!
(
"(resolving glob import) target module has unresolved
\
imports; bailing out"
);
return
Indeterminate
;
}
assert_eq!
(
target_module
.glob_count
.get
(),
0
);
// Add all resolved imports from the containing module.
let
import_resolutions
=
target_module
.import_resolutions
.borrow
();
for
(
ident
,
target_import_resolution
)
in
&*
import_resolutions
{
debug!
(
"(resolving glob import) writing module resolution
\
{} into `{}`"
,
token
::
get_name
(
*
ident
),
self
.module_to_string
(
module_
));
if
!
target_import_resolution
.is_public
{
debug!
(
"(resolving glob import) nevermind, just kidding"
);
continue
}
// Here we merge two import resolutions.
let
mut
import_resolutions
=
module_
.import_resolutions
.borrow_mut
();
match
import_resolutions
.get_mut
(
ident
)
{
Some
(
dest_import_resolution
)
=>
{
// Merge the two import resolutions at a finer-grained
// level.
match
target_import_resolution
.value_target
{
None
=>
{
// Continue.
}
Some
(
ref
value_target
)
=>
{
self
.check_for_conflicting_import
(
&
dest_import_resolution
.value_target
,
import_directive
.span
,
*
ident
,
ValueNS
);
dest_import_resolution
.value_target
=
Some
(
value_target
.clone
());
}
}
match
target_import_resolution
.type_target
{
None
=>
{
// Continue.
}
Some
(
ref
type_target
)
=>
{
self
.check_for_conflicting_import
(
&
dest_import_resolution
.type_target
,
import_directive
.span
,
*
ident
,
TypeNS
);
dest_import_resolution
.type_target
=
Some
(
type_target
.clone
());
}
}
dest_import_resolution
.is_public
=
is_public
;
continue
;
}
None
=>
{}
}
// Simple: just copy the old import resolution.
let
mut
new_import_resolution
=
ImportResolution
::
new
(
id
,
is_public
);
new_import_resolution
.value_target
=
target_import_resolution
.value_target
.clone
();
new_import_resolution
.type_target
=
target_import_resolution
.type_target
.clone
();
import_resolutions
.insert
(
*
ident
,
new_import_resolution
);
}
// Add all children from the containing module.
build_reduced_graph
::
populate_module_if_necessary
(
self
,
&
target_module
);
for
(
&
name
,
name_bindings
)
in
&*
target_module
.children
.borrow
()
{
self
.merge_import_resolution
(
module_
,
target_module
.clone
(),
import_directive
,
name
,
name_bindings
.clone
());
}
// Add external module children from the containing module.
for
(
&
name
,
module
)
in
&*
target_module
.external_module_children
.borrow
()
{
let
name_bindings
=
Rc
::
new
(
Resolver
::
create_name_bindings_from_module
(
module
.clone
()));
self
.merge_import_resolution
(
module_
,
target_module
.clone
(),
import_directive
,
name
,
name_bindings
);
}
// Record the destination of this import
if
let
Some
(
did
)
=
target_module
.def_id
.get
()
{
self
.def_map
.borrow_mut
()
.insert
(
id
,
PathResolution
{
base_def
:
DefMod
(
did
),
last_private
:
lp
,
depth
:
0
});
}
debug!
(
"(resolving glob import) successfully resolved import"
);
return
Success
(());
}
fn
merge_import_resolution
(
&
mut
self
,
module_
:
&
Module
,
containing_module
:
Rc
<
Module
>
,
import_directive
:
&
ImportDirective
,
name
:
Name
,
name_bindings
:
Rc
<
NameBindings
>
)
{
let
id
=
import_directive
.id
;
let
is_public
=
import_directive
.is_public
;
let
mut
import_resolutions
=
module_
.import_resolutions
.borrow_mut
();
let
dest_import_resolution
=
import_resolutions
.entry
(
name
)
.get
()
.unwrap_or_else
(
|
vacant_entry
|
{
// Create a new import resolution from this child.
vacant_entry
.insert
(
ImportResolution
::
new
(
id
,
is_public
))
});
debug!
(
"(resolving glob import) writing resolution `{}` in `{}`
\
to `{}`"
,
&
token
::
get_name
(
name
),
self
.module_to_string
(
&*
containing_module
),
self
.module_to_string
(
module_
));
// Merge the child item into the import resolution.
{
let
mut
merge_child_item
=
|
namespace
|
{
if
name_bindings
.defined_in_namespace_with
(
namespace
,
IMPORTABLE
|
PUBLIC
)
{
let
namespace_name
=
match
namespace
{
TypeNS
=>
"type"
,
ValueNS
=>
"value"
,
};
debug!
(
"(resolving glob import) ... for {} target"
,
namespace_name
);
if
dest_import_resolution
.shadowable
(
namespace
)
==
Shadowable
::
Never
{
let
msg
=
format!
(
"a {} named `{}` has already been imported
\
in this module"
,
namespace_name
,
&
token
::
get_name
(
name
));
span_err!
(
self
.session
,
import_directive
.span
,
E0251
,
"{}"
,
msg
);
}
else
{
let
target
=
Target
::
new
(
containing_module
.clone
(),
name_bindings
.clone
(),
import_directive
.shadowable
);
dest_import_resolution
.set_target_and_id
(
namespace
,
Some
(
target
),
id
);
}
}
};
merge_child_item
(
ValueNS
);
merge_child_item
(
TypeNS
);
}
dest_import_resolution
.is_public
=
is_public
;
self
.check_for_conflicts_between_imports_and_items
(
module_
,
dest_import_resolution
,
import_directive
.span
,
name
);
}
/// Checks that imported names and items don't have the same name.
fn
check_for_conflicting_import
(
&
mut
self
,
target
:
&
Option
<
Target
>
,
import_span
:
Span
,
name
:
Name
,
namespace
:
Namespace
)
{
debug!
(
"check_for_conflicting_import: {}; target exists: {}"
,
&
token
::
get_name
(
name
),
target
.is_some
());
match
*
target
{
Some
(
ref
target
)
if
target
.shadowable
!=
Shadowable
::
Always
=>
{
let
msg
=
format!
(
"a {} named `{}` has already been imported
\
in this module"
,
match
namespace
{
TypeNS
=>
"type"
,
ValueNS
=>
"value"
,
},
&
token
::
get_name
(
name
));
span_err!
(
self
.session
,
import_span
,
E0252
,
"{}"
,
&
msg
[
..
]);
}
Some
(
_
)
|
None
=>
{}
}
}
/// Checks that an import is actually importable
fn
check_that_import_is_importable
(
&
mut
self
,
name_bindings
:
&
NameBindings
,
import_span
:
Span
,
name
:
Name
,
namespace
:
Namespace
)
{
if
!
name_bindings
.defined_in_namespace_with
(
namespace
,
IMPORTABLE
)
{
let
msg
=
format!
(
"`{}` is not directly importable"
,
token
::
get_name
(
name
));
span_err!
(
self
.session
,
import_span
,
E0253
,
"{}"
,
&
msg
[
..
]);
}
}
/// Checks that imported names and items don't have the same name.
fn
check_for_conflicts_between_imports_and_items
(
&
mut
self
,
module
:
&
Module
,
import_resolution
:
&
ImportResolution
,
import_span
:
Span
,
name
:
Name
)
{
// First, check for conflicts between imports and `extern crate`s.
if
module
.external_module_children
.borrow
()
.contains_key
(
&
name
)
{
match
import_resolution
.type_target
{
Some
(
ref
target
)
if
target
.shadowable
!=
Shadowable
::
Always
=>
{
let
msg
=
format!
(
"import `{0}` conflicts with imported
\
crate in this module
\
(maybe you meant `use {0}::*`?)"
,
&
token
::
get_name
(
name
));
span_err!
(
self
.session
,
import_span
,
E0254
,
"{}"
,
&
msg
[
..
]);
}
Some
(
_
)
|
None
=>
{}
}
}
// Check for item conflicts.
let
children
=
module
.children
.borrow
();
let
name_bindings
=
match
children
.get
(
&
name
)
{
None
=>
{
// There can't be any conflicts.
return
}
Some
(
ref
name_bindings
)
=>
(
*
name_bindings
)
.clone
(),
};
match
import_resolution
.value_target
{
Some
(
ref
target
)
if
target
.shadowable
!=
Shadowable
::
Always
=>
{
if
let
Some
(
ref
value
)
=
*
name_bindings
.value_def
.borrow
()
{
span_err!
(
self
.session
,
import_span
,
E0255
,
"import `{}` conflicts with value in this module"
,
&
token
::
get_name
(
name
));
if
let
Some
(
span
)
=
value
.value_span
{
self
.session
.span_note
(
span
,
"conflicting value here"
);
}
}
}
Some
(
_
)
|
None
=>
{}
}
match
import_resolution
.type_target
{
Some
(
ref
target
)
if
target
.shadowable
!=
Shadowable
::
Always
=>
{
if
let
Some
(
ref
ty
)
=
*
name_bindings
.type_def
.borrow
()
{
let
(
what
,
note
)
=
if
ty
.module_def
.is_some
()
{
(
"existing submodule"
,
"note conflicting module here"
)
}
else
{
(
"type in this module"
,
"note conflicting type here"
)
};
span_err!
(
self
.session
,
import_span
,
E0256
,
"import `{}` conflicts with {}"
,
&
token
::
get_name
(
name
),
what
);
if
let
Some
(
span
)
=
ty
.type_span
{
self
.session
.span_note
(
span
,
note
);
}
}
}
Some
(
_
)
|
None
=>
{}
}
}
/// Checks that the names of external crates don't collide with other
/// external crates.
fn
check_for_conflicts_between_external_crates
(
&
self
,
...
...
@@ -1987,7 +996,7 @@ fn search_parent_externals(needle: Name, module: &Rc<Module>)
false
)
{
Failed
(
None
)
=>
{
let
segment_name
=
token
::
get_name
(
name
);
let
module_name
=
self
.
module_to_string
(
&*
search_module
);
let
module_name
=
module_to_string
(
&*
search_module
);
let
mut
span
=
span
;
let
msg
=
if
"???"
==
&
module_name
[
..
]
{
span
.hi
=
span
.lo
+
Pos
::
from_usize
(
segment_name
.len
());
...
...
@@ -1995,10 +1004,10 @@ fn search_parent_externals(needle: Name, module: &Rc<Module>)
match
search_parent_externals
(
name
,
&
self
.current_module
)
{
Some
(
module
)
=>
{
let
path_str
=
self
.
names_to_string
(
module_path
);
let
target_mod_str
=
self
.
module_to_string
(
&*
module
);
let
path_str
=
names_to_string
(
module_path
);
let
target_mod_str
=
module_to_string
(
&*
module
);
let
current_mod_str
=
self
.
module_to_string
(
&*
self
.current_module
);
module_to_string
(
&*
self
.current_module
);
let
prefix
=
if
target_mod_str
==
current_mod_str
{
"self::"
.to_string
()
...
...
@@ -2089,8 +1098,8 @@ fn resolve_module_path(&mut self,
assert
!
(
module_path_len
>
0
);
debug!
(
"(resolving module path for import) processing `{}` rooted at `{}`"
,
self
.
names_to_string
(
module_path
),
self
.
module_to_string
(
&*
module_
));
names_to_string
(
module_path
),
module_to_string
(
&*
module_
));
// Resolve the module prefix, if any.
let
module_prefix_result
=
self
.resolve_module_prefix
(
module_
.clone
(),
...
...
@@ -2101,7 +1110,7 @@ fn resolve_module_path(&mut self,
let
last_private
;
match
module_prefix_result
{
Failed
(
None
)
=>
{
let
mpath
=
self
.
names_to_string
(
module_path
);
let
mpath
=
names_to_string
(
module_path
);
let
mpath
=
&
mpath
[
..
];
match
mpath
.rfind
(
':'
)
{
Some
(
idx
)
=>
{
...
...
@@ -2184,7 +1193,7 @@ fn resolve_item_in_lexical_scope(&mut self,
namespace {:?} in `{}`"
,
token
::
get_name
(
name
),
namespace
,
self
.
module_to_string
(
&*
module_
));
module_to_string
(
&*
module_
));
// The current module node is handled specially. First, check for
// its immediate children.
...
...
@@ -2421,7 +1430,7 @@ fn resolve_module_prefix(&mut self,
break
}
debug!
(
"(resolving module prefix) resolving `super` at {}"
,
self
.
module_to_string
(
&*
containing_module
));
module_to_string
(
&*
containing_module
));
match
self
.get_nearest_normal_module_parent
(
containing_module
)
{
None
=>
return
Failed
(
None
),
Some
(
new_module
)
=>
{
...
...
@@ -2432,7 +1441,7 @@ fn resolve_module_prefix(&mut self,
}
debug!
(
"(resolving module prefix) finished resolving prefix at {}"
,
self
.
module_to_string
(
&*
containing_module
));
module_to_string
(
&*
containing_module
));
return
Success
(
PrefixFound
(
containing_module
,
i
));
}
...
...
@@ -2452,7 +1461,7 @@ fn resolve_name_in_module(&mut self,
->
ResolveResult
<
(
Target
,
bool
)
>
{
debug!
(
"(resolving name in module) resolving `{}` in `{}`"
,
&
token
::
get_name
(
name
),
self
.
module_to_string
(
&*
module_
));
module_to_string
(
&*
module_
));
// First, check the direct children of the module.
build_reduced_graph
::
populate_module_if_necessary
(
self
,
&
module_
);
...
...
@@ -2606,7 +1615,7 @@ fn with_scope<F>(&mut self, name: Option<Name>, f: F) where
None
=>
{
debug!
(
"!!! (with scope) didn't find `{}` in `{}`"
,
token
::
get_name
(
name
),
self
.
module_to_string
(
&*
orig_module
));
module_to_string
(
&*
orig_module
));
}
Some
(
name_bindings
)
=>
{
match
(
*
name_bindings
)
.get_module_if_available
()
{
...
...
@@ -2614,7 +1623,7 @@ fn with_scope<F>(&mut self, name: Option<Name>, f: F) where
debug!
(
"!!! (with scope) didn't find module
\
for `{}` in `{}`"
,
token
::
get_name
(
name
),
self
.
module_to_string
(
&*
orig_module
));
module_to_string
(
&*
orig_module
));
}
Some
(
module_
)
=>
{
self
.current_module
=
module_
;
...
...
@@ -2993,7 +2002,7 @@ fn resolve_trait_reference(&mut self,
}
else
{
self
.resolve_error
(
trait_path
.span
,
&
format!
(
"`{}` is not a trait"
,
self
.
path_names_to_string
(
trait_path
,
path_depth
)));
path_names_to_string
(
trait_path
,
path_depth
)));
// If it's a typedef, give a note
if
let
DefTy
(
..
)
=
path_res
.base_def
{
...
...
@@ -3004,7 +2013,7 @@ fn resolve_trait_reference(&mut self,
}
}
else
{
let
msg
=
format!
(
"use of undeclared trait name `{}`"
,
self
.
path_names_to_string
(
trait_path
,
path_depth
));
path_names_to_string
(
trait_path
,
path_depth
));
self
.resolve_error
(
trait_path
.span
,
&
msg
);
Err
(())
}
...
...
@@ -3120,7 +2129,7 @@ fn check_trait_item(&self, name: Name, span: Span) {
// If there is a TraitRef in scope for an impl, then the method must be in the trait.
if
let
Some
((
did
,
ref
trait_ref
))
=
self
.current_trait_ref
{
if
!
self
.trait_item_map
.contains_key
(
&
(
name
,
did
))
{
let
path_str
=
self
.
path_names_to_string
(
&
trait_ref
.path
,
0
);
let
path_str
=
path_names_to_string
(
&
trait_ref
.path
,
0
);
self
.resolve_error
(
span
,
&
format!
(
"method `{}` is not a member of trait `{}`"
,
token
::
get_name
(
name
),
...
...
@@ -3302,7 +2311,7 @@ fn resolve_type(&mut self, ty: &Ty) {
// Write the result into the def map.
debug!
(
"(resolving type) writing resolution for `{}`
\
(id {}) = {:?}"
,
self
.
path_names_to_string
(
path
,
0
),
path_names_to_string
(
path
,
0
),
ty
.id
,
def
);
self
.record_def
(
ty
.id
,
def
);
}
...
...
@@ -3317,7 +2326,7 @@ fn resolve_type(&mut self, ty: &Ty) {
};
let
msg
=
format!
(
"use of undeclared {} `{}`"
,
kind
,
self
.
path_names_to_string
(
path
,
0
));
path_names_to_string
(
path
,
0
));
self
.resolve_error
(
ty
.span
,
&
msg
[
..
]);
}
}
...
...
@@ -3488,7 +2497,7 @@ struct or enum variant",
debug!
(
"(resolving pattern) didn't find struct
\
def: {:?}"
,
result
);
let
msg
=
format!
(
"`{}` does not name a structure"
,
self
.
path_names_to_string
(
path
,
0
));
path_names_to_string
(
path
,
0
));
self
.resolve_error
(
path
.span
,
&
msg
[
..
]);
}
}
...
...
@@ -3741,7 +2750,7 @@ fn resolve_module_relative_path(&mut self,
Some
((
span
,
msg
))
=>
(
span
,
msg
),
None
=>
{
let
msg
=
format!
(
"Use of undeclared type or module `{}`"
,
self
.
names_to_string
(
&
module_path
));
names_to_string
(
&
module_path
));
(
span
,
msg
)
}
};
...
...
@@ -3801,7 +2810,7 @@ fn resolve_crate_relative_path(&mut self,
Some
((
span
,
msg
))
=>
(
span
,
msg
),
None
=>
{
let
msg
=
format!
(
"Use of undeclared module `::{}`"
,
self
.
names_to_string
(
&
module_path
[
..
]));
names_to_string
(
&
module_path
[
..
]));
(
span
,
msg
)
}
};
...
...
@@ -4021,7 +3030,7 @@ fn is_static_method(this: &Resolver, did: DefId) -> bool {
if
let
Some
(
binding
)
=
module
.children
.borrow
()
.get
(
&
name
)
{
if
let
Some
(
DefMethod
(
did
,
_
))
=
binding
.def_for_namespace
(
ValueNS
)
{
if
is_static_method
(
self
,
did
)
{
return
StaticMethod
(
self
.
path_names_to_string
(
&
path
,
0
))
return
StaticMethod
(
path_names_to_string
(
&
path
,
0
))
}
if
self
.current_trait_ref
.is_some
()
{
return
TraitItem
;
...
...
@@ -4036,7 +3045,7 @@ fn is_static_method(this: &Resolver, did: DefId) -> bool {
if
let
Some
((
trait_did
,
ref
trait_ref
))
=
self
.current_trait_ref
{
if
let
Some
(
&
did
)
=
self
.trait_item_map
.get
(
&
(
name
,
trait_did
))
{
if
is_static_method
(
self
,
did
)
{
return
TraitMethod
(
self
.
path_names_to_string
(
&
trait_ref
.path
,
0
));
return
TraitMethod
(
path_names_to_string
(
&
trait_ref
.path
,
0
));
}
else
{
return
TraitItem
;
}
...
...
@@ -4128,7 +3137,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
if
let
Some
(
path_res
)
=
resolution
{
// Check if struct variant
if
let
DefVariant
(
_
,
_
,
true
)
=
path_res
.base_def
{
let
path_name
=
self
.
path_names_to_string
(
path
,
0
);
let
path_name
=
path_names_to_string
(
path
,
0
);
self
.resolve_error
(
expr
.span
,
&
format!
(
"`{}` is a struct variant name, but
\
this expression
\
...
...
@@ -4146,7 +3155,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
}
else
{
// Write the result into the def map.
debug!
(
"(resolving expr) resolved `{}`"
,
self
.
path_names_to_string
(
path
,
0
));
path_names_to_string
(
path
,
0
));
// Partial resolutions will need the set of traits in scope,
// so they can be completed during typeck.
...
...
@@ -4163,7 +3172,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
// (The pattern matching def_tys where the id is in self.structs
// matches on regular structs while excluding tuple- and enum-like
// structs, which wouldn't result in this error.)
let
path_name
=
self
.
path_names_to_string
(
path
,
0
);
let
path_name
=
path_names_to_string
(
path
,
0
);
let
type_res
=
self
.with_no_errors
(|
this
|
{
this
.resolve_path
(
expr
.id
,
path
,
0
,
TypeNS
,
false
)
});
...
...
@@ -4250,7 +3259,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
None
=>
{
debug!
(
"(resolving expression) didn't find struct def"
,);
let
msg
=
format!
(
"`{}` does not name a structure"
,
self
.
path_names_to_string
(
path
,
0
));
path_names_to_string
(
path
,
0
));
self
.resolve_error
(
path
.span
,
&
msg
[
..
]);
}
}
...
...
@@ -4440,36 +3449,9 @@ fn enforce_default_binding_mode(&mut self,
// hit.
//
/// A somewhat inefficient routine to obtain the name of a module.
fn
module_to_string
(
&
self
,
module
:
&
Module
)
->
String
{
let
mut
names
=
Vec
::
new
();
fn
collect_mod
(
names
:
&
mut
Vec
<
ast
::
Name
>
,
module
:
&
Module
)
{
match
module
.parent_link
{
NoParentLink
=>
{}
ModuleParentLink
(
ref
module
,
name
)
=>
{
names
.push
(
name
);
collect_mod
(
names
,
&*
module
.upgrade
()
.unwrap
());
}
BlockParentLink
(
ref
module
,
_
)
=>
{
// danger, shouldn't be ident?
names
.push
(
special_idents
::
opaque
.name
);
collect_mod
(
names
,
&*
module
.upgrade
()
.unwrap
());
}
}
}
collect_mod
(
&
mut
names
,
module
);
if
names
.len
()
==
0
{
return
"???"
.to_string
();
}
self
.names_to_string
(
&
names
.into_iter
()
.rev
()
.collect
::
<
Vec
<
ast
::
Name
>>
())
}
#[allow(dead_code)]
// useful for debugging
fn
dump_module
(
&
mut
self
,
module_
:
Rc
<
Module
>
)
{
debug!
(
"Dump of module `{}`:"
,
self
.
module_to_string
(
&*
module_
));
debug!
(
"Dump of module `{}`:"
,
module_to_string
(
&*
module_
));
debug!
(
"Children:"
);
build_reduced_graph
::
populate_module_if_necessary
(
self
,
&
module_
);
...
...
@@ -4503,6 +3485,56 @@ fn dump_module(&mut self, module_: Rc<Module>) {
}
}
fn
names_to_string
(
names
:
&
[
Name
])
->
String
{
let
mut
first
=
true
;
let
mut
result
=
String
::
new
();
for
name
in
names
{
if
first
{
first
=
false
}
else
{
result
.push_str
(
"::"
)
}
result
.push_str
(
&
token
::
get_name
(
*
name
));
};
result
}
fn
path_names_to_string
(
path
:
&
Path
,
depth
:
usize
)
->
String
{
let
names
:
Vec
<
ast
::
Name
>
=
path
.segments
[
..
path
.segments
.len
()
-
depth
]
.iter
()
.map
(|
seg
|
seg
.identifier.name
)
.collect
();
names_to_string
(
&
names
[
..
])
}
/// A somewhat inefficient routine to obtain the name of a module.
fn
module_to_string
(
module
:
&
Module
)
->
String
{
let
mut
names
=
Vec
::
new
();
fn
collect_mod
(
names
:
&
mut
Vec
<
ast
::
Name
>
,
module
:
&
Module
)
{
match
module
.parent_link
{
NoParentLink
=>
{}
ModuleParentLink
(
ref
module
,
name
)
=>
{
names
.push
(
name
);
collect_mod
(
names
,
&*
module
.upgrade
()
.unwrap
());
}
BlockParentLink
(
ref
module
,
_
)
=>
{
// danger, shouldn't be ident?
names
.push
(
special_idents
::
opaque
.name
);
collect_mod
(
names
,
&*
module
.upgrade
()
.unwrap
());
}
}
}
collect_mod
(
&
mut
names
,
module
);
if
names
.len
()
==
0
{
return
"???"
.to_string
();
}
names_to_string
(
&
names
.into_iter
()
.rev
()
.collect
::
<
Vec
<
ast
::
Name
>>
())
}
pub
struct
CrateMap
{
pub
def_map
:
DefMap
,
pub
freevars
:
RefCell
<
FreevarMap
>
,
...
...
@@ -4530,7 +3562,7 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
build_reduced_graph
::
build_reduced_graph
(
&
mut
resolver
,
krate
);
session
.abort_if_errors
();
resolve
r
.resolve_imports
(
);
resolve
_imports
::
resolve_imports
(
&
mut
resolver
);
session
.abort_if_errors
();
record_exports
::
record
(
&
mut
resolver
);
...
...
src/librustc_resolve/record_exports.rs
浏览文件 @
2df1ceb0
...
...
@@ -22,6 +22,7 @@
use
Namespace
::{
self
,
TypeNS
,
ValueNS
};
use
build_reduced_graph
;
use
module_to_string
;
use
rustc
::
middle
::
def
::
Export
;
use
syntax
::
ast
;
...
...
@@ -60,19 +61,19 @@ fn record_exports_for_module_subtree(&mut self,
// OK. Continue.
debug!
(
"(recording exports for module subtree) recording
\
exports for local module `{}`"
,
self
.
module_to_string
(
&*
module_
));
module_to_string
(
&*
module_
));
}
None
=>
{
// Record exports for the root module.
debug!
(
"(recording exports for module subtree) recording
\
exports for root module `{}`"
,
self
.
module_to_string
(
&*
module_
));
module_to_string
(
&*
module_
));
}
Some
(
_
)
=>
{
// Bail out.
debug!
(
"(recording exports for module subtree) not recording
\
exports for `{}`"
,
self
.
module_to_string
(
&*
module_
));
module_to_string
(
&*
module_
));
return
;
}
}
...
...
src/librustc_resolve/resolve_imports.rs
0 → 100644
浏览文件 @
2df1ceb0
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use
self
::
ImportDirectiveSubclass
::
*
;
use
{
PUBLIC
,
IMPORTABLE
};
use
Module
;
use
Namespace
::{
self
,
TypeNS
,
ValueNS
};
use
NameBindings
;
use
NamespaceResult
::{
BoundResult
,
UnboundResult
,
UnknownResult
};
use
NamespaceResult
;
use
NameSearchType
;
use
ResolveResult
;
use
Resolver
;
use
UseLexicalScopeFlag
;
use
{
names_to_string
,
module_to_string
};
use
build_reduced_graph
;
use
rustc
::
middle
::
def
::
*
;
use
rustc
::
middle
::
privacy
::
*
;
use
syntax
::
ast
::{
DefId
,
NodeId
,
Name
};
use
syntax
::
attr
::
AttrMetaMethods
;
use
syntax
::
parse
::
token
;
use
syntax
::
codemap
::
Span
;
use
std
::
mem
::
replace
;
use
std
::
rc
::
Rc
;
/// Contains data for specific types of import directives.
#[derive(Copy,Debug)]
pub
enum
ImportDirectiveSubclass
{
SingleImport
(
Name
/* target */
,
Name
/* source */
),
GlobImport
}
/// Whether an import can be shadowed by another import.
#[derive(Debug,PartialEq,Clone,Copy)]
pub
enum
Shadowable
{
Always
,
Never
}
/// One import directive.
#[derive(Debug)]
pub
struct
ImportDirective
{
pub
module_path
:
Vec
<
Name
>
,
pub
subclass
:
ImportDirectiveSubclass
,
pub
span
:
Span
,
pub
id
:
NodeId
,
pub
is_public
:
bool
,
// see note in ImportResolution about how to use this
pub
shadowable
:
Shadowable
,
}
impl
ImportDirective
{
pub
fn
new
(
module_path
:
Vec
<
Name
>
,
subclass
:
ImportDirectiveSubclass
,
span
:
Span
,
id
:
NodeId
,
is_public
:
bool
,
shadowable
:
Shadowable
)
->
ImportDirective
{
ImportDirective
{
module_path
:
module_path
,
subclass
:
subclass
,
span
:
span
,
id
:
id
,
is_public
:
is_public
,
shadowable
:
shadowable
,
}
}
}
/// The item that an import resolves to.
#[derive(Clone,Debug)]
pub
struct
Target
{
pub
target_module
:
Rc
<
Module
>
,
pub
bindings
:
Rc
<
NameBindings
>
,
pub
shadowable
:
Shadowable
,
}
impl
Target
{
pub
fn
new
(
target_module
:
Rc
<
Module
>
,
bindings
:
Rc
<
NameBindings
>
,
shadowable
:
Shadowable
)
->
Target
{
Target
{
target_module
:
target_module
,
bindings
:
bindings
,
shadowable
:
shadowable
,
}
}
}
/// An ImportResolution represents a particular `use` directive.
#[derive(Debug)]
pub
struct
ImportResolution
{
/// Whether this resolution came from a `use` or a `pub use`. Note that this
/// should *not* be used whenever resolution is being performed. Privacy
/// testing occurs during a later phase of compilation.
pub
is_public
:
bool
,
// The number of outstanding references to this name. When this reaches
// zero, outside modules can count on the targets being correct. Before
// then, all bets are off; future imports could override this name.
// Note that this is usually either 0 or 1 - shadowing is forbidden the only
// way outstanding_references is > 1 in a legal program is if the name is
// used in both namespaces.
pub
outstanding_references
:
uint
,
/// The value that this `use` directive names, if there is one.
pub
value_target
:
Option
<
Target
>
,
/// The source node of the `use` directive leading to the value target
/// being non-none
pub
value_id
:
NodeId
,
/// The type that this `use` directive names, if there is one.
pub
type_target
:
Option
<
Target
>
,
/// The source node of the `use` directive leading to the type target
/// being non-none
pub
type_id
:
NodeId
,
}
impl
ImportResolution
{
pub
fn
new
(
id
:
NodeId
,
is_public
:
bool
)
->
ImportResolution
{
ImportResolution
{
type_id
:
id
,
value_id
:
id
,
outstanding_references
:
0
,
value_target
:
None
,
type_target
:
None
,
is_public
:
is_public
,
}
}
pub
fn
target_for_namespace
(
&
self
,
namespace
:
Namespace
)
->
Option
<
Target
>
{
match
namespace
{
TypeNS
=>
self
.type_target
.clone
(),
ValueNS
=>
self
.value_target
.clone
(),
}
}
pub
fn
id
(
&
self
,
namespace
:
Namespace
)
->
NodeId
{
match
namespace
{
TypeNS
=>
self
.type_id
,
ValueNS
=>
self
.value_id
,
}
}
pub
fn
shadowable
(
&
self
,
namespace
:
Namespace
)
->
Shadowable
{
let
target
=
self
.target_for_namespace
(
namespace
);
if
target
.is_none
()
{
return
Shadowable
::
Always
;
}
target
.unwrap
()
.shadowable
}
pub
fn
set_target_and_id
(
&
mut
self
,
namespace
:
Namespace
,
target
:
Option
<
Target
>
,
id
:
NodeId
)
{
match
namespace
{
TypeNS
=>
{
self
.type_target
=
target
;
self
.type_id
=
id
;
}
ValueNS
=>
{
self
.value_target
=
target
;
self
.value_id
=
id
;
}
}
}
}
struct
ImportResolver
<
'a
,
'b
:
'a
,
'tcx
:
'b
>
{
resolver
:
&
'a
mut
Resolver
<
'b
,
'tcx
>
}
impl
<
'a
,
'b
:
'a
,
'tcx
:
'b
>
ImportResolver
<
'a
,
'b
,
'tcx
>
{
// Import resolution
//
// This is a fixed-point algorithm. We resolve imports until our efforts
// are stymied by an unresolved import; then we bail out of the current
// module and continue. We terminate successfully once no more imports
// remain or unsuccessfully when no forward progress in resolving imports
// is made.
/// Resolves all imports for the crate. This method performs the fixed-
/// point iteration.
fn
resolve_imports
(
&
mut
self
)
{
let
mut
i
=
0
;
let
mut
prev_unresolved_imports
=
0
;
loop
{
debug!
(
"(resolving imports) iteration {}, {} imports left"
,
i
,
self
.resolver.unresolved_imports
);
let
module_root
=
self
.resolver.graph_root
.get_module
();
self
.resolve_imports_for_module_subtree
(
module_root
.clone
());
if
self
.resolver.unresolved_imports
==
0
{
debug!
(
"(resolving imports) success"
);
break
;
}
if
self
.resolver.unresolved_imports
==
prev_unresolved_imports
{
self
.resolver
.report_unresolved_imports
(
module_root
);
break
;
}
i
+=
1
;
prev_unresolved_imports
=
self
.resolver.unresolved_imports
;
}
}
/// Attempts to resolve imports for the given module and all of its
/// submodules.
fn
resolve_imports_for_module_subtree
(
&
mut
self
,
module_
:
Rc
<
Module
>
)
{
debug!
(
"(resolving imports for module subtree) resolving {}"
,
module_to_string
(
&*
module_
));
let
orig_module
=
replace
(
&
mut
self
.resolver.current_module
,
module_
.clone
());
self
.resolve_imports_for_module
(
module_
.clone
());
self
.resolver.current_module
=
orig_module
;
build_reduced_graph
::
populate_module_if_necessary
(
self
.resolver
,
&
module_
);
for
(
_
,
child_node
)
in
&*
module_
.children
.borrow
()
{
match
child_node
.get_module_if_available
()
{
None
=>
{
// Nothing to do.
}
Some
(
child_module
)
=>
{
self
.resolve_imports_for_module_subtree
(
child_module
);
}
}
}
for
(
_
,
child_module
)
in
&*
module_
.anonymous_children
.borrow
()
{
self
.resolve_imports_for_module_subtree
(
child_module
.clone
());
}
}
/// Attempts to resolve imports for the given module only.
fn
resolve_imports_for_module
(
&
mut
self
,
module
:
Rc
<
Module
>
)
{
if
module
.all_imports_resolved
()
{
debug!
(
"(resolving imports for module) all imports resolved for
\
{}"
,
module_to_string
(
&*
module
));
return
;
}
let
imports
=
module
.imports
.borrow
();
let
import_count
=
imports
.len
();
while
module
.resolved_import_count
.get
()
<
import_count
{
let
import_index
=
module
.resolved_import_count
.get
();
let
import_directive
=
&
(
*
imports
)[
import_index
];
match
self
.resolve_import_for_module
(
module
.clone
(),
import_directive
)
{
ResolveResult
::
Failed
(
err
)
=>
{
let
(
span
,
help
)
=
match
err
{
Some
((
span
,
msg
))
=>
(
span
,
format!
(
". {}"
,
msg
)),
None
=>
(
import_directive
.span
,
String
::
new
())
};
let
msg
=
format!
(
"unresolved import `{}`{}"
,
import_path_to_string
(
&
import_directive
.module_path
,
import_directive
.subclass
),
help
);
self
.resolver
.resolve_error
(
span
,
&
msg
[
..
]);
}
ResolveResult
::
Indeterminate
=>
break
,
// Bail out. We'll come around next time.
ResolveResult
::
Success
(())
=>
()
// Good. Continue.
}
module
.resolved_import_count
.set
(
module
.resolved_import_count
.get
()
+
1
);
}
}
/// Attempts to resolve the given import. The return value indicates
/// failure if we're certain the name does not exist, indeterminate if we
/// don't know whether the name exists at the moment due to other
/// currently-unresolved imports, or success if we know the name exists.
/// If successful, the resolved bindings are written into the module.
fn
resolve_import_for_module
(
&
mut
self
,
module_
:
Rc
<
Module
>
,
import_directive
:
&
ImportDirective
)
->
ResolveResult
<
()
>
{
let
mut
resolution_result
=
ResolveResult
::
Failed
(
None
);
let
module_path
=
&
import_directive
.module_path
;
debug!
(
"(resolving import for module) resolving import `{}::...` in `{}`"
,
names_to_string
(
&
module_path
[
..
]),
module_to_string
(
&*
module_
));
// First, resolve the module path for the directive, if necessary.
let
container
=
if
module_path
.len
()
==
0
{
// Use the crate root.
Some
((
self
.resolver.graph_root
.get_module
(),
LastMod
(
AllPublic
)))
}
else
{
match
self
.resolver
.resolve_module_path
(
module_
.clone
(),
&
module_path
[
..
],
UseLexicalScopeFlag
::
DontUseLexicalScope
,
import_directive
.span
,
NameSearchType
::
ImportSearch
)
{
ResolveResult
::
Failed
(
err
)
=>
{
resolution_result
=
ResolveResult
::
Failed
(
err
);
None
},
ResolveResult
::
Indeterminate
=>
{
resolution_result
=
ResolveResult
::
Indeterminate
;
None
}
ResolveResult
::
Success
(
container
)
=>
Some
(
container
),
}
};
match
container
{
None
=>
{}
Some
((
containing_module
,
lp
))
=>
{
// We found the module that the target is contained
// within. Attempt to resolve the import within it.
match
import_directive
.subclass
{
SingleImport
(
target
,
source
)
=>
{
resolution_result
=
self
.resolve_single_import
(
&
module_
,
containing_module
,
target
,
source
,
import_directive
,
lp
);
}
GlobImport
=>
{
resolution_result
=
self
.resolve_glob_import
(
&
module_
,
containing_module
,
import_directive
,
lp
);
}
}
}
}
// Decrement the count of unresolved imports.
match
resolution_result
{
ResolveResult
::
Success
(())
=>
{
assert
!
(
self
.resolver.unresolved_imports
>=
1
);
self
.resolver.unresolved_imports
-=
1
;
}
_
=>
{
// Nothing to do here; just return the error.
}
}
// Decrement the count of unresolved globs if necessary. But only if
// the resolution result is indeterminate -- otherwise we'll stop
// processing imports here. (See the loop in
// resolve_imports_for_module).
if
!
resolution_result
.indeterminate
()
{
match
import_directive
.subclass
{
GlobImport
=>
{
assert
!
(
module_
.glob_count
.get
()
>=
1
);
module_
.glob_count
.set
(
module_
.glob_count
.get
()
-
1
);
}
SingleImport
(
..
)
=>
{
// Ignore.
}
}
}
return
resolution_result
;
}
fn
resolve_single_import
(
&
mut
self
,
module_
:
&
Module
,
target_module
:
Rc
<
Module
>
,
target
:
Name
,
source
:
Name
,
directive
:
&
ImportDirective
,
lp
:
LastPrivate
)
->
ResolveResult
<
()
>
{
debug!
(
"(resolving single import) resolving `{}` = `{}::{}` from
\
`{}` id {}, last private {:?}"
,
token
::
get_name
(
target
),
module_to_string
(
&*
target_module
),
token
::
get_name
(
source
),
module_to_string
(
module_
),
directive
.id
,
lp
);
let
lp
=
match
lp
{
LastMod
(
lp
)
=>
lp
,
LastImport
{
..
}
=>
{
self
.resolver.session
.span_bug
(
directive
.span
,
"not expecting Import here, must be LastMod"
)
}
};
// We need to resolve both namespaces for this to succeed.
//
let
mut
value_result
=
UnknownResult
;
let
mut
type_result
=
UnknownResult
;
// Search for direct children of the containing module.
build_reduced_graph
::
populate_module_if_necessary
(
self
.resolver
,
&
target_module
);
match
target_module
.children
.borrow
()
.get
(
&
source
)
{
None
=>
{
// Continue.
}
Some
(
ref
child_name_bindings
)
=>
{
// pub_err makes sure we don't give the same error twice.
let
mut
pub_err
=
false
;
if
child_name_bindings
.defined_in_namespace
(
ValueNS
)
{
debug!
(
"(resolving single import) found value binding"
);
value_result
=
BoundResult
(
target_module
.clone
(),
(
*
child_name_bindings
)
.clone
());
if
directive
.is_public
&&
!
child_name_bindings
.is_public
(
ValueNS
)
{
let
msg
=
format!
(
"`{}` is private"
,
token
::
get_name
(
source
));
span_err!
(
self
.resolver.session
,
directive
.span
,
E0364
,
"{}"
,
&
msg
);
pub_err
=
true
;
}
}
if
child_name_bindings
.defined_in_namespace
(
TypeNS
)
{
debug!
(
"(resolving single import) found type binding"
);
type_result
=
BoundResult
(
target_module
.clone
(),
(
*
child_name_bindings
)
.clone
());
if
!
pub_err
&&
directive
.is_public
&&
!
child_name_bindings
.is_public
(
TypeNS
)
{
let
msg
=
format!
(
"`{}` is private"
,
token
::
get_name
(
source
));
span_err!
(
self
.resolver.session
,
directive
.span
,
E0365
,
"{}"
,
&
msg
);
}
}
}
}
// Unless we managed to find a result in both namespaces (unlikely),
// search imports as well.
let
mut
value_used_reexport
=
false
;
let
mut
type_used_reexport
=
false
;
match
(
value_result
.clone
(),
type_result
.clone
())
{
(
BoundResult
(
..
),
BoundResult
(
..
))
=>
{}
// Continue.
_
=>
{
// If there is an unresolved glob at this point in the
// containing module, bail out. We don't know enough to be
// able to resolve this import.
if
target_module
.glob_count
.get
()
>
0
{
debug!
(
"(resolving single import) unresolved glob;
\
bailing out"
);
return
ResolveResult
::
Indeterminate
;
}
// Now search the exported imports within the containing module.
match
target_module
.import_resolutions
.borrow
()
.get
(
&
source
)
{
None
=>
{
debug!
(
"(resolving single import) no import"
);
// The containing module definitely doesn't have an
// exported import with the name in question. We can
// therefore accurately report that the names are
// unbound.
if
value_result
.is_unknown
()
{
value_result
=
UnboundResult
;
}
if
type_result
.is_unknown
()
{
type_result
=
UnboundResult
;
}
}
Some
(
import_resolution
)
if
import_resolution
.outstanding_references
==
0
=>
{
fn
get_binding
(
this
:
&
mut
Resolver
,
import_resolution
:
&
ImportResolution
,
namespace
:
Namespace
,
source
:
&
Name
)
->
NamespaceResult
{
// Import resolutions must be declared with "pub"
// in order to be exported.
if
!
import_resolution
.is_public
{
return
UnboundResult
;
}
match
import_resolution
.target_for_namespace
(
namespace
)
{
None
=>
{
return
UnboundResult
;
}
Some
(
Target
{
target_module
,
bindings
,
shadowable
:
_
})
=>
{
debug!
(
"(resolving single import) found
\
import in ns {:?}"
,
namespace
);
let
id
=
import_resolution
.id
(
namespace
);
// track used imports and extern crates as well
this
.used_imports
.insert
((
id
,
namespace
));
this
.record_import_use
(
id
,
*
source
);
match
target_module
.def_id
.get
()
{
Some
(
DefId
{
krate
:
kid
,
..
})
=>
{
this
.used_crates
.insert
(
kid
);
},
_
=>
{}
}
return
BoundResult
(
target_module
,
bindings
);
}
}
}
// The name is an import which has been fully
// resolved. We can, therefore, just follow it.
if
value_result
.is_unknown
()
{
value_result
=
get_binding
(
self
.resolver
,
import_resolution
,
ValueNS
,
&
source
);
value_used_reexport
=
import_resolution
.is_public
;
}
if
type_result
.is_unknown
()
{
type_result
=
get_binding
(
self
.resolver
,
import_resolution
,
TypeNS
,
&
source
);
type_used_reexport
=
import_resolution
.is_public
;
}
}
Some
(
_
)
=>
{
// If target_module is the same module whose import we are resolving
// and there it has an unresolved import with the same name as `source`,
// then the user is actually trying to import an item that is declared
// in the same scope
//
// e.g
// use self::submodule;
// pub mod submodule;
//
// In this case we continue as if we resolved the import and let the
// check_for_conflicts_between_imports_and_items call below handle
// the conflict
match
(
module_
.def_id
.get
(),
target_module
.def_id
.get
())
{
(
Some
(
id1
),
Some
(
id2
))
if
id1
==
id2
=>
{
if
value_result
.is_unknown
()
{
value_result
=
UnboundResult
;
}
if
type_result
.is_unknown
()
{
type_result
=
UnboundResult
;
}
}
_
=>
{
// The import is unresolved. Bail out.
debug!
(
"(resolving single import) unresolved import;
\
bailing out"
);
return
ResolveResult
::
Indeterminate
;
}
}
}
}
}
}
let
mut
value_used_public
=
false
;
let
mut
type_used_public
=
false
;
// If we didn't find a result in the type namespace, search the
// external modules.
match
type_result
{
BoundResult
(
..
)
=>
{}
_
=>
{
match
target_module
.external_module_children
.borrow_mut
()
.get
(
&
source
)
.cloned
()
{
None
=>
{}
// Continue.
Some
(
module
)
=>
{
debug!
(
"(resolving single import) found external module"
);
// track the module as used.
match
module
.def_id
.get
()
{
Some
(
DefId
{
krate
:
kid
,
..
})
=>
{
self
.resolver.used_crates
.insert
(
kid
);
}
_
=>
{}
}
let
name_bindings
=
Rc
::
new
(
Resolver
::
create_name_bindings_from_module
(
module
));
type_result
=
BoundResult
(
target_module
.clone
(),
name_bindings
);
type_used_public
=
true
;
}
}
}
}
// We've successfully resolved the import. Write the results in.
let
mut
import_resolutions
=
module_
.import_resolutions
.borrow_mut
();
let
import_resolution
=
&
mut
(
*
import_resolutions
)[
target
];
{
let
mut
check_and_write_import
=
|
namespace
,
result
:
&
_
,
used_public
:
&
mut
bool
|
{
let
namespace_name
=
match
namespace
{
TypeNS
=>
"type"
,
ValueNS
=>
"value"
,
};
match
*
result
{
BoundResult
(
ref
target_module
,
ref
name_bindings
)
=>
{
debug!
(
"(resolving single import) found {:?} target: {:?}"
,
namespace_name
,
name_bindings
.def_for_namespace
(
namespace
));
self
.check_for_conflicting_import
(
&
import_resolution
.target_for_namespace
(
namespace
),
directive
.span
,
target
,
namespace
);
self
.check_that_import_is_importable
(
&**
name_bindings
,
directive
.span
,
target
,
namespace
);
let
target
=
Some
(
Target
::
new
(
target_module
.clone
(),
name_bindings
.clone
(),
directive
.shadowable
));
import_resolution
.set_target_and_id
(
namespace
,
target
,
directive
.id
);
import_resolution
.is_public
=
directive
.is_public
;
*
used_public
=
name_bindings
.defined_in_public_namespace
(
namespace
);
}
UnboundResult
=>
{
/* Continue. */
}
UnknownResult
=>
{
panic!
(
"{:?} result should be known at this point"
,
namespace_name
);
}
}
};
check_and_write_import
(
ValueNS
,
&
value_result
,
&
mut
value_used_public
);
check_and_write_import
(
TypeNS
,
&
type_result
,
&
mut
type_used_public
);
}
self
.check_for_conflicts_between_imports_and_items
(
module_
,
import_resolution
,
directive
.span
,
target
);
if
value_result
.is_unbound
()
&&
type_result
.is_unbound
()
{
let
msg
=
format!
(
"There is no `{}` in `{}`"
,
token
::
get_name
(
source
),
module_to_string
(
&
target_module
));
return
ResolveResult
::
Failed
(
Some
((
directive
.span
,
msg
)));
}
let
value_used_public
=
value_used_reexport
||
value_used_public
;
let
type_used_public
=
type_used_reexport
||
type_used_public
;
assert
!
(
import_resolution
.outstanding_references
>=
1
);
import_resolution
.outstanding_references
-=
1
;
// Record what this import resolves to for later uses in documentation,
// this may resolve to either a value or a type, but for documentation
// purposes it's good enough to just favor one over the other.
let
value_def_and_priv
=
import_resolution
.value_target
.as_ref
()
.map
(|
target
|
{
let
def
=
target
.bindings
.def_for_namespace
(
ValueNS
)
.unwrap
();
(
def
,
if
value_used_public
{
lp
}
else
{
DependsOn
(
def
.def_id
())
})
});
let
type_def_and_priv
=
import_resolution
.type_target
.as_ref
()
.map
(|
target
|
{
let
def
=
target
.bindings
.def_for_namespace
(
TypeNS
)
.unwrap
();
(
def
,
if
type_used_public
{
lp
}
else
{
DependsOn
(
def
.def_id
())
})
});
let
import_lp
=
LastImport
{
value_priv
:
value_def_and_priv
.map
(|(
_
,
p
)|
p
),
value_used
:
Used
,
type_priv
:
type_def_and_priv
.map
(|(
_
,
p
)|
p
),
type_used
:
Used
};
if
let
Some
((
def
,
_
))
=
value_def_and_priv
{
self
.resolver.def_map
.borrow_mut
()
.insert
(
directive
.id
,
PathResolution
{
base_def
:
def
,
last_private
:
import_lp
,
depth
:
0
});
}
if
let
Some
((
def
,
_
))
=
type_def_and_priv
{
self
.resolver.def_map
.borrow_mut
()
.insert
(
directive
.id
,
PathResolution
{
base_def
:
def
,
last_private
:
import_lp
,
depth
:
0
});
}
debug!
(
"(resolving single import) successfully resolved import"
);
return
ResolveResult
::
Success
(());
}
// Resolves a glob import. Note that this function cannot fail; it either
// succeeds or bails out (as importing * from an empty module or a module
// that exports nothing is valid). target_module is the module we are
// actually importing, i.e., `foo` in `use foo::*`.
fn
resolve_glob_import
(
&
mut
self
,
module_
:
&
Module
,
target_module
:
Rc
<
Module
>
,
import_directive
:
&
ImportDirective
,
lp
:
LastPrivate
)
->
ResolveResult
<
()
>
{
let
id
=
import_directive
.id
;
let
is_public
=
import_directive
.is_public
;
// This function works in a highly imperative manner; it eagerly adds
// everything it can to the list of import resolutions of the module
// node.
debug!
(
"(resolving glob import) resolving glob import {}"
,
id
);
// We must bail out if the node has unresolved imports of any kind
// (including globs).
if
!
(
*
target_module
)
.all_imports_resolved
()
{
debug!
(
"(resolving glob import) target module has unresolved
\
imports; bailing out"
);
return
ResolveResult
::
Indeterminate
;
}
assert_eq!
(
target_module
.glob_count
.get
(),
0
);
// Add all resolved imports from the containing module.
let
import_resolutions
=
target_module
.import_resolutions
.borrow
();
for
(
ident
,
target_import_resolution
)
in
&*
import_resolutions
{
debug!
(
"(resolving glob import) writing module resolution
\
{} into `{}`"
,
token
::
get_name
(
*
ident
),
module_to_string
(
module_
));
if
!
target_import_resolution
.is_public
{
debug!
(
"(resolving glob import) nevermind, just kidding"
);
continue
}
// Here we merge two import resolutions.
let
mut
import_resolutions
=
module_
.import_resolutions
.borrow_mut
();
match
import_resolutions
.get_mut
(
ident
)
{
Some
(
dest_import_resolution
)
=>
{
// Merge the two import resolutions at a finer-grained
// level.
match
target_import_resolution
.value_target
{
None
=>
{
// Continue.
}
Some
(
ref
value_target
)
=>
{
self
.check_for_conflicting_import
(
&
dest_import_resolution
.value_target
,
import_directive
.span
,
*
ident
,
ValueNS
);
dest_import_resolution
.value_target
=
Some
(
value_target
.clone
());
}
}
match
target_import_resolution
.type_target
{
None
=>
{
// Continue.
}
Some
(
ref
type_target
)
=>
{
self
.check_for_conflicting_import
(
&
dest_import_resolution
.type_target
,
import_directive
.span
,
*
ident
,
TypeNS
);
dest_import_resolution
.type_target
=
Some
(
type_target
.clone
());
}
}
dest_import_resolution
.is_public
=
is_public
;
continue
;
}
None
=>
{}
}
// Simple: just copy the old import resolution.
let
mut
new_import_resolution
=
ImportResolution
::
new
(
id
,
is_public
);
new_import_resolution
.value_target
=
target_import_resolution
.value_target
.clone
();
new_import_resolution
.type_target
=
target_import_resolution
.type_target
.clone
();
import_resolutions
.insert
(
*
ident
,
new_import_resolution
);
}
// Add all children from the containing module.
build_reduced_graph
::
populate_module_if_necessary
(
self
.resolver
,
&
target_module
);
for
(
&
name
,
name_bindings
)
in
&*
target_module
.children
.borrow
()
{
self
.merge_import_resolution
(
module_
,
target_module
.clone
(),
import_directive
,
name
,
name_bindings
.clone
());
}
// Add external module children from the containing module.
for
(
&
name
,
module
)
in
&*
target_module
.external_module_children
.borrow
()
{
let
name_bindings
=
Rc
::
new
(
Resolver
::
create_name_bindings_from_module
(
module
.clone
()));
self
.merge_import_resolution
(
module_
,
target_module
.clone
(),
import_directive
,
name
,
name_bindings
);
}
// Record the destination of this import
if
let
Some
(
did
)
=
target_module
.def_id
.get
()
{
self
.resolver.def_map
.borrow_mut
()
.insert
(
id
,
PathResolution
{
base_def
:
DefMod
(
did
),
last_private
:
lp
,
depth
:
0
});
}
debug!
(
"(resolving glob import) successfully resolved import"
);
return
ResolveResult
::
Success
(());
}
fn
merge_import_resolution
(
&
mut
self
,
module_
:
&
Module
,
containing_module
:
Rc
<
Module
>
,
import_directive
:
&
ImportDirective
,
name
:
Name
,
name_bindings
:
Rc
<
NameBindings
>
)
{
let
id
=
import_directive
.id
;
let
is_public
=
import_directive
.is_public
;
let
mut
import_resolutions
=
module_
.import_resolutions
.borrow_mut
();
let
dest_import_resolution
=
import_resolutions
.entry
(
name
)
.get
()
.unwrap_or_else
(
|
vacant_entry
|
{
// Create a new import resolution from this child.
vacant_entry
.insert
(
ImportResolution
::
new
(
id
,
is_public
))
});
debug!
(
"(resolving glob import) writing resolution `{}` in `{}`
\
to `{}`"
,
&
token
::
get_name
(
name
),
module_to_string
(
&*
containing_module
),
module_to_string
(
module_
));
// Merge the child item into the import resolution.
{
let
mut
merge_child_item
=
|
namespace
|
{
if
name_bindings
.defined_in_namespace_with
(
namespace
,
IMPORTABLE
|
PUBLIC
)
{
let
namespace_name
=
match
namespace
{
TypeNS
=>
"type"
,
ValueNS
=>
"value"
,
};
debug!
(
"(resolving glob import) ... for {} target"
,
namespace_name
);
if
dest_import_resolution
.shadowable
(
namespace
)
==
Shadowable
::
Never
{
let
msg
=
format!
(
"a {} named `{}` has already been imported
\
in this module"
,
namespace_name
,
&
token
::
get_name
(
name
));
span_err!
(
self
.resolver.session
,
import_directive
.span
,
E0251
,
"{}"
,
msg
);
}
else
{
let
target
=
Target
::
new
(
containing_module
.clone
(),
name_bindings
.clone
(),
import_directive
.shadowable
);
dest_import_resolution
.set_target_and_id
(
namespace
,
Some
(
target
),
id
);
}
}
};
merge_child_item
(
ValueNS
);
merge_child_item
(
TypeNS
);
}
dest_import_resolution
.is_public
=
is_public
;
self
.check_for_conflicts_between_imports_and_items
(
module_
,
dest_import_resolution
,
import_directive
.span
,
name
);
}
/// Checks that imported names and items don't have the same name.
fn
check_for_conflicting_import
(
&
mut
self
,
target
:
&
Option
<
Target
>
,
import_span
:
Span
,
name
:
Name
,
namespace
:
Namespace
)
{
debug!
(
"check_for_conflicting_import: {}; target exists: {}"
,
&
token
::
get_name
(
name
),
target
.is_some
());
match
*
target
{
Some
(
ref
target
)
if
target
.shadowable
!=
Shadowable
::
Always
=>
{
let
msg
=
format!
(
"a {} named `{}` has already been imported
\
in this module"
,
match
namespace
{
TypeNS
=>
"type"
,
ValueNS
=>
"value"
,
},
&
token
::
get_name
(
name
));
span_err!
(
self
.resolver.session
,
import_span
,
E0252
,
"{}"
,
&
msg
[
..
]);
}
Some
(
_
)
|
None
=>
{}
}
}
/// Checks that an import is actually importable
fn
check_that_import_is_importable
(
&
mut
self
,
name_bindings
:
&
NameBindings
,
import_span
:
Span
,
name
:
Name
,
namespace
:
Namespace
)
{
if
!
name_bindings
.defined_in_namespace_with
(
namespace
,
IMPORTABLE
)
{
let
msg
=
format!
(
"`{}` is not directly importable"
,
token
::
get_name
(
name
));
span_err!
(
self
.resolver.session
,
import_span
,
E0253
,
"{}"
,
&
msg
[
..
]);
}
}
/// Checks that imported names and items don't have the same name.
fn
check_for_conflicts_between_imports_and_items
(
&
mut
self
,
module
:
&
Module
,
import_resolution
:
&
ImportResolution
,
import_span
:
Span
,
name
:
Name
)
{
// First, check for conflicts between imports and `extern crate`s.
if
module
.external_module_children
.borrow
()
.contains_key
(
&
name
)
{
match
import_resolution
.type_target
{
Some
(
ref
target
)
if
target
.shadowable
!=
Shadowable
::
Always
=>
{
let
msg
=
format!
(
"import `{0}` conflicts with imported
\
crate in this module
\
(maybe you meant `use {0}::*`?)"
,
&
token
::
get_name
(
name
));
span_err!
(
self
.resolver.session
,
import_span
,
E0254
,
"{}"
,
&
msg
[
..
]);
}
Some
(
_
)
|
None
=>
{}
}
}
// Check for item conflicts.
let
children
=
module
.children
.borrow
();
let
name_bindings
=
match
children
.get
(
&
name
)
{
None
=>
{
// There can't be any conflicts.
return
}
Some
(
ref
name_bindings
)
=>
(
*
name_bindings
)
.clone
(),
};
match
import_resolution
.value_target
{
Some
(
ref
target
)
if
target
.shadowable
!=
Shadowable
::
Always
=>
{
if
let
Some
(
ref
value
)
=
*
name_bindings
.value_def
.borrow
()
{
span_err!
(
self
.resolver.session
,
import_span
,
E0255
,
"import `{}` conflicts with value in this module"
,
&
token
::
get_name
(
name
));
if
let
Some
(
span
)
=
value
.value_span
{
self
.resolver.session
.span_note
(
span
,
"conflicting value here"
);
}
}
}
Some
(
_
)
|
None
=>
{}
}
match
import_resolution
.type_target
{
Some
(
ref
target
)
if
target
.shadowable
!=
Shadowable
::
Always
=>
{
if
let
Some
(
ref
ty
)
=
*
name_bindings
.type_def
.borrow
()
{
let
(
what
,
note
)
=
if
ty
.module_def
.is_some
()
{
(
"existing submodule"
,
"note conflicting module here"
)
}
else
{
(
"type in this module"
,
"note conflicting type here"
)
};
span_err!
(
self
.resolver.session
,
import_span
,
E0256
,
"import `{}` conflicts with {}"
,
&
token
::
get_name
(
name
),
what
);
if
let
Some
(
span
)
=
ty
.type_span
{
self
.resolver.session
.span_note
(
span
,
note
);
}
}
}
Some
(
_
)
|
None
=>
{}
}
}
}
fn
import_path_to_string
(
names
:
&
[
Name
],
subclass
:
ImportDirectiveSubclass
)
->
String
{
if
names
.is_empty
()
{
import_directive_subclass_to_string
(
subclass
)
}
else
{
(
format!
(
"{}::{}"
,
names_to_string
(
names
),
import_directive_subclass_to_string
(
subclass
)))
.to_string
()
}
}
fn
import_directive_subclass_to_string
(
subclass
:
ImportDirectiveSubclass
)
->
String
{
match
subclass
{
SingleImport
(
_
,
source
)
=>
{
token
::
get_name
(
source
)
.to_string
()
}
GlobImport
=>
"*"
.to_string
()
}
}
pub
fn
resolve_imports
(
resolver
:
&
mut
Resolver
)
{
let
mut
import_resolver
=
ImportResolver
{
resolver
:
resolver
,
};
import_resolver
.resolve_imports
();
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录