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:
bors 2016-12-20 22:21:53 +00:00
commit 164619a8cf
135 changed files with 2615 additions and 1526 deletions

View File

@ -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
View File

@ -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",

View File

@ -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;

View File

@ -12,6 +12,8 @@
//!
//! See comments in `src/bootstrap/rustc.rs` for more information.
#![deny(warnings)]
extern crate bootstrap;
use std::env;

View File

@ -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()

View File

@ -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));
}

View File

@ -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);

View File

@ -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
# =============================================================================

View File

@ -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));

View File

@ -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()

View File

@ -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);

View File

@ -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

View File

@ -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() {

View File

@ -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

View File

@ -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,

View File

@ -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" \

View File

@ -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 | \

View File

@ -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:

View File

@ -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");

View File

@ -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> {

View File

@ -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)

View File

@ -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

View File

@ -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))
}
}

View File

@ -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.

View File

@ -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);

View File

@ -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##"

View File

@ -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(())
})?;

View File

@ -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, &macro_def.attrs);
}

View File

@ -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(),
}
}

View File

@ -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

View File

@ -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()));
}
}

View File

@ -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}}",

View File

@ -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;

View File

@ -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>,
}

View File

@ -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") }

View File

@ -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);
}
}

View File

@ -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()),
};

View File

@ -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

View File

@ -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()),

View File

@ -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);
}

View File

@ -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)
}
}

View File

@ -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);

View File

@ -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,

View File

@ -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;

View File

@ -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,

View File

@ -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])
}

View File

@ -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);
}
}
}

View File

@ -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) => {

View File

@ -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)
}),

View File

@ -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,

View File

@ -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,
})

View File

@ -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

View File

@ -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(&macro_def.body)
})),
visibility: ty::Visibility::Public,
span: self.lazy(&macro_def.span),
def_key: self.encode_def_key(def_id),
attributes: self.encode_attributes(&macro_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);

View File

@ -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>>,

View File

@ -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");
}

View File

@ -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);

View File

@ -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));
}

View File

@ -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);
}
}
}

View File

@ -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, &note_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);
}
}

View File

@ -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);

View File

@ -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(),

View File

@ -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();

View File

@ -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,

View File

@ -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>,

View File

@ -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");

View File

@ -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,
}
}
}

View File

@ -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,

View File

@ -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")));

View File

@ -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,

View File

@ -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,

View File

@ -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);

View File

@ -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 {

View File

@ -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 }
}

View File

@ -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,
}

View File

@ -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

View File

@ -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::*;

View File

@ -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)]

View File

@ -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));

View File

@ -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

View File

@ -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 {

View File

@ -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;

View File

@ -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")]

View File

@ -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 {

View File

@ -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

View File

@ -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,

View File

@ -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")]

View File

@ -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>()`.

View File

@ -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".
///

View File

@ -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.

View File

@ -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>
}

View File

@ -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
}

View File

@ -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

View File

@ -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;

View File

@ -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")]

View File

@ -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)

View File

@ -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> {

View File

@ -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,
}

View File

@ -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 {

View File

@ -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 {

View File

@ -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