1
Fork 0

Auto merge of #22860 - Manishearth:rollup, r=alexcrichton

Passes check-stage1, check-stage2
This commit is contained in:
bors 2015-02-27 23:15:17 +00:00
commit e233987ce1
57 changed files with 952 additions and 131 deletions

View file

@ -302,7 +302,7 @@ nonzero_dec: '1' | '2' | '3' | '4'
A _character literal_ is a single Unicode character enclosed within two A _character literal_ is a single Unicode character enclosed within two
`U+0027` (single-quote) characters, with the exception of `U+0027` itself, `U+0027` (single-quote) characters, with the exception of `U+0027` itself,
which must be _escaped_ by a preceding U+005C character (`\`). which must be _escaped_ by a preceding `U+005C` character (`\`).
##### String literals ##### String literals
@ -311,6 +311,19 @@ A _string literal_ is a sequence of any Unicode characters enclosed within two
which must be _escaped_ by a preceding `U+005C` character (`\`), or a _raw which must be _escaped_ by a preceding `U+005C` character (`\`), or a _raw
string literal_. string literal_.
A multi-line string literal may be defined by terminating each line with a
`U+005C` character (`\`) immediately before the newline. This causes the
`U+005C` character, the newline, and all whitespace at the beginning of the
next line to be ignored.
```rust
let a = "foobar";
let b = "foo\
bar";
assert_eq!(a,b);
```
##### Character escapes ##### Character escapes
Some additional _escapes_ are available in either character or non-raw string Some additional _escapes_ are available in either character or non-raw string

View file

@ -18,13 +18,15 @@ the Cargo
README](https://github.com/rust-lang/cargo#installing-cargo-from-nightlies) README](https://github.com/rust-lang/cargo#installing-cargo-from-nightlies)
for specific instructions about installing it. for specific instructions about installing it.
## Converting to Cargo
Let's convert Hello World to Cargo. Let's convert Hello World to Cargo.
To Cargo-ify our project, we need to do two things: Make a `Cargo.toml` To Cargo-ify our project, we need to do two things: Make a `Cargo.toml`
configuration file, and put our source file in the right place. Let's configuration file, and put our source file in the right place. Let's
do that part first: do that part first:
```{bash} ```bash
$ mkdir src $ mkdir src
$ mv main.rs src/main.rs $ mv main.rs src/main.rs
``` ```
@ -36,7 +38,7 @@ place for everything, and everything in its place.
Next, our configuration file: Next, our configuration file:
```{bash} ```bash
$ editor Cargo.toml $ editor Cargo.toml
``` ```
@ -73,7 +75,7 @@ well as what it is named.
Once you have this file in place, we should be ready to build! Try this: Once you have this file in place, we should be ready to build! Try this:
```{bash} ```bash
$ cargo build $ cargo build
Compiling hello_world v0.0.1 (file:///home/yourname/projects/hello_world) Compiling hello_world v0.0.1 (file:///home/yourname/projects/hello_world)
$ ./target/hello_world $ ./target/hello_world
@ -103,6 +105,62 @@ That's it! We've successfully built `hello_world` with Cargo. Even though our
program is simple, it's using much of the real tooling that you'll use for the program is simple, it's using much of the real tooling that you'll use for the
rest of your Rust career. rest of your Rust career.
## A New Project
You don't have to go through this whole process every time you want to start a new
project! Cargo has the ability to make a bare-bones project directory in which you
can start developing right away.
To start a new project with Cargo, use `cargo new`:
```bash
$ cargo new hello_world --bin
```
We're passing `--bin` because we're making a binary program: if we
were making a library, we'd leave it off.
Let's check out what Cargo has generated for us:
```bash
$ cd hello_world
$ tree .
.
├── Cargo.toml
└── src
└── main.rs
1 directory, 2 files
```
If you don't have the `tree` command, you can probably get it from your distro's package
manager. It's not necessary, but it's certainly useful.
This is all we need to get started. First, let's check out `Cargo.toml`:
```toml
[package]
name = "hello_world"
version = "0.0.1"
authors = ["Your Name <you@example.com>"]
```
Cargo has populated this file with reasonable defaults based off the arguments you gave
it and your `git` global configuration. You may notice that Cargo has also initialized
the `hello_world` directory as a `git` repository.
Here's what's in `src/main.rs`:
```rust
fn main() {
println!("Hello, world!");
}
```
Cargo has generated a "Hello World!" for us, and you're ready to start coding! A
much more in-depth guide to Cargo can be found [here](http://doc.crates.io/guide.html).
Now that you've got the tools down, let's actually learn more about the Rust Now that you've got the tools down, let's actually learn more about the Rust
language itself. These are the basics that will serve you well through the rest language itself. These are the basics that will serve you well through the rest
of your time with Rust. of your time with Rust.

View file

@ -300,7 +300,7 @@ mod imp {
libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8 libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8
} else { } else {
let new_ptr = allocate(size, align); let new_ptr = allocate(size, align);
ptr::copy_memory(new_ptr, ptr, cmp::min(size, old_size)); ptr::copy(new_ptr, ptr, cmp::min(size, old_size));
deallocate(ptr, old_size, align); deallocate(ptr, old_size, align);
new_ptr new_ptr
} }

View file

@ -2663,7 +2663,7 @@ mod tests {
let (left, right) = values.split_at_mut(2); let (left, right) = values.split_at_mut(2);
{ {
let left: &[_] = left; let left: &[_] = left;
assert!(left[..left.len()] == [1, 2][]); assert!(left[..left.len()] == [1, 2]);
} }
for p in left { for p in left {
*p += 1; *p += 1;
@ -2671,7 +2671,7 @@ mod tests {
{ {
let right: &[_] = right; let right: &[_] = right;
assert!(right[..right.len()] == [3, 4, 5][]); assert!(right[..right.len()] == [3, 4, 5]);
} }
for p in right { for p in right {
*p += 2; *p += 2;

View file

@ -2093,7 +2093,7 @@ mod tests {
let (left, right) = values.split_at_mut(2); let (left, right) = values.split_at_mut(2);
{ {
let left: &[_] = left; let left: &[_] = left;
assert!(&left[..left.len()] == &[1, 2][]); assert!(&left[..left.len()] == &[1, 2]);
} }
for p in left { for p in left {
*p += 1; *p += 1;
@ -2101,7 +2101,7 @@ mod tests {
{ {
let right: &[_] = right; let right: &[_] = right;
assert!(&right[..right.len()] == &[3, 4, 5][]); assert!(&right[..right.len()] == &[3, 4, 5]);
} }
for p in right { for p in right {
*p += 2; *p += 2;

View file

@ -241,7 +241,12 @@ extern "rust-intrinsic" {
/// will trigger a compiler error. /// will trigger a compiler error.
pub fn return_address() -> *const u8; pub fn return_address() -> *const u8;
/// Returns `true` if a type requires drop glue. /// Returns `true` if the actual type given as `T` requires drop
/// glue; returns `false` if the actual type provided for `T`
/// implements `Copy`.
///
/// If the actual type neither requires drop glue nor implements
/// `Copy`, then may return `true` or `false`.
pub fn needs_drop<T>() -> bool; pub fn needs_drop<T>() -> bool;
/// Returns `true` if a type is managed (will be allocated on the local heap) /// Returns `true` if a type is managed (will be allocated on the local heap)

View file

@ -171,8 +171,7 @@ pub trait IteratorExt: Iterator + Sized {
self.fold(0, |cnt, _x| cnt + 1) self.fold(0, |cnt, _x| cnt + 1)
} }
/// Loops through the entire iterator, returning the last element of the /// Loops through the entire iterator, returning the last element.
/// iterator.
/// ///
/// # Examples /// # Examples
/// ///
@ -637,8 +636,8 @@ pub trait IteratorExt: Iterator + Sized {
/// ``` /// ```
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
fn all<F>(self, mut f: F) -> bool where F: FnMut(Self::Item) -> bool { fn all<F>(&mut self, mut f: F) -> bool where F: FnMut(Self::Item) -> bool {
for x in self { if !f(x) { return false; } } for x in self.by_ref() { if !f(x) { return false; } }
true true
} }
@ -1637,8 +1636,6 @@ impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool
for x in self.iter.by_ref() { for x in self.iter.by_ref() {
if (self.predicate)(&x) { if (self.predicate)(&x) {
return Some(x); return Some(x);
} else {
continue
} }
} }
None None

View file

@ -275,7 +275,13 @@ macro_rules! impls{
/// any methods, but instead is used to gate access to data. /// any methods, but instead is used to gate access to data.
/// ///
/// FIXME. Better documentation needed here! /// FIXME. Better documentation needed here!
pub trait MarkerTrait : PhantomFn<Self> { } pub trait MarkerTrait : PhantomFn<Self,Self> { }
// ~~~~~ <-- FIXME(#22806)?
//
// Marker trait has been made invariant so as to avoid inf recursion,
// but we should ideally solve the underlying problem. That's a bit
// complicated.
impl<T:?Sized> MarkerTrait for T { } impl<T:?Sized> MarkerTrait for T { }
/// `PhantomFn` is a marker trait for use with traits that contain /// `PhantomFn` is a marker trait for use with traits that contain

View file

@ -641,9 +641,9 @@ impl<T, E> Result<T, E> {
/// ``` /// ```
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn or(self, res: Result<T, E>) -> Result<T, E> { pub fn or<F>(self, res: Result<T, F>) -> Result<T, F> {
match self { match self {
Ok(_) => self, Ok(v) => Ok(v),
Err(_) => res, Err(_) => res,
} }
} }

View file

@ -939,6 +939,7 @@ impl<'a, P: Pattern<'a>> Iterator for SplitStr<'a, P> {
type Item = &'a str; type Item = &'a str;
#[inline] #[inline]
#[allow(deprecated)]
fn next(&mut self) -> Option<&'a str> { fn next(&mut self) -> Option<&'a str> {
Iterator::next(&mut self.0) Iterator::next(&mut self.0)
} }

View file

@ -36,10 +36,10 @@ pub fn test_and_then() {
#[test] #[test]
pub fn test_or() { pub fn test_or() {
assert_eq!(op1().or(Ok(667)).unwrap(), 666); assert_eq!(op1().or(Ok::<_, &'static str>(667)).unwrap(), 666);
assert_eq!(op1().or(Err("bad")).unwrap(), 666); assert_eq!(op1().or(Err("bad")).unwrap(), 666);
assert_eq!(op2().or(Ok(667)).unwrap(), 667); assert_eq!(op2().or(Ok::<_, &'static str>(667)).unwrap(), 667);
assert_eq!(op2().or(Err("bad")).unwrap_err(), "bad"); assert_eq!(op2().or(Err("bad")).unwrap_err(), "bad");
} }

View file

@ -59,16 +59,16 @@ fn iterator_to_slice() {
let mut iter = data.iter_mut(); let mut iter = data.iter_mut();
assert_eq!(&iter[..], &other_data[..]); assert_eq!(&iter[..], &other_data[..]);
// mutability: // mutability:
assert!(&mut iter[] == other_data); assert!(&mut iter[..] == other_data);
iter.next(); iter.next();
assert_eq!(&iter[..], &other_data[1..]); assert_eq!(&iter[..], &other_data[1..]);
assert!(&mut iter[] == &mut other_data[1..]); assert!(&mut iter[..] == &mut other_data[1..]);
iter.next_back(); iter.next_back();
assert_eq!(&iter[..], &other_data[1..2]); assert_eq!(&iter[..], &other_data[1..2]);
assert!(&mut iter[] == &mut other_data[1..2]); assert!(&mut iter[..] == &mut other_data[1..2]);
let s = iter.into_slice(); let s = iter.into_slice();
assert!(s == &mut other_data[1..2]); assert!(s == &mut other_data[1..2]);

View file

@ -134,11 +134,7 @@ pub trait Reseeder<R> {
/// Reseed an RNG using a `Default` instance. This reseeds by /// Reseed an RNG using a `Default` instance. This reseeds by
/// replacing the RNG with the result of a `Default::default` call. /// replacing the RNG with the result of a `Default::default` call.
#[derive(Copy)] #[derive(Copy)]
pub struct ReseedWithDefault { __hack: [u8; 0] } pub struct ReseedWithDefault;
// FIXME(#21721) used to be an unit struct but that can cause
// certain LLVM versions to abort during optimizations.
#[allow(non_upper_case_globals)]
pub const ReseedWithDefault: ReseedWithDefault = ReseedWithDefault { __hack: [] };
impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault { impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault {
fn reseed(&mut self, rng: &mut R) { fn reseed(&mut self, rng: &mut R) {

View file

@ -1771,6 +1771,11 @@ impl LintPass for Stability {
stability::check_path(cx.tcx, path, id, stability::check_path(cx.tcx, path, id,
&mut |id, sp, stab| self.lint(cx, id, sp, stab)); &mut |id, sp, stab| self.lint(cx, id, sp, stab));
} }
fn check_pat(&mut self, cx: &Context, pat: &ast::Pat) {
stability::check_pat(cx.tcx, pat,
&mut |id, sp, stab| self.lint(cx, id, sp, stab))
}
} }
declare_lint! { declare_lint! {

View file

@ -68,7 +68,7 @@ pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
Some(d) => d.full_def() Some(d) => d.full_def()
}; };
if let def::DefPrimTy(nty) = def { if let def::DefPrimTy(nty) = def {
Some(prim_ty_to_ty(tcx, &path.segments[], nty)) Some(prim_ty_to_ty(tcx, &path.segments, nty))
} else { } else {
None None
} }
@ -76,4 +76,3 @@ pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
None None
} }
} }

View file

@ -58,8 +58,10 @@ impl<'a> Annotator<'a> {
attrs: &Vec<Attribute>, item_sp: Span, f: F, required: bool) where attrs: &Vec<Attribute>, item_sp: Span, f: F, required: bool) where
F: FnOnce(&mut Annotator), F: FnOnce(&mut Annotator),
{ {
debug!("annotate(id = {:?}, attrs = {:?})", id, attrs);
match attr::find_stability(self.sess.diagnostic(), attrs, item_sp) { match attr::find_stability(self.sess.diagnostic(), attrs, item_sp) {
Some(stab) => { Some(stab) => {
debug!("annotate: found {:?}", stab);
self.index.local.insert(id, stab.clone()); self.index.local.insert(id, stab.clone());
// Don't inherit #[stable(feature = "rust1", since = "1.0.0")] // Don't inherit #[stable(feature = "rust1", since = "1.0.0")]
@ -72,6 +74,8 @@ impl<'a> Annotator<'a> {
} }
} }
None => { None => {
debug!("annotate: not found, use_parent = {:?}, parent = {:?}",
use_parent, self.parent);
if use_parent { if use_parent {
if let Some(stab) = self.parent.clone() { if let Some(stab) = self.parent.clone() {
self.index.local.insert(id, stab); self.index.local.insert(id, stab);
@ -299,6 +303,12 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
&mut |id, sp, stab| self.check(id, sp, stab)); &mut |id, sp, stab| self.check(id, sp, stab));
visit::walk_path(self, path) visit::walk_path(self, path)
} }
fn visit_pat(&mut self, pat: &ast::Pat) {
check_pat(self.tcx, pat,
&mut |id, sp, stab| self.check(id, sp, stab));
visit::walk_pat(self, pat)
}
} }
/// Helper for discovering nodes to check for stability /// Helper for discovering nodes to check for stability
@ -385,6 +395,76 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
None => return None => return
} }
} }
ast::ExprField(ref base_e, ref field) => {
span = field.span;
match ty::expr_ty_adjusted(tcx, base_e).sty {
ty::ty_struct(did, _) => {
ty::lookup_struct_fields(tcx, did)
.iter()
.find(|f| f.name == field.node.name)
.unwrap_or_else(|| {
tcx.sess.span_bug(field.span,
"stability::check_expr: unknown named field access")
})
.id
}
_ => tcx.sess.span_bug(e.span,
"stability::check_expr: named field access on non-struct")
}
}
ast::ExprTupField(ref base_e, ref field) => {
span = field.span;
match ty::expr_ty_adjusted(tcx, base_e).sty {
ty::ty_struct(did, _) => {
ty::lookup_struct_fields(tcx, did)
.get(field.node)
.unwrap_or_else(|| {
tcx.sess.span_bug(field.span,
"stability::check_expr: unknown unnamed field access")
})
.id
}
ty::ty_tup(..) => return,
_ => tcx.sess.span_bug(e.span,
"stability::check_expr: unnamed field access on \
something other than a tuple or struct")
}
}
ast::ExprStruct(_, ref expr_fields, _) => {
let type_ = ty::expr_ty(tcx, e);
match type_.sty {
ty::ty_struct(did, _) => {
let struct_fields = ty::lookup_struct_fields(tcx, did);
// check the stability of each field that appears
// in the construction expression.
for field in expr_fields {
let did = struct_fields
.iter()
.find(|f| f.name == field.ident.node.name)
.unwrap_or_else(|| {
tcx.sess.span_bug(field.span,
"stability::check_expr: unknown named \
field access")
})
.id;
maybe_do_stability_check(tcx, did, field.span, cb);
}
// we're done.
return
}
// we don't look at stability attributes on
// struct-like enums (yet...), but it's definitely not
// a bug to have construct one.
ty::ty_enum(..) => return,
_ => {
tcx.sess.span_bug(e.span,
&format!("stability::check_expr: struct construction \
of non-struct, type {:?}",
type_.repr(tcx)));
}
}
}
_ => return _ => return
}; };
@ -403,6 +483,47 @@ pub fn check_path(tcx: &ty::ctxt, path: &ast::Path, id: ast::NodeId,
} }
pub fn check_pat(tcx: &ty::ctxt, pat: &ast::Pat,
cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
debug!("check_pat(pat = {:?})", pat);
if is_internal(tcx, pat.span) { return; }
let did = match ty::pat_ty_opt(tcx, pat) {
Some(&ty::TyS { sty: ty::ty_struct(did, _), .. }) => did,
Some(_) | None => return,
};
let struct_fields = ty::lookup_struct_fields(tcx, did);
match pat.node {
// Foo(a, b, c)
ast::PatEnum(_, Some(ref pat_fields)) => {
for (field, struct_field) in pat_fields.iter().zip(struct_fields.iter()) {
// a .. pattern is fine, but anything positional is
// not.
if let ast::PatWild(ast::PatWildMulti) = field.node {
continue
}
maybe_do_stability_check(tcx, struct_field.id, field.span, cb)
}
}
// Foo { a, b, c }
ast::PatStruct(_, ref pat_fields, _) => {
for field in pat_fields {
let did = struct_fields
.iter()
.find(|f| f.name == field.node.ident.name)
.unwrap_or_else(|| {
tcx.sess.span_bug(field.span,
"stability::check_pat: unknown named field access")
})
.id;
maybe_do_stability_check(tcx, did, field.span, cb);
}
}
// everything else is fine.
_ => {}
}
}
fn maybe_do_stability_check(tcx: &ty::ctxt, id: ast::DefId, span: Span, fn maybe_do_stability_check(tcx: &ty::ctxt, id: ast::DefId, span: Span,
cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) { cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
if !is_staged_api(tcx, id) { return } if !is_staged_api(tcx, id) { return }

View file

@ -3896,7 +3896,7 @@ pub fn is_type_representable<'tcx>(cx: &ctxt<'tcx>, sp: Span, ty: Ty<'tcx>)
let types_a = substs_a.types.get_slice(subst::TypeSpace); let types_a = substs_a.types.get_slice(subst::TypeSpace);
let types_b = substs_b.types.get_slice(subst::TypeSpace); let types_b = substs_b.types.get_slice(subst::TypeSpace);
let pairs = types_a.iter().zip(types_b.iter()); let mut pairs = types_a.iter().zip(types_b.iter());
pairs.all(|(&a, &b)| same_type(a, b)) pairs.all(|(&a, &b)| same_type(a, b))
} }
@ -4298,6 +4298,9 @@ pub fn free_region_from_def(outlives_extent: region::DestructionScopeData,
pub fn pat_ty<'tcx>(cx: &ctxt<'tcx>, pat: &ast::Pat) -> Ty<'tcx> { pub fn pat_ty<'tcx>(cx: &ctxt<'tcx>, pat: &ast::Pat) -> Ty<'tcx> {
return node_id_to_type(cx, pat.id); return node_id_to_type(cx, pat.id);
} }
pub fn pat_ty_opt<'tcx>(cx: &ctxt<'tcx>, pat: &ast::Pat) -> Option<Ty<'tcx>> {
return node_id_to_type_opt(cx, pat.id);
}
// Returns the type of an expression as a monotype. // Returns the type of an expression as a monotype.

