######################################################################
# 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
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",
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"
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):
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
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")
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()
//! 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;
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));
}
#[derive(RustcDecodable, Default)]
struct TomlConfig {
build: Option<Build>,
+ install: Option<Install>,
llvm: Option<Llvm>,
rust: Option<Rust>,
target: Option<HashMap<String, TomlTarget>>,
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 {
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)) => {
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);
# 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
# =============================================================================
}
/// 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));
// 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,
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") {
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"))
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
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();
}
}
+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,
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 | \
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:
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");
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>>,
}
/// 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>>,
}
/// 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>>,
}
/// 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>>,
}
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
///
}
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> {
/// 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)
/// Returns an iterator over the possibly contained value.
///
+ /// The iterator yields one value if the result is [`Ok`], otherwise none.
+ ///
/// # Examples
///
/// Basic usage:
/// 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> {
/// Returns a mutable iterator over the possibly contained value.
///
+ /// The iterator yields one value if the result is [`Ok`], otherwise none.
+ ///
/// # Examples
///
/// Basic usage:
/// 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> {
/// Returns a consuming iterator over the possibly contained value.
///
+ /// The iterator yields one value if the result is [`Ok`], otherwise none.
+ ///
/// # Examples
///
/// Basic usage:
/// 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() }
/// 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> }
/// 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> }
#[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
// * The `raw` and `bytes` submodules.
// * Boilerplate trait implementations.
+use borrow::Borrow;
use cmp::Ordering::{self, Less, Equal, Greater};
use cmp;
use fmt;
#[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")]
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]
}
#[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))
}
}
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!
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.
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);
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);
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##"
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(())
})?;
pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef) {
visitor.visit_id(macro_def.id);
visitor.visit_name(macro_def.span, macro_def.name);
- walk_opt_name(visitor, macro_def.span, macro_def.imported_from);
walk_list!(visitor, visit_attribute, ¯o_def.attrs);
}
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 {
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(),
}
}
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};
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 {
ignore_nested_items: true
};
- assert_eq!(parent_def_path.krate, parent_def_id.krate);
collector.insert_entry(parent_node, RootInlinedParent(parent));
collector
// 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;
/// 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)>,
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 {
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 {
}
}
}
-
-// 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()));
- }
-}
// 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;
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
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
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 {
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;
}
}
-/// 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 {
// 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,
/// 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
}
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> {
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
}
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.
}
};
- 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
}
Impl |
CrateRoot |
- InlinedRoot(_) |
Misc |
ClosureExpr |
StructCtor |
// 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}}",
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};
/// 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
}
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
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
}
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> {
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 {
}
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 {
}
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 {
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;
pub attrs: HirVec<Attribute>,
pub id: NodeId,
pub span: Span,
- pub imported_from: Option<Name>,
- pub allow_internal_unstable: bool,
pub body: HirVec<TokenTree>,
}
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};
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;
// 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>
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") }
}
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, |_| {});
}
}
}
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);
}
}
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 {
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()));
}
}
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()),
};
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 {
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
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;
}
}
- /// 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,
/// 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>,
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())),
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()),
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);
}
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};
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,
/// 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)
}
}
/// 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,
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,
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);
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);
// 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;
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;
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,
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,
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;
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,
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])
}
}
}
+ // 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") {
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);
}
}
}
/// 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 {
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) => {
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;
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)
}),
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;
/// 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,
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;
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
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:
//
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,
})
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;
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();
}
}
- 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()
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,
(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(),
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),
});
}
}
_ => {}
}
- 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 {
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)
})
}
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())
};
// 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());
}
self.entry(id)
.children
.decode(self)
- .map(|index| self.item_name(&self.entry(index)))
+ .map(|index| self.item_name(index))
.collect()
}
}
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,
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!(),
}
}
}
}
- 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
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;
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())
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());
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
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),
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),
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),
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),
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) => {
/// Serialize the text of exported macros
fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) -> Entry<'tcx> {
- let def_id = self.tcx.map.local_def_id(macro_def.id);
Entry {
kind: EntryKind::MacroDef(self.lazy(&MacroDef {
body: ::syntax::print::pprust::tts_to_string(¯o_def.body)
})),
visibility: ty::Visibility::Public,
span: self.lazy(¯o_def.span),
- def_key: self.encode_def_key(def_id),
attributes: self.encode_attributes(¯o_def.attrs),
children: LazySeq::empty(),
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),
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,
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,
})
.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> {
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();
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,
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);
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>,
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>>,
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");
}
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");
}
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};
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};
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,
- }
+ })
}
}
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);
}
}
/// 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);
}
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(
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,
}
};
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;
// 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,
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);
}
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.
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);
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.
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| {
// 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!"),
// 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))
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) {
}
/// 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 {
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);
}
}
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(..) |
}
}
- 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))
})
})
}
/// 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);
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);
}
}
- 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;
}
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 {
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 {
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,
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);
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};
use errors::DiagnosticBuilder;
}
/// 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.
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
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,
}
}
- 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));
}
}
}
}
-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())
}
}
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
}
}
}
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>>,
}
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);
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);
}
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);
}
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 } => {
self.ambiguity_errors.push(AmbiguityError {
- span: span, name: name, lexical: false, b1: b1, b2: b2,
+ span: span, name: ident.name, lexical: false, b1: b1, b2: b2,
});
true
}
}
}
- 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);
}
}
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.
}
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));
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;
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(..) |
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),
});
}
}
- 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;
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());
- }
-
- 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);
+ 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,
+ }
+ }
- 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
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,
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
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 {
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 {
};
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));
}
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};
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);
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);
}
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),
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),
_ => {
};
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
}
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> {
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,
};
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,
});
}
}
- 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,
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();
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);
+ }
+ }
}
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};
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;
#[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 {
}
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 &&
});
}
}
- 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));
}
}
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),
}
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);
}
// 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()
}
}
- NameBinding {
+ self.arenas.alloc_name_binding(NameBinding {
kind: NameBindingKind::Import {
binding: binding,
directive: directive,
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() &&
// 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);
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);
}
}
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);
});
}
}
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()
});
}
}
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);
}
}
}
_ => 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.
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);
}
}
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,
_ => {}
}
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
}
if ns == TypeNS && binding.is_extern_crate() {
let msg = format!("extern crate `{}` is private, and cannot be reexported \
(error E0364), consider declaring with `pub`",
- name);
+ ident);
self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg);
} else if ns == TypeNS {
struct_span_err!(self.session, directive.span, E0365,
- "`{}` is private, and cannot be reexported", name)
- .span_label(directive.span, &format!("reexport of private `{}`", name))
- .note(&format!("consider declaring type or module `{}` with `pub`", name))
+ "`{}` is private, and cannot be reexported", ident)
+ .span_label(directive.span, &format!("reexport of private `{}`", ident))
+ .note(&format!("consider declaring type or module `{}` with `pub`", ident))
.emit();
} else {
- let msg = format!("`{}` is private, and cannot be reexported", name);
+ let msg = format!("`{}` is private, and cannot be reexported", ident);
let note_msg =
- format!("consider marking `{}` as `pub` in the imported module", name);
+ format!("consider marking `{}` as `pub` in the imported module", ident);
struct_span_err!(self.session, directive.span, E0364, "{}", &msg)
.span_note(directive.span, ¬e_msg)
.emit();
// 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,
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 = resolution.borrow();
let binding = match resolution.binding {
Some(binding) => binding,
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 });
}
}
!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);
}
}
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);
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();
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,
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>,
}
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");
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;
}
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
// 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),
})
}
}
}
// 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,
}
}
}
#![stable(feature = "rust1", since = "1.0.0")]
+use fmt;
use mem;
use ops::Range;
use iter::FusedIterator;
#[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,
.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")));
}
}
+#[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> {
/// 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.
}
}
+#[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> {
}
}
+#[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.
#[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);
#[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;
#[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);
#[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
}
}
+#[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,
#[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;
#[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;
#[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> {
}
}
+#[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,
{
}
+#[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> {
{
}
+#[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> {
{
}
+#[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,
// 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>,
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>>,
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);
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);
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
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)]
}
}
+#[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;
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 {
/// .create(true)
/// .open("foo.txt");
/// ```
-#[derive(Clone)]
+#[derive(Clone, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct OpenOptions(fs_imp::OpenOptions);
///
/// 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,
}
}
+#[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 }
}
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> {
///
/// [`take()`]: trait.Read.html#method.take
#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Debug)]
pub struct Take<T> {
inner: T,
limit: u64,
///
/// [`bytes()`]: trait.Read.html#method.bytes
#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Debug)]
pub struct Bytes<R> {
inner: 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,
}
///
/// [split]: trait.BufRead.html#method.split
#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Debug)]
pub struct Split<B> {
buf: B,
delim: u8,
///
/// [lines]: trait.BufRead.html#method.lines
#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Debug)]
pub struct Lines<B> {
buf: B,
}
}
}
+#[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> {
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
}
}
+#[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> {
}
}
+#[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.
}
}
+#[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> {
}
}
+#[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
#![allow(missing_copy_implementations)]
+use fmt;
use io::{self, Read, Write, ErrorKind, BufRead};
/// Copies the entire contents of a reader into a writer.
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
}
}
+#[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
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::*;
#![no_std]
#![deny(missing_docs)]
+#![deny(missing_debug_implementations)]
// Tell the compiler to link to either panic_abort or panic_unwind
#![needs_panic_runtime]
#![feature(panic_unwind)]
#![feature(placement_in_syntax)]
#![feature(prelude_import)]
+#![feature(pub_restricted)]
#![feature(rand)]
#![feature(raw)]
#![feature(repr_simd)]
}
}
+#[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 {
}
#[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));
#![stable(feature = "rust1", since = "1.0.0")]
+use fmt;
use io::{self, Error, ErrorKind};
use sys_common::net as net_imp;
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
/// [`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 {
crates.io should be used instead for the correct \
definitions")]
#![allow(deprecated)]
+#![allow(missing_debug_implementations)]
use os::raw::c_ulong;
pub type pthread_t = usize;
#[repr(C)]
-#[derive(Clone)]
+#[derive(Clone, Debug)]
#[stable(feature = "raw_ext", since = "1.1.0")]
pub struct stat {
#[stable(feature = "raw_ext", since = "1.1.0")]
#![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",
#[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 {
use any::Any;
use cell::UnsafeCell;
+use fmt;
use ops::{Deref, DerefMut};
use panicking;
use ptr::{Unique, Shared};
}
}
+#[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
/// panic!("Normal panic");
/// ```
#[stable(feature = "panic_hooks", since = "1.10.0")]
+#[derive(Debug)]
pub struct PanicInfo<'a> {
payload: &'a (Any + Send),
location: Location<'a>,
///
/// panic!("Normal panic");
/// ```
+#[derive(Debug)]
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub struct Location<'a> {
file: &'a str,
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`].
///
}
}
+#[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`].
///
}
}
+#[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`].
///
}
}
+#[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.
///
}
}
+#[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")]
#![unstable(feature = "rand", issue = "0")]
use cell::RefCell;
+use fmt;
use io;
use mem;
use rc::Rc;
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>()`.
// 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
#[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.
///
}
}
+#[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".
///
// 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;
}
}
+#[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.
/// 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>
}
/// 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>
}
/// 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>
}
}
}
+#[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
}
// 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};
/// 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,
}
}
}
+#[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
}
}
+#[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;
}
/// 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 {
}
/// Returns true if and only if the address is unnamed.
+ ///
+ /// # Examples
+ ///
+ /// A named address:
+ ///
+ /// ```
+ /// 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() {
}
/// Returns the contents of this address if it is a `pathname` address.
+ ///
+ /// # Examples
+ ///
+ /// With a pathname:
+ ///
+ /// ```
+ /// 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;
+ /// use std::path::Path;
+ ///
+ /// 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() {
///
/// # Examples
///
-/// ```rust,no_run
+/// ```no_run
/// use std::os::unix::net::UnixStream;
/// use std::io::prelude::*;
///
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> {
/// 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)?;
/// 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) })
/// 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)
/// 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()
///
/// 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)
///
/// # Examples
///
-/// ```rust,no_run
+/// ```no_run
/// use std::thread;
/// use std::os::unix::net::{UnixStream, UnixListener};
///
/// }
/// }
/// }
-///
-/// // close the listener socket
-/// drop(listener);
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub struct UnixListener(Socket);
impl UnixListener {
/// Creates a new `UnixListener` bound to the specified socket.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// 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> {
/// 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() };
/// 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()
/// 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 }
}
}
-/// An iterator over incoming connections to a `UnixListener`.
+/// An iterator over incoming connections to a [`UnixListener`].
+///
+/// It will never return [`None`].
+///
+/// [`None`]: ../../../../std/option/enum.Option.html#variant.None
+/// [`UnixListener`]: struct.UnixListener.html
+///
+/// # Examples
///
-/// It will never return `None`.
+/// ```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> {
///
/// # Examples
///
-/// ```rust,no_run
+/// ```no_run
/// use std::os::unix::net::UnixDatagram;
///
/// let socket = UnixDatagram::bind("/path/to/my/socket").unwrap();
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> {
}
/// 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)?;
/// 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)?;
/// 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<()> {
/// 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) })
/// 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) })
///
/// 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;
/// 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)
/// 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> {
/// 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)
/// 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)
/// 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()
///
/// 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)
#![unstable(feature = "thread_local_internals", issue = "0")]
use cell::{Cell, UnsafeCell};
+use fmt;
use intrinsics;
use ptr;
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> {
use sys_common::AsInner;
use sys_common::io::read_to_end_uninitialized;
+#[derive(Debug)]
pub struct FileDesc {
fd: c_int,
}
name: Box<[u8]>
}
-#[derive(Clone)]
+#[derive(Clone, Debug)]
pub struct OpenOptions {
// generic
read: bool,
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct FileType { mode: mode_t }
+#[derive(Debug)]
pub struct DirBuilder { mode: mode_t }
impl FileAttr {
data: c::WIN32_FIND_DATAW,
}
-#[derive(Clone)]
+#[derive(Clone, Debug)]
pub struct OpenOptions {
// generic
read: bool,
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct FilePermissions { attrs: c::DWORD }
+#[derive(Debug)]
pub struct DirBuilder;
impl fmt::Debug for ReadDir {
#![unstable(feature = "thread_local_internals", issue = "0")]
use cell::UnsafeCell;
+use fmt;
use mem;
/// A thread local storage key which owns its contents.
init: fn() -> T,
}
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<T: 'static> fmt::Debug for LocalKey<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.pad("LocalKey { .. }")
+ }
+}
+
/// Declare a new thread local storage key of type `std::thread::LocalKey`.
///
/// # Syntax
#[unstable(feature = "thread_local_state",
reason = "state querying was recently added",
issue = "27716")]
-#[derive(Eq, PartialEq, Copy, Clone)]
+#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum LocalKeyState {
/// All keys are in this state whenever a thread starts. Keys will
/// transition to the `Valid` state once the first call to `with` happens
#[doc(hidden)]
pub mod os {
use cell::{Cell, UnsafeCell};
+ use fmt;
use marker;
use ptr;
use sys_common::thread_local::StaticKey as OsStaticKey;
marker: marker::PhantomData<Cell<T>>,
}
+ #[stable(feature = "std_debug", since = "1.15.0")]
+ 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> { }
struct Value<T: 'static> {
/// Thread configuration. Provides detailed control over the properties
/// and behavior of new threads.
#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Debug)]
pub struct Builder {
// A name for the thread-to-be, for identification in panic messages
name: Option<String>,
}
}
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for ThreadId {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.pad("ThreadId { .. }")
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
// Thread
////////////////////////////////////////////////////////////////////////////////
fn into_inner(self) -> imp::Thread { self.0.native.unwrap() }
}
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<T> fmt::Debug for JoinHandle<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.pad("JoinHandle { .. }")
+ }
+}
+
fn _assert_sync_and_send() {
fn _assert_both<T: Send + Sync>() {}
_assert_both::<JoinHandle<()>>();
const NANOS_PER_MILLI: u32 = 1_000_000;
const MILLIS_PER_SEC: u64 = 1_000;
-/// A duration type to represent a span of time, typically used for system
+/// A `Duration` type to represent a span of time, typically used for system
/// timeouts.
///
-/// Each duration is composed of a number of seconds and nanosecond precision.
+/// Each `Duration` is composed of a number of seconds and nanosecond precision.
/// APIs binding a system timeout will typically round up the nanosecond
/// precision if the underlying system does not support that level of precision.
///
-/// Durations implement many common traits, including `Add`, `Sub`, and other
-/// ops traits. Currently a duration may only be inspected for its number of
-/// seconds and its nanosecond precision.
+/// `Duration`s implement many common traits, including [`Add`], [`Sub`], and other
+/// [`ops`] traits.
+///
+/// [`Add`]: ../../std/ops/trait.Add.html
+/// [`Sub`]: ../../std/ops/trait.Sub.html
+/// [`ops`]: ../../std/ops/index.html
///
/// # Examples
///
///
/// This constructor will panic if the carry from the nanoseconds overflows
/// the seconds counter.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::time::Duration;
+ ///
+ /// let five_seconds = Duration::new(5, 0);
+ /// ```
#[stable(feature = "duration", since = "1.3.0")]
#[inline]
pub fn new(secs: u64, nanos: u32) -> Duration {
}
/// Creates a new `Duration` from the specified number of seconds.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::time::Duration;
+ ///
+ /// let five_seconds = Duration::from_secs(5);
+ /// ```
#[stable(feature = "duration", since = "1.3.0")]
#[inline]
pub fn from_secs(secs: u64) -> Duration {
}
/// Creates a new `Duration` from the specified number of milliseconds.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::time::Duration;
+ ///
+ /// let five_seconds = Duration::from_millis(5000);
+ /// ```
#[stable(feature = "duration", since = "1.3.0")]
#[inline]
pub fn from_millis(millis: u64) -> Duration {
Duration { secs: secs, nanos: nanos }
}
- /// Returns the number of whole seconds represented by this duration.
+ /// Returns the number of whole seconds represented by this `Duration`.
///
/// The extra precision represented by this duration is ignored (i.e. extra
/// nanoseconds are not represented in the returned value).
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::time::Duration;
+ ///
+ /// let five_seconds = Duration::new(5, 0);
+ /// assert_eq!(five_seconds.as_secs(), 5);
+ /// ```
#[stable(feature = "duration", since = "1.3.0")]
#[inline]
pub fn as_secs(&self) -> u64 { self.secs }
- /// Returns the nanosecond precision represented by this duration.
+ /// Returns the nanosecond precision represented by this `Duration`.
///
/// This method does **not** return the length of the duration when
/// represented by nanoseconds. The returned number always represents a
/// fractional portion of a second (i.e. it is less than one billion).
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::time::Duration;
+ ///
+ /// let duration = Duration::from_millis(5010);
+ /// assert_eq!(duration.subsec_nanos(), 10000000);
+ /// ```
#[stable(feature = "duration", since = "1.3.0")]
#[inline]
pub fn subsec_nanos(&self) -> u32 { self.nanos }
- /// Checked duration addition. Computes `self + other`, returning `None`
+ /// Checked `Duration` addition. Computes `self + other`, returning [`None`]
/// if overflow occurred.
///
+ /// [`None`]: ../../std/option/enum.Option.html#variant.None
+ ///
/// # Examples
///
/// Basic usage:
}
}
- /// Checked duration subtraction. Computes `self + other`, returning `None`
+ /// Checked `Duration` subtraction. Computes `self - other`, returning [`None`]
/// if the result would be negative or if underflow occurred.
///
+ /// [`None`]: ../../std/option/enum.Option.html#variant.None
+ ///
/// # Examples
///
/// Basic usage:
}
}
- /// Checked duration multiplication. Computes `self * other`, returning
- /// `None` if underflow or overflow occurred.
+ /// Checked `Duration` multiplication. Computes `self * other`, returning
+ /// [`None`] if overflow occurred.
+ ///
+ /// [`None`]: ../../std/option/enum.Option.html#variant.None
///
/// # Examples
///
}
}
- /// Checked duration division. Computes `self / other`, returning `None`
- /// if `other == 0` or the operation results in underflow or overflow.
+ /// Checked `Duration` division. Computes `self / other`, returning [`None`]
+ /// if `other == 0`.
+ ///
+ /// [`None`]: ../../std/option/enum.Option.html#variant.None
///
/// # Examples
///
Ident { name: name, ctxt: SyntaxContext::empty() }
}
- /// Maps a string to an identifier with an empty syntax context.
- pub fn from_str(s: &str) -> Ident {
- Ident::with_empty_ctxt(Symbol::intern(s))
- }
+ /// Maps a string to an identifier with an empty syntax context.
+ pub fn from_str(s: &str) -> Ident {
+ Ident::with_empty_ctxt(Symbol::intern(s))
+ }
+
+ pub fn unhygienize(&self) -> Ident {
+ Ident { name: self.name, ctxt: SyntaxContext::empty() }
+ }
}
impl fmt::Debug for Ident {
Path {
span: s,
global: false,
- segments: vec![
- PathSegment {
- identifier: identifier,
- parameters: PathParameters::none()
- }
- ],
+ segments: vec![identifier.into()],
}
}
}
/// this is more than just simple syntactic sugar; the use of
/// parens affects the region binding rules, so we preserve the
/// distinction.
- pub parameters: PathParameters,
+ /// The `Option<P<..>>` wrapper is purely a size optimization;
+ /// `None` is used to represent both `Path` and `Path<>`.
+ pub parameters: Option<P<PathParameters>>,
+}
+
+impl From<Ident> for PathSegment {
+ fn from(id: Ident) -> Self {
+ PathSegment { identifier: id, parameters: None }
+ }
}
/// Parameters of a path segment.
Parenthesized(ParenthesizedParameterData),
}
-impl PathParameters {
- pub fn none() -> PathParameters {
- PathParameters::AngleBracketed(AngleBracketedParameterData {
- lifetimes: Vec::new(),
- types: P::new(),
- bindings: P::new(),
- })
- }
-
- pub fn is_empty(&self) -> bool {
- match *self {
- PathParameters::AngleBracketed(ref data) => data.is_empty(),
-
- // Even if the user supplied no types, something like
- // `X()` is equivalent to `X<(),()>`.
- PathParameters::Parenthesized(..) => false,
- }
- }
-
- pub fn has_lifetimes(&self) -> bool {
- match *self {
- PathParameters::AngleBracketed(ref data) => !data.lifetimes.is_empty(),
- PathParameters::Parenthesized(_) => false,
- }
- }
-
- pub fn has_types(&self) -> bool {
- match *self {
- PathParameters::AngleBracketed(ref data) => !data.types.is_empty(),
- PathParameters::Parenthesized(..) => true,
- }
- }
-
- /// Returns the types that the user wrote. Note that these do not necessarily map to the type
- /// parameters in the parenthesized case.
- pub fn types(&self) -> Vec<&P<Ty>> {
- match *self {
- PathParameters::AngleBracketed(ref data) => {
- data.types.iter().collect()
- }
- PathParameters::Parenthesized(ref data) => {
- data.inputs.iter()
- .chain(data.output.iter())
- .collect()
- }
- }
- }
-
- pub fn lifetimes(&self) -> Vec<&Lifetime> {
- match *self {
- PathParameters::AngleBracketed(ref data) => {
- data.lifetimes.iter().collect()
- }
- PathParameters::Parenthesized(_) => {
- Vec::new()
- }
- }
- }
-
- pub fn bindings(&self) -> Vec<&TypeBinding> {
- match *self {
- PathParameters::AngleBracketed(ref data) => {
- data.bindings.iter().collect()
- }
- PathParameters::Parenthesized(_) => {
- Vec::new()
- }
- }
- }
-}
-
/// A path like `Foo<'a, T>`
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Default)]
pub struct AngleBracketedParameterData {
/// The lifetime parameters for this path segment.
pub lifetimes: Vec<Lifetime>,
pub bindings: P<[TypeBinding]>,
}
-impl AngleBracketedParameterData {
- fn is_empty(&self) -> bool {
- self.lifetimes.is_empty() && self.types.is_empty() && self.bindings.is_empty()
+impl Into<Option<P<PathParameters>>> for AngleBracketedParameterData {
+ fn into(self) -> Option<P<PathParameters>> {
+ let empty = self.lifetimes.is_empty() && self.types.is_empty() && self.bindings.is_empty();
+ if empty { None } else { Some(P(PathParameters::AngleBracketed(self))) }
}
}
pub attrs: Vec<Attribute>,
pub id: NodeId,
pub span: Span,
- pub imported_from: Option<Ident>,
- pub allow_internal_unstable: bool,
pub body: Vec<TokenTree>,
}
use util::ThinVec;
use std::cell::{RefCell, Cell};
-use std::collections::HashSet;
thread_local! {
static USED_ATTRS: RefCell<Vec<u64>> = RefCell::new(Vec::new());
}
}
-pub fn mk_doc_attr_outer(id: AttrId, item: MetaItem, is_sugared_doc: bool) -> Attribute {
- Attribute {
- id: id,
- style: ast::AttrStyle::Outer,
- value: item,
- is_sugared_doc: is_sugared_doc,
- span: DUMMY_SP,
- }
-}
-
pub fn mk_sugared_doc_attr(id: AttrId, text: Symbol, lo: BytePos, hi: BytePos)
-> Attribute {
let style = doc_comment_style(&text.as_str());
.and_then(|at| at.value_str())
}
-pub fn last_meta_item_value_str_by_name(items: &[MetaItem], name: &str) -> Option<Symbol> {
- items.iter()
- .rev()
- .find(|mi| mi.check_name(name))
- .and_then(|i| i.value_str())
-}
-
/* Higher-level applications */
pub fn find_crate_name(attrs: &[Attribute]) -> Option<Symbol> {
find_deprecation_generic(diagnostic, attrs.iter(), item_sp)
}
-pub fn require_unique_names(diagnostic: &Handler, metas: &[MetaItem]) {
- let mut set = HashSet::new();
- for meta in metas {
- let name = meta.name();
-
- if !set.insert(name.clone()) {
- panic!(diagnostic.span_fatal(meta.span,
- &format!("duplicate meta item `{}`", name)));
- }
- }
-}
-
/// Parse #[repr(...)] forms.
///
cx: &'cx mut ExtCtxt,
sp: Span,
ident: ast::Ident,
- token_tree: Vec<tokenstream::TokenTree>,
- attrs: Vec<ast::Attribute>)
+ token_tree: Vec<tokenstream::TokenTree>)
-> Box<MacResult+'cx>;
}
cx: &'cx mut ExtCtxt,
sp: Span,
ident: ast::Ident,
- token_tree: Vec<tokenstream::TokenTree>,
- _attrs: Vec<ast::Attribute>)
+ token_tree: Vec<tokenstream::TokenTree>)
-> Box<MacResult+'cx>
{
(*self)(cx, sp, ident, token_tree)
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item>;
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion);
- fn add_macro(&mut self, scope: Mark, def: ast::MacroDef, export: bool);
fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>);
fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec<Mark>);
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> { item }
fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion) {}
- fn add_macro(&mut self, _scope: Mark, _def: ast::MacroDef, _export: bool) {}
fn add_ext(&mut self, _ident: ast::Ident, _ext: Rc<SyntaxExtension>) {}
fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec<Mark>) {}
bindings: Vec<ast::TypeBinding> )
-> ast::Path {
let last_identifier = idents.pop().unwrap();
- let mut segments: Vec<ast::PathSegment> = idents.into_iter()
- .map(|ident| {
- ast::PathSegment {
- identifier: ident,
- parameters: ast::PathParameters::none(),
- }
- }).collect();
- segments.push(ast::PathSegment {
- identifier: last_identifier,
- parameters: ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
+ let mut segments: Vec<ast::PathSegment> = idents.into_iter().map(Into::into).collect();
+ let parameters = if lifetimes.is_empty() && types.is_empty() && bindings.is_empty() {
+ None
+ } else {
+ Some(P(ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
lifetimes: lifetimes,
types: P::from_vec(types),
bindings: P::from_vec(bindings),
- })
- });
+ })))
+ };
+ segments.push(ast::PathSegment { identifier: last_identifier, parameters: parameters });
ast::Path {
span: sp,
global: global,
bindings: Vec<ast::TypeBinding>)
-> (ast::QSelf, ast::Path) {
let mut path = trait_path;
+ let parameters = ast::AngleBracketedParameterData {
+ lifetimes: lifetimes,
+ types: P::from_vec(types),
+ bindings: P::from_vec(bindings),
+ };
path.segments.push(ast::PathSegment {
identifier: ident,
- parameters: ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
- lifetimes: lifetimes,
- types: P::from_vec(types),
- bindings: P::from_vec(bindings),
- })
+ parameters: Some(P(ast::PathParameters::AngleBracketed(parameters))),
});
(ast::QSelf {
pub enum InvocationKind {
Bang {
- attrs: Vec<ast::Attribute>,
mac: ast::Mac,
ident: Option<Ident>,
span: Span,
if expansions.len() < depth {
expansions.push(Vec::new());
}
- expansions[depth - 1].push((mark.as_u32(), expansion));
+ expansions[depth - 1].push((mark, expansion));
if !self.cx.ecfg.single_step {
invocations.extend(new_invocations.into_iter().rev());
}
let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic);
while let Some(expansions) = expansions.pop() {
for (mark, expansion) in expansions.into_iter().rev() {
- placeholder_expander.add(ast::NodeId::from_u32(mark), expansion);
+ placeholder_expander.add(mark.as_placeholder_id(), expansion);
}
}
/// Expand a macro invocation. Returns the result of expansion.
fn expand_bang_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Expansion {
let (mark, kind) = (invoc.expansion_data.mark, invoc.expansion_kind);
- let (attrs, mac, ident, span) = match invoc.kind {
- InvocationKind::Bang { attrs, mac, ident, span } => (attrs, mac, ident, span),
+ let (mac, ident, span) = match invoc.kind {
+ InvocationKind::Bang { mac, ident, span } => (mac, ident, span),
_ => unreachable!(),
};
let Mac_ { path, tts, .. } = mac.node;
- // Detect use of feature-gated or invalid attributes on macro invoations
- // since they will not be detected after macro expansion.
- for attr in attrs.iter() {
- feature_gate::check_attribute(&attr, &self.cx.parse_sess,
- &self.cx.parse_sess.codemap(),
- &self.cx.ecfg.features.unwrap());
- }
-
let extname = path.segments.last().unwrap().identifier.name;
let ident = ident.unwrap_or(keywords::Invalid.ident());
let marked_tts = mark_tts(&tts, mark);
}
});
- kind.make_from(expander.expand(self.cx, span, ident, marked_tts, attrs))
+ kind.make_from(expander.expand(self.cx, span, ident, marked_tts))
}
MultiDecorator(..) | MultiModifier(..) | SyntaxExtension::AttrProcMacro(..) => {
..self.cx.current_expansion.clone()
},
});
- placeholder(expansion_kind, ast::NodeId::from_u32(mark.as_u32()))
+ placeholder(expansion_kind, mark.as_placeholder_id())
}
- fn collect_bang(
- &mut self, mac: ast::Mac, attrs: Vec<ast::Attribute>, span: Span, kind: ExpansionKind,
- ) -> Expansion {
- self.collect(kind, InvocationKind::Bang { attrs: attrs, mac: mac, ident: None, span: span })
+ fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: ExpansionKind) -> Expansion {
+ self.collect(kind, InvocationKind::Bang { mac: mac, ident: None, span: span })
}
fn collect_attr(&mut self, attr: ast::Attribute, item: Annotatable, kind: ExpansionKind)
fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> {
self.cfg.configure(node)
}
+
+ // Detect use of feature-gated or invalid attributes on macro invocations
+ // since they will not be detected after macro expansion.
+ fn check_attributes(&mut self, attrs: &[ast::Attribute]) {
+ let codemap = &self.cx.parse_sess.codemap();
+ let features = self.cx.ecfg.features.unwrap();
+ for attr in attrs.iter() {
+ feature_gate::check_attribute(&attr, &self.cx.parse_sess, codemap, features);
+ }
+ }
}
// These are pretty nasty. Ideally, we would keep the tokens around, linked from
expr.node = self.cfg.configure_expr_kind(expr.node);
if let ast::ExprKind::Mac(mac) = expr.node {
- self.collect_bang(mac, expr.attrs.into(), expr.span, ExpansionKind::Expr).make_expr()
+ self.check_attributes(&expr.attrs);
+ self.collect_bang(mac, expr.span, ExpansionKind::Expr).make_expr()
} else {
P(noop_fold_expr(expr, self))
}
expr.node = self.cfg.configure_expr_kind(expr.node);
if let ast::ExprKind::Mac(mac) = expr.node {
- self.collect_bang(mac, expr.attrs.into(), expr.span, ExpansionKind::OptExpr)
- .make_opt_expr()
+ self.check_attributes(&expr.attrs);
+ self.collect_bang(mac, expr.span, ExpansionKind::OptExpr).make_opt_expr()
} else {
Some(P(noop_fold_expr(expr, self)))
}
}
pat.and_then(|pat| match pat.node {
- PatKind::Mac(mac) =>
- self.collect_bang(mac, Vec::new(), pat.span, ExpansionKind::Pat).make_pat(),
+ PatKind::Mac(mac) => self.collect_bang(mac, pat.span, ExpansionKind::Pat).make_pat(),
_ => unreachable!(),
})
}
}).collect()
};
- let mut placeholder =
- self.collect_bang(mac, attrs.into(), stmt.span, ExpansionKind::Stmts).make_stmts();
+ self.check_attributes(&attrs);
+ let mut placeholder = self.collect_bang(mac, stmt.span, ExpansionKind::Stmts).make_stmts();
// If this is a macro invocation with a semicolon, then apply that
// semicolon to the final statement produced by expansion.
match item.node {
ast::ItemKind::Mac(..) => {
- if match item.node {
- ItemKind::Mac(ref mac) => mac.node.path.segments.is_empty(),
- _ => unreachable!(),
- } {
- return SmallVector::one(item);
- }
+ self.check_attributes(&item.attrs);
+ let is_macro_def = if let ItemKind::Mac(ref mac) = item.node {
+ mac.node.path.segments[0].identifier.name == "macro_rules"
+ } else {
+ unreachable!()
+ };
- item.and_then(|item| match item.node {
+ item.and_then(|mut item| match item.node {
+ ItemKind::Mac(_) if is_macro_def => {
+ item.id = Mark::fresh().as_placeholder_id();
+ SmallVector::one(P(item))
+ }
ItemKind::Mac(mac) => {
self.collect(ExpansionKind::Items, InvocationKind::Bang {
mac: mac,
- attrs: item.attrs,
ident: Some(item.ident),
span: item.span,
}).make_items()
match item.node {
ast::TraitItemKind::Macro(mac) => {
let ast::TraitItem { attrs, span, .. } = item;
- self.collect_bang(mac, attrs, span, ExpansionKind::TraitItems).make_trait_items()
+ self.check_attributes(&attrs);
+ self.collect_bang(mac, span, ExpansionKind::TraitItems).make_trait_items()
}
_ => fold::noop_fold_trait_item(item, self),
}
match item.node {
ast::ImplItemKind::Macro(mac) => {
let ast::ImplItem { attrs, span, .. } = item;
- self.collect_bang(mac, attrs, span, ExpansionKind::ImplItems).make_impl_items()
+ self.check_attributes(&attrs);
+ self.collect_bang(mac, span, ExpansionKind::ImplItems).make_impl_items()
}
_ => fold::noop_fold_impl_item(item, self),
}
};
match ty.node {
- ast::TyKind::Mac(mac) =>
- self.collect_bang(mac, Vec::new(), ty.span, ExpansionKind::Ty).make_ty(),
+ ast::TyKind::Mac(mac) => self.collect_bang(mac, ty.span, ExpansionKind::Ty).make_ty(),
_ => unreachable!(),
}
}
Mark(id.as_u32())
}
- pub fn as_u32(&self) -> u32 {
+ pub fn as_placeholder_id(self) -> NodeId {
+ NodeId::from_u32(self.0)
+ }
+
+ pub fn as_u32(self) -> u32 {
self.0
}
}
})
}
- /// If `ident` is macro expanded, return the source ident from the macro definition
- /// and the mark of the expansion that created the macro definition.
- pub fn source(self) -> (Self /* source context */, Mark /* source macro */) {
- let macro_def_ctxt = self.data().prev_ctxt.data();
- (macro_def_ctxt.prev_ctxt, macro_def_ctxt.outer_mark)
- }
+ /// If `ident` is macro expanded, return the source ident from the macro definition
+ /// and the mark of the expansion that created the macro definition.
+ pub fn source(self) -> (Self /* source context */, Mark /* source macro */) {
+ let macro_def_ctxt = self.data().prev_ctxt.data();
+ (macro_def_ctxt.prev_ctxt, macro_def_ctxt.outer_mark)
+ }
}
impl fmt::Debug for SyntaxContext {
use codemap::{DUMMY_SP, dummy_spanned};
use ext::base::ExtCtxt;
use ext::expand::{Expansion, ExpansionKind};
+use ext::hygiene::Mark;
use fold::*;
use ptr::P;
-use symbol::{Symbol, keywords};
+use symbol::keywords;
use util::move_map::MoveMap;
use util::small_vector::SmallVector;
}
}
-pub fn macro_scope_placeholder() -> Expansion {
- placeholder(ExpansionKind::Items, ast::DUMMY_NODE_ID)
-}
-
pub struct PlaceholderExpander<'a, 'b: 'a> {
expansions: HashMap<ast::NodeId, Expansion>,
cx: &'a mut ExtCtxt<'b>,
impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> {
fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
match item.node {
- // Scope placeholder
- ast::ItemKind::Mac(_) if item.id == ast::DUMMY_NODE_ID => SmallVector::one(item),
- ast::ItemKind::Mac(_) => self.remove(item.id).make_items(),
- _ => noop_fold_item(item, self),
+ ast::ItemKind::Mac(ref mac) if !mac.node.path.segments.is_empty() => {}
+ ast::ItemKind::Mac(_) => return self.remove(item.id).make_items(),
+ _ => {}
}
+
+ noop_fold_item(item, self)
}
fn fold_trait_item(&mut self, item: ast::TraitItem) -> SmallVector<ast::TraitItem> {
block.stmts = block.stmts.move_flat_map(|mut stmt| {
remaining_stmts -= 1;
- // Scope placeholder
+ // `macro_rules!` macro definition
if let ast::StmtKind::Item(ref item) = stmt.node {
- if let ast::ItemKind::Mac(..) = item.node {
- macros.push(item.ident.ctxt.data().outer_mark);
+ if let ast::ItemKind::Mac(_) = item.node {
+ macros.push(Mark::from_placeholder_id(item.id));
return None;
}
}
fn fold_mod(&mut self, module: ast::Mod) -> ast::Mod {
let mut module = noop_fold_mod(module, self);
module.items = module.items.move_flat_map(|item| match item.node {
- ast::ItemKind::Mac(_) => None, // remove scope placeholders from modules
+ ast::ItemKind::Mac(_) if !self.cx.ecfg.keep_macs => None, // remove macro definitions
_ => Some(item),
});
module
}
-}
-pub fn reconstructed_macro_rules(def: &ast::MacroDef) -> Expansion {
- Expansion::Items(SmallVector::one(P(ast::Item {
- ident: def.ident,
- attrs: def.attrs.clone(),
- id: ast::DUMMY_NODE_ID,
- node: ast::ItemKind::Mac(ast::Mac {
- span: def.span,
- node: ast::Mac_ {
- path: ast::Path {
- span: DUMMY_SP,
- global: false,
- segments: vec![ast::PathSegment {
- identifier: ast::Ident::with_empty_ctxt(Symbol::intern("macro_rules")),
- parameters: ast::PathParameters::none(),
- }],
- },
- tts: def.body.clone(),
- }
- }),
- vis: ast::Visibility::Inherited,
- span: def.span,
- })))
+ fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
+ mac
+ }
}
use {ast, attr};
use syntax_pos::{Span, DUMMY_SP};
-use ext::base::{DummyResult, ExtCtxt, MacEager, MacResult, SyntaxExtension};
-use ext::base::{IdentMacroExpander, NormalTT, TTMacroExpander};
+use ext::base::{DummyResult, ExtCtxt, MacResult, SyntaxExtension};
+use ext::base::{NormalTT, TTMacroExpander};
use ext::expand::{Expansion, ExpansionKind};
-use ext::placeholders;
use ext::tt::macro_parser::{Success, Error, Failure};
use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
use ext::tt::macro_parser::{parse, parse_failure_msg};
cx.span_fatal(best_fail_spot.substitute_dummy(sp), &best_fail_msg);
}
-pub struct MacroRulesExpander;
-impl IdentMacroExpander for MacroRulesExpander {
- fn expand(&self,
- cx: &mut ExtCtxt,
- span: Span,
- ident: ast::Ident,
- tts: Vec<tokenstream::TokenTree>,
- attrs: Vec<ast::Attribute>)
- -> Box<MacResult> {
- let export = attr::contains_name(&attrs, "macro_export");
- let def = ast::MacroDef {
- ident: ident,
- id: ast::DUMMY_NODE_ID,
- span: span,
- imported_from: None,
- body: tts,
- allow_internal_unstable: attr::contains_name(&attrs, "allow_internal_unstable"),
- attrs: attrs,
- };
-
- // If keep_macs is true, expands to a MacEager::items instead.
- let result = if cx.ecfg.keep_macs {
- MacEager::items(placeholders::reconstructed_macro_rules(&def).make_items())
- } else {
- MacEager::items(placeholders::macro_scope_placeholder().make_items())
- };
-
- cx.resolver.add_macro(cx.current_expansion.mark, def, export);
- result
- }
-}
-
// Note that macro-by-example's input is also matched against a token tree:
// $( $lhs:tt => $rhs:tt );+
//
valid: valid,
});
- NormalTT(exp, Some(def.span), def.allow_internal_unstable)
+ NormalTT(exp, Some(def.span), attr::contains_name(&def.attrs, "allow_internal_unstable"))
}
fn check_lhs_nt_follows(sess: &ParseSess, lhs: &TokenTree) -> bool {
global: global,
segments: segments.move_map(|PathSegment {identifier, parameters}| PathSegment {
identifier: fld.fold_ident(identifier),
- parameters: fld.fold_path_parameters(parameters),
+ parameters: parameters.map(|ps| ps.map(|ps| fld.fold_path_parameters(ps))),
}),
span: fld.new_span(span)
}
node: ast::ExprKind::Path(None, ast::Path {
span: sp(0, 1),
global: false,
- segments: vec![
- ast::PathSegment {
- identifier: Ident::from_str("a"),
- parameters: ast::PathParameters::none(),
- }
- ],
+ segments: vec![Ident::from_str("a").into()],
}),
span: sp(0, 1),
attrs: ThinVec::new(),
P(ast::Expr {
id: ast::DUMMY_NODE_ID,
node: ast::ExprKind::Path(None, ast::Path {
- span: sp(0, 6),
- global: true,
- segments: vec![
- ast::PathSegment {
- identifier: Ident::from_str("a"),
- parameters: ast::PathParameters::none(),
- },
- ast::PathSegment {
- identifier: Ident::from_str("b"),
- parameters: ast::PathParameters::none(),
- }
- ]
- }),
+ span: sp(0, 6),
+ global: true,
+ segments: vec![Ident::from_str("a").into(), Ident::from_str("b").into()],
+ }),
span: sp(0, 6),
attrs: ThinVec::new(),
}))
node:ast::ExprKind::Path(None, ast::Path{
span: sp(7, 8),
global: false,
- segments: vec![
- ast::PathSegment {
- identifier: Ident::from_str("d"),
- parameters: ast::PathParameters::none(),
- }
- ],
+ segments: vec![Ident::from_str("d").into()],
}),
span:sp(7,8),
attrs: ThinVec::new(),
node: ast::ExprKind::Path(None, ast::Path {
span:sp(0,1),
global:false,
- segments: vec![
- ast::PathSegment {
- identifier: Ident::from_str("b"),
- parameters: ast::PathParameters::none(),
- }
- ],
+ segments: vec![Ident::from_str("b").into()],
}),
span: sp(0,1),
attrs: ThinVec::new()})),
node: ast::TyKind::Path(None, ast::Path{
span:sp(10,13),
global:false,
- segments: vec![
- ast::PathSegment {
- identifier: Ident::from_str("i32"),
- parameters: ast::PathParameters::none(),
- }
- ],
+ segments: vec![Ident::from_str("i32").into()],
}),
span:sp(10,13)
}),
ast::Path{
span:sp(17,18),
global:false,
- segments: vec![
- ast::PathSegment {
- identifier: Ident::from_str("b"),
- parameters:
- ast::PathParameters::none(),
- }
- ],
+ segments: vec![Ident::from_str("b").into()],
}),
span: sp(17,18),
attrs: ThinVec::new()})),
// Parse types, optionally.
let parameters = if self.eat_lt() {
let (lifetimes, types, bindings) = self.parse_generic_values_after_lt()?;
-
- ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
+ ast::AngleBracketedParameterData {
lifetimes: lifetimes,
types: P::from_vec(types),
bindings: P::from_vec(bindings),
- })
+ }.into()
} else if self.eat(&token::OpenDelim(token::Paren)) {
let lo = self.prev_span.lo;
let hi = self.prev_span.hi;
- ast::PathParameters::Parenthesized(ast::ParenthesizedParameterData {
+ Some(P(ast::PathParameters::Parenthesized(ast::ParenthesizedParameterData {
span: mk_sp(lo, hi),
inputs: inputs,
output: output_ty,
- })
+ })))
} else {
- ast::PathParameters::none()
+ None
};
// Assemble and push the result.
- segments.push(ast::PathSegment { identifier: identifier,
- parameters: parameters });
+ segments.push(ast::PathSegment { identifier: identifier, parameters: parameters });
// Continue only if we see a `::`
if !self.eat(&token::ModSep) {
// If we do not see a `::`, stop.
if !self.eat(&token::ModSep) {
- segments.push(ast::PathSegment {
- identifier: identifier,
- parameters: ast::PathParameters::none()
- });
+ segments.push(identifier.into());
return Ok(segments);
}
if self.eat_lt() {
// Consumed `a::b::<`, go look for types
let (lifetimes, types, bindings) = self.parse_generic_values_after_lt()?;
- let parameters = ast::AngleBracketedParameterData {
- lifetimes: lifetimes,
- types: P::from_vec(types),
- bindings: P::from_vec(bindings),
- };
segments.push(ast::PathSegment {
identifier: identifier,
- parameters: ast::PathParameters::AngleBracketed(parameters),
+ parameters: ast::AngleBracketedParameterData {
+ lifetimes: lifetimes,
+ types: P::from_vec(types),
+ bindings: P::from_vec(bindings),
+ }.into(),
});
// Consumed `a::b::<T,U>`, check for `::` before proceeding
}
} else {
// Consumed `a::`, go look for `b`
- segments.push(ast::PathSegment {
- identifier: identifier,
- parameters: ast::PathParameters::none(),
- });
+ segments.push(identifier.into());
}
}
}
let identifier = self.parse_path_segment_ident()?;
// Assemble and push the result.
- segments.push(ast::PathSegment {
- identifier: identifier,
- parameters: ast::PathParameters::none()
- });
+ segments.push(identifier.into());
// If we do not see a `::` or see `::{`/`::*`, stop.
if !self.check(&token::ModSep) || self.is_import_coupler() {
try!(self.print_ident(segment.identifier));
- try!(self.print_path_parameters(&segment.parameters, colons_before_params));
+ if let Some(ref parameters) = segment.parameters {
+ try!(self.print_path_parameters(parameters, colons_before_params))
+ }
}
Ok(())
try!(word(&mut self.s, "::"));
let item_segment = path.segments.last().unwrap();
try!(self.print_ident(item_segment.identifier));
- self.print_path_parameters(&item_segment.parameters, colons_before_params)
+ match item_segment.parameters {
+ Some(ref parameters) => self.print_path_parameters(parameters, colons_before_params),
+ None => Ok(()),
+ }
}
fn print_path_parameters(&mut self,
colons_before_params: bool)
-> io::Result<()>
{
- if parameters.is_empty() {
- return Ok(());
- }
-
if colons_before_params {
try!(word(&mut self.s, "::"))
}
vis: ast::Visibility::Inherited,
node: ast::ItemKind::Use(P(codemap::dummy_spanned(ast::ViewPathGlob(ast::Path {
global: false,
- segments: vec![name, "prelude", "v1"].into_iter().map(|name| ast::PathSegment {
- identifier: ast::Ident::from_str(name),
- parameters: ast::PathParameters::none(),
+ segments: vec![name, "prelude", "v1"].into_iter().map(|name| {
+ ast::Ident::from_str(name).into()
}).collect(),
span: span,
})))),
ast::Path {
span: DUMMY_SP,
global: false,
- segments: ids.into_iter().map(|identifier| ast::PathSegment {
- identifier: identifier,
- parameters: ast::PathParameters::none(),
- }).collect()
+ segments: ids.into_iter().map(Into::into).collect(),
}
}
pub fn walk_macro_def<'a, V: Visitor<'a>>(visitor: &mut V, macro_def: &'a MacroDef) {
visitor.visit_ident(macro_def.span, macro_def.ident);
- walk_opt_ident(visitor, macro_def.span, macro_def.imported_from);
walk_list!(visitor, visit_attribute, ¯o_def.attrs);
}
path_span: Span,
segment: &'a PathSegment) {
visitor.visit_ident(path_span, segment.identifier);
- visitor.visit_path_parameters(path_span, &segment.parameters);
+ if let Some(ref parameters) = segment.parameters {
+ visitor.visit_path_parameters(path_span, parameters);
+ }
}
pub fn walk_path_parameters<'a, V>(visitor: &mut V,
impl Result {
fn path(&self) -> ast::Path {
- let segment = ast::PathSegment {
- identifier: self.ident,
- parameters: ast::PathParameters::none(),
- };
ast::Path {
span: self.span,
global: false,
- segments: vec![segment],
+ segments: vec![self.ident.into()],
}
}
}
use std::rc::Rc;
use syntax::ast;
-use syntax::ext::base::{MacroExpanderFn, NormalTT, IdentTT, MultiModifier, NamedSyntaxExtension};
-use syntax::ext::tt::macro_rules::MacroRulesExpander;
+use syntax::ext::base::{MacroExpanderFn, NormalTT, MultiModifier, NamedSyntaxExtension};
use syntax::symbol::Symbol;
pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
resolver.add_ext(ast::Ident::with_empty_ctxt(name), Rc::new(ext));
};
- register(Symbol::intern("macro_rules"), IdentTT(Box::new(MacroRulesExpander), None, false));
-
macro_rules! register {
($( $name:ident: $f:expr, )*) => { $(
register(Symbol::intern(stringify!($name)),
# released on `$date`
rustc: beta-2016-12-16
-cargo: nightly-2016-11-16
+cargo: fbeea902d2c9a5be6d99cc35681565d8f7832592
extern crate libc as collections;
//~^ ERROR E0259
-//~| NOTE `collections` was already imported
+//~| NOTE `collections` already imported
fn main() {}
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo {
+ bar: Bar
+}
+
+struct Bar {
+ baz: Baz
+}
+
+struct Baz {
+ x: *const u8
+}
+
+fn is_send<T: Send>() { }
+
+fn main() {
+ is_send::<Foo>();
+ //~^ ERROR the trait bound `*const u8: std::marker::Send` is not satisfied in `Foo`
+ //~| NOTE within `Foo`, the trait `std::marker::Send` is not implemented for `*const u8`
+ //~| NOTE: `*const u8` cannot be sent between threads safely
+ //~| NOTE: required because it appears within the type `Baz`
+ //~| NOTE: required because it appears within the type `Bar`
+ //~| NOTE: required because it appears within the type `Foo`
+ //~| NOTE: required by `is_send`
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use std::path::Path;
+
trait Foo {
fn bar(&self);
}
foo.bar();
}
+fn f(p: Path) { }
+//~^ ERROR the trait bound `[u8]: std::marker::Sized` is not satisfied in `std::path::Path`
+//~| NOTE within `std::path::Path`, the trait `std::marker::Sized` is not implemented for `[u8]`
+//~| NOTE `[u8]` does not have a constant size known at compile-time
+//~| NOTE required because it appears within the type `std::path::Path`
+//~| NOTE all local variables must have a statically known size
+
fn main() {
some_func(5i32);
//~^ ERROR the trait bound `i32: Foo` is not satisfied
use foo::foo;
//~^ ERROR a module named `foo` has already been defined in this module
-//~| was already imported
+//~| `foo` already defined
fn main() {}
+++ /dev/null
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn illegal_cast<U:?Sized,V:?Sized>(u: *const U) -> *const V
-{
- u as *const V
- //~^ ERROR casting
- //~^^ NOTE vtable kinds
-}
-
-fn illegal_cast_2<U:?Sized>(u: *const U) -> *const str
-{
- u as *const str
- //~^ ERROR casting
- //~^^ NOTE vtable kinds
-}
-
-trait Foo { fn foo(&self) {} }
-impl<T> Foo for T {}
-
-trait Bar { fn foo(&self) {} }
-impl<T> Bar for T {}
-
-enum E {
- A, B
-}
-
-fn main()
-{
- let f: f32 = 1.2;
- let v = 0 as *const u8;
- let fat_v : *const [u8] = unsafe { &*(0 as *const [u8; 1])};
- let fat_sv : *const [i8] = unsafe { &*(0 as *const [i8; 1])};
- let foo: &Foo = &f;
-
- let _ = v as &u8; //~ ERROR non-scalar
- let _ = v as E; //~ ERROR non-scalar
- let _ = v as fn(); //~ ERROR non-scalar
- let _ = v as (u32,); //~ ERROR non-scalar
- let _ = Some(&v) as *const u8; //~ ERROR non-scalar
-
- let _ = v as f32;
- //~^ ERROR casting
- let _ = main as f64;
- //~^ ERROR casting
- let _ = &v as usize;
- //~^ ERROR casting
- //~^^ HELP through a raw pointer first
- let _ = f as *const u8;
- //~^ ERROR casting
- let _ = 3_i32 as bool;
- //~^ ERROR cannot cast as `bool` [E0054]
- //~| unsupported cast
- //~| HELP compare with zero
- let _ = E::A as bool;
- //~^ ERROR cannot cast as `bool` [E0054]
- //~| unsupported cast
- //~| HELP compare with zero
- let _ = 0x61u32 as char; //~ ERROR only `u8` can be cast
-
- let _ = false as f32;
- //~^ ERROR casting
- //~^^ HELP through an integer first
- let _ = E::A as f32;
- //~^ ERROR casting
- //~^^ HELP through an integer first
- let _ = 'a' as f32;
- //~^ ERROR casting
- //~^^ HELP through an integer first
-
- let _ = false as *const u8;
- //~^ ERROR casting
- let _ = E::A as *const u8;
- //~^ ERROR casting
- let _ = 'a' as *const u8;
- //~^ ERROR casting
-
- let _ = 42usize as *const [u8]; //~ ERROR casting
- let _ = v as *const [u8]; //~ ERROR cannot cast
- let _ = fat_v as *const Foo;
- //~^ ERROR the trait bound `[u8]: std::marker::Sized` is not satisfied
- //~| NOTE the trait `std::marker::Sized` is not implemented for `[u8]`
- //~| NOTE `[u8]` does not have a constant size known at compile-time
- //~| NOTE required for the cast to the object type `Foo`
- let _ = foo as *const str; //~ ERROR casting
- let _ = foo as *mut str; //~ ERROR casting
- let _ = main as *mut str; //~ ERROR casting
- let _ = &f as *mut f32; //~ ERROR casting
- let _ = &f as *const f64; //~ ERROR casting
- let _ = fat_sv as usize;
- //~^ ERROR casting
- //~^^ HELP through a thin pointer first
-
- let a : *const str = "hello";
- let _ = a as *const Foo;
- //~^ ERROR the trait bound `str: std::marker::Sized` is not satisfied
- //~| NOTE the trait `std::marker::Sized` is not implemented for `str`
- //~| NOTE `str` does not have a constant size known at compile-time
- //~| NOTE required for the cast to the object type `Foo`
-
- // check no error cascade
- let _ = main.f as *const u32; //~ no field `f` on type `fn() {main}`
-
- let cf: *const Foo = &0;
- let _ = cf as *const [u16];
- //~^ ERROR casting
- //~^^ NOTE vtable kinds
- let _ = cf as *const Bar;
- //~^ ERROR casting
- //~^^ NOTE vtable kinds
-
- vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
- //~^ ERROR casting `&{float}` as `f32` is invalid
- //~| NOTE cannot cast `&{float}` as `f32`
- //~| NOTE did you mean `*s`?
-}
use self::A; //~ NOTE previous import of `A` here
use self::B; //~ NOTE previous import of `B` here
mod A {} //~ ERROR a module named `A` has already been imported in this module
-//~| `A` was already imported
+//~| `A` already imported
pub mod B {} //~ ERROR a module named `B` has already been imported in this module
-//~| `B` was already imported
+//~| `B` already imported
mod C {
use C::D; //~ NOTE previous import of `D` here
mod D {} //~ ERROR a module named `D` has already been imported in this module
- //~| `D` was already imported
+ //~| `D` already imported
}
fn main() {}
use std::ops::Rem; //~ NOTE previous import
type Add = bool; //~ ERROR a trait named `Add` has already been imported in this module
-//~| was already imported
+//~| `Add` already imported
struct Sub { x: f32 } //~ ERROR a trait named `Sub` has already been imported in this module
-//~| was already imported
+//~| `Sub` already imported
enum Mul { A, B } //~ ERROR a trait named `Mul` has already been imported in this module
-//~| was already imported
+//~| `Mul` already imported
mod Div { } //~ ERROR a trait named `Div` has already been imported in this module
-//~| was already imported
+//~| `Div` already imported
trait Rem { } //~ ERROR a trait named `Rem` has already been imported in this module
-//~| was already imported
+//~| `Rem` already imported
fn main() {}
fn transmute() {}
//~^ ERROR a value named `transmute` has already been imported in this module
-//~| was already imported
+//~| `transmute` already imported
fn main() {
}
// ignore-android FIXME #17520
// ignore-emscripten spawning processes is not supported
+// ignore-openbsd no support for libbacktrace without filename
// compile-flags:-g
use std::env;
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn illegal_cast<U:?Sized,V:?Sized>(u: *const U) -> *const V
+{
+ u as *const V
+}
+
+fn illegal_cast_2<U:?Sized>(u: *const U) -> *const str
+{
+ u as *const str
+}
+
+trait Foo { fn foo(&self) {} }
+impl<T> Foo for T {}
+
+trait Bar { fn foo(&self) {} }
+impl<T> Bar for T {}
+
+enum E {
+ A, B
+}
+
+fn main()
+{
+ let f: f32 = 1.2;
+ let v = 0 as *const u8;
+ let fat_v : *const [u8] = unsafe { &*(0 as *const [u8; 1])};
+ let fat_sv : *const [i8] = unsafe { &*(0 as *const [i8; 1])};
+ let foo: &Foo = &f;
+
+ let _ = v as &u8;
+ let _ = v as E;
+ let _ = v as fn();
+ let _ = v as (u32,);
+ let _ = Some(&v) as *const u8;
+
+ let _ = v as f32;
+ let _ = main as f64;
+ let _ = &v as usize;
+ let _ = f as *const u8;
+ let _ = 3_i32 as bool;
+ let _ = E::A as bool;
+ let _ = 0x61u32 as char;
+
+ let _ = false as f32;
+ let _ = E::A as f32;
+ let _ = 'a' as f32;
+
+ let _ = false as *const u8;
+ let _ = E::A as *const u8;
+ let _ = 'a' as *const u8;
+
+ let _ = 42usize as *const [u8];
+ let _ = v as *const [u8];
+ let _ = fat_v as *const Foo;
+ let _ = foo as *const str;
+ let _ = foo as *mut str;
+ let _ = main as *mut str;
+ let _ = &f as *mut f32;
+ let _ = &f as *const f64;
+ let _ = fat_sv as usize;
+
+ let a : *const str = "hello";
+ let _ = a as *const Foo;
+
+ // check no error cascade
+ let _ = main.f as *const u32;
+
+ let cf: *const Foo = &0;
+ let _ = cf as *const [u16];
+ let _ = cf as *const Bar;
+
+ vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
+}
--- /dev/null
+error: casting `*const U` as `*const V` is invalid
+ --> $DIR/cast-rfc0401.rs:13:5
+ |
+13 | u as *const V
+ | ^^^^^^^^^^^^^
+ |
+ = note: vtable kinds may not match
+
+error: casting `*const U` as `*const str` is invalid
+ --> $DIR/cast-rfc0401.rs:18:5
+ |
+18 | u as *const str
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: vtable kinds may not match
+
+error: no field `f` on type `fn() {main}`
+ --> $DIR/cast-rfc0401.rs:75:18
+ |
+75 | let _ = main.f as *const u32;
+ | ^
+
+error: non-scalar cast: `*const u8` as `&u8`
+ --> $DIR/cast-rfc0401.rs:39:13
+ |
+39 | let _ = v as &u8;
+ | ^^^^^^^^
+
+error: non-scalar cast: `*const u8` as `E`
+ --> $DIR/cast-rfc0401.rs:40:13
+ |
+40 | let _ = v as E;
+ | ^^^^^^
+
+error: non-scalar cast: `*const u8` as `fn()`
+ --> $DIR/cast-rfc0401.rs:41:13
+ |
+41 | let _ = v as fn();
+ | ^^^^^^^^^
+
+error: non-scalar cast: `*const u8` as `(u32,)`
+ --> $DIR/cast-rfc0401.rs:42:13
+ |
+42 | let _ = v as (u32,);
+ | ^^^^^^^^^^^
+
+error: non-scalar cast: `std::option::Option<&*const u8>` as `*const u8`
+ --> $DIR/cast-rfc0401.rs:43:13
+ |
+43 | let _ = Some(&v) as *const u8;
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error: casting `*const u8` as `f32` is invalid
+ --> $DIR/cast-rfc0401.rs:45:13
+ |
+45 | let _ = v as f32;
+ | ^^^^^^^^
+
+error: casting `fn() {main}` as `f64` is invalid
+ --> $DIR/cast-rfc0401.rs:46:13
+ |
+46 | let _ = main as f64;
+ | ^^^^^^^^^^^
+
+error: casting `&*const u8` as `usize` is invalid
+ --> $DIR/cast-rfc0401.rs:47:13
+ |
+47 | let _ = &v as usize;
+ | ^^^^^^^^^^^
+ |
+ = help: cast through a raw pointer first
+
+error: casting `f32` as `*const u8` is invalid
+ --> $DIR/cast-rfc0401.rs:48:13
+ |
+48 | let _ = f as *const u8;
+ | ^^^^^^^^^^^^^^
+
+error[E0054]: cannot cast as `bool`
+ --> $DIR/cast-rfc0401.rs:49:13
+ |
+49 | let _ = 3_i32 as bool;
+ | ^^^^^^^^^^^^^ unsupported cast
+ |
+ = help: compare with zero instead
+
+error[E0054]: cannot cast as `bool`
+ --> $DIR/cast-rfc0401.rs:50:13
+ |
+50 | let _ = E::A as bool;
+ | ^^^^^^^^^^^^ unsupported cast
+ |
+ = help: compare with zero instead
+
+error: only `u8` can be cast as `char`, not `u32`
+ --> $DIR/cast-rfc0401.rs:51:13
+ |
+51 | let _ = 0x61u32 as char;
+ | ^^^^^^^^^^^^^^^
+
+error: casting `bool` as `f32` is invalid
+ --> $DIR/cast-rfc0401.rs:53:13
+ |
+53 | let _ = false as f32;
+ | ^^^^^^^^^^^^
+ |
+ = help: cast through an integer first
+
+error: casting `E` as `f32` is invalid
+ --> $DIR/cast-rfc0401.rs:54:13
+ |
+54 | let _ = E::A as f32;
+ | ^^^^^^^^^^^
+ |
+ = help: cast through an integer first
+
+error: casting `char` as `f32` is invalid
+ --> $DIR/cast-rfc0401.rs:55:13
+ |
+55 | let _ = 'a' as f32;
+ | ^^^^^^^^^^
+ |
+ = help: cast through an integer first
+
+error: casting `bool` as `*const u8` is invalid
+ --> $DIR/cast-rfc0401.rs:57:13
+ |
+57 | let _ = false as *const u8;
+ | ^^^^^^^^^^^^^^^^^^
+
+error: casting `E` as `*const u8` is invalid
+ --> $DIR/cast-rfc0401.rs:58:13
+ |
+58 | let _ = E::A as *const u8;
+ | ^^^^^^^^^^^^^^^^^
+
+error: casting `char` as `*const u8` is invalid
+ --> $DIR/cast-rfc0401.rs:59:13
+ |
+59 | let _ = 'a' as *const u8;
+ | ^^^^^^^^^^^^^^^^
+
+error: casting `usize` as `*const [u8]` is invalid
+ --> $DIR/cast-rfc0401.rs:61:13
+ |
+61 | let _ = 42usize as *const [u8];
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
+ --> $DIR/cast-rfc0401.rs:62:13
+ |
+62 | let _ = v as *const [u8];
+ | ^^^^^^^^^^^^^^^^
+
+error: casting `&Foo` as `*const str` is invalid
+ --> $DIR/cast-rfc0401.rs:64:13
+ |
+64 | let _ = foo as *const str;
+ | ^^^^^^^^^^^^^^^^^
+
+error: casting `&Foo` as `*mut str` is invalid
+ --> $DIR/cast-rfc0401.rs:65:13
+ |
+65 | let _ = foo as *mut str;
+ | ^^^^^^^^^^^^^^^
+
+error: casting `fn() {main}` as `*mut str` is invalid
+ --> $DIR/cast-rfc0401.rs:66:13
+ |
+66 | let _ = main as *mut str;
+ | ^^^^^^^^^^^^^^^^
+
+error: casting `&f32` as `*mut f32` is invalid
+ --> $DIR/cast-rfc0401.rs:67:13
+ |
+67 | let _ = &f as *mut f32;
+ | ^^^^^^^^^^^^^^
+
+error: casting `&f32` as `*const f64` is invalid
+ --> $DIR/cast-rfc0401.rs:68:13
+ |
+68 | let _ = &f as *const f64;
+ | ^^^^^^^^^^^^^^^^
+
+error: casting `*const [i8]` as `usize` is invalid
+ --> $DIR/cast-rfc0401.rs:69:13
+ |
+69 | let _ = fat_sv as usize;
+ | ^^^^^^^^^^^^^^^
+ |
+ = help: cast through a thin pointer first
+
+error: casting `*const Foo` as `*const [u16]` is invalid
+ --> $DIR/cast-rfc0401.rs:78:13
+ |
+78 | let _ = cf as *const [u16];
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = note: vtable kinds may not match
+
+error: casting `*const Foo` as `*const Bar` is invalid
+ --> $DIR/cast-rfc0401.rs:79:13
+ |
+79 | let _ = cf as *const Bar;
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: vtable kinds may not match
+
+error[E0277]: the trait bound `[u8]: std::marker::Sized` is not satisfied
+ --> $DIR/cast-rfc0401.rs:63:13
+ |
+63 | let _ = fat_v as *const Foo;
+ | ^^^^^ the trait `std::marker::Sized` is not implemented for `[u8]`
+ |
+ = note: `[u8]` does not have a constant size known at compile-time
+ = note: required for the cast to the object type `Foo`
+
+error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
+ --> $DIR/cast-rfc0401.rs:72:13
+ |
+72 | let _ = a as *const Foo;
+ | ^ the trait `std::marker::Sized` is not implemented for `str`
+ |
+ = note: `str` does not have a constant size known at compile-time
+ = note: required for the cast to the object type `Foo`
+
+error: casting `&{float}` as `f32` is invalid
+ --> $DIR/cast-rfc0401.rs:81:30
+ |
+81 | vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
+ | ^^^^^^^^ cannot cast `&{float}` as `f32`
+ |
+help: did you mean `*s`?
+ --> $DIR/cast-rfc0401.rs:81:30
+ |
+81 | vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
+ | ^
+
+error: aborting due to 34 previous errors
+
log = "0.3"
env_logger = { version = "0.3.5", default-features = false }
serialize = { path = "../../libserialize" }
+build_helper = { path = "../../build_helper" }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+extern crate build_helper;
+
use common::Config;
use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind};
use common::{Codegen, DebugInfoLldb, DebugInfoGdb, Rustdoc, CodegenUnits};
}
self.create_dir_racy(&tmpdir);
- let mut cmd = Command::new("make");
+ let mut cmd = Command::new(build_helper::make(&self.config.host));
cmd.current_dir(&self.testpaths.file)
.env("TARGET", &self.config.target)
.env("PYTHON", &self.config.docck_python)
};
}
if !found {
- panic!("ran out of mir dump output to match against");
+ let normalize_all = dumped_string.lines()
+ .map(nocomment_mir_line)
+ .filter(|l| !l.is_empty())
+ .collect::<Vec<_>>()
+ .join("\n");
+ panic!("ran out of mir dump output to match against.\n\
+ Did not find expected line: {:?}\n\
+ Expected:\n{}\n\
+ Actual:\n{}",
+ expected_line,
+ expected_content.join("\n"),
+ normalize_all);
}
}
}
}
fn normalize_mir_line(line: &str) -> String {
- let no_comments = if let Some(idx) = line.find("//") {
+ nocomment_mir_line(line).replace(char::is_whitespace, "")
+}
+
+fn nocomment_mir_line(line: &str) -> &str {
+ if let Some(idx) = line.find("//") {
let (l, _) = line.split_at(idx);
- l
+ l.trim_right()
} else {
line
- };
- no_comments.replace(char::is_whitespace, "")
+ }
}