Auto merge of #38499 - alexcrichton:rollup, r=alexcrichton
Rollup of 29 pull requests - Successful merges: #37761, #38006, #38131, #38150, #38158, #38171, #38208, #38215, #38236, #38245, #38289, #38302, #38315, #38346, #38388, #38395, #38398, #38418, #38432, #38451, #38463, #38468, #38470, #38471, #38472, #38478, #38486, #38493, #38498 - Failed merges: #38271, #38483
This commit is contained in:
commit
164619a8cf
@ -13,7 +13,7 @@
|
||||
######################################################################
|
||||
|
||||
# The version number
|
||||
CFG_RELEASE_NUM=1.15.0
|
||||
CFG_RELEASE_NUM=1.16.0
|
||||
|
||||
# An optional number to put after the label, e.g. '.2' -> '-beta.2'
|
||||
# NB Make sure it starts with a dot to conform to semver pre-release
|
||||
|
1
src/Cargo.lock
generated
1
src/Cargo.lock
generated
@ -87,6 +87,7 @@ dependencies = [
|
||||
name = "compiletest"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"build_helper 0.1.0",
|
||||
"env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serialize 0.0.0",
|
||||
|
@ -25,6 +25,8 @@
|
||||
//! switching compilers for the bootstrap and for build scripts will probably
|
||||
//! never get replaced.
|
||||
|
||||
#![deny(warnings)]
|
||||
|
||||
extern crate bootstrap;
|
||||
|
||||
use std::env;
|
||||
|
@ -12,6 +12,8 @@
|
||||
//!
|
||||
//! See comments in `src/bootstrap/rustc.rs` for more information.
|
||||
|
||||
#![deny(warnings)]
|
||||
|
||||
extern crate bootstrap;
|
||||
|
||||
use std::env;
|
||||
|
@ -81,7 +81,7 @@ def verify(path, sha_path, verbose):
|
||||
with open(path, "rb") as f:
|
||||
found = hashlib.sha256(f.read()).hexdigest()
|
||||
with open(sha_path, "r") as f:
|
||||
expected, _ = f.readline().split()
|
||||
expected = f.readline().split()[0]
|
||||
verified = found == expected
|
||||
if not verified:
|
||||
print("invalid checksum:\n"
|
||||
@ -146,7 +146,7 @@ class RustBuild(object):
|
||||
def download_stage0(self):
|
||||
cache_dst = os.path.join(self.build_dir, "cache")
|
||||
rustc_cache = os.path.join(cache_dst, self.stage0_rustc_date())
|
||||
cargo_cache = os.path.join(cache_dst, self.stage0_cargo_date())
|
||||
cargo_cache = os.path.join(cache_dst, self.stage0_cargo_rev())
|
||||
if not os.path.exists(rustc_cache):
|
||||
os.makedirs(rustc_cache)
|
||||
if not os.path.exists(cargo_cache):
|
||||
@ -179,21 +179,17 @@ class RustBuild(object):
|
||||
if self.cargo().startswith(self.bin_root()) and \
|
||||
(not os.path.exists(self.cargo()) or self.cargo_out_of_date()):
|
||||
self.print_what_it_means_to_bootstrap()
|
||||
channel = self.stage0_cargo_channel()
|
||||
filename = "cargo-{}-{}.tar.gz".format(channel, self.build)
|
||||
url = "https://static.rust-lang.org/cargo-dist/" + self.stage0_cargo_date()
|
||||
filename = "cargo-nightly-{}.tar.gz".format(self.build)
|
||||
url = "https://s3.amazonaws.com/rust-lang-ci/cargo-builds/" + self.stage0_cargo_rev()
|
||||
tarball = os.path.join(cargo_cache, filename)
|
||||
if not os.path.exists(tarball):
|
||||
get("{}/{}".format(url, filename), tarball, verbose=self.verbose)
|
||||
unpack(tarball, self.bin_root(), match="cargo", verbose=self.verbose)
|
||||
with open(self.cargo_stamp(), 'w') as f:
|
||||
f.write(self.stage0_cargo_date())
|
||||
f.write(self.stage0_cargo_rev())
|
||||
|
||||
def stage0_cargo_date(self):
|
||||
return self._cargo_date
|
||||
|
||||
def stage0_cargo_channel(self):
|
||||
return self._cargo_channel
|
||||
def stage0_cargo_rev(self):
|
||||
return self._cargo_rev
|
||||
|
||||
def stage0_rustc_date(self):
|
||||
return self._rustc_date
|
||||
@ -217,7 +213,7 @@ class RustBuild(object):
|
||||
if not os.path.exists(self.cargo_stamp()) or self.clean:
|
||||
return True
|
||||
with open(self.cargo_stamp(), 'r') as f:
|
||||
return self.stage0_cargo_date() != f.read()
|
||||
return self.stage0_cargo_rev() != f.read()
|
||||
|
||||
def bin_root(self):
|
||||
return os.path.join(self.build_dir, self.build, "stage0")
|
||||
@ -469,7 +465,7 @@ def main():
|
||||
|
||||
data = stage0_data(rb.rust_root)
|
||||
rb._rustc_channel, rb._rustc_date = data['rustc'].split('-', 1)
|
||||
rb._cargo_channel, rb._cargo_date = data['cargo'].split('-', 1)
|
||||
rb._cargo_rev = data['cargo']
|
||||
|
||||
start_time = time()
|
||||
|
||||
|
@ -13,6 +13,8 @@
|
||||
//! This file implements the various regression test suites that we execute on
|
||||
//! our CI.
|
||||
|
||||
extern crate build_helper;
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::fmt;
|
||||
@ -543,7 +545,7 @@ pub fn distcheck(build: &Build) {
|
||||
build.run(&mut cmd);
|
||||
build.run(Command::new("./configure")
|
||||
.current_dir(&dir));
|
||||
build.run(Command::new("make")
|
||||
build.run(Command::new(build_helper::make(&build.config.build))
|
||||
.arg("check")
|
||||
.current_dir(&dir));
|
||||
}
|
||||
|
@ -113,6 +113,7 @@ pub struct Target {
|
||||
#[derive(RustcDecodable, Default)]
|
||||
struct TomlConfig {
|
||||
build: Option<Build>,
|
||||
install: Option<Install>,
|
||||
llvm: Option<Llvm>,
|
||||
rust: Option<Rust>,
|
||||
target: Option<HashMap<String, TomlTarget>>,
|
||||
@ -135,6 +136,12 @@ struct Build {
|
||||
python: Option<String>,
|
||||
}
|
||||
|
||||
/// TOML representation of various global install decisions.
|
||||
#[derive(RustcDecodable, Default, Clone)]
|
||||
struct Install {
|
||||
prefix: Option<String>,
|
||||
}
|
||||
|
||||
/// TOML representation of how the LLVM build is configured.
|
||||
#[derive(RustcDecodable, Default)]
|
||||
struct Llvm {
|
||||
@ -258,6 +265,10 @@ impl Config {
|
||||
set(&mut config.submodules, build.submodules);
|
||||
set(&mut config.vendor, build.vendor);
|
||||
|
||||
if let Some(ref install) = toml.install {
|
||||
config.prefix = install.prefix.clone();
|
||||
}
|
||||
|
||||
if let Some(ref llvm) = toml.llvm {
|
||||
match llvm.ccache {
|
||||
Some(StringOrBool::String(ref s)) => {
|
||||
@ -275,6 +286,7 @@ impl Config {
|
||||
set(&mut config.llvm_version_check, llvm.version_check);
|
||||
set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp);
|
||||
}
|
||||
|
||||
if let Some(ref rust) = toml.rust {
|
||||
set(&mut config.rust_debug_assertions, rust.debug_assertions);
|
||||
set(&mut config.rust_debuginfo, rust.debuginfo);
|
||||
|
@ -100,6 +100,14 @@
|
||||
# Indicate whether the vendored sources are used for Rust dependencies or not
|
||||
#vendor = false
|
||||
|
||||
# =============================================================================
|
||||
# General install configuration options
|
||||
# =============================================================================
|
||||
[install]
|
||||
|
||||
# Instead of installing to /usr/local, install to this path instead.
|
||||
#prefix = "/path/to/install"
|
||||
|
||||
# =============================================================================
|
||||
# Options for compiling Rust code itself
|
||||
# =============================================================================
|
||||
|
@ -346,8 +346,14 @@ pub fn analysis(build: &Build, compiler: &Compiler, target: &str) {
|
||||
}
|
||||
|
||||
/// Creates the `rust-src` installer component and the plain source tarball
|
||||
pub fn rust_src(build: &Build) {
|
||||
pub fn rust_src(build: &Build, host: &str) {
|
||||
println!("Dist src");
|
||||
|
||||
if host != build.config.build {
|
||||
println!("\tskipping, not a build host");
|
||||
return
|
||||
}
|
||||
|
||||
let plain_name = format!("rustc-{}-src", package_vers(build));
|
||||
let name = format!("rust-src-{}", package_vers(build));
|
||||
let image = tmpdir(build).join(format!("{}-image", name));
|
||||
|
@ -280,7 +280,7 @@ To learn more about a subcommand, run `./x.py <command> -h`
|
||||
|
||||
Flags {
|
||||
verbose: m.opt_count("v"),
|
||||
stage: m.opt_str("stage").map(|j| j.parse().unwrap()),
|
||||
stage: stage,
|
||||
keep_stage: m.opt_str("keep-stage").map(|j| j.parse().unwrap()),
|
||||
build: m.opt_str("build").unwrap_or_else(|| {
|
||||
env::var("BUILD").unwrap()
|
||||
|
@ -64,6 +64,8 @@
|
||||
//! More documentation can be found in each respective module below, and you can
|
||||
//! also check out the `src/bootstrap/README.md` file for more information.
|
||||
|
||||
#![deny(warnings)]
|
||||
|
||||
extern crate build_helper;
|
||||
extern crate cmake;
|
||||
extern crate filetime;
|
||||
@ -721,7 +723,8 @@ impl Build {
|
||||
fn llvm_filecheck(&self, target: &str) -> PathBuf {
|
||||
let target_config = self.config.target_config.get(target);
|
||||
if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
|
||||
s.parent().unwrap().join(exe("FileCheck", target))
|
||||
let llvm_bindir = output(Command::new(s).arg("--bindir"));
|
||||
Path::new(llvm_bindir.trim()).join(exe("FileCheck", target))
|
||||
} else {
|
||||
let base = self.llvm_out(&self.config.build).join("build");
|
||||
let exe = exe("FileCheck", target);
|
||||
|
@ -66,7 +66,7 @@ tidy:
|
||||
check-stage2-T-arm-linux-androideabi-H-x86_64-unknown-linux-gnu:
|
||||
$(Q)$(BOOTSTRAP) test --target arm-linux-androideabi
|
||||
check-stage2-T-x86_64-unknown-linux-musl-H-x86_64-unknown-linux-gnu:
|
||||
$(Q)$(BOOTSTRAP) test --target x86_64-unknown-linux-gnu
|
||||
$(Q)$(BOOTSTRAP) test --target x86_64-unknown-linux-musl
|
||||
|
||||
|
||||
.PHONY: dist
|
||||
|
@ -143,7 +143,7 @@ pub fn check(build: &mut Build) {
|
||||
// Externally configured LLVM requires FileCheck to exist
|
||||
let filecheck = build.llvm_filecheck(&build.config.build);
|
||||
if !filecheck.starts_with(&build.out) && !filecheck.exists() && build.config.codegen_tests {
|
||||
panic!("filecheck executable {:?} does not exist", filecheck);
|
||||
panic!("FileCheck executable {:?} does not exist", filecheck);
|
||||
}
|
||||
|
||||
for target in build.config.target.iter() {
|
||||
|
@ -267,16 +267,18 @@ pub fn build_rules(build: &Build) -> Rules {
|
||||
// nothing to do for debuginfo tests
|
||||
} else if build.config.build.contains("apple") {
|
||||
rules.test("check-debuginfo", "src/test/debuginfo")
|
||||
.default(true)
|
||||
.dep(|s| s.name("libtest"))
|
||||
.dep(|s| s.name("tool-compiletest").host(s.host))
|
||||
.dep(|s| s.name("tool-compiletest").target(s.host))
|
||||
.dep(|s| s.name("test-helpers"))
|
||||
.dep(|s| s.name("debugger-scripts"))
|
||||
.run(move |s| check::compiletest(build, &s.compiler(), s.target,
|
||||
"debuginfo-lldb", "debuginfo"));
|
||||
} else {
|
||||
rules.test("check-debuginfo", "src/test/debuginfo")
|
||||
.default(true)
|
||||
.dep(|s| s.name("libtest"))
|
||||
.dep(|s| s.name("tool-compiletest").host(s.host))
|
||||
.dep(|s| s.name("tool-compiletest").target(s.host))
|
||||
.dep(|s| s.name("test-helpers"))
|
||||
.dep(|s| s.name("debugger-scripts"))
|
||||
.run(move |s| check::compiletest(build, &s.compiler(), s.target,
|
||||
@ -455,7 +457,7 @@ pub fn build_rules(build: &Build) -> Rules {
|
||||
for (krate, path, default) in krates("test_shim") {
|
||||
rules.doc(&krate.doc_step, path)
|
||||
.dep(|s| s.name("libtest"))
|
||||
.default(default && build.config.docs)
|
||||
.default(default && build.config.compiler_docs)
|
||||
.run(move |s| doc::test(build, s.stage, s.target));
|
||||
}
|
||||
for (krate, path, default) in krates("rustc-main") {
|
||||
@ -496,7 +498,7 @@ pub fn build_rules(build: &Build) -> Rules {
|
||||
rules.dist("dist-src", "src")
|
||||
.default(true)
|
||||
.host(true)
|
||||
.run(move |_| dist::rust_src(build));
|
||||
.run(move |s| dist::rust_src(build, s.target));
|
||||
rules.dist("dist-docs", "src/doc")
|
||||
.default(true)
|
||||
.dep(|s| s.name("default:doc"))
|
||||
@ -820,7 +822,16 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd?
|
||||
let hosts = if self.build.flags.host.len() > 0 {
|
||||
&self.build.flags.host
|
||||
} else {
|
||||
&self.build.config.host
|
||||
if kind == Kind::Dist {
|
||||
// For 'dist' steps we only distribute artifacts built from
|
||||
// the build platform, so only consider that in the hosts
|
||||
// array.
|
||||
// NOTE: This relies on the fact that the build triple is
|
||||
// always placed first, as done in `config.rs`.
|
||||
&self.build.config.host[..1]
|
||||
} else {
|
||||
&self.build.config.host
|
||||
}
|
||||
};
|
||||
let targets = if self.build.flags.target.len() > 0 {
|
||||
&self.build.flags.target
|
||||
|
@ -47,6 +47,8 @@ pub fn cc2ar(cc: &Path, target: &str) -> Option<PathBuf> {
|
||||
None
|
||||
} else if target.contains("musl") {
|
||||
Some(PathBuf::from("ar"))
|
||||
} else if target.contains("openbsd") {
|
||||
Some(PathBuf::from("ar"))
|
||||
} else {
|
||||
let parent = cc.parent().unwrap();
|
||||
let file = cc.file_name().unwrap().to_str().unwrap();
|
||||
@ -61,6 +63,16 @@ pub fn cc2ar(cc: &Path, target: &str) -> Option<PathBuf> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make(host: &str) -> PathBuf {
|
||||
if host.contains("bitrig") || host.contains("dragonfly") ||
|
||||
host.contains("freebsd") || host.contains("netbsd") ||
|
||||
host.contains("openbsd") {
|
||||
PathBuf::from("gmake")
|
||||
} else {
|
||||
PathBuf::from("make")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn output(cmd: &mut Command) -> String {
|
||||
let output = match cmd.stderr(Stdio::inherit()).output() {
|
||||
Ok(status) => status,
|
||||
|
@ -28,15 +28,23 @@ docker \
|
||||
mkdir -p $HOME/.cargo
|
||||
mkdir -p $root_dir/obj
|
||||
|
||||
args=
|
||||
if [ "$SCCACHE_BUCKET" != "" ]; then
|
||||
args="$args --env SCCACHE_BUCKET=$SCCACHE_BUCKET"
|
||||
args="$args --env AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID"
|
||||
args="$args --env AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY"
|
||||
else
|
||||
mkdir -p $HOME/.cache/sccache
|
||||
args="$args --env SCCACHE_DIR=/sccache --volume $HOME/.cache/sccache:/sccache"
|
||||
fi
|
||||
|
||||
exec docker \
|
||||
run \
|
||||
--volume "$root_dir:/checkout:ro" \
|
||||
--volume "$root_dir/obj:/checkout/obj" \
|
||||
--workdir /checkout/obj \
|
||||
--env SRC=/checkout \
|
||||
--env SCCACHE_BUCKET=$SCCACHE_BUCKET \
|
||||
--env AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
|
||||
--env AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
|
||||
$args \
|
||||
--env CARGO_HOME=/cargo \
|
||||
--env LOCAL_USER_ID=`id -u` \
|
||||
--volume "$HOME/.cargo:/cargo" \
|
||||
|
@ -12,7 +12,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
ccache \
|
||||
libssl-dev \
|
||||
sudo \
|
||||
xz-utils
|
||||
xz-utils \
|
||||
pkg-config
|
||||
|
||||
ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
|
||||
RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
|
||||
|
@ -1731,7 +1731,8 @@ of an item to see whether it should be allowed or not. This is where privacy
|
||||
warnings are generated, or otherwise "you used a private item of another module
|
||||
and weren't allowed to."
|
||||
|
||||
By default, everything in Rust is *private*, with one exception. Enum variants
|
||||
By default, everything in Rust is *private*, with two exceptions: Associated
|
||||
items in a `pub` Trait are public by default; Enum variants
|
||||
in a `pub` enum are also public by default. When an item is declared as `pub`,
|
||||
it can be thought of as being accessible to the outside world. For example:
|
||||
|
||||
|
@ -151,7 +151,7 @@ fn main() {
|
||||
cmd.arg(format!("--build={}", build_helper::gnu_target(&host)));
|
||||
|
||||
run(&mut cmd);
|
||||
let mut make = Command::new("make");
|
||||
let mut make = Command::new(build_helper::make(&host));
|
||||
make.current_dir(&build_dir)
|
||||
.arg("build_lib_static");
|
||||
|
||||
|
@ -74,24 +74,44 @@ pub struct BTreeSet<T> {
|
||||
map: BTreeMap<T, ()>,
|
||||
}
|
||||
|
||||
/// An iterator over a BTreeSet's items.
|
||||
/// An iterator over a `BTreeSet`'s items.
|
||||
///
|
||||
/// This structure is created by the [`iter`] method on [`BTreeSet`].
|
||||
///
|
||||
/// [`BTreeSet`]: struct.BTreeSet.html
|
||||
/// [`iter`]: struct.BTreeSet.html#method.iter
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Iter<'a, T: 'a> {
|
||||
iter: Keys<'a, T, ()>,
|
||||
}
|
||||
|
||||
/// An owning iterator over a BTreeSet's items.
|
||||
/// An owning iterator over a `BTreeSet`'s items.
|
||||
///
|
||||
/// This structure is created by the `into_iter` method on [`BTreeSet`]
|
||||
/// [`BTreeSet`] (provided by the `IntoIterator` trait).
|
||||
///
|
||||
/// [`BTreeSet`]: struct.BTreeSet.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct IntoIter<T> {
|
||||
iter: ::btree_map::IntoIter<T, ()>,
|
||||
}
|
||||
|
||||
/// An iterator over a sub-range of BTreeSet's items.
|
||||
/// An iterator over a sub-range of `BTreeSet`'s items.
|
||||
///
|
||||
/// This structure is created by the [`range`] method on [`BTreeSet`].
|
||||
///
|
||||
/// [`BTreeSet`]: struct.BTreeSet.html
|
||||
/// [`range`]: struct.BTreeSet.html#method.range
|
||||
pub struct Range<'a, T: 'a> {
|
||||
iter: ::btree_map::Range<'a, T, ()>,
|
||||
}
|
||||
|
||||
/// A lazy iterator producing elements in the set difference (in-order).
|
||||
///
|
||||
/// This structure is created by the [`difference`] method on [`BTreeSet`].
|
||||
///
|
||||
/// [`BTreeSet`]: struct.BTreeSet.html
|
||||
/// [`difference`]: struct.BTreeSet.html#method.difference
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Difference<'a, T: 'a> {
|
||||
a: Peekable<Iter<'a, T>>,
|
||||
@ -99,6 +119,12 @@ pub struct Difference<'a, T: 'a> {
|
||||
}
|
||||
|
||||
/// A lazy iterator producing elements in the set symmetric difference (in-order).
|
||||
///
|
||||
/// This structure is created by the [`symmetric_difference`] method on
|
||||
/// [`BTreeSet`].
|
||||
///
|
||||
/// [`BTreeSet`]: struct.BTreeSet.html
|
||||
/// [`symmetric_difference`]: struct.BTreeSet.html#method.symmetric_difference
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct SymmetricDifference<'a, T: 'a> {
|
||||
a: Peekable<Iter<'a, T>>,
|
||||
@ -106,6 +132,11 @@ pub struct SymmetricDifference<'a, T: 'a> {
|
||||
}
|
||||
|
||||
/// A lazy iterator producing elements in the set intersection (in-order).
|
||||
///
|
||||
/// This structure is created by the [`intersection`] method on [`BTreeSet`].
|
||||
///
|
||||
/// [`BTreeSet`]: struct.BTreeSet.html
|
||||
/// [`intersection`]: struct.BTreeSet.html#method.intersection
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Intersection<'a, T: 'a> {
|
||||
a: Peekable<Iter<'a, T>>,
|
||||
@ -113,6 +144,11 @@ pub struct Intersection<'a, T: 'a> {
|
||||
}
|
||||
|
||||
/// A lazy iterator producing elements in the set union (in-order).
|
||||
///
|
||||
/// This structure is created by the [`union`] method on [`BTreeSet`].
|
||||
///
|
||||
/// [`BTreeSet`]: struct.BTreeSet.html
|
||||
/// [`union`]: struct.BTreeSet.html#method.union
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Union<'a, T: 'a> {
|
||||
a: Peekable<Iter<'a, T>>,
|
||||
@ -120,7 +156,7 @@ pub struct Union<'a, T: 'a> {
|
||||
}
|
||||
|
||||
impl<T: Ord> BTreeSet<T> {
|
||||
/// Makes a new BTreeSet with a reasonable choice of B.
|
||||
/// Makes a new `BTreeSet` with a reasonable choice of B.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -137,21 +173,32 @@ impl<T: Ord> BTreeSet<T> {
|
||||
}
|
||||
|
||||
impl<T> BTreeSet<T> {
|
||||
/// Gets an iterator over the BTreeSet's contents.
|
||||
/// Gets an iterator that visits the values in the `BTreeSet` in ascending order.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::BTreeSet;
|
||||
///
|
||||
/// let set: BTreeSet<usize> = [1, 2, 3, 4].iter().cloned().collect();
|
||||
/// let set: BTreeSet<usize> = [1, 2, 3].iter().cloned().collect();
|
||||
/// let mut set_iter = set.iter();
|
||||
/// assert_eq!(set_iter.next(), Some(&1));
|
||||
/// assert_eq!(set_iter.next(), Some(&2));
|
||||
/// assert_eq!(set_iter.next(), Some(&3));
|
||||
/// assert_eq!(set_iter.next(), None);
|
||||
/// ```
|
||||
///
|
||||
/// for x in set.iter() {
|
||||
/// println!("{}", x);
|
||||
/// }
|
||||
/// Values returned by the iterator are returned in ascending order:
|
||||
///
|
||||
/// let v: Vec<_> = set.iter().cloned().collect();
|
||||
/// assert_eq!(v, [1, 2, 3, 4]);
|
||||
/// ```
|
||||
/// use std::collections::BTreeSet;
|
||||
///
|
||||
/// let set: BTreeSet<usize> = [3, 1, 2].iter().cloned().collect();
|
||||
/// let mut set_iter = set.iter();
|
||||
/// assert_eq!(set_iter.next(), Some(&1));
|
||||
/// assert_eq!(set_iter.next(), Some(&2));
|
||||
/// assert_eq!(set_iter.next(), Some(&3));
|
||||
/// assert_eq!(set_iter.next(), None);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn iter(&self) -> Iter<T> {
|
||||
|
@ -1496,10 +1496,10 @@ unsafe fn merge<T, F>(v: &mut [T], mid: usize, buf: *mut T, compare: &mut F)
|
||||
/// The algorithm identifies strictly descending and non-descending subsequences, which are called
|
||||
/// natural runs. There is a stack of pending runs yet to be merged. Each newly found run is pushed
|
||||
/// onto the stack, and then some pairs of adjacent runs are merged until these two invariants are
|
||||
/// satisfied, for every `i` in `0 .. runs.len() - 2`:
|
||||
/// satisfied:
|
||||
///
|
||||
/// 1. `runs[i].len > runs[i + 1].len`
|
||||
/// 2. `runs[i].len > runs[i + 1].len + runs[i + 2].len`
|
||||
/// 1. for every `i` in `1..runs.len()`: `runs[i - 1].len > runs[i].len`
|
||||
/// 2. for every `i` in `2..runs.len()`: `runs[i - 2].len > runs[i - 1].len + runs[i].len`
|
||||
///
|
||||
/// The invariants ensure that the total running time is `O(n log n)` worst-case.
|
||||
fn merge_sort<T, F>(v: &mut [T], mut compare: F)
|
||||
|
@ -501,6 +501,8 @@ impl<T, E> Result<T, E> {
|
||||
|
||||
/// Returns an iterator over the possibly contained value.
|
||||
///
|
||||
/// The iterator yields one value if the result is [`Ok`], otherwise none.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
@ -512,6 +514,8 @@ impl<T, E> Result<T, E> {
|
||||
/// let x: Result<u32, &str> = Err("nothing!");
|
||||
/// assert_eq!(x.iter().next(), None);
|
||||
/// ```
|
||||
///
|
||||
/// [`Ok`]: enum.Result.html#variant.Ok
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn iter(&self) -> Iter<T> {
|
||||
@ -520,6 +524,8 @@ impl<T, E> Result<T, E> {
|
||||
|
||||
/// Returns a mutable iterator over the possibly contained value.
|
||||
///
|
||||
/// The iterator yields one value if the result is [`Ok`], otherwise none.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
@ -535,6 +541,8 @@ impl<T, E> Result<T, E> {
|
||||
/// let mut x: Result<u32, &str> = Err("nothing!");
|
||||
/// assert_eq!(x.iter_mut().next(), None);
|
||||
/// ```
|
||||
///
|
||||
/// [`Ok`]: enum.Result.html#variant.Ok
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn iter_mut(&mut self) -> IterMut<T> {
|
||||
@ -848,6 +856,8 @@ impl<T, E> IntoIterator for Result<T, E> {
|
||||
|
||||
/// Returns a consuming iterator over the possibly contained value.
|
||||
///
|
||||
/// The iterator yields one value if the result is [`Ok`], otherwise none.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
@ -861,6 +871,8 @@ impl<T, E> IntoIterator for Result<T, E> {
|
||||
/// let v: Vec<u32> = x.into_iter().collect();
|
||||
/// assert_eq!(v, []);
|
||||
/// ```
|
||||
///
|
||||
/// [`Ok`]: enum.Result.html#variant.Ok
|
||||
#[inline]
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
IntoIter { inner: self.ok() }
|
||||
@ -893,8 +905,13 @@ impl<'a, T, E> IntoIterator for &'a mut Result<T, E> {
|
||||
|
||||
/// An iterator over a reference to the [`Ok`] variant of a [`Result`].
|
||||
///
|
||||
/// The iterator yields one value if the result is [`Ok`], otherwise none.
|
||||
///
|
||||
/// Created by [`Result::iter`].
|
||||
///
|
||||
/// [`Ok`]: enum.Result.html#variant.Ok
|
||||
/// [`Result`]: enum.Result.html
|
||||
/// [`Result::iter`]: enum.Result.html#method.iter
|
||||
#[derive(Debug)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Iter<'a, T: 'a> { inner: Option<&'a T> }
|
||||
@ -934,8 +951,11 @@ impl<'a, T> Clone for Iter<'a, T> {
|
||||
|
||||
/// An iterator over a mutable reference to the [`Ok`] variant of a [`Result`].
|
||||
///
|
||||
/// Created by [`Result::iter_mut`].
|
||||
///
|
||||
/// [`Ok`]: enum.Result.html#variant.Ok
|
||||
/// [`Result`]: enum.Result.html
|
||||
/// [`Result::iter_mut`]: enum.Result.html#method.iter_mut
|
||||
#[derive(Debug)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct IterMut<'a, T: 'a> { inner: Option<&'a mut T> }
|
||||
@ -968,9 +988,12 @@ impl<'a, T> FusedIterator for IterMut<'a, T> {}
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<'a, A> TrustedLen for IterMut<'a, A> {}
|
||||
|
||||
/// An iterator over the value in a [`Ok`] variant of a [`Result`]. This struct is
|
||||
/// created by the [`into_iter`] method on [`Result`][`Result`] (provided by
|
||||
/// the [`IntoIterator`] trait).
|
||||
/// An iterator over the value in a [`Ok`] variant of a [`Result`].
|
||||
///
|
||||
/// The iterator yields one value if the result is [`Ok`], otherwise none.
|
||||
///
|
||||
/// This struct is created by the [`into_iter`] method on
|
||||
/// [`Result`][`Result`] (provided by the [`IntoIterator`] trait).
|
||||
///
|
||||
/// [`Ok`]: enum.Result.html#variant.Ok
|
||||
/// [`Result`]: enum.Result.html
|
||||
|
@ -33,6 +33,7 @@
|
||||
// * The `raw` and `bytes` submodules.
|
||||
// * Boilerplate trait implementations.
|
||||
|
||||
use borrow::Borrow;
|
||||
use cmp::Ordering::{self, Less, Equal, Greater};
|
||||
use cmp;
|
||||
use fmt;
|
||||
@ -100,15 +101,17 @@ pub trait SliceExt {
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
fn as_ptr(&self) -> *const Self::Item;
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
fn binary_search(&self, x: &Self::Item) -> Result<usize, usize>
|
||||
where Self::Item: Ord;
|
||||
fn binary_search<Q: ?Sized>(&self, x: &Q) -> Result<usize, usize>
|
||||
where Self::Item: Borrow<Q>,
|
||||
Q: Ord;
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
fn binary_search_by<'a, F>(&'a self, f: F) -> Result<usize, usize>
|
||||
where F: FnMut(&'a Self::Item) -> Ordering;
|
||||
#[stable(feature = "slice_binary_search_by_key", since = "1.10.0")]
|
||||
fn binary_search_by_key<'a, B, F>(&'a self, b: &B, f: F) -> Result<usize, usize>
|
||||
fn binary_search_by_key<'a, B, F, Q: ?Sized>(&'a self, b: &Q, f: F) -> Result<usize, usize>
|
||||
where F: FnMut(&'a Self::Item) -> B,
|
||||
B: Ord;
|
||||
B: Borrow<Q>,
|
||||
Q: Ord;
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
fn len(&self) -> usize;
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
@ -493,8 +496,8 @@ impl<T> SliceExt for [T] {
|
||||
m >= n && needle == &self[m-n..]
|
||||
}
|
||||
|
||||
fn binary_search(&self, x: &T) -> Result<usize, usize> where T: Ord {
|
||||
self.binary_search_by(|p| p.cmp(x))
|
||||
fn binary_search<Q: ?Sized>(&self, x: &Q) -> Result<usize, usize> where T: Borrow<Q>, Q: Ord {
|
||||
self.binary_search_by(|p| p.borrow().cmp(x))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -522,11 +525,12 @@ impl<T> SliceExt for [T] {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result<usize, usize>
|
||||
fn binary_search_by_key<'a, B, F, Q: ?Sized>(&'a self, b: &Q, mut f: F) -> Result<usize, usize>
|
||||
where F: FnMut(&'a Self::Item) -> B,
|
||||
B: Ord
|
||||
B: Borrow<Q>,
|
||||
Q: Ord
|
||||
{
|
||||
self.binary_search_by(|k| f(k).cmp(b))
|
||||
self.binary_search_by(|k| f(k).borrow().cmp(b))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -418,7 +418,7 @@ to see something like:
|
||||
|
||||
Hir(foo) -> Collect(bar)
|
||||
Collect(bar) -> TypeckItemBody(bar)
|
||||
|
||||
|
||||
That first edge looks suspicious to you. So you set
|
||||
`RUST_FORBID_DEP_GRAPH_EDGE` to `Hir&foo -> Collect&bar`, re-run, and
|
||||
then observe the backtrace. Voila, bug fixed!
|
||||
@ -440,6 +440,4 @@ To achieve this, the HIR map will detect if the def-id originates in
|
||||
an inlined node and add a dependency to a suitable `MetaData` node
|
||||
instead. If you are reading a HIR node and are not sure if it may be
|
||||
inlined or not, you can use `tcx.map.read(node_id)` and it will detect
|
||||
whether the node is inlined or not and do the right thing. You can
|
||||
also use `tcx.map.is_inlined_def_id()` and
|
||||
`tcx.map.is_inlined_node_id()` to test.
|
||||
whether the node is inlined or not and do the right thing.
|
||||
|
@ -40,7 +40,6 @@ pub fn visit_all_item_likes_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>
|
||||
let task_id = (self.dep_node_fn)(item_def_id);
|
||||
let _task = self.tcx.dep_graph.in_task(task_id.clone());
|
||||
debug!("Started task {:?}", task_id);
|
||||
assert!(!self.tcx.map.is_inlined_def_id(item_def_id));
|
||||
self.tcx.dep_graph.read(DepNode::Hir(item_def_id));
|
||||
self.visitor.visit_item(i);
|
||||
debug!("Ended task {:?}", task_id);
|
||||
@ -51,7 +50,6 @@ pub fn visit_all_item_likes_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>
|
||||
let task_id = (self.dep_node_fn)(impl_item_def_id);
|
||||
let _task = self.tcx.dep_graph.in_task(task_id.clone());
|
||||
debug!("Started task {:?}", task_id);
|
||||
assert!(!self.tcx.map.is_inlined_def_id(impl_item_def_id));
|
||||
self.tcx.dep_graph.read(DepNode::Hir(impl_item_def_id));
|
||||
self.visitor.visit_impl_item(i);
|
||||
debug!("Ended task {:?}", task_id);
|
||||
|
@ -1236,6 +1236,23 @@ struct Foo<'a, T: 'a> {
|
||||
foo: &'a T
|
||||
}
|
||||
```
|
||||
|
||||
To see why this is important, consider the case where `T` is itself a reference
|
||||
(e.g., `T = &str`). If we don't include the restriction that `T: 'a`, the
|
||||
following code would be perfectly legal:
|
||||
|
||||
```compile_fail,E0309
|
||||
struct Foo<'a, T> {
|
||||
foo: &'a T
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let v = "42".to_string();
|
||||
let f = Foo{foo: &v};
|
||||
drop(v);
|
||||
println!("{}", f.foo); // but we've already dropped v!
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0310: r##"
|
||||
|
@ -120,9 +120,7 @@ impl fmt::Debug for DefId {
|
||||
|
||||
ty::tls::with_opt(|opt_tcx| {
|
||||
if let Some(tcx) = opt_tcx {
|
||||
if let Some(def_path) = tcx.opt_def_path(*self) {
|
||||
write!(f, " => {}", def_path.to_string(tcx))?;
|
||||
}
|
||||
write!(f, " => {}", tcx.def_path(*self).to_string(tcx))?;
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
|
@ -365,7 +365,6 @@ pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) {
|
||||
pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef) {
|
||||
visitor.visit_id(macro_def.id);
|
||||
visitor.visit_name(macro_def.span, macro_def.name);
|
||||
walk_opt_name(visitor, macro_def.span, macro_def.imported_from);
|
||||
walk_list!(visitor, visit_attribute, ¯o_def.attrs);
|
||||
}
|
||||
|
||||
|
@ -433,13 +433,19 @@ impl<'a> LoweringContext<'a> {
|
||||
segment: &PathSegment,
|
||||
param_mode: ParamMode)
|
||||
-> hir::PathSegment {
|
||||
let parameters = match segment.parameters {
|
||||
PathParameters::AngleBracketed(ref data) => {
|
||||
let data = self.lower_angle_bracketed_parameter_data(data, param_mode);
|
||||
hir::AngleBracketedParameters(data)
|
||||
let parameters = if let Some(ref parameters) = segment.parameters {
|
||||
match **parameters {
|
||||
PathParameters::AngleBracketed(ref data) => {
|
||||
let data = self.lower_angle_bracketed_parameter_data(data, param_mode);
|
||||
hir::AngleBracketedParameters(data)
|
||||
}
|
||||
PathParameters::Parenthesized(ref data) => {
|
||||
hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data))
|
||||
}
|
||||
}
|
||||
PathParameters::Parenthesized(ref data) =>
|
||||
hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data)),
|
||||
} else {
|
||||
let data = self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode);
|
||||
hir::AngleBracketedParameters(data)
|
||||
};
|
||||
|
||||
hir::PathSegment {
|
||||
@ -987,8 +993,6 @@ impl<'a> LoweringContext<'a> {
|
||||
attrs: self.lower_attrs(&m.attrs),
|
||||
id: m.id,
|
||||
span: m.span,
|
||||
imported_from: m.imported_from.map(|x| x.name),
|
||||
allow_internal_unstable: m.allow_internal_unstable,
|
||||
body: m.body.clone().into(),
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,6 @@
|
||||
use super::*;
|
||||
|
||||
use hir::intravisit::{Visitor, NestedVisitorMap};
|
||||
use hir::def_id::DefId;
|
||||
use middle::cstore::InlinedItem;
|
||||
use std::iter::repeat;
|
||||
use syntax::ast::{NodeId, CRATE_NODE_ID};
|
||||
@ -47,8 +46,6 @@ impl<'ast> NodeCollector<'ast> {
|
||||
pub fn extend(krate: &'ast Crate,
|
||||
parent: &'ast InlinedItem,
|
||||
parent_node: NodeId,
|
||||
parent_def_path: DefPath,
|
||||
parent_def_id: DefId,
|
||||
map: Vec<MapEntry<'ast>>)
|
||||
-> NodeCollector<'ast> {
|
||||
let mut collector = NodeCollector {
|
||||
@ -58,7 +55,6 @@ impl<'ast> NodeCollector<'ast> {
|
||||
ignore_nested_items: true
|
||||
};
|
||||
|
||||
assert_eq!(parent_def_path.krate, parent_def_id.krate);
|
||||
collector.insert_entry(parent_node, RootInlinedParent(parent));
|
||||
|
||||
collector
|
||||
|
@ -9,12 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
use hir::map::definitions::*;
|
||||
|
||||
use hir;
|
||||
use hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
|
||||
|
||||
use middle::cstore::InlinedItem;
|
||||
use hir::def_id::{CRATE_DEF_INDEX, DefIndex};
|
||||
|
||||
use syntax::ast::*;
|
||||
use syntax::ext::hygiene::Mark;
|
||||
@ -23,9 +18,6 @@ use syntax::symbol::{Symbol, keywords};
|
||||
|
||||
/// Creates def ids for nodes in the HIR.
|
||||
pub struct DefCollector<'a> {
|
||||
// If we are walking HIR (c.f., AST), we need to keep a reference to the
|
||||
// crate.
|
||||
hir_crate: Option<&'a hir::Crate>,
|
||||
definitions: &'a mut Definitions,
|
||||
parent_def: Option<DefIndex>,
|
||||
pub visit_macro_invoc: Option<&'a mut FnMut(MacroInvocationData)>,
|
||||
@ -40,43 +32,16 @@ pub struct MacroInvocationData {
|
||||
impl<'a> DefCollector<'a> {
|
||||
pub fn new(definitions: &'a mut Definitions) -> Self {
|
||||
DefCollector {
|
||||
hir_crate: None,
|
||||
definitions: definitions,
|
||||
parent_def: None,
|
||||
visit_macro_invoc: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extend(parent_node: NodeId,
|
||||
parent_def_path: DefPath,
|
||||
parent_def_id: DefId,
|
||||
definitions: &'a mut Definitions)
|
||||
-> Self {
|
||||
let mut collector = DefCollector::new(definitions);
|
||||
|
||||
assert_eq!(parent_def_path.krate, parent_def_id.krate);
|
||||
let root_path = Box::new(InlinedRootPath {
|
||||
data: parent_def_path.data,
|
||||
def_id: parent_def_id,
|
||||
});
|
||||
|
||||
let def = collector.create_def(parent_node, DefPathData::InlinedRoot(root_path));
|
||||
collector.parent_def = Some(def);
|
||||
|
||||
collector
|
||||
}
|
||||
|
||||
pub fn collect_root(&mut self) {
|
||||
let root = self.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot);
|
||||
assert_eq!(root, CRATE_DEF_INDEX);
|
||||
self.parent_def = Some(root);
|
||||
|
||||
self.create_def_with_parent(Some(CRATE_DEF_INDEX), DUMMY_NODE_ID, DefPathData::Misc);
|
||||
}
|
||||
|
||||
pub fn walk_item(&mut self, ii: &'a InlinedItem, krate: &'a hir::Crate) {
|
||||
self.hir_crate = Some(krate);
|
||||
ii.visit(self);
|
||||
}
|
||||
|
||||
fn create_def(&mut self, node_id: NodeId, data: DefPathData) -> DefIndex {
|
||||
@ -114,16 +79,6 @@ impl<'a> DefCollector<'a> {
|
||||
self.create_def(expr.id, DefPathData::Initializer);
|
||||
}
|
||||
|
||||
fn visit_hir_const_integer(&mut self, expr: &hir::Expr) {
|
||||
// FIXME(eddyb) Closures should have separate
|
||||
// function definition IDs and expression IDs.
|
||||
if let hir::ExprClosure(..) = expr.node {
|
||||
return;
|
||||
}
|
||||
|
||||
self.create_def(expr.id, DefPathData::Initializer);
|
||||
}
|
||||
|
||||
fn visit_macro_invoc(&mut self, id: NodeId, const_integer: bool) {
|
||||
if let Some(ref mut visit) = self.visit_macro_invoc {
|
||||
visit(MacroInvocationData {
|
||||
@ -324,169 +279,3 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We walk the HIR rather than the AST when reading items from metadata.
|
||||
impl<'ast> Visitor<'ast> for DefCollector<'ast> {
|
||||
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'ast> {
|
||||
// note however that we override `visit_body` below
|
||||
NestedVisitorMap::None
|
||||
}
|
||||
|
||||
fn visit_body(&mut self, id: hir::ExprId) {
|
||||
if let Some(krate) = self.hir_crate {
|
||||
self.visit_expr(krate.expr(id));
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, i: &'ast hir::Item) {
|
||||
debug!("visit_item: {:?}", i);
|
||||
|
||||
// Pick the def data. This need not be unique, but the more
|
||||
// information we encapsulate into
|
||||
let def_data = match i.node {
|
||||
hir::ItemDefaultImpl(..) | hir::ItemImpl(..) =>
|
||||
DefPathData::Impl,
|
||||
hir::ItemEnum(..) | hir::ItemStruct(..) | hir::ItemUnion(..) |
|
||||
hir::ItemTrait(..) | hir::ItemExternCrate(..) | hir::ItemMod(..) |
|
||||
hir::ItemForeignMod(..) | hir::ItemTy(..) =>
|
||||
DefPathData::TypeNs(i.name.as_str()),
|
||||
hir::ItemStatic(..) | hir::ItemConst(..) | hir::ItemFn(..) =>
|
||||
DefPathData::ValueNs(i.name.as_str()),
|
||||
hir::ItemUse(..) => DefPathData::Misc,
|
||||
};
|
||||
let def = self.create_def(i.id, def_data);
|
||||
|
||||
self.with_parent(def, |this| {
|
||||
match i.node {
|
||||
hir::ItemEnum(ref enum_definition, _) => {
|
||||
for v in &enum_definition.variants {
|
||||
let variant_def_index =
|
||||
this.create_def(v.node.data.id(),
|
||||
DefPathData::EnumVariant(v.node.name.as_str()));
|
||||
|
||||
this.with_parent(variant_def_index, |this| {
|
||||
for field in v.node.data.fields() {
|
||||
this.create_def(field.id,
|
||||
DefPathData::Field(field.name.as_str()));
|
||||
}
|
||||
if let Some(ref expr) = v.node.disr_expr {
|
||||
this.visit_hir_const_integer(expr);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
hir::ItemStruct(ref struct_def, _) |
|
||||
hir::ItemUnion(ref struct_def, _) => {
|
||||
// If this is a tuple-like struct, register the constructor.
|
||||
if !struct_def.is_struct() {
|
||||
this.create_def(struct_def.id(),
|
||||
DefPathData::StructCtor);
|
||||
}
|
||||
|
||||
for field in struct_def.fields() {
|
||||
this.create_def(field.id, DefPathData::Field(field.name.as_str()));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
intravisit::walk_item(this, i);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_foreign_item(&mut self, foreign_item: &'ast hir::ForeignItem) {
|
||||
let def = self.create_def(foreign_item.id,
|
||||
DefPathData::ValueNs(foreign_item.name.as_str()));
|
||||
|
||||
self.with_parent(def, |this| {
|
||||
intravisit::walk_foreign_item(this, foreign_item);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_generics(&mut self, generics: &'ast hir::Generics) {
|
||||
for ty_param in generics.ty_params.iter() {
|
||||
self.create_def(ty_param.id, DefPathData::TypeParam(ty_param.name.as_str()));
|
||||
}
|
||||
|
||||
intravisit::walk_generics(self, generics);
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
|
||||
let def_data = match ti.node {
|
||||
hir::MethodTraitItem(..) | hir::ConstTraitItem(..) =>
|
||||
DefPathData::ValueNs(ti.name.as_str()),
|
||||
hir::TypeTraitItem(..) => DefPathData::TypeNs(ti.name.as_str()),
|
||||
};
|
||||
|
||||
let def = self.create_def(ti.id, def_data);
|
||||
self.with_parent(def, |this| {
|
||||
if let hir::ConstTraitItem(_, Some(ref expr)) = ti.node {
|
||||
this.create_def(expr.id, DefPathData::Initializer);
|
||||
}
|
||||
|
||||
intravisit::walk_trait_item(this, ti);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
|
||||
let def_data = match ii.node {
|
||||
hir::ImplItemKind::Method(..) | hir::ImplItemKind::Const(..) =>
|
||||
DefPathData::ValueNs(ii.name.as_str()),
|
||||
hir::ImplItemKind::Type(..) => DefPathData::TypeNs(ii.name.as_str()),
|
||||
};
|
||||
|
||||
let def = self.create_def(ii.id, def_data);
|
||||
self.with_parent(def, |this| {
|
||||
if let hir::ImplItemKind::Const(_, ref expr) = ii.node {
|
||||
this.create_def(expr.id, DefPathData::Initializer);
|
||||
}
|
||||
|
||||
intravisit::walk_impl_item(this, ii);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_pat(&mut self, pat: &'ast hir::Pat) {
|
||||
let parent_def = self.parent_def;
|
||||
|
||||
if let hir::PatKind::Binding(_, _, name, _) = pat.node {
|
||||
let def = self.create_def(pat.id, DefPathData::Binding(name.node.as_str()));
|
||||
self.parent_def = Some(def);
|
||||
}
|
||||
|
||||
intravisit::walk_pat(self, pat);
|
||||
self.parent_def = parent_def;
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &'ast hir::Expr) {
|
||||
let parent_def = self.parent_def;
|
||||
|
||||
if let hir::ExprRepeat(_, ref count) = expr.node {
|
||||
self.visit_hir_const_integer(count);
|
||||
}
|
||||
|
||||
if let hir::ExprClosure(..) = expr.node {
|
||||
let def = self.create_def(expr.id, DefPathData::ClosureExpr);
|
||||
self.parent_def = Some(def);
|
||||
}
|
||||
|
||||
intravisit::walk_expr(self, expr);
|
||||
self.parent_def = parent_def;
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: &'ast hir::Ty) {
|
||||
if let hir::TyArray(_, ref length) = ty.node {
|
||||
self.visit_hir_const_integer(length);
|
||||
}
|
||||
if let hir::TyImplTrait(..) = ty.node {
|
||||
self.create_def(ty.id, DefPathData::ImplTrait);
|
||||
}
|
||||
intravisit::walk_ty(self, ty);
|
||||
}
|
||||
|
||||
fn visit_lifetime_def(&mut self, def: &'ast hir::LifetimeDef) {
|
||||
self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name.as_str()));
|
||||
}
|
||||
|
||||
fn visit_macro_def(&mut self, macro_def: &'ast hir::MacroDef) {
|
||||
self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name.as_str()));
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,16 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! For each definition, we track the following data. A definition
|
||||
//! here is defined somewhat circularly as "something with a def-id",
|
||||
//! but it generally corresponds to things like structs, enums, etc.
|
||||
//! There are also some rather random cases (like const initializer
|
||||
//! expressions) that are mostly just leftovers.
|
||||
|
||||
use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::stable_hasher::StableHasher;
|
||||
use serialize::{Encodable, Decodable, Encoder, Decoder};
|
||||
use std::fmt::Write;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use syntax::ast;
|
||||
@ -18,12 +25,102 @@ use syntax::symbol::{Symbol, InternedString};
|
||||
use ty::TyCtxt;
|
||||
use util::nodemap::NodeMap;
|
||||
|
||||
/// The definition table containing node definitions
|
||||
/// The DefPathTable maps DefIndexes to DefKeys and vice versa.
|
||||
/// Internally the DefPathTable holds a tree of DefKeys, where each DefKey
|
||||
/// stores the DefIndex of its parent.
|
||||
/// There is one DefPathTable for each crate.
|
||||
#[derive(Clone)]
|
||||
pub struct DefPathTable {
|
||||
index_to_key: Vec<DefKey>,
|
||||
key_to_index: FxHashMap<DefKey, DefIndex>,
|
||||
}
|
||||
|
||||
impl DefPathTable {
|
||||
fn insert(&mut self, key: DefKey) -> DefIndex {
|
||||
let index = DefIndex::new(self.index_to_key.len());
|
||||
debug!("DefPathTable::insert() - {:?} <-> {:?}", key, index);
|
||||
self.index_to_key.push(key.clone());
|
||||
self.key_to_index.insert(key, index);
|
||||
index
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn def_key(&self, index: DefIndex) -> DefKey {
|
||||
self.index_to_key[index.as_usize()].clone()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn def_index_for_def_key(&self, key: &DefKey) -> Option<DefIndex> {
|
||||
self.key_to_index.get(key).cloned()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn contains_key(&self, key: &DefKey) -> bool {
|
||||
self.key_to_index.contains_key(key)
|
||||
}
|
||||
|
||||
pub fn retrace_path(&self,
|
||||
path_data: &[DisambiguatedDefPathData])
|
||||
-> Option<DefIndex> {
|
||||
let root_key = DefKey {
|
||||
parent: None,
|
||||
disambiguated_data: DisambiguatedDefPathData {
|
||||
data: DefPathData::CrateRoot,
|
||||
disambiguator: 0,
|
||||
},
|
||||
};
|
||||
|
||||
let root_index = self.key_to_index
|
||||
.get(&root_key)
|
||||
.expect("no root key?")
|
||||
.clone();
|
||||
|
||||
debug!("retrace_path: root_index={:?}", root_index);
|
||||
|
||||
let mut index = root_index;
|
||||
for data in path_data {
|
||||
let key = DefKey { parent: Some(index), disambiguated_data: data.clone() };
|
||||
debug!("retrace_path: key={:?}", key);
|
||||
match self.key_to_index.get(&key) {
|
||||
Some(&i) => index = i,
|
||||
None => return None,
|
||||
}
|
||||
}
|
||||
|
||||
Some(index)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Encodable for DefPathTable {
|
||||
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
|
||||
self.index_to_key.encode(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for DefPathTable {
|
||||
fn decode<D: Decoder>(d: &mut D) -> Result<DefPathTable, D::Error> {
|
||||
let index_to_key: Vec<DefKey> = Decodable::decode(d)?;
|
||||
let key_to_index = index_to_key.iter()
|
||||
.enumerate()
|
||||
.map(|(index, key)| (key.clone(), DefIndex::new(index)))
|
||||
.collect();
|
||||
Ok(DefPathTable {
|
||||
index_to_key: index_to_key,
|
||||
key_to_index: key_to_index,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// The definition table containing node definitions.
|
||||
/// It holds the DefPathTable for local DefIds/DefPaths and it also stores a
|
||||
/// mapping from NodeIds to local DefIds.
|
||||
#[derive(Clone)]
|
||||
pub struct Definitions {
|
||||
data: Vec<DefData>,
|
||||
key_map: FxHashMap<DefKey, DefIndex>,
|
||||
node_map: NodeMap<DefIndex>,
|
||||
table: DefPathTable,
|
||||
node_to_def_index: NodeMap<DefIndex>,
|
||||
def_index_to_node: Vec<ast::NodeId>,
|
||||
}
|
||||
|
||||
/// A unique identifier that we can use to lookup a definition
|
||||
@ -50,19 +147,6 @@ pub struct DisambiguatedDefPathData {
|
||||
pub disambiguator: u32
|
||||
}
|
||||
|
||||
/// For each definition, we track the following data. A definition
|
||||
/// here is defined somewhat circularly as "something with a def-id",
|
||||
/// but it generally corresponds to things like structs, enums, etc.
|
||||
/// There are also some rather random cases (like const initializer
|
||||
/// expressions) that are mostly just leftovers.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DefData {
|
||||
pub key: DefKey,
|
||||
|
||||
/// Local ID within the HIR.
|
||||
pub node_id: ast::NodeId,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub struct DefPath {
|
||||
/// the path leading from the crate root to the item
|
||||
@ -77,12 +161,11 @@ impl DefPath {
|
||||
self.krate == LOCAL_CRATE
|
||||
}
|
||||
|
||||
pub fn make<FN>(start_krate: CrateNum,
|
||||
pub fn make<FN>(krate: CrateNum,
|
||||
start_index: DefIndex,
|
||||
mut get_key: FN) -> DefPath
|
||||
where FN: FnMut(DefIndex) -> DefKey
|
||||
{
|
||||
let mut krate = start_krate;
|
||||
let mut data = vec![];
|
||||
let mut index = Some(start_index);
|
||||
loop {
|
||||
@ -95,13 +178,6 @@ impl DefPath {
|
||||
assert!(key.parent.is_none());
|
||||
break;
|
||||
}
|
||||
DefPathData::InlinedRoot(ref p) => {
|
||||
assert!(key.parent.is_none());
|
||||
assert!(!p.def_id.is_local());
|
||||
data.extend(p.data.iter().cloned().rev());
|
||||
krate = p.def_id.krate;
|
||||
break;
|
||||
}
|
||||
_ => {
|
||||
data.push(key.disambiguated_data);
|
||||
index = key.parent;
|
||||
@ -144,31 +220,6 @@ impl DefPath {
|
||||
}
|
||||
}
|
||||
|
||||
/// Root of an inlined item. We track the `DefPath` of the item within
|
||||
/// the original crate but also its def-id. This is kind of an
|
||||
/// augmented version of a `DefPath` that includes a `DefId`. This is
|
||||
/// all sort of ugly but the hope is that inlined items will be going
|
||||
/// away soon anyway.
|
||||
///
|
||||
/// Some of the constraints that led to the current approach:
|
||||
///
|
||||
/// - I don't want to have a `DefId` in the main `DefPath` because
|
||||
/// that gets serialized for incr. comp., and when reloaded the
|
||||
/// `DefId` is no longer valid. I'd rather maintain the invariant
|
||||
/// that every `DefId` is valid, and a potentially outdated `DefId` is
|
||||
/// represented as a `DefPath`.
|
||||
/// - (We don't serialize def-paths from inlined items, so it's ok to have one here.)
|
||||
/// - We need to be able to extract the def-id from inline items to
|
||||
/// make the symbol name. In theory we could retrace it from the
|
||||
/// data, but the metadata doesn't have the required indices, and I
|
||||
/// don't want to write the code to create one just for this.
|
||||
/// - It may be that we don't actually need `data` at all. We'll have
|
||||
/// to see about that.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub struct InlinedRootPath {
|
||||
pub data: Vec<DisambiguatedDefPathData>,
|
||||
pub def_id: DefId,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub enum DefPathData {
|
||||
@ -176,8 +227,6 @@ pub enum DefPathData {
|
||||
// they are treated specially by the `def_path` function.
|
||||
/// The crate root (marker)
|
||||
CrateRoot,
|
||||
/// An inlined root
|
||||
InlinedRoot(Box<InlinedRootPath>),
|
||||
|
||||
// Catch-all for random DefId things like DUMMY_NODE_ID
|
||||
Misc,
|
||||
@ -219,23 +268,30 @@ impl Definitions {
|
||||
/// Create new empty definition map.
|
||||
pub fn new() -> Definitions {
|
||||
Definitions {
|
||||
data: vec![],
|
||||
key_map: FxHashMap(),
|
||||
node_map: NodeMap(),
|
||||
table: DefPathTable {
|
||||
index_to_key: vec![],
|
||||
key_to_index: FxHashMap(),
|
||||
},
|
||||
node_to_def_index: NodeMap(),
|
||||
def_index_to_node: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn def_path_table(&self) -> &DefPathTable {
|
||||
&self.table
|
||||
}
|
||||
|
||||
/// Get the number of definitions.
|
||||
pub fn len(&self) -> usize {
|
||||
self.data.len()
|
||||
self.def_index_to_node.len()
|
||||
}
|
||||
|
||||
pub fn def_key(&self, index: DefIndex) -> DefKey {
|
||||
self.data[index.as_usize()].key.clone()
|
||||
self.table.def_key(index)
|
||||
}
|
||||
|
||||
pub fn def_index_for_def_key(&self, key: DefKey) -> Option<DefIndex> {
|
||||
self.key_map.get(&key).cloned()
|
||||
self.table.def_index_for_def_key(&key)
|
||||
}
|
||||
|
||||
/// Returns the path from the crate root to `index`. The root
|
||||
@ -248,7 +304,7 @@ impl Definitions {
|
||||
}
|
||||
|
||||
pub fn opt_def_index(&self, node: ast::NodeId) -> Option<DefIndex> {
|
||||
self.node_map.get(&node).cloned()
|
||||
self.node_to_def_index.get(&node).cloned()
|
||||
}
|
||||
|
||||
pub fn opt_local_def_id(&self, node: ast::NodeId) -> Option<DefId> {
|
||||
@ -261,8 +317,8 @@ impl Definitions {
|
||||
|
||||
pub fn as_local_node_id(&self, def_id: DefId) -> Option<ast::NodeId> {
|
||||
if def_id.krate == LOCAL_CRATE {
|
||||
assert!(def_id.index.as_usize() < self.data.len());
|
||||
Some(self.data[def_id.index.as_usize()].node_id)
|
||||
assert!(def_id.index.as_usize() < self.def_index_to_node.len());
|
||||
Some(self.def_index_to_node[def_id.index.as_usize()])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -277,16 +333,13 @@ impl Definitions {
|
||||
debug!("create_def_with_parent(parent={:?}, node_id={:?}, data={:?})",
|
||||
parent, node_id, data);
|
||||
|
||||
assert!(!self.node_map.contains_key(&node_id),
|
||||
assert!(!self.node_to_def_index.contains_key(&node_id),
|
||||
"adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
|
||||
node_id,
|
||||
data,
|
||||
self.data[self.node_map[&node_id].as_usize()]);
|
||||
self.table.def_key(self.node_to_def_index[&node_id]));
|
||||
|
||||
assert!(parent.is_some() ^ match data {
|
||||
DefPathData::CrateRoot | DefPathData::InlinedRoot(_) => true,
|
||||
_ => false,
|
||||
});
|
||||
assert!(parent.is_some() ^ (data == DefPathData::CrateRoot));
|
||||
|
||||
// Find a unique DefKey. This basically means incrementing the disambiguator
|
||||
// until we get no match.
|
||||
@ -298,20 +351,18 @@ impl Definitions {
|
||||
}
|
||||
};
|
||||
|
||||
while self.key_map.contains_key(&key) {
|
||||
while self.table.contains_key(&key) {
|
||||
key.disambiguated_data.disambiguator += 1;
|
||||
}
|
||||
|
||||
debug!("create_def_with_parent: after disambiguation, key = {:?}", key);
|
||||
|
||||
// Create the definition.
|
||||
let index = DefIndex::new(self.data.len());
|
||||
self.data.push(DefData { key: key.clone(), node_id: node_id });
|
||||
debug!("create_def_with_parent: node_map[{:?}] = {:?}", node_id, index);
|
||||
self.node_map.insert(node_id, index);
|
||||
debug!("create_def_with_parent: key_map[{:?}] = {:?}", key, index);
|
||||
self.key_map.insert(key, index);
|
||||
|
||||
let index = self.table.insert(key);
|
||||
debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id);
|
||||
self.node_to_def_index.insert(node_id, index);
|
||||
assert_eq!(index.as_usize(), self.def_index_to_node.len());
|
||||
self.def_index_to_node.push(node_id);
|
||||
|
||||
index
|
||||
}
|
||||
@ -333,7 +384,6 @@ impl DefPathData {
|
||||
|
||||
Impl |
|
||||
CrateRoot |
|
||||
InlinedRoot(_) |
|
||||
Misc |
|
||||
ClosureExpr |
|
||||
StructCtor |
|
||||
@ -360,9 +410,6 @@ impl DefPathData {
|
||||
// note that this does not show up in user printouts
|
||||
CrateRoot => "{{root}}",
|
||||
|
||||
// note that this does not show up in user printouts
|
||||
InlinedRoot(_) => "{{inlined-root}}",
|
||||
|
||||
Impl => "{{impl}}",
|
||||
Misc => "{{?}}",
|
||||
ClosureExpr => "{{closure}}",
|
||||
|
@ -13,7 +13,7 @@ use self::MapEntry::*;
|
||||
use self::collector::NodeCollector;
|
||||
pub use self::def_collector::{DefCollector, MacroInvocationData};
|
||||
pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData,
|
||||
DisambiguatedDefPathData, InlinedRootPath};
|
||||
DisambiguatedDefPathData};
|
||||
|
||||
use dep_graph::{DepGraph, DepNode};
|
||||
|
||||
@ -221,22 +221,14 @@ pub struct Map<'ast> {
|
||||
/// plain old integers.
|
||||
map: RefCell<Vec<MapEntry<'ast>>>,
|
||||
|
||||
definitions: RefCell<Definitions>,
|
||||
definitions: Definitions,
|
||||
|
||||
/// All NodeIds that are numerically greater or equal to this value come
|
||||
/// from inlined items.
|
||||
local_node_id_watermark: NodeId,
|
||||
|
||||
/// All def-indices that are numerically greater or equal to this value come
|
||||
/// from inlined items.
|
||||
local_def_id_watermark: usize,
|
||||
}
|
||||
|
||||
impl<'ast> Map<'ast> {
|
||||
pub fn is_inlined_def_id(&self, id: DefId) -> bool {
|
||||
id.is_local() && id.index.as_usize() >= self.local_def_id_watermark
|
||||
}
|
||||
|
||||
pub fn is_inlined_node_id(&self, id: NodeId) -> bool {
|
||||
id >= self.local_node_id_watermark
|
||||
}
|
||||
@ -262,7 +254,6 @@ impl<'ast> Map<'ast> {
|
||||
EntryItem(_, item) => {
|
||||
assert_eq!(id, item.id);
|
||||
let def_id = self.local_def_id(id);
|
||||
assert!(!self.is_inlined_def_id(def_id));
|
||||
|
||||
if let Some(last_id) = last_expr {
|
||||
// The body of the item may have a separate dep node
|
||||
@ -278,7 +269,6 @@ impl<'ast> Map<'ast> {
|
||||
|
||||
EntryImplItem(_, item) => {
|
||||
let def_id = self.local_def_id(id);
|
||||
assert!(!self.is_inlined_def_id(def_id));
|
||||
|
||||
if let Some(last_id) = last_expr {
|
||||
// The body of the item may have a separate dep node
|
||||
@ -392,12 +382,16 @@ impl<'ast> Map<'ast> {
|
||||
}
|
||||
|
||||
pub fn num_local_def_ids(&self) -> usize {
|
||||
self.definitions.borrow().len()
|
||||
self.definitions.len()
|
||||
}
|
||||
|
||||
pub fn definitions(&self) -> &Definitions {
|
||||
&self.definitions
|
||||
}
|
||||
|
||||
pub fn def_key(&self, def_id: DefId) -> DefKey {
|
||||
assert!(def_id.is_local());
|
||||
self.definitions.borrow().def_key(def_id.index)
|
||||
self.definitions.def_key(def_id.index)
|
||||
}
|
||||
|
||||
pub fn def_path_from_id(&self, id: NodeId) -> Option<DefPath> {
|
||||
@ -408,11 +402,11 @@ impl<'ast> Map<'ast> {
|
||||
|
||||
pub fn def_path(&self, def_id: DefId) -> DefPath {
|
||||
assert!(def_id.is_local());
|
||||
self.definitions.borrow().def_path(def_id.index)
|
||||
self.definitions.def_path(def_id.index)
|
||||
}
|
||||
|
||||
pub fn def_index_for_def_key(&self, def_key: DefKey) -> Option<DefIndex> {
|
||||
self.definitions.borrow().def_index_for_def_key(def_key)
|
||||
self.definitions.def_index_for_def_key(def_key)
|
||||
}
|
||||
|
||||
pub fn local_def_id(&self, node: NodeId) -> DefId {
|
||||
@ -423,11 +417,11 @@ impl<'ast> Map<'ast> {
|
||||
}
|
||||
|
||||
pub fn opt_local_def_id(&self, node: NodeId) -> Option<DefId> {
|
||||
self.definitions.borrow().opt_local_def_id(node)
|
||||
self.definitions.opt_local_def_id(node)
|
||||
}
|
||||
|
||||
pub fn as_local_node_id(&self, def_id: DefId) -> Option<NodeId> {
|
||||
self.definitions.borrow().as_local_node_id(def_id)
|
||||
self.definitions.as_local_node_id(def_id)
|
||||
}
|
||||
|
||||
fn entry_count(&self) -> usize {
|
||||
@ -930,23 +924,19 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest,
|
||||
}
|
||||
|
||||
let local_node_id_watermark = NodeId::new(map.len());
|
||||
let local_def_id_watermark = definitions.len();
|
||||
|
||||
Map {
|
||||
forest: forest,
|
||||
dep_graph: forest.dep_graph.clone(),
|
||||
map: RefCell::new(map),
|
||||
definitions: RefCell::new(definitions),
|
||||
definitions: definitions,
|
||||
local_node_id_watermark: local_node_id_watermark,
|
||||
local_def_id_watermark: local_def_id_watermark,
|
||||
}
|
||||
}
|
||||
|
||||
/// Used for items loaded from external crate that are being inlined into this
|
||||
/// crate.
|
||||
pub fn map_decoded_item<'ast>(map: &Map<'ast>,
|
||||
parent_def_path: DefPath,
|
||||
parent_def_id: DefId,
|
||||
ii: InlinedItem,
|
||||
ii_parent_id: NodeId)
|
||||
-> &'ast InlinedItem {
|
||||
@ -954,18 +944,9 @@ pub fn map_decoded_item<'ast>(map: &Map<'ast>,
|
||||
|
||||
let ii = map.forest.inlined_items.alloc(ii);
|
||||
|
||||
let defs = &mut *map.definitions.borrow_mut();
|
||||
let mut def_collector = DefCollector::extend(ii_parent_id,
|
||||
parent_def_path.clone(),
|
||||
parent_def_id,
|
||||
defs);
|
||||
def_collector.walk_item(ii, map.krate());
|
||||
|
||||
let mut collector = NodeCollector::extend(map.krate(),
|
||||
ii,
|
||||
ii_parent_id,
|
||||
parent_def_path,
|
||||
parent_def_id,
|
||||
mem::replace(&mut *map.map.borrow_mut(), vec![]));
|
||||
ii.visit(&mut collector);
|
||||
*map.map.borrow_mut() = collector.map;
|
||||
|
@ -475,8 +475,6 @@ pub struct MacroDef {
|
||||
pub attrs: HirVec<Attribute>,
|
||||
pub id: NodeId,
|
||||
pub span: Span,
|
||||
pub imported_from: Option<Name>,
|
||||
pub allow_internal_unstable: bool,
|
||||
pub body: HirVec<TokenTree>,
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
use hir::def::{self, Def};
|
||||
use hir::def_id::{CrateNum, DefId, DefIndex};
|
||||
use hir::map as hir_map;
|
||||
use hir::map::definitions::{Definitions, DefKey};
|
||||
use hir::map::definitions::{Definitions, DefKey, DisambiguatedDefPathData};
|
||||
use hir::svh::Svh;
|
||||
use middle::lang_items;
|
||||
use ty::{self, Ty, TyCtxt};
|
||||
@ -336,12 +336,12 @@ pub trait CrateStore<'tcx> {
|
||||
fn is_no_builtins(&self, cnum: CrateNum) -> bool;
|
||||
|
||||
// resolve
|
||||
fn def_index_for_def_key(&self,
|
||||
cnum: CrateNum,
|
||||
def: DefKey)
|
||||
-> Option<DefIndex>;
|
||||
fn def_key(&self, def: DefId) -> hir_map::DefKey;
|
||||
fn relative_def_path(&self, def: DefId) -> Option<hir_map::DefPath>;
|
||||
fn retrace_path(&self,
|
||||
cnum: CrateNum,
|
||||
path_data: &[DisambiguatedDefPathData])
|
||||
-> Option<DefId>;
|
||||
fn def_key(&self, def: DefId) -> DefKey;
|
||||
fn def_path(&self, def: DefId) -> hir_map::DefPath;
|
||||
fn struct_field_names(&self, def: DefId) -> Vec<ast::Name>;
|
||||
fn item_children(&self, did: DefId) -> Vec<def::Export>;
|
||||
fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro;
|
||||
@ -442,12 +442,6 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
|
||||
|
||||
// trait info
|
||||
fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId> { vec![] }
|
||||
fn def_index_for_def_key(&self,
|
||||
cnum: CrateNum,
|
||||
def: DefKey)
|
||||
-> Option<DefIndex> {
|
||||
None
|
||||
}
|
||||
|
||||
// impl info
|
||||
fn associated_item_def_ids(&self, def_id: DefId) -> Vec<DefId>
|
||||
@ -508,8 +502,15 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
|
||||
fn is_no_builtins(&self, cnum: CrateNum) -> bool { bug!("is_no_builtins") }
|
||||
|
||||
// resolve
|
||||
fn def_key(&self, def: DefId) -> hir_map::DefKey { bug!("def_key") }
|
||||
fn relative_def_path(&self, def: DefId) -> Option<hir_map::DefPath> {
|
||||
fn retrace_path(&self,
|
||||
cnum: CrateNum,
|
||||
path_data: &[DisambiguatedDefPathData])
|
||||
-> Option<DefId> {
|
||||
None
|
||||
}
|
||||
|
||||
fn def_key(&self, def: DefId) -> DefKey { bug!("def_key") }
|
||||
fn def_path(&self, def: DefId) -> hir_map::DefPath {
|
||||
bug!("relative_def_path")
|
||||
}
|
||||
fn struct_field_names(&self, def: DefId) -> Vec<ast::Name> { bug!("struct_field_names") }
|
||||
|
@ -302,9 +302,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) {
|
||||
if md.imported_from.is_none() {
|
||||
self.annotate(md.id, &md.attrs, md.span, AnnotationKind::Required, |_| {});
|
||||
}
|
||||
self.annotate(md.id, &md.attrs, md.span, AnnotationKind::Required, |_| {});
|
||||
}
|
||||
}
|
||||
|
||||
@ -373,9 +371,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) {
|
||||
if md.imported_from.is_none() {
|
||||
self.check_missing_stability(md.id, md.span);
|
||||
}
|
||||
self.check_missing_stability(md.id, md.span);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,6 +136,8 @@ pub struct PerfStats {
|
||||
pub incr_comp_bytes_hashed: Cell<u64>,
|
||||
// The accumulated time spent on computing symbol hashes
|
||||
pub symbol_hash_time: Cell<Duration>,
|
||||
// The accumulated time spent decoding def path tables from metadata
|
||||
pub decode_def_path_tables_time: Cell<Duration>,
|
||||
}
|
||||
|
||||
impl Session {
|
||||
@ -501,6 +503,8 @@ impl Session {
|
||||
self.perf_stats.incr_comp_hashes_count.get());
|
||||
println!("Total time spent computing symbol hashes: {}",
|
||||
duration_to_secs_str(self.perf_stats.symbol_hash_time.get()));
|
||||
println!("Total time spent decoding DefPath tables: {}",
|
||||
duration_to_secs_str(self.perf_stats.decode_def_path_tables_time.get()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -635,6 +639,7 @@ pub fn build_session_(sopts: config::Options,
|
||||
incr_comp_hashes_count: Cell::new(0),
|
||||
incr_comp_bytes_hashed: Cell::new(0),
|
||||
symbol_hash_time: Cell::new(Duration::from_secs(0)),
|
||||
decode_def_path_tables_time: Cell::new(Duration::from_secs(0)),
|
||||
},
|
||||
code_stats: RefCell::new(CodeStats::new()),
|
||||
};
|
||||
|
@ -458,11 +458,28 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
err
|
||||
}
|
||||
|
||||
|
||||
/// Get the parent trait chain start
|
||||
fn get_parent_trait_ref(&self, code: &ObligationCauseCode<'tcx>) -> Option<String> {
|
||||
match code {
|
||||
&ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
|
||||
let parent_trait_ref = self.resolve_type_vars_if_possible(
|
||||
&data.parent_trait_ref);
|
||||
match self.get_parent_trait_ref(&data.parent_code) {
|
||||
Some(t) => Some(t),
|
||||
None => Some(format!("{}", parent_trait_ref.0.self_ty())),
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn report_selection_error(&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
error: &SelectionError<'tcx>)
|
||||
{
|
||||
let span = obligation.cause.span;
|
||||
|
||||
let mut err = match *error {
|
||||
SelectionError::Unimplemented => {
|
||||
if let ObligationCauseCode::CompareImplMethodObligation {
|
||||
@ -487,14 +504,27 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
return;
|
||||
} else {
|
||||
let trait_ref = trait_predicate.to_poly_trait_ref();
|
||||
|
||||
let mut err = struct_span_err!(self.tcx.sess, span, E0277,
|
||||
"the trait bound `{}` is not satisfied",
|
||||
trait_ref.to_predicate());
|
||||
err.span_label(span, &format!("the trait `{}` is not implemented \
|
||||
for `{}`",
|
||||
trait_ref,
|
||||
trait_ref.self_ty()));
|
||||
let (post_message, pre_message) = match self.get_parent_trait_ref(
|
||||
&obligation.cause.code)
|
||||
{
|
||||
Some(t) => {
|
||||
(format!(" in `{}`", t), format!("within `{}`, ", t))
|
||||
}
|
||||
None => (String::new(), String::new()),
|
||||
};
|
||||
let mut err = struct_span_err!(
|
||||
self.tcx.sess,
|
||||
span,
|
||||
E0277,
|
||||
"the trait bound `{}` is not satisfied{}",
|
||||
trait_ref.to_predicate(),
|
||||
post_message);
|
||||
err.span_label(span,
|
||||
&format!("{}the trait `{}` is not \
|
||||
implemented for `{}`",
|
||||
pre_message,
|
||||
trait_ref,
|
||||
trait_ref.self_ty()));
|
||||
|
||||
// Try to report a help message
|
||||
|
||||
|
@ -15,9 +15,9 @@ use session::Session;
|
||||
use middle;
|
||||
use hir::TraitMap;
|
||||
use hir::def::Def;
|
||||
use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
|
||||
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||
use hir::map as ast_map;
|
||||
use hir::map::{DefKey, DefPathData, DisambiguatedDefPathData};
|
||||
use hir::map::DisambiguatedDefPathData;
|
||||
use middle::free_region::FreeRegionMap;
|
||||
use middle::region::RegionMaps;
|
||||
use middle::resolve_lifetime;
|
||||
@ -627,50 +627,21 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a def-key `key` and a crate `krate`, finds the def-index
|
||||
/// that `krate` assigned to `key`. This `DefIndex` will always be
|
||||
/// relative to `krate`.
|
||||
///
|
||||
/// Returns `None` if there is no `DefIndex` with that key.
|
||||
pub fn def_index_for_def_key(self, krate: CrateNum, key: DefKey)
|
||||
-> Option<DefIndex> {
|
||||
if krate == LOCAL_CRATE {
|
||||
self.map.def_index_for_def_key(key)
|
||||
} else {
|
||||
self.sess.cstore.def_index_for_def_key(krate, key)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn retrace_path(self,
|
||||
krate: CrateNum,
|
||||
path_data: &[DisambiguatedDefPathData])
|
||||
-> Option<DefId> {
|
||||
debug!("retrace_path(path={:?}, krate={:?})", path_data, self.crate_name(krate));
|
||||
|
||||
let root_key = DefKey {
|
||||
parent: None,
|
||||
disambiguated_data: DisambiguatedDefPathData {
|
||||
data: DefPathData::CrateRoot,
|
||||
disambiguator: 0,
|
||||
},
|
||||
};
|
||||
|
||||
let root_index = self.def_index_for_def_key(krate, root_key)
|
||||
.expect("no root key?");
|
||||
|
||||
debug!("retrace_path: root_index={:?}", root_index);
|
||||
|
||||
let mut index = root_index;
|
||||
for data in path_data {
|
||||
let key = DefKey { parent: Some(index), disambiguated_data: data.clone() };
|
||||
debug!("retrace_path: key={:?}", key);
|
||||
match self.def_index_for_def_key(krate, key) {
|
||||
Some(i) => index = i,
|
||||
None => return None,
|
||||
}
|
||||
if krate == LOCAL_CRATE {
|
||||
self.map
|
||||
.definitions()
|
||||
.def_path_table()
|
||||
.retrace_path(path_data)
|
||||
.map(|def_index| DefId { krate: krate, index: def_index })
|
||||
} else {
|
||||
self.sess.cstore.retrace_path(krate, path_data)
|
||||
}
|
||||
|
||||
Some(DefId { krate: krate, index: index })
|
||||
}
|
||||
|
||||
pub fn type_parameter_def(self,
|
||||
@ -762,11 +733,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
/// reference to the context, to allow formatting values that need it.
|
||||
pub fn create_and_enter<F, R>(s: &'tcx Session,
|
||||
arenas: &'tcx CtxtArenas<'tcx>,
|
||||
trait_map: TraitMap,
|
||||
resolutions: ty::Resolutions,
|
||||
named_region_map: resolve_lifetime::NamedRegionMap,
|
||||
map: ast_map::Map<'tcx>,
|
||||
freevars: FreevarMap,
|
||||
maybe_unused_trait_imports: NodeSet,
|
||||
region_maps: RegionMaps,
|
||||
lang_items: middle::lang_items::LanguageItems,
|
||||
stability: stability::Index<'tcx>,
|
||||
@ -790,7 +759,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
item_variance_map: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
variance_computed: Cell::new(false),
|
||||
sess: s,
|
||||
trait_map: trait_map,
|
||||
trait_map: resolutions.trait_map,
|
||||
tables: RefCell::new(Tables::empty()),
|
||||
impl_trait_refs: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
trait_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
@ -802,8 +771,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
fulfilled_predicates: RefCell::new(fulfilled_predicates),
|
||||
map: map,
|
||||
mir_map: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
freevars: RefCell::new(freevars),
|
||||
maybe_unused_trait_imports: maybe_unused_trait_imports,
|
||||
freevars: RefCell::new(resolutions.freevars),
|
||||
maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports,
|
||||
item_types: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
rcache: RefCell::new(FxHashMap()),
|
||||
tc_cache: RefCell::new(FxHashMap()),
|
||||
|
@ -160,11 +160,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
self.push_krate_path(buffer, def_id.krate);
|
||||
}
|
||||
|
||||
DefPathData::InlinedRoot(ref root_path) => {
|
||||
assert!(key.parent.is_none());
|
||||
self.push_item_path(buffer, root_path.def_id);
|
||||
}
|
||||
|
||||
DefPathData::Impl => {
|
||||
self.push_impl_path(buffer, def_id);
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ pub use self::LvaluePreference::*;
|
||||
pub use self::fold::TypeFoldable;
|
||||
|
||||
use dep_graph::{self, DepNode};
|
||||
use hir::map as ast_map;
|
||||
use hir::{map as ast_map, FreevarMap, TraitMap};
|
||||
use middle;
|
||||
use hir::def::{Def, CtorKind, ExportMap};
|
||||
use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||
@ -112,6 +112,13 @@ pub struct CrateAnalysis<'tcx> {
|
||||
pub hir_ty_to_ty: NodeMap<Ty<'tcx>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Resolutions {
|
||||
pub freevars: FreevarMap,
|
||||
pub trait_map: TraitMap,
|
||||
pub maybe_unused_trait_imports: NodeSet,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum DtorKind {
|
||||
NoDtor,
|
||||
@ -2241,40 +2248,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
/// Convert a `DefId` into its fully expanded `DefPath` (every
|
||||
/// `DefId` is really just an interned def-path).
|
||||
///
|
||||
/// Note that if `id` is not local to this crate -- or is
|
||||
/// inlined into this crate -- the result will be a non-local
|
||||
/// `DefPath`.
|
||||
///
|
||||
/// This function is only safe to use when you are sure that the
|
||||
/// full def-path is accessible. Examples that are known to be
|
||||
/// safe are local def-ids or items; see `opt_def_path` for more
|
||||
/// details.
|
||||
/// Note that if `id` is not local to this crate, the result will
|
||||
// be a non-local `DefPath`.
|
||||
pub fn def_path(self, id: DefId) -> ast_map::DefPath {
|
||||
self.opt_def_path(id).unwrap_or_else(|| {
|
||||
bug!("could not load def-path for {:?}", id)
|
||||
})
|
||||
}
|
||||
|
||||
/// Convert a `DefId` into its fully expanded `DefPath` (every
|
||||
/// `DefId` is really just an interned def-path).
|
||||
///
|
||||
/// When going across crates, we do not save the full info for
|
||||
/// every cross-crate def-id, and hence we may not always be able
|
||||
/// to create a def-path. Therefore, this returns
|
||||
/// `Option<DefPath>` to cover that possibility. It will always
|
||||
/// return `Some` for local def-ids, however, as well as for
|
||||
/// items. The problems arise with "minor" def-ids like those
|
||||
/// associated with a pattern, `impl Trait`, or other internal
|
||||
/// detail to a fn.
|
||||
///
|
||||
/// Note that if `id` is not local to this crate -- or is
|
||||
/// inlined into this crate -- the result will be a non-local
|
||||
/// `DefPath`.
|
||||
pub fn opt_def_path(self, id: DefId) -> Option<ast_map::DefPath> {
|
||||
if id.is_local() {
|
||||
Some(self.map.def_path(id))
|
||||
self.map.def_path(id)
|
||||
} else {
|
||||
self.sess.cstore.relative_def_path(id)
|
||||
self.sess.cstore.def_path(id)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -267,6 +267,9 @@ pub struct TargetOptions {
|
||||
/// user-defined libraries.
|
||||
pub post_link_args: Vec<String>,
|
||||
|
||||
/// Extra arguments to pass to the external assembler (when used)
|
||||
pub asm_args: Vec<String>,
|
||||
|
||||
/// Default CPU to pass to LLVM. Corresponds to `llc -mcpu=$cpu`. Defaults
|
||||
/// to "generic".
|
||||
pub cpu: String,
|
||||
@ -394,6 +397,7 @@ impl Default for TargetOptions {
|
||||
ar: option_env!("CFG_DEFAULT_AR").unwrap_or("ar").to_string(),
|
||||
pre_link_args: Vec::new(),
|
||||
post_link_args: Vec::new(),
|
||||
asm_args: Vec::new(),
|
||||
cpu: "generic".to_string(),
|
||||
features: "".to_string(),
|
||||
dynamic_linking: false,
|
||||
@ -561,6 +565,7 @@ impl Target {
|
||||
key!(late_link_args, list);
|
||||
key!(post_link_objects, list);
|
||||
key!(post_link_args, list);
|
||||
key!(asm_args, list);
|
||||
key!(cpu);
|
||||
key!(features);
|
||||
key!(dynamic_linking, bool);
|
||||
@ -723,6 +728,7 @@ impl ToJson for Target {
|
||||
target_option_val!(late_link_args);
|
||||
target_option_val!(post_link_objects);
|
||||
target_option_val!(post_link_args);
|
||||
target_option_val!(asm_args);
|
||||
target_option_val!(cpu);
|
||||
target_option_val!(features);
|
||||
target_option_val!(dynamic_linking);
|
||||
|
@ -8,8 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use rustc::hir;
|
||||
use rustc::hir::{map as hir_map, FreevarMap, TraitMap};
|
||||
use rustc::hir::{self, map as hir_map};
|
||||
use rustc::hir::lowering::lower_crate;
|
||||
use rustc_data_structures::stable_hasher::StableHasher;
|
||||
use rustc_mir as mir;
|
||||
@ -20,7 +19,7 @@ use rustc::session::search_paths::PathKind;
|
||||
use rustc::lint;
|
||||
use rustc::middle::{self, dependency_format, stability, reachable};
|
||||
use rustc::middle::privacy::AccessLevels;
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::ty::{self, TyCtxt, Resolutions};
|
||||
use rustc::util::common::time;
|
||||
use rustc::util::nodemap::{NodeSet, NodeMap};
|
||||
use rustc_borrowck as borrowck;
|
||||
@ -59,13 +58,6 @@ use syntax_ext;
|
||||
|
||||
use derive_registrar;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Resolutions {
|
||||
pub freevars: FreevarMap,
|
||||
pub trait_map: TraitMap,
|
||||
pub maybe_unused_trait_imports: NodeSet,
|
||||
}
|
||||
|
||||
pub fn compile_input(sess: &Session,
|
||||
cstore: &CStore,
|
||||
input: &Input,
|
||||
@ -864,11 +856,9 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
||||
|
||||
TyCtxt::create_and_enter(sess,
|
||||
arenas,
|
||||
resolutions.trait_map,
|
||||
resolutions,
|
||||
named_region_map,
|
||||
hir_map,
|
||||
resolutions.freevars,
|
||||
resolutions.maybe_unused_trait_imports,
|
||||
region_map,
|
||||
lang_items,
|
||||
index,
|
||||
|
@ -15,10 +15,9 @@ pub use self::PpSourceMode::*;
|
||||
pub use self::PpMode::*;
|
||||
use self::NodesMatchingUII::*;
|
||||
|
||||
use abort_on_err;
|
||||
use driver::{self, Resolutions};
|
||||
use {abort_on_err, driver};
|
||||
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::ty::{self, TyCtxt, Resolutions};
|
||||
use rustc::cfg;
|
||||
use rustc::cfg::graphviz::LabelledCFG;
|
||||
use rustc::dep_graph::DepGraph;
|
||||
|
@ -138,11 +138,9 @@ fn test_env<F>(source_string: &str,
|
||||
let index = stability::Index::new(&ast_map);
|
||||
TyCtxt::create_and_enter(&sess,
|
||||
&arenas,
|
||||
resolutions.trait_map,
|
||||
resolutions,
|
||||
named_region_map.unwrap(),
|
||||
ast_map,
|
||||
resolutions.freevars,
|
||||
resolutions.maybe_unused_trait_imports,
|
||||
region_map,
|
||||
lang_items,
|
||||
index,
|
||||
|
@ -66,11 +66,6 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> {
|
||||
def_id,
|
||||
self.tcx.item_path_str(def_id));
|
||||
|
||||
assert!(!self.tcx.map.is_inlined_def_id(def_id),
|
||||
"cannot hash HIR for inlined def-id {:?} => {:?}",
|
||||
def_id,
|
||||
self.tcx.item_path_str(def_id));
|
||||
|
||||
Some(self.incremental_hashes_map[dep_node])
|
||||
}
|
||||
|
||||
|
@ -230,6 +230,13 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
// OpenBSD has a particular C++ runtime library name
|
||||
let stdcppname = if target.contains("openbsd") {
|
||||
"estdc++"
|
||||
} else {
|
||||
"stdc++"
|
||||
};
|
||||
|
||||
// C++ runtime library
|
||||
if !target.contains("msvc") {
|
||||
if let Some(s) = env::var_os("LLVM_STATIC_STDCPP") {
|
||||
@ -237,11 +244,11 @@ fn main() {
|
||||
let path = PathBuf::from(s);
|
||||
println!("cargo:rustc-link-search=native={}",
|
||||
path.parent().unwrap().display());
|
||||
println!("cargo:rustc-link-lib=static=stdc++");
|
||||
println!("cargo:rustc-link-lib=static={}", stdcppname);
|
||||
} else if cxxflags.contains("stdlib=libc++") {
|
||||
println!("cargo:rustc-link-lib=c++");
|
||||
} else {
|
||||
println!("cargo:rustc-link-lib=stdc++");
|
||||
println!("cargo:rustc-link-lib={}", stdcppname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -102,8 +102,6 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for SideTableEncodingIdVisitor<'a, 'b, 'tcx> {
|
||||
/// ast-map.
|
||||
pub fn decode_inlined_item<'a, 'tcx>(cdata: &CrateMetadata,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
parent_def_path: ast_map::DefPath,
|
||||
parent_did: DefId,
|
||||
ast: Ast<'tcx>,
|
||||
orig_did: DefId)
|
||||
-> &'tcx InlinedItem {
|
||||
@ -120,17 +118,9 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &CrateMetadata,
|
||||
let ii = ast.item.decode((cdata, tcx, id_ranges));
|
||||
let item_node_id = tcx.sess.next_node_id();
|
||||
let ii = ast_map::map_decoded_item(&tcx.map,
|
||||
parent_def_path,
|
||||
parent_did,
|
||||
ii,
|
||||
item_node_id);
|
||||
|
||||
let inlined_did = tcx.map.local_def_id(item_node_id);
|
||||
let ty = tcx.item_type(orig_did);
|
||||
let generics = tcx.item_generics(orig_did);
|
||||
tcx.item_types.borrow_mut().insert(inlined_did, ty);
|
||||
tcx.generics.borrow_mut().insert(inlined_did, generics);
|
||||
|
||||
for (id, entry) in ast.side_tables.decode((cdata, tcx, id_ranges)) {
|
||||
match entry {
|
||||
TableEntry::TypeRelativeDef(def) => {
|
||||
|
@ -22,6 +22,7 @@ use rustc_back::PanicStrategy;
|
||||
use rustc::session::search_paths::PathKind;
|
||||
use rustc::middle;
|
||||
use rustc::middle::cstore::{CrateStore, validate_crate_name, ExternCrate};
|
||||
use rustc::util::common::record_time;
|
||||
use rustc::util::nodemap::FxHashSet;
|
||||
use rustc::middle::cstore::NativeLibrary;
|
||||
use rustc::hir::map::Definitions;
|
||||
@ -297,10 +298,14 @@ impl<'a> CrateLoader<'a> {
|
||||
|
||||
let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span, dep_kind);
|
||||
|
||||
let def_path_table = record_time(&self.sess.perf_stats.decode_def_path_tables_time, || {
|
||||
crate_root.def_path_table.decode(&metadata)
|
||||
});
|
||||
|
||||
let mut cmeta = cstore::CrateMetadata {
|
||||
name: name,
|
||||
extern_crate: Cell::new(None),
|
||||
key_map: metadata.load_key_map(crate_root.index),
|
||||
def_path_table: def_path_table,
|
||||
proc_macros: crate_root.macro_derive_registrar.map(|_| {
|
||||
self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span)
|
||||
}),
|
||||
|
@ -16,7 +16,7 @@ use schema;
|
||||
|
||||
use rustc::dep_graph::DepGraph;
|
||||
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefIndex, DefId};
|
||||
use rustc::hir::map::DefKey;
|
||||
use rustc::hir::map::definitions::DefPathTable;
|
||||
use rustc::hir::svh::Svh;
|
||||
use rustc::middle::cstore::{DepKind, ExternCrate};
|
||||
use rustc_back::PanicStrategy;
|
||||
@ -78,7 +78,7 @@ pub struct CrateMetadata {
|
||||
/// hashmap, which gives the reverse mapping. This allows us to
|
||||
/// quickly retrace a `DefPath`, which is needed for incremental
|
||||
/// compilation support.
|
||||
pub key_map: FxHashMap<DefKey, DefIndex>,
|
||||
pub def_path_table: DefPathTable,
|
||||
|
||||
pub dep_kind: Cell<DepKind>,
|
||||
pub source: CrateSource,
|
||||
|
@ -22,8 +22,7 @@ use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||
|
||||
use rustc::dep_graph::DepNode;
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::hir::map::DefKey;
|
||||
use rustc::hir::map::{DefKey, DefPath, DisambiguatedDefPathData};
|
||||
use rustc::mir::Mir;
|
||||
use rustc::util::nodemap::{NodeSet, DefIdMap};
|
||||
use rustc_back::PanicStrategy;
|
||||
@ -336,18 +335,20 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
|
||||
self.get_crate_data(cnum).is_no_builtins()
|
||||
}
|
||||
|
||||
fn def_index_for_def_key(&self,
|
||||
cnum: CrateNum,
|
||||
def: DefKey)
|
||||
-> Option<DefIndex> {
|
||||
fn retrace_path(&self,
|
||||
cnum: CrateNum,
|
||||
path: &[DisambiguatedDefPathData])
|
||||
-> Option<DefId> {
|
||||
let cdata = self.get_crate_data(cnum);
|
||||
cdata.key_map.get(&def).cloned()
|
||||
cdata.def_path_table
|
||||
.retrace_path(&path)
|
||||
.map(|index| DefId { krate: cnum, index: index })
|
||||
}
|
||||
|
||||
/// Returns the `DefKey` for a given `DefId`. This indicates the
|
||||
/// parent `DefId` as well as some idea of what kind of data the
|
||||
/// `DefId` refers to.
|
||||
fn def_key(&self, def: DefId) -> hir_map::DefKey {
|
||||
fn def_key(&self, def: DefId) -> DefKey {
|
||||
// Note: loading the def-key (or def-path) for a def-id is not
|
||||
// a *read* of its metadata. This is because the def-id is
|
||||
// really just an interned shorthand for a def-path, which is the
|
||||
@ -357,7 +358,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
|
||||
self.get_crate_data(def.krate).def_key(def.index)
|
||||
}
|
||||
|
||||
fn relative_def_path(&self, def: DefId) -> Option<hir_map::DefPath> {
|
||||
fn def_path(&self, def: DefId) -> DefPath {
|
||||
// See `Note` above in `def_key()` for why this read is
|
||||
// commented out:
|
||||
//
|
||||
@ -418,8 +419,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
|
||||
ident: ast::Ident::with_empty_ctxt(name),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: local_span,
|
||||
imported_from: None, // FIXME
|
||||
allow_internal_unstable: attr::contains_name(&attrs, "allow_internal_unstable"),
|
||||
attrs: attrs,
|
||||
body: body,
|
||||
})
|
||||
|
@ -12,12 +12,9 @@
|
||||
|
||||
use astencode::decode_inlined_item;
|
||||
use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary};
|
||||
use index::Index;
|
||||
use schema::*;
|
||||
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::hir::map::{DefKey, DefPathData};
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
use rustc::hir::map::{DefKey, DefPath, DefPathData};
|
||||
use rustc::hir;
|
||||
use rustc::hir::intravisit::IdRange;
|
||||
|
||||
@ -456,14 +453,6 @@ impl<'a, 'tcx> MetadataBlob {
|
||||
Lazy::with_position(pos).decode(self)
|
||||
}
|
||||
|
||||
/// Go through each item in the metadata and create a map from that
|
||||
/// item's def-key to the item's DefIndex.
|
||||
pub fn load_key_map(&self, index: LazySeq<Index>) -> FxHashMap<DefKey, DefIndex> {
|
||||
index.iter_enumerated(self.raw_bytes())
|
||||
.map(|(index, item)| (item.decode(self).def_key.decode(self), index))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn list_crate_metadata(&self, out: &mut io::Write) -> io::Result<()> {
|
||||
write!(out, "=External Dependencies=\n")?;
|
||||
let root = self.get_root();
|
||||
@ -543,9 +532,8 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
}
|
||||
}
|
||||
|
||||
fn item_name(&self, item: &Entry<'tcx>) -> ast::Name {
|
||||
item.def_key
|
||||
.decode(self)
|
||||
fn item_name(&self, item_index: DefIndex) -> ast::Name {
|
||||
self.def_key(item_index)
|
||||
.disambiguated_data
|
||||
.data
|
||||
.get_opt_name()
|
||||
@ -578,7 +566,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
ty::TraitDef::new(self.local_def_id(item_id),
|
||||
data.unsafety,
|
||||
data.paren_sugar,
|
||||
self.def_path(item_id).unwrap().deterministic_hash(tcx))
|
||||
self.def_path(item_id).deterministic_hash(tcx))
|
||||
}
|
||||
|
||||
fn get_variant(&self,
|
||||
@ -594,12 +582,12 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
|
||||
(ty::VariantDef {
|
||||
did: self.local_def_id(data.struct_ctor.unwrap_or(index)),
|
||||
name: self.item_name(item),
|
||||
name: self.item_name(index),
|
||||
fields: item.children.decode(self).map(|index| {
|
||||
let f = self.entry(index);
|
||||
ty::FieldDef {
|
||||
did: self.local_def_id(index),
|
||||
name: self.item_name(&f),
|
||||
name: self.item_name(index),
|
||||
vis: f.visibility
|
||||
}
|
||||
}).collect(),
|
||||
@ -771,7 +759,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
if let Some(def) = self.get_def(child_index) {
|
||||
callback(def::Export {
|
||||
def: def,
|
||||
name: self.item_name(&self.entry(child_index)),
|
||||
name: self.item_name(child_index),
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -783,7 +771,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let def_key = child.def_key.decode(self);
|
||||
let def_key = self.def_key(child_index);
|
||||
if let (Some(def), Some(name)) =
|
||||
(self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) {
|
||||
callback(def::Export {
|
||||
@ -839,12 +827,9 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
if self.is_proc_macro(id) { return None; }
|
||||
let item_doc = self.entry(id);
|
||||
let item_did = self.local_def_id(id);
|
||||
let parent_def_id = self.local_def_id(self.def_key(id).parent.unwrap());
|
||||
let mut parent_def_path = self.def_path(id).unwrap();
|
||||
parent_def_path.data.pop();
|
||||
item_doc.ast.map(|ast| {
|
||||
let ast = ast.decode(self);
|
||||
decode_inlined_item(self, tcx, parent_def_path, parent_def_id, ast, item_did)
|
||||
decode_inlined_item(self, tcx, ast, item_did)
|
||||
})
|
||||
}
|
||||
|
||||
@ -889,7 +874,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
pub fn get_associated_item(&self, id: DefIndex) -> Option<ty::AssociatedItem> {
|
||||
let item = self.entry(id);
|
||||
let parent_and_name = || {
|
||||
let def_key = item.def_key.decode(self);
|
||||
let def_key = self.def_key(id);
|
||||
(self.local_def_id(def_key.parent.unwrap()),
|
||||
def_key.disambiguated_data.data.get_opt_name().unwrap())
|
||||
};
|
||||
@ -966,7 +951,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
// we assume that someone passing in a tuple struct ctor is actually wanting to
|
||||
// look at the definition
|
||||
let mut item = self.entry(node_id);
|
||||
let def_key = item.def_key.decode(self);
|
||||
let def_key = self.def_key(node_id);
|
||||
if def_key.disambiguated_data.data == DefPathData::StructCtor {
|
||||
item = self.entry(def_key.parent.unwrap());
|
||||
}
|
||||
@ -977,7 +962,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
self.entry(id)
|
||||
.children
|
||||
.decode(self)
|
||||
.map(|index| self.item_name(&self.entry(index)))
|
||||
.map(|index| self.item_name(index))
|
||||
.collect()
|
||||
}
|
||||
|
||||
@ -1039,7 +1024,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
}
|
||||
|
||||
pub fn get_trait_of_item(&self, id: DefIndex) -> Option<DefId> {
|
||||
self.entry(id).def_key.decode(self).parent.and_then(|parent_index| {
|
||||
self.def_key(id).parent.and_then(|parent_index| {
|
||||
match self.entry(parent_index).kind {
|
||||
EntryKind::Trait(_) => Some(self.local_def_id(parent_index)),
|
||||
_ => None,
|
||||
@ -1085,7 +1070,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
pub fn get_macro(&self, id: DefIndex) -> (ast::Name, MacroDef) {
|
||||
let entry = self.entry(id);
|
||||
match entry.kind {
|
||||
EntryKind::MacroDef(macro_def) => (self.item_name(&entry), macro_def.decode(self)),
|
||||
EntryKind::MacroDef(macro_def) => (self.item_name(id), macro_def.decode(self)),
|
||||
_ => bug!(),
|
||||
}
|
||||
}
|
||||
@ -1138,32 +1123,14 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn def_key(&self, id: DefIndex) -> hir_map::DefKey {
|
||||
debug!("def_key: id={:?}", id);
|
||||
if self.is_proc_macro(id) {
|
||||
let name = self.proc_macros.as_ref().unwrap()[id.as_usize() - 1].0;
|
||||
hir_map::DefKey {
|
||||
parent: Some(CRATE_DEF_INDEX),
|
||||
disambiguated_data: hir_map::DisambiguatedDefPathData {
|
||||
data: hir_map::DefPathData::MacroDef(name.as_str()),
|
||||
disambiguator: 0,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
self.entry(id).def_key.decode(self)
|
||||
}
|
||||
pub fn def_key(&self, index: DefIndex) -> DefKey {
|
||||
self.def_path_table.def_key(index)
|
||||
}
|
||||
|
||||
// Returns the path leading to the thing with this `id`. Note that
|
||||
// some def-ids don't wind up in the metadata, so `def_path` sometimes
|
||||
// returns `None`
|
||||
pub fn def_path(&self, id: DefIndex) -> Option<hir_map::DefPath> {
|
||||
// Returns the path leading to the thing with this `id`.
|
||||
pub fn def_path(&self, id: DefIndex) -> DefPath {
|
||||
debug!("def_path(id={:?})", id);
|
||||
if self.is_proc_macro(id) || self.maybe_entry(id).is_some() {
|
||||
Some(hir_map::DefPath::make(self.cnum, id, |parent| self.def_key(parent)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
DefPath::make(self.cnum, id, |parent| self.def_path_table.def_key(parent))
|
||||
}
|
||||
|
||||
/// Imports the codemap from an external crate into the codemap of the crate
|
||||
|
@ -16,6 +16,7 @@ use rustc::middle::cstore::{InlinedItemRef, LinkMeta};
|
||||
use rustc::middle::cstore::{LinkagePreference, NativeLibrary};
|
||||
use rustc::hir::def;
|
||||
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId};
|
||||
use rustc::hir::map::definitions::DefPathTable;
|
||||
use rustc::middle::dependency_format::Linkage;
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::mir;
|
||||
@ -233,13 +234,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// For every DefId that we create a metadata item for, we include a
|
||||
/// serialized copy of its DefKey, which allows us to recreate a path.
|
||||
fn encode_def_key(&mut self, def_id: DefId) -> Lazy<hir::map::DefKey> {
|
||||
let tcx = self.tcx;
|
||||
self.lazy(&tcx.map.def_key(def_id))
|
||||
}
|
||||
|
||||
fn encode_item_variances(&mut self, def_id: DefId) -> LazySeq<ty::Variance> {
|
||||
let tcx = self.tcx;
|
||||
self.lazy_seq(tcx.item_variances(def_id).iter().cloned())
|
||||
@ -276,7 +270,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
kind: EntryKind::Variant(self.lazy(&data)),
|
||||
visibility: enum_vis.simplify(),
|
||||
span: self.lazy(&tcx.def_span(def_id)),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
attributes: self.encode_attributes(&tcx.get_attrs(def_id)),
|
||||
children: self.lazy_seq(variant.fields.iter().map(|f| {
|
||||
assert!(f.did.is_local());
|
||||
@ -315,7 +308,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
kind: EntryKind::Mod(self.lazy(&data)),
|
||||
visibility: vis.simplify(),
|
||||
span: self.lazy(&md.inner),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
attributes: self.encode_attributes(attrs),
|
||||
children: self.lazy_seq(md.item_ids.iter().map(|item_id| {
|
||||
tcx.map.local_def_id(item_id.id).index
|
||||
@ -396,7 +388,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
kind: EntryKind::Field,
|
||||
visibility: field.vis.simplify(),
|
||||
span: self.lazy(&tcx.def_span(def_id)),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
attributes: self.encode_attributes(&variant_data.fields()[field_index].attrs),
|
||||
children: LazySeq::empty(),
|
||||
stability: self.encode_stability(def_id),
|
||||
@ -430,7 +421,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
kind: EntryKind::Struct(self.lazy(&data)),
|
||||
visibility: struct_vis.simplify(),
|
||||
span: self.lazy(&tcx.def_span(def_id)),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
attributes: LazySeq::empty(),
|
||||
children: LazySeq::empty(),
|
||||
stability: self.encode_stability(def_id),
|
||||
@ -497,7 +487,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
kind: kind,
|
||||
visibility: trait_item.vis.simplify(),
|
||||
span: self.lazy(&ast_item.span),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
attributes: self.encode_attributes(&ast_item.attrs),
|
||||
children: LazySeq::empty(),
|
||||
stability: self.encode_stability(def_id),
|
||||
@ -587,7 +576,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
kind: kind,
|
||||
visibility: impl_item.vis.simplify(),
|
||||
span: self.lazy(&ast_item.span),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
attributes: self.encode_attributes(&ast_item.attrs),
|
||||
children: LazySeq::empty(),
|
||||
stability: self.encode_stability(def_id),
|
||||
@ -750,7 +738,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
kind: kind,
|
||||
visibility: item.vis.simplify(),
|
||||
span: self.lazy(&item.span),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
attributes: self.encode_attributes(&item.attrs),
|
||||
children: match item.node {
|
||||
hir::ItemForeignMod(ref fm) => {
|
||||
@ -858,14 +845,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
|
||||
/// Serialize the text of exported macros
|
||||
fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) -> Entry<'tcx> {
|
||||
let def_id = self.tcx.map.local_def_id(macro_def.id);
|
||||
Entry {
|
||||
kind: EntryKind::MacroDef(self.lazy(&MacroDef {
|
||||
body: ::syntax::print::pprust::tts_to_string(¯o_def.body)
|
||||
})),
|
||||
visibility: ty::Visibility::Public,
|
||||
span: self.lazy(¯o_def.span),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
|
||||
attributes: self.encode_attributes(¯o_def.attrs),
|
||||
children: LazySeq::empty(),
|
||||
@ -967,7 +952,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
kind: kind,
|
||||
visibility: nitem.vis.simplify(),
|
||||
span: self.lazy(&nitem.span),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
attributes: self.encode_attributes(&nitem.attrs),
|
||||
children: LazySeq::empty(),
|
||||
stability: self.encode_stability(def_id),
|
||||
@ -1050,7 +1034,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
kind: EntryKind::Type,
|
||||
visibility: ty::Visibility::Public,
|
||||
span: self.lazy(&tcx.def_span(def_id)),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
attributes: LazySeq::empty(),
|
||||
children: LazySeq::empty(),
|
||||
stability: None,
|
||||
@ -1079,7 +1062,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
kind: EntryKind::Closure(self.lazy(&data)),
|
||||
visibility: ty::Visibility::Public,
|
||||
span: self.lazy(&tcx.def_span(def_id)),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
attributes: self.encode_attributes(&tcx.get_attrs(def_id)),
|
||||
children: LazySeq::empty(),
|
||||
stability: None,
|
||||
@ -1179,6 +1161,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
})
|
||||
.map(|filemap| &**filemap))
|
||||
}
|
||||
|
||||
fn encode_def_path_table(&mut self) -> Lazy<DefPathTable> {
|
||||
let definitions = self.tcx.map.definitions();
|
||||
self.lazy(definitions.def_path_table())
|
||||
}
|
||||
}
|
||||
|
||||
struct ImplVisitor<'a, 'tcx: 'a> {
|
||||
@ -1276,6 +1263,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
let codemap = self.encode_codemap();
|
||||
let codemap_bytes = self.position() - i;
|
||||
|
||||
// Encode DefPathTable
|
||||
i = self.position();
|
||||
let def_path_table = self.encode_def_path_table();
|
||||
let def_path_table_bytes = self.position() - i;
|
||||
|
||||
// Encode the def IDs of impls, for coherence checking.
|
||||
i = self.position();
|
||||
let impls = self.encode_impls();
|
||||
@ -1321,6 +1313,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
lang_items_missing: lang_items_missing,
|
||||
native_libraries: native_libraries,
|
||||
codemap: codemap,
|
||||
def_path_table: def_path_table,
|
||||
impls: impls,
|
||||
exported_symbols: exported_symbols,
|
||||
index: index,
|
||||
@ -1343,6 +1336,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
println!(" codemap bytes: {}", codemap_bytes);
|
||||
println!(" impl bytes: {}", impl_bytes);
|
||||
println!(" exp. symbols bytes: {}", exported_symbols_bytes);
|
||||
println!(" def-path table bytes: {}", def_path_table_bytes);
|
||||
println!(" item bytes: {}", item_bytes);
|
||||
println!(" index bytes: {}", index_bytes);
|
||||
println!(" zero bytes: {}", zero_bytes);
|
||||
|
@ -179,6 +179,7 @@ pub struct CrateRoot {
|
||||
pub lang_items_missing: LazySeq<lang_items::LangItem>,
|
||||
pub native_libraries: LazySeq<NativeLibrary>,
|
||||
pub codemap: LazySeq<syntax_pos::FileMap>,
|
||||
pub def_path_table: Lazy<hir::map::definitions::DefPathTable>,
|
||||
pub impls: LazySeq<TraitImpls>,
|
||||
pub exported_symbols: LazySeq<DefIndex>,
|
||||
pub index: LazySeq<index::Index>,
|
||||
@ -202,7 +203,6 @@ pub struct Entry<'tcx> {
|
||||
pub kind: EntryKind<'tcx>,
|
||||
pub visibility: ty::Visibility,
|
||||
pub span: Lazy<Span>,
|
||||
pub def_key: Lazy<hir::map::DefKey>,
|
||||
pub attributes: LazySeq<ast::Attribute>,
|
||||
pub children: LazySeq<DefIndex>,
|
||||
pub stability: Option<Lazy<attr::Stability>>,
|
||||
|
@ -171,7 +171,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
match item.node {
|
||||
ItemKind::Use(ref view_path) => {
|
||||
let path = view_path.node.path();
|
||||
if !path.segments.iter().all(|segment| segment.parameters.is_empty()) {
|
||||
if path.segments.iter().any(|segment| segment.parameters.is_some()) {
|
||||
self.err_handler()
|
||||
.span_err(path.span, "type or lifetime parameters in import path");
|
||||
}
|
||||
@ -275,7 +275,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
fn visit_vis(&mut self, vis: &'a Visibility) {
|
||||
match *vis {
|
||||
Visibility::Restricted { ref path, .. } => {
|
||||
if !path.segments.iter().all(|segment| segment.parameters.is_empty()) {
|
||||
if !path.segments.iter().all(|segment| segment.parameters.is_none()) {
|
||||
self.err_handler()
|
||||
.span_err(path.span, "type or lifetime parameters in visibility path");
|
||||
}
|
||||
|
@ -16,7 +16,8 @@
|
||||
use macros::{InvocationData, LegacyScope};
|
||||
use resolve_imports::ImportDirective;
|
||||
use resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport};
|
||||
use {Resolver, Module, ModuleS, ModuleKind, NameBinding, NameBindingKind, ToNameBinding};
|
||||
use {Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, ToNameBinding};
|
||||
use {Resolver, ResolverArenas};
|
||||
use Namespace::{self, TypeNS, ValueNS, MacroNS};
|
||||
use {resolve_error, resolve_struct_error, ResolutionError};
|
||||
|
||||
@ -28,7 +29,7 @@ use rustc::ty;
|
||||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use syntax::ast::Name;
|
||||
use syntax::ast::{Name, Ident};
|
||||
use syntax::attr;
|
||||
|
||||
use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind};
|
||||
@ -45,24 +46,24 @@ use syntax::visit::{self, Visitor};
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
|
||||
impl<'a> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, Mark) {
|
||||
fn to_name_binding(self) -> NameBinding<'a> {
|
||||
NameBinding {
|
||||
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
|
||||
arenas.alloc_name_binding(NameBinding {
|
||||
kind: NameBindingKind::Module(self.0),
|
||||
vis: self.1,
|
||||
span: self.2,
|
||||
expansion: self.3,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark) {
|
||||
fn to_name_binding(self) -> NameBinding<'a> {
|
||||
NameBinding {
|
||||
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
|
||||
arenas.alloc_name_binding(NameBinding {
|
||||
kind: NameBindingKind::Def(self.0),
|
||||
vis: self.1,
|
||||
span: self.2,
|
||||
expansion: self.3,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,15 +74,15 @@ struct LegacyMacroImports {
|
||||
reexports: Vec<(Name, Span)>,
|
||||
}
|
||||
|
||||
impl<'b> Resolver<'b> {
|
||||
impl<'a> Resolver<'a> {
|
||||
/// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
|
||||
/// otherwise, reports an error.
|
||||
fn define<T>(&mut self, parent: Module<'b>, name: Name, ns: Namespace, def: T)
|
||||
where T: ToNameBinding<'b>,
|
||||
fn define<T>(&mut self, parent: Module<'a>, ident: Ident, ns: Namespace, def: T)
|
||||
where T: ToNameBinding<'a>,
|
||||
{
|
||||
let binding = def.to_name_binding();
|
||||
if let Err(old_binding) = self.try_define(parent, name, ns, binding.clone()) {
|
||||
self.report_conflict(parent, name, ns, old_binding, &binding);
|
||||
let binding = def.to_name_binding(self.arenas);
|
||||
if let Err(old_binding) = self.try_define(parent, ident, ns, binding) {
|
||||
self.report_conflict(parent, ident, ns, old_binding, &binding);
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,7 +103,7 @@ impl<'b> Resolver<'b> {
|
||||
/// Constructs the reduced graph for one item.
|
||||
fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
|
||||
let parent = self.current_module;
|
||||
let name = item.ident.name;
|
||||
let ident = item.ident;
|
||||
let sp = item.span;
|
||||
let vis = self.resolve_visibility(&item.vis);
|
||||
|
||||
@ -157,8 +158,8 @@ impl<'b> Resolver<'b> {
|
||||
}
|
||||
|
||||
let subclass = SingleImport {
|
||||
target: binding.name,
|
||||
source: source.name,
|
||||
target: binding,
|
||||
source: source,
|
||||
result: self.per_ns(|_, _| Cell::new(Err(Undetermined))),
|
||||
};
|
||||
self.add_import_directive(
|
||||
@ -187,13 +188,13 @@ impl<'b> Resolver<'b> {
|
||||
|
||||
for source_item in source_items {
|
||||
let node = source_item.node;
|
||||
let (module_path, name, rename) = {
|
||||
let (module_path, ident, rename) = {
|
||||
if node.name.name != keywords::SelfValue.name() {
|
||||
let rename = node.rename.unwrap_or(node.name).name;
|
||||
(module_path.clone(), node.name.name, rename)
|
||||
let rename = node.rename.unwrap_or(node.name);
|
||||
(module_path.clone(), node.name, rename)
|
||||
} else {
|
||||
let name = match module_path.last() {
|
||||
Some(ident) => ident.name,
|
||||
let ident = match module_path.last() {
|
||||
Some(&ident) => ident,
|
||||
None => {
|
||||
resolve_error(
|
||||
self,
|
||||
@ -205,13 +206,13 @@ impl<'b> Resolver<'b> {
|
||||
}
|
||||
};
|
||||
let module_path = module_path.split_last().unwrap().1;
|
||||
let rename = node.rename.map(|i| i.name).unwrap_or(name);
|
||||
(module_path.to_vec(), name, rename)
|
||||
let rename = node.rename.unwrap_or(ident);
|
||||
(module_path.to_vec(), ident, rename)
|
||||
}
|
||||
};
|
||||
let subclass = SingleImport {
|
||||
target: rename,
|
||||
source: name,
|
||||
source: ident,
|
||||
result: self.per_ns(|_, _| Cell::new(Err(Undetermined))),
|
||||
};
|
||||
let id = source_item.node.id;
|
||||
@ -238,8 +239,8 @@ impl<'b> Resolver<'b> {
|
||||
// n.b. we don't need to look at the path option here, because cstore already did
|
||||
let crate_id = self.session.cstore.extern_mod_stmt_cnum(item.id).unwrap();
|
||||
let module = self.get_extern_crate_root(crate_id);
|
||||
let binding = (module, ty::Visibility::Public, sp, expansion).to_name_binding();
|
||||
let binding = self.arenas.alloc_name_binding(binding);
|
||||
let binding =
|
||||
(module, ty::Visibility::Public, sp, expansion).to_name_binding(self.arenas);
|
||||
let directive = self.arenas.alloc_import_directive(ImportDirective {
|
||||
id: item.id,
|
||||
parent: parent,
|
||||
@ -251,7 +252,7 @@ impl<'b> Resolver<'b> {
|
||||
expansion: expansion,
|
||||
});
|
||||
let imported_binding = self.import(binding, directive);
|
||||
self.define(parent, name, TypeNS, imported_binding);
|
||||
self.define(parent, ident, TypeNS, imported_binding);
|
||||
self.populate_module_if_necessary(module);
|
||||
self.process_legacy_macro_imports(item, module, expansion);
|
||||
}
|
||||
@ -260,14 +261,14 @@ impl<'b> Resolver<'b> {
|
||||
|
||||
ItemKind::Mod(..) => {
|
||||
let def = Def::Mod(self.definitions.local_def_id(item.id));
|
||||
let module = self.arenas.alloc_module(ModuleS {
|
||||
let module = self.arenas.alloc_module(ModuleData {
|
||||
no_implicit_prelude: parent.no_implicit_prelude || {
|
||||
attr::contains_name(&item.attrs, "no_implicit_prelude")
|
||||
},
|
||||
normal_ancestor_id: Some(item.id),
|
||||
..ModuleS::new(Some(parent), ModuleKind::Def(def, name))
|
||||
..ModuleData::new(Some(parent), ModuleKind::Def(def, ident.name))
|
||||
});
|
||||
self.define(parent, name, TypeNS, (module, vis, sp, expansion));
|
||||
self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
|
||||
self.module_map.insert(item.id, module);
|
||||
|
||||
// Descend into the module.
|
||||
@ -280,27 +281,27 @@ impl<'b> Resolver<'b> {
|
||||
ItemKind::Static(_, m, _) => {
|
||||
let mutbl = m == Mutability::Mutable;
|
||||
let def = Def::Static(self.definitions.local_def_id(item.id), mutbl);
|
||||
self.define(parent, name, ValueNS, (def, vis, sp, expansion));
|
||||
self.define(parent, ident, ValueNS, (def, vis, sp, expansion));
|
||||
}
|
||||
ItemKind::Const(..) => {
|
||||
let def = Def::Const(self.definitions.local_def_id(item.id));
|
||||
self.define(parent, name, ValueNS, (def, vis, sp, expansion));
|
||||
self.define(parent, ident, ValueNS, (def, vis, sp, expansion));
|
||||
}
|
||||
ItemKind::Fn(..) => {
|
||||
let def = Def::Fn(self.definitions.local_def_id(item.id));
|
||||
self.define(parent, name, ValueNS, (def, vis, sp, expansion));
|
||||
self.define(parent, ident, ValueNS, (def, vis, sp, expansion));
|
||||
}
|
||||
|
||||
// These items live in the type namespace.
|
||||
ItemKind::Ty(..) => {
|
||||
let def = Def::TyAlias(self.definitions.local_def_id(item.id));
|
||||
self.define(parent, name, TypeNS, (def, vis, sp, expansion));
|
||||
self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
|
||||
}
|
||||
|
||||
ItemKind::Enum(ref enum_definition, _) => {
|
||||
let def = Def::Enum(self.definitions.local_def_id(item.id));
|
||||
let module = self.new_module(parent, ModuleKind::Def(def, name), true);
|
||||
self.define(parent, name, TypeNS, (module, vis, sp, expansion));
|
||||
let module = self.new_module(parent, ModuleKind::Def(def, ident.name), true);
|
||||
self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
|
||||
|
||||
for variant in &(*enum_definition).variants {
|
||||
self.build_reduced_graph_for_variant(variant, module, vis, expansion);
|
||||
@ -311,14 +312,14 @@ impl<'b> Resolver<'b> {
|
||||
ItemKind::Struct(ref struct_def, _) => {
|
||||
// Define a name in the type namespace.
|
||||
let def = Def::Struct(self.definitions.local_def_id(item.id));
|
||||
self.define(parent, name, TypeNS, (def, vis, sp, expansion));
|
||||
self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
|
||||
|
||||
// If this is a tuple or unit struct, define a name
|
||||
// in the value namespace as well.
|
||||
if !struct_def.is_struct() {
|
||||
let ctor_def = Def::StructCtor(self.definitions.local_def_id(struct_def.id()),
|
||||
CtorKind::from_ast(struct_def));
|
||||
self.define(parent, name, ValueNS, (ctor_def, vis, sp, expansion));
|
||||
self.define(parent, ident, ValueNS, (ctor_def, vis, sp, expansion));
|
||||
}
|
||||
|
||||
// Record field names for error reporting.
|
||||
@ -332,7 +333,7 @@ impl<'b> Resolver<'b> {
|
||||
|
||||
ItemKind::Union(ref vdata, _) => {
|
||||
let def = Def::Union(self.definitions.local_def_id(item.id));
|
||||
self.define(parent, name, TypeNS, (def, vis, sp, expansion));
|
||||
self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
|
||||
|
||||
// Record field names for error reporting.
|
||||
let field_names = vdata.fields().iter().filter_map(|field| {
|
||||
@ -350,8 +351,8 @@ impl<'b> Resolver<'b> {
|
||||
|
||||
// Add all the items within to a new module.
|
||||
let module =
|
||||
self.new_module(parent, ModuleKind::Def(Def::Trait(def_id), name), true);
|
||||
self.define(parent, name, TypeNS, (module, vis, sp, expansion));
|
||||
self.new_module(parent, ModuleKind::Def(Def::Trait(def_id), ident.name), true);
|
||||
self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
|
||||
self.current_module = module;
|
||||
}
|
||||
ItemKind::Mac(_) => panic!("unexpanded macro in resolve!"),
|
||||
@ -362,29 +363,26 @@ impl<'b> Resolver<'b> {
|
||||
// type and value namespaces.
|
||||
fn build_reduced_graph_for_variant(&mut self,
|
||||
variant: &Variant,
|
||||
parent: Module<'b>,
|
||||
parent: Module<'a>,
|
||||
vis: ty::Visibility,
|
||||
expansion: Mark) {
|
||||
let name = variant.node.name.name;
|
||||
let ident = variant.node.name;
|
||||
let def_id = self.definitions.local_def_id(variant.node.data.id());
|
||||
|
||||
// Define a name in the type namespace.
|
||||
let def = Def::Variant(def_id);
|
||||
self.define(parent, name, TypeNS, (def, vis, variant.span, expansion));
|
||||
self.define(parent, ident, TypeNS, (def, vis, variant.span, expansion));
|
||||
|
||||
// Define a constructor name in the value namespace.
|
||||
// Braced variants, unlike structs, generate unusable names in
|
||||
// value namespace, they are reserved for possible future use.
|
||||
let ctor_kind = CtorKind::from_ast(&variant.node.data);
|
||||
let ctor_def = Def::VariantCtor(def_id, ctor_kind);
|
||||
self.define(parent, name, ValueNS, (ctor_def, vis, variant.span, expansion));
|
||||
self.define(parent, ident, ValueNS, (ctor_def, vis, variant.span, expansion));
|
||||
}
|
||||
|
||||
/// Constructs the reduced graph for one foreign item.
|
||||
fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem, expansion: Mark) {
|
||||
let parent = self.current_module;
|
||||
let name = item.ident.name;
|
||||
|
||||
let def = match item.node {
|
||||
ForeignItemKind::Fn(..) => {
|
||||
Def::Fn(self.definitions.local_def_id(item.id))
|
||||
@ -393,8 +391,9 @@ impl<'b> Resolver<'b> {
|
||||
Def::Static(self.definitions.local_def_id(item.id), m)
|
||||
}
|
||||
};
|
||||
let parent = self.current_module;
|
||||
let vis = self.resolve_visibility(&item.vis);
|
||||
self.define(parent, name, ValueNS, (def, vis, item.span, expansion));
|
||||
self.define(parent, item.ident, ValueNS, (def, vis, item.span, expansion));
|
||||
}
|
||||
|
||||
fn build_reduced_graph_for_block(&mut self, block: &Block) {
|
||||
@ -413,8 +412,8 @@ impl<'b> Resolver<'b> {
|
||||
}
|
||||
|
||||
/// Builds the reduced graph for a single item in an external crate.
|
||||
fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>, child: Export) {
|
||||
let name = child.name;
|
||||
fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, child: Export) {
|
||||
let ident = Ident::with_empty_ctxt(child.name);
|
||||
let def = child.def;
|
||||
let def_id = def.def_id();
|
||||
let vis = match def {
|
||||
@ -425,25 +424,25 @@ impl<'b> Resolver<'b> {
|
||||
|
||||
match def {
|
||||
Def::Mod(..) | Def::Enum(..) => {
|
||||
let module = self.new_module(parent, ModuleKind::Def(def, name), false);
|
||||
self.define(parent, name, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
|
||||
let module = self.new_module(parent, ModuleKind::Def(def, ident.name), false);
|
||||
self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
|
||||
}
|
||||
Def::Variant(..) => {
|
||||
self.define(parent, name, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
}
|
||||
Def::VariantCtor(..) => {
|
||||
self.define(parent, name, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
}
|
||||
Def::Fn(..) |
|
||||
Def::Static(..) |
|
||||
Def::Const(..) |
|
||||
Def::AssociatedConst(..) |
|
||||
Def::Method(..) => {
|
||||
self.define(parent, name, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
}
|
||||
Def::Trait(..) => {
|
||||
let module = self.new_module(parent, ModuleKind::Def(def, name), false);
|
||||
self.define(parent, name, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
|
||||
let module = self.new_module(parent, ModuleKind::Def(def, ident.name), false);
|
||||
self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
|
||||
|
||||
// If this is a trait, add all the trait item names to the trait info.
|
||||
let trait_item_def_ids = self.session.cstore.associated_item_def_ids(def_id);
|
||||
@ -455,27 +454,27 @@ impl<'b> Resolver<'b> {
|
||||
}
|
||||
}
|
||||
Def::TyAlias(..) | Def::AssociatedTy(..) => {
|
||||
self.define(parent, name, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
}
|
||||
Def::Struct(..) => {
|
||||
self.define(parent, name, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
|
||||
// Record field names for error reporting.
|
||||
let field_names = self.session.cstore.struct_field_names(def_id);
|
||||
self.insert_field_names(def_id, field_names);
|
||||
}
|
||||
Def::StructCtor(..) => {
|
||||
self.define(parent, name, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
}
|
||||
Def::Union(..) => {
|
||||
self.define(parent, name, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
|
||||
// Record field names for error reporting.
|
||||
let field_names = self.session.cstore.struct_field_names(def_id);
|
||||
self.insert_field_names(def_id, field_names);
|
||||
}
|
||||
Def::Macro(..) => {
|
||||
self.define(parent, name, MacroNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
self.define(parent, ident, MacroNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
}
|
||||
Def::Local(..) |
|
||||
Def::PrimTy(..) |
|
||||
@ -489,14 +488,15 @@ impl<'b> Resolver<'b> {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_extern_crate_root(&mut self, cnum: CrateNum) -> Module<'b> {
|
||||
fn get_extern_crate_root(&mut self, cnum: CrateNum) -> Module<'a> {
|
||||
let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
|
||||
let name = self.session.cstore.crate_name(cnum);
|
||||
let macros_only = self.session.cstore.dep_kind(cnum).macros_only();
|
||||
let arenas = self.arenas;
|
||||
*self.extern_crate_roots.entry((cnum, macros_only)).or_insert_with(|| {
|
||||
arenas.alloc_module(ModuleS {
|
||||
arenas.alloc_module(ModuleData {
|
||||
populated: Cell::new(false),
|
||||
..ModuleS::new(None, ModuleKind::Def(Def::Mod(def_id), keywords::Invalid.name()))
|
||||
..ModuleData::new(None, ModuleKind::Def(Def::Mod(def_id), name))
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -532,7 +532,7 @@ impl<'b> Resolver<'b> {
|
||||
|
||||
/// Ensures that the reduced graph rooted at the given external module
|
||||
/// is built, building it if it is not.
|
||||
pub fn populate_module_if_necessary(&mut self, module: Module<'b>) {
|
||||
pub fn populate_module_if_necessary(&mut self, module: Module<'a>) {
|
||||
if module.populated.get() { return }
|
||||
for child in self.session.cstore.item_children(module.def_id().unwrap()) {
|
||||
self.build_reduced_graph_for_external_crate_def(module, child);
|
||||
@ -542,7 +542,7 @@ impl<'b> Resolver<'b> {
|
||||
|
||||
fn legacy_import_macro(&mut self,
|
||||
name: Name,
|
||||
binding: &'b NameBinding<'b>,
|
||||
binding: &'a NameBinding<'a>,
|
||||
span: Span,
|
||||
allow_shadowing: bool) {
|
||||
self.used_crates.insert(binding.def().def_id().krate);
|
||||
@ -555,7 +555,7 @@ impl<'b> Resolver<'b> {
|
||||
}
|
||||
}
|
||||
|
||||
fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'b>, expansion: Mark) {
|
||||
fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>, expansion: Mark) {
|
||||
let allow_shadowing = expansion == Mark::root();
|
||||
let legacy_imports = self.legacy_macro_imports(&item.attrs);
|
||||
let cnum = module.def_id().unwrap().krate;
|
||||
@ -574,12 +574,13 @@ impl<'b> Resolver<'b> {
|
||||
}
|
||||
|
||||
if let Some(span) = legacy_imports.import_all {
|
||||
module.for_each_child(|name, ns, binding| if ns == MacroNS {
|
||||
self.legacy_import_macro(name, binding, span, allow_shadowing);
|
||||
module.for_each_child(|ident, ns, binding| if ns == MacroNS {
|
||||
self.legacy_import_macro(ident.name, binding, span, allow_shadowing);
|
||||
});
|
||||
} else {
|
||||
for (name, span) in legacy_imports.imports {
|
||||
let result = self.resolve_name_in_module(module, name, MacroNS, false, None);
|
||||
let ident = Ident::with_empty_ctxt(name);
|
||||
let result = self.resolve_ident_in_module(module, ident, MacroNS, false, None);
|
||||
if let Ok(binding) = result {
|
||||
self.legacy_import_macro(name, binding, span, allow_shadowing);
|
||||
} else {
|
||||
@ -591,7 +592,8 @@ impl<'b> Resolver<'b> {
|
||||
let krate = module.def_id().unwrap().krate;
|
||||
self.used_crates.insert(krate);
|
||||
self.session.cstore.export_macros(krate);
|
||||
let result = self.resolve_name_in_module(module, name, MacroNS, false, None);
|
||||
let ident = Ident::with_empty_ctxt(name);
|
||||
let result = self.resolve_ident_in_module(module, ident, MacroNS, false, None);
|
||||
if let Ok(binding) = result {
|
||||
self.macro_exports.push(Export { name: name, def: binding.def() });
|
||||
} else {
|
||||
@ -696,9 +698,13 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
|
||||
|
||||
fn visit_item(&mut self, item: &'a Item) {
|
||||
let macro_use = match item.node {
|
||||
ItemKind::Mac(..) if item.id == ast::DUMMY_NODE_ID => return, // Scope placeholder
|
||||
ItemKind::Mac(..) => {
|
||||
return self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(item.id));
|
||||
ItemKind::Mac(ref mac) => {
|
||||
if mac.node.path.segments.is_empty() {
|
||||
self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(item.id));
|
||||
} else {
|
||||
self.resolver.define_macro(item, &mut self.legacy_scope);
|
||||
}
|
||||
return
|
||||
}
|
||||
ItemKind::Mod(..) => self.resolver.contains_macro_use(&item.attrs),
|
||||
_ => false,
|
||||
@ -759,7 +765,7 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
|
||||
self.resolver.trait_item_map.insert((item.ident.name, def_id), is_static_method);
|
||||
|
||||
let vis = ty::Visibility::Public;
|
||||
self.resolver.define(parent, item.ident.name, ns, (def, vis, item.span, self.expansion));
|
||||
self.resolver.define(parent, item.ident, ns, (def, vis, item.span, self.expansion));
|
||||
|
||||
self.resolver.current_module = parent.parent.unwrap(); // nearest normal ancestor
|
||||
visit::walk_trait_item(self, item);
|
||||
|
@ -62,7 +62,7 @@ use syntax::ast::{Arm, BindingMode, Block, Crate, Expr, ExprKind};
|
||||
use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, Generics};
|
||||
use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
|
||||
use syntax::ast::{Local, Mutability, Pat, PatKind, Path};
|
||||
use syntax::ast::{PathSegment, PathParameters, QSelf, TraitItemKind, TraitRef, Ty, TyKind};
|
||||
use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
|
||||
|
||||
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
|
||||
use errors::DiagnosticBuilder;
|
||||
@ -774,15 +774,15 @@ enum ModuleKind {
|
||||
}
|
||||
|
||||
/// One node in the tree of modules.
|
||||
pub struct ModuleS<'a> {
|
||||
pub struct ModuleData<'a> {
|
||||
parent: Option<Module<'a>>,
|
||||
kind: ModuleKind,
|
||||
|
||||
// The node id of the closest normal module (`mod`) ancestor (including this module).
|
||||
normal_ancestor_id: Option<NodeId>,
|
||||
|
||||
resolutions: RefCell<FxHashMap<(Name, Namespace), &'a RefCell<NameResolution<'a>>>>,
|
||||
legacy_macro_resolutions: RefCell<Vec<(Mark, Name, Span)>>,
|
||||
resolutions: RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>,
|
||||
legacy_macro_resolutions: RefCell<Vec<(Mark, Ident, Span)>>,
|
||||
macro_resolutions: RefCell<Vec<(Box<[Ident]>, PathScope, Span)>>,
|
||||
|
||||
// Macro invocations that can expand into items in this module.
|
||||
@ -794,7 +794,7 @@ pub struct ModuleS<'a> {
|
||||
globs: RefCell<Vec<&'a ImportDirective<'a>>>,
|
||||
|
||||
// Used to memoize the traits in this module for faster searches through all traits in scope.
|
||||
traits: RefCell<Option<Box<[(Name, &'a NameBinding<'a>)]>>>,
|
||||
traits: RefCell<Option<Box<[(Ident, &'a NameBinding<'a>)]>>>,
|
||||
|
||||
// Whether this module is populated. If not populated, any attempt to
|
||||
// access the children must be preceded with a
|
||||
@ -802,11 +802,11 @@ pub struct ModuleS<'a> {
|
||||
populated: Cell<bool>,
|
||||
}
|
||||
|
||||
pub type Module<'a> = &'a ModuleS<'a>;
|
||||
pub type Module<'a> = &'a ModuleData<'a>;
|
||||
|
||||
impl<'a> ModuleS<'a> {
|
||||
impl<'a> ModuleData<'a> {
|
||||
fn new(parent: Option<Module<'a>>, kind: ModuleKind) -> Self {
|
||||
ModuleS {
|
||||
ModuleData {
|
||||
parent: parent,
|
||||
kind: kind,
|
||||
normal_ancestor_id: None,
|
||||
@ -822,9 +822,9 @@ impl<'a> ModuleS<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn for_each_child<F: FnMut(Name, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) {
|
||||
for (&(name, ns), name_resolution) in self.resolutions.borrow().iter() {
|
||||
name_resolution.borrow().binding.map(|binding| f(name, ns, binding));
|
||||
fn for_each_child<F: FnMut(Ident, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) {
|
||||
for (&(ident, ns), name_resolution) in self.resolutions.borrow().iter() {
|
||||
name_resolution.borrow().binding.map(|binding| f(ident, ns, binding));
|
||||
}
|
||||
}
|
||||
|
||||
@ -859,7 +859,7 @@ impl<'a> ModuleS<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Debug for ModuleS<'a> {
|
||||
impl<'a> fmt::Debug for ModuleData<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{:?}", self.def())
|
||||
}
|
||||
@ -875,11 +875,11 @@ pub struct NameBinding<'a> {
|
||||
}
|
||||
|
||||
pub trait ToNameBinding<'a> {
|
||||
fn to_name_binding(self) -> NameBinding<'a>;
|
||||
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a>;
|
||||
}
|
||||
|
||||
impl<'a> ToNameBinding<'a> for NameBinding<'a> {
|
||||
fn to_name_binding(self) -> NameBinding<'a> {
|
||||
impl<'a> ToNameBinding<'a> for &'a NameBinding<'a> {
|
||||
fn to_name_binding(self, _: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
|
||||
self
|
||||
}
|
||||
}
|
||||
@ -1120,7 +1120,7 @@ pub struct Resolver<'a> {
|
||||
}
|
||||
|
||||
pub struct ResolverArenas<'a> {
|
||||
modules: arena::TypedArena<ModuleS<'a>>,
|
||||
modules: arena::TypedArena<ModuleData<'a>>,
|
||||
local_modules: RefCell<Vec<Module<'a>>>,
|
||||
name_bindings: arena::TypedArena<NameBinding<'a>>,
|
||||
import_directives: arena::TypedArena<ImportDirective<'a>>,
|
||||
@ -1130,7 +1130,7 @@ pub struct ResolverArenas<'a> {
|
||||
}
|
||||
|
||||
impl<'a> ResolverArenas<'a> {
|
||||
fn alloc_module(&'a self, module: ModuleS<'a>) -> Module<'a> {
|
||||
fn alloc_module(&'a self, module: ModuleData<'a>) -> Module<'a> {
|
||||
let module = self.modules.alloc(module);
|
||||
if module.def_id().map(|def_id| def_id.is_local()).unwrap_or(true) {
|
||||
self.local_modules.borrow_mut().push(module);
|
||||
@ -1210,10 +1210,10 @@ impl<'a> Resolver<'a> {
|
||||
arenas: &'a ResolverArenas<'a>)
|
||||
-> Resolver<'a> {
|
||||
let root_def = Def::Mod(DefId::local(CRATE_DEF_INDEX));
|
||||
let graph_root = arenas.alloc_module(ModuleS {
|
||||
let graph_root = arenas.alloc_module(ModuleData {
|
||||
normal_ancestor_id: Some(CRATE_NODE_ID),
|
||||
no_implicit_prelude: attr::contains_name(&krate.attrs, "no_implicit_prelude"),
|
||||
..ModuleS::new(None, ModuleKind::Def(root_def, keywords::Invalid.name()))
|
||||
..ModuleData::new(None, ModuleKind::Def(root_def, keywords::Invalid.name()))
|
||||
});
|
||||
let mut module_map = NodeMap();
|
||||
module_map.insert(CRATE_NODE_ID, graph_root);
|
||||
@ -1331,17 +1331,17 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
|
||||
fn new_module(&self, parent: Module<'a>, kind: ModuleKind, local: bool) -> Module<'a> {
|
||||
self.arenas.alloc_module(ModuleS {
|
||||
self.arenas.alloc_module(ModuleData {
|
||||
normal_ancestor_id: if local { self.current_module.normal_ancestor_id } else { None },
|
||||
populated: Cell::new(local),
|
||||
..ModuleS::new(Some(parent), kind)
|
||||
..ModuleData::new(Some(parent), kind)
|
||||
})
|
||||
}
|
||||
|
||||
fn record_use(&mut self, name: Name, ns: Namespace, binding: &'a NameBinding<'a>, span: Span)
|
||||
fn record_use(&mut self, ident: Ident, ns: Namespace, binding: &'a NameBinding<'a>, span: Span)
|
||||
-> bool /* true if an error was reported */ {
|
||||
// track extern crates for unused_extern_crate lint
|
||||
if let Some(DefId { krate, .. }) = binding.module().and_then(ModuleS::def_id) {
|
||||
if let Some(DefId { krate, .. }) = binding.module().and_then(ModuleData::def_id) {
|
||||
self.used_crates.insert(krate);
|
||||
}
|
||||
|
||||
@ -1349,16 +1349,16 @@ impl<'a> Resolver<'a> {
|
||||
NameBindingKind::Import { directive, binding, ref used } if !used.get() => {
|
||||
used.set(true);
|
||||
self.used_imports.insert((directive.id, ns));
|
||||
self.add_to_glob_map(directive.id, name);
|
||||
self.record_use(name, ns, binding, span)
|
||||
self.add_to_glob_map(directive.id, ident);
|
||||
self.record_use(ident, ns, binding, span)
|
||||
}
|
||||
NameBindingKind::Import { .. } => false,
|
||||
NameBindingKind::Ambiguity { b1, b2, legacy } => {
|
||||
self.ambiguity_errors.push(AmbiguityError {
|
||||
span: span, name: name, lexical: false, b1: b1, b2: b2, legacy: legacy,
|
||||
span: span, name: ident.name, lexical: false, b1: b1, b2: b2, legacy: legacy,
|
||||
});
|
||||
if legacy {
|
||||
self.record_use(name, ns, b1, span);
|
||||
self.record_use(ident, ns, b1, span);
|
||||
}
|
||||
!legacy
|
||||
}
|
||||
@ -1366,9 +1366,9 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn add_to_glob_map(&mut self, id: NodeId, name: Name) {
|
||||
fn add_to_glob_map(&mut self, id: NodeId, ident: Ident) {
|
||||
if self.make_glob_map {
|
||||
self.glob_map.entry(id).or_insert_with(FxHashSet).insert(name);
|
||||
self.glob_map.entry(id).or_insert_with(FxHashSet).insert(ident.name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1395,7 +1395,7 @@ impl<'a> Resolver<'a> {
|
||||
record_used: Option<Span>)
|
||||
-> Option<LexicalScopeBinding<'a>> {
|
||||
if ns == TypeNS {
|
||||
ident = Ident::with_empty_ctxt(ident.name);
|
||||
ident = ident.unhygienize();
|
||||
}
|
||||
|
||||
// Walk backwards up the ribs in scope.
|
||||
@ -1410,8 +1410,7 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
|
||||
if let ModuleRibKind(module) = self.ribs[ns][i].kind {
|
||||
let name = ident.name;
|
||||
let item = self.resolve_name_in_module(module, name, ns, false, record_used);
|
||||
let item = self.resolve_ident_in_module(module, ident, ns, false, record_used);
|
||||
if let Ok(binding) = item {
|
||||
// The ident resolves to an item.
|
||||
return Some(LexicalScopeBinding::Item(binding));
|
||||
@ -1420,7 +1419,7 @@ impl<'a> Resolver<'a> {
|
||||
if let ModuleKind::Block(..) = module.kind { // We can see through blocks
|
||||
} else if !module.no_implicit_prelude {
|
||||
return self.prelude.and_then(|prelude| {
|
||||
self.resolve_name_in_module(prelude, name, ns, false, None).ok()
|
||||
self.resolve_ident_in_module(prelude, ident, ns, false, None).ok()
|
||||
}).map(LexicalScopeBinding::Item)
|
||||
} else {
|
||||
return None;
|
||||
@ -2190,8 +2189,7 @@ impl<'a> Resolver<'a> {
|
||||
Def::VariantCtor(_, CtorKind::Const) |
|
||||
Def::Const(..) if !always_binding => {
|
||||
// A unit struct/variant or constant pattern.
|
||||
let name = ident.node.name;
|
||||
self.record_use(name, ValueNS, binding.unwrap(), ident.span);
|
||||
self.record_use(ident.node, ValueNS, binding.unwrap(), ident.span);
|
||||
Some(PathResolution::new(def))
|
||||
}
|
||||
Def::StructCtor(..) | Def::VariantCtor(..) |
|
||||
@ -2370,9 +2368,9 @@ impl<'a> Resolver<'a> {
|
||||
allow_super = false;
|
||||
|
||||
let binding = if let Some(module) = module {
|
||||
self.resolve_name_in_module(module, ident.name, ns, false, record_used)
|
||||
self.resolve_ident_in_module(module, ident, ns, false, record_used)
|
||||
} else if opt_ns == Some(MacroNS) {
|
||||
self.resolve_lexical_macro_path_segment(ident.name, ns, record_used)
|
||||
self.resolve_lexical_macro_path_segment(ident, ns, record_used)
|
||||
} else {
|
||||
match self.resolve_ident_in_lexical_scope(ident, ns, record_used) {
|
||||
Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
|
||||
@ -2412,7 +2410,7 @@ impl<'a> Resolver<'a> {
|
||||
});
|
||||
}
|
||||
}
|
||||
let msg = if module.and_then(ModuleS::def) == self.graph_root.def() {
|
||||
let msg = if module.and_then(ModuleData::def) == self.graph_root.def() {
|
||||
let is_mod = |def| match def { Def::Mod(..) => true, _ => false };
|
||||
let mut candidates =
|
||||
self.lookup_candidates(ident.name, TypeNS, is_mod).candidates;
|
||||
@ -2872,72 +2870,64 @@ impl<'a> Resolver<'a> {
|
||||
fn get_traits_containing_item(&mut self, name: Name) -> Vec<TraitCandidate> {
|
||||
debug!("(getting traits containing item) looking for '{}'", name);
|
||||
|
||||
fn add_trait_info(found_traits: &mut Vec<TraitCandidate>,
|
||||
trait_def_id: DefId,
|
||||
import_id: Option<NodeId>,
|
||||
name: Name) {
|
||||
debug!("(adding trait info) found trait {:?} for method '{}'",
|
||||
trait_def_id,
|
||||
name);
|
||||
found_traits.push(TraitCandidate {
|
||||
def_id: trait_def_id,
|
||||
import_id: import_id,
|
||||
});
|
||||
}
|
||||
|
||||
let mut found_traits = Vec::new();
|
||||
// Look for the current trait.
|
||||
if let Some((trait_def_id, _)) = self.current_trait_ref {
|
||||
if self.trait_item_map.contains_key(&(name, trait_def_id)) {
|
||||
add_trait_info(&mut found_traits, trait_def_id, None, name);
|
||||
found_traits.push(TraitCandidate { def_id: trait_def_id, import_id: None });
|
||||
}
|
||||
}
|
||||
|
||||
let mut search_module = self.current_module;
|
||||
loop {
|
||||
// Look for trait children.
|
||||
let mut search_in_module = |this: &mut Self, module: Module<'a>| {
|
||||
let mut traits = module.traits.borrow_mut();
|
||||
if traits.is_none() {
|
||||
let mut collected_traits = Vec::new();
|
||||
module.for_each_child(|name, ns, binding| {
|
||||
if ns != TypeNS { return }
|
||||
if let Def::Trait(_) = binding.def() {
|
||||
collected_traits.push((name, binding));
|
||||
}
|
||||
});
|
||||
*traits = Some(collected_traits.into_boxed_slice());
|
||||
}
|
||||
self.get_traits_in_module_containing_item(name, search_module, &mut found_traits);
|
||||
match search_module.kind {
|
||||
ModuleKind::Block(..) => search_module = search_module.parent.unwrap(),
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
|
||||
for &(trait_name, binding) in traits.as_ref().unwrap().iter() {
|
||||
let trait_def_id = binding.def().def_id();
|
||||
if this.trait_item_map.contains_key(&(name, trait_def_id)) {
|
||||
let mut import_id = None;
|
||||
if let NameBindingKind::Import { directive, .. } = binding.kind {
|
||||
let id = directive.id;
|
||||
this.maybe_unused_trait_imports.insert(id);
|
||||
this.add_to_glob_map(id, trait_name);
|
||||
import_id = Some(id);
|
||||
}
|
||||
add_trait_info(&mut found_traits, trait_def_id, import_id, name);
|
||||
}
|
||||
}
|
||||
};
|
||||
search_in_module(self, search_module);
|
||||
|
||||
if let ModuleKind::Block(..) = search_module.kind {
|
||||
search_module = search_module.parent.unwrap();
|
||||
} else {
|
||||
if !search_module.no_implicit_prelude {
|
||||
self.prelude.map(|prelude| search_in_module(self, prelude));
|
||||
}
|
||||
break;
|
||||
if let Some(prelude) = self.prelude {
|
||||
if !search_module.no_implicit_prelude {
|
||||
self.get_traits_in_module_containing_item(name, prelude, &mut found_traits);
|
||||
}
|
||||
}
|
||||
|
||||
found_traits
|
||||
}
|
||||
|
||||
fn get_traits_in_module_containing_item(&mut self,
|
||||
name: Name,
|
||||
module: Module,
|
||||
found_traits: &mut Vec<TraitCandidate>) {
|
||||
let mut traits = module.traits.borrow_mut();
|
||||
if traits.is_none() {
|
||||
let mut collected_traits = Vec::new();
|
||||
module.for_each_child(|name, ns, binding| {
|
||||
if ns != TypeNS { return }
|
||||
if let Def::Trait(_) = binding.def() {
|
||||
collected_traits.push((name, binding));
|
||||
}
|
||||
});
|
||||
*traits = Some(collected_traits.into_boxed_slice());
|
||||
}
|
||||
|
||||
for &(trait_name, binding) in traits.as_ref().unwrap().iter() {
|
||||
let trait_def_id = binding.def().def_id();
|
||||
if self.trait_item_map.contains_key(&(name, trait_def_id)) {
|
||||
let import_id = match binding.kind {
|
||||
NameBindingKind::Import { directive, .. } => {
|
||||
self.maybe_unused_trait_imports.insert(directive.id);
|
||||
self.add_to_glob_map(directive.id, trait_name);
|
||||
Some(directive.id)
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
found_traits.push(TraitCandidate { def_id: trait_def_id, import_id: import_id });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// When name resolution fails, this method can be used to look up candidate
|
||||
/// entities with the expected name. It allows filtering them using the
|
||||
/// supplied predicate (which should be used to only accept the types of
|
||||
@ -2960,24 +2950,18 @@ impl<'a> Resolver<'a> {
|
||||
in_module_is_extern)) = worklist.pop() {
|
||||
self.populate_module_if_necessary(in_module);
|
||||
|
||||
in_module.for_each_child(|name, ns, name_binding| {
|
||||
in_module.for_each_child(|ident, ns, name_binding| {
|
||||
|
||||
// avoid imports entirely
|
||||
if name_binding.is_import() && !name_binding.is_extern_crate() { return; }
|
||||
|
||||
// collect results based on the filter function
|
||||
if name == lookup_name && ns == namespace {
|
||||
if ident.name == lookup_name && ns == namespace {
|
||||
if filter_fn(name_binding.def()) {
|
||||
// create the path
|
||||
let ident = Ident::with_empty_ctxt(name);
|
||||
let params = PathParameters::none();
|
||||
let segment = PathSegment {
|
||||
identifier: ident,
|
||||
parameters: params,
|
||||
};
|
||||
let span = name_binding.span;
|
||||
let mut segms = path_segments.clone();
|
||||
segms.push(segment);
|
||||
segms.push(ident.into());
|
||||
let path = Path {
|
||||
span: span,
|
||||
global: false,
|
||||
@ -3000,10 +2984,7 @@ impl<'a> Resolver<'a> {
|
||||
if let Some(module) = name_binding.module() {
|
||||
// form the path
|
||||
let mut path_segments = path_segments.clone();
|
||||
path_segments.push(PathSegment {
|
||||
identifier: Ident::with_empty_ctxt(name),
|
||||
parameters: PathParameters::none(),
|
||||
});
|
||||
path_segments.push(ident.into());
|
||||
|
||||
if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
|
||||
// add the module to the lookup
|
||||
@ -3144,13 +3125,13 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
fn report_conflict(&mut self,
|
||||
parent: Module,
|
||||
name: Name,
|
||||
ident: Ident,
|
||||
ns: Namespace,
|
||||
binding: &NameBinding,
|
||||
old_binding: &NameBinding) {
|
||||
// Error on the second of two conflicting names
|
||||
if old_binding.span.lo > binding.span.lo {
|
||||
return self.report_conflict(parent, name, ns, old_binding, binding);
|
||||
return self.report_conflict(parent, ident, ns, old_binding, binding);
|
||||
}
|
||||
|
||||
let container = match parent.kind {
|
||||
@ -3165,7 +3146,7 @@ impl<'a> Resolver<'a> {
|
||||
false => ("defined", "definition"),
|
||||
};
|
||||
|
||||
let span = binding.span;
|
||||
let (name, span) = (ident.name, binding.span);
|
||||
|
||||
if let Some(s) = self.name_already_seen.get(&name) {
|
||||
if s == &span {
|
||||
@ -3187,40 +3168,19 @@ impl<'a> Resolver<'a> {
|
||||
};
|
||||
|
||||
let mut err = match (old_binding.is_extern_crate(), binding.is_extern_crate()) {
|
||||
(true, true) => {
|
||||
let mut e = struct_span_err!(self.session, span, E0259, "{}", msg);
|
||||
e.span_label(span, &format!("`{}` was already imported", name));
|
||||
e
|
||||
},
|
||||
(true, _) | (_, true) if binding.is_import() && old_binding.is_import() => {
|
||||
let mut e = struct_span_err!(self.session, span, E0254, "{}", msg);
|
||||
e.span_label(span, &"already imported");
|
||||
e
|
||||
},
|
||||
(true, _) | (_, true) => {
|
||||
let mut e = struct_span_err!(self.session, span, E0260, "{}", msg);
|
||||
e.span_label(span, &format!("`{}` already imported", name));
|
||||
e
|
||||
(true, true) => struct_span_err!(self.session, span, E0259, "{}", msg),
|
||||
(true, _) | (_, true) => match binding.is_import() && old_binding.is_import() {
|
||||
true => struct_span_err!(self.session, span, E0254, "{}", msg),
|
||||
false => struct_span_err!(self.session, span, E0260, "{}", msg),
|
||||
},
|
||||
_ => match (old_binding.is_import(), binding.is_import()) {
|
||||
(false, false) => {
|
||||
let mut e = struct_span_err!(self.session, span, E0428, "{}", msg);
|
||||
e.span_label(span, &format!("already defined"));
|
||||
e
|
||||
},
|
||||
(true, true) => {
|
||||
let mut e = struct_span_err!(self.session, span, E0252, "{}", msg);
|
||||
e.span_label(span, &format!("already imported"));
|
||||
e
|
||||
},
|
||||
_ => {
|
||||
let mut e = struct_span_err!(self.session, span, E0255, "{}", msg);
|
||||
e.span_label(span, &format!("`{}` was already imported", name));
|
||||
e
|
||||
}
|
||||
(false, false) => struct_span_err!(self.session, span, E0428, "{}", msg),
|
||||
(true, true) => struct_span_err!(self.session, span, E0252, "{}", msg),
|
||||
_ => struct_span_err!(self.session, span, E0255, "{}", msg),
|
||||
},
|
||||
};
|
||||
|
||||
err.span_label(span, &format!("`{}` already {}", name, participle));
|
||||
if old_binding.span != syntax_pos::DUMMY_SP {
|
||||
err.span_label(old_binding.span, &format!("previous {} of `{}` here", noun, name));
|
||||
}
|
||||
|
@ -19,11 +19,12 @@ use rustc::hir::map::{self, DefCollector};
|
||||
use rustc::ty;
|
||||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
use syntax::ast::{self, Name};
|
||||
use syntax::ast::{self, Name, Ident};
|
||||
use syntax::attr;
|
||||
use syntax::errors::DiagnosticBuilder;
|
||||
use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator};
|
||||
use syntax::ext::base::{NormalTT, SyntaxExtension};
|
||||
use syntax::ext::expand::Expansion;
|
||||
use syntax::ext::base::{NormalTT, Resolver as SyntaxResolver, SyntaxExtension};
|
||||
use syntax::ext::expand::{Expansion, mark_tts};
|
||||
use syntax::ext::hygiene::Mark;
|
||||
use syntax::ext::tt::macro_rules;
|
||||
use syntax::feature_gate::{emit_feature_err, GateIssue};
|
||||
@ -138,34 +139,6 @@ impl<'a> base::Resolver for Resolver<'a> {
|
||||
invocation.expansion.set(visitor.legacy_scope);
|
||||
}
|
||||
|
||||
fn add_macro(&mut self, scope: Mark, mut def: ast::MacroDef, export: bool) {
|
||||
if def.ident.name == "macro_rules" {
|
||||
self.session.span_err(def.span, "user-defined macros may not be named `macro_rules`");
|
||||
}
|
||||
|
||||
let invocation = self.invocations[&scope];
|
||||
let binding = self.arenas.alloc_legacy_binding(LegacyBinding {
|
||||
parent: Cell::new(invocation.legacy_scope.get()),
|
||||
name: def.ident.name,
|
||||
ext: Rc::new(macro_rules::compile(&self.session.parse_sess, &def)),
|
||||
span: def.span,
|
||||
});
|
||||
invocation.legacy_scope.set(LegacyScope::Binding(binding));
|
||||
self.macro_names.insert(def.ident.name);
|
||||
|
||||
if export {
|
||||
def.id = self.next_node_id();
|
||||
DefCollector::new(&mut self.definitions).with_parent(CRATE_DEF_INDEX, |collector| {
|
||||
collector.visit_macro_def(&def)
|
||||
});
|
||||
self.macro_exports.push(Export {
|
||||
name: def.ident.name,
|
||||
def: Def::Macro(self.definitions.local_def_id(def.id)),
|
||||
});
|
||||
self.exported_macros.push(def);
|
||||
}
|
||||
}
|
||||
|
||||
fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
|
||||
if let NormalTT(..) = *ext {
|
||||
self.macro_names.insert(ident.name);
|
||||
@ -210,9 +183,9 @@ impl<'a> base::Resolver for Resolver<'a> {
|
||||
fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
|
||||
-> Result<Rc<SyntaxExtension>, Determinacy> {
|
||||
let ast::Path { ref segments, global, span } = *path;
|
||||
if segments.iter().any(|segment| !segment.parameters.is_empty()) {
|
||||
if segments.iter().any(|segment| segment.parameters.is_some()) {
|
||||
let kind =
|
||||
if segments.last().unwrap().parameters.is_empty() { "module" } else { "macro" };
|
||||
if segments.last().unwrap().parameters.is_some() { "macro" } else { "module" };
|
||||
let msg = format!("type parameters are not allowed on {}s", kind);
|
||||
self.session.span_err(path.span, &msg);
|
||||
return Err(Determinacy::Determined);
|
||||
@ -232,7 +205,10 @@ impl<'a> base::Resolver for Resolver<'a> {
|
||||
}
|
||||
|
||||
let ext = match self.resolve_path(&path, path_scope, Some(MacroNS), None) {
|
||||
PathResult::NonModule(path_res) => Ok(self.get_macro(path_res.base_def)),
|
||||
PathResult::NonModule(path_res) => match path_res.base_def {
|
||||
Def::Err => Err(Determinacy::Determined),
|
||||
def @ _ => Ok(self.get_macro(def)),
|
||||
},
|
||||
PathResult::Module(..) => unreachable!(),
|
||||
PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined),
|
||||
_ => Err(Determinacy::Determined),
|
||||
@ -246,7 +222,7 @@ impl<'a> base::Resolver for Resolver<'a> {
|
||||
let result = match self.resolve_legacy_scope(&invocation.legacy_scope, name, false) {
|
||||
Some(MacroBinding::Legacy(binding)) => Ok(binding.ext.clone()),
|
||||
Some(MacroBinding::Modern(binding)) => Ok(binding.get_macro(self)),
|
||||
None => match self.resolve_lexical_macro_path_segment(name, MacroNS, None) {
|
||||
None => match self.resolve_lexical_macro_path_segment(path[0], MacroNS, None) {
|
||||
Ok(binding) => Ok(binding.get_macro(self)),
|
||||
Err(Determinacy::Undetermined) if !force => return Err(Determinacy::Undetermined),
|
||||
_ => {
|
||||
@ -260,7 +236,7 @@ impl<'a> base::Resolver for Resolver<'a> {
|
||||
};
|
||||
|
||||
if self.use_extern_macros {
|
||||
self.current_module.legacy_macro_resolutions.borrow_mut().push((scope, name, span));
|
||||
self.current_module.legacy_macro_resolutions.borrow_mut().push((scope, path[0], span));
|
||||
}
|
||||
result
|
||||
}
|
||||
@ -269,7 +245,7 @@ impl<'a> base::Resolver for Resolver<'a> {
|
||||
impl<'a> Resolver<'a> {
|
||||
// Resolve the initial segment of a non-global macro path (e.g. `foo` in `foo::bar!();`)
|
||||
pub fn resolve_lexical_macro_path_segment(&mut self,
|
||||
name: Name,
|
||||
ident: Ident,
|
||||
ns: Namespace,
|
||||
record_used: Option<Span>)
|
||||
-> Result<&'a NameBinding<'a>, Determinacy> {
|
||||
@ -278,7 +254,7 @@ impl<'a> Resolver<'a> {
|
||||
loop {
|
||||
// Since expanded macros may not shadow the lexical scope (enforced below),
|
||||
// we can ignore unresolved invocations (indicated by the penultimate argument).
|
||||
match self.resolve_name_in_module(module, name, ns, true, record_used) {
|
||||
match self.resolve_ident_in_module(module, ident, ns, true, record_used) {
|
||||
Ok(binding) => {
|
||||
let span = match record_used {
|
||||
Some(span) => span,
|
||||
@ -286,6 +262,7 @@ impl<'a> Resolver<'a> {
|
||||
};
|
||||
match potential_expanded_shadower {
|
||||
Some(shadower) if shadower.def() != binding.def() => {
|
||||
let name = ident.name;
|
||||
self.ambiguity_errors.push(AmbiguityError {
|
||||
span: span, name: name, b1: shadower, b2: binding, lexical: true,
|
||||
legacy: false,
|
||||
@ -384,10 +361,10 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
for &(mark, name, span) in module.legacy_macro_resolutions.borrow().iter() {
|
||||
for &(mark, ident, span) in module.legacy_macro_resolutions.borrow().iter() {
|
||||
let legacy_scope = &self.invocations[&mark].legacy_scope;
|
||||
let legacy_resolution = self.resolve_legacy_scope(legacy_scope, name, true);
|
||||
let resolution = self.resolve_lexical_macro_path_segment(name, MacroNS, Some(span));
|
||||
let legacy_resolution = self.resolve_legacy_scope(legacy_scope, ident.name, true);
|
||||
let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, Some(span));
|
||||
let (legacy_resolution, resolution) = match (legacy_resolution, resolution) {
|
||||
(Some(legacy_resolution), Ok(resolution)) => (legacy_resolution, resolution),
|
||||
_ => continue,
|
||||
@ -397,9 +374,9 @@ impl<'a> Resolver<'a> {
|
||||
MacroBinding::Modern(binding) => (binding.span, "imported"),
|
||||
MacroBinding::Legacy(binding) => (binding.span, "defined"),
|
||||
};
|
||||
let msg1 = format!("`{}` could resolve to the macro {} here", name, participle);
|
||||
let msg2 = format!("`{}` could also resolve to the macro imported here", name);
|
||||
self.session.struct_span_err(span, &format!("`{}` is ambiguous", name))
|
||||
let msg1 = format!("`{}` could resolve to the macro {} here", ident, participle);
|
||||
let msg2 = format!("`{}` could also resolve to the macro imported here", ident);
|
||||
self.session.struct_span_err(span, &format!("`{}` is ambiguous", ident))
|
||||
.span_note(legacy_span, &msg1)
|
||||
.span_note(resolution.span, &msg2)
|
||||
.emit();
|
||||
@ -443,4 +420,47 @@ impl<'a> Resolver<'a> {
|
||||
expansion.visit_with(def_collector)
|
||||
});
|
||||
}
|
||||
|
||||
pub fn define_macro(&mut self, item: &ast::Item, legacy_scope: &mut LegacyScope<'a>) {
|
||||
let tts = match item.node {
|
||||
ast::ItemKind::Mac(ref mac) => &mac.node.tts,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
if item.ident.name == "macro_rules" {
|
||||
self.session.span_err(item.span, "user-defined macros may not be named `macro_rules`");
|
||||
}
|
||||
|
||||
let mark = Mark::from_placeholder_id(item.id);
|
||||
let invocation = self.invocations[&mark];
|
||||
invocation.module.set(self.current_module);
|
||||
|
||||
let mut def = ast::MacroDef {
|
||||
ident: item.ident,
|
||||
attrs: item.attrs.clone(),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: item.span,
|
||||
body: mark_tts(tts, mark),
|
||||
};
|
||||
|
||||
*legacy_scope = LegacyScope::Binding(self.arenas.alloc_legacy_binding(LegacyBinding {
|
||||
parent: Cell::new(*legacy_scope),
|
||||
name: def.ident.name,
|
||||
ext: Rc::new(macro_rules::compile(&self.session.parse_sess, &def)),
|
||||
span: def.span,
|
||||
}));
|
||||
self.macro_names.insert(def.ident.name);
|
||||
|
||||
if attr::contains_name(&def.attrs, "macro_export") {
|
||||
def.id = self.next_node_id();
|
||||
DefCollector::new(&mut self.definitions).with_parent(CRATE_DEF_INDEX, |collector| {
|
||||
collector.visit_macro_def(&def)
|
||||
});
|
||||
self.macro_exports.push(Export {
|
||||
name: def.ident.name,
|
||||
def: Def::Macro(self.definitions.local_def_id(def.id)),
|
||||
});
|
||||
self.exported_macros.push(def);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ use self::ImportDirectiveSubclass::*;
|
||||
|
||||
use {AmbiguityError, Module, PerNS};
|
||||
use Namespace::{self, TypeNS, MacroNS};
|
||||
use {NameBinding, NameBindingKind, PathResult, PathScope, PrivacyError, ToNameBinding};
|
||||
use {NameBinding, NameBindingKind, PathResult, PathScope, PrivacyError};
|
||||
use Resolver;
|
||||
use {names_to_string, module_to_string};
|
||||
use {resolve_error, ResolutionError};
|
||||
@ -21,7 +21,7 @@ use rustc::ty;
|
||||
use rustc::lint::builtin::PRIVATE_IN_PUBLIC;
|
||||
use rustc::hir::def::*;
|
||||
|
||||
use syntax::ast::{Ident, NodeId, Name};
|
||||
use syntax::ast::{Ident, NodeId};
|
||||
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
|
||||
use syntax::ext::hygiene::Mark;
|
||||
use syntax::symbol::keywords;
|
||||
@ -35,8 +35,8 @@ use std::mem;
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ImportDirectiveSubclass<'a> {
|
||||
SingleImport {
|
||||
target: Name,
|
||||
source: Name,
|
||||
target: Ident,
|
||||
source: Ident,
|
||||
result: PerNS<Cell<Result<&'a NameBinding<'a>, Determinacy>>>,
|
||||
},
|
||||
GlobImport {
|
||||
@ -126,31 +126,32 @@ impl<'a> NameResolution<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Resolver<'a> {
|
||||
fn resolution(&self, module: Module<'a>, name: Name, ns: Namespace)
|
||||
fn resolution(&self, module: Module<'a>, ident: Ident, ns: Namespace)
|
||||
-> &'a RefCell<NameResolution<'a>> {
|
||||
*module.resolutions.borrow_mut().entry((name, ns))
|
||||
*module.resolutions.borrow_mut().entry((ident, ns))
|
||||
.or_insert_with(|| self.arenas.alloc_name_resolution())
|
||||
}
|
||||
|
||||
/// Attempts to resolve the supplied name in the given module for the given namespace.
|
||||
/// If successful, returns the binding corresponding to the name.
|
||||
/// Attempts to resolve `ident` in namespaces `ns` of `module`.
|
||||
/// Invariant: if `record_used` is `Some`, import resolution must be complete.
|
||||
pub fn resolve_name_in_module(&mut self,
|
||||
module: Module<'a>,
|
||||
name: Name,
|
||||
ns: Namespace,
|
||||
ignore_unresolved_invocations: bool,
|
||||
record_used: Option<Span>)
|
||||
-> Result<&'a NameBinding<'a>, Determinacy> {
|
||||
pub fn resolve_ident_in_module(&mut self,
|
||||
module: Module<'a>,
|
||||
ident: Ident,
|
||||
ns: Namespace,
|
||||
ignore_unresolved_invocations: bool,
|
||||
record_used: Option<Span>)
|
||||
-> Result<&'a NameBinding<'a>, Determinacy> {
|
||||
let ident = ident.unhygienize();
|
||||
self.populate_module_if_necessary(module);
|
||||
|
||||
let resolution = self.resolution(module, name, ns)
|
||||
let resolution = self.resolution(module, ident, ns)
|
||||
.try_borrow_mut()
|
||||
.map_err(|_| Determined)?; // This happens when there is a cycle of imports
|
||||
|
||||
if let Some(span) = record_used {
|
||||
if let Some(binding) = resolution.binding {
|
||||
if let Some(shadowed_glob) = resolution.shadows_glob {
|
||||
let name = ident.name;
|
||||
// If we ignore unresolved invocations, we must forbid
|
||||
// expanded shadowing to avoid time travel.
|
||||
if ignore_unresolved_invocations &&
|
||||
@ -163,11 +164,11 @@ impl<'a> Resolver<'a> {
|
||||
});
|
||||
}
|
||||
}
|
||||
if self.record_use(name, ns, binding, span) {
|
||||
if self.record_use(ident, ns, binding, span) {
|
||||
return Ok(self.dummy_binding);
|
||||
}
|
||||
if !self.is_accessible(binding.vis) {
|
||||
self.privacy_errors.push(PrivacyError(span, name, binding));
|
||||
self.privacy_errors.push(PrivacyError(span, ident.name, binding));
|
||||
}
|
||||
}
|
||||
|
||||
@ -195,11 +196,11 @@ impl<'a> Resolver<'a> {
|
||||
Some(module) => module,
|
||||
None => return Err(Undetermined),
|
||||
};
|
||||
let name = match directive.subclass {
|
||||
let ident = match directive.subclass {
|
||||
SingleImport { source, .. } => source,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
match self.resolve_name_in_module(module, name, ns, false, None) {
|
||||
match self.resolve_ident_in_module(module, ident, ns, false, None) {
|
||||
Err(Determined) => {}
|
||||
_ => return Err(Undetermined),
|
||||
}
|
||||
@ -221,7 +222,7 @@ impl<'a> Resolver<'a> {
|
||||
for directive in module.globs.borrow().iter() {
|
||||
if self.is_accessible(directive.vis.get()) {
|
||||
if let Some(module) = directive.imported_module.get() {
|
||||
let result = self.resolve_name_in_module(module, name, ns, false, None);
|
||||
let result = self.resolve_ident_in_module(module, ident, ns, false, None);
|
||||
if let Err(Undetermined) = result {
|
||||
return Err(Undetermined);
|
||||
}
|
||||
@ -273,7 +274,7 @@ impl<'a> Resolver<'a> {
|
||||
// Given a binding and an import directive that resolves to it,
|
||||
// return the corresponding binding defined by the import directive.
|
||||
pub fn import(&mut self, binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>)
|
||||
-> NameBinding<'a> {
|
||||
-> &'a NameBinding<'a> {
|
||||
let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) ||
|
||||
!directive.is_glob() && binding.is_extern_crate() { // c.f. `PRIVATE_IN_PUBLIC`
|
||||
directive.vis.get()
|
||||
@ -287,7 +288,7 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
NameBinding {
|
||||
self.arenas.alloc_name_binding(NameBinding {
|
||||
kind: NameBindingKind::Import {
|
||||
binding: binding,
|
||||
directive: directive,
|
||||
@ -296,16 +297,18 @@ impl<'a> Resolver<'a> {
|
||||
span: directive.span,
|
||||
vis: vis,
|
||||
expansion: directive.expansion,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Define the name or return the existing binding if there is a collision.
|
||||
pub fn try_define<T>(&mut self, module: Module<'a>, name: Name, ns: Namespace, binding: T)
|
||||
-> Result<(), &'a NameBinding<'a>>
|
||||
where T: ToNameBinding<'a>
|
||||
{
|
||||
let binding = self.arenas.alloc_name_binding(binding.to_name_binding());
|
||||
self.update_resolution(module, name, ns, |this, resolution| {
|
||||
pub fn try_define(&mut self,
|
||||
module: Module<'a>,
|
||||
ident: Ident,
|
||||
ns: Namespace,
|
||||
binding: &'a NameBinding<'a>)
|
||||
-> Result<(), &'a NameBinding<'a>> {
|
||||
let ident = ident.unhygienize();
|
||||
self.update_resolution(module, ident, ns, |this, resolution| {
|
||||
if let Some(old_binding) = resolution.binding {
|
||||
if binding.is_glob_import() {
|
||||
if !old_binding.is_glob_import() &&
|
||||
@ -348,13 +351,14 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
// Use `f` to mutate the resolution of the name in the module.
|
||||
// If the resolution becomes a success, define it in the module's glob importers.
|
||||
fn update_resolution<T, F>(&mut self, module: Module<'a>, name: Name, ns: Namespace, f: F) -> T
|
||||
fn update_resolution<T, F>(&mut self, module: Module<'a>, ident: Ident, ns: Namespace, f: F)
|
||||
-> T
|
||||
where F: FnOnce(&mut Resolver<'a>, &mut NameResolution<'a>) -> T
|
||||
{
|
||||
// Ensure that `resolution` isn't borrowed when defining in the module's glob importers,
|
||||
// during which the resolution might end up getting re-defined via a glob cycle.
|
||||
let (binding, t) = {
|
||||
let mut resolution = &mut *self.resolution(module, name, ns).borrow_mut();
|
||||
let mut resolution = &mut *self.resolution(module, ident, ns).borrow_mut();
|
||||
let old_binding = resolution.binding();
|
||||
|
||||
let t = f(self, resolution);
|
||||
@ -373,7 +377,7 @@ impl<'a> Resolver<'a> {
|
||||
for directive in module.glob_importers.borrow_mut().iter() {
|
||||
if self.is_accessible_from(binding.vis, directive.parent) {
|
||||
let imported_binding = self.import(binding, directive);
|
||||
let _ = self.try_define(directive.parent, name, ns, imported_binding);
|
||||
let _ = self.try_define(directive.parent, ident, ns, imported_binding);
|
||||
}
|
||||
}
|
||||
|
||||
@ -387,7 +391,7 @@ impl<'a> Resolver<'a> {
|
||||
let dummy_binding = self.dummy_binding;
|
||||
let dummy_binding = self.import(dummy_binding, directive);
|
||||
self.per_ns(|this, ns| {
|
||||
let _ = this.try_define(directive.parent, target, ns, dummy_binding.clone());
|
||||
let _ = this.try_define(directive.parent, target, ns, dummy_binding);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -509,15 +513,16 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
let mut indeterminate = false;
|
||||
self.per_ns(|this, ns| {
|
||||
if let Err(Undetermined) = result[ns].get() {
|
||||
result[ns].set(this.resolve_name_in_module(module, source, ns, false, None));
|
||||
result[ns].set(this.resolve_ident_in_module(module, source, ns, false, None));
|
||||
} else {
|
||||
return
|
||||
};
|
||||
|
||||
let parent = directive.parent;
|
||||
match result[ns].get() {
|
||||
Err(Undetermined) => indeterminate = true,
|
||||
Err(Determined) => {
|
||||
this.update_resolution(directive.parent, target, ns, |_, resolution| {
|
||||
this.update_resolution(parent, target, ns, |_, resolution| {
|
||||
resolution.single_imports.directive_failed()
|
||||
});
|
||||
}
|
||||
@ -532,10 +537,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
}
|
||||
Ok(binding) => {
|
||||
let imported_binding = this.import(binding, directive);
|
||||
let conflict = this.try_define(directive.parent, target, ns, imported_binding);
|
||||
let conflict = this.try_define(parent, target, ns, imported_binding);
|
||||
if let Err(old_binding) = conflict {
|
||||
let binding = &this.import(binding, directive);
|
||||
this.report_conflict(directive.parent, target, ns, binding, old_binding);
|
||||
this.report_conflict(parent, target, ns, imported_binding, old_binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -565,7 +569,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
let (name, result) = match directive.subclass {
|
||||
let (ident, result) = match directive.subclass {
|
||||
SingleImport { source, ref result, .. } => (source, result),
|
||||
GlobImport { .. } if module.def_id() == directive.parent.def_id() => {
|
||||
// Importing a module into itself is not allowed.
|
||||
@ -587,8 +591,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
self.per_ns(|this, ns| {
|
||||
if let Ok(binding) = result[ns].get() {
|
||||
all_ns_err = false;
|
||||
if this.record_use(name, ns, binding, directive.span) {
|
||||
this.resolution(module, name, ns).borrow_mut().binding =
|
||||
if this.record_use(ident, ns, binding, directive.span) {
|
||||
this.resolution(module, ident, ns).borrow_mut().binding =
|
||||
Some(this.dummy_binding);
|
||||
}
|
||||
}
|
||||
@ -597,7 +601,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
if all_ns_err {
|
||||
let mut all_ns_failed = true;
|
||||
self.per_ns(|this, ns| {
|
||||
match this.resolve_name_in_module(module, name, ns, false, Some(span)) {
|
||||
match this.resolve_ident_in_module(module, ident, ns, false, Some(span)) {
|
||||
Ok(_) => all_ns_failed = false,
|
||||
_ => {}
|
||||
}
|
||||
@ -605,27 +609,28 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
|
||||
return if all_ns_failed {
|
||||
let resolutions = module.resolutions.borrow();
|
||||
let names = resolutions.iter().filter_map(|(&(ref n, _), resolution)| {
|
||||
if *n == name { return None; } // Never suggest the same name
|
||||
let names = resolutions.iter().filter_map(|(&(ref i, _), resolution)| {
|
||||
if *i == ident { return None; } // Never suggest the same name
|
||||
match *resolution.borrow() {
|
||||
NameResolution { binding: Some(_), .. } => Some(n),
|
||||
NameResolution { binding: Some(_), .. } => Some(&i.name),
|
||||
NameResolution { single_imports: SingleImports::None, .. } => None,
|
||||
_ => Some(n),
|
||||
_ => Some(&i.name),
|
||||
}
|
||||
});
|
||||
let lev_suggestion = match find_best_match_for_name(names, &name.as_str(), None) {
|
||||
Some(name) => format!(". Did you mean to use `{}`?", name),
|
||||
None => "".to_owned(),
|
||||
};
|
||||
let lev_suggestion =
|
||||
match find_best_match_for_name(names, &ident.name.as_str(), None) {
|
||||
Some(name) => format!(". Did you mean to use `{}`?", name),
|
||||
None => "".to_owned(),
|
||||
};
|
||||
let module_str = module_to_string(module);
|
||||
let msg = if &module_str == "???" {
|
||||
format!("no `{}` in the root{}", name, lev_suggestion)
|
||||
format!("no `{}` in the root{}", ident, lev_suggestion)
|
||||
} else {
|
||||
format!("no `{}` in `{}`{}", name, module_str, lev_suggestion)
|
||||
format!("no `{}` in `{}`{}", ident, module_str, lev_suggestion)
|
||||
};
|
||||
Some(msg)
|
||||
} else {
|
||||
// `resolve_name_in_module` reported a privacy error.
|
||||
// `resolve_ident_in_module` reported a privacy error.
|
||||
self.import_dummy_binding(directive);
|
||||
None
|
||||
}
|
||||
@ -650,18 +655,18 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
if ns == TypeNS && binding.is_extern_crate() {
|
||||
let msg = format!("extern crate `{}` is private, and cannot be reexported \
|
||||
(error E0364), consider declaring with `pub`",
|
||||
name);
|
||||
ident);
|
||||
self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg);
|
||||
} else if ns == TypeNS {
|
||||
struct_span_err!(self.session, directive.span, E0365,
|
||||
"`{}` is private, and cannot be reexported", name)
|
||||
.span_label(directive.span, &format!("reexport of private `{}`", name))
|
||||
.note(&format!("consider declaring type or module `{}` with `pub`", name))
|
||||
"`{}` is private, and cannot be reexported", ident)
|
||||
.span_label(directive.span, &format!("reexport of private `{}`", ident))
|
||||
.note(&format!("consider declaring type or module `{}` with `pub`", ident))
|
||||
.emit();
|
||||
} else {
|
||||
let msg = format!("`{}` is private, and cannot be reexported", name);
|
||||
let msg = format!("`{}` is private, and cannot be reexported", ident);
|
||||
let note_msg =
|
||||
format!("consider marking `{}` as `pub` in the imported module", name);
|
||||
format!("consider marking `{}` as `pub` in the imported module", ident);
|
||||
struct_span_err!(self.session, directive.span, E0364, "{}", &msg)
|
||||
.span_note(directive.span, ¬e_msg)
|
||||
.emit();
|
||||
@ -698,21 +703,18 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
|
||||
// Ensure that `resolutions` isn't borrowed during `try_define`,
|
||||
// since it might get updated via a glob cycle.
|
||||
let bindings = module.resolutions.borrow().iter().filter_map(|(name, resolution)| {
|
||||
resolution.borrow().binding().map(|binding| (*name, binding))
|
||||
let bindings = module.resolutions.borrow().iter().filter_map(|(&ident, resolution)| {
|
||||
resolution.borrow().binding().map(|binding| (ident, binding))
|
||||
}).collect::<Vec<_>>();
|
||||
for ((name, ns), binding) in bindings {
|
||||
for ((ident, ns), binding) in bindings {
|
||||
if binding.pseudo_vis() == ty::Visibility::Public || self.is_accessible(binding.vis) {
|
||||
let imported_binding = self.import(binding, directive);
|
||||
let _ = self.try_define(directive.parent, name, ns, imported_binding);
|
||||
let _ = self.try_define(directive.parent, ident, ns, imported_binding);
|
||||
}
|
||||
}
|
||||
|
||||
// Record the destination of this import
|
||||
if let Some(did) = module.def_id() {
|
||||
let resolution = PathResolution::new(Def::Mod(did));
|
||||
self.def_map.insert(directive.id, resolution);
|
||||
}
|
||||
self.def_map.insert(directive.id, PathResolution::new(module.def().unwrap()));
|
||||
}
|
||||
|
||||
// Miscellaneous post-processing, including recording reexports, reporting conflicts,
|
||||
@ -726,7 +728,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
reexports = mem::replace(&mut self.macro_exports, Vec::new());
|
||||
}
|
||||
|
||||
for (&(name, ns), resolution) in module.resolutions.borrow().iter() {
|
||||
for (&(ident, ns), resolution) in module.resolutions.borrow().iter() {
|
||||
let resolution = &mut *resolution.borrow_mut();
|
||||
let binding = match resolution.binding {
|
||||
Some(binding) => binding,
|
||||
@ -740,7 +742,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
if !def.def_id().is_local() {
|
||||
self.session.cstore.export_macros(def.def_id().krate);
|
||||
}
|
||||
reexports.push(Export { name: name, def: def });
|
||||
reexports.push(Export { name: ident.name, def: def });
|
||||
}
|
||||
}
|
||||
|
||||
@ -750,7 +752,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
!orig_binding.vis.is_at_least(binding.vis, self) {
|
||||
let msg = format!("variant `{}` is private, and cannot be reexported \
|
||||
(error E0364), consider declaring its enum as `pub`",
|
||||
name);
|
||||
ident);
|
||||
self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, binding.span, msg);
|
||||
}
|
||||
}
|
||||
|
@ -1085,6 +1085,10 @@ fn run_work_multithreaded(sess: &Session,
|
||||
pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) {
|
||||
let (pname, mut cmd, _) = get_linker(sess);
|
||||
|
||||
for arg in &sess.target.target.options.asm_args {
|
||||
cmd.arg(arg);
|
||||
}
|
||||
|
||||
cmd.arg("-c").arg("-o").arg(&outputs.path(OutputType::Object))
|
||||
.arg(&outputs.temp_path(OutputType::Assembly, None));
|
||||
debug!("{:?}", cmd);
|
||||
|
@ -10,14 +10,13 @@
|
||||
|
||||
use libc::c_uint;
|
||||
use llvm::{self, ValueRef};
|
||||
use rustc::ty;
|
||||
use rustc::ty::{self, layout};
|
||||
use rustc::mir;
|
||||
use rustc::mir::tcx::LvalueTy;
|
||||
use session::config::FullDebugInfo;
|
||||
use base;
|
||||
use common::{self, Block, BlockAndBuilder, CrateContext, FunctionContext, C_null};
|
||||
use debuginfo::{self, declare_local, DebugLoc, VariableAccess, VariableKind, FunctionDebugContext};
|
||||
use machine;
|
||||
use type_of;
|
||||
|
||||
use syntax_pos::{DUMMY_SP, NO_EXPANSION, COMMAND_LINE_EXPN, BytePos};
|
||||
@ -494,10 +493,15 @@ fn arg_local_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
|
||||
llval
|
||||
};
|
||||
|
||||
let llclosurety = type_of::type_of(bcx.ccx(), closure_ty);
|
||||
let layout = bcx.ccx().layout_of(closure_ty);
|
||||
let offsets = match *layout {
|
||||
layout::Univariant { ref variant, .. } => &variant.offsets[..],
|
||||
_ => bug!("Closures are only supposed to be Univariant")
|
||||
};
|
||||
|
||||
for (i, (decl, ty)) in mir.upvar_decls.iter().zip(upvar_tys).enumerate() {
|
||||
let byte_offset_of_var_in_env =
|
||||
machine::llelement_offset(bcx.ccx(), llclosurety, i);
|
||||
let byte_offset_of_var_in_env = offsets[i].bytes();
|
||||
|
||||
|
||||
let ops = unsafe {
|
||||
[llvm::LLVMRustDIBuilderCreateOpDeref(),
|
||||
|
@ -142,20 +142,21 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
|
||||
fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
|
||||
match e {
|
||||
CastError::NeedDeref => {
|
||||
let error_span = self.span;
|
||||
let cast_ty = fcx.ty_to_string(self.cast_ty);
|
||||
let mut err = fcx.type_error_struct(self.cast_span,
|
||||
let mut err = fcx.type_error_struct(error_span,
|
||||
|actual| {
|
||||
format!("casting `{}` as `{}` is invalid",
|
||||
actual,
|
||||
cast_ty)
|
||||
},
|
||||
self.expr_ty);
|
||||
err.span_label(self.expr.span,
|
||||
err.span_label(error_span,
|
||||
&format!("cannot cast `{}` as `{}`",
|
||||
fcx.ty_to_string(self.expr_ty),
|
||||
cast_ty));
|
||||
if let Ok(snippet) = fcx.sess().codemap().span_to_snippet(self.expr.span) {
|
||||
err.span_label(self.expr.span,
|
||||
err.span_help(self.expr.span,
|
||||
&format!("did you mean `*{}`?", snippet));
|
||||
}
|
||||
err.emit();
|
||||
|
@ -2801,7 +2801,7 @@ impl Clean<Item> for doctree::Macro {
|
||||
visibility: Some(Public),
|
||||
stability: self.stab.clean(cx),
|
||||
deprecation: self.depr.clean(cx),
|
||||
def_id: cx.tcx.map.local_def_id(self.id),
|
||||
def_id: self.def_id,
|
||||
inner: MacroItem(Macro {
|
||||
source: format!("macro_rules! {} {{\n{}}}",
|
||||
name,
|
||||
|
@ -233,9 +233,11 @@ pub struct DefaultImpl {
|
||||
pub whence: Span,
|
||||
}
|
||||
|
||||
// For Macro we store the DefId instead of the NodeId, since we also create
|
||||
// these imported macro_rules (which only have a DUMMY_NODE_ID).
|
||||
pub struct Macro {
|
||||
pub name: Name,
|
||||
pub id: ast::NodeId,
|
||||
pub def_id: hir::def_id::DefId,
|
||||
pub attrs: hir::HirVec<ast::Attribute>,
|
||||
pub whence: Span,
|
||||
pub matchers: hir::HirVec<Span>,
|
||||
|
@ -259,10 +259,11 @@ pub fn main_args(args: &[String]) -> isize {
|
||||
}
|
||||
|
||||
let external_html = match ExternalHtml::load(
|
||||
&matches.opt_strs("html-in-header"), &matches.opt_strs("html-before-content"),
|
||||
&matches.opt_strs("html-in-header"),
|
||||
&matches.opt_strs("html-before-content"),
|
||||
&matches.opt_strs("html-after-content")) {
|
||||
Some(eh) => eh,
|
||||
None => return 3
|
||||
None => return 3,
|
||||
};
|
||||
let crate_name = matches.opt_str("crate-name");
|
||||
let playground_url = matches.opt_str("playground-url");
|
||||
|
@ -85,7 +85,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
None);
|
||||
// attach the crate's exported macros to the top-level module:
|
||||
let macro_exports: Vec<_> =
|
||||
krate.exported_macros.iter().map(|def| self.visit_macro(def)).collect();
|
||||
krate.exported_macros.iter().map(|def| self.visit_local_macro(def)).collect();
|
||||
self.module.macros.extend(macro_exports);
|
||||
self.module.is_crate = true;
|
||||
}
|
||||
@ -201,6 +201,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
if def_id.krate == LOCAL_CRATE {
|
||||
continue // These are `krate.exported_macros`, handled in `self.visit()`.
|
||||
}
|
||||
let imported_from = self.cx.sess().cstore.original_crate_name(def_id.krate);
|
||||
let def = match self.cx.sess().cstore.load_macro(def_id, self.cx.sess()) {
|
||||
LoadedMacro::MacroRules(macro_rules) => macro_rules,
|
||||
// FIXME(jseyfried): document proc macro reexports
|
||||
@ -210,14 +211,14 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
// FIXME(jseyfried) merge with `self.visit_macro()`
|
||||
let matchers = def.body.chunks(4).map(|arm| arm[0].get_span()).collect();
|
||||
om.macros.push(Macro {
|
||||
id: def.id,
|
||||
def_id: def_id,
|
||||
attrs: def.attrs.clone().into(),
|
||||
name: def.ident.name,
|
||||
whence: def.span,
|
||||
matchers: matchers,
|
||||
stab: self.stability(def.id),
|
||||
depr: self.deprecation(def.id),
|
||||
imported_from: def.imported_from.map(|ident| ident.name),
|
||||
imported_from: Some(imported_from),
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -513,19 +514,19 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
// convert each exported_macro into a doc item
|
||||
fn visit_macro(&self, def: &hir::MacroDef) -> Macro {
|
||||
fn visit_local_macro(&self, def: &hir::MacroDef) -> Macro {
|
||||
// Extract the spans of all matchers. They represent the "interface" of the macro.
|
||||
let matchers = def.body.chunks(4).map(|arm| arm[0].get_span()).collect();
|
||||
|
||||
Macro {
|
||||
id: def.id,
|
||||
def_id: self.cx.tcx.map.local_def_id(def.id),
|
||||
attrs: def.attrs.clone(),
|
||||
name: def.name,
|
||||
whence: def.span,
|
||||
matchers: matchers,
|
||||
stab: self.stability(def.id),
|
||||
depr: self.deprecation(def.id),
|
||||
imported_from: def.imported_from,
|
||||
imported_from: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use fmt;
|
||||
use mem;
|
||||
use ops::Range;
|
||||
use iter::FusedIterator;
|
||||
@ -370,6 +371,13 @@ impl ExactSizeIterator for EscapeDefault {}
|
||||
#[unstable(feature = "fused", issue = "35602")]
|
||||
impl FusedIterator for EscapeDefault {}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for EscapeDefault {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("EscapeDefault { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static ASCII_LOWERCASE_MAP: [u8; 256] = [
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
|
@ -104,7 +104,7 @@ fn build_libbacktrace(host: &str, target: &str) {
|
||||
.env("AR", &ar)
|
||||
.env("RANLIB", format!("{} s", ar.display()))
|
||||
.env("CFLAGS", cflags));
|
||||
run(Command::new("make")
|
||||
run(Command::new(build_helper::make(host))
|
||||
.current_dir(&build_dir)
|
||||
.arg(format!("INCDIR={}", src_dir.display()))
|
||||
.arg("-j").arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set")));
|
||||
|
@ -1276,6 +1276,15 @@ impl<'a, K, V> Clone for Iter<'a, K, V> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl<'a, K: Debug, V: Debug> fmt::Debug for Iter<'a, K, V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_list()
|
||||
.entries(self.clone())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// HashMap mutable values iterator.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct IterMut<'a, K: 'a, V: 'a> {
|
||||
@ -1285,7 +1294,7 @@ pub struct IterMut<'a, K: 'a, V: 'a> {
|
||||
/// HashMap move iterator.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct IntoIter<K, V> {
|
||||
inner: table::IntoIter<K, V>,
|
||||
pub(super) inner: table::IntoIter<K, V>,
|
||||
}
|
||||
|
||||
/// HashMap keys iterator.
|
||||
@ -1302,6 +1311,15 @@ impl<'a, K, V> Clone for Keys<'a, K, V> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl<'a, K: Debug, V: Debug> fmt::Debug for Keys<'a, K, V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_list()
|
||||
.entries(self.clone())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// HashMap values iterator.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Values<'a, K: 'a, V: 'a> {
|
||||
@ -1316,10 +1334,19 @@ impl<'a, K, V> Clone for Values<'a, K, V> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl<'a, K: Debug, V: Debug> fmt::Debug for Values<'a, K, V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_list()
|
||||
.entries(self.clone())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// HashMap drain iterator.
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
pub struct Drain<'a, K: 'a, V: 'a> {
|
||||
inner: table::Drain<'a, K, V>,
|
||||
pub(super) inner: table::Drain<'a, K, V>,
|
||||
}
|
||||
|
||||
/// Mutable HashMap values iterator.
|
||||
@ -1557,6 +1584,18 @@ impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
|
||||
#[unstable(feature = "fused", issue = "35602")]
|
||||
impl<'a, K, V> FusedIterator for IterMut<'a, K, V> {}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl<'a, K, V> fmt::Debug for IterMut<'a, K, V>
|
||||
where K: fmt::Debug,
|
||||
V: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_list()
|
||||
.entries(self.inner.iter())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<K, V> Iterator for IntoIter<K, V> {
|
||||
type Item = (K, V);
|
||||
@ -1580,6 +1619,15 @@ impl<K, V> ExactSizeIterator for IntoIter<K, V> {
|
||||
#[unstable(feature = "fused", issue = "35602")]
|
||||
impl<K, V> FusedIterator for IntoIter<K, V> {}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl<K: Debug, V: Debug> fmt::Debug for IntoIter<K, V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_list()
|
||||
.entries(self.inner.iter())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, K, V> Iterator for Keys<'a, K, V> {
|
||||
type Item = &'a K;
|
||||
@ -1649,6 +1697,18 @@ impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> {
|
||||
#[unstable(feature = "fused", issue = "35602")]
|
||||
impl<'a, K, V> FusedIterator for ValuesMut<'a, K, V> {}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl<'a, K, V> fmt::Debug for ValuesMut<'a, K, V>
|
||||
where K: fmt::Debug,
|
||||
V: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_list()
|
||||
.entries(self.inner.inner.iter())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
impl<'a, K, V> Iterator for Drain<'a, K, V> {
|
||||
type Item = (K, V);
|
||||
@ -1672,6 +1732,18 @@ impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> {
|
||||
#[unstable(feature = "fused", issue = "35602")]
|
||||
impl<'a, K, V> FusedIterator for Drain<'a, K, V> {}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl<'a, K, V> fmt::Debug for Drain<'a, K, V>
|
||||
where K: fmt::Debug,
|
||||
V: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_list()
|
||||
.entries(self.inner.iter())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K, V> Entry<'a, K, V> {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
/// Ensures a value is in the entry by inserting the default if empty, and returns
|
||||
@ -2148,6 +2220,13 @@ impl Default for RandomState {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for RandomState {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("RandomState { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, S, Q: ?Sized> super::Recover<Q> for HashMap<K, (), S>
|
||||
where K: Eq + Hash + Borrow<Q>,
|
||||
S: BuildHasher,
|
||||
|
@ -948,6 +948,15 @@ impl<'a, K> ExactSizeIterator for Iter<'a, K> {
|
||||
#[unstable(feature = "fused", issue = "35602")]
|
||||
impl<'a, K> FusedIterator for Iter<'a, K> {}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl<'a, K: fmt::Debug> fmt::Debug for Iter<'a, K> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_list()
|
||||
.entries(self.clone())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<K> Iterator for IntoIter<K> {
|
||||
type Item = K;
|
||||
@ -968,6 +977,16 @@ impl<K> ExactSizeIterator for IntoIter<K> {
|
||||
#[unstable(feature = "fused", issue = "35602")]
|
||||
impl<K> FusedIterator for IntoIter<K> {}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl<K: fmt::Debug> fmt::Debug for IntoIter<K> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let entries_iter = self.iter.inner.iter().map(|(k, _)| k);
|
||||
f.debug_list()
|
||||
.entries(entries_iter)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, K> Iterator for Drain<'a, K> {
|
||||
type Item = K;
|
||||
@ -988,6 +1007,16 @@ impl<'a, K> ExactSizeIterator for Drain<'a, K> {
|
||||
#[unstable(feature = "fused", issue = "35602")]
|
||||
impl<'a, K> FusedIterator for Drain<'a, K> {}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl<'a, K: fmt::Debug> fmt::Debug for Drain<'a, K> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let entries_iter = self.iter.inner.iter().map(|(k, _)| k);
|
||||
f.debug_list()
|
||||
.entries(entries_iter)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T, S> Clone for Intersection<'a, T, S> {
|
||||
fn clone(&self) -> Intersection<'a, T, S> {
|
||||
@ -1021,6 +1050,18 @@ impl<'a, T, S> Iterator for Intersection<'a, T, S>
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl<'a, T, S> fmt::Debug for Intersection<'a, T, S>
|
||||
where T: fmt::Debug + Eq + Hash,
|
||||
S: BuildHasher,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_list()
|
||||
.entries(self.clone())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "fused", issue = "35602")]
|
||||
impl<'a, T, S> FusedIterator for Intersection<'a, T, S>
|
||||
where T: Eq + Hash,
|
||||
@ -1068,6 +1109,18 @@ impl<'a, T, S> FusedIterator for Difference<'a, T, S>
|
||||
{
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl<'a, T, S> fmt::Debug for Difference<'a, T, S>
|
||||
where T: fmt::Debug + Eq + Hash,
|
||||
S: BuildHasher,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_list()
|
||||
.entries(self.clone())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T, S> Clone for SymmetricDifference<'a, T, S> {
|
||||
fn clone(&self) -> SymmetricDifference<'a, T, S> {
|
||||
@ -1097,6 +1150,18 @@ impl<'a, T, S> FusedIterator for SymmetricDifference<'a, T, S>
|
||||
{
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl<'a, T, S> fmt::Debug for SymmetricDifference<'a, T, S>
|
||||
where T: fmt::Debug + Eq + Hash,
|
||||
S: BuildHasher,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_list()
|
||||
.entries(self.clone())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T, S> Clone for Union<'a, T, S> {
|
||||
fn clone(&self) -> Union<'a, T, S> {
|
||||
@ -1111,6 +1176,18 @@ impl<'a, T, S> FusedIterator for Union<'a, T, S>
|
||||
{
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl<'a, T, S> fmt::Debug for Union<'a, T, S>
|
||||
where T: fmt::Debug + Eq + Hash,
|
||||
S: BuildHasher,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_list()
|
||||
.entries(self.clone())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T, S> Iterator for Union<'a, T, S>
|
||||
where T: Eq + Hash,
|
||||
|
@ -882,6 +882,15 @@ unsafe impl<'a, K: Sync, V: Sync> Sync for IterMut<'a, K, V> {}
|
||||
// but Send is the more useful bound
|
||||
unsafe impl<'a, K: Send, V: Send> Send for IterMut<'a, K, V> {}
|
||||
|
||||
impl<'a, K: 'a, V: 'a> IterMut<'a, K, V> {
|
||||
pub fn iter(&self) -> Iter<K, V> {
|
||||
Iter {
|
||||
iter: self.iter.clone(),
|
||||
elems_left: self.elems_left,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterator over the entries in a table, consuming the table.
|
||||
pub struct IntoIter<K, V> {
|
||||
table: RawTable<K, V>,
|
||||
@ -891,6 +900,15 @@ pub struct IntoIter<K, V> {
|
||||
unsafe impl<K: Sync, V: Sync> Sync for IntoIter<K, V> {}
|
||||
unsafe impl<K: Send, V: Send> Send for IntoIter<K, V> {}
|
||||
|
||||
impl<K, V> IntoIter<K, V> {
|
||||
pub fn iter(&self) -> Iter<K, V> {
|
||||
Iter {
|
||||
iter: self.iter.clone(),
|
||||
elems_left: self.table.size,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterator over the entries in a table, clearing the table.
|
||||
pub struct Drain<'a, K: 'a, V: 'a> {
|
||||
table: Shared<RawTable<K, V>>,
|
||||
@ -901,6 +919,17 @@ pub struct Drain<'a, K: 'a, V: 'a> {
|
||||
unsafe impl<'a, K: Sync, V: Sync> Sync for Drain<'a, K, V> {}
|
||||
unsafe impl<'a, K: Send, V: Send> Send for Drain<'a, K, V> {}
|
||||
|
||||
impl<'a, K, V> Drain<'a, K, V> {
|
||||
pub fn iter(&self) -> Iter<K, V> {
|
||||
unsafe {
|
||||
Iter {
|
||||
iter: self.iter.clone(),
|
||||
elems_left: (**self.table).size,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K, V> Iterator for Iter<'a, K, V> {
|
||||
type Item = (&'a K, &'a V);
|
||||
|
||||
|
@ -143,6 +143,13 @@ impl Iterator for Vars {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for Vars {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("Vars { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "env", since = "1.0.0")]
|
||||
impl Iterator for VarsOs {
|
||||
type Item = (OsString, OsString);
|
||||
@ -150,6 +157,13 @@ impl Iterator for VarsOs {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for VarsOs {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("VarsOs { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetches the environment variable `key` from the current process.
|
||||
///
|
||||
/// The returned result is `Ok(s)` if the environment variable is present and is
|
||||
@ -364,6 +378,13 @@ impl<'a> Iterator for SplitPaths<'a> {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl<'a> fmt::Debug for SplitPaths<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("SplitPaths { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
/// Error type returned from `std::env::join_paths` when paths fail to be
|
||||
/// joined.
|
||||
#[derive(Debug)]
|
||||
@ -640,6 +661,13 @@ impl DoubleEndedIterator for Args {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for Args {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("Args { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "env", since = "1.0.0")]
|
||||
impl Iterator for ArgsOs {
|
||||
type Item = OsString;
|
||||
@ -657,6 +685,14 @@ impl ExactSizeIterator for ArgsOs {
|
||||
impl DoubleEndedIterator for ArgsOs {
|
||||
fn next_back(&mut self) -> Option<OsString> { self.inner.next_back() }
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for ArgsOs {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("ArgsOs { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
/// Constants associated with the current target
|
||||
#[stable(feature = "env", since = "1.0.0")]
|
||||
pub mod consts {
|
||||
|
@ -140,7 +140,7 @@ pub struct DirEntry(fs_imp::DirEntry);
|
||||
/// .create(true)
|
||||
/// .open("foo.txt");
|
||||
/// ```
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct OpenOptions(fs_imp::OpenOptions);
|
||||
|
||||
@ -168,6 +168,7 @@ pub struct FileType(fs_imp::FileType);
|
||||
///
|
||||
/// This builder also supports platform-specific options.
|
||||
#[stable(feature = "dir_builder", since = "1.6.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct DirBuilder {
|
||||
inner: fs_imp::DirBuilder,
|
||||
recursive: bool,
|
||||
@ -834,6 +835,21 @@ impl Metadata {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for Metadata {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("Metadata")
|
||||
.field("file_type", &self.file_type())
|
||||
.field("is_dir", &self.is_dir())
|
||||
.field("is_file", &self.is_file())
|
||||
.field("permissions", &self.permissions())
|
||||
.field("modified", &self.modified())
|
||||
.field("accessed", &self.accessed())
|
||||
.field("created", &self.created())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInner<fs_imp::FileAttr> for Metadata {
|
||||
fn as_inner(&self) -> &fs_imp::FileAttr { &self.0 }
|
||||
}
|
||||
|
@ -1444,6 +1444,16 @@ pub struct Chain<T, U> {
|
||||
done_first: bool,
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl<T: fmt::Debug, U: fmt::Debug> fmt::Debug for Chain<T, U> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("Chain")
|
||||
.field("t", &self.first)
|
||||
.field("u", &self.second)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: Read, U: Read> Read for Chain<T, U> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
|
||||
@ -1485,6 +1495,7 @@ impl<T: BufRead, U: BufRead> BufRead for Chain<T, U> {
|
||||
///
|
||||
/// [`take()`]: trait.Read.html#method.take
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct Take<T> {
|
||||
inner: T,
|
||||
limit: u64,
|
||||
@ -1602,6 +1613,7 @@ fn read_one_byte(reader: &mut Read) -> Option<Result<u8>> {
|
||||
///
|
||||
/// [`bytes()`]: trait.Read.html#method.bytes
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct Bytes<R> {
|
||||
inner: R,
|
||||
}
|
||||
@ -1623,6 +1635,7 @@ impl<R: Read> Iterator for Bytes<R> {
|
||||
/// [chars]: trait.Read.html#method.chars
|
||||
#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
|
||||
issue = "27802")]
|
||||
#[derive(Debug)]
|
||||
pub struct Chars<R> {
|
||||
inner: R,
|
||||
}
|
||||
@ -1712,6 +1725,7 @@ impl fmt::Display for CharsError {
|
||||
///
|
||||
/// [split]: trait.BufRead.html#method.split
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct Split<B> {
|
||||
buf: B,
|
||||
delim: u8,
|
||||
@ -1743,6 +1757,7 @@ impl<B: BufRead> Iterator for Split<B> {
|
||||
///
|
||||
/// [lines]: trait.BufRead.html#method.lines
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct Lines<B> {
|
||||
buf: B,
|
||||
}
|
||||
|
@ -282,6 +282,13 @@ impl Stdin {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for Stdin {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("Stdin { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Read for Stdin {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
@ -314,6 +321,13 @@ impl<'a> BufRead for StdinLock<'a> {
|
||||
fn consume(&mut self, n: usize) { self.inner.consume(n) }
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl<'a> fmt::Debug for StdinLock<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("StdinLock { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
/// A handle to the global standard output stream of the current process.
|
||||
///
|
||||
/// Each handle shares a global buffer of data to be written to the standard
|
||||
@ -424,6 +438,13 @@ impl Stdout {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for Stdout {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("Stdout { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Write for Stdout {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
@ -449,6 +470,13 @@ impl<'a> Write for StdoutLock<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl<'a> fmt::Debug for StdoutLock<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("StdoutLock { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
/// A handle to the standard error stream of a process.
|
||||
///
|
||||
/// For more information, see the [`io::stderr`] method.
|
||||
@ -545,6 +573,13 @@ impl Stderr {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for Stderr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("Stderr { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Write for Stderr {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
@ -570,6 +605,13 @@ impl<'a> Write for StderrLock<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl<'a> fmt::Debug for StderrLock<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("StderrLock { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
/// Resets the thread-local stderr handle to the specified writer
|
||||
///
|
||||
/// This will replace the current thread's stderr handle, returning the old
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#![allow(missing_copy_implementations)]
|
||||
|
||||
use fmt;
|
||||
use io::{self, Read, Write, ErrorKind, BufRead};
|
||||
|
||||
/// Copies the entire contents of a reader into a writer.
|
||||
@ -97,6 +98,13 @@ impl BufRead for Empty {
|
||||
fn consume(&mut self, _n: usize) {}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for Empty {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("Empty { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
/// A reader which yields one byte over and over and over and over and over and...
|
||||
///
|
||||
/// This struct is generally created by calling [`repeat()`][repeat]. Please
|
||||
@ -133,6 +141,13 @@ impl Read for Repeat {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for Repeat {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("Repeat { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
/// A writer which will move data into the void.
|
||||
///
|
||||
/// This struct is generally created by calling [`sink()`][sink]. Please
|
||||
@ -165,6 +180,13 @@ impl Write for Sink {
|
||||
fn flush(&mut self) -> io::Result<()> { Ok(()) }
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for Sink {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("Sink { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use io::prelude::*;
|
||||
|
@ -214,6 +214,7 @@
|
||||
#![no_std]
|
||||
|
||||
#![deny(missing_docs)]
|
||||
#![deny(missing_debug_implementations)]
|
||||
|
||||
// Tell the compiler to link to either panic_abort or panic_unwind
|
||||
#![needs_panic_runtime]
|
||||
@ -276,6 +277,7 @@
|
||||
#![feature(panic_unwind)]
|
||||
#![feature(placement_in_syntax)]
|
||||
#![feature(prelude_import)]
|
||||
#![feature(pub_restricted)]
|
||||
#![feature(rand)]
|
||||
#![feature(raw)]
|
||||
#![feature(repr_simd)]
|
||||
|
@ -1068,6 +1068,14 @@ impl From<[u8; 16]> for Ipv6Addr {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "ipv6_from_segments", since = "1.15.0")]
|
||||
impl From<[u16; 8]> for Ipv6Addr {
|
||||
fn from(segments: [u16; 8]) -> Ipv6Addr {
|
||||
let [a, b, c, d, e, f, g, h] = segments;
|
||||
Ipv6Addr::new(a, b, c, d, e, f, g, h)
|
||||
}
|
||||
}
|
||||
|
||||
// Tests for this module
|
||||
#[cfg(all(test, not(target_os = "emscripten")))]
|
||||
mod tests {
|
||||
@ -1413,10 +1421,28 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ipv4_from_u32_slice() {
|
||||
fn ipv4_from_octets() {
|
||||
assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ipv6_from_segments() {
|
||||
let from_u16s = Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677,
|
||||
0x8899, 0xaabb, 0xccdd, 0xeeff]);
|
||||
let new = Ipv6Addr::new(0x0011, 0x2233, 0x4455, 0x6677,
|
||||
0x8899, 0xaabb, 0xccdd, 0xeeff);
|
||||
assert_eq!(new, from_u16s);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ipv6_from_octets() {
|
||||
let from_u16s = Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677,
|
||||
0x8899, 0xaabb, 0xccdd, 0xeeff]);
|
||||
let from_u8s = Ipv6Addr::from([0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]);
|
||||
assert_eq!(from_u16s, from_u8s);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ord() {
|
||||
assert!(Ipv4Addr::new(100, 64, 3, 3) < Ipv4Addr::new(192, 0, 2, 2));
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use fmt;
|
||||
use io::{self, Error, ErrorKind};
|
||||
use sys_common::net as net_imp;
|
||||
|
||||
@ -105,6 +106,13 @@ impl Iterator for LookupHost {
|
||||
fn next(&mut self) -> Option<SocketAddr> { self.0.next() }
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for LookupHost {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("LookupHost { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve the host specified by `host` as a number of `SocketAddr` instances.
|
||||
///
|
||||
/// This method may perform a DNS query to resolve `host` and may also inspect
|
||||
|
@ -76,6 +76,7 @@ pub struct TcpListener(net_imp::TcpListener);
|
||||
/// [`incoming`]: struct.TcpListener.html#method.incoming
|
||||
/// [`TcpListener`]: struct.TcpListener.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct Incoming<'a> { listener: &'a TcpListener }
|
||||
|
||||
impl TcpStream {
|
||||
|
@ -17,6 +17,7 @@
|
||||
crates.io should be used instead for the correct \
|
||||
definitions")]
|
||||
#![allow(deprecated)]
|
||||
#![allow(missing_debug_implementations)]
|
||||
|
||||
use os::raw::c_ulong;
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
//! OS-specific functionality.
|
||||
|
||||
#![stable(feature = "os", since = "1.0.0")]
|
||||
#![allow(missing_docs, bad_style)]
|
||||
#![allow(missing_docs, bad_style, missing_debug_implementations)]
|
||||
|
||||
#[cfg(any(target_os = "redox", unix))]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
#![stable(feature = "raw_os", since = "1.1.0")]
|
||||
|
||||
use fmt;
|
||||
|
||||
#[cfg(any(target_os = "android",
|
||||
target_os = "emscripten",
|
||||
all(target_os = "linux", any(target_arch = "aarch64",
|
||||
@ -71,6 +73,13 @@ pub enum c_void {
|
||||
#[doc(hidden)] __variant2,
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for c_void {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("c_void")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(unused_imports)]
|
||||
mod tests {
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
use any::Any;
|
||||
use cell::UnsafeCell;
|
||||
use fmt;
|
||||
use ops::{Deref, DerefMut};
|
||||
use panicking;
|
||||
use ptr::{Unique, Shared};
|
||||
@ -296,6 +297,15 @@ impl<R, F: FnOnce() -> R> FnOnce<()> for AssertUnwindSafe<F> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for AssertUnwindSafe<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("AssertUnwindSafe")
|
||||
.field(&self.0)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// Invokes a closure, capturing the cause of an unwinding panic if one occurs.
|
||||
///
|
||||
/// This function will return `Ok` with the closure's result if the closure
|
||||
|
@ -177,6 +177,7 @@ pub fn take_hook() -> Box<Fn(&PanicInfo) + 'static + Sync + Send> {
|
||||
/// panic!("Normal panic");
|
||||
/// ```
|
||||
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct PanicInfo<'a> {
|
||||
payload: &'a (Any + Send),
|
||||
location: Location<'a>,
|
||||
@ -256,6 +257,7 @@ impl<'a> PanicInfo<'a> {
|
||||
///
|
||||
/// panic!("Normal panic");
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
||||
pub struct Location<'a> {
|
||||
file: &'a str,
|
||||
|
@ -114,6 +114,17 @@ impl IntoInner<imp::Process> for Child {
|
||||
fn into_inner(self) -> imp::Process { self.handle }
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for Child {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("Child")
|
||||
.field("stdin", &self.stdin)
|
||||
.field("stdout", &self.stdout)
|
||||
.field("stderr", &self.stderr)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// A handle to a child process's stdin. This struct is used in the [`stdin`]
|
||||
/// field on [`Child`].
|
||||
///
|
||||
@ -149,6 +160,13 @@ impl FromInner<AnonPipe> for ChildStdin {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for ChildStdin {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("ChildStdin { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
/// A handle to a child process's stdout. This struct is used in the [`stdout`]
|
||||
/// field on [`Child`].
|
||||
///
|
||||
@ -183,6 +201,13 @@ impl FromInner<AnonPipe> for ChildStdout {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for ChildStdout {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("ChildStdout { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
/// A handle to a child process's stderr. This struct is used in the [`stderr`]
|
||||
/// field on [`Child`].
|
||||
///
|
||||
@ -217,6 +242,13 @@ impl FromInner<AnonPipe> for ChildStderr {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for ChildStderr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("ChildStderr { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
/// A process builder, providing fine-grained control
|
||||
/// over how a new process should be spawned.
|
||||
///
|
||||
@ -622,6 +654,13 @@ impl FromInner<imp::Stdio> for Stdio {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for Stdio {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("Stdio { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes the result of a process after it has terminated.
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
#[stable(feature = "process", since = "1.0.0")]
|
||||
|
@ -59,6 +59,7 @@
|
||||
#![unstable(feature = "rand", issue = "0")]
|
||||
|
||||
use cell::RefCell;
|
||||
use fmt;
|
||||
use io;
|
||||
use mem;
|
||||
use rc::Rc;
|
||||
@ -143,6 +144,12 @@ pub struct ThreadRng {
|
||||
rng: Rc<RefCell<ThreadRngInner>>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for ThreadRng {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("ThreadRng { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieve the lazily-initialized thread-local random number
|
||||
/// generator, seeded by the system. Intended to be used in method
|
||||
/// chaining style, e.g. `thread_rng().gen::<isize>()`.
|
||||
|
@ -8,6 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use fmt;
|
||||
use sync::{Mutex, Condvar};
|
||||
|
||||
/// A barrier enables multiple threads to synchronize the beginning
|
||||
@ -54,6 +55,13 @@ struct BarrierState {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct BarrierWaitResult(bool);
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for Barrier {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("Barrier { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
impl Barrier {
|
||||
/// Creates a new barrier that can block a given number of threads.
|
||||
///
|
||||
@ -102,6 +110,15 @@ impl Barrier {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for BarrierWaitResult {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("BarrierWaitResult")
|
||||
.field("is_leader", &self.is_leader())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl BarrierWaitResult {
|
||||
/// Returns whether this thread from `wait` is the "leader thread".
|
||||
///
|
||||
|
@ -8,6 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use fmt;
|
||||
use sync::atomic::{AtomicUsize, Ordering};
|
||||
use sync::{mutex, MutexGuard, PoisonError};
|
||||
use sys_common::condvar as sys;
|
||||
@ -239,6 +240,13 @@ impl Condvar {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for Condvar {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("Condvar { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "condvar_default", since = "1.9.0")]
|
||||
impl Default for Condvar {
|
||||
/// Creates a `Condvar` which is ready to be waited on and notified.
|
||||
|
@ -306,6 +306,7 @@ impl<T> !Sync for Receiver<T> { }
|
||||
/// whenever `next` is called, waiting for a new message, and `None` will be
|
||||
/// returned when the corresponding channel has hung up.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct Iter<'a, T: 'a> {
|
||||
rx: &'a Receiver<T>
|
||||
}
|
||||
@ -317,6 +318,7 @@ pub struct Iter<'a, T: 'a> {
|
||||
/// This Iterator will never block the caller in order to wait for data to
|
||||
/// become available. Instead, it will return `None`.
|
||||
#[stable(feature = "receiver_try_iter", since = "1.15.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct TryIter<'a, T: 'a> {
|
||||
rx: &'a Receiver<T>
|
||||
}
|
||||
@ -325,6 +327,7 @@ pub struct TryIter<'a, T: 'a> {
|
||||
/// whenever `next` is called, waiting for a new message, and `None` will be
|
||||
/// returned when the corresponding channel has hung up.
|
||||
#[stable(feature = "receiver_into_iter", since = "1.1.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct IntoIter<T> {
|
||||
rx: Receiver<T>
|
||||
}
|
||||
|
@ -351,6 +351,15 @@ impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("MutexGuard")
|
||||
.field("lock", &self.__lock)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex {
|
||||
&guard.__lock.inner
|
||||
}
|
||||
|
@ -64,6 +64,7 @@
|
||||
// You'll find a few more details in the implementation, but that's the gist of
|
||||
// it!
|
||||
|
||||
use fmt;
|
||||
use marker;
|
||||
use ptr;
|
||||
use sync::atomic::{AtomicUsize, AtomicBool, Ordering};
|
||||
@ -103,6 +104,7 @@ unsafe impl Send for Once {}
|
||||
/// State yielded to the `call_once_force` method which can be used to query
|
||||
/// whether the `Once` was previously poisoned or not.
|
||||
#[unstable(feature = "once_poison", issue = "33577")]
|
||||
#[derive(Debug)]
|
||||
pub struct OnceState {
|
||||
poisoned: bool,
|
||||
}
|
||||
@ -328,6 +330,13 @@ impl Once {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl fmt::Debug for Once {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("Once { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Finish {
|
||||
fn drop(&mut self) {
|
||||
// Swap out our state with however we finished. We should only ever see
|
||||
|
@ -362,6 +362,24 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl<'a, T: fmt::Debug> fmt::Debug for RwLockReadGuard<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("RwLockReadGuard")
|
||||
.field("lock", &self.__lock)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
impl<'a, T: fmt::Debug> fmt::Debug for RwLockWriteGuard<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("RwLockWriteGuard")
|
||||
.field("lock", &self.__lock)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'rwlock, T: ?Sized> Deref for RwLockReadGuard<'rwlock, T> {
|
||||
type Target = T;
|
||||
|
@ -30,6 +30,8 @@
|
||||
//! inter-dependencies within `std` that will be a challenging goal to
|
||||
//! achieve.
|
||||
|
||||
#![allow(missing_debug_implementations)]
|
||||
|
||||
pub use self::imp::*;
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
|
@ -85,6 +85,21 @@ enum AddressKind<'a> {
|
||||
}
|
||||
|
||||
/// An address associated with a Unix socket.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::os::unix::net::UnixListener;
|
||||
///
|
||||
/// let socket = match UnixListener::bind("/tmp/sock") {
|
||||
/// Ok(sock) => sock,
|
||||
/// Err(e) => {
|
||||
/// println!("Couldn't bind: {:?}", e);
|
||||
/// return
|
||||
/// }
|
||||
/// };
|
||||
/// let addr = socket.local_addr().expect("Couldn't get local address");
|
||||
/// ```
|
||||
#[derive(Clone)]
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub struct SocketAddr {
|
||||
@ -121,6 +136,28 @@ impl SocketAddr {
|
||||
}
|
||||
|
||||
/// Returns true if and only if the address is unnamed.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// A named address:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixListener;
|
||||
///
|
||||
/// let socket = UnixListener::bind("/tmp/sock").unwrap();
|
||||
/// let addr = socket.local_addr().expect("Couldn't get local address");
|
||||
/// assert_eq!(addr.is_unnamed(), false);
|
||||
/// ```
|
||||
///
|
||||
/// An unnamed address:
|
||||
///
|
||||
/// ```
|
||||
/// use std::os::unix::net::UnixDatagram;
|
||||
///
|
||||
/// let socket = UnixDatagram::unbound().unwrap();
|
||||
/// let addr = socket.local_addr().expect("Couldn't get local address");
|
||||
/// assert_eq!(addr.is_unnamed(), true);
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn is_unnamed(&self) -> bool {
|
||||
if let AddressKind::Unnamed = self.address() {
|
||||
@ -131,6 +168,29 @@ impl SocketAddr {
|
||||
}
|
||||
|
||||
/// Returns the contents of this address if it is a `pathname` address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// With a pathname:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixListener;
|
||||
/// use std::path::Path;
|
||||
///
|
||||
/// let socket = UnixListener::bind("/tmp/sock").unwrap();
|
||||
/// let addr = socket.local_addr().expect("Couldn't get local address");
|
||||
/// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock")));
|
||||
/// ```
|
||||
///
|
||||
/// Without a pathname:
|
||||
///
|
||||
/// ```
|
||||
/// use std::os::unix::net::UnixDatagram;
|
||||
///
|
||||
/// let socket = UnixDatagram::unbound().unwrap();
|
||||
/// let addr = socket.local_addr().expect("Couldn't get local address");
|
||||
/// assert_eq!(addr.as_pathname(), None);
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn as_pathname(&self) -> Option<&Path> {
|
||||
if let AddressKind::Pathname(path) = self.address() {
|
||||
@ -182,7 +242,7 @@ impl<'a> fmt::Display for AsciiEscaped<'a> {
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixStream;
|
||||
/// use std::io::prelude::*;
|
||||
///
|
||||
@ -212,6 +272,20 @@ impl fmt::Debug for UnixStream {
|
||||
|
||||
impl UnixStream {
|
||||
/// Connects to the socket named by `path`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixStream;
|
||||
///
|
||||
/// let socket = match UnixStream::connect("/tmp/sock") {
|
||||
/// Ok(sock) => sock,
|
||||
/// Err(e) => {
|
||||
/// println!("Couldn't connect: {:?}", e);
|
||||
/// return
|
||||
/// }
|
||||
/// };
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn connect<P: AsRef<Path>>(path: P) -> io::Result<UnixStream> {
|
||||
fn inner(path: &Path) -> io::Result<UnixStream> {
|
||||
@ -229,6 +303,20 @@ impl UnixStream {
|
||||
/// Creates an unnamed pair of connected sockets.
|
||||
///
|
||||
/// Returns two `UnixStream`s which are connected to each other.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixStream;
|
||||
///
|
||||
/// let (sock1, sock2) = match UnixStream::pair() {
|
||||
/// Ok((sock1, sock2)) => (sock1, sock2),
|
||||
/// Err(e) => {
|
||||
/// println!("Couldn't create a pair of sockets: {:?}", e);
|
||||
/// return
|
||||
/// }
|
||||
/// };
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn pair() -> io::Result<(UnixStream, UnixStream)> {
|
||||
let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_STREAM)?;
|
||||
@ -241,18 +329,45 @@ impl UnixStream {
|
||||
/// object references. Both handles will read and write the same stream of
|
||||
/// data, and options set on one stream will be propogated to the other
|
||||
/// stream.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixStream;
|
||||
///
|
||||
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
|
||||
/// let sock_copy = socket.try_clone().expect("Couldn't clone socket");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn try_clone(&self) -> io::Result<UnixStream> {
|
||||
self.0.duplicate().map(UnixStream)
|
||||
}
|
||||
|
||||
/// Returns the socket address of the local half of this connection.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixStream;
|
||||
///
|
||||
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
|
||||
/// let addr = socket.local_addr().expect("Couldn't get local address");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn local_addr(&self) -> io::Result<SocketAddr> {
|
||||
SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
|
||||
}
|
||||
|
||||
/// Returns the socket address of the remote half of this connection.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixStream;
|
||||
///
|
||||
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
|
||||
/// let addr = socket.peer_addr().expect("Couldn't get peer address");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
|
||||
SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) })
|
||||
@ -260,9 +375,23 @@ impl UnixStream {
|
||||
|
||||
/// Sets the read timeout for the socket.
|
||||
///
|
||||
/// If the provided value is `None`, then `read` calls will block
|
||||
/// indefinitely. It is an error to pass the zero `Duration` to this
|
||||
/// If the provided value is [`None`], then [`read()`] calls will block
|
||||
/// indefinitely. It is an error to pass the zero [`Duration`] to this
|
||||
/// method.
|
||||
///
|
||||
/// [`None`]: ../../../../std/option/enum.Option.html#variant.None
|
||||
/// [`read()`]: ../../../../std/io/trait.Read.html#tymethod.read
|
||||
/// [`Duration`]: ../../../../std/time/struct.Duration.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixStream;
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
|
||||
/// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
|
||||
self.0.set_timeout(timeout, libc::SO_RCVTIMEO)
|
||||
@ -270,33 +399,89 @@ impl UnixStream {
|
||||
|
||||
/// Sets the write timeout for the socket.
|
||||
///
|
||||
/// If the provided value is `None`, then `write` calls will block
|
||||
/// indefinitely. It is an error to pass the zero `Duration` to this
|
||||
/// If the provided value is [`None`], then [`write()`] calls will block
|
||||
/// indefinitely. It is an error to pass the zero [`Duration`] to this
|
||||
/// method.
|
||||
///
|
||||
/// [`None`]: ../../../../std/option/enum.Option.html#variant.None
|
||||
/// [`read()`]: ../../../../std/io/trait.Write.html#tymethod.write
|
||||
/// [`Duration`]: ../../../../std/time/struct.Duration.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixStream;
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
|
||||
/// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
|
||||
self.0.set_timeout(timeout, libc::SO_SNDTIMEO)
|
||||
}
|
||||
|
||||
/// Returns the read timeout of this socket.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixStream;
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
|
||||
/// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
|
||||
/// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0)));
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
|
||||
self.0.timeout(libc::SO_RCVTIMEO)
|
||||
}
|
||||
|
||||
/// Returns the write timeout of this socket.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixStream;
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
|
||||
/// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout");
|
||||
/// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0)));
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
|
||||
self.0.timeout(libc::SO_SNDTIMEO)
|
||||
}
|
||||
|
||||
/// Moves the socket into or out of nonblocking mode.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixStream;
|
||||
///
|
||||
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
|
||||
/// socket.set_nonblocking(true).expect("Couldn't set nonblocking");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
|
||||
self.0.set_nonblocking(nonblocking)
|
||||
}
|
||||
|
||||
/// Returns the value of the `SO_ERROR` option.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixStream;
|
||||
///
|
||||
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
|
||||
/// if let Ok(Some(err)) = socket.take_error() {
|
||||
/// println!("Got error: {:?}", err);
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
|
||||
self.0.take_error()
|
||||
@ -306,7 +491,19 @@ impl UnixStream {
|
||||
///
|
||||
/// This function will cause all pending and future I/O calls on the
|
||||
/// specified portions to immediately return with an appropriate value
|
||||
/// (see the documentation of `Shutdown`).
|
||||
/// (see the documentation of [`Shutdown`]).
|
||||
///
|
||||
/// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixStream;
|
||||
/// use std::net::Shutdown;
|
||||
///
|
||||
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
|
||||
/// socket.shutdown(Shutdown::Both).expect("shutdown function failed");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
|
||||
self.0.shutdown(how)
|
||||
@ -382,7 +579,7 @@ impl IntoRawFd for UnixStream {
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// ```no_run
|
||||
/// use std::thread;
|
||||
/// use std::os::unix::net::{UnixStream, UnixListener};
|
||||
///
|
||||
@ -405,9 +602,6 @@ impl IntoRawFd for UnixStream {
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // close the listener socket
|
||||
/// drop(listener);
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub struct UnixListener(Socket);
|
||||
@ -426,6 +620,20 @@ impl fmt::Debug for UnixListener {
|
||||
|
||||
impl UnixListener {
|
||||
/// Creates a new `UnixListener` bound to the specified socket.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixListener;
|
||||
///
|
||||
/// let listener = match UnixListener::bind("/path/to/the/socket") {
|
||||
/// Ok(sock) => sock,
|
||||
/// Err(e) => {
|
||||
/// println!("Couldn't connect: {:?}", e);
|
||||
/// return
|
||||
/// }
|
||||
/// };
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixListener> {
|
||||
fn inner(path: &Path) -> io::Result<UnixListener> {
|
||||
@ -445,8 +653,23 @@ impl UnixListener {
|
||||
/// Accepts a new incoming connection to this listener.
|
||||
///
|
||||
/// This function will block the calling thread until a new Unix connection
|
||||
/// is established. When established, the corersponding `UnixStream` and
|
||||
/// is established. When established, the corersponding [`UnixStream`] and
|
||||
/// the remote peer's address will be returned.
|
||||
///
|
||||
/// [`UnixStream`]: ../../../../std/os/unix/net/struct.UnixStream.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixListener;
|
||||
///
|
||||
/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
|
||||
///
|
||||
/// match listener.accept() {
|
||||
/// Ok((socket, addr)) => println!("Got a client: {:?}", addr),
|
||||
/// Err(e) => println!("accept function failed: {:?}", e),
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> {
|
||||
let mut storage: libc::sockaddr_un = unsafe { mem::zeroed() };
|
||||
@ -461,24 +684,66 @@ impl UnixListener {
|
||||
/// The returned `UnixListener` is a reference to the same socket that this
|
||||
/// object references. Both handles can be used to accept incoming
|
||||
/// connections and options set on one listener will affect the other.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixListener;
|
||||
///
|
||||
/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
|
||||
///
|
||||
/// let listener_copy = listener.try_clone().expect("try_clone failed");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn try_clone(&self) -> io::Result<UnixListener> {
|
||||
self.0.duplicate().map(UnixListener)
|
||||
}
|
||||
|
||||
/// Returns the local socket address of this listener.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixListener;
|
||||
///
|
||||
/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
|
||||
///
|
||||
/// let addr = listener.local_addr().expect("Couldn't get local address");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn local_addr(&self) -> io::Result<SocketAddr> {
|
||||
SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
|
||||
}
|
||||
|
||||
/// Moves the socket into or out of nonblocking mode.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixListener;
|
||||
///
|
||||
/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
|
||||
///
|
||||
/// listener.set_nonblocking(true).expect("Couldn't set non blocking");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
|
||||
self.0.set_nonblocking(nonblocking)
|
||||
}
|
||||
|
||||
/// Returns the value of the `SO_ERROR` option.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixListener;
|
||||
///
|
||||
/// let listener = UnixListener::bind("/tmp/sock").unwrap();
|
||||
///
|
||||
/// if let Ok(Some(err)) = listener.take_error() {
|
||||
/// println!("Got error: {:?}", err);
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
|
||||
self.0.take_error()
|
||||
@ -486,8 +751,35 @@ impl UnixListener {
|
||||
|
||||
/// Returns an iterator over incoming connections.
|
||||
///
|
||||
/// The iterator will never return `None` and will also not yield the
|
||||
/// peer's `SocketAddr` structure.
|
||||
/// The iterator will never return [`None`] and will also not yield the
|
||||
/// peer's [`SocketAddr`] structure.
|
||||
///
|
||||
/// [`None`]: ../../../../std/option/enum.Option.html#variant.None
|
||||
/// [`SocketAddr`]: struct.SocketAddr.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::thread;
|
||||
/// use std::os::unix::net::{UnixStream, UnixListener};
|
||||
///
|
||||
/// fn handle_client(stream: UnixStream) {
|
||||
/// // ...
|
||||
/// }
|
||||
///
|
||||
/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
|
||||
///
|
||||
/// for stream in listener.incoming() {
|
||||
/// match stream {
|
||||
/// Ok(stream) => {
|
||||
/// thread::spawn(|| handle_client(stream));
|
||||
/// }
|
||||
/// Err(err) => {
|
||||
/// break;
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn incoming<'a>(&'a self) -> Incoming<'a> {
|
||||
Incoming { listener: self }
|
||||
@ -525,9 +817,36 @@ impl<'a> IntoIterator for &'a UnixListener {
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over incoming connections to a `UnixListener`.
|
||||
/// An iterator over incoming connections to a [`UnixListener`].
|
||||
///
|
||||
/// It will never return `None`.
|
||||
/// It will never return [`None`].
|
||||
///
|
||||
/// [`None`]: ../../../../std/option/enum.Option.html#variant.None
|
||||
/// [`UnixListener`]: struct.UnixListener.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::thread;
|
||||
/// use std::os::unix::net::{UnixStream, UnixListener};
|
||||
///
|
||||
/// fn handle_client(stream: UnixStream) {
|
||||
/// // ...
|
||||
/// }
|
||||
///
|
||||
/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
|
||||
///
|
||||
/// for stream in listener.incoming() {
|
||||
/// match stream {
|
||||
/// Ok(stream) => {
|
||||
/// thread::spawn(|| handle_client(stream));
|
||||
/// }
|
||||
/// Err(err) => {
|
||||
/// break;
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub struct Incoming<'a> {
|
||||
@ -551,7 +870,7 @@ impl<'a> Iterator for Incoming<'a> {
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixDatagram;
|
||||
///
|
||||
/// let socket = UnixDatagram::bind("/path/to/my/socket").unwrap();
|
||||
@ -580,6 +899,20 @@ impl fmt::Debug for UnixDatagram {
|
||||
|
||||
impl UnixDatagram {
|
||||
/// Creates a Unix datagram socket bound to the given path.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixDatagram;
|
||||
///
|
||||
/// let sock = match UnixDatagram::bind("/path/to/the/socket") {
|
||||
/// Ok(sock) => sock,
|
||||
/// Err(e) => {
|
||||
/// println!("Couldn't bind: {:?}", e);
|
||||
/// return
|
||||
/// }
|
||||
/// };
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixDatagram> {
|
||||
fn inner(path: &Path) -> io::Result<UnixDatagram> {
|
||||
@ -596,6 +929,20 @@ impl UnixDatagram {
|
||||
}
|
||||
|
||||
/// Creates a Unix Datagram socket which is not bound to any address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixDatagram;
|
||||
///
|
||||
/// let sock = match UnixDatagram::unbound() {
|
||||
/// Ok(sock) => sock,
|
||||
/// Err(e) => {
|
||||
/// println!("Couldn't unbound: {:?}", e);
|
||||
/// return
|
||||
/// }
|
||||
/// };
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn unbound() -> io::Result<UnixDatagram> {
|
||||
let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_DGRAM)?;
|
||||
@ -605,6 +952,20 @@ impl UnixDatagram {
|
||||
/// Create an unnamed pair of connected sockets.
|
||||
///
|
||||
/// Returns two `UnixDatagrams`s which are connected to each other.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixDatagram;
|
||||
///
|
||||
/// let (sock1, sock2) = match UnixDatagram::pair() {
|
||||
/// Ok((sock1, sock2)) => (sock1, sock2),
|
||||
/// Err(e) => {
|
||||
/// println!("Couldn't unbound: {:?}", e);
|
||||
/// return
|
||||
/// }
|
||||
/// };
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn pair() -> io::Result<(UnixDatagram, UnixDatagram)> {
|
||||
let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_DGRAM)?;
|
||||
@ -613,8 +974,27 @@ impl UnixDatagram {
|
||||
|
||||
/// Connects the socket to the specified address.
|
||||
///
|
||||
/// The `send` method may be used to send data to the specified address.
|
||||
/// `recv` and `recv_from` will only receive data from that address.
|
||||
/// The [`send()`] method may be used to send data to the specified address.
|
||||
/// [`recv()`] and [`recv_from()`] will only receive data from that address.
|
||||
///
|
||||
/// [`send()`]: #method.send
|
||||
/// [`recv()`]: #method.recv
|
||||
/// [`recv_from()`]: #method.recv_from
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixDatagram;
|
||||
///
|
||||
/// let sock = UnixDatagram::unbound().unwrap();
|
||||
/// match sock.connect("/path/to/the/socket") {
|
||||
/// Ok(sock) => sock,
|
||||
/// Err(e) => {
|
||||
/// println!("Couldn't connect: {:?}", e);
|
||||
/// return
|
||||
/// }
|
||||
/// };
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn connect<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
|
||||
fn inner(d: &UnixDatagram, path: &Path) -> io::Result<()> {
|
||||
@ -631,15 +1011,35 @@ impl UnixDatagram {
|
||||
|
||||
/// Creates a new independently owned handle to the underlying socket.
|
||||
///
|
||||
/// The returned `UnixListener` is a reference to the same socket that this
|
||||
/// The returned `UnixDatagram` is a reference to the same socket that this
|
||||
/// object references. Both handles can be used to accept incoming
|
||||
/// connections and options set on one listener will affect the other.
|
||||
/// connections and options set on one side will affect the other.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixDatagram;
|
||||
///
|
||||
/// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap();
|
||||
///
|
||||
/// let sock_copy = sock.try_clone().expect("try_clone failed");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn try_clone(&self) -> io::Result<UnixDatagram> {
|
||||
self.0.duplicate().map(UnixDatagram)
|
||||
}
|
||||
|
||||
/// Returns the address of this socket.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixDatagram;
|
||||
///
|
||||
/// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap();
|
||||
///
|
||||
/// let addr = sock.local_addr().expect("Couldn't get local address");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn local_addr(&self) -> io::Result<SocketAddr> {
|
||||
SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
|
||||
@ -647,7 +1047,20 @@ impl UnixDatagram {
|
||||
|
||||
/// Returns the address of this socket's peer.
|
||||
///
|
||||
/// The `connect` method will connect the socket to a peer.
|
||||
/// The [`connect()`] method will connect the socket to a peer.
|
||||
///
|
||||
/// [`connect()`]: #method.connect
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixDatagram;
|
||||
///
|
||||
/// let sock = UnixDatagram::unbound().unwrap();
|
||||
/// sock.connect("/path/to/the/socket").unwrap();
|
||||
///
|
||||
/// let addr = sock.peer_addr().expect("Couldn't get peer address");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
|
||||
SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) })
|
||||
@ -657,6 +1070,19 @@ impl UnixDatagram {
|
||||
///
|
||||
/// On success, returns the number of bytes read and the address from
|
||||
/// whence the data came.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixDatagram;
|
||||
///
|
||||
/// let sock = UnixDatagram::unbound().unwrap();
|
||||
/// let mut buf = vec![0; 10];
|
||||
/// match sock.recv_from(buf.as_mut_slice()) {
|
||||
/// Ok((size, sender)) => println!("received {} bytes from {:?}", size, sender),
|
||||
/// Err(e) => println!("recv_from function failed: {:?}", e),
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
|
||||
let mut count = 0;
|
||||
@ -684,6 +1110,16 @@ impl UnixDatagram {
|
||||
/// Receives data from the socket.
|
||||
///
|
||||
/// On success, returns the number of bytes read.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixDatagram;
|
||||
///
|
||||
/// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap();
|
||||
/// let mut buf = vec![0; 10];
|
||||
/// sock.recv(buf.as_mut_slice()).expect("recv function failed");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.read(buf)
|
||||
@ -692,6 +1128,15 @@ impl UnixDatagram {
|
||||
/// Sends data on the socket to the specified address.
|
||||
///
|
||||
/// On success, returns the number of bytes written.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixDatagram;
|
||||
///
|
||||
/// let sock = UnixDatagram::unbound().unwrap();
|
||||
/// sock.send_to(b"omelette au fromage", "/some/sock").expect("send_to function failed");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn send_to<P: AsRef<Path>>(&self, buf: &[u8], path: P) -> io::Result<usize> {
|
||||
fn inner(d: &UnixDatagram, buf: &[u8], path: &Path) -> io::Result<usize> {
|
||||
@ -716,6 +1161,16 @@ impl UnixDatagram {
|
||||
/// will return an error if the socket has not already been connected.
|
||||
///
|
||||
/// On success, returns the number of bytes written.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixDatagram;
|
||||
///
|
||||
/// let sock = UnixDatagram::unbound().unwrap();
|
||||
/// sock.connect("/some/sock").expect("Couldn't connect");
|
||||
/// sock.send(b"omelette au fromage").expect("send_to function failed");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.0.write(buf)
|
||||
@ -723,9 +1178,24 @@ impl UnixDatagram {
|
||||
|
||||
/// Sets the read timeout for the socket.
|
||||
///
|
||||
/// If the provided value is `None`, then `recv` and `recv_from` calls will
|
||||
/// block indefinitely. It is an error to pass the zero `Duration` to this
|
||||
/// If the provided value is [`None`], then [`recv()`] and [`recv_from()`] calls will
|
||||
/// block indefinitely. It is an error to pass the zero [`Duration`] to this
|
||||
/// method.
|
||||
///
|
||||
/// [`None`]: ../../../../std/option/enum.Option.html#variant.None
|
||||
/// [`recv()`]: #method.recv
|
||||
/// [`recv_from()`]: #method.recv_from
|
||||
/// [`Duration`]: ../../../../std/time/struct.Duration.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::os::unix::net::UnixDatagram;
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let sock = UnixDatagram::unbound().unwrap();
|
||||
/// sock.set_read_timeout(Some(Duration::new(1, 0))).expect("set_read_timeout function failed");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
|
||||
self.0.set_timeout(timeout, libc::SO_RCVTIMEO)
|
||||
@ -733,33 +1203,92 @@ impl UnixDatagram {
|
||||
|
||||
/// Sets the write timeout for the socket.
|
||||
///
|
||||
/// If the provided value is `None`, then `send` and `send_to` calls will
|
||||
/// block indefinitely. It is an error to pass the zero `Duration` to this
|
||||
/// If the provided value is [`None`], then [`send()`] and [`send_to()`] calls will
|
||||
/// block indefinitely. It is an error to pass the zero [`Duration`] to this
|
||||
/// method.
|
||||
///
|
||||
/// [`None`]: ../../../../std/option/enum.Option.html#variant.None
|
||||
/// [`send()`]: #method.send
|
||||
/// [`send_to()`]: #method.send_to
|
||||
/// [`Duration`]: ../../../../std/time/struct.Duration.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::os::unix::net::UnixDatagram;
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let sock = UnixDatagram::unbound().unwrap();
|
||||
/// sock.set_write_timeout(Some(Duration::new(1, 0)))
|
||||
/// .expect("set_write_timeout function failed");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
|
||||
self.0.set_timeout(timeout, libc::SO_SNDTIMEO)
|
||||
}
|
||||
|
||||
/// Returns the read timeout of this socket.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::os::unix::net::UnixDatagram;
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let sock = UnixDatagram::unbound().unwrap();
|
||||
/// sock.set_read_timeout(Some(Duration::new(1, 0))).expect("set_read_timeout function failed");
|
||||
/// assert_eq!(sock.read_timeout().unwrap(), Some(Duration::new(1, 0)));
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
|
||||
self.0.timeout(libc::SO_RCVTIMEO)
|
||||
}
|
||||
|
||||
/// Returns the write timeout of this socket.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::os::unix::net::UnixDatagram;
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let sock = UnixDatagram::unbound().unwrap();
|
||||
/// sock.set_write_timeout(Some(Duration::new(1, 0)))
|
||||
/// .expect("set_write_timeout function failed");
|
||||
/// assert_eq!(sock.write_timeout().unwrap(), Some(Duration::new(1, 0)));
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
|
||||
self.0.timeout(libc::SO_SNDTIMEO)
|
||||
}
|
||||
|
||||
/// Moves the socket into or out of nonblocking mode.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::os::unix::net::UnixDatagram;
|
||||
///
|
||||
/// let sock = UnixDatagram::unbound().unwrap();
|
||||
/// sock.set_nonblocking(true).expect("set_nonblocking function failed");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
|
||||
self.0.set_nonblocking(nonblocking)
|
||||
}
|
||||
|
||||
/// Returns the value of the `SO_ERROR` option.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixDatagram;
|
||||
///
|
||||
/// let sock = UnixDatagram::unbound().unwrap();
|
||||
/// if let Ok(Some(err)) = sock.take_error() {
|
||||
/// println!("Got error: {:?}", err);
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
|
||||
self.0.take_error()
|
||||
@ -769,7 +1298,17 @@ impl UnixDatagram {
|
||||
///
|
||||
/// This function will cause all pending and future I/O calls on the
|
||||
/// specified portions to immediately return with an appropriate value
|
||||
/// (see the documentation of `Shutdown`).
|
||||
/// (see the documentation of [`Shutdown`]).
|
||||
///
|
||||
/// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixDatagram;
|
||||
/// use std::net::Shutdown;
|
||||
///
|
||||
/// let sock = UnixDatagram::unbound().unwrap();
|
||||
/// sock.shutdown(Shutdown::Both).expect("shutdown function failed");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
|
||||
self.0.shutdown(how)
|
||||
|
@ -12,6 +12,7 @@
|
||||
#![unstable(feature = "thread_local_internals", issue = "0")]
|
||||
|
||||
use cell::{Cell, UnsafeCell};
|
||||
use fmt;
|
||||
use intrinsics;
|
||||
use ptr;
|
||||
|
||||
@ -24,6 +25,12 @@ pub struct Key<T> {
|
||||
dtor_running: Cell<bool>,
|
||||
}
|
||||
|
||||
impl<T> fmt::Debug for Key<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("Key { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T> ::marker::Sync for Key<T> { }
|
||||
|
||||
impl<T> Key<T> {
|
||||
|
@ -18,6 +18,7 @@ use sys::cvt;
|
||||
use sys_common::AsInner;
|
||||
use sys_common::io::read_to_end_uninitialized;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FileDesc {
|
||||
fd: c_int,
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ pub struct DirEntry {
|
||||
name: Box<[u8]>
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OpenOptions {
|
||||
// generic
|
||||
read: bool,
|
||||
@ -86,6 +86,7 @@ pub struct FilePermissions { mode: mode_t }
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub struct FileType { mode: mode_t }
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DirBuilder { mode: mode_t }
|
||||
|
||||
impl FileAttr {
|
||||
|
@ -58,7 +58,7 @@ pub struct DirEntry {
|
||||
data: c::WIN32_FIND_DATAW,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OpenOptions {
|
||||
// generic
|
||||
read: bool,
|
||||
@ -79,6 +79,7 @@ pub struct OpenOptions {
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct FilePermissions { attrs: c::DWORD }
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DirBuilder;
|
||||
|
||||
impl fmt::Debug for ReadDir {
|
||||
|
@ -23,6 +23,7 @@
|
||||
//! `std::sys` from the standard library.
|
||||
|
||||
#![allow(missing_docs)]
|
||||
#![allow(missing_debug_implementations)]
|
||||
|
||||
use sync::Once;
|
||||
use sys;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user