View file

@ -233,6 +233,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
ast::ItemEnum(ref def, _) if public_first => { ast::ItemEnum(ref def, _) if public_first => {
for variant in &def.variants { for variant in &def.variants {
self.exported_items.insert(variant.node.id); self.exported_items.insert(variant.node.id);
self.public_items.insert(variant.node.id);
} }
} }
@ -321,6 +322,15 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
Some(id) => { self.exported_items.insert(id); } Some(id) => { self.exported_items.insert(id); }
None => {} None => {}
} }
// fields can be public or private, so lets check
for field in &def.fields {
let vis = match field.node.kind {
ast::NamedField(_, vis) | ast::UnnamedField(vis) => vis
};
if vis == ast::Public {
self.public_items.insert(field.node.id);
}
}
} }
ast::ItemTy(ref ty, _) if public_first => { ast::ItemTy(ref ty, _) if public_first => {

View file

@ -2985,7 +2985,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
} else { } else {
let msg = format!("use of undeclared trait name `{}`", let msg = format!("use of undeclared trait name `{}`",
self.path_names_to_string(trait_path, path_depth)); self.path_names_to_string(trait_path, path_depth));
self.resolve_error(trait_path.span, &msg[]); self.resolve_error(trait_path.span, &msg);
Err(()) Err(())
} }
} }

