putvar CFG_MSVC_LIB_PATH_${bits}
;;
+ *-rumprun-netbsd)
+ step_msg "targeting rumprun-netbsd, disabling jemalloc"
+ CFG_DISABLE_JEMALLOC=1
+ putvar CFG_DISABLE_JEMALLOC
+ ;;
+
*)
;;
esac
--- /dev/null
+# x86_64-rumprun-netbsd configuration
+CROSS_PREFIX_x86_64-rumprun-netbsd=x86_64-rumprun-netbsd-
+CC_x86_64-rumprun-netbsd=gcc
+CXX_x86_64-rumprun-netbsd=g++
+CPP_x86_64-rumprun-netbsd=gcc -E
+AR_x86_64-rumprun-netbsd=ar
+CFG_INSTALL_ONLY_RLIB_x86_64-rumprun-netbsd = 1
+CFG_LIB_NAME_x86_64-rumprun-netbsd=lib$(1).so
+CFG_STATIC_LIB_NAME_x86_64-rumprun-netbsd=lib$(1).a
+CFG_LIB_GLOB_x86_64-rumprun-netbsd=lib$(1)-*.so
+CFG_JEMALLOC_CFLAGS_x86_64-rumprun-netbsd := -m64
+CFG_GCCISH_CFLAGS_x86_64-rumprun-netbsd := -Wall -Werror -g -fPIC -m64
+CFG_GCCISH_CXXFLAGS_x86_64-rumprun-netbsd :=
+CFG_GCCISH_LINK_FLAGS_x86_64-rumprun-netbsd :=
+CFG_GCCISH_DEF_FLAG_x86_64-rumprun-netbsd :=
+CFG_LLC_FLAGS_x86_64-rumprun-netbsd :=
+CFG_INSTALL_NAME_x86_64-rumprun-netbsd =
+CFG_EXE_SUFFIX_x86_64-rumprun-netbsd =
+CFG_WINDOWSY_x86_64-rumprun-netbsd :=
+CFG_UNIXY_x86_64-rumprun-netbsd := 1
+CFG_LDPATH_x86_64-rumprun-netbsd :=
+CFG_RUN_x86_64-rumprun-netbsd=$(2)
+CFG_RUN_TARG_x86_64-rumprun-netbsd=$(call CFG_RUN_x86_64-rumprun-netbsd,,$(2))
+CFG_GNU_TRIPLE_x86_64-rumprun-netbsd := x86_64-rumprun-netbsd
if !full_version_line.trim().is_empty() => {
let full_version_line = full_version_line.trim();
- // used to be a regex "(^|[^0-9])([0-9]\.[0-9])([^0-9]|$)"
+ // used to be a regex "(^|[^0-9])([0-9]\.[0-9]+)"
for (pos, c) in full_version_line.char_indices() {
if !c.is_digit(10) { continue }
if pos + 2 >= full_version_line.len() { continue }
if pos > 0 && full_version_line.char_at_reverse(pos).is_digit(10) {
continue
}
- if pos + 3 < full_version_line.len() &&
- full_version_line.char_at(pos + 3).is_digit(10) {
- continue
+ let mut end = pos + 3;
+ while end < full_version_line.len() &&
+ full_version_line.char_at(end).is_digit(10) {
+ end += 1;
}
- return Some(full_version_line[pos..pos+3].to_owned());
+ return Some(full_version_line[pos..end].to_owned());
}
println!("Could not extract GDB version from line '{}'",
full_version_line);
## Building
-To generate all the docs, just run `make docs` from the root of the repository.
-This will convert the distributed Markdown docs to HTML and generate HTML doc
-for the 'std' and 'extra' libraries.
+To generate all the docs, follow the "Building Documentation" instructions in
+the README in the root of the repository. This will convert the distributed
+Markdown docs to HTML and generate HTML doc for the books, 'std' and 'extra'
+libraries.
To generate HTML documentation from one source file/crate, do something like:
}
use foo::example::iter; // good: foo is at crate root
-// use example::iter; // bad: core is not at the crate root
+// use example::iter; // bad: example is not at the crate root
use self::baz::foobaz; // good: self refers to module 'foo'
use foo::bar::foobar; // good: foo is at crate root
* `target_pointer_width = "..."` - Target pointer width in bits. This is set
to `"32"` for targets with 32-bit pointers, and likewise set to `"64"` for
64-bit pointers.
+* `target_vendor = "..."` - Vendor of the target, for example `apple`, `pc`, or
+ simply `"unknown"`.
* `test` - Enabled when compiling the test harness (using the `--test` flag).
* `unix` - See `target_family`.
* `windows` - See `target_family`.
* `advanced_slice_patterns` - See the [match expressions](#match-expressions)
section for discussion; the exact semantics of
slice patterns are subject to change, so some types
- are still unstable.
+ are still unstable.
* `slice_patterns` - OK, actually, slice patterns are just scary and
completely unstable.
* `box_syntax` - Allows use of `box` expressions, the exact semantics of which
is subject to change.
+* `cfg_target_vendor` - Allows conditional compilation using the `target_vendor`
+ matcher which is subject to change.
+
* `concat_idents` - Allows use of the `concat_idents` macro, which is in many
ways insufficient for concatenating identifiers, and may be
removed entirely for something more wholesome.
```
Right. Because we have a reference, we need to give it a lifetime. But
-our `factory()` function takes no arguments, so elision doesn’t kick in
-here. What lifetime can we choose? `'static`:
+our `factory()` function takes no arguments, so
+[elision](lifetimes.html#lifetime-elision) doesn’t kick in here. Then what
+choices do we have? Try `'static`:
```rust,ignore
fn factory() -> &'static (Fn(i32) -> i32) {
```text
error: mismatched types:
expected `&'static core::ops::Fn(i32) -> i32`,
- found `[closure <anon>:7:9: 7:20]`
+ found `[closure@<anon>:7:9: 7:20]`
(expected &-ptr,
found closure) [E0308]
|x| x + num
```
This error is letting us know that we don’t have a `&'static Fn(i32) -> i32`,
-we have a `[closure <anon>:7:9: 7:20]`. Wait, what?
+we have a `[closure@<anon>:7:9: 7:20]`. Wait, what?
Because each closure generates its own environment `struct` and implementation
of `Fn` and friends, these types are anonymous. They exist just solely for
-this closure. So Rust shows them as `closure <anon>`, rather than some
+this closure. So Rust shows them as `closure@<anon>`, rather than some
autogenerated name.
-But why doesn’t our closure implement `&'static Fn`? Well, as we discussed before,
-closures borrow their environment. And in this case, our environment is based
-on a stack-allocated `5`, the `num` variable binding. So the borrow has a lifetime
-of the stack frame. So if we returned this closure, the function call would be
-over, the stack frame would go away, and our closure is capturing an environment
-of garbage memory!
-
-So what to do? This _almost_ works:
+The error also points out that the return type is expected to be a reference,
+but what we are trying to return is not. Further, we cannot directly assign a
+`'static` lifetime to an object. So we'll take a different approach and return
+a "trait object" by `Box`ing up the `Fn`. This _almost_ works:
```rust,ignore
fn factory() -> Box<Fn(i32) -> i32> {
# }
```
-We use a trait object, by `Box`ing up the `Fn`. There’s just one last problem:
+There’s just one last problem:
```text
error: closure may outlive the current function, but it borrows `num`,
^~~~~~~~~~~
```
-We still have a reference to the parent stack frame. With one last fix, we can
-make this work:
+Well, as we discussed before, closures borrow their environment. And in this
+case, our environment is based on a stack-allocated `5`, the `num` variable
+binding. So the borrow has a lifetime of the stack frame. So if we returned
+this closure, the function call would be over, the stack frame would go away,
+and our closure is capturing an environment of garbage memory! With one last
+fix, we can make this work:
```rust
fn factory() -> Box<Fn(i32) -> i32> {
.find(|x| *x > 42);
match greater_than_forty_two {
- Some(_) => println!("We got some numbers!"),
- None => println!("No numbers found :("),
+ Some(_) => println!("Found a match!"),
+ None => println!("No match found :("),
}
```
`find` takes a closure, and works on a reference to each element of an
iterator. This closure returns `true` if the element is the element we're
-looking for, and `false` otherwise. Because we might not find a matching
-element, `find` returns an `Option` rather than the element itself.
+looking for, and `false` otherwise. `find` returns the first element satisfying
+the specified predicate. Because we might not find a matching element, `find`
+returns an `Option` rather than the element itself.
Another important consumer is `fold`. Here's what it looks like:
fn get_mut(&mut self) -> &mut T; // elided
fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded
-fn args<T:ToCStr>(&mut self, args: &[T]) -> &mut Command // elided
-fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded
+fn args<T:ToCStr>(&mut self, args: &[T]) -> &mut Command; // elided
+fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command; // expanded
fn new(buf: &mut [u8]) -> BufWriter; // elided
-fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded
+fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a>; // expanded
```
```rust
struct Electron;
+
+let x = Electron;
```
Such a `struct` is called ‘unit-like’ because it resembles the empty
fn parse_token_list(file: &str) -> HashMap<String, token::Token> {
fn id() -> token::Token {
- token::Ident(ast::Ident { name: Name(0), ctxt: 0, }, token::Plain)
+ token::Ident(ast::Ident::with_empty_ctxt(Name(0))), token::Plain)
}
let mut res = HashMap::new();
"RPAREN" => token::CloseDelim(token::Paren),
"SLASH" => token::BinOp(token::Slash),
"COMMA" => token::Comma,
- "LIFETIME" => token::Lifetime(ast::Ident { name: Name(0), ctxt: 0 }),
+ "LIFETIME" => token::Lifetime(ast::Ident::with_empty_ctxt(Name(0))),
"CARET" => token::BinOp(token::Caret),
"TILDE" => token::Tilde,
"IDENT" => id(),
token::Literal(token::ByteStr(..), n) => token::Literal(token::ByteStr(nm), n),
token::Literal(token::ByteStrRaw(..), n) => token::Literal(token::ByteStrRaw(fix(content),
count(content)), n),
- token::Ident(..) => token::Ident(ast::Ident { name: nm, ctxt: 0 },
+ token::Ident(..) => token::Ident(ast::Ident::with_empty_ctxt(nm)),
token::ModName),
- token::Lifetime(..) => token::Lifetime(ast::Ident { name: nm, ctxt: 0 }),
+ token::Lifetime(..) => token::Lifetime(ast::Ident::with_empty_ctxt(nm)),
ref t => t.clone()
};
#[stable(feature = "arc_unique", since = "1.4.0")]
pub fn try_unwrap(this: Self) -> Result<T, Self> {
// See `drop` for why all these atomics are like this
- if this.inner().strong.compare_and_swap(1, 0, Release) != 1 { return Err(this) }
+ if this.inner().strong.compare_and_swap(1, 0, Release) != 1 {
+ return Err(this)
+ }
atomic::fence(Acquire);
let cur = this.inner().weak.load(Relaxed);
// check if the weak counter is currently "locked"; if so, spin.
- if cur == usize::MAX { continue }
+ if cur == usize::MAX {
+ continue
+ }
// NOTE: this code currently ignores the possibility of overflow
// into usize::MAX; in general both Rc and Arc need to be adjusted
if self.inner().weak.fetch_sub(1, Release) == 1 {
atomic::fence(Acquire);
- deallocate(ptr as *mut u8, size_of_val(&*ptr), align_of_val(&*ptr))
+ deallocate(ptr as *mut u8,
+ size_of_val(&*ptr),
+ align_of_val(&*ptr))
}
}
}
// We abort because such a program is incredibly degenerate, and we
// don't care to support it.
if old_size > MAX_REFCOUNT {
- unsafe { abort(); }
+ unsafe {
+ abort();
+ }
}
Arc { _ptr: self._ptr }
// Because `fetch_sub` is already atomic, we do not need to synchronize
// with other threads unless we are going to delete the object. This
// same logic applies to the below `fetch_sub` to the `weak` count.
- if self.inner().strong.fetch_sub(1, Release) != 1 { return }
+ if self.inner().strong.fetch_sub(1, Release) != 1 {
+ return
+ }
// This fence is needed to prevent reordering of use of the data and
// deletion of the data. Because it is marked `Release`, the decreasing
atomic::fence(Acquire);
unsafe {
- self.drop_slow()
+ self.drop_slow();
}
}
}
// "stale" read of 0 is fine), and any other value is
// confirmed via the CAS below.
let n = inner.strong.load(Relaxed);
- if n == 0 { return None }
+ if n == 0 {
+ return None
+ }
// Relaxed is valid for the same reason it is on Arc's Clone impl
let old = inner.strong.compare_and_swap(n, n + 1, Relaxed);
- if old == n { return Some(Arc { _ptr: self._ptr }) }
+ if old == n {
+ return Some(Arc { _ptr: self._ptr })
+ }
}
}
// See comments in Arc::clone() for why we do this (for mem::forget).
if old_size > MAX_REFCOUNT {
- unsafe { abort(); }
+ unsafe {
+ abort();
+ }
}
return Weak { _ptr: self._ptr }
// ref, which can only happen after the lock is released.
if self.inner().weak.fetch_sub(1, Release) == 1 {
atomic::fence(Acquire);
- unsafe { deallocate(ptr as *mut u8,
- size_of_val(&*ptr),
- align_of_val(&*ptr)) }
+ unsafe {
+ deallocate(ptr as *mut u8,
+ size_of_val(&*ptr),
+ align_of_val(&*ptr))
+ }
}
}
}
///
/// five == Arc::new(5);
/// ```
- fn eq(&self, other: &Arc<T>) -> bool { *(*self) == *(*other) }
+ fn eq(&self, other: &Arc<T>) -> bool {
+ *(*self) == *(*other)
+ }
/// Inequality for two `Arc<T>`s.
///
///
/// five != Arc::new(5);
/// ```
- fn ne(&self, other: &Arc<T>) -> bool { *(*self) != *(*other) }
+ fn ne(&self, other: &Arc<T>) -> bool {
+ *(*self) != *(*other)
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + PartialOrd> PartialOrd for Arc<T> {
///
/// five < Arc::new(5);
/// ```
- fn lt(&self, other: &Arc<T>) -> bool { *(*self) < *(*other) }
+ fn lt(&self, other: &Arc<T>) -> bool {
+ *(*self) < *(*other)
+ }
/// 'Less-than or equal to' comparison for two `Arc<T>`s.
///
///
/// five <= Arc::new(5);
/// ```
- fn le(&self, other: &Arc<T>) -> bool { *(*self) <= *(*other) }
+ fn le(&self, other: &Arc<T>) -> bool {
+ *(*self) <= *(*other)
+ }
/// Greater-than comparison for two `Arc<T>`s.
///
///
/// five > Arc::new(5);
/// ```
- fn gt(&self, other: &Arc<T>) -> bool { *(*self) > *(*other) }
+ fn gt(&self, other: &Arc<T>) -> bool {
+ *(*self) > *(*other)
+ }
/// 'Greater-than or equal to' comparison for two `Arc<T>`s.
///
///
/// five >= Arc::new(5);
/// ```
- fn ge(&self, other: &Arc<T>) -> bool { *(*self) >= *(*other) }
+ fn ge(&self, other: &Arc<T>) -> bool {
+ *(*self) >= *(*other)
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Ord> Ord for Arc<T> {
- fn cmp(&self, other: &Arc<T>) -> Ordering { (**self).cmp(&**other) }
+ fn cmp(&self, other: &Arc<T>) -> Ordering {
+ (**self).cmp(&**other)
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Eq> Eq for Arc<T> {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Default> Default for Arc<T> {
#[stable(feature = "rust1", since = "1.0.0")]
- fn default() -> Arc<T> { Arc::new(Default::default()) }
+ fn default() -> Arc<T> {
+ Arc::new(Default::default())
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
#[test]
fn weak_self_cyclic() {
struct Cycle {
- x: Mutex<Option<Weak<Cycle>>>
+ x: Mutex<Option<Weak<Cycle>>>,
}
let a = Arc::new(Cycle { x: Mutex::new(None) });
// Make sure deriving works with Arc<T>
#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug, Default)]
- struct Foo { inner: Arc<i32> }
+ struct Foo {
+ inner: Arc<i32>,
+ }
#[test]
fn test_unsized() {
}
impl<T: ?Sized> borrow::Borrow<T> for Arc<T> {
- fn borrow(&self) -> &T { &**self }
+ fn borrow(&self) -> &T {
+ &**self
+ }
}
use core::ops::{CoerceUnsized, Deref, DerefMut};
use core::ops::{Placer, Boxed, Place, InPlace, BoxPlace};
use core::ptr::{self, Unique};
-use core::raw::{TraitObject};
+use core::raw::TraitObject;
/// A value that represents the heap. This is the default place that the `box`
/// keyword allocates into when no place is supplied.
reason = "may be renamed; uncertain about custom allocator design",
issue = "27779")]
#[derive(Copy, Clone)]
-pub struct ExchangeHeapSingleton { _force_singleton: () }
+pub struct ExchangeHeapSingleton {
+ _force_singleton: (),
+}
/// A pointer type for heap allocation.
///
#[unstable(feature = "placement_in",
reason = "placement box design is still being worked out.",
issue = "27779")]
-pub struct IntermediateBox<T: ?Sized>{
+pub struct IntermediateBox<T: ?Sized> {
ptr: *mut u8,
size: usize,
align: usize,
let p = if size == 0 {
heap::EMPTY as *mut u8
} else {
- let p = unsafe {
- heap::allocate(size, align)
- };
+ let p = unsafe { heap::allocate(size, align) };
if p.is_null() {
panic!("Box make_place allocation failure.");
}
}
impl<T> BoxPlace<T> for IntermediateBox<T> {
- fn make_place() -> IntermediateBox<T> { make_place() }
+ fn make_place() -> IntermediateBox<T> {
+ make_place()
+ }
}
impl<T> InPlace<T> for IntermediateBox<T> {
type Owner = Box<T>;
- unsafe fn finalize(self) -> Box<T> { finalize(self) }
+ unsafe fn finalize(self) -> Box<T> {
+ finalize(self)
+ }
}
impl<T> Boxed for Box<T> {
type Data = T;
type Place = IntermediateBox<T>;
- unsafe fn finalize(b: IntermediateBox<T>) -> Box<T> { finalize(b) }
+ unsafe fn finalize(b: IntermediateBox<T>) -> Box<T> {
+ finalize(b)
+ }
}
impl<T> Placer<T> for ExchangeHeapSingleton {
impl<T: ?Sized> Drop for IntermediateBox<T> {
fn drop(&mut self) {
if self.size > 0 {
- unsafe {
- heap::deallocate(self.ptr, self.size, self.align)
- }
+ unsafe { heap::deallocate(self.ptr, self.size, self.align) }
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Default> Default for Box<T> {
#[stable(feature = "rust1", since = "1.0.0")]
- fn default() -> Box<T> { box Default::default() }
+ fn default() -> Box<T> {
+ box Default::default()
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Default for Box<[T]> {
#[stable(feature = "rust1", since = "1.0.0")]
- fn default() -> Box<[T]> { Box::<[T; 0]>::new([]) }
+ fn default() -> Box<[T]> {
+ Box::<[T; 0]>::new([])
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
/// let x = Box::new(5);
/// let y = x.clone();
/// ```
+ #[rustfmt_skip]
#[inline]
- fn clone(&self) -> Box<T> { box {(**self).clone()} }
+ fn clone(&self) -> Box<T> {
+ box { (**self).clone() }
+ }
/// Copies `source`'s contents into `self` without creating a new allocation.
///
/// # Examples
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + PartialEq> PartialEq for Box<T> {
#[inline]
- fn eq(&self, other: &Box<T>) -> bool { PartialEq::eq(&**self, &**other) }
+ fn eq(&self, other: &Box<T>) -> bool {
+ PartialEq::eq(&**self, &**other)
+ }
#[inline]
- fn ne(&self, other: &Box<T>) -> bool { PartialEq::ne(&**self, &**other) }
+ fn ne(&self, other: &Box<T>) -> bool {
+ PartialEq::ne(&**self, &**other)
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + PartialOrd> PartialOrd for Box<T> {
PartialOrd::partial_cmp(&**self, &**other)
}
#[inline]
- fn lt(&self, other: &Box<T>) -> bool { PartialOrd::lt(&**self, &**other) }
+ fn lt(&self, other: &Box<T>) -> bool {
+ PartialOrd::lt(&**self, &**other)
+ }
#[inline]
- fn le(&self, other: &Box<T>) -> bool { PartialOrd::le(&**self, &**other) }
+ fn le(&self, other: &Box<T>) -> bool {
+ PartialOrd::le(&**self, &**other)
+ }
#[inline]
- fn ge(&self, other: &Box<T>) -> bool { PartialOrd::ge(&**self, &**other) }
+ fn ge(&self, other: &Box<T>) -> bool {
+ PartialOrd::ge(&**self, &**other)
+ }
#[inline]
- fn gt(&self, other: &Box<T>) -> bool { PartialOrd::gt(&**self, &**other) }
+ fn gt(&self, other: &Box<T>) -> bool {
+ PartialOrd::gt(&**self, &**other)
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Ord> Ord for Box<T> {
unsafe {
// Get the raw representation of the trait object
let raw = Box::into_raw(self);
- let to: TraitObject =
- mem::transmute::<*mut Any, TraitObject>(raw);
+ let to: TraitObject = mem::transmute::<*mut Any, TraitObject>(raw);
// Extract the data pointer
Ok(Box::from_raw(to.data as *mut T))
impl<T: ?Sized> Deref for Box<T> {
type Target = T;
- fn deref(&self) -> &T { &**self }
+ fn deref(&self) -> &T {
+ &**self
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> DerefMut for Box<T> {
- fn deref_mut(&mut self) -> &mut T { &mut **self }
+ fn deref_mut(&mut self) -> &mut T {
+ &mut **self
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator + ?Sized> Iterator for Box<I> {
type Item = I::Item;
- fn next(&mut self) -> Option<I::Item> { (**self).next() }
- fn size_hint(&self) -> (usize, Option<usize>) { (**self).size_hint() }
+ fn next(&mut self) -> Option<I::Item> {
+ (**self).next()
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (**self).size_hint()
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for Box<I> {
- fn next_back(&mut self) -> Option<I::Item> { (**self).next_back() }
+ fn next_back(&mut self) -> Option<I::Item> {
+ (**self).next_back()
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {}
#[stable(feature = "box_slice_clone", since = "1.3.0")]
impl<T: Clone> Clone for Box<[T]> {
fn clone(&self) -> Self {
- let mut new = BoxBuilder {
- data: RawVec::with_capacity(self.len()),
- len: 0
- };
+ let mut new = BoxBuilder { data: RawVec::with_capacity(self.len()), len: 0 };
let mut target = new.data.ptr();
}
impl<T: ?Sized> borrow::Borrow<T> for Box<T> {
- fn borrow(&self) -> &T { &**self }
+ fn borrow(&self) -> &T {
+ &**self
+ }
}
impl<T: ?Sized> borrow::BorrowMut<T> for Box<T> {
- fn borrow_mut(&mut self) -> &mut T { &mut **self }
+ fn borrow_mut(&mut self) -> &mut T {
+ &mut **self
+ }
}
let b = Box::new(Test) as Box<Any>;
match a.downcast::<i32>() {
- Ok(a) => { assert!(a == Box::new(8)); }
- Err(..) => panic!()
+ Ok(a) => {
+ assert!(a == Box::new(8));
+ }
+ Err(..) => panic!(),
}
match b.downcast::<Test>() {
- Ok(a) => { assert!(a == Box::new(Test)); }
- Err(..) => panic!()
+ Ok(a) => {
+ assert!(a == Box::new(Test));
+ }
+ Err(..) => panic!(),
}
let a = Box::new(8) as Box<Any>;
#[test]
fn deref() {
- fn homura<T: Deref<Target=i32>>(_: T) { }
+ fn homura<T: Deref<Target = i32>>(_: T) {
+ }
homura(Box::new(765));
}
#[allocator]
fn __rust_allocate(size: usize, align: usize) -> *mut u8;
fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize);
- fn __rust_reallocate(ptr: *mut u8, old_size: usize, size: usize,
- align: usize) -> *mut u8;
- fn __rust_reallocate_inplace(ptr: *mut u8, old_size: usize, size: usize,
- align: usize) -> usize;
+ fn __rust_reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8;
+ fn __rust_reallocate_inplace(ptr: *mut u8,
+ old_size: usize,
+ size: usize,
+ align: usize)
+ -> usize;
fn __rust_usable_size(size: usize, align: usize) -> usize;
}
#[inline(always)]
fn check_size_and_alignment(size: usize, align: usize) {
debug_assert!(size != 0);
- debug_assert!(size <= isize::MAX as usize, "Tried to allocate too much: {} bytes", size);
- debug_assert!(usize::is_power_of_two(align), "Invalid alignment of allocation: {}", align);
+ debug_assert!(size <= isize::MAX as usize,
+ "Tried to allocate too much: {} bytes",
+ size);
+ debug_assert!(usize::is_power_of_two(align),
+ "Invalid alignment of allocation: {}",
+ align);
}
// FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
-pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: usize, size: usize,
- align: usize) -> usize {
+pub unsafe fn reallocate_inplace(ptr: *mut u8,
+ old_size: usize,
+ size: usize,
+ align: usize)
+ -> usize {
check_size_and_alignment(size, align);
__rust_reallocate_inplace(ptr, old_size, size, align)
}
EMPTY as *mut u8
} else {
let ptr = allocate(size, align);
- if ptr.is_null() { ::oom() }
+ if ptr.is_null() {
+ ::oom()
+ }
ptr
}
}
unsafe {
let size = 4000;
let ptr = heap::allocate(size, 8);
- if ptr.is_null() { ::oom() }
+ if ptr.is_null() {
+ ::oom()
+ }
let ret = heap::reallocate_inplace(ptr, size, size, 8);
heap::deallocate(ptr, size, 8);
assert_eq!(ret, heap::usable_size(size, 8));
// Allow testing this library
-#[cfg(test)] #[macro_use] extern crate std;
-#[cfg(test)] #[macro_use] extern crate log;
+#[cfg(test)]
+#[macro_use]
+extern crate std;
+#[cfg(test)]
+#[macro_use]
+extern crate log;
// Heaps provided for low-level allocation strategies
#[cfg(not(test))]
pub mod boxed;
#[cfg(test)]
-mod boxed { pub use std::boxed::{Box, HEAP}; }
+mod boxed {
+ pub use std::boxed::{Box, HEAP};
+}
#[cfg(test)]
mod boxed_test;
pub mod arc;
pub fn new() -> Self {
unsafe {
// !0 is usize::MAX. This branch should be stripped at compile time.
- let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 };
+ let cap = if mem::size_of::<T>() == 0 {
+ !0
+ } else {
+ 0
+ };
// heap::EMPTY doubles as "unallocated" and "zero-sized allocation"
RawVec { ptr: Unique::new(heap::EMPTY as *mut T), cap: cap }
} else {
let align = mem::align_of::<T>();
let ptr = heap::allocate(alloc_size, align);
- if ptr.is_null() { oom() }
+ if ptr.is_null() {
+ oom()
+ }
ptr
};
///
/// This will always be `usize::MAX` if `T` is zero-sized.
pub fn cap(&self) -> usize {
- if mem::size_of::<T>() == 0 { !0 } else { self.cap }
+ if mem::size_of::<T>() == 0 {
+ !0
+ } else {
+ self.cap
+ }
}
/// Doubles the size of the type's backing allocation. This is common enough
let (new_cap, ptr) = if self.cap == 0 {
// skip to 4 because tiny Vec's are dumb; but not if that would cause overflow
- let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 };
+ let new_cap = if elem_size > (!0) / 8 {
+ 1
+ } else {
+ 4
+ };
let ptr = heap::allocate(new_cap * elem_size, align);
(new_cap, ptr)
} else {
};
// If allocate or reallocate fail, we'll get `null` back
- if ptr.is_null() { oom() }
+ if ptr.is_null() {
+ oom()
+ }
self.ptr = Unique::new(ptr as *mut _);
self.cap = new_cap;
// Don't actually need any more capacity.
// Wrapping in case they gave a bad `used_cap`.
- if self.cap().wrapping_sub(used_cap) >= needed_extra_cap { return; }
+ if self.cap().wrapping_sub(used_cap) >= needed_extra_cap {
+ return;
+ }
// Nothing we can really do about these checks :(
let new_cap = used_cap.checked_add(needed_extra_cap).expect("capacity overflow");
};
// If allocate or reallocate fail, we'll get `null` back
- if ptr.is_null() { oom() }
+ if ptr.is_null() {
+ oom()
+ }
self.ptr = Unique::new(ptr as *mut _);
self.cap = new_cap;
// Don't actually need any more capacity.
// Wrapping in case they give a bas `used_cap`
- if self.cap().wrapping_sub(used_cap) >= needed_extra_cap { return; }
+ if self.cap().wrapping_sub(used_cap) >= needed_extra_cap {
+ return;
+ }
// Nothing we can really do about these checks :(
let new_cap = used_cap.checked_add(needed_extra_cap)
};
// If allocate or reallocate fail, we'll get `null` back
- if ptr.is_null() { oom() }
+ if ptr.is_null() {
+ oom()
+ }
self.ptr = Unique::new(ptr as *mut _);
self.cap = new_cap;
}
// This check is my waterloo; it's the only thing Vec wouldn't have to do.
- assert!(self.cap >= amount, "Tried to shrink to a larger capacity");
+ assert!(self.cap >= amount,
+ "Tried to shrink to a larger capacity");
if amount == 0 {
mem::replace(self, RawVec::new());
self.cap * elem_size,
amount * elem_size,
align);
- if ptr.is_null() { oom() }
+ if ptr.is_null() {
+ oom()
+ }
self.ptr = Unique::new(ptr as *mut _);
}
self.cap = amount;
#[inline]
fn alloc_guard(alloc_size: usize) {
if core::usize::BITS < 64 {
- assert!(alloc_size <= ::core::isize::MAX as usize, "capacity overflow");
+ assert!(alloc_size <= ::core::isize::MAX as usize,
+ "capacity overflow");
}
}
_ptr: NonZero::new(Box::into_raw(box RcBox {
strong: Cell::new(1),
weak: Cell::new(1),
- value: value
+ value: value,
})),
}
}
#[inline]
#[unstable(feature = "rc_counts", reason = "not clearly useful",
issue = "28356")]
- pub fn weak_count(this: &Self) -> usize { this.weak() - 1 }
+ pub fn weak_count(this: &Self) -> usize {
+ this.weak() - 1
+ }
/// Get the number of strong references to this value.
#[inline]
#[unstable(feature = "rc_counts", reason = "not clearly useful",
issue = "28356")]
- pub fn strong_count(this: &Self) -> usize { this.strong() }
+ pub fn strong_count(this: &Self) -> usize {
+ this.strong()
+ }
/// Returns true if there are no other `Rc` or `Weak<T>` values that share
/// the same inner value.
unsafe {
let ptr = *self._ptr;
if !(*(&ptr as *const _ as *const *const ())).is_null() &&
- ptr as *const () as usize != mem::POST_DROP_USIZE {
+ ptr as *const () as usize != mem::POST_DROP_USIZE {
self.dec_strong();
if self.strong() == 0 {
// destroy the contained object
/// five == Rc::new(5);
/// ```
#[inline(always)]
- fn eq(&self, other: &Rc<T>) -> bool { **self == **other }
+ fn eq(&self, other: &Rc<T>) -> bool {
+ **self == **other
+ }
/// Inequality for two `Rc<T>`s.
///
/// five != Rc::new(5);
/// ```
#[inline(always)]
- fn ne(&self, other: &Rc<T>) -> bool { **self != **other }
+ fn ne(&self, other: &Rc<T>) -> bool {
+ **self != **other
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
/// five < Rc::new(5);
/// ```
#[inline(always)]
- fn lt(&self, other: &Rc<T>) -> bool { **self < **other }
+ fn lt(&self, other: &Rc<T>) -> bool {
+ **self < **other
+ }
/// 'Less-than or equal to' comparison for two `Rc<T>`s.
///
/// five <= Rc::new(5);
/// ```
#[inline(always)]
- fn le(&self, other: &Rc<T>) -> bool { **self <= **other }
+ fn le(&self, other: &Rc<T>) -> bool {
+ **self <= **other
+ }
/// Greater-than comparison for two `Rc<T>`s.
///
/// five > Rc::new(5);
/// ```
#[inline(always)]
- fn gt(&self, other: &Rc<T>) -> bool { **self > **other }
+ fn gt(&self, other: &Rc<T>) -> bool {
+ **self > **other
+ }
/// 'Greater-than or equal to' comparison for two `Rc<T>`s.
///
/// five >= Rc::new(5);
/// ```
#[inline(always)]
- fn ge(&self, other: &Rc<T>) -> bool { **self >= **other }
+ fn ge(&self, other: &Rc<T>) -> bool {
+ **self >= **other
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
/// five.partial_cmp(&Rc::new(5));
/// ```
#[inline]
- fn cmp(&self, other: &Rc<T>) -> Ordering { (**self).cmp(&**other) }
+ fn cmp(&self, other: &Rc<T>) -> Ordering {
+ (**self).cmp(&**other)
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
unsafe {
let ptr = *self._ptr;
if !(*(&ptr as *const _ as *const *const ())).is_null() &&
- ptr as *const () as usize != mem::POST_DROP_USIZE {
+ ptr as *const () as usize != mem::POST_DROP_USIZE {
self.dec_weak();
// the weak count starts at 1, and will only go to zero if all
// the strong pointers have disappeared.
if self.weak() == 0 {
- deallocate(ptr as *mut u8, size_of_val(&*ptr),
+ deallocate(ptr as *mut u8,
+ size_of_val(&*ptr),
align_of_val(&*ptr))
}
}
fn inner(&self) -> &RcBox<T>;
#[inline]
- fn strong(&self) -> usize { self.inner().strong.get() }
+ fn strong(&self) -> usize {
+ self.inner().strong.get()
+ }
#[inline]
fn inc_strong(&self) {
}
#[inline]
- fn dec_strong(&self) { self.inner().strong.set(self.strong() - 1); }
+ fn dec_strong(&self) {
+ self.inner().strong.set(self.strong() - 1);
+ }
#[inline]
- fn weak(&self) -> usize { self.inner().weak.get() }
+ fn weak(&self) -> usize {
+ self.inner().weak.get()
+ }
#[inline]
fn inc_weak(&self) {
}
#[inline]
- fn dec_weak(&self) { self.inner().weak.set(self.weak() - 1); }
+ fn dec_weak(&self) {
+ self.inner().weak.set(self.weak() - 1);
+ }
}
impl<T: ?Sized> RcBoxPtr<T> for Rc<T> {
#[test]
fn weak_self_cyclic() {
struct Cycle {
- x: RefCell<Option<Weak<Cycle>>>
+ x: RefCell<Option<Weak<Cycle>>>,
}
let a = Rc::new(Cycle { x: RefCell::new(None) });
}
impl<T: ?Sized> borrow::Borrow<T> for Rc<T> {
- fn borrow(&self) -> &T { &**self }
+ fn borrow(&self) -> &T {
+ &**self
+ }
}
core_str::StrExt::rmatches(self, pat)
}
- /// An iterator over the start and end indices of the disjoint matches
- /// of a pattern within `self`.
+ /// An iterator over the disjoint matches of a pattern within `self` as well
+ /// as the index that the match starts at.
///
/// For matches of `pat` within `self` that overlap, only the indices
- /// corresponding to the first
- /// match are returned.
+ /// corresponding to the first match are returned.
///
- /// The pattern can be a simple `&str`, `char`, or a closure that
- /// determines if a character matches.
- /// Additional libraries might provide more complex patterns like
- /// regular expressions.
+ /// The pattern can be a simple `&str`, `char`, or a closure that determines
+ /// if a character matches. Additional libraries might provide more complex
+ /// patterns like regular expressions.
///
/// # Iterator behavior
///
/// The returned iterator will be double ended if the pattern allows a
- /// reverse search
- /// and forward/reverse search yields the same elements. This is true for,
- /// eg, `char` but not
- /// for `&str`.
+ /// reverse search and forward/reverse search yields the same elements. This
+ /// is true for, eg, `char` but not for `&str`.
///
/// If the pattern allows a reverse search but its results might differ
/// from a forward search, `rmatch_indices()` can be used.
/// ```
/// #![feature(str_match_indices)]
///
- /// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".match_indices("abc").collect();
- /// assert_eq!(v, [(0, 3), (6, 9), (12, 15)]);
+ /// let v: Vec<_> = "abcXXXabcYYYabc".match_indices("abc").collect();
+ /// assert_eq!(v, [(0, "abc"), (6, "abc"), (12, "abc")]);
///
- /// let v: Vec<(usize, usize)> = "1abcabc2".match_indices("abc").collect();
- /// assert_eq!(v, [(1, 4), (4, 7)]);
+ /// let v: Vec<_> = "1abcabc2".match_indices("abc").collect();
+ /// assert_eq!(v, [(1, "abc"), (4, "abc")]);
///
- /// let v: Vec<(usize, usize)> = "ababa".match_indices("aba").collect();
- /// assert_eq!(v, [(0, 3)]); // only the first `aba`
+ /// let v: Vec<_> = "ababa".match_indices("aba").collect();
+ /// assert_eq!(v, [(0, "aba")]); // only the first `aba`
/// ```
#[unstable(feature = "str_match_indices",
reason = "might have its iterator type changed",
issue = "27743")]
- // NB: Right now MatchIndices yields `(usize, usize)`, but it would
- // be more consistent with `matches` and `char_indices` to return `(usize, &str)`
pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> {
core_str::StrExt::match_indices(self, pat)
}
- /// An iterator over the start and end indices of the disjoint matches of
- /// a pattern within
- /// `self`, yielded in reverse order.
+ /// An iterator over the disjoint matches of a pattern within `self`,
+ /// yielded in reverse order along with the index of the match.
///
/// For matches of `pat` within `self` that overlap, only the indices
- /// corresponding to the last
- /// match are returned.
+ /// corresponding to the last match are returned.
///
- /// The pattern can be a simple `&str`, `char`, or a closure that
- /// determines if a character matches.
- /// Additional libraries might provide more complex patterns like
- /// regular expressions.
+ /// The pattern can be a simple `&str`, `char`, or a closure that determines
+ /// if a character matches. Additional libraries might provide more complex
+ /// patterns like regular expressions.
///
/// # Iterator behavior
///
- /// The returned iterator requires that the pattern supports a
- /// reverse search,
- /// and it will be double ended if a forward/reverse search yields
+ /// The returned iterator requires that the pattern supports a reverse
+ /// search, and it will be double ended if a forward/reverse search yields
/// the same elements.
///
/// For iterating from the front, `match_indices()` can be used.
/// ```
/// #![feature(str_match_indices)]
///
- /// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".rmatch_indices("abc").collect();
- /// assert_eq!(v, [(12, 15), (6, 9), (0, 3)]);
+ /// let v: Vec<_> = "abcXXXabcYYYabc".rmatch_indices("abc").collect();
+ /// assert_eq!(v, [(12, "abc"), (6, "abc"), (0, "abc")]);
///
- /// let v: Vec<(usize, usize)> = "1abcabc2".rmatch_indices("abc").collect();
- /// assert_eq!(v, [(4, 7), (1, 4)]);
+ /// let v: Vec<_> = "1abcabc2".rmatch_indices("abc").collect();
+ /// assert_eq!(v, [(4, "abc"), (1, "abc")]);
///
- /// let v: Vec<(usize, usize)> = "ababa".rmatch_indices("aba").collect();
- /// assert_eq!(v, [(2, 5)]); // only the last `aba`
+ /// let v: Vec<_> = "ababa".rmatch_indices("aba").collect();
+ /// assert_eq!(v, [(2, "aba")]); // only the last `aba`
/// ```
#[unstable(feature = "str_match_indices",
reason = "might have its iterator type changed",
issue = "27743")]
- // NB: Right now RMatchIndices yields `(usize, usize)`, but it would
- // be more consistent with `rmatches` and `char_indices` to return `(usize, &str)`
pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P>
where P::Searcher: ReverseSearcher<'a>
{
pub fn replace(&self, from: &str, to: &str) -> String {
let mut result = String::new();
let mut last_end = 0;
- for (start, end) in self.match_indices(from) {
+ for (start, part) in self.match_indices(from) {
result.push_str(unsafe { self.slice_unchecked(last_end, start) });
result.push_str(to);
- last_end = end;
+ last_end = start + part.len();
}
result.push_str(unsafe { self.slice_unchecked(last_end, self.len()) });
result
#[unstable(feature = "str_parse_error", reason = "may want to be replaced with \
Void if it ever exists",
issue = "27734")]
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
-pub struct ParseError(());
+#[derive(Copy)]
+pub enum ParseError {}
#[stable(feature = "rust1", since = "1.0.0")]
impl FromStr for String {
}
}
+impl Clone for ParseError {
+ fn clone(&self) -> ParseError {
+ match *self {}
+ }
+}
+
+impl fmt::Debug for ParseError {
+ fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
+ match *self {}
+ }
+}
+
+impl PartialEq for ParseError {
+ fn eq(&self, _: &ParseError) -> bool {
+ match *self {}
+ }
+}
+
+impl Eq for ParseError {}
+
/// A generic trait for converting a value to a string
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ToString {
fn test_empty_match_indices() {
let data = "aää¸!";
let vec: Vec<_> = data.match_indices("").collect();
- assert_eq!(vec, [(0, 0), (1, 1), (3, 3), (6, 6), (7, 7)]);
+ assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
}
#[test]
generate_iterator_test! {
double_ended_match_indices {
- ("a1b2c3", char::is_numeric) -> [(1, 2), (3, 4), (5, 6)];
+ ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
}
with str::match_indices, str::rmatch_indices;
}
let mut sign = None;
if !is_positive {
sign = Some('-'); width += 1;
- } else if self.flags & (1 << (FlagV1::SignPlus as u32)) != 0 {
+ } else if self.sign_plus() {
sign = Some('+'); width += 1;
}
let mut prefixed = false;
- if self.flags & (1 << (FlagV1::Alternate as u32)) != 0 {
+ if self.alternate() {
prefixed = true; width += prefix.char_len();
}
}
// The sign and prefix goes before the padding if the fill character
// is zero
- Some(min) if self.flags & (1 << (FlagV1::SignAwareZeroPad as u32)) != 0 => {
+ Some(min) if self.sign_aware_zero_pad() => {
self.fill = '0';
try!(write_prefix(self));
self.with_padding(min - width, Alignment::Right, |f| {
let mut formatted = formatted.clone();
let mut align = self.align;
let old_fill = self.fill;
- if self.flags & (1 << (FlagV1::SignAwareZeroPad as u32)) != 0 {
+ if self.sign_aware_zero_pad() {
// a sign always goes first
let sign = unsafe { str::from_utf8_unchecked(formatted.sign) };
try!(self.buf.write_str(sign));
issue = "27726")]
pub fn precision(&self) -> Option<usize> { self.precision }
+ /// Determines if the `+` flag was specified.
+ #[unstable(feature = "fmt_flags", reason = "method was just created",
+ issue = "27726")]
+ pub fn sign_plus(&self) -> bool { self.flags & (1 << FlagV1::SignPlus as u32) != 0 }
+
+ /// Determines if the `-` flag was specified.
+ #[unstable(feature = "fmt_flags", reason = "method was just created",
+ issue = "27726")]
+ pub fn sign_minus(&self) -> bool { self.flags & (1 << FlagV1::SignMinus as u32) != 0 }
+
+ /// Determines if the `#` flag was specified.
+ #[unstable(feature = "fmt_flags", reason = "method was just created",
+ issue = "27726")]
+ pub fn alternate(&self) -> bool { self.flags & (1 << FlagV1::Alternate as u32) != 0 }
+
+ /// Determines if the `0` flag was specified.
+ #[unstable(feature = "fmt_flags", reason = "method was just created",
+ issue = "27726")]
+ pub fn sign_aware_zero_pad(&self) -> bool {
+ self.flags & (1 << FlagV1::SignAwareZeroPad as u32) != 0
+ }
+
/// Creates a `DebugStruct` builder designed to assist with creation of
/// `fmt::Debug` implementations for structs.
///
// it denotes whether to prefix with 0x. We use it to work out whether
// or not to zero extend, and then unconditionally set it to get the
// prefix.
- if f.flags & 1 << (FlagV1::Alternate as u32) > 0 {
+ if f.alternate() {
f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32);
if let None = f.width {
fn float_to_decimal_common<T>(fmt: &mut Formatter, num: &T, negative_zero: bool) -> Result
where T: flt2dec::DecodableFloat
{
- let force_sign = fmt.flags & (1 << (FlagV1::SignPlus as u32)) != 0;
+ let force_sign = fmt.sign_plus();
let sign = match (force_sign, negative_zero) {
(false, false) => flt2dec::Sign::Minus,
(false, true) => flt2dec::Sign::MinusRaw,
fn float_to_exponential_common<T>(fmt: &mut Formatter, num: &T, upper: bool) -> Result
where T: flt2dec::DecodableFloat
{
- let force_sign = fmt.flags & (1 << (FlagV1::SignPlus as u32)) != 0;
+ let force_sign = fmt.sign_plus();
let sign = match force_sign {
false => flt2dec::Sign::Minus,
true => flt2dec::Sign::MinusPlus,
/// While this does call the argument's implementation of `Drop`, it will not
/// release any borrows, as borrows are based on lexical scope.
///
+/// This effectively does nothing for
+/// [types which implement `Copy`](../../book/ownership.html#copy-types),
+/// e.g. integers. Such values are copied and _then_ moved into the function,
+/// so the value persists after this function call.
+///
/// # Examples
///
/// Basic usage:
/// let borrow = x.borrow();
/// println!("{}", *borrow);
/// ```
+///
+/// Integers and other types implementing `Copy` are unaffected by `drop()`
+///
+/// ```
+/// #[derive(Copy, Clone)]
+/// struct Foo(u8);
+///
+/// let x = 1;
+/// let y = Foo(2);
+/// drop(x); // a copy of `x` is moved and dropped
+/// drop(y); // a copy of `y` is moved and dropped
+///
+/// println!("x: {}, y: {}", x, y.0); // still available
+/// ```
+///
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn drop<T>(_x: T) { }
/// impl<T> Deref for DerefExample<T> {
/// type Target = T;
///
-/// fn deref<'a>(&'a self) -> &'a T {
+/// fn deref(&self) -> &T {
/// &self.value
/// }
/// }
// Free functions
//
-/// Converts a pointer to A into a slice of length 1 (without copying).
+/// Converts a reference to A into a slice of length 1 (without copying).
#[unstable(feature = "ref_slice", issue = "27774")]
pub fn ref_slice<A>(s: &A) -> &[A] {
unsafe {
}
}
-/// Converts a pointer to A into a slice of length 1 (without copying).
+/// Converts a reference to A into a slice of length 1 (without copying).
#[unstable(feature = "ref_slice", issue = "27774")]
pub fn mut_ref_slice<A>(s: &mut A) -> &mut [A] {
unsafe {
/// Returns the index in the given string up to which valid UTF-8 was
/// verified.
///
- /// Starting at the index provided, but not necessarily at it precisely, an
- /// invalid UTF-8 encoding sequence was found.
+ /// It is the maximum index such that `from_utf8(input[..index])`
+ /// would return `Some(_)`.
#[unstable(feature = "utf8_error", reason = "method just added",
issue = "27734")]
pub fn valid_up_to(&self) -> usize { self.valid_up_to }
impl<'a, P: Pattern<'a>> MatchIndicesInternal<'a, P> {
#[inline]
- fn next(&mut self) -> Option<(usize, usize)> {
- self.0.next_match()
+ fn next(&mut self) -> Option<(usize, &'a str)> {
+ self.0.next_match().map(|(start, end)| unsafe {
+ (start, self.0.haystack().slice_unchecked(start, end))
+ })
}
#[inline]
- fn next_back(&mut self) -> Option<(usize, usize)>
+ fn next_back(&mut self) -> Option<(usize, &'a str)>
where P::Searcher: ReverseSearcher<'a>
{
- self.0.next_match_back()
+ self.0.next_match_back().map(|(start, end)| unsafe {
+ (start, self.0.haystack().slice_unchecked(start, end))
+ })
}
}
reason = "type may be removed or have its iterator impl changed",
issue = "27743")]
internal:
- MatchIndicesInternal yielding ((usize, usize));
+ MatchIndicesInternal yielding ((usize, &'a str));
delegate double ended;
}
html_playground_url = "https://play.rust-lang.org/",
issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
#![cfg_attr(test, feature(test))]
+#![feature(cfg_target_vendor)]
//! Bindings for the C standard library and other platform libraries
//!
// On NaCl, these libraries are static. Thus it would be a Bad Idea to link them
// in when creating a test crate.
-#[cfg(not(any(windows, target_env = "musl", all(target_os = "nacl", test))))]
+#[cfg(not(any(windows,
+ target_env = "musl",
+ all(target_os = "nacl", test),
+ all(target_os = "netbsd", target_vendor = "rumprun"))))]
#[link(name = "c")]
#[link(name = "m")]
extern {}
let span = mk_sp(lo, p.last_span.hi);
p.abort_if_errors();
macros.push(ast::MacroDef {
- ident: name.ident(),
+ ident: ast::Ident::with_empty_ctxt(name),
attrs: attrs,
id: ast::DUMMY_NODE_ID,
span: span,
});
if let hir::ItemImpl(..) = item.node {
- let (ident, did) = (item.name, item.id);
+ let (name, did) = (item.name, item.id);
debug!("(encoding info for module) ... encoding impl {} ({}/{})",
- ident,
+ name,
did, ecx.tcx.map.node_to_string(did));
rbml_w.wr_tagged_u64(tag_mod_impl, def_to_u64(DefId::local(did)));
}
'[' => {
let def = self.parse_def(RegionParameter);
- let ident = token::str_to_ident(&self.parse_str(']'));
- ty::BrNamed(def, ident.name)
+ let name = token::intern(&self.parse_str(']'));
+ ty::BrNamed(def, name)
}
'f' => {
let id = self.parse_u32();
assert_eq!(self.next(), '|');
let index = self.parse_u32();
assert_eq!(self.next(), '|');
- let nm = token::str_to_ident(&self.parse_str(']'));
+ let name = token::intern(&self.parse_str(']'));
ty::ReEarlyBound(ty::EarlyBoundRegion {
param_id: node_id,
space: space,
index: index,
- name: nm.name
+ name: name
})
}
'f' => {
ty::ProjectionPredicate {
projection_ty: ty::ProjectionTy {
trait_ref: self.parse_trait_ref(),
- item_name: token::str_to_ident(&self.parse_str('|')).name,
+ item_name: token::intern(&self.parse_str('|')),
},
ty: self.parse_ty(),
}
}
hir::ExprBreak(label) => {
- let loop_scope = self.find_scope(expr, label.map(|l| l.node));
+ let loop_scope = self.find_scope(expr, label.map(|l| l.node.name));
let b = self.add_ast_node(expr.id, &[pred]);
self.add_exiting_edge(expr, b,
loop_scope, loop_scope.break_index);
}
hir::ExprAgain(label) => {
- let loop_scope = self.find_scope(expr, label.map(|l| l.node));
+ let loop_scope = self.find_scope(expr, label.map(|l| l.node.name));
let a = self.add_ast_node(expr.id, &[pred]);
self.add_exiting_edge(expr, a,
loop_scope, loop_scope.continue_index);
fn find_scope(&self,
expr: &hir::Expr,
- label: Option<ast::Ident>) -> LoopScope {
+ label: Option<ast::Name>) -> LoopScope {
if label.is_none() {
return *self.loop_scopes.last().unwrap();
}
if !is_const {
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
+ fn span_limited_call_error(tcx: &ty::ctxt, span: Span, s: &str) {
+ span_err!(tcx.sess, span, E0015, "{}", s);
+ }
+
// FIXME(#24111) Remove this check when const fn stabilizes
if let UnstableFeatures::Disallow = v.tcx.sess.opts.unstable_features {
- span_err!(v.tcx.sess, e.span, E0015,
- "function calls in {}s are limited to \
- struct and enum constructors", v.msg());
+ span_limited_call_error(&v.tcx, e.span,
+ &format!("function calls in {}s are limited to \
+ struct and enum constructors",
+ v.msg()));
v.tcx.sess.span_note(e.span,
"a limited form of compile-time function \
evaluation is available on a nightly \
compiler via `const fn`");
} else {
- span_err!(v.tcx.sess, e.span, E0015,
- "function calls in {}s are limited to \
- constant functions, \
- struct and enum constructors", v.msg());
+ span_limited_call_error(&v.tcx, e.span,
+ &format!("function calls in {}s are limited \
+ to constant functions, \
+ struct and enum constructors",
+ v.msg()));
}
}
}
ps: &mut pprust::State,
node: pprust::AnnNode) -> io::Result<()> {
let id = match node {
- pprust::NodeIdent(_) | pprust::NodeName(_) => 0,
+ pprust::NodeName(_) => 0,
pprust::NodeExpr(expr) => expr.id,
pprust::NodeBlock(blk) => blk.id,
pprust::NodeItem(_) | pprust::NodeSubItem(_) => 0,
EntryPointType::Start
} else if attr::contains_name(&item.attrs, "main") {
EntryPointType::MainAttr
- } else if item.name == "main" {
+ } else if item.name.as_str() == "main" {
if depth == 1 {
// This is a top-level function so can be 'main'
EntryPointType::MainNamed
},
None => None
};
- let (fn_decl, generics, unsafety, constness, ident, expl_self, span)
+ let (fn_decl, generics, unsafety, constness, name, expl_self, span)
= node_inner.expect("expect item fn");
let rebuilder = Rebuilder::new(self.tcx, fn_decl, expl_self,
generics, same_regions, &life_giver);
let (fn_decl, expl_self, generics) = rebuilder.rebuild();
- self.give_expl_lifetime_param(&fn_decl, unsafety, constness, ident,
+ self.give_expl_lifetime_param(&fn_decl, unsafety, constness, name,
expl_self.as_ref(), &generics, span);
}
}
names.push(lt_name);
}
names.sort();
- let name = token::str_to_ident(&names[0]).name;
+ let name = token::intern(&names[0]);
return (name_to_dummy_lifetime(name), Kept);
}
return (self.life_giver.give_lifetime(), Fresh);
let mut s = String::from("'");
s.push_str(&num_to_string(self.counter.get()));
if !self.taken.contains(&s) {
- lifetime = name_to_dummy_lifetime(
- token::str_to_ident(&s[..]).name);
+ lifetime = name_to_dummy_lifetime(token::intern(&s[..]));
self.generated.borrow_mut().push(lifetime);
break;
}
ty::TyBareFn(_, ref bfty) => bfty.abi == RustIntrinsic,
_ => return false
};
- intrinsic && self.tcx.item_name(def_id) == "transmute"
+ intrinsic && self.tcx.item_name(def_id).as_str() == "transmute"
}
fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>, id: ast::NodeId) {
&*arg.pat,
|_bm, arg_id, _x, path1| {
debug!("adding argument {}", arg_id);
- let name = path1.node.name;
+ let name = path1.node;
fn_maps.add_variable(Arg(arg_id, name));
})
};
fn visit_local(ir: &mut IrMaps, local: &hir::Local) {
pat_util::pat_bindings(&ir.tcx.def_map, &*local.pat, |_, p_id, sp, path1| {
debug!("adding local variable {}", p_id);
- let name = path1.node.name;
+ let name = path1.node;
ir.add_live_node_for_node(p_id, VarDefNode(sp));
ir.add_variable(Local(LocalInfo {
id: p_id,
pat_util::pat_bindings(&ir.tcx.def_map, &**pat, |bm, p_id, sp, path1| {
debug!("adding local variable {} from match with bm {:?}",
p_id, bm);
- let name = path1.node.name;
+ let name = path1.node;
ir.add_live_node_for_node(p_id, VarDefNode(sp));
ir.add_variable(Local(LocalInfo {
id: p_id,
}
fn find_loop_scope(&self,
- opt_label: Option<ast::Ident>,
+ opt_label: Option<ast::Name>,
id: NodeId,
sp: Span)
-> NodeId {
hir::ExprBreak(opt_label) => {
// Find which label this break jumps to
- let sc = self.find_loop_scope(opt_label.map(|l| l.node), expr.id, expr.span);
+ let sc = self.find_loop_scope(opt_label.map(|l| l.node.name), expr.id, expr.span);
// Now that we know the label we're going to,
// look it up in the break loop nodes table
hir::ExprAgain(opt_label) => {
// Find which label this expr continues to
- let sc = self.find_loop_scope(opt_label.map(|l| l.node), expr.id, expr.span);
+ let sc = self.find_loop_scope(opt_label.map(|l| l.node.name), expr.id, expr.span);
// Now that we know the label we're going to,
// look it up in the continue loop nodes table
|_bm, p_id, sp, path1| {
let var = self.variable(p_id, sp);
// Ignore unused self.
- let ident = path1.node;
- if ident.name != special_idents::self_.name {
+ let name = path1.node;
+ if name != special_idents::self_.name {
self.warn_about_unused(sp, p_id, entry_ln, var);
}
})
use syntax::ast;
use rustc_front::hir;
use rustc_front::util::walk_pat;
-use syntax::codemap::{Span, Spanned, DUMMY_SP};
+use syntax::codemap::{respan, Span, Spanned, DUMMY_SP};
-pub type PatIdMap = FnvHashMap<ast::Ident, ast::NodeId>;
+pub type PatIdMap = FnvHashMap<ast::Name, ast::NodeId>;
// This is used because same-named variables in alternative patterns need to
// use the NodeId of their namesake in the first pattern.
/// Call `it` on every "binding" in a pattern, e.g., on `a` in
/// `match foo() { Some(a) => (), None => () }`
pub fn pat_bindings<I>(dm: &DefMap, pat: &hir::Pat, mut it: I) where
+ I: FnMut(hir::BindingMode, ast::NodeId, Span, &Spanned<ast::Name>),
+{
+ walk_pat(pat, |p| {
+ match p.node {
+ hir::PatIdent(binding_mode, ref pth, _) if pat_is_binding(dm, p) => {
+ it(binding_mode, p.id, p.span, &respan(pth.span, pth.node.name));
+ }
+ _ => {}
+ }
+ true
+ });
+}
+
+pub fn pat_bindings_hygienic<I>(dm: &DefMap, pat: &hir::Pat, mut it: I) where
I: FnMut(hir::BindingMode, ast::NodeId, Span, &Spanned<ast::Ident>),
{
walk_pat(pat, |p| {
match p.node {
hir::PatIdent(binding_mode, ref pth, _) if pat_is_binding(dm, p) => {
- it(binding_mode, p.id, p.span, pth);
+ it(binding_mode, p.id, p.span, &respan(pth.span, pth.node));
}
_ => {}
}
contains_bindings
}
-pub fn simple_identifier<'a>(pat: &'a hir::Pat) -> Option<&'a ast::Ident> {
+pub fn simple_name<'a>(pat: &'a hir::Pat) -> Option<ast::Name> {
match pat.node {
hir::PatIdent(hir::BindByValue(_), ref path1, None) => {
- Some(&path1.node)
+ Some(path1.node.name)
}
_ => {
None
tcx.with_path(id, |path| hir::Path {
global: false,
segments: path.last().map(|elem| hir::PathSegment {
- identifier: ast::Ident::new(elem.name()),
+ identifier: ast::Ident::with_empty_ctxt(elem.name()),
parameters: hir::PathParameters::none(),
}).into_iter().collect(),
span: DUMMY_SP,
trait_ref_hack: bool,
// List of labels in the function/method currently under analysis.
- labels_in_fn: Vec<(ast::Ident, Span)>,
+ labels_in_fn: Vec<(ast::Name, Span)>,
}
enum ScopeChain<'a> {
struct GatherLabels<'a> {
sess: &'a Session,
scope: Scope<'a>,
- labels_in_fn: &'a mut Vec<(ast::Ident, Span)>,
+ labels_in_fn: &'a mut Vec<(ast::Name, Span)>,
}
let mut gather = GatherLabels {
if let Some(label) = expression_label(ex) {
for &(prior, prior_span) in &self.labels_in_fn[..] {
// FIXME (#24278): non-hygienic comparison
- if label.name == prior.name {
+ if label == prior {
signal_shadowing_problem(self.sess,
- label.name,
+ label,
original_label(prior_span),
shadower_label(ex.span));
}
}
}
- fn expression_label(ex: &hir::Expr) -> Option<ast::Ident> {
+ fn expression_label(ex: &hir::Expr) -> Option<ast::Name> {
match ex.node {
hir::ExprWhile(_, _, Some(label)) |
- hir::ExprLoop(_, Some(label)) => Some(label),
+ hir::ExprLoop(_, Some(label)) => Some(label.name),
_ => None,
}
}
fn check_if_label_shadows_lifetime<'a>(sess: &'a Session,
mut scope: Scope<'a>,
- label: ast::Ident,
+ label: ast::Name,
label_span: Span) {
loop {
match *scope {
LateScope(lifetimes, s) => {
for lifetime_def in lifetimes {
// FIXME (#24278): non-hygienic comparison
- if label.name == lifetime_def.lifetime.name {
+ if label == lifetime_def.lifetime.name {
signal_shadowing_problem(
sess,
- label.name,
+ label,
original_lifetime(&lifetime_def.lifetime),
shadower_label(label_span));
return;
{
for &(label, label_span) in &self.labels_in_fn {
// FIXME (#24278): non-hygienic comparison
- if lifetime.name == label.name {
+ if lifetime.name == label {
signal_shadowing_problem(self.sess,
lifetime.name,
original_label(label_span),
// When compiling with --test we don't enforce stability on the
// compiler-generated test module, demarcated with `DUMMY_SP` plus the
// name `__test`
- if item.span == DUMMY_SP && item.name == "__test" { return }
+ if item.span == DUMMY_SP && item.name.as_str() == "__test" { return }
check_item(self.tcx, item, true,
&mut |id, sp, stab| self.check(id, sp, stab));
}
ty::Predicate::ObjectSafe(trait_def_id) => {
+ let violations = object_safety_violations(
+ infcx.tcx, trait_def_id);
report_object_safety_error(infcx.tcx,
obligation.cause.span,
trait_def_id,
+ violations,
is_warning);
note_obligation_cause(infcx, obligation);
}
}
TraitNotObjectSafe(did) => {
- report_object_safety_error(infcx.tcx, obligation.cause.span, did, is_warning);
+ let violations = object_safety_violations(infcx.tcx, did);
+ report_object_safety_error(infcx.tcx, obligation.cause.span, did,
+ violations, is_warning);
note_obligation_cause(infcx, obligation);
}
}
pub fn report_object_safety_error<'tcx>(tcx: &ty::ctxt<'tcx>,
span: Span,
trait_def_id: DefId,
+ violations: Vec<ObjectSafetyViolation>,
is_warning: bool)
{
span_err_or_warn!(
"the trait `{}` cannot be made into an object",
tcx.item_path_str(trait_def_id));
- for violation in object_safety_violations(tcx, trait_def_id) {
+ for violation in violations {
match violation {
ObjectSafetyViolation::SizedSelf => {
tcx.sess.fileline_note(
pub use self::project::normalize;
pub use self::project::Normalized;
pub use self::object_safety::is_object_safe;
+pub use self::object_safety::astconv_object_safety_violations;
pub use self::object_safety::object_safety_violations;
pub use self::object_safety::ObjectSafetyViolation;
pub use self::object_safety::MethodViolationCode;
result
}
+/// Returns the object safety violations that affect
+/// astconv - currently, Self in supertraits. This is needed
+/// because `object_safety_violations` can't be used during
+/// type collection.
+pub fn astconv_object_safety_violations<'tcx>(tcx: &ty::ctxt<'tcx>,
+ trait_def_id: DefId)
+ -> Vec<ObjectSafetyViolation<'tcx>>
+{
+ let mut violations = vec![];
+
+ if supertraits_reference_self(tcx, trait_def_id) {
+ violations.push(ObjectSafetyViolation::SupertraitSelf);
+ }
+
+ debug!("object_safety_violations_for_trait(trait_def_id={:?}) = {:?}",
+ trait_def_id,
+ violations);
+
+ violations
+}
+
pub fn object_safety_violations<'tcx>(tcx: &ty::ctxt<'tcx>,
trait_def_id: DefId)
-> Vec<ObjectSafetyViolation<'tcx>>
violations
}
-fn supertraits_reference_self<'tcx>(tcx: &ty::ctxt<'tcx>,
- trait_def_id: DefId)
- -> bool
+pub fn supertraits_reference_self<'tcx>(tcx: &ty::ctxt<'tcx>,
+ trait_def_id: DefId)
+ -> bool
{
let trait_def = tcx.lookup_trait_def(trait_def_id);
let trait_ref = trait_def.trait_ref.clone();
let wordsz = &sess.target.target.target_pointer_width;
let os = &sess.target.target.target_os;
let env = &sess.target.target.target_env;
+ let vendor = &sess.target.target.target_vendor;
let fam = match sess.target.target.options.is_like_windows {
true => InternedString::new("windows"),
mk(InternedString::new("target_endian"), intern(end)),
mk(InternedString::new("target_pointer_width"), intern(wordsz)),
mk(InternedString::new("target_env"), intern(env)),
+ mk(InternedString::new("target_vendor"), intern(vendor)),
];
if sess.opts.debug_assertions {
ret.push(attr::mk_word_item(InternedString::new("debug_assertions")));
let first = msg.match_indices("expected").filter(|s| {
s.0 > 0 && (msg.char_at_reverse(s.0) == ' ' ||
msg.char_at_reverse(s.0) == '(')
- }).map(|(a, b)| (a - 1, b));
+ }).map(|(a, b)| (a - 1, a + b.len()));
let second = msg.match_indices("found").filter(|s| {
msg.char_at_reverse(s.0) == ' '
- }).map(|(a, b)| (a - 1, b));
+ }).map(|(a, b)| (a - 1, a + b.len()));
let mut new_msg = String::new();
let mut head = 0;
arch: "aarch64".to_string(),
target_os: "ios".to_string(),
target_env: "".to_string(),
+ target_vendor: "apple".to_string(),
options: TargetOptions {
features: "+neon,+fp-armv8,+cyclone".to_string(),
eliminate_frame_pointer: false,
arch: "aarch64".to_string(),
target_os: "android".to_string(),
target_env: "".to_string(),
+ target_vendor: "unknown".to_string(),
options: super::android_base::opts(),
}
}
target_env: "gnu".to_string(),
arch: "aarch64".to_string(),
target_os: "linux".to_string(),
+ target_vendor: "unknown".to_string(),
options: base,
}
}
arch: "arm".to_string(),
target_os: "android".to_string(),
target_env: "gnu".to_string(),
+ target_vendor: "unknown".to_string(),
options: base,
}
}
arch: "arm".to_string(),
target_os: "linux".to_string(),
target_env: "gnueabi".to_string(),
+ target_vendor: "unknown".to_string(),
options: TargetOptions {
features: "+v6".to_string(),
arch: "arm".to_string(),
target_os: "linux".to_string(),
target_env: "gnueabihf".to_string(),
+ target_vendor: "unknown".to_string(),
options: TargetOptions {
features: "+v6,+vfp2".to_string(),
arch: "arm".to_string(),
target_os: "ios".to_string(),
target_env: "".to_string(),
+ target_vendor: "apple".to_string(),
options: TargetOptions {
features: "+v7,+vfp3,+neon".to_string(),
.. opts(Arch::Armv7)
arch: "arm".to_string(),
target_os: "ios".to_string(),
target_env: "".to_string(),
+ target_vendor: "apple".to_string(),
options: TargetOptions {
features: "+v7,+vfp4,+neon".to_string(),
.. opts(Arch::Armv7s)
arch: "x86".to_string(),
target_os: "ios".to_string(),
target_env: "".to_string(),
+ target_vendor: "apple".to_string(),
options: opts(Arch::I386)
}
}
arch: "x86".to_string(),
target_os: "macos".to_string(),
target_env: "".to_string(),
+ target_vendor: "apple".to_string(),
options: base,
}
}
arch: "x86".to_string(),
target_os: "android".to_string(),
target_env: "gnu".to_string(),
+ target_vendor: "unknown".to_string(),
options: base,
}
}
arch: "x86".to_string(),
target_os: "windows".to_string(),
target_env: "gnu".to_string(),
+ target_vendor: "pc".to_string(),
options: options,
}
}
arch: "x86".to_string(),
target_os: "windows".to_string(),
target_env: "msvc".to_string(),
+ target_vendor: "pc".to_string(),
options: base,
}
}
arch: "x86".to_string(),
target_os: "dragonfly".to_string(),
target_env: "".to_string(),
+ target_vendor: "unknown".to_string(),
options: base,
}
}
arch: "x86".to_string(),
target_os: "freebsd".to_string(),
target_env: "".to_string(),
+ target_vendor: "unknown".to_string(),
options: base,
}
}
arch: "x86".to_string(),
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
+ target_vendor: "unknown".to_string(),
options: base,
}
}
arch: "mips".to_string(),
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
+ target_vendor: "unknown".to_string(),
options: super::linux_base::opts()
}
}
arch: "mips".to_string(),
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
+ target_vendor: "unknown".to_string(),
options: super::linux_base::opts()
}
pub target_os: String,
/// Environment name to use for conditional compilation.
pub target_env: String,
+ /// Vendor name to use for conditional compilation.
+ pub target_vendor: String,
/// Architecture to use for ABI considerations. Valid options: "x86", "x86_64", "arm",
/// "aarch64", "mips", and "powerpc". "mips" includes "mipsel".
pub arch: String,
}
};
+ let get_opt_field = |name: &str, default: &str| {
+ obj.find(name).and_then(|s| s.as_string())
+ .map(|s| s.to_string())
+ .unwrap_or(default.to_string())
+ };
+
let mut base = Target {
llvm_target: get_req_field("llvm-target"),
target_endian: get_req_field("target-endian"),
target_pointer_width: get_req_field("target-pointer-width"),
arch: get_req_field("arch"),
target_os: get_req_field("os"),
- target_env: obj.find("env").and_then(|s| s.as_string())
- .map(|s| s.to_string()).unwrap_or(String::new()),
+ target_env: get_opt_field("env", ""),
+ target_vendor: get_opt_field("vendor", "unknown"),
options: Default::default(),
};
x86_64_unknown_bitrig,
x86_64_unknown_openbsd,
x86_64_unknown_netbsd,
+ x86_64_rumprun_netbsd,
x86_64_apple_darwin,
i686_apple_darwin,
arch: "powerpc".to_string(),
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
+ target_vendor: "unknown".to_string(),
options: base,
}
}
arch: "x86_64".to_string(),
target_os: "macos".to_string(),
target_env: "".to_string(),
+ target_vendor: "apple".to_string(),
options: base,
}
}
arch: "x86_64".to_string(),
target_os: "ios".to_string(),
target_env: "".to_string(),
+ target_vendor: "apple".to_string(),
options: opts(Arch::X86_64)
}
}
arch: "x86_64".to_string(),
target_os: "windows".to_string(),
target_env: "gnu".to_string(),
+ target_vendor: "pc".to_string(),
options: base,
}
}
arch: "x86_64".to_string(),
target_os: "windows".to_string(),
target_env: "msvc".to_string(),
+ target_vendor: "pc".to_string(),
options: base,
}
}
--- /dev/null
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use target::Target;
+
+pub fn target() -> Target {
+ let mut base = super::netbsd_base::opts();
+ base.pre_link_args.push("-m64".to_string());
+ base.linker = "x86_64-rumprun-netbsd-gcc".to_string();
+ base.ar = "x86_64-rumprun-netbsd-ar".to_string();
+
+ base.dynamic_linking = false;
+ base.has_rpath = false;
+ base.position_independent_executables = false;
+ base.disable_redzone = true;
+ base.no_default_libraries = false;
+
+ Target {
+ llvm_target: "x86_64-rumprun-netbsd".to_string(),
+ target_endian: "little".to_string(),
+ target_pointer_width: "64".to_string(),
+ arch: "x86_64".to_string(),
+ target_os: "netbsd".to_string(),
+ target_env: "".to_string(),
+ target_vendor: "rumprun".to_string(),
+ options: base,
+ }
+}
arch: "x86_64".to_string(),
target_os: "bitrig".to_string(),
target_env: "".to_string(),
+ target_vendor: "unknown".to_string(),
options: base,
}
}
arch: "x86_64".to_string(),
target_os: "dragonfly".to_string(),
target_env: "".to_string(),
+ target_vendor: "unknown".to_string(),
options: base,
}
}
arch: "x86_64".to_string(),
target_os: "freebsd".to_string(),
target_env: "".to_string(),
+ target_vendor: "unknown".to_string(),
options: base,
}
}
arch: "x86_64".to_string(),
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
+ target_vendor: "unknown".to_string(),
options: base,
}
}
arch: "x86_64".to_string(),
target_os: "linux".to_string(),
target_env: "musl".to_string(),
+ target_vendor: "unknown".to_string(),
options: base,
}
}
arch: "x86_64".to_string(),
target_os: "netbsd".to_string(),
target_env: "".to_string(),
+ target_vendor: "unknown".to_string(),
options: base,
}
}
arch: "x86_64".to_string(),
target_os: "openbsd".to_string(),
target_env: "".to_string(),
+ target_vendor: "unknown".to_string(),
options: base,
}
}
let pat_span_path_opt = match move_pat.node {
hir::PatIdent(_, ref path1, _) => {
Some(MoveSpanAndPath{span: move_pat.span,
- ident: path1.node})
+ name: path1.node.name})
},
_ => None,
};
use std::cell::RefCell;
use syntax::ast;
use syntax::codemap;
-use rustc_front::print::pprust;
use rustc_front::hir;
pub struct MoveErrorCollector<'tcx> {
#[derive(Clone)]
pub struct MoveSpanAndPath {
pub span: codemap::Span,
- pub ident: ast::Ident
+ pub name: ast::Name,
}
pub struct GroupedMoveErrors<'tcx> {
let mut is_first_note = true;
for move_to in &error.move_to_places {
note_move_destination(bccx, move_to.span,
- &move_to.ident, is_first_note);
+ move_to.name, is_first_note);
is_first_note = false;
}
}
fn note_move_destination(bccx: &BorrowckCtxt,
move_to_span: codemap::Span,
- pat_ident: &ast::Ident,
+ pat_name: ast::Name,
is_first_note: bool) {
- let pat_name = pprust::ident_to_string(pat_ident);
if is_first_note {
bccx.span_note(
move_to_span,
s: &mut pprust_hir::State,
node: pprust_hir::AnnNode) -> io::Result<()> {
match node {
- pprust_hir::NodeIdent(_) | pprust_hir::NodeName(_) => Ok(()),
-
+ pprust_hir::NodeName(_) => Ok(()),
pprust_hir::NodeItem(item) => {
try!(pp::space(&mut s.s));
s.synth_comment(item.id.to_string())
try!(pp::space(&mut s.s));
// FIXME #16420: this doesn't display the connections
// between syntax contexts
- s.synth_comment(format!("{}#{}", nm, ctxt))
+ s.synth_comment(format!("{}#{}", nm, ctxt.0))
}
pprust::NodeName(&ast::Name(nm)) => {
try!(pp::space(&mut s.s));
pub fn noop_fold_view_path<T: Folder>(view_path: P<ViewPath>, fld: &mut T) -> P<ViewPath> {
view_path.map(|Spanned {node, span}| Spanned {
node: match node {
- ViewPathSimple(ident, path) => {
- ViewPathSimple(ident, fld.fold_path(path))
+ ViewPathSimple(name, path) => {
+ ViewPathSimple(name, fld.fold_path(path))
}
ViewPathGlob(path) => {
ViewPathGlob(fld.fold_path(path))
-> ExplicitSelf_ {
match es {
SelfStatic | SelfValue(_) => es,
- SelfRegion(lifetime, m, ident) => {
- SelfRegion(fld.fold_opt_lifetime(lifetime), m, ident)
+ SelfRegion(lifetime, m, name) => {
+ SelfRegion(fld.fold_opt_lifetime(lifetime), m, name)
}
- SelfExplicit(typ, ident) => {
- SelfExplicit(fld.fold_ty(typ), ident)
+ SelfExplicit(typ, name) => {
+ SelfExplicit(fld.fold_ty(typ), name)
}
}
}
respan(folder.new_span(name.span),
folder.fold_name(name.node)))
}
- ExprTupField(el, ident) => {
+ ExprTupField(el, index) => {
ExprTupField(folder.fold_expr(el),
- respan(folder.new_span(ident.span),
- folder.fold_usize(ident.node)))
+ respan(folder.new_span(index.span),
+ folder.fold_usize(index.node)))
}
ExprIndex(el, er) => {
ExprIndex(folder.fold_expr(el), folder.fold_expr(er))
///
/// `if expr { block } else { expr }`
ExprIf(P<Expr>, P<Block>, Option<P<Expr>>),
- // FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
/// A while loop, with an optional label
///
/// `'label: while expr { block }`
/// Conditionless loop (can be exited with break, continue, or return)
///
/// `'label: loop { block }`
- // FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
ExprLoop(P<Block>, Option<Ident>),
/// A `match` block, with a source that indicates whether or not it is
/// the result of a desugaring, and if so, which kind.
use std::io::{self, Write, Read};
pub enum AnnNode<'a> {
- NodeIdent(&'a ast::Ident),
NodeName(&'a ast::Name),
NodeBlock(&'a hir::Block),
NodeItem(&'a hir::Item),
to_string(|s| s.print_path(p, false, 0))
}
-pub fn ident_to_string(id: &ast::Ident) -> String {
- to_string(|s| s.print_ident(*id))
+pub fn name_to_string(name: ast::Name) -> String {
+ to_string(|s| s.print_name(name))
}
pub fn fun_to_string(decl: &hir::FnDecl,
}
hir::ExprWhile(ref test, ref blk, opt_ident) => {
if let Some(ident) = opt_ident {
- try!(self.print_ident(ident));
+ try!(self.print_name(ident.name));
try!(self.word_space(":"));
}
try!(self.head("while"));
}
hir::ExprLoop(ref blk, opt_ident) => {
if let Some(ident) = opt_ident {
- try!(self.print_ident(ident));
+ try!(self.print_name(ident.name));
try!(self.word_space(":"));
}
try!(self.head("loop"));
try!(word(&mut self.s, "break"));
try!(space(&mut self.s));
if let Some(ident) = opt_ident {
- try!(self.print_ident(ident.node));
+ try!(self.print_name(ident.node.name));
try!(space(&mut self.s));
}
}
try!(word(&mut self.s, "continue"));
try!(space(&mut self.s));
if let Some(ident) = opt_ident {
- try!(self.print_ident(ident.node));
+ try!(self.print_name(ident.node.name));
try!(space(&mut self.s))
}
}
}
}
- pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> {
- try!(word(&mut self.s, &ident.name.as_str()));
- self.ann.post(self, NodeIdent(&ident))
- }
-
pub fn print_usize(&mut self, i: usize) -> io::Result<()> {
word(&mut self.s, &i.to_string())
}
try!(word(&mut self.s, "::"))
}
- try!(self.print_ident(segment.identifier));
+ try!(self.print_name(segment.identifier.name));
try!(self.print_path_parameters(&segment.parameters, colons_before_params));
}
try!(word(&mut self.s, ">"));
try!(word(&mut self.s, "::"));
let item_segment = path.segments.last().unwrap();
- try!(self.print_ident(item_segment.identifier));
+ try!(self.print_name(item_segment.identifier.name));
self.print_path_parameters(&item_segment.parameters, colons_before_params)
}
try!(self.word_nbsp("mut"));
}
}
- try!(self.print_ident(path1.node));
+ try!(self.print_name(path1.node.name));
match *sub {
Some(ref p) => {
try!(word(&mut self.s, "@"));
hir::ViewPathSimple(name, ref path) => {
try!(self.print_path(path, false, 0));
- // FIXME(#6993) can't compare identifiers directly here
if path.segments.last().unwrap().identifier.name != name {
try!(space(&mut self.s));
try!(self.word_space("as"));
word(&mut self.s, "::*")
}
- hir::ViewPathList(ref path, ref idents) => {
+ hir::ViewPathList(ref path, ref segments) => {
if path.segments.is_empty() {
try!(word(&mut self.s, "{"));
} else {
try!(self.print_path(path, false, 0));
try!(word(&mut self.s, "::{"));
}
- try!(self.commasep(Inconsistent, &idents[..], |s, w| {
+ try!(self.commasep(Inconsistent, &segments[..], |s, w| {
match w.node {
hir::PathListIdent { name, .. } => {
s.print_name(name)
abi: abi::Abi,
unsafety: hir::Unsafety,
decl: &hir::FnDecl,
- name: Option<ast::Ident>,
+ name: Option<ast::Name>,
generics: &hir::Generics,
opt_explicit_self: Option<&hir::ExplicitSelf_>)
-> io::Result<()> {
unsafety,
hir::Constness::NotConst,
abi,
- name.map(|x| x.name),
+ name,
&generics,
opt_explicit_self,
hir::Inherited));
// convert a span and an identifier to the corresponding
// 1-segment path
-pub fn ident_to_path(s: Span, identifier: Ident) -> Path {
+pub fn ident_to_path(s: Span, ident: Ident) -> Path {
hir::Path {
span: s,
global: false,
segments: vec!(
hir::PathSegment {
- identifier: identifier,
+ identifier: ident,
parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData {
lifetimes: Vec::new(),
types: OwnedSlice::empty(),
impl LateLintPass for UnconditionalRecursion {
fn check_fn(&mut self, cx: &LateContext, fn_kind: FnKind, _: &hir::FnDecl,
blk: &hir::Block, sp: Span, id: ast::NodeId) {
- type F = for<'tcx> fn(&ty::ctxt<'tcx>,
- ast::NodeId, ast::NodeId, ast::Ident, ast::NodeId) -> bool;
-
let method = match fn_kind {
FnKind::ItemFn(..) => None,
FnKind::Method(..) => {
let mut mutables = FnvHashMap();
for p in pats {
pat_util::pat_bindings(&cx.tcx.def_map, p, |mode, id, _, path1| {
- let ident = path1.node;
+ let name = path1.node;
if let hir::BindByValue(hir::MutMutable) = mode {
- if !ident.name.as_str().starts_with("_") {
- match mutables.entry(ident.name.usize()) {
+ if !name.as_str().starts_with("_") {
+ match mutables.entry(name.0 as usize) {
Vacant(entry) => { entry.insert(vec![id]); },
Occupied(mut entry) => { entry.get_mut().push(id); },
}
struct Binding<H:Hair> {
span: H::Span,
source: Lvalue<H>,
- name: H::Ident,
+ name: H::Name,
var_id: H::VarId,
var_ty: H::Ty,
mutability: Mutability,
fn declare_binding(&mut self,
var_extent: H::CodeExtent,
mutability: Mutability,
- name: H::Ident,
+ name: H::Name,
var_id: H::VarId,
var_ty: H::Ty,
span: H::Span)
type DefId: Copy+Debug+Eq+Hash; // e.g., DefId
type AdtDef: Copy+Debug+Eq+Hash; // e.g., AdtDef<'tcx>
type Name: Copy+Debug+Eq+Hash; // e.g., ast::Name
- type Ident: Copy+Debug+Eq+Hash; // e.g., ast::Ident
type InternedString: Clone+Debug+Eq+Hash; // e.g., InternedString
type Bytes: Clone+Debug+Eq+Hash; // e.g., Rc<Vec<u8>>
type Span: Copy+Debug+Eq; // e.g., syntax::codemap::Span
// x, ref x, x @ P, etc
Binding { mutability: Mutability,
- name: H::Ident,
+ name: H::Name,
mode: BindingMode<H>,
var: H::VarId,
ty: H::Ty,
// decl, a let, etc.
pub struct VarDecl<H:Hair> {
pub mutability: Mutability,
- pub name: H::Ident,
+ pub name: H::Name,
pub ty: H::Ty,
}
hir::ExprField(ref source, name) =>
ExprKind::Field { lhs: source.to_ref(),
name: Field::Named(name.node) },
- hir::ExprTupField(ref source, ident) =>
+ hir::ExprTupField(ref source, index) =>
ExprKind::Field { lhs: source.to_ref(),
- name: Field::Indexed(ident.node) },
+ name: Field::Indexed(index.node) },
hir::ExprCast(ref source, _) =>
ExprKind::Cast { source: source.to_ref() },
hir::ExprBox(ref value) =>
type DefId = DefId;
type AdtDef = ty::AdtDef<'tcx>;
type Name = ast::Name;
- type Ident = ast::Ident;
type InternedString = InternedString;
type Bytes = Rc<Vec<u8>>;
type Span = Span;
#[derive(Clone, Debug)]
pub struct PatNode<'tcx> {
pat: &'tcx hir::Pat,
- binding_map: Option<Rc<FnvHashMap<ast::Ident, ast::NodeId>>>
+ binding_map: Option<Rc<FnvHashMap<ast::Name, ast::NodeId>>>
}
impl<'tcx> PatNode<'tcx> {
pub fn new(pat: &'tcx hir::Pat,
- binding_map: Option<Rc<FnvHashMap<ast::Ident, ast::NodeId>>>)
+ binding_map: Option<Rc<FnvHashMap<ast::Name, ast::NodeId>>>)
-> PatNode<'tcx> {
PatNode {
pat: pat,
{
let id = match self.binding_map {
None => self.pat.id,
- Some(ref map) => map[&ident.node],
+ Some(ref map) => map[&ident.node.name],
};
let var_ty = cx.tcx.node_id_to_type(self.pat.id);
let region = match var_ty.sty {
PatternKind::Binding {
mutability: mutability,
mode: mode,
- name: ident.node,
+ name: ident.node.name,
var: id,
ty: var_ty,
subpattern: self.opt_pat_ref(sub),
enum FieldName {
UnnamedField(usize), // index
- // (Name, not Ident, because struct fields are not macro-hygienic)
NamedField(ast::Name),
}
ViewPathSimple(_, ref full_path) => {
full_path.segments
.split_last().unwrap().1
- .iter().map(|ident| ident.identifier.name)
+ .iter().map(|seg| seg.identifier.name)
.collect()
}
ViewPathGlob(ref module_ident_path) |
ViewPathList(ref module_ident_path, _) => {
module_ident_path.segments
- .iter().map(|ident| ident.identifier.name).collect()
+ .iter().map(|seg| seg.identifier.name).collect()
}
};
use rustc::metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
use rustc::middle::def::*;
use rustc::middle::def_id::DefId;
-use rustc::middle::pat_util::pat_bindings;
+use rustc::middle::pat_util::pat_bindings_hygienic;
use rustc::middle::privacy::*;
use rustc::middle::subst::{ParamSpace, FnSpace, TypeSpace};
use rustc::middle::ty::{Freevar, FreevarMap, TraitMap, GlobMap};
// user and one 'x' came from the macro.
fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
let mut result = HashMap::new();
- pat_bindings(&self.def_map, pat, |binding_mode, _id, sp, path1| {
+ pat_bindings_hygienic(&self.def_map, pat, |binding_mode, _id, sp, path1| {
let name = mtwt::resolve(path1.node);
result.insert(name, BindingInfo {
span: sp,
false // Stop advancing
});
- if method_scope && special_names::self_ == path_name {
+ if method_scope && special_names::self_.as_str() == &path_name[..] {
resolve_error(
self,
expr.span,
fn get_binding(this: &mut Resolver,
import_resolution: &ImportResolution,
namespace: Namespace,
- source: &Name)
+ source: Name)
-> NamespaceResult {
// Import resolutions must be declared with "pub"
let id = import_resolution.id(namespace);
// track used imports and extern crates as well
this.used_imports.insert((id, namespace));
- this.record_import_use(id, *source);
+ this.record_import_use(id, source);
match target_module.def_id.get() {
Some(DefId{krate: kid, ..}) => {
this.used_crates.insert(kid);
value_result = get_binding(self.resolver,
import_resolution,
ValueNS,
- &source);
+ source);
value_used_reexport = import_resolution.is_public;
}
if type_result.is_unknown() {
type_result = get_binding(self.resolver,
import_resolution,
TypeNS,
- &source);
+ source);
type_used_reexport = import_resolution.is_public;
}
)));
}
- for (ident, target_import_resolution) in import_resolutions.iter() {
+ for (name, target_import_resolution) in import_resolutions.iter() {
debug!("(resolving glob import) writing module resolution \
{} into `{}`",
- *ident,
+ *name,
module_to_string(module_));
if !target_import_resolution.is_public {
// Here we merge two import resolutions.
let mut import_resolutions = module_.import_resolutions.borrow_mut();
- match import_resolutions.get_mut(ident) {
+ match import_resolutions.get_mut(name) {
Some(dest_import_resolution) => {
// Merge the two import resolutions at a finer-grained
// level.
Some(ref value_target) => {
self.check_for_conflicting_import(&dest_import_resolution,
import_directive.span,
- *ident,
+ *name,
ValueNS);
dest_import_resolution.value_target = Some(value_target.clone());
}
Some(ref type_target) => {
self.check_for_conflicting_import(&dest_import_resolution,
import_directive.span,
- *ident,
+ *name,
TypeNS);
dest_import_resolution.type_target = Some(type_target.clone());
}
new_import_resolution.type_target =
target_import_resolution.type_target.clone();
- import_resolutions.insert(*ident, new_import_resolution);
+ import_resolutions.insert(*name, new_import_resolution);
}
// Add all children from the containing module.
use metadata::csearch;
use middle::dependency_format::Linkage;
use session::Session;
-use session::config::DebugInfoLevel::{NoDebugInfo, LimitedDebugInfo, FullDebugInfo};
use session::config::CrateTypeDylib;
use session::config;
use syntax::ast;
}
fn debuginfo(&mut self) {
- match self.sess.opts.debuginfo {
- NoDebugInfo => {
- // Do nothing if debuginfo is disabled
- },
- LimitedDebugInfo |
- FullDebugInfo => {
- // This will cause the Microsoft linker to generate a PDB file
- // from the CodeView line tables in the object files.
- self.cmd.arg("/DEBUG");
- }
- }
+ // This will cause the Microsoft linker to generate a PDB file
+ // from the CodeView line tables in the object files.
+ self.cmd.arg("/DEBUG");
}
fn whole_archives(&mut self) {
fn process_const(&mut self,
id: ast::NodeId,
- ident: &ast::Ident,
+ name: ast::Name,
span: Span,
typ: &ast::Ty,
expr: &ast::Expr) {
self.fmt.static_str(span,
sub_span,
id,
- &ident.name.as_str(),
+ &name.as_str(),
&qualname,
&self.span.snippet(expr.span),
&ty_to_string(&*typ),
fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) {
match trait_item.node {
ast::ConstTraitItem(ref ty, Some(ref expr)) => {
- self.process_const(trait_item.id, &trait_item.ident,
+ self.process_const(trait_item.id, trait_item.ident.name,
trait_item.span, &*ty, &*expr);
}
ast::MethodTraitItem(ref sig, ref body) => {
fn visit_impl_item(&mut self, impl_item: &ast::ImplItem) {
match impl_item.node {
ast::ConstImplItem(ref ty, ref expr) => {
- self.process_const(impl_item.id, &impl_item.ident,
+ self.process_const(impl_item.id, impl_item.ident.name,
impl_item.span, &ty, &expr);
}
ast::MethodImplItem(ref sig, ref body) => {
pub ty: Ty<'tcx>,
}
-type BindingsMap<'tcx> = FnvHashMap<ast::Ident, BindingInfo<'tcx>>;
+type BindingsMap<'tcx> = FnvHashMap<ast::Name, BindingInfo<'tcx>>;
struct ArmData<'p, 'blk, 'tcx: 'blk> {
bodycx: Block<'blk, 'tcx>,
struct Match<'a, 'p: 'a, 'blk: 'a, 'tcx: 'blk> {
pats: Vec<&'p hir::Pat>,
data: &'a ArmData<'p, 'blk, 'tcx>,
- bound_ptrs: Vec<(ast::Ident, ValueRef)>,
+ bound_ptrs: Vec<(ast::Name, ValueRef)>,
// Thread along renamings done by the check_match::StaticInliner, so we can
// map back to original NodeIds
pat_renaming_map: Option<&'a FnvHashMap<(NodeId, Span), NodeId>>
loop {
pat = match pat.node {
hir::PatIdent(_, ref path, Some(ref inner)) => {
- bound_ptrs.push((path.node, val.val));
+ bound_ptrs.push((path.node.name, val.val));
&**inner
},
_ => break
match this.node {
hir::PatIdent(_, ref path, None) => {
if pat_is_binding(dm, &*this) {
- bound_ptrs.push((path.node, val.val));
+ bound_ptrs.push((path.node.name, val.val));
}
}
hir::PatVec(ref before, Some(ref slice), ref after) => {
let subslice_val = bind_subslice_pat(
bcx, this.id, val,
before.len(), after.len());
- bound_ptrs.push((path.node, subslice_val));
+ bound_ptrs.push((path.node.name, subslice_val));
}
}
_ => {}
bindings_map: &BindingsMap<'tcx>,
cs: Option<cleanup::ScopeId>)
-> Block<'blk, 'tcx> {
- for (&ident, &binding_info) in bindings_map {
+ for (&name, &binding_info) in bindings_map {
let (llval, aliases_other_state) = match binding_info.trmode {
// By value mut binding for a copy type: load from the ptr
// into the matched value and copy to our alloca
debug!("binding {} to {}", binding_info.id, bcx.val_to_string(llval));
bcx.fcx.lllocals.borrow_mut().insert(binding_info.id, datum);
- debuginfo::create_match_binding_metadata(bcx, ident.name, binding_info);
+ debuginfo::create_match_binding_metadata(bcx, name, binding_info);
}
bcx
}
let reassigned = is_discr_reassigned(bcx, discr, body);
let mut bindings_map = FnvHashMap();
pat_bindings(&tcx.def_map, &*pat, |bm, p_id, span, path1| {
- let ident = path1.node;
- let name = ident.name;
+ let name = path1.node;
let variable_ty = node_id_type(bcx, p_id);
let llvariable_ty = type_of::type_of(ccx, variable_ty);
let tcx = bcx.tcx();
trmode = TrByRef;
}
};
- bindings_map.insert(ident, BindingInfo {
+ bindings_map.insert(name, BindingInfo {
llmatch: llmatch,
trmode: trmode,
id: p_id,
pat_bindings(&tcx.def_map, pat, |_, p_id, _, path1| {
let scope = cleanup::var_scope(tcx, p_id);
bcx = mk_binding_alloca(
- bcx, p_id, path1.node.name, scope, (),
+ bcx, p_id, path1.node, scope, (),
"_match::store_local::create_dummy_locals",
|(), bcx, Datum { val: llval, ty, kind }| {
// Dummy-locals start out uninitialized, so set their
//
// In such cases, the more general path is unsafe, because
// it assumes it is matching against a valid value.
- match simple_identifier(&*pat) {
- Some(ident) => {
+ match simple_name(pat) {
+ Some(name) => {
let var_scope = cleanup::var_scope(tcx, local.id);
return mk_binding_alloca(
- bcx, pat.id, ident.name, var_scope, (),
+ bcx, pat.id, name, var_scope, (),
"_match::store_local",
|(), bcx, Datum { val: v, .. }| expr::trans_into(bcx, &**init_expr,
expr::SaveIn(v)));
use middle::def_id::{DefId, LOCAL_CRATE};
use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
use middle::weak_lang_items;
-use middle::pat_util::simple_identifier;
+use middle::pat_util::simple_name;
use middle::subst::Substs;
use middle::ty::{self, Ty, HasTypeFlags};
use rustc::front::map as hir_map;
};
let pat = &*args[i].pat;
- bcx = if let Some(ident) = simple_identifier(&*pat) {
+ bcx = if let Some(name) = simple_name(pat) {
// Generate nicer LLVM for the common case of fn a pattern
// like `x: T`
- set_value_name(arg_datum.val, &bcx.name(ident.name));
+ set_value_name(arg_datum.val, &bcx.name(name));
bcx.fcx.lllocals.borrow_mut().insert(pat.id, arg_datum);
bcx
} else {
unsafe {
let mut declared = HashSet::new();
- let iter_globals = |llmod| {
- ValueIter {
- cur: llvm::LLVMGetFirstGlobal(llmod),
- step: llvm::LLVMGetNextGlobal,
- }
- };
-
- let iter_functions = |llmod| {
- ValueIter {
- cur: llvm::LLVMGetFirstFunction(llmod),
- step: llvm::LLVMGetNextFunction,
- }
- };
-
// Collect all external declarations in all compilation units.
for ccx in cx.iter() {
for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) {
}
}
}
+}
+
+// Create a `__imp_<symbol> = &symbol` global for every public static `symbol`.
+// This is required to satisfy `dllimport` references to static data in .rlibs
+// when using MSVC linker. We do this only for data, as linker can fix up
+// code references on its own.
+// See #26591, #27438
+fn create_imps(cx: &SharedCrateContext) {
+ unsafe {
+ for ccx in cx.iter() {
+ let exported: Vec<_> = iter_globals(ccx.llmod())
+ .filter(|&val| llvm::LLVMGetLinkage(val) == llvm::ExternalLinkage as c_uint &&
+ llvm::LLVMIsDeclaration(val) == 0)
+ .collect();
+
+ let i8p_ty = Type::i8p(&ccx);
+ for val in exported {
+ let name = CStr::from_ptr(llvm::LLVMGetValueName(val));
+ let imp_name = String::from("__imp_") +
+ str::from_utf8(name.to_bytes()).unwrap();
+ let imp_name = CString::new(imp_name).unwrap();
+ let imp = llvm::LLVMAddGlobal(ccx.llmod(), i8p_ty.to_ref(),
+ imp_name.as_ptr() as *const _);
+ llvm::LLVMSetInitializer(imp, llvm::LLVMConstBitCast(val, i8p_ty.to_ref()));
+ llvm::SetLinkage(imp, llvm::ExternalLinkage);
+ }
+ }
+ }
+}
+
+struct ValueIter {
+ cur: ValueRef,
+ step: unsafe extern "C" fn(ValueRef) -> ValueRef,
+}
+impl Iterator for ValueIter {
+ type Item = ValueRef;
- struct ValueIter {
- cur: ValueRef,
- step: unsafe extern "C" fn(ValueRef) -> ValueRef,
+ fn next(&mut self) -> Option<ValueRef> {
+ let old = self.cur;
+ if !old.is_null() {
+ self.cur = unsafe {
+ let step: unsafe extern "C" fn(ValueRef) -> ValueRef =
+ mem::transmute_copy(&self.step);
+ step(old)
+ };
+ Some(old)
+ } else {
+ None
+ }
}
+}
- impl Iterator for ValueIter {
- type Item = ValueRef;
+fn iter_globals(llmod: llvm::ModuleRef) -> ValueIter {
+ unsafe {
+ ValueIter {
+ cur: llvm::LLVMGetFirstGlobal(llmod),
+ step: llvm::LLVMGetNextGlobal,
+ }
+ }
+}
- fn next(&mut self) -> Option<ValueRef> {
- let old = self.cur;
- if !old.is_null() {
- self.cur = unsafe {
- let step: unsafe extern "C" fn(ValueRef) -> ValueRef =
- mem::transmute_copy(&self.step);
- step(old)
- };
- Some(old)
- } else {
- None
- }
+fn iter_functions(llmod: llvm::ModuleRef) -> ValueIter {
+ unsafe {
+ ValueIter {
+ cur: llvm::LLVMGetFirstFunction(llmod),
+ step: llvm::LLVMGetNextFunction,
}
}
}
&reachable_symbols.iter().map(|x| &x[..]).collect());
}
+ if sess.target.target.options.is_like_msvc &&
+ sess.crate_types.borrow().iter().any(|ct| *ct == config::CrateTypeRlib) {
+ create_imps(&shared_ccx);
+ }
+
let metadata_module = ModuleTranslation {
llcx: shared_ccx.metadata_llcx(),
llmod: shared_ccx.metadata_llmod(),
/// Generates a unique symbol based off the name given. This is used to create
/// unique symbols for things like closures.
pub fn gensym_name(name: &str) -> PathElem {
- let num = token::gensym(name).usize();
+ let num = token::gensym(name).0;
// use one colon which will get translated to a period by the mangler, and
// we're guaranteed that `num` is globally unique for this crate.
PathName(token::gensym(&format!("{}:{}", name, num)))
!null_terminated as Bool);
let gsym = token::gensym("str");
- let sym = format!("str{}", gsym.usize());
+ let sym = format!("str{}", gsym.0);
let g = declare::define_global(cx, &sym[..], val_ty(sc)).unwrap_or_else(||{
cx.sess().bug(&format!("symbol `{}` is already defined", sym));
});
// FIXME: this totally needs a better name generation scheme, perhaps a simple global
// counter? Also most other uses of gensym in trans.
let gsym = token::gensym("_");
- let name = format!("{}{}", kind, gsym.usize());
+ let name = format!("{}{}", kind, gsym.0);
let gv = declare::define_global(ccx, &name[..], val_ty(cv)).unwrap_or_else(||{
ccx.sess().bug(&format!("symbol `{}` is already defined", name));
});
pub fn trans_break_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
expr: &hir::Expr,
- opt_label: Option<ast::Ident>,
+ opt_label: Option<ast::Name>,
exit: usize)
-> Block<'blk, 'tcx> {
let _icx = push_ctxt("trans_break_cont");
pub fn trans_break<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
expr: &hir::Expr,
- label_opt: Option<ast::Ident>)
+ label_opt: Option<ast::Name>)
-> Block<'blk, 'tcx> {
return trans_break_cont(bcx, expr, label_opt, cleanup::EXIT_BREAK);
}
pub fn trans_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
expr: &hir::Expr,
- label_opt: Option<ast::Ident>)
+ label_opt: Option<ast::Name>)
-> Block<'blk, 'tcx> {
return trans_break_cont(bcx, expr, label_opt, cleanup::EXIT_LOOP);
}
for arg in args {
pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, _, path1| {
scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata,
- name: Some(path1.node.name) });
+ name: Some(path1.node) });
scope_map.insert(node_id, fn_metadata);
})
}
let def_map = &cx.tcx().def_map;
let locals = bcx.fcx.lllocals.borrow();
- pat_util::pat_bindings(def_map, &*local.pat, |_, node_id, span, var_ident| {
+ pat_util::pat_bindings(def_map, &*local.pat, |_, node_id, span, var_name| {
let datum = match locals.get(&node_id) {
Some(datum) => datum,
None => {
let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
declare_local(bcx,
- var_ident.node.name,
+ var_name.node,
datum.ty,
scope_metadata,
VariableAccess::DirectVariable { alloca: datum.val },
.fn_metadata;
let locals = bcx.fcx.lllocals.borrow();
- pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, span, var_ident| {
+ pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, span, var_name| {
let datum = match locals.get(&node_id) {
Some(v) => v,
None => {
};
declare_local(bcx,
- var_ident.node.name,
+ var_name.node,
datum.ty,
scope_metadata,
VariableAccess::DirectVariable { alloca: datum.val },
match expr.node {
hir::ExprBreak(label_opt) => {
- controlflow::trans_break(bcx, expr, label_opt.map(|l| l.node))
+ controlflow::trans_break(bcx, expr, label_opt.map(|l| l.node.name))
}
hir::ExprAgain(label_opt) => {
- controlflow::trans_cont(bcx, expr, label_opt.map(|l| l.node))
+ controlflow::trans_cont(bcx, expr, label_opt.map(|l| l.node.name))
}
hir::ExprRet(ref ex) => {
// Check to see if the return expression itself is reachable.
// trans. Shudder.
fn make_field(field_name: &str, expr: P<hir::Expr>) -> hir::Field {
hir::Field {
- name: codemap::dummy_spanned(token::str_to_ident(field_name).name),
+ name: codemap::dummy_spanned(token::intern(field_name)),
expr: expr,
span: codemap::DUMMY_SP,
}
let tcx = this.tcx();
debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}, \
- types_provided={:?}, region_substs={:?}",
+ types_provided={:?}, region_substs={:?})",
decl_generics, self_ty, types_provided,
region_substs);
}
}
+ debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}",
+ decl_generics, self_ty, substs);
+
substs
}
poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
-> ty::PolyTraitRef<'tcx>
{
+ debug!("ast_path_to_poly_trait_ref(trait_segment={:?})", trait_segment);
// The trait reference introduces a binding level here, so
// we need to shift the `rscope`. It'd be nice if we could
// do away with this rscope stuff and work this knowledge
poly_projections.extend(converted_bindings);
}
+ debug!("ast_path_to_poly_trait_ref(trait_segment={:?}, projections={:?}) -> {:?}",
+ trait_segment, poly_projections, poly_trait_ref);
poly_trait_ref
}
object.principal_trait_ref_with_self_ty(tcx, tcx.types.err);
// ensure the super predicates and stop if we encountered an error
- if this.ensure_super_predicates(span, object.principal_def_id()).is_err() {
+ if this.ensure_super_predicates(span, principal.def_id()).is_err() {
+ return tcx.types.err;
+ }
+
+ // check that there are no gross object safety violations,
+ // most importantly, that the supertraits don't contain Self,
+ // to avoid ICE-s.
+ let object_safety_violations =
+ traits::astconv_object_safety_violations(tcx, principal.def_id());
+ if !object_safety_violations.is_empty() {
+ traits::report_object_safety_error(
+ tcx, span, principal.def_id(), object_safety_violations, false);
return tcx.types.err;
}
// if there are multiple arms, make sure they all agree on
// what the type of the binding `x` ought to be
- let canon_id = *pcx.map.get(&path.node).unwrap();
+ let canon_id = *pcx.map.get(&path.node.name).unwrap();
if canon_id != pat.id {
let ct = fcx.local_ty(pat.span, canon_id);
demand::eqtype(fcx, pat.span, ct, typ);
}
pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
- debug!("check_item_type(it.id={}, it.ident={})",
+ debug!("check_item_type(it.id={}, it.name={})",
it.id,
ccx.tcx.item_path_str(DefId::local(it.id)));
let _indenter = indenter();
}
pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
- debug!("check_item_body(it.id={}, it.ident={})",
+ debug!("check_item_body(it.id={}, it.name={})",
it.id,
ccx.tcx.item_path_str(DefId::local(it.id)));
let _indenter = indenter();
Position::ArgumentNamed(s) if s == "Self" => (),
// So is `{A}` if A is a type parameter
Position::ArgumentNamed(s) => match types.iter().find(|t| {
- t.name == s
+ t.name.as_str() == s
}) {
Some(_) => (),
None => {
/// the types first.
fn check_item_well_formed(&mut self, item: &hir::Item) {
let ccx = self.ccx;
- debug!("check_item_well_formed(it.id={}, it.ident={})",
+ debug!("check_item_well_formed(it.id={}, it.name={})",
item.id,
ccx.tcx.item_path_str(DefId::local(item.id)));
/// the types first.
fn check_item_well_formed(&mut self, item: &hir::Item) {
let ccx = self.ccx;
- debug!("check_item_well_formed(it.id={}, it.ident={})",
+ debug!("check_item_well_formed(it.id={}, it.name={})",
item.id,
ccx.tcx.item_path_str(DefId::local(item.id)));
rcvr_ty_generics,
rcvr_ty_predicates);
- for (sig, id, ident, vis, _span) in methods {
+ for (sig, id, name, vis, _span) in methods {
convert_method(ccx,
container,
sig,
id,
- ident,
+ name,
vis,
untransformed_rcvr_ty,
rcvr_ty_generics,
E0399, // trait items need to be implemented because the associated
// type `{}` was overridden
E0436, // functional record update requires a struct
- E0513, // no type for local variable ..
+ E0513 // no type for local variable ..
}
let mut trait_path = p.clone();
trait_path.segments.pop();
Type::QPath {
- name: p.segments.last().unwrap().identifier.clean(cx),
+ name: p.segments.last().unwrap().identifier.name.clean(cx),
self_type: box qself.ty.clean(cx),
trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
}
impl Clean<PathSegment> for hir::PathSegment {
fn clean(&self, cx: &DocContext) -> PathSegment {
PathSegment {
- name: self.identifier.clean(cx),
+ name: self.identifier.name.clean(cx),
params: self.parameters.clean(cx)
}
}
s
}
-impl Clean<String> for ast::Ident {
- fn clean(&self, _: &DocContext) -> String {
- self.to_string()
- }
-}
-
impl Clean<String> for ast::Name {
fn clean(&self, _: &DocContext) -> String {
self.to_string()
/*globals $: true, rootPath: true */
document.addEventListener('DOMContentLoaded', function() {
+ 'use strict';
+
if (!window.playgroundUrl) {
return;
}
#![feature(associated_consts)]
#![feature(borrow_state)]
#![feature(box_syntax)]
+#![feature(cfg_target_vendor)]
#![feature(char_from_unchecked)]
#![feature(char_internals)]
#![feature(clone_from_slice)]
($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*)));
}
-/// Macro for printing to the standard output.
+/// Macro for printing to the standard output, with a newline.
///
/// Use the `format!` syntax to write data to the standard output.
/// See `std::fmt` for more information.
use io::prelude::*;
use any::Any;
+use cell::Cell;
use cell::RefCell;
+use intrinsics;
use sys::stdio::Stderr;
use sys_common::backtrace;
use sys_common::thread_info;
-use sys_common::unwind;
+use sys_common::util;
+
+thread_local! { pub static PANIC_COUNT: Cell<usize> = Cell::new(0) }
thread_local! {
pub static LOCAL_STDERR: RefCell<Option<Box<Write + Send>>> = {
}
}
-pub fn on_panic(obj: &(Any+Send), file: &'static str, line: u32) {
+fn log_panic(obj: &(Any+Send), file: &'static str, line: u32,
+ log_backtrace: bool) {
let msg = match obj.downcast_ref::<&'static str>() {
Some(s) => *s,
None => match obj.downcast_ref::<String>() {
let mut err = Stderr::new().ok();
let thread = thread_info::current_thread();
let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
+
+ let write = |err: &mut ::io::Write| {
+ let _ = writeln!(err, "thread '{}' panicked at '{}', {}:{}",
+ name, msg, file, line);
+ if log_backtrace {
+ let _ = backtrace::write(err);
+ }
+ };
+
let prev = LOCAL_STDERR.with(|s| s.borrow_mut().take());
match (prev, err.as_mut()) {
(Some(mut stderr), _) => {
- // FIXME: what to do when the thread printing panics?
- let _ = writeln!(stderr,
- "thread '{}' panicked at '{}', {}:{}\n",
- name, msg, file, line);
- if backtrace::log_enabled() {
- let _ = backtrace::write(&mut *stderr);
- }
+ write(&mut *stderr);
let mut s = Some(stderr);
LOCAL_STDERR.with(|slot| {
*slot.borrow_mut() = s.take();
});
}
- (None, Some(ref mut err)) => {
- let _ = writeln!(err, "thread '{}' panicked at '{}', {}:{}",
- name, msg, file, line);
- if backtrace::log_enabled() {
- let _ = backtrace::write(err);
- }
- }
+ (None, Some(ref mut err)) => { write(err) }
_ => {}
}
+}
- // If this is a double panic, make sure that we printed a backtrace
- // for this panic.
- match err {
- Some(ref mut err) if unwind::panicking() && !backtrace::log_enabled() => {
- let _ = backtrace::write(err);
- }
- _ => {}
+pub fn on_panic(obj: &(Any+Send), file: &'static str, line: u32) {
+ let panics = PANIC_COUNT.with(|s| {
+ let count = s.get() + 1;
+ s.set(count);
+ count
+ });
+
+ // If this is the third nested call, on_panic triggered the last panic,
+ // otherwise the double-panic check would have aborted the process.
+ // Even if it is likely that on_panic was unable to log the backtrace,
+ // abort immediately to avoid infinite recursion, so that attaching a
+ // debugger provides a useable stacktrace.
+ if panics >= 3 {
+ util::dumb_print(format_args!("thread panicked while processing \
+ panic. aborting."));
+ unsafe { intrinsics::abort() }
+ }
+
+ // If this is a double panic, make sure that we print a backtrace
+ // for this panic. Otherwise only print it if logging is enabled.
+ let log_backtrace = panics >= 2 || backtrace::log_enabled();
+ log_panic(obj, file, line, log_backtrace);
+
+ if panics >= 2 {
+ // If a thread panics while it's already unwinding then we
+ // have limited options. Currently our preference is to
+ // just abort. In the future we may consider resuming
+ // unwinding or otherwise exiting the thread cleanly.
+ util::dumb_print(format_args!("thread panicked while panicking. \
+ aborting."));
+ unsafe { intrinsics::abort() }
}
}
#[link(name = "unwind", kind = "static")]
extern {}
-#[cfg(any(target_os = "android", target_os = "netbsd", target_os = "openbsd"))]
+#[cfg(any(target_os = "android", target_os = "openbsd"))]
#[link(name = "gcc")]
extern {}
+#[cfg(all(target_os = "netbsd", not(target_vendor = "rumprun")))]
+#[link(name = "gcc")]
+extern {}
+
+#[cfg(all(target_os = "netbsd", target_vendor = "rumprun"))]
+#[link(name = "unwind")]
+extern {}
+
#[cfg(target_os = "dragonfly")]
#[link(name = "gcc_pic")]
extern {}
use any::Any;
use boxed;
-use cell::Cell;
use cmp;
-use panicking;
+use panicking::{self,PANIC_COUNT};
use fmt;
use intrinsics;
use mem;
#[path = "gcc.rs"] #[doc(hidden)]
pub mod imp;
-thread_local! { static PANICKING: Cell<bool> = Cell::new(false) }
-
/// Invoke a closure, capturing the cause of panic if one occurs.
///
/// This function will return `Ok(())` if the closure did not panic, and will
// care of exposing correctly.
unsafe fn inner_try(f: fn(*mut u8), data: *mut u8)
-> Result<(), Box<Any + Send>> {
- PANICKING.with(|s| {
+ PANIC_COUNT.with(|s| {
let prev = s.get();
- s.set(false);
+ s.set(0);
let ep = intrinsics::try(f, data);
s.set(prev);
if ep.is_null() {
/// Determines whether the current thread is unwinding because of panic.
pub fn panicking() -> bool {
- PANICKING.with(|s| s.get())
+ PANIC_COUNT.with(|s| s.get() != 0)
}
// An uninlined, unmangled function upon which to slap yer breakpoints
// First, invoke the default panic handler.
panicking::on_panic(&*msg, file, line);
- if panicking() {
- // If a thread panics while it's already unwinding then we
- // have limited options. Currently our preference is to
- // just abort. In the future we may consider resuming
- // unwinding or otherwise exiting the thread cleanly.
- super::util::dumb_print(format_args!("thread panicked while panicking. \
- aborting."));
- unsafe { intrinsics::abort() }
- }
- PANICKING.with(|s| s.set(true));
-
// Finally, perform the unwinding.
rust_panic(msg);
}
#[cfg(any(target_os = "linux",
target_os = "macos",
target_os = "bitrig",
- target_os = "netbsd",
+ all(target_os = "netbsd", not(target_vendor = "rumprun")),
target_os = "openbsd"))]
mod imp {
use super::Handler;
#[cfg(not(any(target_os = "linux",
target_os = "macos",
target_os = "bitrig",
- target_os = "netbsd",
+ all(target_os = "netbsd", not(target_vendor = "rumprun")),
target_os = "openbsd")))]
mod imp {
use ptr;
#[cfg(all(not(target_os = "linux"),
not(target_os = "macos"),
not(target_os = "bitrig"),
- not(target_os = "netbsd"),
+ not(all(target_os = "netbsd", not(target_vendor = "rumprun"))),
not(target_os = "openbsd")))]
pub mod guard {
pub unsafe fn current() -> Option<usize> { None }
#[cfg(any(target_os = "linux",
target_os = "macos",
target_os = "bitrig",
- target_os = "netbsd",
+ all(target_os = "netbsd", not(target_vendor = "rumprun")),
target_os = "openbsd"))]
#[allow(unused_imports)]
pub mod guard {
use std::rc::Rc;
use serialize::{Encodable, Decodable, Encoder, Decoder};
-// FIXME #6993: in librustc, uses of "ident" should be replaced
-// by just "Name".
+/// A name is a part of an identifier, representing a string or gensym. It's
+/// the result of interning.
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct Name(pub u32);
+
+/// A SyntaxContext represents a chain of macro-expandings
+/// and renamings. Each macro expansion corresponds to
+/// a fresh u32. This u32 is a reference to a table stored
+// in thread-local storage.
+// The special value EMPTY_CTXT is used to indicate an empty
+// syntax context.
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+pub struct SyntaxContext(pub u32);
/// An identifier contains a Name (index into the interner
/// table) and a SyntaxContext to track renaming and
-/// macro expansion per Flatt et al., "Macros
-/// That Work Together"
-#[derive(Clone, Copy, Hash, PartialOrd, Eq, Ord)]
+/// macro expansion per Flatt et al., "Macros That Work Together"
+#[derive(Clone, Copy, Eq, Hash)]
pub struct Ident {
pub name: Name,
pub ctxt: SyntaxContext
}
-impl Ident {
- /// Construct an identifier with the given name and an empty context:
- pub fn new(name: Name) -> Ident { Ident {name: name, ctxt: EMPTY_CTXT}}
+impl Name {
+ pub fn as_str(self) -> token::InternedString {
+ token::InternedString::new_from_name(self)
+ }
}
-impl fmt::Debug for Ident {
+impl fmt::Debug for Name {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "{}#{}", self.name, self.ctxt)
+ write!(f, "{}({})", self, self.0)
}
}
-impl fmt::Display for Ident {
+impl fmt::Display for Name {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- fmt::Display::fmt(&self.name, f)
+ fmt::Display::fmt(&self.as_str(), f)
}
}
-impl fmt::Debug for Name {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let Name(nm) = *self;
- write!(f, "{}({})", self, nm)
+impl Encodable for Name {
+ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+ s.emit_str(&self.as_str())
}
}
-impl fmt::Display for Name {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- fmt::Display::fmt(&self.as_str(), f)
+impl Decodable for Name {
+ fn decode<D: Decoder>(d: &mut D) -> Result<Name, D::Error> {
+ Ok(token::intern(&try!(d.read_str())[..]))
+ }
+}
+
+pub const EMPTY_CTXT : SyntaxContext = SyntaxContext(0);
+
+impl Ident {
+ pub fn new(name: Name, ctxt: SyntaxContext) -> Ident {
+ Ident {name: name, ctxt: ctxt}
+ }
+ pub fn with_empty_ctxt(name: Name) -> Ident {
+ Ident {name: name, ctxt: EMPTY_CTXT}
}
}
// idents that have different contexts. You can't fix this without
// knowing whether the comparison should be hygienic or non-hygienic.
// if it should be non-hygienic (most things are), just compare the
- // 'name' fields of the idents. Or, even better, replace the idents
- // with Name's.
+ // 'name' fields of the idents.
//
// On the other hand, if the comparison does need to be hygienic,
// one example and its non-hygienic counterpart would be:
// syntax::parse::token::Token::mtwt_eq
// syntax::ext::tt::macro_parser::token_name_eq
- panic!("not allowed to compare these idents: {:?}, {:?}. \
- Probably related to issue \\#6993", self, other);
+ panic!("idents with different contexts are compared with operator `==`: \
+ {:?}, {:?}.", self, other);
}
}
}
-/// A SyntaxContext represents a chain of macro-expandings
-/// and renamings. Each macro expansion corresponds to
-/// a fresh u32
-
-// I'm representing this syntax context as an index into
-// a table, in order to work around a compiler bug
-// that's causing unreleased memory to cause core dumps
-// and also perhaps to save some work in destructor checks.
-// the special uint '0' will be used to indicate an empty
-// syntax context.
-
-// this uint is a reference to a table stored in thread-local
-// storage.
-pub type SyntaxContext = u32;
-pub const EMPTY_CTXT : SyntaxContext = 0;
-pub const ILLEGAL_CTXT : SyntaxContext = 1;
-
-/// A name is a part of an identifier, representing a string or gensym. It's
-/// the result of interning.
-#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Clone, Copy)]
-pub struct Name(pub u32);
-
-impl<T: AsRef<str>> PartialEq<T> for Name {
- fn eq(&self, other: &T) -> bool {
- self.as_str() == other.as_ref()
- }
-}
-
-impl Name {
- pub fn as_str(&self) -> token::InternedString {
- token::InternedString::new_from_name(*self)
- }
-
- pub fn usize(&self) -> usize {
- let Name(nm) = *self;
- nm as usize
- }
-
- pub fn ident(&self) -> Ident {
- Ident { name: *self, ctxt: 0 }
- }
-}
-
-/// A mark represents a unique id associated with a macro expansion
-pub type Mrk = u32;
-
-impl Encodable for Name {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_str(&self.as_str())
+impl fmt::Debug for Ident {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}#{}", self.name, self.ctxt.0)
}
}
-impl Decodable for Name {
- fn decode<D: Decoder>(d: &mut D) -> Result<Name, D::Error> {
- Ok(token::intern(&try!(d.read_str())[..]))
+impl fmt::Display for Ident {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Display::fmt(&self.name, f)
}
}
}
}
-/// Function name (not all functions have names)
-pub type FnIdent = Option<Ident>;
+/// A mark represents a unique id associated with a macro expansion
+pub type Mrk = u32;
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
pub struct Lifetime {
///
/// This is desugared to a `match` expression.
ExprIfLet(P<Pat>, P<Expr>, P<Block>, Option<P<Expr>>),
- // FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
/// A while loop, with an optional label
///
/// `'label: while expr { block }`
ExprWhile(P<Expr>, P<Block>, Option<Ident>),
- // FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
/// A while-let loop, with an optional label
///
/// `'label: while let pat = expr { block }`
///
/// This is desugared to a combination of `loop` and `match` expressions.
ExprWhileLet(P<Pat>, P<Expr>, P<Block>, Option<Ident>),
- // FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
/// A for loop, with an optional label
///
/// `'label: for pat in expr { block }`
/// Conditionless loop (can be exited with break, continue, or return)
///
/// `'label: loop { block }`
- // FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
ExprLoop(P<Block>, Option<Ident>),
/// A `match` block, with a source that indicates whether or not it is
/// the result of a desugaring, and if so, which kind.
pub mutbl: Mutability,
}
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct TypeField {
- pub ident: Ident,
- pub mt: MutTy,
- pub span: Span,
-}
-
/// Represents a method's signature in a trait declaration,
/// or in an implementation.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
use ast::*;
use super::*;
- fn ident_to_segment(id : &Ident) -> PathSegment {
- PathSegment {identifier: id.clone(),
+ fn ident_to_segment(id: Ident) -> PathSegment {
+ PathSegment {identifier: id,
parameters: PathParameters::none()}
}
#[test] fn idents_name_eq_test() {
assert!(segments_name_eq(
- &[Ident{name:Name(3),ctxt:4}, Ident{name:Name(78),ctxt:82}]
- .iter().map(ident_to_segment).collect::<Vec<PathSegment>>(),
- &[Ident{name:Name(3),ctxt:104}, Ident{name:Name(78),ctxt:182}]
- .iter().map(ident_to_segment).collect::<Vec<PathSegment>>()));
+ &[Ident::new(Name(3),SyntaxContext(4)), Ident::new(Name(78),SyntaxContext(82))]
+ .iter().cloned().map(ident_to_segment).collect::<Vec<PathSegment>>(),
+ &[Ident::new(Name(3),SyntaxContext(104)), Ident::new(Name(78),SyntaxContext(182))]
+ .iter().cloned().map(ident_to_segment).collect::<Vec<PathSegment>>()));
assert!(!segments_name_eq(
- &[Ident{name:Name(3),ctxt:4}, Ident{name:Name(78),ctxt:82}]
- .iter().map(ident_to_segment).collect::<Vec<PathSegment>>(),
- &[Ident{name:Name(3),ctxt:104}, Ident{name:Name(77),ctxt:182}]
- .iter().map(ident_to_segment).collect::<Vec<PathSegment>>()));
+ &[Ident::new(Name(3),SyntaxContext(4)), Ident::new(Name(78),SyntaxContext(82))]
+ .iter().cloned().map(ident_to_segment).collect::<Vec<PathSegment>>(),
+ &[Ident::new(Name(3),SyntaxContext(104)), Ident::new(Name(77),SyntaxContext(182))]
+ .iter().cloned().map(ident_to_segment).collect::<Vec<PathSegment>>()));
}
}
#[cfg(test)]
mod tests {
use super::*;
- use std::rc::Rc;
#[test]
fn t1 () {
#[cfg(test)]
mod test {
use super::{EmitterWriter, Level};
- use codemap::{mk_sp, CodeMap, BytePos};
+ use codemap::{mk_sp, CodeMap};
use std::sync::{Arc, Mutex};
use std::io::{self, Write};
use std::str::from_utf8;
));
}
});
- let sym = Ident::new(token::gensym(&format!(
+ let sym = Ident::with_empty_ctxt(token::gensym(&format!(
"__register_diagnostic_{}", code
)));
MacEager::items(SmallVector::many(vec![
EntryPointType::Start
} else if attr::contains_name(&item.attrs, "main") {
EntryPointType::MainAttr
- } else if item.ident.name == "main" {
+ } else if item.ident.name.as_str() == "main" {
if depth == 1 {
// This is a top-level function so can be 'main'
EntryPointType::MainNamed
loop {
if self.codemap().with_expn_info(expn_id, |info| {
info.map_or(None, |i| {
- if i.callee.name() == "include" {
+ if i.callee.name().as_str() == "include" {
// Stop going up the backtrace once include! is encountered
return None;
}
unreachable!()
}
- pub fn find(&self, k: &Name) -> Option<Rc<SyntaxExtension>> {
+ pub fn find(&self, k: Name) -> Option<Rc<SyntaxExtension>> {
for frame in self.chain.iter().rev() {
- match frame.map.get(k) {
+ match frame.map.get(&k) {
Some(v) => return Some(v.clone()),
None => {}
}
fn ty_vars(&self, ty_params: &OwnedSlice<ast::TyParam>) -> Vec<P<ast::Ty>> ;
fn ty_vars_global(&self, ty_params: &OwnedSlice<ast::TyParam>) -> Vec<P<ast::Ty>> ;
- fn ty_field_imm(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> ast::TypeField;
fn typaram(&self,
span: Span,
Vec::new()))
}
- fn ty_field_imm(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> ast::TypeField {
- ast::TypeField {
- ident: name,
- mt: ast::MutTy { ty: ty, mutbl: ast::MutImmutable },
- span: span,
- }
- }
-
fn ty_infer(&self, span: Span) -> P<ast::Ty> {
self.ty(span, ast::TyInfer)
}
return None;
}
let extname = pth.segments[0].identifier.name;
- match fld.cx.syntax_env.find(&extname) {
+ match fld.cx.syntax_env.find(extname) {
None => {
fld.cx.span_err(
pth.span,
fld: &mut MacroExpander) -> (P<Block>, Option<Ident>) {
match opt_ident {
Some(label) => {
- let new_label = fresh_name(&label);
+ let new_label = fresh_name(label);
let rename = (label, new_label);
// The rename *must not* be added to the pending list of current
let fm = fresh_mark();
let items = {
- let expanded = match fld.cx.syntax_env.find(&extname) {
+ let expanded = match fld.cx.syntax_env.find(extname) {
None => {
fld.cx.span_err(path_span,
&format!("macro undefined: '{}!'",
// generate fresh names, push them to a new pending list
let idents = pattern_bindings(&*expanded_pat);
let mut new_pending_renames =
- idents.iter().map(|ident| (*ident, fresh_name(ident))).collect();
+ idents.iter().map(|ident| (*ident, fresh_name(*ident))).collect();
// rewrite the pattern using the new names (the old
// ones have already been applied):
let rewritten_pat = {
// all of the pats must have the same set of bindings, so use the
// first one to extract them and generate new names:
let idents = pattern_bindings(&*expanded_pats[0]);
- let new_renames = idents.into_iter().map(|id| (id, fresh_name(&id))).collect();
+ let new_renames = idents.into_iter().map(|id| (id, fresh_name(id))).collect();
// apply the renaming, but only to the PatIdents:
let mut rename_pats_fld = PatIdentRenamer{renames:&new_renames};
let rewritten_pats = expanded_pats.move_map(|pat| rename_pats_fld.fold_pat(pat));
return DummyResult::raw_pat(span);
}
let extname = pth.segments[0].identifier.name;
- let marked_after = match fld.cx.syntax_env.find(&extname) {
+ let marked_after = match fld.cx.syntax_env.find(extname) {
None => {
fld.cx.span_err(pth.span,
&format!("macro undefined: '{}!'",
impl<'a> Folder for IdentRenamer<'a> {
fn fold_ident(&mut self, id: Ident) -> Ident {
- Ident {
- name: id.name,
- ctxt: mtwt::apply_renames(self.renames, id.ctxt),
- }
+ Ident::new(id.name, mtwt::apply_renames(self.renames, id.ctxt))
}
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
fold::noop_fold_mac(mac, self)
pat.map(|ast::Pat {id, node, span}| match node {
ast::PatIdent(binding_mode, Spanned{span: sp, node: ident}, sub) => {
- let new_ident = Ident{name: ident.name,
- ctxt: mtwt::apply_renames(self.renames, ident.ctxt)};
+ let new_ident = Ident::new(ident.name,
+ mtwt::apply_renames(self.renames, ident.ctxt));
let new_node =
ast::PatIdent(binding_mode,
Spanned{span: self.new_span(sp), node: new_ident},
fld: &MacroExpander)
-> (Vec<ast::Attribute>, Vec<ast::Attribute>) {
attrs.iter().cloned().partition(|attr| {
- match fld.cx.syntax_env.find(&intern(&attr.name())) {
+ match fld.cx.syntax_env.find(intern(&attr.name())) {
Some(rc) => match *rc {
$variant(..) => true,
_ => false
{
for attr in a.attrs() {
let mname = intern(&attr.name());
- match fld.cx.syntax_env.find(&mname) {
+ match fld.cx.syntax_env.find(mname) {
Some(rc) => match *rc {
MultiDecorator(ref dec) => {
attr::mark_used(&attr);
for attr in &modifiers {
let mname = intern(&attr.name());
- match fld.cx.syntax_env.find(&mname) {
+ match fld.cx.syntax_env.find(mname) {
Some(rc) => match *rc {
MultiModifier(ref mac) => {
attr::mark_used(attr);
let expanded_decl = fld.fold_fn_decl(fn_decl);
let idents = fn_decl_arg_bindings(&*expanded_decl);
let renames =
- idents.iter().map(|id : &ast::Ident| (*id,fresh_name(id))).collect();
+ idents.iter().map(|id| (*id,fresh_name(*id))).collect();
// first, a renamer for the PatIdents, for the fn_decl:
let mut rename_pat_fld = PatIdentRenamer{renames: &renames};
let rewritten_fn_decl = rename_pat_fld.fold_fn_decl(expanded_decl);
impl Folder for Marker {
fn fold_ident(&mut self, id: Ident) -> Ident {
- ast::Ident {
- name: id.name,
- ctxt: mtwt::apply_mark(self.mark, id.ctxt)
- }
+ ast::Ident::new(id.name, mtwt::apply_mark(self.mark, id.ctxt))
}
fn fold_mac(&mut self, Spanned {node, span}: ast::Mac) -> ast::Mac {
Spanned {
// find the xx binding
let bindings = crate_bindings(&cr);
let cxbinds: Vec<&ast::Ident> =
- bindings.iter().filter(|b| b.name == "xx").collect();
+ bindings.iter().filter(|b| b.name.as_str() == "xx").collect();
let cxbinds: &[&ast::Ident] = &cxbinds[..];
let cxbind = match (cxbinds.len(), cxbinds.get(0)) {
(1, Some(b)) => *b,
// the xx binding should bind all of the xx varrefs:
for (idx,v) in varrefs.iter().filter(|p| {
p.segments.len() == 1
- && p.segments[0].identifier.name == "xx"
+ && p.segments[0].identifier.name.as_str() == "xx"
}).enumerate() {
if mtwt::resolve(v.segments[0].identifier) != resolved_binding {
println!("uh oh, xx binding didn't match xx varref:");
pub struct SCTable {
table: RefCell<Vec<SyntaxContext_>>,
mark_memo: RefCell<HashMap<(SyntaxContext,Mrk),SyntaxContext>>,
- rename_memo: RefCell<HashMap<(SyntaxContext,Ident,Name),SyntaxContext>>,
+ rename_memo: RefCell<HashMap<(SyntaxContext,Name,SyntaxContext,Name),SyntaxContext>>,
}
#[derive(PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy, Clone)]
/// Extend a syntax context with a given mark and sctable (explicit memoization)
fn apply_mark_internal(m: Mrk, ctxt: SyntaxContext, table: &SCTable) -> SyntaxContext {
let key = (ctxt, m);
- * table.mark_memo.borrow_mut().entry(key)
- .or_insert_with(|| idx_push(&mut *table.table.borrow_mut(), Mark(m, ctxt)))
+ *table.mark_memo.borrow_mut().entry(key).or_insert_with(|| {
+ SyntaxContext(idx_push(&mut *table.table.borrow_mut(), Mark(m, ctxt)))
+ })
}
/// Extend a syntax context with a given rename
to: Name,
ctxt: SyntaxContext,
table: &SCTable) -> SyntaxContext {
- let key = (ctxt, id, to);
+ let key = (ctxt, id.name, id.ctxt, to);
- * table.rename_memo.borrow_mut().entry(key)
- .or_insert_with(|| idx_push(&mut *table.table.borrow_mut(), Rename(id, to, ctxt)))
+ *table.rename_memo.borrow_mut().entry(key).or_insert_with(|| {
+ SyntaxContext(idx_push(&mut *table.table.borrow_mut(), Rename(id, to, ctxt)))
+ })
}
/// Apply a list of renamings to a context
}
let resolved = {
- let result = (*table.table.borrow())[id.ctxt as usize];
+ let result = (*table.table.borrow())[id.ctxt.0 as usize];
match result {
EmptyCtxt => id.name,
// ignore marks here:
Mark(_,subctxt) =>
- resolve_internal(Ident{name:id.name, ctxt: subctxt},
+ resolve_internal(Ident::new(id.name, subctxt),
table, resolve_table),
// do the rename if necessary:
Rename(Ident{name, ctxt}, toname, subctxt) => {
let resolvedfrom =
- resolve_internal(Ident{name:name, ctxt:ctxt},
+ resolve_internal(Ident::new(name, ctxt),
table, resolve_table);
let resolvedthis =
- resolve_internal(Ident{name:id.name, ctxt:subctxt},
+ resolve_internal(Ident::new(id.name, subctxt),
table, resolve_table);
if (resolvedthis == resolvedfrom)
&& (marksof_internal(ctxt, resolvedthis, table)
let mut result = Vec::new();
let mut loopvar = ctxt;
loop {
- let table_entry = (*table.table.borrow())[loopvar as usize];
+ let table_entry = (*table.table.borrow())[loopvar.0 as usize];
match table_entry {
EmptyCtxt => {
return result;
/// FAILS when outside is not a mark.
pub fn outer_mark(ctxt: SyntaxContext) -> Mrk {
with_sctable(|sctable| {
- match (*sctable.table.borrow())[ctxt as usize] {
+ match (*sctable.table.borrow())[ctxt.0 as usize] {
Mark(mrk, _) => mrk,
_ => panic!("can't retrieve outer mark when outside is not a mark")
}
}
fn id(n: u32, s: SyntaxContext) -> Ident {
- Ident {name: Name(n), ctxt: s}
+ Ident::new(Name(n), s)
}
// because of the SCTable, I now need a tidy way of
let mut result = Vec::new();
loop {
let table = table.table.borrow();
- match (*table)[sc as usize] {
+ match (*table)[sc.0 as usize] {
EmptyCtxt => {return result;},
Mark(mrk,tail) => {
result.push(M(mrk));
fn test_unfold_refold(){
let mut t = new_sctable_internal();
- let test_sc = vec!(M(3),R(id(101,0),Name(14)),M(9));
- assert_eq!(unfold_test_sc(test_sc.clone(),EMPTY_CTXT,&mut t),4);
+ let test_sc = vec!(M(3),R(id(101,EMPTY_CTXT),Name(14)),M(9));
+ assert_eq!(unfold_test_sc(test_sc.clone(),EMPTY_CTXT,&mut t),SyntaxContext(4));
{
let table = t.table.borrow();
- assert!((*table)[2] == Mark(9,0));
- assert!((*table)[3] == Rename(id(101,0),Name(14),2));
- assert!((*table)[4] == Mark(3,3));
+ assert!((*table)[2] == Mark(9,EMPTY_CTXT));
+ assert!((*table)[3] == Rename(id(101,EMPTY_CTXT),Name(14),SyntaxContext(2)));
+ assert!((*table)[4] == Mark(3,SyntaxContext(3)));
}
- assert_eq!(refold_test_sc(4,&t),test_sc);
+ assert_eq!(refold_test_sc(SyntaxContext(4),&t),test_sc);
}
// extend a syntax context with a sequence of marks given
#[test] fn unfold_marks_test() {
let mut t = new_sctable_internal();
- assert_eq!(unfold_marks(vec!(3,7),EMPTY_CTXT,&mut t),3);
+ assert_eq!(unfold_marks(vec!(3,7),EMPTY_CTXT,&mut t),SyntaxContext(3));
{
let table = t.table.borrow();
- assert!((*table)[2] == Mark(7,0));
- assert!((*table)[3] == Mark(3,2));
+ assert!((*table)[2] == Mark(7,EMPTY_CTXT));
+ assert!((*table)[3] == Mark(3,SyntaxContext(2)));
}
}
assert_eq! (marksof_internal (ans, stopname,&t), [16]);}
// rename where stop doesn't match:
{ let chain = vec!(M(9),
- R(id(name1.usize() as u32,
+ R(id(name1.0,
apply_mark_internal (4, EMPTY_CTXT,&mut t)),
Name(100101102)),
M(14));
// rename where stop does match
{ let name1sc = apply_mark_internal(4, EMPTY_CTXT, &mut t);
let chain = vec!(M(9),
- R(id(name1.usize() as u32, name1sc),
+ R(id(name1.0, name1sc),
stopname),
M(14));
let ans = unfold_test_sc(chain,EMPTY_CTXT,&mut t);
#[test]
fn hashing_tests () {
let mut t = new_sctable_internal();
- assert_eq!(apply_mark_internal(12,EMPTY_CTXT,&mut t),2);
- assert_eq!(apply_mark_internal(13,EMPTY_CTXT,&mut t),3);
+ assert_eq!(apply_mark_internal(12,EMPTY_CTXT,&mut t),SyntaxContext(2));
+ assert_eq!(apply_mark_internal(13,EMPTY_CTXT,&mut t),SyntaxContext(3));
// using the same one again should result in the same index:
- assert_eq!(apply_mark_internal(12,EMPTY_CTXT,&mut t),2);
+ assert_eq!(apply_mark_internal(12,EMPTY_CTXT,&mut t),SyntaxContext(2));
// I'm assuming that the rename table will behave the same....
}
#[test]
fn new_resolves_test() {
- let renames = vec!((Ident{name:Name(23),ctxt:EMPTY_CTXT},Name(24)),
- (Ident{name:Name(29),ctxt:EMPTY_CTXT},Name(29)));
+ let renames = vec!((Ident::with_empty_ctxt(Name(23)),Name(24)),
+ (Ident::with_empty_ctxt(Name(29)),Name(29)));
let new_ctxt1 = apply_renames(&renames,EMPTY_CTXT);
- assert_eq!(resolve(Ident{name:Name(23),ctxt:new_ctxt1}),Name(24));
- assert_eq!(resolve(Ident{name:Name(29),ctxt:new_ctxt1}),Name(29));
+ assert_eq!(resolve(Ident::new(Name(23),new_ctxt1)),Name(24));
+ assert_eq!(resolve(Ident::new(Name(29),new_ctxt1)),Name(29));
}
}
($name: expr, $suffix: expr, $($args: expr),*) => {{
let inner = cx.expr_call(sp, mk_token_path(cx, sp, $name), vec![$($args),*]);
let suffix = match $suffix {
- Some(name) => cx.expr_some(sp, mk_name(cx, sp, ast::Ident::new(name))),
+ Some(name) => cx.expr_some(sp, mk_name(cx, sp, ast::Ident::with_empty_ctxt(name))),
None => cx.expr_none(sp)
};
cx.expr_call(sp, mk_token_path(cx, sp, "Literal"), vec![inner, suffix])
}
token::Literal(token::Byte(i), suf) => {
- let e_byte = mk_name(cx, sp, i.ident());
+ let e_byte = mk_name(cx, sp, ast::Ident::with_empty_ctxt(i));
return mk_lit!("Byte", suf, e_byte);
}
token::Literal(token::Char(i), suf) => {
- let e_char = mk_name(cx, sp, i.ident());
+ let e_char = mk_name(cx, sp, ast::Ident::with_empty_ctxt(i));
return mk_lit!("Char", suf, e_char);
}
token::Literal(token::Integer(i), suf) => {
- let e_int = mk_name(cx, sp, i.ident());
+ let e_int = mk_name(cx, sp, ast::Ident::with_empty_ctxt(i));
return mk_lit!("Integer", suf, e_int);
}
token::Literal(token::Float(fident), suf) => {
- let e_fident = mk_name(cx, sp, fident.ident());
+ let e_fident = mk_name(cx, sp, ast::Ident::with_empty_ctxt(fident));
return mk_lit!("Float", suf, e_fident);
}
token::Literal(token::Str_(ident), suf) => {
- return mk_lit!("Str_", suf, mk_name(cx, sp, ident.ident()))
+ return mk_lit!("Str_", suf, mk_name(cx, sp, ast::Ident::with_empty_ctxt(ident)))
}
token::Literal(token::StrRaw(ident, n), suf) => {
- return mk_lit!("StrRaw", suf, mk_name(cx, sp, ident.ident()), cx.expr_usize(sp, n))
+ return mk_lit!("StrRaw", suf, mk_name(cx, sp, ast::Ident::with_empty_ctxt(ident)),
+ cx.expr_usize(sp, n))
}
token::Ident(ident, style) => {
token::DocComment(ident) => {
return cx.expr_call(sp,
mk_token_path(cx, sp, "DocComment"),
- vec!(mk_name(cx, sp, ident.ident())));
+ vec!(mk_name(cx, sp, ast::Ident::with_empty_ctxt(ident))));
}
token::MatchNt(name, kind, namep, kindp) => {
use self::TokenTreeOrTokenTreeVec::*;
use ast;
-use ast::{TokenTree, Ident};
+use ast::{TokenTree, Name};
use ast::{TtDelimited, TtSequence, TtToken};
use codemap::{BytePos, mk_sp, Span};
use codemap;
}
pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc<NamedMatch>])
- -> HashMap<Ident, Rc<NamedMatch>> {
+ -> HashMap<Name, Rc<NamedMatch>> {
fn n_rec(p_s: &ParseSess, m: &TokenTree, res: &[Rc<NamedMatch>],
- ret_val: &mut HashMap<Ident, Rc<NamedMatch>>, idx: &mut usize) {
+ ret_val: &mut HashMap<Name, Rc<NamedMatch>>, idx: &mut usize) {
match m {
&TtSequence(_, ref seq) => {
for next_m in &seq.tts {
}
}
&TtToken(sp, MatchNt(bind_name, _, _, _)) => {
- match ret_val.entry(bind_name) {
+ match ret_val.entry(bind_name.name) {
Vacant(spot) => {
spot.insert(res[*idx].clone());
*idx += 1;
Error(codemap::Span, String)
}
-pub type NamedParseResult = ParseResult<HashMap<Ident, Rc<NamedMatch>>>;
+pub type NamedParseResult = ParseResult<HashMap<Name, Rc<NamedMatch>>>;
pub type PositionalParseResult = ParseResult<Vec<Rc<NamedMatch>>>;
/// Perform a token equality check, ignoring syntax context (that is, an
};
// Extract the arguments:
- let lhses = match **argument_map.get(&lhs_nm).unwrap() {
+ let lhses = match **argument_map.get(&lhs_nm.name).unwrap() {
MatchedSeq(ref s, _) => /* FIXME (#2543) */ (*s).clone(),
_ => cx.span_bug(def.span, "wrong-structured lhs")
};
check_lhs_nt_follows(cx, &**lhs, def.span);
}
- let rhses = match **argument_map.get(&rhs_nm).unwrap() {
+ let rhses = match **argument_map.get(&rhs_nm.name).unwrap() {
MatchedSeq(ref s, _) => /* FIXME (#2543) */ (*s).clone(),
_ => cx.span_bug(def.span, "wrong-structured rhs")
};
"pat" => {
match *tok {
FatArrow | Comma | Eq => Ok(true),
- Ident(i, _) if i.name == "if" || i.name == "in" => Ok(true),
+ Ident(i, _) if i.name.as_str() == "if" || i.name.as_str() == "in" => Ok(true),
_ => Ok(false)
}
},
"path" | "ty" => {
match *tok {
Comma | FatArrow | Colon | Eq | Gt | Semi => Ok(true),
- Ident(i, _) if i.name == "as" => Ok(true),
+ Ident(i, _) if i.name.as_str() == "as" => Ok(true),
_ => Ok(false)
}
},
use self::LockstepIterSize::*;
use ast;
-use ast::{TokenTree, TtDelimited, TtToken, TtSequence, Ident};
+use ast::{TokenTree, TtDelimited, TtToken, TtSequence, Ident, Name};
use codemap::{Span, DUMMY_SP};
use diagnostic::SpanHandler;
use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
/// the unzipped tree:
stack: Vec<TtFrame>,
/* for MBE-style macro transcription */
- interpolations: HashMap<Ident, Rc<NamedMatch>>,
+ interpolations: HashMap<Name, Rc<NamedMatch>>,
imported_from: Option<Ident>,
// Some => return imported_from as the next token
/// `src` contains no `TtSequence`s, `MatchNt`s or `SubstNt`s, `interp` can
/// (and should) be None.
pub fn new_tt_reader<'a>(sp_diag: &'a SpanHandler,
- interp: Option<HashMap<Ident, Rc<NamedMatch>>>,
+ interp: Option<HashMap<Name, Rc<NamedMatch>>>,
imported_from: Option<Ident>,
src: Vec<ast::TokenTree>)
-> TtReader<'a> {
/// `src` contains no `TtSequence`s, `MatchNt`s or `SubstNt`s, `interp` can
/// (and should) be None.
pub fn new_tt_reader_with_doc_flag<'a>(sp_diag: &'a SpanHandler,
- interp: Option<HashMap<Ident, Rc<NamedMatch>>>,
+ interp: Option<HashMap<Name, Rc<NamedMatch>>>,
imported_from: Option<Ident>,
src: Vec<ast::TokenTree>,
desugar_doc_comments: bool)
}
fn lookup_cur_matched(r: &TtReader, name: Ident) -> Option<Rc<NamedMatch>> {
- let matched_opt = r.interpolations.get(&name).cloned();
+ let matched_opt = r.interpolations.get(&name.name).cloned();
matched_opt.map(|s| lookup_cur_matched_by_matched(r, s))
}
use diagnostic::SpanHandler;
use visit;
use visit::{FnKind, Visitor};
-use parse::token::{self, InternedString};
+use parse::token::InternedString;
use std::ascii::AsciiExt;
use std::cmp;
// allow `#[omit_gdb_pretty_printer_section]`
("omit_gdb_pretty_printer_section", "1.5.0", None, Active),
+
+ // Allows cfg(target_vendor = "...").
+ ("cfg_target_vendor", "1.5.0", None, Active),
];
// (changing above list without updating src/doc/reference.md makes @cmr sad)
const GATED_CFGS: &'static [(&'static str, &'static str, fn(&Features) -> bool)] = &[
// (name in cfg, feature, function to check if the feature is enabled)
("target_feature", "cfg_target_feature", cfg_fn!(|x| x.cfg_target_feature)),
+ ("target_vendor", "cfg_target_vendor", cfg_fn!(|x| x.cfg_target_vendor)),
];
#[derive(Debug, Eq, PartialEq)]
pub default_type_parameter_fallback: bool,
pub type_macros: bool,
pub cfg_target_feature: bool,
+ pub cfg_target_vendor: bool,
pub augmented_assignments: bool,
}
default_type_parameter_fallback: false,
type_macros: false,
cfg_target_feature: false,
+ cfg_target_vendor: false,
augmented_assignments: false,
}
}
impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> {
fn visit_mac(&mut self, mac: &ast::Mac) {
let path = &mac.node.path;
- let id = path.segments.last().unwrap().identifier;
+ let name = path.segments.last().unwrap().identifier.name.as_str();
// Issue 22234: If you add a new case here, make sure to also
// add code to catch the macro during or after expansion.
// catch uses of these macros within conditionally-compiled
// code, e.g. `#[cfg]`-guarded functions.
- if id == token::str_to_ident("asm") {
+ if name == "asm" {
self.context.gate_feature("asm", path.span, EXPLAIN_ASM);
}
- else if id == token::str_to_ident("log_syntax") {
+ else if name == "log_syntax" {
self.context.gate_feature("log_syntax", path.span, EXPLAIN_LOG_SYNTAX);
}
- else if id == token::str_to_ident("trace_macros") {
+ else if name == "trace_macros" {
self.context.gate_feature("trace_macros", path.span, EXPLAIN_TRACE_MACROS);
}
- else if id == token::str_to_ident("concat_idents") {
+ else if name == "concat_idents" {
self.context.gate_feature("concat_idents", path.span, EXPLAIN_CONCAT_IDENTS);
}
}
default_type_parameter_fallback: cx.has_feature("default_type_parameter_fallback"),
type_macros: cx.has_feature("type_macros"),
cfg_target_feature: cx.has_feature("cfg_target_feature"),
+ cfg_target_vendor: cx.has_feature("cfg_target_vendor"),
augmented_assignments: cx.has_feature("augmented_assignments"),
}
}
token::DocComment(s) => {
let attr = ::attr::mk_sugared_doc_attr(
attr::mk_attr_id(),
- self.id_to_interned_str(s.ident()),
+ self.id_to_interned_str(ast::Ident::with_empty_ctxt(s)),
self.span.lo,
self.span.hi
);
token::DocComment(s) => {
// we need to get the position of this token before we bump.
let Span { lo, hi, .. } = self.span;
- let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(),
- self.id_to_interned_str(s.ident()),
- lo, hi);
+ let str = self.id_to_interned_str(ast::Ident::with_empty_ctxt(s));
+ let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), str, lo, hi);
if attr.node.style == ast::AttrInner {
attrs.push(attr);
panictry!(self.bump());
Some(&ast::TtToken(_, token::Ident(name_zip, token::Plain))),
Some(&ast::TtDelimited(_, ref macro_delimed)),
)
- if name_macro_rules.name == "macro_rules"
- && name_zip.name == "zip" => {
+ if name_macro_rules.name.as_str() == "macro_rules"
+ && name_zip.name.as_str() == "zip" => {
let tts = ¯o_delimed.tts[..];
match (tts.len(), tts.get(0), tts.get(1), tts.get(2)) {
(
Some(&ast::TtToken(_, token::Ident(ident, token::Plain))),
)
if first_delimed.delim == token::Paren
- && ident.name == "a" => {},
+ && ident.name.as_str() == "a" => {},
_ => panic!("value 3: {:?}", **first_delimed),
}
let tts = &second_delimed.tts[..];
Some(&ast::TtToken(_, token::Ident(ident, token::Plain))),
)
if second_delimed.delim == token::Paren
- && ident.name == "a" => {},
+ && ident.name.as_str() == "a" => {},
_ => panic!("value 4: {:?}", **second_delimed),
}
},
(fields, None)
// Tuple-style struct definition with optional where-clause.
} else if self.token == token::OpenDelim(token::Paren) {
- let fields = try!(self.parse_tuple_struct_body(&class_name, &mut generics));
+ let fields = try!(self.parse_tuple_struct_body(class_name, &mut generics));
(fields, Some(ast::DUMMY_NODE_ID))
} else {
let token_str = self.this_token_to_string();
}
pub fn parse_tuple_struct_body(&mut self,
- class_name: &ast::Ident,
+ class_name: ast::Ident,
generics: &mut ast::Generics)
-> PResult<Vec<StructField>> {
// This is the case where we find `struct Foo<T>(T) where T: Copy;`
Option<ast::Name>)>> {
let ret = match self.token {
token::Literal(token::Str_(s), suf) => {
- (self.id_to_interned_str(s.ident()), ast::CookedStr, suf)
+ (self.id_to_interned_str(ast::Ident::with_empty_ctxt(s)), ast::CookedStr, suf)
}
token::Literal(token::StrRaw(s, n), suf) => {
- (self.id_to_interned_str(s.ident()), ast::RawStr(n), suf)
+ (self.id_to_interned_str(ast::Ident::with_empty_ctxt(s)), ast::RawStr(n), suf)
}
_ => return Ok(None)
};
#[allow(non_upper_case_globals)]
pub const $si_static: ast::Ident = ast::Ident {
name: ast::Name($si_name),
- ctxt: 0,
+ ctxt: ast::EMPTY_CTXT,
};
)*
}
use ast;
$(
#[allow(non_upper_case_globals)]
- pub const $si_static: ast::Name = ast::Name($si_name);
+ pub const $si_static: ast::Name = ast::Name($si_name);
)*
}
/// Maps a string to an identifier with an empty syntax context.
#[inline]
pub fn str_to_ident(s: &str) -> ast::Ident {
- ast::Ident::new(intern(s))
+ ast::Ident::with_empty_ctxt(intern(s))
}
/// Maps a string to a gensym'ed identifier.
#[inline]
pub fn gensym_ident(s: &str) -> ast::Ident {
- ast::Ident::new(gensym(s))
+ ast::Ident::with_empty_ctxt(gensym(s))
}
// create a fresh name that maps to the same string as the old one.
// note that this guarantees that str_ptr_eq(ident_to_string(src),interner_get(fresh_name(src)));
// that is, that the new name and the old one are connected to ptr_eq strings.
-pub fn fresh_name(src: &ast::Ident) -> ast::Name {
+pub fn fresh_name(src: ast::Ident) -> ast::Name {
let interner = get_ident_interner();
interner.gensym_copy(src.name)
// following: debug version. Could work in final except that it's incompatible with
// create a fresh mark.
pub fn fresh_mark() -> ast::Mrk {
- gensym("mark").usize() as u32
+ gensym("mark").0
}
#[cfg(test)]
use ext::mtwt;
fn mark_ident(id : ast::Ident, m : ast::Mrk) -> ast::Ident {
- ast::Ident { name: id.name, ctxt:mtwt::apply_mark(m, id.ctxt) }
+ ast::Ident::new(id.name, mtwt::apply_mark(m, id.ctxt))
}
#[test] fn mtwt_token_eq_test() {
token::NtBlock(ref e) => block_to_string(&**e),
token::NtStmt(ref e) => stmt_to_string(&**e),
token::NtPat(ref e) => pat_to_string(&**e),
- token::NtIdent(ref e, _) => ident_to_string(&**e),
+ token::NtIdent(ref e, _) => ident_to_string(**e),
token::NtTT(ref e) => tt_to_string(&**e),
token::NtArm(ref e) => arm_to_string(&*e),
token::NtImplItem(ref e) => impl_item_to_string(&**e),
to_string(|s| s.print_path(p, false, 0))
}
-pub fn ident_to_string(id: &ast::Ident) -> String {
- to_string(|s| s.print_ident(*id))
+pub fn ident_to_string(id: ast::Ident) -> String {
+ to_string(|s| s.print_ident(id))
}
pub fn fun_to_string(decl: &ast::FnDecl,
ast::ViewPathSimple(ident, ref path) => {
try!(self.print_path(path, false, 0));
- // FIXME(#6993) can't compare identifiers directly here
if path.segments.last().unwrap().identifier.name !=
ident.name {
try!(space(&mut self.s));
pub fn get(&self, idx: Name) -> T {
let vect = self.vect.borrow();
- (*vect)[idx.usize()].clone()
+ (*vect)[idx.0 as usize].clone()
}
pub fn len(&self) -> usize {
let new_idx = Name(self.len() as u32);
// leave out of map to avoid colliding
let mut vect = self.vect.borrow_mut();
- let existing = (*vect)[idx.usize()].clone();
+ let existing = (*vect)[idx.0 as usize].clone();
vect.push(existing);
new_idx
}
pub fn get(&self, idx: Name) -> RcStr {
- (*self.vect.borrow())[idx.usize()].clone()
+ (*self.vect.borrow())[idx.0 as usize].clone()
}
pub fn len(&self) -> usize {
use book;
use book::{Book, BookItem};
-use javascript;
-
use rustdoc;
struct Build;
}
fn render(book: &Book, tgt: &Path) -> CliResult<()> {
- let tmp = try!(TempDir::new("rust-book"));
+ let tmp = try!(TempDir::new("rustbook"));
for (_section, item) in book.iter() {
let out_path = match item.path.parent() {
// write the prelude to a temporary HTML file for rustdoc inclusion
let prelude = tmp.path().join("prelude.html");
{
- let mut toc = BufWriter::new(try!(File::create(&prelude)));
- try!(writeln!(&mut toc, r#"<div id="nav">
- <button id="toggle-nav">
- <span class="sr-only">Toggle navigation</span>
- <span class="bar"></span>
- <span class="bar"></span>
- <span class="bar"></span>
- </button>
- </div>"#));
- let _ = write_toc(book, &item, &mut toc);
- try!(writeln!(&mut toc, "<div id='page-wrapper'>"));
- try!(writeln!(&mut toc, "<div id='page'>"));
+ let mut buffer = BufWriter::new(try!(File::create(&prelude)));
+ try!(writeln!(&mut buffer, r#"
+ <div id="nav">
+ <button id="toggle-nav">
+ <span class="sr-only">Toggle navigation</span>
+ <span class="bar"></span>
+ <span class="bar"></span>
+ <span class="bar"></span>
+ </button>
+ </div>"#));
+ let _ = write_toc(book, &item, &mut buffer);
+ try!(writeln!(&mut buffer, "<div id='page-wrapper'>"));
+ try!(writeln!(&mut buffer, "<div id='page'>"));
}
// write the postlude to a temporary HTML file for rustdoc inclusion
let postlude = tmp.path().join("postlude.html");
{
- let mut toc = BufWriter::new(try!(File::create(&postlude)));
- try!(toc.write_all(javascript::JAVASCRIPT.as_bytes()));
- try!(writeln!(&mut toc, "</div></div>"));
+ let mut buffer = BufWriter::new(try!(File::create(&postlude)));
+ try!(writeln!(&mut buffer, "<script src='rustbook.js'></script>"));
+ try!(writeln!(&mut buffer, "<script src='playpen.js'></script>"));
+ try!(writeln!(&mut buffer, "</div></div>"));
}
try!(fs::create_dir_all(&out_path));
format!("--html-before-content={}", prelude.display()),
format!("--html-after-content={}", postlude.display()),
format!("--markdown-playground-url=https://play.rust-lang.org"),
- format!("--markdown-css={}", item.path_to_root.join("rust-book.css").display()),
+ format!("--markdown-css={}", item.path_to_root.join("rustbook.css").display()),
"--markdown-no-toc".to_string(),
];
let output_result = rustdoc::main_args(rustdoc_args);
let css = include_bytes!("static/rustbook.css");
let js = include_bytes!("static/rustbook.js");
- let mut css_file = try!(File::create(tgt.join("rust-book.css")));
+ let mut css_file = try!(File::create(tgt.join("rustbook.css")));
try!(css_file.write_all(css));
- let mut js_file = try!(File::create(tgt.join("rust-book.js")));
+ let mut js_file = try!(File::create(tgt.join("rustbook.js")));
try!(js_file.write_all(js));
}
pub fn usage() {
- println!("Usage: rust-book <command> [<args>]");
+ println!("Usage: rustbook <command> [<args>]");
println!("");
println!("The <command> must be one of:");
println!(" help Print this message.");
+++ /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.
-
-// The rust-book JavaScript in string form.
-
-pub static JAVASCRIPT: &'static str = r#"
-<script type="text/javascript" src="rust-book.js"></script>
-<script type="text/javascript" src="playpen.js"></script>
-"#;
mod serve;
mod test;
-mod javascript;
-
static EXIT_STATUS: AtomicIsize = ATOMIC_ISIZE_INIT;
fn main() {
/**
- * Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+ * Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
* file at the top-level directory of this distribution and at
* http://rust-lang.org/COPYRIGHT.
*
* except according to those terms.
*/
-@import url("../rust.css");
+@import url('../rust.css');
body {
- max-width:none;
- font: 16px/1.4 'Source Serif Pro', Georgia, Times, 'Times New Roman', serif;
- line-height: 1.6;
+ max-width: none;
+ font: 16px/1.6 'Source Serif Pro', Georgia, Times, 'Times New Roman', serif;
color: #333;
}
@media only screen {
#toc {
position: fixed;
- left: 0px;
- top: 0px;
- bottom: 0px;
+ top: 0;
+ left: 0;
+ bottom: 0;
width: 300px;
overflow-y: auto;
- border-right: 1px solid rgba(0, 0, 0, 0.07);
- padding: 10px 10px;
+ border-right: 1px solid #e8e8e8;
+ padding: 0 15px;
font-size: 14px;
- box-sizing: border-box;
- -webkit-overflow-scrolling: touch;
background-color: #fafafa;
- color: #364149;
+ -webkit-overflow-scrolling: touch;
}
#page-wrapper {
position: absolute;
- left: 310px;
- right: 0px;
- top: 0px;
- box-sizing: border-box;
- background: none repeat scroll 0% 0% #FFF;
+ top: 0;
+ left: 300px;
+ right: 0;
+ padding: 0 15px;
-webkit-overflow-scrolling: touch;
}
}
@media only print {
- #toc, #nav, #menu-bar {
+ #toc, #nav {
display: none;
}
}
-@media only screen and (max-width: 1060px) {
+@media only screen and (max-width: 1023px) {
#toc {
width: 100%;
- margin-right: 0;
top: 40px;
}
+
#page-wrapper {
top: 40px;
- left: 15px;
- padding-right: 15px;
+ left: 0;
}
+
.mobile-hidden {
display: none;
}
}
#page {
- margin-left: auto;
- margin-right:auto;
+ margin: 0 auto;
max-width: 750px;
padding-bottom: 50px;
}
.chapter {
- list-style: none outside none;
- padding-left: 0px;
+ list-style: none;
+ padding-left: 0;
line-height: 30px;
}
.section {
- list-style: none outside none;
+ list-style: none;
padding-left: 20px;
line-height: 40px;
}
padding: 5px 0;
}
-.chapter li a.active {
- color: #008cff;
-}
-
+.chapter li a.active,
.chapter li a:hover {
color: #008cff;
text-decoration: none;
}
#toggle-nav {
- height: 20px;
- width: 30px;
- padding: 3px 3px 0 3px;
-}
-
-#toggle-nav {
+ cursor: pointer;
margin-top: 5px;
width: 30px;
height: 30px;
- background-color: #FFF;
+ background-color: #fff;
border: 1px solid #666;
- border-radius: 3px 3px 3px 3px;
+ border-radius: 3px;
+ padding: 3px 3px 0 3px;
}
.sr-only {
border-radius: 3px;
}
-.nav-previous-next {
- margin-top: 60px;
-}
-
.left {
float: left;
}
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+/*jslint browser: true, es5: true */
+/*globals $: true, rootPath: true */
-document.addEventListener("DOMContentLoaded", function(event) {
+document.addEventListener('DOMContentLoaded', function() {
+ 'use strict';
- document.getElementById("toggle-nav").onclick = toggleNav;
+ document.getElementById('toggle-nav').onclick = function(e) {
+ var toc = document.getElementById('toc');
+ var pagewrapper = document.getElementById('page-wrapper');
+ toggleClass(toc, 'mobile-hidden');
+ toggleClass(pagewrapper, 'mobile-hidden');
+ };
- function toggleNav() {
- var toc = document.getElementById("toc");
- var pagewrapper = document.getElementById("page-wrapper");
- toggleClass(toc, "mobile-hidden");
- toggleClass(pagewrapper, "mobile-hidden");
- }
+ function toggleClass(el, className) {
+ // from http://youmightnotneedjquery.com/
+ if (el.classList) {
+ el.classList.toggle(className);
+ } else {
+ var classes = el.className.split(' ');
+ var existingIndex = classes.indexOf(className);
- function toggleClass(el, className) {
- // from http://youmightnotneedjquery.com/
- if (el.classList) {
- el.classList.toggle(className);
- } else {
- var classes = el.className.split(' ');
- var existingIndex = classes.indexOf(className);
+ if (existingIndex >= 0) {
+ classes.splice(existingIndex, 1);
+ } else {
+ classes.push(className);
+ }
- if (existingIndex >= 0) {
- classes.splice(existingIndex, 1);
- } else {
- classes.push(className);
- }
-
- el.className = classes.join(' ');
- }
- }
+ el.className = classes.join(' ');
+ }
+ }
- // The below code is used to add prev and next navigation links to the bottom
- // of each of the sections.
- // It works by extracting the current page based on the url and iterates over
- // the menu links until it finds the menu item for the current page. We then
- // create a copy of the preceding and following menu links and add the
- // correct css class and insert them into the bottom of the page.
- var toc = document.getElementById('toc').getElementsByTagName('a');
- var href = document.location.pathname.split('/').pop();
- if (href === 'index.html' || href === '') {
- href = 'README.html';
- }
+ // The below code is used to add prev and next navigation links to the
+ // bottom of each of the sections.
+ // It works by extracting the current page based on the url and iterates
+ // over the menu links until it finds the menu item for the current page. We
+ // then create a copy of the preceding and following menu links and add the
+ // correct css class and insert them into the bottom of the page.
+ var toc = document.getElementById('toc').getElementsByTagName('a');
+ var href = document.location.pathname.split('/').pop();
- for (var i = 0; i < toc.length; i++) {
- if (toc[i].attributes.href.value.split('/').pop() === href) {
- var nav = document.createElement('p');
- if (i > 0) {
- var prevNode = toc[i-1].cloneNode(true);
- prevNode.className = 'left';
- prevNode.setAttribute('rel', 'prev');
- nav.appendChild(prevNode);
- }
- if (i < toc.length - 1) {
- var nextNode = toc[i+1].cloneNode(true);
- nextNode.className = 'right';
- nextNode.setAttribute('rel', 'next');
- nav.appendChild(nextNode);
- }
- document.getElementById('page').appendChild(nav);
- break;
+ if (href === 'index.html' || href === '') {
+ href = 'README.html';
}
- }
+ for (var i = 0; i < toc.length; i++) {
+ if (toc[i].attributes.href.value.split('/').pop() === href) {
+ var nav = document.createElement('p');
+
+ if (i > 0) {
+ var prevNode = toc[i-1].cloneNode(true);
+ prevNode.className = 'left';
+ prevNode.setAttribute('rel', 'prev');
+ nav.appendChild(prevNode);
+ }
+
+ if (i < toc.length - 1) {
+ var nextNode = toc[i+1].cloneNode(true);
+ nextNode.className = 'right';
+ nextNode.setAttribute('rel', 'next');
+ nav.appendChild(nextNode);
+ }
+
+ document.getElementById('page').appendChild(nav);
+
+ break;
+ }
+ }
});
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-//! Common API for all rust-book subcommands.
+//! Common API for all rustbook subcommands.
use error::CliResult;
use error::CommandResult;
impl EarlyLintPass for Pass {
fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
- if it.ident.name == "lintme" {
+ if it.ident.name.as_str() == "lintme" {
cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'");
}
}
--- /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.
+
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+pub static FOO: i32 = 42;
let mac_expr = match TokenTree::parse(cx, &mbe_matcher[..], args) {
Success(map) => {
- match (&*map[&str_to_ident("matched")], &*map[&str_to_ident("pat")]) {
+ match (&*map[&str_to_ident("matched").name], &*map[&str_to_ident("pat").name]) {
(&MatchedNonterminal(NtExpr(ref matched_expr)),
&MatchedSeq(ref pats, seq_sp)) => {
let pats: Vec<P<Pat>> = pats.iter().map(|pat_nt|
--- /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.
+
+#[cfg(target_vendor = "x")] //~ ERROR `cfg(target_vendor)` is experimental
+#[cfg_attr(target_vendor = "x", x)] //~ ERROR `cfg(target_vendor)` is experimental
+struct Foo(u64, u64);
+
+#[cfg(not(any(all(target_vendor = "x"))))] //~ ERROR `cfg(target_vendor)` is experimental
+fn foo() {}
+
+fn main() {
+ cfg!(target_vendor = "x");
+ //~^ ERROR `cfg(target_vendor)` is experimental and subject to change
+}
--- /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.
+
+pub trait Foo<RHS=Self> {
+ type Assoc;
+}
+
+pub trait Bar: Foo<Assoc=()> {
+ fn new(&self, b: &
+ Bar //~ ERROR the trait `Bar` cannot be made into an object
+ <Assoc=()>
+ );
+}
+
+fn main() {}
#[derive(Debug)]
struct SExpr<'x> {
elements: Vec<Box<Expr+ 'x>>,
+ //~^ ERROR E0038
}
impl<'x> PartialEq for SExpr<'x> {
fn eq(&self, other:&SExpr<'x>) -> bool {
println!("L1: {} L2: {}", self.elements.len(), other.elements.len());
- //~^ ERROR E0038
let result = self.elements.len() == other.elements.len();
println!("Got compare {}", result);
}
fn main() {
- let a: Box<Expr> = Box::new(SExpr::new()); //~ ERROR E0038
- let b: Box<Expr> = Box::new(SExpr::new()); //~ ERROR E0038
+ let a: Box<Expr> = Box::new(SExpr::new());
+ let b: Box<Expr> = Box::new(SExpr::new());
// assert_eq!(a , b);
}
}
fn make_baz<T:Baz>(t: &T) -> &Baz {
+ //~^ ERROR E0038
+ //~| NOTE the trait cannot use `Self` as a type parameter in the supertrait listing
t
- //~^ ERROR E0038
- //~| NOTE the trait cannot use `Self` as a type parameter in the supertrait listing
}
fn main() {
$(call REMOVE_RLIBS,bar)
$(call REMOVE_DYLIBS,bar)
rm $(TMPDIR)/libbar.a
- rm -f $(TMPDIR)/bar.{exp,lib}
+ rm -f $(TMPDIR)/bar.{exp,lib,pdb}
# Check that $(TMPDIR) is empty.
[ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
$(RUSTC) foo.rs --crate-type=bin
rm $(TMPDIR)/$(call BIN,bar)
+ rm -f $(TMPDIR)/bar.pdb
[ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
$(RUSTC) foo.rs --emit=asm,llvm-ir,llvm-bc,obj,link
rm $(TMPDIR)/bar.s
rm $(TMPDIR)/bar.o
rm $(TMPDIR)/$(call BIN,bar)
+ rm -f $(TMPDIR)/bar.pdb
[ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
$(RUSTC) foo.rs --emit=asm -o $(TMPDIR)/foo
$(RUSTC) foo.rs --emit=link -o $(TMPDIR)/$(call BIN,foo)
rm $(TMPDIR)/$(call BIN,foo)
+ rm -f $(TMPDIR)/foo.pdb
[ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
$(RUSTC) foo.rs --crate-type=rlib -o $(TMPDIR)/foo
$(RUSTC) foo.rs --crate-type=dylib -o $(TMPDIR)/$(call BIN,foo)
rm $(TMPDIR)/$(call BIN,foo)
- rm -f $(TMPDIR)/foo.{exp,lib}
+ rm -f $(TMPDIR)/foo.{exp,lib,pdb}
[ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
$(RUSTC) foo.rs --crate-type=staticlib -o $(TMPDIR)/foo
$(RUSTC) foo.rs --crate-type=bin -o $(TMPDIR)/$(call BIN,foo)
rm $(TMPDIR)/$(call BIN,foo)
+ rm -f $(TMPDIR)/foo.pdb
[ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
$(RUSTC) foo.rs --emit=asm,llvm-ir,llvm-bc,obj,link --crate-type=staticlib
--- /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.
+
+#![feature(cfg_target_vendor)]
+
+#[cfg(target_vendor = "unknown")]
+pub fn main() {
+}
+
+#[cfg(not(target_vendor = "unknown"))]
+pub fn main() {
+}
fn main() {
let s = "abcbdef";
match_indices(s, |c: char| c == 'b')
- .collect::<Vec<(usize, usize)>>();
+ .collect::<Vec<_>>();
}
--- /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.
+
+// aux-build:msvc-data-only-lib.rs
+
+extern crate msvc_data_only_lib;
+
+fn main() {
+ println!("The answer is {} !", msvc_data_only_lib::FOO);
+}