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
`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
@ -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
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
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)
for specific instructions about installing it.
## Converting to Cargo
Let's convert Hello World to Cargo.
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
do that part first:
```{bash}
```bash
$ mkdir src
$ mv main.rs src/main.rs
```
@ -36,7 +38,7 @@ place for everything, and everything in its place.
Next, our configuration file:
```{bash}
```bash
$ 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:
```{bash}
```bash
$ cargo build
Compiling hello_world v0.0.1 (file:///home/yourname/projects/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
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
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 @@ pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usiz
libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8
} else {
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);
new_ptr
}

View file

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

View file

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

View file

@ -241,7 +241,12 @@ pub struct TyDesc {
/// will trigger a compiler error.
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;
/// Returns `true` if a type is managed (will be allocated on the local heap)

View file

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

View file

@ -275,7 +275,13 @@ fn clone(&self) -> $t<T> {
/// any methods, but instead is used to gate access to data.
///
/// 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 { }
/// `PhantomFn` is a marker trait for use with traits that contain

View file

@ -641,9 +641,9 @@ pub fn and_then<U, F: FnOnce(T) -> Result<U, E>>(self, op: F) -> Result<U, E> {
/// ```
#[inline]
#[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 {
Ok(_) => self,
Ok(v) => Ok(v),
Err(_) => res,
}
}

View file

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

View file

@ -36,10 +36,10 @@ pub fn test_and_then() {
#[test]
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!(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");
}

View file

@ -59,16 +59,16 @@ macro_rules! test {
let mut iter = data.iter_mut();
assert_eq!(&iter[..], &other_data[..]);
// mutability:
assert!(&mut iter[] == other_data);
assert!(&mut iter[..] == other_data);
iter.next();
assert_eq!(&iter[..], &other_data[1..]);
assert!(&mut iter[] == &mut other_data[1..]);
assert!(&mut iter[..] == &mut other_data[1..]);
iter.next_back();
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();
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
/// replacing the RNG with the result of a `Default::default` call.
#[derive(Copy)]
pub struct ReseedWithDefault { __hack: [u8; 0] }
// 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: [] };
pub struct ReseedWithDefault;
impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault {
fn reseed(&mut self, rng: &mut R) {

View file

@ -1771,6 +1771,11 @@ fn check_path(&mut self, cx: &Context, path: &ast::Path, id: ast::NodeId) {
stability::check_path(cx.tcx, path, id,
&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! {

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()
};
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 {
None
}
@ -76,4 +76,3 @@ pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
None
}
}

View file

@ -58,8 +58,10 @@ fn annotate<F>(&mut self, id: NodeId, use_parent: bool,
attrs: &Vec<Attribute>, item_sp: Span, f: F, required: bool) where
F: FnOnce(&mut Annotator),
{
debug!("annotate(id = {:?}, attrs = {:?})", id, attrs);
match attr::find_stability(self.sess.diagnostic(), attrs, item_sp) {
Some(stab) => {
debug!("annotate: found {:?}", stab);
self.index.local.insert(id, stab.clone());
// Don't inherit #[stable(feature = "rust1", since = "1.0.0")]
@ -72,6 +74,8 @@ fn annotate<F>(&mut self, id: NodeId, use_parent: bool,
}
}
None => {
debug!("annotate: not found, use_parent = {:?}, parent = {:?}",
use_parent, self.parent);
if use_parent {
if let Some(stab) = self.parent.clone() {
self.index.local.insert(id, stab);
@ -299,6 +303,12 @@ fn visit_path(&mut self, path: &ast::Path, id: ast::NodeId) {
&mut |id, sp, stab| self.check(id, sp, stab));
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
@ -385,6 +395,76 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
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
};
@ -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,
cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
if !is_staged_api(tcx, id) { return }

View file

@ -3896,7 +3896,7 @@ fn same_type<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
let types_a = substs_a.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))
}
@ -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> {
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.

View file

@ -233,6 +233,7 @@ fn visit_item(&mut self, item: &ast::Item) {
ast::ItemEnum(ref def, _) if public_first => {
for variant in &def.variants {
self.exported_items.insert(variant.node.id);
self.public_items.insert(variant.node.id);
}
}
@ -321,6 +322,15 @@ fn visit_item(&mut self, item: &ast::Item) {
Some(id) => { self.exported_items.insert(id); }
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 => {

View file

@ -2985,7 +2985,7 @@ fn resolve_trait_reference(&mut self,
} else {
let msg = format!("use of undeclared trait name `{}`",
self.path_names_to_string(trait_path, path_depth));
self.resolve_error(trait_path.span, &msg[]);
self.resolve_error(trait_path.span, &msg);
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>,
pat: &ast::Pat)
-> Block<'blk, 'tcx> {
let _icx = push_ctxt("create_dummy_locals");
// create dummy memory for the variables if we have no
// value to store into them immediately
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 ||
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
// return type, otherwise push "undef".
if common::type_is_zero_size(ccx, ret_ty) {

View file

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

View file

@ -213,8 +213,43 @@ fn type_needs_unwind_cleanup_<'tcx>(tcx: &ty::ctxt<'tcx>,
}
}
/// 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 {
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 {
@ -534,6 +569,12 @@ pub fn monomorphize<T>(&self, value: &T) -> T
self.param_substs,
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

View file

@ -77,7 +77,7 @@ pub fn trans_stmt_semi<'blk, 'tcx>(cx: Block<'blk, 'tcx>, e: &ast::Expr)
-> Block<'blk, 'tcx> {
let _icx = push_ctxt("trans_stmt_semi");
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
} else {
expr::trans_into(cx, e, expr::Ignore)

View file

@ -311,7 +311,8 @@ fn post_store<'blk, 'tcx>(&self,
val: ValueRef,
ty: Ty<'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
let () = zero_mem(bcx, val, ty);
bcx
@ -656,7 +657,7 @@ pub fn appropriate_rvalue_mode<'a>(&self, ccx: &CrateContext<'a, 'tcx>)
/// 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.
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);
if self.kind.is_by_ref() {
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 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
// are copying from an rvalue, since that cannot possible
// 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);
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));
},
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
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 = 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) {
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) {
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.
debug!("drop_ty(t={})", t.repr(bcx.tcx()));
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 glue = get_drop_glue(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));
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,
v0,
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 tcx = bcx.tcx();
let _icx = push_ctxt("trans_intrinsic_call");
let ret_ty = match callee_ty.sty {
ty::ty_bare_fn(_, ref f) => {
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") => {
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") => {
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!(
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!(
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);
with_cond(bcx, not_null, |bcx| {
let ccx = bcx.ccx();
let tcx = bcx.tcx();
let _icx = push_ctxt("tvec::make_drop_glue_unboxed");
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);
iter_vec_raw(bcx,
dataptr,

View file

@ -991,6 +991,17 @@ fn trait_ref_to_object_type<'tcx>(this: &AstConv<'tcx>,
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>,
span: Span,
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 {
ty_path_def.local_node_id()
} else {
span_err!(tcx.sess, span, E0223,
"ambiguous associated type; specify the type using the syntax \
`<{} as Trait>::{}`",
ty.user_string(tcx), token::get_name(assoc_name));
report_ambiguous_associated_type(
tcx, span, &ty.user_string(tcx), "Trait", &token::get_name(assoc_name));
return (tcx.types.err, ty_path_def);
};
@ -1109,10 +1118,8 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
ty
} else {
let path_str = ty::item_path_str(tcx, trait_def_id);
span_err!(tcx.sess, span, E0223,
"ambiguous associated type; specify the type using the syntax \
`<Type as {}>::{}`",
path_str, &token::get_ident(item_segment.identifier));
report_ambiguous_associated_type(
tcx, span, "Type", &path_str, &token::get_ident(item_segment.identifier));
return tcx.types.err;
};

View file

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

View file

@ -173,7 +173,7 @@ fn test_mem_writer() {
assert_eq!(writer.write(&[1, 2, 3]), Ok(3));
assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4));
let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
assert_eq!(&writer.get_ref()[], b);
assert_eq!(&writer.get_ref()[..], b);
}
#[test]
@ -369,28 +369,28 @@ fn test_seekable_mem_writer() {
assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4));
assert_eq!(writer.position(), 8);
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.position(), 0);
assert_eq!(writer.write(&[3, 4]), Ok(2));
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.write(&[0, 1]), Ok(2));
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.write(&[1, 2]), Ok(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.write(&[1]), Ok(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]

View file

@ -102,6 +102,7 @@ pub fn into_inner(self) -> Vec<u8> { self.buf }
impl Writer for MemWriter {
#[inline]
#[allow(deprecated)]
fn write_all(&mut self, buf: &[u8]) -> IoResult<()> {
self.buf.push_all(buf);
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.
#[stable(feature = "rust1", since = "1.0.0")]
#[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`.
///

View file

@ -291,29 +291,14 @@ fn mkstat(stat: &libc::stat) -> FileStat {
// FileStat times are in milliseconds
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 {
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 {
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 {
mktime(stat.st_mtime as u64, stat.st_mtime_nsec as u64)
}

View file

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

View file

@ -12,6 +12,8 @@
use time::Duration;
use sync::{Once, ONCE_INIT};
const NANOS_PER_SEC: i64 = 1_000_000_000;
pub struct SteadyTime {
t: libc::LARGE_INTEGER,
}
@ -24,7 +26,7 @@ pub fn now() -> SteadyTime {
}
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 {
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
// to this field and rustc can declare the `static` as constant as well.
#[doc(hidden)]
#[unstable(feature = "thread_local_internals")]
pub inner: fn() -> &'static __impl::KeyInner<UnsafeCell<Option<T>>>,
// initialization routine to invoke to create a value
#[doc(hidden)]
#[unstable(feature = "thread_local_internals")]
pub init: fn() -> T,
}

View file

@ -760,13 +760,13 @@ fn ident_to_segment(id : &Ident) -> PathSegment {
#[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>>()[],
.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>>()[]));
.iter().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>>()[],
.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>>()[]));
.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!() };
// If T' is in the set FOLLOW(NT), continue. Else, reject.
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())),
(_, Ok(true)) => continue,
(next, Ok(false)) => {
@ -343,10 +347,6 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token)
token_to_string(next)));
continue
},
(_, Err(msg)) => {
cx.span_err(sp, &msg);
continue
}
}
},
TtSequence(sp, ref seq) => {

View file

@ -506,16 +506,25 @@ pub fn write_pretty(&mut self,
if self.use_color {
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<()> {
match self.out {
Pretty(ref mut term) => term.write_all(s.as_bytes()),
Raw(ref mut stdout) => stdout.write_all(s.as_bytes())
Pretty(ref mut term) => {
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 @@ fn collapse(stack: &mut Vec<BookItem>,
}
};
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 end_bracket = start_bracket + line[start_bracket..].find_str("](").unwrap();
let start_bracket = star_idx + line[star_idx..].find("[").unwrap();
let end_bracket = start_bracket + line[start_bracket..].find("](").unwrap();
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 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")]
#[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")]
#[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")]
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")]
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")]
#[deprecated(since = "1.0.0")]
@ -137,14 +145,14 @@ pub enum Enum {
#[stable(feature = "test_feature", 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")]
#[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")]
pub struct UnstableTupleStruct(pub int);
pub struct UnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub int);
#[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_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_type = "lib"]
use std::int;
pub trait read {
fn readMaybe(s: String) -> Option<Self>;
}
impl read for int {
fn readMaybe(s: String) -> Option<int> {
impl read for isize {
fn readMaybe(s: String) -> Option<isize> {
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
// certain LLVM versions to abort during optimizations.
type nillist = List<[u8; 0]>;
type nillist = List<()>;
// Filled with things that have to be unwound
@ -83,11 +81,11 @@ fn recurse_or_panic(depth: int, st: Option<State>) {
}
Some(st) => {
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 {
unique: box List::Cons([], box *st.unique),
unique: box List::Cons((), box *st.unique),
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 @@ impl Trait for MethodTester {}
#[unstable(feature = "test_feature")]
#[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")]
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")]
pub struct StableStruct { i: isize }
pub struct StableStruct {
#[stable(feature = "test_feature", since = "1.0.0")] i: isize
}
#[unstable(feature = "test_feature")]
#[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.
use std::num::FromPrimitive;
use std::int;
use std::isize;
#[derive(PartialEq, FromPrimitive, Debug)]
enum A {
Foo = int::MAX,
Foo = isize::MAX,
Bar = 1,
Baz = 3,
Qux,
}
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));
let x: Option<A> = FromPrimitive::from_int(1);

View file

@ -25,9 +25,7 @@ fn main() {
let mut dropped = false;
{
let leak = Leak { dropped: &mut dropped };
// FIXME(#21721) "hack" used to be () but that can cause
// certain LLVM versions to abort during optimizations.
for (_, leaked) in Some(("hack", leak)).into_iter() {}
for ((), leaked) in Some(((), leak)).into_iter() {}
}
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
// except according to those terms.
use std::uint;
pub fn main() {
// sometimes we have had trouble finding
// the right type for f, as we unified
// bot and u32 here
let f = match "1234".parse::<uint>().ok() {
let f = match "1234".parse::<usize>().ok() {
None => return (),
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 ()>>();
}