View file

@ -1499,6 +1499,7 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
fn create_dummy_locals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, fn create_dummy_locals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
pat: &ast::Pat) pat: &ast::Pat)
-> Block<'blk, 'tcx> { -> Block<'blk, 'tcx> {
let _icx = push_ctxt("create_dummy_locals");
// create dummy memory for the variables if we have no // create dummy memory for the variables if we have no
// value to store into them immediately // value to store into them immediately
let tcx = bcx.tcx(); let tcx = bcx.tcx();

View file

@ -734,7 +734,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
}; };
if !is_rust_fn || if !is_rust_fn ||
type_of::return_uses_outptr(ccx, ret_ty) || type_of::return_uses_outptr(ccx, ret_ty) ||
common::type_needs_drop(bcx.tcx(), ret_ty) { bcx.fcx.type_needs_drop(ret_ty) {
// Push the out-pointer if we use an out-pointer for this // Push the out-pointer if we use an out-pointer for this
// return type, otherwise push "undef". // return type, otherwise push "undef".
if common::type_is_zero_size(ccx, ret_ty) { if common::type_is_zero_size(ccx, ret_ty) {

View file

@ -386,7 +386,7 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
cleanup_scope: ScopeId, cleanup_scope: ScopeId,
val: ValueRef, val: ValueRef,
ty: Ty<'tcx>) { ty: Ty<'tcx>) {
if !common::type_needs_drop(self.ccx.tcx(), ty) { return; } if !self.type_needs_drop(ty) { return; }
let drop = box DropValue { let drop = box DropValue {
is_immediate: false, is_immediate: false,
must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty), must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty),
@ -408,7 +408,8 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
cleanup_scope: ScopeId, cleanup_scope: ScopeId,
val: ValueRef, val: ValueRef,
ty: Ty<'tcx>) { ty: Ty<'tcx>) {
if !common::type_needs_drop(self.ccx.tcx(), ty) { return; } if !self.type_needs_drop(ty) { return; }
let drop = box DropValue { let drop = box DropValue {
is_immediate: false, is_immediate: false,
must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty), must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty),
@ -432,7 +433,7 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
val: ValueRef, val: ValueRef,
ty: Ty<'tcx>) { ty: Ty<'tcx>) {
if !common::type_needs_drop(self.ccx.tcx(), ty) { return; } if !self.type_needs_drop(ty) { return; }
let drop = box DropValue { let drop = box DropValue {
is_immediate: true, is_immediate: true,
must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty), must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty),
@ -1007,6 +1008,7 @@ impl<'tcx> Cleanup<'tcx> for DropValue<'tcx> {
bcx: Block<'blk, 'tcx>, bcx: Block<'blk, 'tcx>,
debug_loc: DebugLoc) debug_loc: DebugLoc)
-> Block<'blk, 'tcx> { -> Block<'blk, 'tcx> {
let _icx = base::push_ctxt("<DropValue as Cleanup>::trans");
let bcx = if self.is_immediate { let bcx = if self.is_immediate {
glue::drop_ty_immediate(bcx, self.val, self.ty, debug_loc) glue::drop_ty_immediate(bcx, self.val, self.ty, debug_loc)
} else { } else {

View file

@ -213,8 +213,43 @@ pub fn type_needs_unwind_cleanup<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<
} }
} }
/// If `type_needs_drop` returns true, then `ty` is definitely
/// non-copy and *might* have a destructor attached; if it returns
/// false, then `ty` definitely has no destructor (i.e. no drop glue).
///
/// (Note that this implies that if `ty` has a destructor attached,
/// then `type_needs_drop` will definitely return `true` for `ty`.)
pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
ty::type_contents(cx, ty).needs_drop(cx) type_needs_drop_given_env(cx, ty, &ty::empty_parameter_environment(cx))
}
/// Core implementation of type_needs_drop, potentially making use of
/// and/or updating caches held in the `param_env`.
fn type_needs_drop_given_env<'a,'tcx>(cx: &ty::ctxt<'tcx>,
ty: Ty<'tcx>,
param_env: &ty::ParameterEnvironment<'a,'tcx>) -> bool {
// Issue #22536: We first query type_moves_by_default. It sees a
// normalized version of the type, and therefore will definitely
// know whether the type implements Copy (and thus needs no
// cleanup/drop/zeroing) ...
let implements_copy = !ty::type_moves_by_default(&param_env, DUMMY_SP, ty);
if implements_copy { return false; }
// ... (issue #22536 continued) but as an optimization, still use
// prior logic of asking if the `needs_drop` bit is set; we need
// not zero non-Copy types if they have no destructor.
// FIXME(#22815): Note that calling `ty::type_contents` is a
// conservative heuristic; it may report that `needs_drop` is set
// when actual type does not actually have a destructor associated
// with it. But since `ty` absolutely did not have the `Copy`
// bound attached (see above), it is sound to treat it as having a
// destructor (e.g. zero its memory on move).
let contents = ty::type_contents(cx, ty);
debug!("type_needs_drop ty={} contents={:?}", ty.repr(cx), contents);
contents.needs_drop(cx)
} }
fn type_is_newtype_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { fn type_is_newtype_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
@ -534,6 +569,12 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
self.param_substs, self.param_substs,
value) value)
} }
/// This is the same as `common::type_needs_drop`, except that it
/// may use or update caches within this `FunctionContext`.
pub fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
type_needs_drop_given_env(self.ccx.tcx(), ty, &self.param_env)
}
} }
// Basic block context. We create a block context for each basic block // Basic block context. We create a block context for each basic block

