- it is now cross platform, instead of just unix
- it now avoids sleeping (fixing issue #6156)
- it now calls force_destroy() when force = true (was a bug)
This adds #[inline] to many very common string routines (e.g. `len`).
It also rewrites `repeat` to not use `+=` and make it O(n) rather than O(n^2), and also concat/connect(_slices) to reduce the overhead of reallocations, and constantly `set_len`ing (etc) in `push_str`. (The added complexity might not be worth the 20% speedup though.)
I have noticed these comments scattered across the codebase. They appear to be vestigial Emacs formatting settings and they don't appear in newer files. For the sake of consistency it's probably best to remove them.
this could probably use expansion - it just uses all of the default
options, which is usually what we want, but not always. maybe add a
separate function that takes more options?
only tested on linux/x86_64, but i got the values for other platforms
from their system header files.
no bindings for win32, because win32 doesn't include glob.h.
also, glob() takes a callback for error handling, but i'm just making
this a *c_void for now, since i don't know how to represent c calling
back into rust (if that's even currently possible).
The drop block has been deprecated for quite some time. This patch series removes support for parsing it and all the related machinery that made drop work.
As a side feature of all this, I also added the ability to annote fields in structs. This allows comments to be properly associated with an individual field. However, I didn't update `rustdoc` to integrate these comment blocks into the documentation it generates.
After much discussion on IRC and #4819, we have decided to revert to the old naming of the `/` operator. This does not change its behavior. In making this change, we also have had to rename some of the methods in the `Integer` trait. Here is a list of the methods that have changed:
- `Quot::quot` -> `Div::div`
- `Rem::rem` - stays the same
- `Integer::quot_rem` -> `Integer::div_rem`
- `Integer::div` -> `Integer::div_floor`
- `Integer::modulo` -> `Integer::mod_floor`
- `Integer::div_mod` -> `Integer::div_mod_floor`
r? @brson or @thestinger : Added a change_dir_locked function to os, and use it in the
mkdir_recursive tests so that the tests don't clobber each other's
directory changes.
This replaces the wrapper around the runtime RNG with a pure Rust implementation of the same algorithm. This is much faster (up to 5x), and is hopefully safer.
There is still (a little) room for optimisation: testing by summing 100,000,000 random `u32`s indicates this is about ~~40-50%~~ 10% slower than the pure C implementation (running as standalone executable, not in the runtime).
(Only 6d50d55 is part of this PR, the first two are from #6058, but are required for the rt rng to be correct to compare against in the tests.)
This replaces the wrapper around the runtime RNG with a pure Rust
implementation of the same algorithm. This is faster (up to 5x), and
is hopefully safer.
There is still much room for optimisation: testing by summing 100,000,000
random `u32`s indicates this is about 40-50% slower than the pure C
implementation (running as standalone executable, not in the runtime).
As discussed on issue #4819, I have created four new traits: `Algebraic`, `Trigonometric`, `Exponential` and `Hyperbolic`, and moved the appropriate methods into them from `Real`.
~~~rust
pub trait Algebraic {
fn pow(&self, n: Self) -> Self;
fn sqrt(&self) -> Self;
fn rsqrt(&self) -> Self;
fn cbrt(&self) -> Self;
fn hypot(&self, other: Self) -> Self;
}
pub trait Trigonometric {
fn sin(&self) -> Self;
fn cos(&self) -> Self;
fn tan(&self) -> Self;
fn asin(&self) -> Self;
fn acos(&self) -> Self;
fn atan(&self) -> Self;
fn atan2(&self, other: Self) -> Self;
}
pub trait Exponential {
fn exp(&self) -> Self;
fn exp2(&self) -> Self;
fn expm1(&self) -> Self;
fn log(&self) -> Self;
fn log2(&self) -> Self;
fn log10(&self) -> Self;
}
pub trait Hyperbolic: Exponential {
fn sinh(&self) -> Self;
fn cosh(&self) -> Self;
fn tanh(&self) -> Self;
}
~~~
There was some discussion over whether we should shorten the names, for example `Trig` and `Exp`. No abbreviations have been agreed on yet, but this could be considered in the future.
Additionally, `Integer::divisible_by` has been renamed to `Integer::is_multiple_of`.
After discussions on IRC and #4819, we have decided to revert this change. This is due to the traits expressing different ideas and because hyperbolic functions are not trivially implementable from exponential functions for floating-point types.
The Hyperbolic Functions are trivially implemented in terms of `exp`, so it's simpler to group them the Exponential trait. In the future these would have default implementations.
r? @brson mkdir_recursive creates a directory as well as any of its
parent directories that don't exist already. Seems like a useful
thing to have in core.
(Or r? anyone who gets to it first.)
As part of the numeric trait reform (see issue #4819), I have added the following traits to `core::num` and implemented them for Rust's primitive numeric types:
~~~rust
pub trait Bitwise: Not<Self>
+ BitAnd<Self,Self>
+ BitOr<Self,Self>
+ BitXor<Self,Self>
+ Shl<Self,Self>
+ Shr<Self,Self> {}
pub trait BitCount {
fn population_count(&self) -> Self;
fn leading_zeros(&self) -> Self;
fn trailing_zeros(&self) -> Self;
}
pub trait Bounded {
fn min_value() -> Self;
fn max_value() -> Self;
}
pub trait Primitive: Num
+ NumCast
+ Bounded
+ Neg<Self>
+ Add<Self,Self>
+ Sub<Self,Self>
+ Mul<Self,Self>
+ Quot<Self,Self>
+ Rem<Self,Self> {
fn bits() -> uint;
fn bytes() -> uint;
}
pub trait Int: Integer
+ Primitive
+ Bitwise
+ BitCount {}
pub trait Float: Real
+ Signed
+ Primitive {
fn NaN() -> Self;
fn infinity() -> Self;
fn neg_infinity() -> Self;
fn neg_zero() -> Self;
fn is_NaN(&self) -> bool;
fn is_infinite(&self) -> bool;
fn is_finite(&self) -> bool;
fn mantissa_digits() -> uint;
fn digits() -> uint;
fn epsilon() -> Self;
fn min_exp() -> int;
fn max_exp() -> int;
fn min_10_exp() -> int;
fn max_10_exp() -> int;
fn mul_add(&self, a: Self, b: Self) -> Self;
fn next_after(&self, other: Self) -> Self;
}
~~~
Note: I'm not sure my implementation for `BitCount::trailing_zeros` and `BitCount::leading_zeros` is correct for uints. I also need some assistance creating appropriate unit tests for them.
More work needs to be done in implementing specialized primitive floating-point and integer methods, but I'm beginning to reach the limits of my knowledge. Please leave your suggestions/critiques/ideas on #4819 if you have them – I'd very much appreciate hearing them.
I have also added an `Orderable` trait:
~~~rust
pub trait Orderable: Ord {
fn min(&self, other: &Self) -> Self;
fn max(&self, other: &Self) -> Self;
fn clamp(&self, mn: &Self, mx: &Self) -> Self;
}
~~~
This is a temporary trait until we have default methods. We don't want to encumber all implementors of Ord by requiring them to implement these functions, but at the same time we want to be able to take advantage of the speed of the specific numeric functions (like the `fmin` and `fmax` intrinsics).
r? @brson
Unwinding through macros now happens as a call to the trait function `FailWithCause::fail_with()`, which consumes self, allowing to use a more generic failure object in the future.
This is a temporary trait until we have default methods. We don't want to encumber all implementors of Ord by requiring them to implement these functions, but at the same time we want to be able to take advantage of the speed of the specific numeric functions (like the `fmin` and `fmax` intrinsics).
Having three traits for primitive ints/uints seemed rather excessive. If users wish to specify between them they can simply combine Int with either the Signed and Unsigned traits. For example: fn foo<T: Int + Signed>() { … }
r? @graydon
Sorry, this pull request is a few different things at once, but I tried to make them separate commits.
First, as before, this should do file searching the way that's described in the doc now.
Second, there's also some preliminary work on the install command (really just tests for it).
As part of the numeric trait reform (see issue #4819), I have added the following traits to `core::num` and implemented them for floating point types:
~~~rust
pub trait Round {
fn floor(&self) -> Self;
fn ceil(&self) -> Self;
fn round(&self) -> Self;
fn trunc(&self) -> Self;
fn fract(&self) -> Self;
}
pub trait Fractional: Num
+ Ord
+ Round
+ Quot<Self,Self> {
fn recip(&self) -> Self;
}
pub trait Real: Signed
+ Fractional {
// Common Constants
fn pi() -> Self;
fn two_pi() -> Self;
fn frac_pi_2() -> Self;
fn frac_pi_3() -> Self;
fn frac_pi_4() -> Self;
fn frac_pi_6() -> Self;
fn frac_pi_8() -> Self;
fn frac_1_pi() -> Self;
fn frac_2_pi() -> Self;
fn frac_2_sqrtpi() -> Self;
fn sqrt2() -> Self;
fn frac_1_sqrt2() -> Self;
fn e() -> Self;
fn log2_e() -> Self;
fn log10_e() -> Self;
fn log_2() -> Self;
fn log_10() -> Self;
// Exponential functions
fn pow(&self, n: Self) -> Self;
fn exp(&self) -> Self;
fn exp2(&self) -> Self;
fn expm1(&self) -> Self;
fn ldexp(&self, n: int) -> Self;
fn log(&self) -> Self;
fn log2(&self) -> Self;
fn log10(&self) -> Self;
fn log_radix(&self) -> Self;
fn ilog_radix(&self) -> int;
fn sqrt(&self) -> Self;
fn rsqrt(&self) -> Self;
fn cbrt(&self) -> Self;
// Angular conversions
fn to_degrees(&self) -> Self;
fn to_radians(&self) -> Self;
// Triganomic functions
fn hypot(&self, other: Self) -> Self;
fn sin(&self) -> Self;
fn cos(&self) -> Self;
fn tan(&self) -> Self;
// Inverse triganomic functions
fn asin(&self) -> Self;
fn acos(&self) -> Self;
fn atan(&self) -> Self;
fn atan2(&self, other: Self) -> Self;
// Hyperbolic triganomic functions
fn sinh(&self) -> Self;
fn cosh(&self) -> Self;
fn tanh(&self) -> Self;
}
/// Methods that are harder to implement and not commonly used.
pub trait RealExt: Real {
// Gamma functions
fn lgamma(&self) -> (int, Self);
fn tgamma(&self) -> Self;
// Bessel functions
fn j0(&self) -> Self;
fn j1(&self) -> Self;
fn jn(&self, n: int) -> Self;
fn y0(&self) -> Self;
fn y1(&self) -> Self;
fn yn(&self, n: int) -> Self;
}
~~~
The constants in `Real` could be [associated items](http://smallcultfollowing.com/babysteps/blog/2013/04/03/associated-items-continued/) in the future (see issue #5527). At the moment I have left the constants in `{float|f32|f64}::consts` in case folks need to access these at compile time. There are also instances of `int` in `Real` and `RealExt`. In the future these could be replaced with an associated `INTEGER` type on `Real`.
`Natural` has also been renamed to `Integer`. This is because `Natural` normally means 'positive integer' in mathematics. It is therefore strange to implement it on signed integer types. `Integer` is probably a better choice.
I have also switched some of the `Integer` methods to take borrowed pointers as arguments. This brings them in line with the `Quot` and `Rem` traits, and is be better for large Integer types like `BigInt` and `BigUint` because they don't need to be copied unnecessarily.
There has also been considerable discussion on the mailing list and IRC about the renaming of the `Div` and `Modulo` traits to `Quot` and `Rem`. Depending on the outcome of these discussions they might be renamed again.
Unwinding through macros now happens as a call to the trait function `FailWithCause::fail_with()`, which consumes self, allowing to use a more generic failure object in the future.
This brings them in line with the quot and rem traits, and is be better for large Integer types like BigInt and BigUint because they don't need to be copied unnecessarily.
'Natural' normally means 'positive integer' in mathematics. It is therefore strange to implement it on signed integer types. 'Integer' is probably a better choice.
From a cursory `git grep` this removes the last part of `core` that requires on `@` (other than `io` and the task local data section).
It renames `RandRes` to ~~StdRng~~ `IsaacRng` and `XorShiftState` to `XorShiftRng` as well as moving their constructors to static methods. To go with this, it adds `rng()` which is designed to be used when the programmer just wants a random number generator, without caring about which exact algorithm is being used.
It also removes all the `gen_int`, `gen_uint`, `gen_char` (etc) methods on `RngUtil` (by moving the defintions to the actual `Rand` instances). The replacement is using `RngUtil::gen`, either type-inferred or with an annotation (`rng.gen::<uint>()`).
I tried to have the `Rng` and `RngUtil` traits exported by `core::prelude` (since `core::rand` (except for `random()`) is useless without them), but this caused [an explosion of (seemingly unrelated) `error: unresolved import`'s](https://gist.github.com/5451839).
This moves all the basic random value generation into the Rand instances for
each type and then removes the `gen_int`, `gen_char` (etc) methods on RngUtil,
leaving only the generic `gen` and the more specialised methods.
Also, removes some imports that are redundant due to a `use core::prelude::*`
statement.
This adds the following methods to ints and uints:
- div
- modulo
- div_mod
- quot_rem
- gcd
- lcm
- divisible_by
- is_even
- is_odd
I have not implemented Natural for BigInt and BigUInt because they're a little over my head.
This also reverts some changes to TLS that were leaking memory.
Conflicts:
src/libcore/rt/uv/net.rs
src/libcore/task/local_data_priv.rs
src/libcore/unstable/lang.rs
A task without an unwinder will abort the process on failure.
I'm using this in the runtime tests to guarantee that a call to
`assert!` actually triggers some kind of failure (an abort)
instead of silently doing nothing. This is essentially in lieu
of a working linked failure implementation.
This fixes#5976.
It also removes `os::waitpid` in favour of (the existing) `run::waitpid`. I included this change because I figured it is kind of related.
r?
- The return value meant different things on different
platforms (on windows, it was the exit code, on unix it was
the status information returned from waitpid).
- It was undocumented.
- There also exists run::waitpid, which does much the same
thing but has a more consistent return value and also some
documentation.
Closes#3083.
This takes a similar approach to #5797 where a set is present on the `tcx` of used mutable definitions. Everything is by default warned about, and analyses must explicitly add mutable definitions to this set so they're not warned about.
Most of this was pretty straightforward, although there was one caveat that I ran into when implementing it. Apparently when the old modes are used (or maybe `legacy_modes`, I'm not sure) some different code paths are taken to cause spurious warnings to be issued which shouldn't be issued. I'm not really sure how modes even worked, so I was having a lot of trouble tracking this down. I figured that because they're a legacy thing that I'd just de-mode the compiler so that the warnings wouldn't be a problem anymore (or at least for the compiler).
Other than that, the entire compiler compiles without warnings of unused mutable variables. To prevent bad warnings, #5965 should be landed (which in turn is waiting on #5963) before landing this. I figured I'd stick it out for review anyway though.
use core::cell;
fn main() {
let x = cell::Cell(Some(~"foo"));
let y = x.value.get_ref().get_ref();
do x.with_mut_ref |z| { *z = None; }
println(*y) // boom!
}
Things like the GC heap and unwinding are desirable everywhere the language
might be used, not just in tasks. All Rust code should have access to
LocalServices.
This renaming, proposed in the [Numeric Bikeshed](https://github.com/mozilla/rust/wiki/Bikeshed-Numeric-Traits#rename-modulo-into-rem-or-remainder-in-traits-and-docs), will allow us to implement div and and modulo methods that follow the conventional mathematical definitions for negative numbers without altering the definitions of the operators (and confusing systems programmers). Here is a useful answer on StackOverflow that explains the difference between `div`/`mod` and `quot`/`rem` in Haskell: (When is the difference between quotRem and divMod useful?)[http://stackoverflow.com/a/339823/679485].
This is part of the numeric trait reforms tracked in issue #4819.
As the name suggests this replaces many instances of cast::reinterpret_cast by cast::transmute. It's essentially the boring part of fixing #5163, the remaining reinterpret_casts should be more tricky to remove (unless I missed a boring case).
r? @catamorphism
This implements the fixed_stack_segment for items with the rust-intrinsic abi, and then uses it to make f32 and f64 use intrinsics where appropriate, but without overflowing stacks and killing canaries (cf. #5686 and #5697). Hopefully.
@pcwalton, the fixed_stack_segment implementation involved mirroring its implementation in `base.rs` in `trans_closure`, but without adding the `set_no_inline` (reasoning: that would defeat the purpose of intrinsics), which is possibly incorrect.
I'm a little hazy about how the underlying structure works, so I've annotated the 4 that have caused problems so far, but there's no guarantee that the other intrinsics are entirely well-behaved.
Anyway, it has good results (the following are just summing the result of each function for 1 up to 100 million):
```
$ ./intrinsics-perf.sh f32
func new old speedup
sin 0.80 2.75 3.44
cos 0.80 2.76 3.45
sqrt 0.56 2.73 4.88
ln 1.01 2.94 2.91
log10 0.97 2.90 2.99
log2 1.01 2.95 2.92
exp 0.90 2.85 3.17
exp2 0.92 2.87 3.12
pow 6.95 8.57 1.23
geometric mean: 2.97
$ ./intrinsics-perf.sh f64
func new old speedup
sin 12.08 14.06 1.16
cos 12.04 13.67 1.14
sqrt 0.49 2.73 5.57
ln 4.11 5.59 1.36
log10 5.09 6.54 1.28
log2 2.78 5.10 1.83
exp 2.00 3.97 1.99
exp2 1.71 3.71 2.17
pow 5.90 7.51 1.27
geometric mean: 1.72
```
So about 3x faster on average for f32, and 1.7x for f64. This isn't exactly apples to apples though, since this patch also adds #[inline(always)] to all the function definitions too, which possibly gives a speedup.
(fwiw, GitHub is showing 93c0888 after d9c54f8 (since I cherry-picked the latter from #5697), but git's order is the other way.)
Achieves at least 5x speed up for some functions!
Also, reorganise the delegation code so that the delegated function wrappers
have the #[inline(always)] annotation, and reduce the repetition of
delegate!(..).
@thestinger r?
~~The 2 `_unlimited` functions are marked `unsafe` since they may not terminate.~~
The `state` fields of the `Unfoldr` and `Scan` iterators are public, since being able to access the final state after the iteration has finished seems reasonable/possibly useful.
~~Lastly, I converted the tests to use `.to_vec`, which halves the amount of code for them, but it means that a `.transform(|x| *x)` call is required on each iterator.~~
(removed the 2 commits with `to_vec` and `foldl`.)
This allows one to write
```rust
let x = function_with_complicated_return_type();
let size = size_of_val(&x);
```
instead of
```rust
let x = function_with_complicated_return_type();
let size = size_of::<ComplicatedReturnType<Foo, Bar>>();
```
This closes#4364. I came into rust after modes had begun to be phased out, so I'm not exactly sure what they all did. My strategy was basically to turn on the compilation warnings and then when everything compiles and passes all the tests it's all good.
In most cases, I just dropped the mode, but in others I converted things to use `&` pointers when otherwise a move would happen.
This depends on #5963. When running the tests, everything passed except for a few compile-fail tests. These tests leaked memory, causing the task to abort differently. By suppressing the ICE from #5963, no leaks happen and the tests all pass. I would have looked into where the leaks were coming from, but I wasn't sure where or how to debug them (I found `RUSTRT_TRACK_ALLOCATIONS`, but it wasn't all that useful).
This switches the unicode functions in core to use static character-range tables and a binary search helper rather than open-coded switch statements. It adds about 50k of read only data to the libcore binary but cuts out a similar amount of compiled IR. Would have done it this way in the first place but we didn't have structured statics for a long time.
vec::windowed fails if given window size is greater than vector length + 1.
```rust
for vec::windowed(7, &[1,2,3,4,5,6]) |vs| { fail!(); } // => do nothing
for vec::windowed(8, &[1,2,3,4,5,6]) |vs| { fail!(); } // => assertion failure in vec::slice
```