Auto merge of #22860 - Manishearth:rollup, r=alexcrichton
Passes check-stage1, check-stage2
This commit is contained in:
commit
e233987ce1
@ -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
|
||||
|
@ -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.
|
@ -300,7 +300,7 @@ mod imp {
|
||||
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
|
||||
}
|
||||
|
@ -2663,7 +2663,7 @@ mod tests {
|
||||
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 @@ mod tests {
|
||||
|
||||
{
|
||||
let right: &[_] = right;
|
||||
assert!(right[..right.len()] == [3, 4, 5][]);
|
||||
assert!(right[..right.len()] == [3, 4, 5]);
|
||||
}
|
||||
for p in right {
|
||||
*p += 2;
|
||||
|
@ -2093,7 +2093,7 @@ mod tests {
|
||||
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 @@ mod tests {
|
||||
|
||||
{
|
||||
let right: &[_] = right;
|
||||
assert!(&right[..right.len()] == &[3, 4, 5][]);
|
||||
assert!(&right[..right.len()] == &[3, 4, 5]);
|
||||
}
|
||||
for p in right {
|
||||
*p += 2;
|
||||
|
@ -241,7 +241,12 @@ extern "rust-intrinsic" {
|
||||
/// 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)
|
||||
|
@ -171,8 +171,7 @@ pub trait IteratorExt: Iterator + Sized {
|
||||
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 @@ pub trait IteratorExt: Iterator + Sized {
|
||||
/// ```
|
||||
#[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 @@ impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool
|
||||
for x in self.iter.by_ref() {
|
||||
if (self.predicate)(&x) {
|
||||
return Some(x);
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
None
|
||||
|
@ -275,7 +275,13 @@ macro_rules! impls{
|
||||
/// 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
|
||||
|
@ -641,9 +641,9 @@ impl<T, E> Result<T, 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,
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -59,16 +59,16 @@ fn iterator_to_slice() {
|
||||
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]);
|
||||
|
@ -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) {
|
||||
|
@ -1771,6 +1771,11 @@ impl LintPass for Stability {
|
||||
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! {
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,8 +58,10 @@ impl<'a> Annotator<'a> {
|
||||
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 @@ impl<'a> Annotator<'a> {
|
||||
}
|
||||
}
|
||||
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 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
|
||||
&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 }
|
||||
|
@ -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_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.
|
||||
|
@ -233,6 +233,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
|
||||
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 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
|
||||
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 => {
|
||||
|
@ -2985,7 +2985,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
} 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(())
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -386,7 +386,7 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
|
||||
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 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
|
||||
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 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
|
||||
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 @@ impl<'tcx> Cleanup<'tcx> for DropValue<'tcx> {
|
||||
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 {
|
||||
|
@ -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 {
|
||||
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(¶m_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 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
|
||||
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
|
||||
|
@ -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)
|
||||
|
@ -311,7 +311,8 @@ impl KindOps for Lvalue {
|
||||
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 @@ 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
|
||||
/// 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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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"));
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -3945,9 +3945,7 @@ mod tests {
|
||||
|
||||
#[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();
|
||||
|
@ -173,7 +173,7 @@ mod tests {
|
||||
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 @@ mod tests {
|
||||
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]
|
||||
|
@ -102,6 +102,7 @@ impl MemWriter {
|
||||
|
||||
impl Writer for MemWriter {
|
||||
#[inline]
|
||||
#[allow(deprecated)]
|
||||
fn write_all(&mut self, buf: &[u8]) -> IoResult<()> {
|
||||
self.buf.push_all(buf);
|
||||
Ok(())
|
||||
|
@ -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`.
|
||||
///
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -439,6 +439,7 @@ fn translate_status(status: c_int) -> ExitStatus {
|
||||
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 }
|
||||
|
@ -12,6 +12,8 @@ use ops::Sub;
|
||||
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 @@ impl 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);
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -760,13 +760,13 @@ mod test {
|
||||
#[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>>()));
|
||||
}
|
||||
}
|
||||
|
@ -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) => {
|
||||
|
@ -506,16 +506,25 @@ impl<T: Writer> ConsoleTestState<T> {
|
||||
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()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 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();
|
||||
|
@ -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 {
|
||||
|
60
src/test/auxiliary/lint_stability_fields.rs
Normal file
60
src/test/auxiliary/lint_stability_fields.rs
Normal 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);
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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())),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
346
src/test/compile-fail/lint-stability-fields.rs
Normal file
346
src/test/compile-fail/lint-stability-fields.rs
Normal 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() {}
|
@ -317,11 +317,17 @@ mod this_crate {
|
||||
|
||||
#[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")]
|
||||
|
17
src/test/compile-fail/unused-macro-with-bad-frag-spec.rs
Normal file
17
src/test/compile-fail/unused-macro-with-bad-frag-spec.rs
Normal 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() { }
|
15
src/test/compile-fail/unused-macro-with-follow-violation.rs
Normal file
15
src/test/compile-fail/unused-macro-with-follow-violation.rs
Normal 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() { }
|
@ -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);
|
||||
|
@ -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);
|
||||
|
17
src/test/run-pass/issue-21721.rs
Normal file
17
src/test/run-pass/issue-21721.rs
Normal 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());
|
||||
}
|
34
src/test/run-pass/issue-22536-copy-mustnt-zero.rs
Normal file
34
src/test/run-pass/issue-22536-copy-mustnt-zero.rs
Normal 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)
|
||||
}
|
@ -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
|
||||
};
|
||||
|
29
src/test/run-pass/traits-issue-22655.rs
Normal file
29
src/test/run-pass/traits-issue-22655.rs
Normal 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 ()>>();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user