View file

@ -77,7 +77,7 @@ pub fn trans_stmt_semi<'blk, 'tcx>(cx: Block<'blk, 'tcx>, e: &ast::Expr)
-> Block<'blk, 'tcx> { -> Block<'blk, 'tcx> {
let _icx = push_ctxt("trans_stmt_semi"); let _icx = push_ctxt("trans_stmt_semi");
let ty = expr_ty(cx, e); let ty = expr_ty(cx, e);
if type_needs_drop(cx.tcx(), ty) { if cx.fcx.type_needs_drop(ty) {
expr::trans_to_lvalue(cx, e, "stmt").bcx expr::trans_to_lvalue(cx, e, "stmt").bcx
} else { } else {
expr::trans_into(cx, e, expr::Ignore) expr::trans_into(cx, e, expr::Ignore)

View file

@ -311,7 +311,8 @@ impl KindOps for Lvalue {
val: ValueRef, val: ValueRef,
ty: Ty<'tcx>) ty: Ty<'tcx>)
-> Block<'blk, 'tcx> { -> Block<'blk, 'tcx> {
if type_needs_drop(bcx.tcx(), ty) { let _icx = push_ctxt("<Lvalue as KindOps>::post_store");
if bcx.fcx.type_needs_drop(ty) {
// cancel cleanup of affine values by zeroing out // cancel cleanup of affine values by zeroing out
let () = zero_mem(bcx, val, ty); let () = zero_mem(bcx, val, ty);
bcx bcx
@ -656,7 +657,7 @@ impl<'tcx, K: KindOps + fmt::Debug> Datum<'tcx, K> {
/// scalar-ish (like an int or a pointer) which (1) does not require drop glue and (2) is /// scalar-ish (like an int or a pointer) which (1) does not require drop glue and (2) is
/// naturally passed around by value, and not by reference. /// naturally passed around by value, and not by reference.
pub fn to_llscalarish<'blk>(self, bcx: Block<'blk, 'tcx>) -> ValueRef { pub fn to_llscalarish<'blk>(self, bcx: Block<'blk, 'tcx>) -> ValueRef {
assert!(!type_needs_drop(bcx.tcx(), self.ty)); assert!(!bcx.fcx.type_needs_drop(self.ty));
assert!(self.appropriate_rvalue_mode(bcx.ccx()) == ByValue); assert!(self.appropriate_rvalue_mode(bcx.ccx()) == ByValue);
if self.kind.is_by_ref() { if self.kind.is_by_ref() {
load_ty(bcx, self.val, self.ty) load_ty(bcx, self.val, self.ty)

View file

@ -974,7 +974,7 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let src_datum = unpack_datum!(bcx, trans(bcx, &**src)); let src_datum = unpack_datum!(bcx, trans(bcx, &**src));
let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &**dst, "assign")); let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &**dst, "assign"));
if type_needs_drop(bcx.tcx(), dst_datum.ty) { if bcx.fcx.type_needs_drop(dst_datum.ty) {
// If there are destructors involved, make sure we // If there are destructors involved, make sure we
// are copying from an rvalue, since that cannot possible // are copying from an rvalue, since that cannot possible
// alias an lvalue. We are concerned about code like: // alias an lvalue. We are concerned about code like:
@ -1498,7 +1498,7 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
assert_eq!(discr, 0); assert_eq!(discr, 0);
match ty::expr_kind(bcx.tcx(), &*base.expr) { match ty::expr_kind(bcx.tcx(), &*base.expr) {
ty::RvalueDpsExpr | ty::RvalueDatumExpr if !type_needs_drop(bcx.tcx(), ty) => { ty::RvalueDpsExpr | ty::RvalueDatumExpr if !bcx.fcx.type_needs_drop(ty) => {
bcx = trans_into(bcx, &*base.expr, SaveIn(addr)); bcx = trans_into(bcx, &*base.expr, SaveIn(addr));
}, },
ty::RvalueStmtExpr => bcx.tcx().sess.bug("unexpected expr kind for struct base expr"), ty::RvalueStmtExpr => bcx.tcx().sess.bug("unexpected expr kind for struct base expr"),
@ -2116,7 +2116,7 @@ fn trans_assign_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// Evaluate LHS (destination), which should be an lvalue // Evaluate LHS (destination), which should be an lvalue
let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, dst, "assign_op")); let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, dst, "assign_op"));
assert!(!type_needs_drop(bcx.tcx(), dst_datum.ty)); assert!(!bcx.fcx.type_needs_drop(dst_datum.ty));
let dst_ty = dst_datum.ty; let dst_ty = dst_datum.ty;
let dst = load_ty(bcx, dst_datum.val, dst_datum.ty); let dst = load_ty(bcx, dst_datum.val, dst_datum.ty);

View file

@ -99,6 +99,16 @@ pub fn get_drop_glue_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
if !type_is_sized(tcx, t) { if !type_is_sized(tcx, t) {
return t return t
} }
// FIXME (#22815): note that type_needs_drop conservatively
// approximates in some cases and may say a type expression
// requires drop glue when it actually does not.
//
// (In this case it is not clear whether any harm is done, i.e.
// erroneously returning `t` in some cases where we could have
// returned `tcx.types.i8` does not appear unsound. The impact on
// code quality is unknown at this time.)
if !type_needs_drop(tcx, t) { if !type_needs_drop(tcx, t) {
return tcx.types.i8; return tcx.types.i8;
} }
@ -125,7 +135,7 @@ pub fn drop_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// NB: v is an *alias* of type t here, not a direct value. // NB: v is an *alias* of type t here, not a direct value.
debug!("drop_ty(t={})", t.repr(bcx.tcx())); debug!("drop_ty(t={})", t.repr(bcx.tcx()));
let _icx = push_ctxt("drop_ty"); let _icx = push_ctxt("drop_ty");
if type_needs_drop(bcx.tcx(), t) { if bcx.fcx.type_needs_drop(t) {
let ccx = bcx.ccx(); let ccx = bcx.ccx();
let glue = get_drop_glue(ccx, t); let glue = get_drop_glue(ccx, t);
let glue_type = get_drop_glue_type(ccx, t); let glue_type = get_drop_glue_type(ccx, t);
@ -480,7 +490,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>)
}, },
_ => { _ => {
assert!(type_is_sized(bcx.tcx(), t)); assert!(type_is_sized(bcx.tcx(), t));
if type_needs_drop(bcx.tcx(), t) && ty::type_is_structural(t) { if bcx.fcx.type_needs_drop(t) && ty::type_is_structural(t) {
iter_structural_ty(bcx, iter_structural_ty(bcx,
v0, v0,
t, t,

View file

@ -156,6 +156,8 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
let ccx = fcx.ccx; let ccx = fcx.ccx;
let tcx = bcx.tcx(); let tcx = bcx.tcx();
let _icx = push_ctxt("trans_intrinsic_call");
let ret_ty = match callee_ty.sty { let ret_ty = match callee_ty.sty {
ty::ty_bare_fn(_, ref f) => { ty::ty_bare_fn(_, ref f) => {
ty::erase_late_bound_regions(bcx.tcx(), &f.sig.output()) ty::erase_late_bound_regions(bcx.tcx(), &f.sig.output())
@ -376,7 +378,8 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
} }
(_, "needs_drop") => { (_, "needs_drop") => {
let tp_ty = *substs.types.get(FnSpace, 0); let tp_ty = *substs.types.get(FnSpace, 0);
C_bool(ccx, type_needs_drop(ccx.tcx(), tp_ty))
C_bool(ccx, bcx.fcx.type_needs_drop(tp_ty))
} }
(_, "owns_managed") => { (_, "owns_managed") => {
let tp_ty = *substs.types.get(FnSpace, 0); let tp_ty = *substs.types.get(FnSpace, 0);

View file

@ -454,7 +454,7 @@ fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let self_datum = unpack_datum!( let self_datum = unpack_datum!(
bcx, expr::trans(bcx, self_expr)); bcx, expr::trans(bcx, self_expr));
let llval = if type_needs_drop(bcx.tcx(), self_datum.ty) { let llval = if bcx.fcx.type_needs_drop(self_datum.ty) {
let self_datum = unpack_datum!( let self_datum = unpack_datum!(
bcx, self_datum.to_rvalue_datum(bcx, "trait_callee")); bcx, self_datum.to_rvalue_datum(bcx, "trait_callee"));

View file

@ -53,11 +53,10 @@ pub fn make_drop_glue_unboxed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let not_null = IsNotNull(bcx, vptr); let not_null = IsNotNull(bcx, vptr);
with_cond(bcx, not_null, |bcx| { with_cond(bcx, not_null, |bcx| {
let ccx = bcx.ccx(); let ccx = bcx.ccx();
let tcx = bcx.tcx();
let _icx = push_ctxt("tvec::make_drop_glue_unboxed"); let _icx = push_ctxt("tvec::make_drop_glue_unboxed");
let dataptr = get_dataptr(bcx, vptr); let dataptr = get_dataptr(bcx, vptr);
let bcx = if type_needs_drop(tcx, unit_ty) { let bcx = if bcx.fcx.type_needs_drop(unit_ty) {
let len = get_len(bcx, vptr); let len = get_len(bcx, vptr);
iter_vec_raw(bcx, iter_vec_raw(bcx,
dataptr, dataptr,

View file

@ -991,6 +991,17 @@ fn trait_ref_to_object_type<'tcx>(this: &AstConv<'tcx>,
result result
} }
fn report_ambiguous_associated_type(tcx: &ty::ctxt,
span: Span,
type_str: &str,
trait_str: &str,
name: &str) {
span_err!(tcx.sess, span, E0223,
"ambiguous associated type; specify the type using the syntax \
`<{} as {}>::{}`",
type_str, trait_str, name);
}
fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>, fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
span: Span, span: Span,
ty: Ty<'tcx>, ty: Ty<'tcx>,
@ -1011,10 +1022,8 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
let ty_param_node_id = if is_param { let ty_param_node_id = if is_param {
ty_path_def.local_node_id() ty_path_def.local_node_id()
} else { } else {
span_err!(tcx.sess, span, E0223, report_ambiguous_associated_type(
"ambiguous associated type; specify the type using the syntax \ tcx, span, &ty.user_string(tcx), "Trait", &token::get_name(assoc_name));
`<{} as Trait>::{}`",
ty.user_string(tcx), token::get_name(assoc_name));
return (tcx.types.err, ty_path_def); return (tcx.types.err, ty_path_def);
}; };
@ -1109,10 +1118,8 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
ty ty
} else { } else {
let path_str = ty::item_path_str(tcx, trait_def_id); let path_str = ty::item_path_str(tcx, trait_def_id);
span_err!(tcx.sess, span, E0223, report_ambiguous_associated_type(
"ambiguous associated type; specify the type using the syntax \ tcx, span, "Type", &path_str, &token::get_ident(item_segment.identifier));
`<Type as {}>::{}`",
path_str, &token::get_ident(item_segment.identifier));
return tcx.types.err; return tcx.types.err;
}; };

View file

@ -3945,9 +3945,7 @@ mod tests {
#[test] #[test]
fn test_encode_hashmap_with_arbitrary_key() { fn test_encode_hashmap_with_arbitrary_key() {
use std::old_io::Writer;
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt;
#[derive(PartialEq, Eq, Hash, RustcEncodable)] #[derive(PartialEq, Eq, Hash, RustcEncodable)]
struct ArbitraryType(uint); struct ArbitraryType(uint);
let mut hm: HashMap<ArbitraryType, bool> = HashMap::new(); let mut hm: HashMap<ArbitraryType, bool> = HashMap::new();

View file

@ -173,7 +173,7 @@ mod tests {
assert_eq!(writer.write(&[1, 2, 3]), Ok(3)); assert_eq!(writer.write(&[1, 2, 3]), Ok(3));
assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4)); assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4));
let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
assert_eq!(&writer.get_ref()[], b); assert_eq!(&writer.get_ref()[..], b);
} }
#[test] #[test]
@ -369,28 +369,28 @@ mod tests {
assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4)); assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4));
assert_eq!(writer.position(), 8); assert_eq!(writer.position(), 8);
let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
assert_eq!(&writer.get_ref()[], b); assert_eq!(&writer.get_ref()[..], b);
assert_eq!(writer.seek(SeekFrom::Start(0)), Ok(0)); assert_eq!(writer.seek(SeekFrom::Start(0)), Ok(0));
assert_eq!(writer.position(), 0); assert_eq!(writer.position(), 0);
assert_eq!(writer.write(&[3, 4]), Ok(2)); assert_eq!(writer.write(&[3, 4]), Ok(2));
let b: &[_] = &[3, 4, 2, 3, 4, 5, 6, 7]; let b: &[_] = &[3, 4, 2, 3, 4, 5, 6, 7];
assert_eq!(&writer.get_ref()[], b); assert_eq!(&writer.get_ref()[..], b);
assert_eq!(writer.seek(SeekFrom::Current(1)), Ok(3)); assert_eq!(writer.seek(SeekFrom::Current(1)), Ok(3));
assert_eq!(writer.write(&[0, 1]), Ok(2)); assert_eq!(writer.write(&[0, 1]), Ok(2));
let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 7]; let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 7];
assert_eq!(&writer.get_ref()[], b); assert_eq!(&writer.get_ref()[..], b);
assert_eq!(writer.seek(SeekFrom::End(-1)), Ok(7)); assert_eq!(writer.seek(SeekFrom::End(-1)), Ok(7));
assert_eq!(writer.write(&[1, 2]), Ok(2)); assert_eq!(writer.write(&[1, 2]), Ok(2));
let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2]; let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2];
assert_eq!(&writer.get_ref()[], b); assert_eq!(&writer.get_ref()[..], b);
assert_eq!(writer.seek(SeekFrom::End(1)), Ok(10)); assert_eq!(writer.seek(SeekFrom::End(1)), Ok(10));
assert_eq!(writer.write(&[1]), Ok(1)); assert_eq!(writer.write(&[1]), Ok(1));
let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1]; let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1];
assert_eq!(&writer.get_ref()[], b); assert_eq!(&writer.get_ref()[..], b);
} }
#[test] #[test]

View file

@ -102,6 +102,7 @@ impl MemWriter {
impl Writer for MemWriter { impl Writer for MemWriter {
#[inline] #[inline]
#[allow(deprecated)]
fn write_all(&mut self, buf: &[u8]) -> IoResult<()> { fn write_all(&mut self, buf: &[u8]) -> IoResult<()> {
self.buf.push_all(buf); self.buf.push_all(buf);
Ok(()) Ok(())

View file

@ -384,7 +384,7 @@ impl<T> !Sync for SyncSender<T> {}
/// contains the data being sent as a payload so it can be recovered. /// contains the data being sent as a payload so it can be recovered.
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[derive(PartialEq, Eq, Clone, Copy)] #[derive(PartialEq, Eq, Clone, Copy)]
pub struct SendError<T>(pub T); pub struct SendError<T>(#[stable(feature = "rust1", since = "1.0.0")] pub T);
/// An error returned from the `recv` function on a `Receiver`. /// An error returned from the `recv` function on a `Receiver`.
/// ///

View file

@ -291,29 +291,14 @@ fn mkstat(stat: &libc::stat) -> FileStat {
// FileStat times are in milliseconds // FileStat times are in milliseconds
fn mktime(secs: u64, nsecs: u64) -> u64 { secs * 1000 + nsecs / 1000000 } fn mktime(secs: u64, nsecs: u64) -> u64 { secs * 1000 + nsecs / 1000000 }
#[cfg(target_os = "bitrig")]
fn ctime(stat: &libc::stat) -> u64 {
mktime(stat.st_ctim.tv_sec as u64, stat.st_ctim.tv_nsec as u64)
}
#[cfg(not(target_os = "bitrig"))]
fn ctime(stat: &libc::stat) -> u64 { fn ctime(stat: &libc::stat) -> u64 {
mktime(stat.st_ctime as u64, stat.st_ctime_nsec as u64) mktime(stat.st_ctime as u64, stat.st_ctime_nsec as u64)
} }
#[cfg(target_os = "bitrig")]
fn atime(stat: &libc::stat) -> u64 {
mktime(stat.st_atim.tv_sec as u64, stat.st_atim.tv_nsec as u64)
}
#[cfg(not(target_os = "bitrig"))]
fn atime(stat: &libc::stat) -> u64 { fn atime(stat: &libc::stat) -> u64 {
mktime(stat.st_atime as u64, stat.st_atime_nsec as u64) mktime(stat.st_atime as u64, stat.st_atime_nsec as u64)
} }
#[cfg(target_os = "bitrig")]
fn mtime(stat: &libc::stat) -> u64 {
mktime(stat.st_mtim.tv_sec as u64, stat.st_mtim.tv_nsec as u64)
}
#[cfg(not(target_os = "bitrig"))]
fn mtime(stat: &libc::stat) -> u64 { fn mtime(stat: &libc::stat) -> u64 {
mktime(stat.st_mtime as u64, stat.st_mtime_nsec as u64) mktime(stat.st_mtime as u64, stat.st_mtime_nsec as u64)
} }

View file

@ -439,6 +439,7 @@ fn translate_status(status: c_int) -> ExitStatus {
target_os = "ios", target_os = "ios",
target_os = "freebsd", target_os = "freebsd",
target_os = "dragonfly", target_os = "dragonfly",
target_os = "bitrig",
target_os = "openbsd"))] target_os = "openbsd"))]
mod imp { mod imp {
pub fn WIFEXITED(status: i32) -> bool { (status & 0x7f) == 0 } pub fn WIFEXITED(status: i32) -> bool { (status & 0x7f) == 0 }

View file

@ -12,6 +12,8 @@ use ops::Sub;
use time::Duration; use time::Duration;
use sync::{Once, ONCE_INIT}; use sync::{Once, ONCE_INIT};
const NANOS_PER_SEC: i64 = 1_000_000_000;
pub struct SteadyTime { pub struct SteadyTime {
t: libc::LARGE_INTEGER, t: libc::LARGE_INTEGER,
} }
@ -24,7 +26,7 @@ impl SteadyTime {
} }
pub fn ns(&self) -> u64 { pub fn ns(&self) -> u64 {
self.t as u64 * 1_000_000_000 / frequency() as u64 mul_div_i64(self.t as i64, NANOS_PER_SEC, frequency() as i64) as u64
} }
} }
@ -45,6 +47,27 @@ impl<'a> Sub for &'a SteadyTime {
fn sub(self, other: &SteadyTime) -> Duration { fn sub(self, other: &SteadyTime) -> Duration {
let diff = self.t as i64 - other.t as i64; let diff = self.t as i64 - other.t as i64;
Duration::microseconds(diff * 1_000_000 / frequency() as i64) Duration::nanoseconds(mul_div_i64(diff, NANOS_PER_SEC, frequency() as i64))
} }
} }
// Computes (value*numer)/denom without overflow, as long as both
// (numer*denom) and the overall result fit into i64 (which is the case
// for our time conversions).
fn mul_div_i64(value: i64, numer: i64, denom: i64) -> i64 {
let q = value / denom;
let r = value % denom;
// Decompose value as (value/denom*denom + value%denom),
// substitute into (value*numer)/denom and simplify.
// r < denom, so (denom*numer) is the upper bound of (r*numer)
q * numer + r * numer / denom
}
#[test]
fn test_muldiv() {
assert_eq!(mul_div_i64( 1_000_000_000_001, 1_000_000_000, 1_000_000), 1_000_000_000_001_000);
assert_eq!(mul_div_i64(-1_000_000_000_001, 1_000_000_000, 1_000_000), -1_000_000_000_001_000);
assert_eq!(mul_div_i64(-1_000_000_000_001,-1_000_000_000, 1_000_000), 1_000_000_000_001_000);
assert_eq!(mul_div_i64( 1_000_000_000_001, 1_000_000_000,-1_000_000), -1_000_000_000_001_000);
assert_eq!(mul_div_i64( 1_000_000_000_001,-1_000_000_000,-1_000_000), 1_000_000_000_001_000);
}

View file

@ -105,10 +105,12 @@ pub struct Key<T> {
// This is trivially devirtualizable by LLVM because we never store anything // This is trivially devirtualizable by LLVM because we never store anything
// to this field and rustc can declare the `static` as constant as well. // to this field and rustc can declare the `static` as constant as well.
#[doc(hidden)] #[doc(hidden)]
#[unstable(feature = "thread_local_internals")]
pub inner: fn() -> &'static __impl::KeyInner<UnsafeCell<Option<T>>>, pub inner: fn() -> &'static __impl::KeyInner<UnsafeCell<Option<T>>>,
// initialization routine to invoke to create a value // initialization routine to invoke to create a value
#[doc(hidden)] #[doc(hidden)]
#[unstable(feature = "thread_local_internals")]
pub init: fn() -> T, pub init: fn() -> T,
} }

View file

@ -760,13 +760,13 @@ mod test {
#[test] fn idents_name_eq_test() { #[test] fn idents_name_eq_test() {
assert!(segments_name_eq( assert!(segments_name_eq(
&[Ident{name:Name(3),ctxt:4}, Ident{name:Name(78),ctxt:82}] &[Ident{name:Name(3),ctxt:4}, Ident{name:Name(78),ctxt:82}]
.iter().map(ident_to_segment).collect::<Vec<PathSegment>>()[], .iter().map(ident_to_segment).collect::<Vec<PathSegment>>(),
&[Ident{name:Name(3),ctxt:104}, Ident{name:Name(78),ctxt:182}] &[Ident{name:Name(3),ctxt:104}, Ident{name:Name(78),ctxt:182}]
.iter().map(ident_to_segment).collect::<Vec<PathSegment>>()[])); .iter().map(ident_to_segment).collect::<Vec<PathSegment>>()));
assert!(!segments_name_eq( assert!(!segments_name_eq(
&[Ident{name:Name(3),ctxt:4}, Ident{name:Name(78),ctxt:82}] &[Ident{name:Name(3),ctxt:4}, Ident{name:Name(78),ctxt:82}]
.iter().map(ident_to_segment).collect::<Vec<PathSegment>>()[], .iter().map(ident_to_segment).collect::<Vec<PathSegment>>(),
&[Ident{name:Name(3),ctxt:104}, Ident{name:Name(77),ctxt:182}] &[Ident{name:Name(3),ctxt:104}, Ident{name:Name(77),ctxt:182}]
.iter().map(ident_to_segment).collect::<Vec<PathSegment>>()[])); .iter().map(ident_to_segment).collect::<Vec<PathSegment>>()));
} }
} }

View file

@ -334,6 +334,10 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token)
let tok = if let TtToken(_, ref tok) = *token { tok } else { unreachable!() }; let tok = if let TtToken(_, ref tok) = *token { tok } else { unreachable!() };
// If T' is in the set FOLLOW(NT), continue. Else, reject. // If T' is in the set FOLLOW(NT), continue. Else, reject.
match (&next_token, is_in_follow(cx, &next_token, frag_spec.as_str())) { match (&next_token, is_in_follow(cx, &next_token, frag_spec.as_str())) {
(_, Err(msg)) => {
cx.span_err(sp, &msg);
continue
}
(&Eof, _) => return Some((sp, tok.clone())), (&Eof, _) => return Some((sp, tok.clone())),
(_, Ok(true)) => continue, (_, Ok(true)) => continue,
(next, Ok(false)) => { (next, Ok(false)) => {
@ -343,10 +347,6 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token)
token_to_string(next))); token_to_string(next)));
continue continue
}, },
(_, Err(msg)) => {
cx.span_err(sp, &msg);
continue
}
} }
}, },
TtSequence(sp, ref seq) => { TtSequence(sp, ref seq) => {

View file

@ -506,16 +506,25 @@ impl<T: Writer> ConsoleTestState<T> {
if self.use_color { if self.use_color {
try!(term.reset()); try!(term.reset());
} }
Ok(()) term.flush()
}
Raw(ref mut stdout) => {
try!(stdout.write_all(word.as_bytes()));
stdout.flush()
} }
Raw(ref mut stdout) => stdout.write_all(word.as_bytes())
} }
} }
pub fn write_plain(&mut self, s: &str) -> old_io::IoResult<()> { pub fn write_plain(&mut self, s: &str) -> old_io::IoResult<()> {
match self.out { match self.out {
Pretty(ref mut term) => term.write_all(s.as_bytes()), Pretty(ref mut term) => {
Raw(ref mut stdout) => stdout.write_all(s.as_bytes()) try!(term.write_all(s.as_bytes()));
term.flush()
},
Raw(ref mut stdout) => {
try!(stdout.write_all(s.as_bytes()));
stdout.flush()
},
} }
} }

View file

@ -114,12 +114,12 @@ pub fn parse_summary<R: Reader>(input: R, src: &Path) -> Result<Book, Vec<String
} }
}; };
let star_idx = match line.find_str("*") { Some(i) => i, None => continue }; let star_idx = match line.find("*") { Some(i) => i, None => continue };
let start_bracket = star_idx + line[star_idx..].find_str("[").unwrap(); let start_bracket = star_idx + line[star_idx..].find("[").unwrap();
let end_bracket = start_bracket + line[start_bracket..].find_str("](").unwrap(); let end_bracket = start_bracket + line[start_bracket..].find("](").unwrap();
let start_paren = end_bracket + 1; let start_paren = end_bracket + 1;
let end_paren = start_paren + line[start_paren..].find_str(")").unwrap(); let end_paren = start_paren + line[start_paren..].find(")").unwrap();
let given_path = &line[start_paren + 1 .. end_paren]; let given_path = &line[start_paren + 1 .. end_paren];
let title = line[start_bracket + 1..end_bracket].to_string(); let title = line[start_bracket + 1..end_bracket].to_string();

View file

@ -100,14 +100,22 @@ pub trait UnstableTrait { fn dummy(&self) { } }
#[stable(feature = "test_feature", since = "1.0.0")] #[stable(feature = "test_feature", since = "1.0.0")]
#[deprecated(since = "1.0.0")] #[deprecated(since = "1.0.0")]
pub struct DeprecatedStruct { pub i: int } pub struct DeprecatedStruct {
#[stable(feature = "test_feature", since = "1.0.0")] pub i: int
}
#[unstable(feature = "test_feature")] #[unstable(feature = "test_feature")]
#[deprecated(since = "1.0.0")] #[deprecated(since = "1.0.0")]
pub struct DeprecatedUnstableStruct { pub i: int } pub struct DeprecatedUnstableStruct {
#[stable(feature = "test_feature", since = "1.0.0")] pub i: int
}
#[unstable(feature = "test_feature")] #[unstable(feature = "test_feature")]
pub struct UnstableStruct { pub i: int } pub struct UnstableStruct {
#[stable(feature = "test_feature", since = "1.0.0")] pub i: int
}
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct StableStruct { pub i: int } pub struct StableStruct {
#[stable(feature = "test_feature", since = "1.0.0")] pub i: int
}
#[stable(feature = "test_feature", since = "1.0.0")] #[stable(feature = "test_feature", since = "1.0.0")]
#[deprecated(since = "1.0.0")] #[deprecated(since = "1.0.0")]
@ -137,14 +145,14 @@ pub enum Enum {
#[stable(feature = "test_feature", since = "1.0.0")] #[stable(feature = "test_feature", since = "1.0.0")]
#[deprecated(since = "1.0.0")] #[deprecated(since = "1.0.0")]
pub struct DeprecatedTupleStruct(pub int); pub struct DeprecatedTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub int);
#[unstable(feature = "test_feature")] #[unstable(feature = "test_feature")]
#[deprecated(since = "1.0.0")] #[deprecated(since = "1.0.0")]
pub struct DeprecatedUnstableTupleStruct(pub int); pub struct DeprecatedUnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub int);
#[unstable(feature = "test_feature")] #[unstable(feature = "test_feature")]
pub struct UnstableTupleStruct(pub int); pub struct UnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub int);
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct StableTupleStruct(pub int); pub struct StableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub int);
#[macro_export] #[macro_export]
macro_rules! macro_test { macro_rules! macro_test {

View file

@ -0,0 +1,60 @@
// 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(staged_api)]
#![staged_api]
#![stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stable {
#[stable(feature = "rust1", since = "1.0.0")]
pub inherit: u8, // it's a lie (stable doesn't inherit)
#[unstable(feature = "test_feature")]
pub override1: u8,
#[deprecated(since = "1.0.0")]
#[unstable(feature = "test_feature")]
pub override2: u8,
}
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stable2(#[stable(feature = "rust1", since = "1.0.0")] pub u8,
#[unstable(feature = "test_feature")] pub u8,
#[unstable(feature = "test_feature")] #[deprecated(since = "1.0.0")] pub u8);
#[unstable(feature = "test_feature")]
pub struct Unstable {
pub inherit: u8,
#[stable(feature = "rust1", since = "1.0.0")]
pub override1: u8,
#[deprecated(since = "1.0.0")]
#[unstable(feature = "test_feature")]
pub override2: u8,
}
#[unstable(feature = "test_feature")]
pub struct Unstable2(pub u8,
#[stable(feature = "rust1", since = "1.0.0")] pub u8,
#[unstable(feature = "test_feature")] #[deprecated(since = "1.0.0")] pub u8);
#[unstable(feature = "test_feature")]
#[deprecated(feature = "rust1", since = "1.0.0")]
pub struct Deprecated {
pub inherit: u8,
#[stable(feature = "rust1", since = "1.0.0")]
pub override1: u8,
#[unstable(feature = "test_feature")]
pub override2: u8,
}
#[unstable(feature = "test_feature")]
#[deprecated(feature = "rust1", since = "1.0.0")]
pub struct Deprecated2(pub u8,
#[stable(feature = "rust1", since = "1.0.0")] pub u8,
#[unstable(feature = "test_feature")] pub u8);

View file

@ -11,14 +11,12 @@
#![crate_name="static_methods_crate"] #![crate_name="static_methods_crate"]
#![crate_type = "lib"] #![crate_type = "lib"]
use std::int;
pub trait read { pub trait read {
fn readMaybe(s: String) -> Option<Self>; fn readMaybe(s: String) -> Option<Self>;
} }
impl read for int { impl read for isize {
fn readMaybe(s: String) -> Option<int> { fn readMaybe(s: String) -> Option<isize> {
s.parse().ok() s.parse().ok()
} }
} }

View file

@ -40,9 +40,7 @@ fn run(repeat: int, depth: int) {
} }
} }
// FIXME(#21721) used to be `List<()>` but that can cause type nillist = List<()>;
// certain LLVM versions to abort during optimizations.
type nillist = List<[u8; 0]>;
// Filled with things that have to be unwound // Filled with things that have to be unwound
@ -83,11 +81,11 @@ fn recurse_or_panic(depth: int, st: Option<State>) {
} }
Some(st) => { Some(st) => {
let mut v = st.vec.clone(); let mut v = st.vec.clone();
v.push_all(&[box List::Cons([], st.vec.last().unwrap().clone())]); v.push_all(&[box List::Cons((), st.vec.last().unwrap().clone())]);
State { State {
unique: box List::Cons([], box *st.unique), unique: box List::Cons((), box *st.unique),
vec: v, vec: v,
res: r(box List::Cons([], st.res._l.clone())), res: r(box List::Cons((), st.res._l.clone())),
} }
} }
}; };

View file

@ -0,0 +1,346 @@
// 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:lint_stability_fields.rs
#![deny(deprecated)]
#![allow(dead_code)]
#![feature(staged_api)]
#![staged_api]
mod cross_crate {
extern crate lint_stability_fields;
use self::lint_stability_fields::*;
pub fn foo() {
let x = Stable {
inherit: 1,
override1: 2, //~ WARN use of unstable
override2: 3,
//~^ ERROR use of deprecated item
//~^^ WARN use of unstable
};
let _ = x.inherit;
let _ = x.override1; //~ WARN use of unstable
let _ = x.override2;
//~^ ERROR use of deprecated item
//~^^ WARN use of unstable
let Stable {
inherit: _,
override1: _, //~ WARN use of unstable
override2: _
//~^ ERROR use of deprecated item
//~^^ WARN use of unstable
} = x;
// all fine
let Stable { .. } = x;
let x = Stable2(1, 2, 3);
let _ = x.0;
let _ = x.1; //~ WARN use of unstable
let _ = x.2;
//~^ ERROR use of deprecated item
//~^^ WARN use of unstable
let Stable2(_,
_, //~ WARN use of unstable
_)
//~^ ERROR use of deprecated item
//~^^ WARN use of unstable
= x;
// all fine
let Stable2(..) = x;
let x = Unstable { //~ WARN use of unstable
inherit: 1, //~ WARN use of unstable
override1: 2,
override2: 3,
//~^ ERROR use of deprecated item
//~^^ WARN use of unstable
};
let _ = x.inherit; //~ WARN use of unstable
let _ = x.override1;
let _ = x.override2;
//~^ ERROR use of deprecated item
//~^^ WARN use of unstable
let Unstable { //~ WARN use of unstable
inherit: _, //~ WARN use of unstable
override1: _,
override2: _
//~^ ERROR use of deprecated item
//~^^ WARN use of unstable
} = x;
let Unstable //~ WARN use of unstable
// the patterns are all fine:
{ .. } = x;
let x = Unstable2(1, 2, 3); //~ WARN use of unstable
let _ = x.0; //~ WARN use of unstable
let _ = x.1;
let _ = x.2;
//~^ ERROR use of deprecated item
//~^^ WARN use of unstable
let Unstable2 //~ WARN use of unstable
(_, //~ WARN use of unstable
_,
_)
//~^ ERROR use of deprecated item
//~^^ WARN use of unstable
= x;
let Unstable2 //~ WARN use of unstable
// the patterns are all fine:
(..) = x;
let x = Deprecated {
//~^ ERROR use of deprecated item
//~^^ WARN use of unstable
inherit: 1,
//~^ ERROR use of deprecated item
//~^^ WARN use of unstable
override1: 2,
override2: 3, //~ WARN use of unstable
};
let _ = x.inherit;
//~^ ERROR use of deprecated item
//~^^ WARN use of unstable
let _ = x.override1;
let _ = x.override2; //~ WARN use of unstable
let Deprecated {
//~^ ERROR use of deprecated item
//~^^ WARN use of unstable
inherit: _,
//~^ ERROR use of deprecated item
//~^^ WARN use of unstable
override1: _,
override2: _ //~ WARN use of unstable
} = x;
let Deprecated
//~^ ERROR use of deprecated item
//~^^ WARN use of unstable
// the patterns are all fine:
{ .. } = x;
let x = Deprecated2(1, 2, 3);
//~^ ERROR use of deprecated item
//~^^ WARN use of unstable
let _ = x.0;
//~^ ERROR use of deprecated item
//~^^ WARN use of unstable
let _ = x.1;
let _ = x.2; //~ WARN use of unstable
let Deprecated2
//~^ ERROR use of deprecated item
//~^^ WARN use of unstable
(_,
//~^ ERROR use of deprecated item
//~^^ WARN use of unstable
_,
_) //~ WARN use of unstable
= x;
let Deprecated2
//~^ ERROR use of deprecated item
//~^^ WARN use of unstable
// the patterns are all fine:
(..) = x;
}
}
mod this_crate {
#[stable(feature = "rust1", since = "1.0.0")]
struct Stable {
inherit: u8,
#[unstable(feature = "test_feature")]
override1: u8,
#[deprecated(since = "1.0.0")]
#[unstable(feature = "test_feature")]
override2: u8,
}
#[stable(feature = "rust1", since = "1.0.0")]
struct Stable2(u8,
#[stable(feature = "rust1", since = "1.0.0")] u8,
#[unstable(feature = "test_feature")] #[deprecated(since = "1.0.0")] u8);
#[unstable(feature = "test_feature")]
struct Unstable {
inherit: u8,
#[stable(feature = "rust1", since = "1.0.0")]
override1: u8,
#[deprecated(since = "1.0.0")]
#[unstable(feature = "test_feature")]
override2: u8,
}
#[unstable(feature = "test_feature")]
struct Unstable2(u8,
#[stable(feature = "rust1", since = "1.0.0")] u8,
#[unstable(feature = "test_feature")] #[deprecated(since = "1.0.0")] u8);
#[unstable(feature = "test_feature")]
#[deprecated(feature = "rust1", since = "1.0.0")]
struct Deprecated {
inherit: u8,
#[stable(feature = "rust1", since = "1.0.0")]
override1: u8,
#[unstable(feature = "test_feature")]
override2: u8,
}
#[unstable(feature = "test_feature")]
#[deprecated(feature = "rust1", since = "1.0.0")]
struct Deprecated2(u8,
#[stable(feature = "rust1", since = "1.0.0")] u8,
#[unstable(feature = "test_feature")] u8);
pub fn foo() {
let x = Stable {
inherit: 1,
override1: 2,
override2: 3,
//~^ ERROR use of deprecated item
};
let _ = x.inherit;
let _ = x.override1;
let _ = x.override2;
//~^ ERROR use of deprecated item
let Stable {
inherit: _,
override1: _,
override2: _
//~^ ERROR use of deprecated item
} = x;
// all fine
let Stable { .. } = x;
let x = Stable2(1, 2, 3);
let _ = x.0;
let _ = x.1;
let _ = x.2;
//~^ ERROR use of deprecated item
let Stable2(_,
_,
_)
//~^ ERROR use of deprecated item
= x;
// all fine
let Stable2(..) = x;
let x = Unstable {
inherit: 1,
override1: 2,
override2: 3,
//~^ ERROR use of deprecated item
};
let _ = x.inherit;
let _ = x.override1;
let _ = x.override2;
//~^ ERROR use of deprecated item
let Unstable {
inherit: _,
override1: _,
override2: _
//~^ ERROR use of deprecated item
} = x;
let Unstable
// the patterns are all fine:
{ .. } = x;
let x = Unstable2(1, 2, 3);
let _ = x.0;
let _ = x.1;
let _ = x.2;
//~^ ERROR use of deprecated item
let Unstable2
(_,
_,
_)
//~^ ERROR use of deprecated item
= x;
let Unstable2
// the patterns are all fine:
(..) = x;
let x = Deprecated {
//~^ ERROR use of deprecated item
inherit: 1,
//~^ ERROR use of deprecated item
override1: 2,
override2: 3,
};
let _ = x.inherit;
//~^ ERROR use of deprecated item
let _ = x.override1;
let _ = x.override2;
let Deprecated {
//~^ ERROR use of deprecated item
inherit: _,
//~^ ERROR use of deprecated item
override1: _,
override2: _
} = x;
let Deprecated
//~^ ERROR use of deprecated item
// the patterns are all fine:
{ .. } = x;
let x = Deprecated2(1, 2, 3);
//~^ ERROR use of deprecated item
let _ = x.0;
//~^ ERROR use of deprecated item
let _ = x.1;
let _ = x.2;
let Deprecated2
//~^ ERROR use of deprecated item
(_,
//~^ ERROR use of deprecated item
_,
_)
= x;
let Deprecated2
//~^ ERROR use of deprecated item
// the patterns are all fine:
(..) = x;
}
}
fn main() {}

View file

@ -317,11 +317,17 @@ mod this_crate {
#[unstable(feature = "test_feature")] #[unstable(feature = "test_feature")]
#[deprecated(since = "1.0.0")] #[deprecated(since = "1.0.0")]
pub struct DeprecatedStruct { i: isize } pub struct DeprecatedStruct {
#[stable(feature = "test_feature", since = "1.0.0")] i: isize
}
#[unstable(feature = "test_feature")] #[unstable(feature = "test_feature")]
pub struct UnstableStruct { i: isize } pub struct UnstableStruct {
#[stable(feature = "test_feature", since = "1.0.0")] i: isize
}
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct StableStruct { i: isize } pub struct StableStruct {
#[stable(feature = "test_feature", since = "1.0.0")] i: isize
}
#[unstable(feature = "test_feature")] #[unstable(feature = "test_feature")]
#[deprecated(since = "1.0.0")] #[deprecated(since = "1.0.0")]

View file

@ -0,0 +1,17 @@
// 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.
// Issue #21370
macro_rules! test {
($wrong:t_ty) => () //~ ERROR invalid fragment specifier `t_ty`
}
fn main() { }

View file

@ -0,0 +1,15 @@
// 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.
macro_rules! test {
($e:expr +) => () //~ ERROR not allowed for `expr` fragments
}
fn main() { }

View file

@ -9,18 +9,18 @@
// except according to those terms. // except according to those terms.
use std::num::FromPrimitive; use std::num::FromPrimitive;
use std::int; use std::isize;
#[derive(PartialEq, FromPrimitive, Debug)] #[derive(PartialEq, FromPrimitive, Debug)]
enum A { enum A {
Foo = int::MAX, Foo = isize::MAX,
Bar = 1, Bar = 1,
Baz = 3, Baz = 3,
Qux, Qux,
} }
pub fn main() { pub fn main() {
let x: Option<A> = FromPrimitive::from_int(int::MAX); let x: Option<A> = FromPrimitive::from_int(isize::MAX);
assert_eq!(x, Some(A::Foo)); assert_eq!(x, Some(A::Foo));
let x: Option<A> = FromPrimitive::from_int(1); let x: Option<A> = FromPrimitive::from_int(1);

View file

@ -25,9 +25,7 @@ fn main() {
let mut dropped = false; let mut dropped = false;
{ {
let leak = Leak { dropped: &mut dropped }; let leak = Leak { dropped: &mut dropped };
// FIXME(#21721) "hack" used to be () but that can cause for ((), leaked) in Some(((), leak)).into_iter() {}
// certain LLVM versions to abort during optimizations.
for (_, leaked) in Some(("hack", leak)).into_iter() {}
} }
assert!(dropped); assert!(dropped);

View file

@ -0,0 +1,17 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() {
static NONE: Option<((), &'static u8)> = None;
let ptr = unsafe {
*(&NONE as *const _ as *const *const u8)
};
assert!(ptr.is_null());
}

View file

@ -0,0 +1,34 @@
// 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.
// Regression test for Issue #22536: If a type implements Copy, then
// moving it must not zero the original memory.
trait Resources {
type Buffer: Copy;
fn foo(&self) {}
}
struct BufferHandle<R: Resources> {
raw: <R as Resources>::Buffer,
}
impl<R: Resources> Copy for BufferHandle<R> {}
enum Res {}
impl Resources for Res {
type Buffer = u32;
}
impl Copy for Res { }
fn main() {
let b: BufferHandle<Res> = BufferHandle { raw: 1 };
let c = b;
assert_eq!(c.raw, b.raw)
}

View file

@ -8,13 +8,11 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use std::uint;
pub fn main() { pub fn main() {
// sometimes we have had trouble finding // sometimes we have had trouble finding
// the right type for f, as we unified // the right type for f, as we unified
// bot and u32 here // bot and u32 here
let f = match "1234".parse::<uint>().ok() { let f = match "1234".parse::<usize>().ok() {
None => return (), None => return (),
Some(num) => num as u32 Some(num) => num as u32
}; };

View file

@ -0,0 +1,29 @@
// 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.
// Regression test for issue #22655: This test should not lead to
// infinite recursion.
unsafe impl<T: Send + ?Sized> Send for Unique<T> { }
pub struct Unique<T:?Sized> {
pointer: *const T,
}
pub struct Node<V> {
vals: V,
edges: Unique<Node<V>>,
}
fn is_send<T: Send>() {}
fn main() {
is_send::<Node<&'static ()>>();
}