## Contributing
-To contribute to Rust, please see [CONTRIBUTING.md](CONTRIBUTING.md).
+To contribute to Rust, please see [CONTRIBUTING](CONTRIBUTING.md).
Rust has an [IRC] culture and most real-time collaboration happens in a
variety of channels on Mozilla's IRC network, irc.mozilla.org. The
and the Apache License (Version 2.0), with portions covered by various
BSD-like licenses.
-See LICENSE-APACHE, LICENSE-MIT, and COPYRIGHT for details.
+See [LICENSE-APACHE](LICENSE-APACHE), [LICENSE-MIT](LICENSE-MIT), and [COPYRIGHT](COPYRIGHT) for details.
.SH DESCRIPTION
This program is a compiler for the Rust language, available at
-<\fBhttps://www.rust-lang.org\fR>.
+.UR https://www.rust\-lang.org
+.UE .
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
-Display the help message
+Display the help message.
.TP
-\fB\-\-cfg\fR SPEC
-Configure the compilation environment
+\fB\-\-cfg\fR \fISPEC\fR
+Configure the compilation environment.
.TP
-\fB\-L\fR [KIND=]PATH
-Add a directory to the library search path. The optional KIND can be one of:
- dependency = only lookup transitive dependencies here
- crate = only lookup local `extern crate` directives here
- native = only lookup native libraries here
- framework = only look for OSX frameworks here
- all = look for anything here (the default)
+\fB\-L\fR [\fIKIND\fR=]\fIPATH\fR
+Add a directory to the library search path.
+The optional \fIKIND\fR can be one of:
+.RS
.TP
-\fB\-l\fR [KIND=]NAME
-Link the generated crate(s) to the specified native library NAME. The optional
-KIND can be one of, static, dylib, or framework. If omitted, dylib is assumed.
+\fBdependency\fR
+only lookup transitive dependencies here
.TP
-\fB\-\-crate-type\fR [bin|lib|rlib|dylib|staticlib]
-Comma separated list of types of crates for the compiler to emit
+.B crate
+only lookup local `extern crate` directives here
.TP
-\fB\-\-crate-name NAME\fR
-Specify the name of the crate being built
+.B native
+only lookup native libraries here
.TP
-\fB\-\-emit\fR [asm|llvm-bc|llvm-ir|obj|link|dep-info]
-Configure the output that rustc will produce
+.B framework
+only look for OSX frameworks here
.TP
-\fB\-\-print\fR [crate-name|file-names|sysroot]
-Comma separated list of compiler information to print on stdout
+.B all
+look for anything here (the default)
+.RE
+.TP
+\fB\-l\fR [\fIKIND\fR=]\fINAME\fR
+Link the generated crate(s) to the specified native library \fINAME\fR.
+The optional \fIKIND\fR can be one of \fIstatic\fR, \fIdylib\fR, or
+\fIframework\fR.
+If omitted, \fIdylib\fR is assumed.
+.TP
+\fB\-\-crate\-type\fR [bin|lib|rlib|dylib|staticlib]
+Comma separated list of types of crates for the compiler to emit.
+.TP
+\fB\-\-crate\-name\fR \fINAME\fR
+Specify the name of the crate being built.
+.TP
+\fB\-\-emit\fR [asm|llvm\-bc|llvm\-ir|obj|link|dep\-info]
+Configure the output that \fBrustc\fR will produce.
+.TP
+\fB\-\-print\fR [crate\-name|file\-names|sysroot]
+Comma separated list of compiler information to print on stdout.
.TP
\fB\-g\fR
-Equivalent to \fI\-C\fR debuginfo=2
+Equivalent to \fI\-C\ debuginfo=2\fR.
.TP
\fB\-O\fR
-Equivalent to \fI\-C\fR opt-level=2
+Equivalent to \fI\-C\ opt\-level=2\fR.
.TP
-\fB\-o\fR FILENAME
-Write output to <filename>. Ignored if multiple \fI\-\-emit\fR outputs are
-specified.
+\fB\-o\fR \fIFILENAME\fR
+Write output to \fIFILENAME\fR.
+Ignored if multiple \fI\-\-emit\fR outputs are specified.
.TP
-\fB\-\-out\-dir\fR DIR
-Write output to compiler-chosen filename in <dir>. Ignored if \fI\-o\fR is
-specified. Defaults to the current directory.
+\fB\-\-out\-dir\fR \fIDIR\fR
+Write output to compiler\[hy]chosen filename in \fIDIR\fR.
+Ignored if \fI\-o\fR is specified.
+Defaults to the current directory.
.TP
-\fB\-\-explain\fR OPT
-Provide a detailed explanation of an error message
+\fB\-\-explain\fR \fIOPT\fR
+Provide a detailed explanation of an error message.
.TP
\fB\-\-test\fR
-Build a test harness
+Build a test harness.
.TP
-\fB\-\-target\fR TRIPLE
-Target triple cpu-manufacturer-kernel[-os] to compile for (see chapter 3.4 of
-http://www.sourceware.org/autobook/ for details)
+\fB\-\-target\fR \fITRIPLE\fR
+Target triple \fIcpu\fR\-\fImanufacturer\fR\-\fIkernel\fR[\-\fIos\fR]
+to compile for (see chapter 3.4 of
+.UR http://www.sourceware.org/autobook/
+.UE
+for details).
.TP
-\fB\-W\fR help
-Print 'lint' options and default settings
+\fB\-W help\fR
+Print 'lint' options and default settings.
.TP
-\fB\-W\fR OPT, \fB\-\-warn\fR OPT
-Set lint warnings
+\fB\-W\fR \fIOPT\fR, \fB\-\-warn\fR \fIOPT\fR
+Set lint warnings.
.TP
-\fB\-A\fR OPT, \fB\-\-allow\fR OPT
-Set lint allowed
+\fB\-A\fR \fIOPT\fR, \fB\-\-allow\fR \fIOPT\fR
+Set lint allowed.
.TP
-\fB\-D\fR OPT, \fB\-\-deny\fR OPT
-Set lint denied
+\fB\-D\fR \fIOPT\fR, \fB\-\-deny\fR \fIOPT\fR
+Set lint denied.
.TP
-\fB\-F\fR OPT, \fB\-\-forbid\fR OPT
-Set lint forbidden
+\fB\-F\fR \fIOPT\fR, \fB\-\-forbid\fR \fIOPT\fR
+Set lint forbidden.
.TP
-\fB\-C\fR FLAG[=VAL], \fB\-\-codegen\fR FLAG[=VAL]
-Set a codegen-related flag to the value specified. Use "-C help" to print
-available flags. See CODEGEN OPTIONS below
+\fB\-C\fR \fIFLAG\fR[=\fIVAL\fR], \fB\-\-codegen\fR \fIFLAG\fR[=\fIVAL\fR]
+Set a codegen\[hy]related flag to the value specified.
+Use \fI\-C help\fR to print available flags.
+See CODEGEN OPTIONS below.
.TP
\fB\-V\fR, \fB\-\-version\fR
-Print version info and exit
+Print version info and exit.
.TP
\fB\-v\fR, \fB\-\-verbose\fR
-Use verbose output
+Use verbose output.
.TP
-\fB\-\-extern\fR NAME=PATH
-Specify where an external rust library is located
+\fB\-\-extern\fR \fINAME\fR=\fIPATH\fR
+Specify where an external rust library is located.
.TP
-\fB\-\-sysroot\fR PATH
-Override the system root
+\fB\-\-sysroot\fR \fIPATH\fR
+Override the system root.
.TP
-\fB\-Z\fR FLAG
-Set internal debugging options. Use "-Z help" to print available options.
+\fB\-Z\fR \fIFLAG\fR
+Set internal debugging options.
+Use \fI\-Z help\fR to print available options.
.TP
\fB\-\-color\fR auto|always|never
Configure coloring of output:
- auto = colorize, if output goes to a tty (default);
- always = always colorize output;
- never = never colorize output
+.RS
+.TP
+.B auto
+colorize, if output goes to a tty (default);
+.TP
+.B always
+always colorize output;
+.TP
+.B never
+never colorize output.
+.RE
.SH CODEGEN OPTIONS
.TP
-\fBar\fR=/path/to/ar
+\fBar\fR=\fI/path/to/ar\fR
Path to the archive utility to use when assembling archives.
.TP
-\fBlinker\fR=/path/to/cc
+\fBlinker\fR=\fI/path/to/cc\fR
Path to the linker utility to use when linking libraries, executables, and
objects.
.TP
-\fBlink-args\fR='-flag1 -flag2'
-A space-separated list of extra arguments to pass to the linker when the linker
+\fBlink\-args\fR='\fI\-flag1 \-flag2\fR'
+A space\[hy]separated list of extra arguments to pass to the linker when the linker
is invoked.
.TP
\fBlto\fR
-Perform LLVM link-time optimizations.
+Perform LLVM link\[hy]time optimizations.
.TP
-\fBtarget-cpu\fR=help
-Selects a target processor. If the value is 'help', then a list of available
-CPUs is printed.
+\fBtarget\-cpu\fR=\fIhelp\fR
+Selects a target processor.
+If the value is 'help', then a list of available CPUs is printed.
.TP
-\fBtarget-feature\fR='+feature1,-feature2'
-A comma-separated list of features to enable or disable for the target. A
-preceding '+' enables a feature while a preceding '-' disables it. Available
-features can be discovered through target-cpu=help.
+\fBtarget\-feature\fR='\fI+feature1\fR,\fI\-feature2\fR'
+A comma\[hy]separated list of features to enable or disable for the target.
+A preceding '+' enables a feature while a preceding '\-' disables it.
+Available features can be discovered through \fItarget\-cpu=help\fR.
.TP
-\fBpasses\fR=list
-A space-separated list of extra LLVM passes to run. A value of 'list' will
-cause rustc to print all known passes and exit. The passes specified are
-appended at the end of the normal pass manager.
+\fBpasses\fR=\fIval\fR
+A space\[hy]separated list of extra LLVM passes to run.
+A value of 'list' will cause \fBrustc\fR to print all known passes and
+exit.
+The passes specified are appended at the end of the normal pass manager.
.TP
-\fBllvm-args\fR='-arg1 -arg2'
-A space-separated list of arguments to pass through to LLVM.
+\fBllvm\-args\fR='\fI\-arg1\fR \fI\-arg2\fR'
+A space\[hy]separated list of arguments to pass through to LLVM.
.TP
-\fBsave-temps\fR
-If specified, the compiler will save more files (.bc, .o, .no-opt.bc) generated
+\fBsave\-temps\fR
+If specified, the compiler will save more files (.bc, .o, .no\-opt.bc) generated
throughout compilation in the output directory.
.TP
\fBrpath\fR
If specified, then the rpath value for dynamic libraries will be set in
either dynamic library or executable outputs.
.TP
-\fBno-prepopulate-passes\fR
-Suppresses pre-population of the LLVM pass manager that is run over the module.
+\fBno\-prepopulate\-passes\fR
+Suppresses pre\[hy]population of the LLVM pass manager that is run over the module.
.TP
-\fBno-vectorize-loops\fR
+\fBno\-vectorize\-loops\fR
Suppresses running the loop vectorization LLVM pass, regardless of optimization
level.
.TP
-\fBno-vectorize-slp\fR
+\fBno\-vectorize\-slp\fR
Suppresses running the LLVM SLP vectorization pass, regardless of optimization
level.
.TP
-\fBsoft-float\fR
+\fBsoft\-float\fR
Generates software floating point library calls instead of hardware
instructions.
.TP
-\fBprefer-dynamic\fR
+\fBprefer\-dynamic\fR
Prefers dynamic linking to static linking.
.TP
-\fBno-integrated-as\fR
+\fBno\-integrated\-as\fR
Force usage of an external assembler rather than LLVM's integrated one.
.TP
-\fBno-redzone\fR
+\fBno\-redzone\fR
Disable the use of the redzone.
.TP
-\fBrelocation-model\fR=[pic,static,dynamic-no-pic]
-The relocation model to use. (Default: pic)
+\fBrelocation\-model\fR=[pic,static,dynamic\-no\-pic]
+The relocation model to use.
+(Default: \fIpic\fR)
.TP
-\fBcode-model\fR=[small,kernel,medium,large]
+\fBcode\-model\fR=[small,kernel,medium,large]
Choose the code model to use.
.TP
-\fBmetadata\fR=val
+\fBmetadata\fR=\fIval\fR
Metadata to mangle symbol names with.
.TP
-\fBextra-filename\fR=val
+\fBextra\-filename\fR=\fIval\fR
Extra data to put in each output filename.
.TP
-\fBcodegen-units\fR=val
-Divide crate into N units to optimize in parallel.
+\fBcodegen\-units\fR=\fIn\fR
+Divide crate into \fIn\fR units to optimize in parallel.
.TP
-\fBremark\fR=val
+\fBremark\fR=\fIval\fR
Print remarks for these optimization passes (space separated, or "all").
.TP
-\fBno-stack-check\fR
-Disable checks for stack exhaustion (a memory-safety hazard!).
+\fBno\-stack\-check\fR
+Disable checks for stack exhaustion (a memory\[hy]safety hazard!).
.TP
-\fBdebuginfo\fR=val
+\fBdebuginfo\fR=\fIval\fR
Debug info emission level:
- 0 = no debug info;
- 1 = line-tables only (for stacktraces and breakpoints);
- 2 = full debug info with variable and type information.
+.RS
+.TP
+.B 0
+no debug info;
+.TP
+.B 1
+line\[hy]tables only (for stacktraces and breakpoints);
+.TP
+.B 2
+full debug info with variable and type information.
+.RE
.TP
-\fBopt-level\fR=val
-Optimize with possible levels 0-3
+\fBopt\-level\fR=\fIVAL\fR
+Optimize with possible levels 0\[en]3
.SH "EXAMPLES"
To build an executable from a source file with a main function:
- $ rustc -o hello hello.rs
+ $ rustc \-o hello hello.rs
To build a library from a source file:
- $ rustc --crate-type=lib hello-lib.rs
+ $ rustc \-\-crate\-type=lib hello\-lib.rs
To build either with a crate (.rs) file:
$ rustc hello.rs
To build an executable with debug info:
- $ rustc -g -o hello hello.rs
+ $ rustc \-g \-o hello hello.rs
.SH "SEE ALSO"
-rustdoc
+.BR rustdoc (1)
.SH "BUGS"
-See <\fBhttps://github.com/rust-lang/rust/issues\fR> for issues.
+See
+.UR https://github.com/rust\-lang/rust/issues
+.UE
+for issues.
.SH "AUTHOR"
-See \fBAUTHORS.txt\fR in the Rust source distribution.
+See \fIAUTHORS.txt\fR in the Rust source distribution.
.SH "COPYRIGHT"
-This work is dual-licensed under Apache 2.0 and MIT terms. See \fBCOPYRIGHT\fR
-file in the rust source distribution.
+This work is dual\[hy]licensed under Apache\ 2.0 and MIT terms.
+See \fICOPYRIGHT\fR file in the rust source distribution.
.SH DESCRIPTION
This tool generates API reference documentation by extracting comments from
source code written in the Rust language, available at
-<\fBhttps://www.rust-lang.org\fR>. It accepts several input formats and provides
-several output formats for the generated documentation.
+.UR https://www.rust\-lang.org
+.UE .
+It accepts several input formats and provides several output formats
+for the generated documentation.
.SH OPTIONS
.TP
--r --input-format <val>
+\fB\-r\fR, \fB\-\-input\-format\fR \fIFORMAT\fR
html or json (default: inferred)
.TP
--w --output-format <val>
+\fB\-w\fR, \fB\-\-output\-format\fR \fIFORMAT\fR
html or json (default: html)
.TP
--o --output <val>
-where to place the output (default: doc/ for html, doc.json for json)
+\fB\-o\fR, \fB\-\-output\fR \fIOUTPUT\fR
+where to place the output (default: \fIdoc/\fR for html,
+\fIdoc.json\fR for json)
.TP
---passes <val>
-space-separated list of passes to run (default: '')
+\fB\-\-passes\fR \fILIST\fR
+space\[hy]separated list of passes to run (default: '')
.TP
---no-defaults
+\fB\-\-no\-defaults\fR
don't run the default passes
.TP
---plugins <val>
+\fB\-\-plugins\fR \fILIST\fR
space-separated list of plugins to run (default: '')
.TP
---plugin-path <val>
-directory to load plugins from (default: /tmp/rustdoc_ng/plugins)
+\fB\-\-plugin\-path\fR \fIDIR\fR
+directory to load plugins from (default: \fI/tmp/rustdoc_ng/plugins\fR)
.TP
---target <val>
+\fB\-\-target\fR \fITRIPLE\fR
target triple to document
.TP
---crate-name <val>
+\fB\-\-crate\-name\fR \fINAME\fR
specify the name of this crate
.TP
--L --library-path <val>
+\fB\-L\fR, \fB\-\-library\-path\fR \fIDIR\fR
directory to add to crate search path
.TP
---cfg <val>
-pass a --cfg to rustc
+\fB\-\-cfg\fR \fISPEC\fR
+pass a \fI\-\-cfg\fR to rustc
.TP
---extern <val>
-pass an --extern to rustc
+\fB\-\-extern\fR \fIVAL\fR
+pass an \fI\-\-extern\fR to rustc
.TP
---test
+\fB\-\-test\fR
run code examples as tests
.TP
---test-args <val>
+\fB\-\-test\-args\fR \fIARGS\fR
pass arguments to the test runner
.TP
---html-in-header <val>
+\fB\-\-html\-in\-header\fR \fIFILE\fR
file to add to <head>
.TP
---html-before-content <val>
+\fB\-\-html\-before\-content\fR \fIFILE\fR
file to add in <body>, before content
.TP
---html-after-content <val>
+\fB\-\-html\-after\-content\fR \fIFILE\fR
file to add in <body>, after content
.TP
---markdown-css <val>
+\fB\-\-markdown\-css\fR \fIFILE\fR
CSS files to include via <link> in a rendered Markdown file
.TP
---markdown-playground-url <val>
+\fB\-\-markdown\-playground\-url\fR \fIURL\fR
URL to send code snippets to
.TP
---markdown-no-toc
+\fB\-\-markdown\-no\-toc\fR
don't include table of contents
.TP
--h, --help
+\fB\-h\fR, \fB\-\-help\fR
Print help
.TP
--V, --version
+\fB\-V\fR, \fB\-\-version\fR
Print rustdoc's version
.SH "OUTPUT FORMATS"
The rustdoc tool can generate output in either an HTML or JSON format.
If using an HTML format, then the specified output destination will be the root
-directory of an HTML structure for all the documentation. Pages will be placed
-into this directory, and source files will also possibly be rendered into it as
-well.
+directory of an HTML structure for all the documentation.
+Pages will be placed into this directory, and source files will also
+possibly be rendered into it as well.
If using a JSON format, then the specified output destination will have the
-rustdoc output serialized as JSON into it. This output format exists to
-pre-compile documentation for crates, and for usage in non-rustdoc tools. The
-JSON output is the following hash:
+rustdoc output serialized as JSON into it.
+This output format exists to pre\[hy]compile documentation for crates,
+and for usage in non\[hy]rustdoc tools.
+The JSON output is the following hash:
{
"schema": VERSION,
"plugins": ...,
}
-The schema version indicates what the structure of crate/plugins will look
-like. Within a schema version the structure will remain the same. The `crate`
-field will contain all relevant documentation for the source being documented,
-and the `plugins` field will contain the output of the plugins run over the
-crate.
+The schema version indicates what the structure of crate/plugins will
+look like.
+Within a schema version the structure will remain the same.
+The \fIcrate\fR field will contain all relevant documentation for the
+source being documented, and the \fIplugins\fR field will contain the
+output of the plugins run over the crate.
.SH "EXAMPLES"
$ rustdoc hello.rs
List all available passes that rustdoc has, along with default passes:
- $ rustdoc --passes list
+ $ rustdoc \-\-passes list
To precompile the documentation for a crate, and then use it to render html at
a later date:
- $ rustdoc -w json hello.rs
+ $ rustdoc \-w json hello.rs
$ rustdoc doc.json
The generated HTML can be viewed with any standard web browser.
.SH "SEE ALSO"
-rustc
+.BR rustc (1)
.SH "BUGS"
-See <\fBhttps://github.com/rust-lang/rust/issues\fR> for issues.
+See
+.UR https://github.com/rust\-lang/rust/issues
+.UE
+for issues.
.SH "AUTHOR"
-See \fBAUTHORS.txt\fR in the Rust source distribution.
+See \fIAUTHORS.txt\fR in the Rust source distribution.
.SH "COPYRIGHT"
-This work is dual-licensed under Apache 2.0 and MIT terms. See \fBCOPYRIGHT\fR
-file in the rust source distribution.
+This work is dual\[hy]licensed under Apache\ 2.0 and MIT terms.
+See \fICOPYRIGHT\fR file in the rust source distribution.
desc: test::TestDesc {
name: make_test_name(config, testfile),
ignore: header::is_test_ignored(config, testfile),
- should_fail: test::ShouldFail::No,
+ should_panic: test::ShouldPanic::No,
},
testfn: f(),
}
See also [a long thread][alt] on renaming `let mut` to `var`.
[alt]: https://mail.mozilla.org/pipermail/rust-dev/2014-January/008319.html
+
+## Why no `--x` or `x++`?
+
+Preincrement and postincrement, while convenient, are also fairly complex. They
+require knowledge of evaluation order, and often lead to subtle bugs and
+undefined behavior in C and C++. `x = x + 1` or `x += 1` is only slightly
+longer, but unambiguous.
### Array expressions
```antlr
-array_expr : '[' "mut" ? vec_elems? ']' ;
+array_expr : '[' "mut" ? array_elems? ']' ;
array_elems : [expr [',' expr]*] | [expr ',' ".." expr] ;
```
Here's an example of a concurrent Rust program:
```{rust}
-use std::thread::Thread;
+use std::thread;
fn main() {
let guards: Vec<_> = (0..10).map(|_| {
- Thread::scoped(|| {
+ thread::scoped(|| {
println!("Hello, world!");
})
}).collect();
Let's see an example. This Rust code will not compile:
```{rust,ignore}
-use std::thread::Thread;
+use std::thread;
fn main() {
let mut numbers = vec![1, 2, 3];
let guards: Vec<_> = (0..3).map(|i| {
- Thread::scoped(move || {
+ thread::scoped(move || {
numbers[i] += 1;
println!("numbers[{}] is {}", i, numbers[i]);
- });
+ })
}).collect();
}
```
```text
7:25: 10:6 error: cannot move out of captured outer variable in an `FnMut` closure
-7 Thread::scoped(move || {
+7 thread::scoped(move || {
8 numbers[i] += 1;
9 println!("numbers[{}] is {}", i, numbers[i]);
-10 });
+10 })
error: aborting due to previous error
```
Here's what using an Arc with a Mutex looks like:
```{rust}
-use std::thread::Thread;
+use std::thread;
use std::sync::{Arc,Mutex};
fn main() {
let guards: Vec<_> = (0..3).map(|i| {
let number = numbers.clone();
- Thread::scoped(move || {
+ thread::scoped(move || {
let mut array = number.lock().unwrap();
array[i] += 1;
println!("numbers[{}] is {}", i, array[i]);
- });
+ })
}).collect();
}
```
safety check that makes this an error about moved values:
```{rust,ignore}
-use std::thread::Thread;
+use std::thread;
fn main() {
let numbers = vec![1, 2, 3];
let guards: Vec<_> = (0..3).map(|i| {
- Thread::scoped(move || {
+ thread::scoped(move || {
println!("{}", numbers[i]);
- });
+ })
}).collect();
}
```
### Array expressions
```{.ebnf .gram}
-array_expr : '[' "mut" ? vec_elems? ']' ;
+array_expr : '[' "mut" ? array_elems? ']' ;
array_elems : [expr [',' expr]*] | [expr ';' expr] ;
```
Executing an `as` expression casts the value on the left-hand side to the type
on the right-hand side.
-A numeric value can be cast to any numeric type. A raw pointer value can be
-cast to or from any integral type or raw pointer type. Any other cast is
-unsupported and will fail to compile.
-
An example of an `as` expression:
```
let mut file = File::open_mode(&Path::new("my_best_friends.txt"),
Open, Write);
// Early return on error
- try!(file.write_line(format!("name: {}", info.name).as_slice()));
- try!(file.write_line(format!("age: {}", info.age).as_slice()));
- try!(file.write_line(format!("rating: {}", info.rating).as_slice()));
+ try!(file.write_line(&format!("name: {}", info.name)));
+ try!(file.write_line(&format!("age: {}", info.age)));
+ try!(file.write_line(&format!("rating: {}", info.rating)));
return Ok(());
}
```
let mut file = File::open_mode(&Path::new("my_best_friends.txt"),
Open, Write);
// Early return on error
- match file.write_line(format!("name: {}", info.name).as_slice()) {
+ match file.write_line(&format!("name: {}", info.name)) {
Ok(_) => (),
Err(e) => return Err(e)
}
- match file.write_line(format!("age: {}", info.age).as_slice()) {
+ match file.write_line(&format!("age: {}", info.age)) {
Ok(_) => (),
Err(e) => return Err(e)
}
- return file.write_line(format!("rating: {}", info.rating).as_slice());
+ return file.write_line(&format!("rating: {}", info.rating));
}
```
* [Standard Input](standard-input.md)
* [Guessing Game](guessing-game.md)
* [II: Intermediate Rust](intermediate.md)
- * [More Strings](more-strings.md)
* [Crates and Modules](crates-and-modules.md)
* [Testing](testing.md)
* [Pointers](pointers.md)
* [Ownership](ownership.md)
+ * [More Strings](more-strings.md)
* [Patterns](patterns.md)
* [Method Syntax](method-syntax.md)
* [Closures](closures.md)
fn lock(&self) -> LockResult<MutexGuard<T>>
```
-If we [look at the code for MutexGuard](https://github.com/rust-lang/rust/blob/ca4b9674c26c1de07a2042cb68e6a062d7184cef/src/libstd/sync/mutex.rs#L172), we'll see
-this:
-
-```ignore
-__marker: marker::NoSend,
-```
-
-Because our guard is `NoSend`, it's not `Send`. Which means we can't actually
-transfer the guard across thread boundaries, which gives us our error.
+Because `Send` is not implemented for `MutexGuard<T>`, we can't transfer the
+guard across thread boundaries, which gives us our error.
We can use `Arc<T>` to fix this. Here's the working version:
variants correspond to the three kinds of thing `x` could be: `self` if it's
just a value on the stack, `&self` if it's a reference, and `&mut self` if it's
a mutable reference. We should default to using `&self`, as it's the most
-common.
+common. Here's an example of all three variants:
+
+```rust
+struct Circle {
+ x: f64,
+ y: f64,
+ radius: f64,
+}
+
+impl Circle {
+ fn reference(&self) {
+ println!("taking self by reference!");
+ }
+
+ fn mutable_reference(&mut self) {
+ println!("taking self by mutable reference!");
+ }
+
+ fn takes_ownership(self) {
+ println!("taking ownership of self!");
+ }
+}
+```
Finally, as you may remember, the value of the area of a circle is `π*r²`.
Because we took the `&self` parameter to `area`, we can use it just like any
Many more bytes than graphemes!
-# Other Documentation
+# `Deref` coercions
-* [the `&str` API documentation](../std/str/index.html)
-* [the `String` API documentation](../std/string/index.html)
+References to `String`s will automatically coerce into `&str`s. Like this:
+
+```
+fn hello(s: &str) {
+ println!("Hello, {}!", s);
+}
+
+let slice = "Steve";
+let string = "Steve".to_string();
+
+hello(slice);
+hello(&string);
+```
```ignore
#![crate_type="dylib"]
-#![feature(plugin_registrar)]
+#![feature(plugin_registrar, rustc_private)]
extern crate syntax;
extern crate rustc;
}
};
- let mut text = &text;
+ let mut text = &*text;
let mut total = 0;
while !text.is_empty() {
match NUMERALS.iter().find(|&&(rn, _)| text.starts_with(rn)) {
Some(&(rn, val)) => {
total += val;
- text = text.slice_from(rn.len());
+ text = &text[rn.len()..];
}
None => {
cx.span_err(sp, "invalid Roman numeral");
}
}
- MacEager::expr(cx.expr_usize(sp, total))
+ MacEager::expr(cx.expr_u32(sp, total))
}
#[plugin_registrar]
### Returning data
This is important enough to have its own section entirely. The TL;DR is this:
-you don't generally want to return pointers, even when you might in a language
-like C or C++.
+you don't want to return pointers, even when you might in a language like C or
+C++.
See [Returning Pointers](#returning-pointers) below for more.
println!("the inverse of {} is {:?}", 0.0f32, inverse(0.0f32));
println!("the inverse of {} is {:?}", 0.0f64, inverse(0.0f64));
```
+
+## Default methods
+
+There's one last feature of traits we should cover: default methods. It's
+easiest just to show an example:
+
+```rust
+trait Foo {
+ fn bar(&self);
+
+ fn baz(&self) { println!("We called baz."); }
+}
+```
+
+Implementors of the `Foo` trait need to implement `bar()`, but they don't
+need to implement `baz()`. They'll get this default behavior. They can
+override the default if they so choose:
+
+```rust
+# trait Foo {
+# fn bar(&self);
+# fn baz(&self) { println!("We called baz."); }
+# }
+struct UseDefault;
+
+impl Foo for UseDefault {
+ fn bar(&self) { println!("We called bar."); }
+}
+
+struct OverrideDefault;
+
+impl Foo for OverrideDefault {
+ fn bar(&self) { println!("We called bar."); }
+
+ fn baz(&self) { println!("Override baz!"); }
+}
+
+let default = UseDefault;
+default.baz(); // prints "We called bar."
+
+let over = OverrideDefault;
+over.baz(); // prints "Override baz!"
+```
}
#[test]
-#[should_fail]
+#[should_panic]
fn test_arena_destructors_fail() {
let arena = Arena::new();
// Put some stuff in the arena.
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_overflow() {
#[allow(dead_code)]
#[derive(Copy)]
//! // for details, and the function `pad` can be used to pad strings.
//! let decimals = f.precision().unwrap_or(3);
//! let string = f64::to_str_exact(magnitude, decimals);
-//! f.pad_integral(true, "", string.as_slice())
+//! f.pad_integral(true, "", &string)
//! }
//! }
//!
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_tail_empty() {
let a = Vec::<i32>::new();
a.tail();
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_tail_mut_empty() {
let mut a = Vec::<i32>::new();
a.tail_mut();
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_init_empty() {
let a = Vec::<i32>::new();
a.init();
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_init_mut_empty() {
let mut a = Vec::<i32>::new();
a.init_mut();
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_swap_remove_fail() {
let mut v = vec![1];
let _ = v.swap_remove(0);
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_insert_oob() {
let mut a = vec![1, 2, 3];
a.insert(4, 5);
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_remove_fail() {
let mut a = vec![1];
let _ = a.remove(0);
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_permute_fail() {
let v: [(Box<_>, Rc<_>); 4] =
[(box 0, Rc::new(0)), (box 0, Rc::new(0)),
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_windowsator_0() {
let v = &[1,2,3,4];
let _it = v.windows(0);
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_chunksator_0() {
let v = &[1,2,3,4];
let _it = v.chunks(0);
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_overflow_does_not_cause_segfault() {
let mut v = vec![];
v.reserve_exact(-1);
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_overflow_does_not_cause_segfault_managed() {
let mut v = vec![Rc::new(1)];
v.reserve_exact(-1);
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_mut_chunks_0() {
let mut v = [1, 2, 3, 4];
let _it = v.chunks_mut(0);
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_slice_fail() {
"中华Việt Nam".slice(0, 2);
}
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_as_bytes_fail() {
// Don't double free. (I'm not sure if this exercises the
// original problem code path anymore.)
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_subslice_offset_2() {
let a = "alchemiter";
let b = "cruxtruder";
/// ```rust
/// let input = b"Hello \xF0\x90\x80World";
/// let output = String::from_utf8_lossy(input);
- /// assert_eq!(output.as_slice(), "Hello \u{FFFD}World");
+ /// assert_eq!(output, "Hello \u{FFFD}World");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> Cow<'a, str> {
/// ```
/// let mut s = String::from_str("foo");
/// s.push_str("bar");
- /// assert_eq!(s.as_slice(), "foobar");
+ /// assert_eq!(s, "foobar");
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
/// s.push('1');
/// s.push('2');
/// s.push('3');
- /// assert_eq!(s.as_slice(), "abc123");
+ /// assert_eq!(s, "abc123");
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
/// ```
/// let mut s = String::from_str("hello");
/// s.truncate(2);
- /// assert_eq!(s.as_slice(), "he");
+ /// assert_eq!(s, "he");
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
/// assert!(vec == &[104, 101, 108, 108, 111]);
/// vec.reverse();
/// }
- /// assert_eq!(s.as_slice(), "olleh");
+ /// assert_eq!(s, "olleh");
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_str_truncate_invalid_len() {
let mut s = String::from_str("12345");
s.truncate(6);
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_str_truncate_split_codepoint() {
let mut s = String::from_str("\u{FC}"); // ü
s.truncate(1);
assert_eq!(s, "ไทย中华Vit Nam; foobar");
}
- #[test] #[should_fail]
+ #[test] #[should_panic]
fn remove_bad() {
"ศ".to_string().remove(1);
}
assert_eq!(s, "ệfooยbar");
}
- #[test] #[should_fail] fn insert_bad1() { "".to_string().insert(1, 't'); }
- #[test] #[should_fail] fn insert_bad2() { "ệ".to_string().insert(1, 't'); }
+ #[test] #[should_panic] fn insert_bad1() { "".to_string().insert(1, 't'); }
+ #[test] #[should_panic] fn insert_bad2() { "ệ".to_string().insert(1, 't'); }
#[test]
fn test_slicing() {
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_vec_truncate_fail() {
struct BadElem(i32);
impl Drop for BadElem {
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_index_out_of_bounds() {
let vec = vec![1, 2, 3];
let _ = vec[3];
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_slice_out_of_bounds_1() {
let x = vec![1, 2, 3, 4, 5];
&x[-1..];
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_slice_out_of_bounds_2() {
let x = vec![1, 2, 3, 4, 5];
&x[..6];
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_slice_out_of_bounds_3() {
let x = vec![1, 2, 3, 4, 5];
&x[-1..4];
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_slice_out_of_bounds_4() {
let x = vec![1, 2, 3, 4, 5];
&x[1..6];
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_slice_out_of_bounds_5() {
let x = vec![1, 2, 3, 4, 5];
&x[3..2];
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_swap_remove_empty() {
let mut vec= Vec::<i32>::new();
vec.swap_remove(0);
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_map_in_place_incompatible_types_fail() {
let v = vec![0, 1, 2];
v.map_in_place(|_| ());
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_index_out_of_bounds() {
let mut deq = VecDeque::new();
for i in 1..4 {
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_index_nonexistent() {
let mut map = VecMap::new();
///
/// Types like `Cell<T>` and `RefCell<T>` use this type to wrap their internal data.
///
-/// `UnsafeCell<T>` doesn't opt-out from any marker traits, instead, types with an `UnsafeCell<T>`
-/// interior are expected to opt-out from those traits themselves.
-///
/// # Examples
///
/// ```
pub fn u32_mul_with_overflow(x: u32, y: u32) -> (u32, bool);
/// Performs checked `u64` multiplication.
pub fn u64_mul_with_overflow(x: u64, y: u64) -> (u64, bool);
-}
-// SNAP 880fb89
-#[cfg(not(stage0))]
-extern "rust-intrinsic" {
/// Returns (a + b) mod 2^N, where N is the width of N in bits.
pub fn overflowing_add<T>(a: T, b: T) -> T;
/// Returns (a - b) mod 2^N, where N is the width of N in bits.
///
/// ```
/// let a = [1, 2, 3, 4, 5];
- /// assert!(a.iter().fold(0, |a, &b| a + b) == 15);
+ /// assert!(a.iter().fold(0, |acc, &item| acc + item) == 15);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
/// the `sync` crate do ensure that any mutation cannot cause data
/// races. Hence these types are `Sync`.
///
-/// Users writing their own types with interior mutability (or anything
-/// else that is not thread-safe) should use the `NoSync` marker type
-/// (from `std::marker`) to ensure that the compiler doesn't
-/// consider the user-defined type to be `Sync`. Any types with
-/// interior mutability must also use the `std::cell::UnsafeCell` wrapper
-/// around the value(s) which can be mutated when behind a `&`
-/// reference; not doing this is undefined behaviour (for example,
-/// `transmute`-ing from `&T` to `&mut T` is illegal).
+/// Any types with interior mutability must also use the `std::cell::UnsafeCell` wrapper around the
+/// value(s) which can be mutated when behind a `&` reference; not doing this is undefined
+/// behaviour (for example, `transmute`-ing from `&T` to `&mut T` is illegal).
#[stable(feature = "rust1", since = "1.0.0")]
#[lang="sync"]
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
/// instance, it will behave *as if* an instance of the type `T` were
/// present for the purpose of various automatic analyses.
///
-/// For example, embedding a `PhantomData<T>` will inform the compiler
+/// # Examples
+///
+/// When handling external resources over a foreign function interface, `PhantomData<T>` can
+/// prevent mismatches by enforcing types in the method implementations, although the struct
+/// doesn't actually contain values of the resource type.
+///
+/// ```
+/// # trait ResType { fn foo(&self); };
+/// # struct ParamType;
+/// # mod foreign_lib {
+/// # pub fn new(_: usize) -> *mut () { 42 as *mut () }
+/// # pub fn do_stuff(_: *mut (), _: usize) {}
+/// # }
+/// # fn convert_params(_: ParamType) -> usize { 42 }
+/// use std::marker::PhantomData;
+/// use std::mem;
+///
+/// struct ExternalResource<R> {
+/// resource_handle: *mut (),
+/// resource_type: PhantomData<R>,
+/// }
+///
+/// impl<R: ResType> ExternalResource<R> {
+/// fn new() -> ExternalResource<R> {
+/// let size_of_res = mem::size_of::<R>();
+/// ExternalResource {
+/// resource_handle: foreign_lib::new(size_of_res),
+/// resource_type: PhantomData,
+/// }
+/// }
+///
+/// fn do_stuff(&self, param: ParamType) {
+/// let foreign_params = convert_params(param);
+/// foreign_lib::do_stuff(self.resource_handle, foreign_params);
+/// }
+/// }
+/// ```
+///
+/// Another example: embedding a `PhantomData<T>` will inform the compiler
/// that one or more instances of the type `T` could be dropped when
/// instances of the type itself is dropped, though that may not be
/// apparent from the other structure of the type itself. This is
fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::Err>;
}
-/// A utility function that just calls FromStrRadix::from_str_radix.
+/// A utility function that just calls `FromStrRadix::from_str_radix`.
#[unstable(feature = "core", reason = "needs reevaluation")]
pub fn from_str_radix<T: FromStrRadix>(str: &str, radix: u32)
-> Result<T, T::Err> {
use ops::*;
-#[cfg(not(stage0))]
use intrinsics::{overflowing_add, overflowing_sub, overflowing_mul};
use intrinsics::{i8_add_with_overflow, u8_add_with_overflow};
fn overflowing_mul(self, rhs: Self) -> (Self, bool);
}
-#[cfg(not(stage0))]
macro_rules! wrapping_impl {
($($t:ty)*) => ($(
impl WrappingOps for $t {
)*)
}
-#[cfg(stage0)]
-macro_rules! wrapping_impl {
- ($($t:ty)*) => ($(
- impl WrappingOps for $t {
- #[inline(always)]
- fn wrapping_add(self, rhs: $t) -> $t {
- self + rhs
- }
- #[inline(always)]
- fn wrapping_sub(self, rhs: $t) -> $t {
- self - rhs
- }
- #[inline(always)]
- fn wrapping_mul(self, rhs: $t) -> $t {
- self * rhs
- }
- }
- )*)
-}
-
wrapping_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 }
#[unstable(feature = "core", reason = "may be removed, renamed, or relocated")]
//! fn write_info(info: &Info) -> Result<(), IoError> {
//! let mut file = File::open_mode(&Path::new("my_best_friends.txt"), Open, Write);
//! // Early return on error
-//! if let Err(e) = file.write_line(format!("name: {}", info.name).as_slice()) {
+//! if let Err(e) = file.write_line(&format!("name: {}", info.name)) {
//! return Err(e)
//! }
-//! if let Err(e) = file.write_line(format!("age: {}", info.age).as_slice()) {
+//! if let Err(e) = file.write_line(&format!("age: {}", info.age)) {
//! return Err(e)
//! }
-//! return file.write_line(format!("rating: {}", info.rating).as_slice());
+//! return file.write_line(&format!("rating: {}", info.rating));
//! }
//! ```
//!
//! fn write_info(info: &Info) -> Result<(), IoError> {
//! let mut file = File::open_mode(&Path::new("my_best_friends.txt"), Open, Write);
//! // Early return on error
-//! try!(file.write_line(format!("name: {}", info.name).as_slice()));
-//! try!(file.write_line(format!("age: {}", info.age).as_slice()));
-//! try!(file.write_line(format!("rating: {}", info.rating).as_slice()));
+//! try!(file.write_line(&format!("name: {}", info.name)));
+//! try!(file.write_line(&format!("age: {}", info.age)));
+//! try!(file.write_line(&format!("rating: {}", info.rating)));
//! return Ok(());
//! }
//! ```
}
#[test]
-#[should_fail]
+#[should_panic]
fn discard_doesnt_unborrow() {
let x = RefCell::new(0);
let _b = x.borrow();
}
#[test]
-#[should_fail]
+#[should_panic]
fn test_fail() {
let mut i = 0;
try_finally(
}
#[test]
-#[should_fail]
+#[should_panic]
fn test_radix_base_too_large() {
let _ = radix(55, 37);
}
}
#[test]
-#[should_fail]
+#[should_panic]
fn test_rposition_panic() {
let v: [(Box<_>, Box<_>); 4] =
[(box 0, box 0), (box 0, box 0),
assert!(y.is_none());
}
-#[test] #[should_fail]
+#[test] #[should_panic]
fn test_option_too_much_dance() {
let mut y = Some(marker::NoCopy);
let _y2 = y.take().unwrap();
}
#[test]
-#[should_fail]
+#[should_panic]
fn test_unwrap_panic1() {
let x: Option<int> = None;
x.unwrap();
}
#[test]
-#[should_fail]
+#[should_panic]
fn test_unwrap_panic2() {
let x: Option<String> = None;
x.unwrap();
}
#[test]
-#[should_fail]
+#[should_panic]
pub fn test_unwrap_or_else_panic() {
fn handler(msg: &'static str) -> int {
if msg == "I got this." {
//!
//! fn print_usage(program: &str, opts: &[OptGroup]) {
//! let brief = format!("Usage: {} [options]", program);
-//! print!("{}", usage(brief.as_slice(), opts));
+//! print!("{}", usage(brief, opts));
//! }
//!
//! fn main() {
//! Err(f) => { panic!(f.to_string()) }
//! };
//! if matches.opt_present("h") {
-//! print_usage(program.as_slice(), opts);
+//! print_usage(program, opts);
//! return;
//! }
//! let output = matches.opt_str("o");
//! let input = if !matches.free.is_empty() {
//! matches.free[0].clone()
//! } else {
-//! print_usage(program.as_slice(), opts);
+//! print_usage(program, opts);
//! return;
//! };
-//! do_work(input.as_slice(), output);
+//! do_work(input, output);
//! }
//! ```
}
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_exp_invalid_lambda_zero() {
Exp::new(0.0);
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_exp_invalid_lambda_neg() {
Exp::new(-10.0);
}
}
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_chi_squared_invalid_dof() {
ChiSquared::new(-1.0);
}
[50, 51, 52, 53, 54, 55, 56]);
}
- #[test] #[should_fail]
+ #[test] #[should_panic]
fn test_weighted_choice_no_items() {
WeightedChoice::<int>::new(&mut []);
}
- #[test] #[should_fail]
+ #[test] #[should_panic]
fn test_weighted_choice_zero_weight() {
WeightedChoice::new(&mut [Weighted { weight: 0, item: 0},
Weighted { weight: 0, item: 1}]);
}
- #[test] #[should_fail]
+ #[test] #[should_panic]
fn test_weighted_choice_weight_overflows() {
let x = (-1) as uint / 2; // x + x + 2 is the overflow
WeightedChoice::new(&mut [Weighted { weight: x, item: 0 },
}
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_normal_invalid_sd() {
Normal::new(10.0, -1.0);
}
}
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_log_normal_invalid_sd() {
LogNormal::new(10.0, -1.0);
}
use distributions::{Sample, IndependentSample};
use super::Range as Range;
- #[should_fail]
+ #[should_panic]
#[test]
fn test_range_bad_limits_equal() {
Range::new(10, 10);
}
- #[should_fail]
+ #[should_panic]
#[test]
fn test_range_bad_limits_flipped() {
Range::new(10, 5);
//! The ISAAC random number generator.
+#![allow(non_camel_case_types)]
+
use core::prelude::*;
use core::slice;
use core::iter::{range_step, repeat};
-use core::num::wrapping::Wrapping;
+use core::num::wrapping::Wrapping as w;
use {Rng, SeedableRng, Rand};
-const RAND_SIZE_LEN: u32 = 8;
-const RAND_SIZE: u32 = 1 << (RAND_SIZE_LEN as uint);
-const RAND_SIZE_UINT: uint = 1 << (RAND_SIZE_LEN as uint);
+type w32 = w<u32>;
+type w64 = w<u64>;
+
+const RAND_SIZE_LEN: usize = 8;
+const RAND_SIZE: u32 = 1 << RAND_SIZE_LEN;
+const RAND_SIZE_USIZE: usize = 1 << RAND_SIZE_LEN;
/// A random number generator that uses the ISAAC algorithm[1].
///
#[derive(Copy)]
pub struct IsaacRng {
cnt: u32,
- rsl: [u32; RAND_SIZE_UINT],
- mem: [u32; RAND_SIZE_UINT],
- a: u32,
- b: u32,
- c: u32
+ rsl: [w32; RAND_SIZE_USIZE],
+ mem: [w32; RAND_SIZE_USIZE],
+ a: w32,
+ b: w32,
+ c: w32,
}
static EMPTY: IsaacRng = IsaacRng {
cnt: 0,
- rsl: [0; RAND_SIZE_UINT],
- mem: [0; RAND_SIZE_UINT],
- a: 0, b: 0, c: 0
+ rsl: [w(0); RAND_SIZE_USIZE],
+ mem: [w(0); RAND_SIZE_USIZE],
+ a: w(0), b: w(0), c: w(0),
};
impl IsaacRng {
/// of `rsl` as a seed, otherwise construct one algorithmically (not
/// randomly).
fn init(&mut self, use_rsl: bool) {
- let mut a = Wrapping(0x9e3779b9);
+ let mut a = w(0x9e3779b9);
let mut b = a;
let mut c = a;
let mut d = a;
if use_rsl {
macro_rules! memloop {
($arr:expr) => {{
- for i in range_step(0, RAND_SIZE as uint, 8) {
- a=a+Wrapping($arr[i ]); b=b+Wrapping($arr[i+1]);
- c=c+Wrapping($arr[i+2]); d=d+Wrapping($arr[i+3]);
- e=e+Wrapping($arr[i+4]); f=f+Wrapping($arr[i+5]);
- g=g+Wrapping($arr[i+6]); h=h+Wrapping($arr[i+7]);
+ for i in range_step(0, RAND_SIZE_USIZE, 8) {
+ a=a+$arr[i ]; b=b+$arr[i+1];
+ c=c+$arr[i+2]; d=d+$arr[i+3];
+ e=e+$arr[i+4]; f=f+$arr[i+5];
+ g=g+$arr[i+6]; h=h+$arr[i+7];
mix!();
- self.mem[i ]=a.0; self.mem[i+1]=b.0;
- self.mem[i+2]=c.0; self.mem[i+3]=d.0;
- self.mem[i+4]=e.0; self.mem[i+5]=f.0;
- self.mem[i+6]=g.0; self.mem[i+7]=h.0;
+ self.mem[i ]=a; self.mem[i+1]=b;
+ self.mem[i+2]=c; self.mem[i+3]=d;
+ self.mem[i+4]=e; self.mem[i+5]=f;
+ self.mem[i+6]=g; self.mem[i+7]=h;
}
}}
}
memloop!(self.rsl);
memloop!(self.mem);
} else {
- for i in range_step(0, RAND_SIZE as uint, 8) {
+ for i in range_step(0, RAND_SIZE_USIZE, 8) {
mix!();
- self.mem[i ]=a.0; self.mem[i+1]=b.0;
- self.mem[i+2]=c.0; self.mem[i+3]=d.0;
- self.mem[i+4]=e.0; self.mem[i+5]=f.0;
- self.mem[i+6]=g.0; self.mem[i+7]=h.0;
+ self.mem[i ]=a; self.mem[i+1]=b;
+ self.mem[i+2]=c; self.mem[i+3]=d;
+ self.mem[i+4]=e; self.mem[i+5]=f;
+ self.mem[i+6]=g; self.mem[i+7]=h;
}
}
#[inline]
#[allow(unsigned_negation)]
fn isaac(&mut self) {
- self.c += 1;
+ self.c = self.c + w(1);
// abbreviations
let mut a = self.a;
let mut b = self.b + self.c;
- const MIDPOINT: uint = (RAND_SIZE / 2) as uint;
+ const MIDPOINT: usize = RAND_SIZE_USIZE / 2;
macro_rules! ind {
- ($x:expr) => (Wrapping( self.mem[(($x >> 2) as uint &
- ((RAND_SIZE - 1) as uint))] ))
+ ($x:expr) => ( self.mem[($x >> 2).0 as usize & (RAND_SIZE_USIZE - 1)] )
}
let r = [(0, MIDPOINT), (MIDPOINT, 0)];
- for &(mr_offset, m2_offset) in &r {
+ for &(mr_offset, m2_offset) in r.iter() {
macro_rules! rngstepp {
($j:expr, $shift:expr) => {{
let base = $j;
- let mix = a << $shift as uint;
+ let mix = a << $shift;
let x = self.mem[base + mr_offset];
- a = (Wrapping(a ^ mix) + Wrapping(self.mem[base + m2_offset])).0;
- let y = ind!(x) + Wrapping(a) + Wrapping(b);
- self.mem[base + mr_offset] = y.0;
+ a = (a ^ mix) + self.mem[base + m2_offset];
+ let y = ind!(x) + a + b;
+ self.mem[base + mr_offset] = y;
- b = (ind!(y.0 >> RAND_SIZE_LEN as uint) + Wrapping(x)).0;
+ b = ind!(y >> RAND_SIZE_LEN) + x;
self.rsl[base + mr_offset] = b;
}}
}
macro_rules! rngstepn {
($j:expr, $shift:expr) => {{
let base = $j;
- let mix = a >> $shift as uint;
+ let mix = a >> $shift;
let x = self.mem[base + mr_offset];
- a = (Wrapping(a ^ mix) + Wrapping(self.mem[base + m2_offset])).0;
- let y = ind!(x) + Wrapping(a) + Wrapping(b);
- self.mem[base + mr_offset] = y.0;
+ a = (a ^ mix) + self.mem[base + m2_offset];
+ let y = ind!(x) + a + b;
+ self.mem[base + mr_offset] = y;
- b = (ind!(y.0 >> RAND_SIZE_LEN as uint) + Wrapping(x)).0;
+ b = ind!(y >> RAND_SIZE_LEN) + x;
self.rsl[base + mr_offset] = b;
}}
}
// (the % is cheaply telling the optimiser that we're always
// in bounds, without unsafe. NB. this is a power of two, so
// it optimises to a bitwise mask).
- self.rsl[(self.cnt % RAND_SIZE) as uint]
+ self.rsl[(self.cnt % RAND_SIZE) as usize].0
}
}
let seed_iter = seed.iter().cloned().chain(repeat(0));
for (rsl_elem, seed_elem) in self.rsl.iter_mut().zip(seed_iter) {
- *rsl_elem = seed_elem;
+ *rsl_elem = w(seed_elem);
}
self.cnt = 0;
- self.a = 0;
- self.b = 0;
- self.c = 0;
+ self.a = w(0);
+ self.b = w(0);
+ self.c = w(0);
self.init(true);
}
unsafe {
let ptr = ret.rsl.as_mut_ptr() as *mut u8;
- let slice = slice::from_raw_parts_mut(ptr, (RAND_SIZE * 4) as uint);
+ let slice = slice::from_raw_parts_mut(ptr, RAND_SIZE_USIZE * 4);
other.fill_bytes(slice);
}
ret.cnt = 0;
- ret.a = 0;
- ret.b = 0;
- ret.c = 0;
+ ret.a = w(0);
+ ret.b = w(0);
+ ret.c = w(0);
ret.init(true);
return ret;
}
}
-const RAND_SIZE_64_LEN: uint = 8;
-const RAND_SIZE_64: uint = 1 << RAND_SIZE_64_LEN;
+const RAND_SIZE_64_LEN: usize = 8;
+const RAND_SIZE_64: usize = 1 << RAND_SIZE_64_LEN;
/// A random number generator that uses ISAAC-64[1], the 64-bit
/// variant of the ISAAC algorithm.
/// generator*](http://www.burtleburtle.net/bob/rand/isaacafa.html)
#[derive(Copy)]
pub struct Isaac64Rng {
- cnt: uint,
- rsl: [u64; RAND_SIZE_64],
- mem: [u64; RAND_SIZE_64],
- a: u64,
- b: u64,
- c: u64,
+ cnt: usize,
+ rsl: [w64; RAND_SIZE_64],
+ mem: [w64; RAND_SIZE_64],
+ a: w64,
+ b: w64,
+ c: w64,
}
static EMPTY_64: Isaac64Rng = Isaac64Rng {
cnt: 0,
- rsl: [0; RAND_SIZE_64],
- mem: [0; RAND_SIZE_64],
- a: 0, b: 0, c: 0,
+ rsl: [w(0); RAND_SIZE_64],
+ mem: [w(0); RAND_SIZE_64],
+ a: w(0), b: w(0), c: w(0),
};
impl Isaac64Rng {
fn init(&mut self, use_rsl: bool) {
macro_rules! init {
($var:ident) => (
- let mut $var = Wrapping(0x9e3779b97f4a7c13);
+ let mut $var = w(0x9e3779b97f4a7c13);
)
}
init!(a); init!(b); init!(c); init!(d);
macro_rules! mix {
() => {{
- a=a-e; f=f^h>>9; h=h+a;
- b=b-f; g=g^a<<9; a=a+b;
- c=c-g; h=h^b>>23; b=b+c;
- d=d-h; a=a^c<<15; c=c+d;
- e=e-a; b=b^d>>14; d=d+e;
- f=f-b; c=c^e<<20; e=e+f;
- g=g-c; d=d^f>>17; f=f+g;
- h=h-d; e=e^g<<14; g=g+h;
+ a=a-e; f=f^(h>>9); h=h+a;
+ b=b-f; g=g^(a<<9); a=a+b;
+ c=c-g; h=h^(b>>23); b=b+c;
+ d=d-h; a=a^(c<<15); c=c+d;
+ e=e-a; b=b^(d>>14); d=d+e;
+ f=f-b; c=c^(e<<20); e=e+f;
+ g=g-c; d=d^(f>>17); f=f+g;
+ h=h-d; e=e^(g<<14); g=g+h;
}}
}
macro_rules! memloop {
($arr:expr) => {{
for i in (0..RAND_SIZE_64 / 8).map(|i| i * 8) {
- a=a+Wrapping($arr[i ]); b=b+Wrapping($arr[i+1]);
- c=c+Wrapping($arr[i+2]); d=d+Wrapping($arr[i+3]);
- e=e+Wrapping($arr[i+4]); f=f+Wrapping($arr[i+5]);
- g=g+Wrapping($arr[i+6]); h=h+Wrapping($arr[i+7]);
+ a=a+$arr[i ]; b=b+$arr[i+1];
+ c=c+$arr[i+2]; d=d+$arr[i+3];
+ e=e+$arr[i+4]; f=f+$arr[i+5];
+ g=g+$arr[i+6]; h=h+$arr[i+7];
mix!();
- self.mem[i ]=a.0; self.mem[i+1]=b.0;
- self.mem[i+2]=c.0; self.mem[i+3]=d.0;
- self.mem[i+4]=e.0; self.mem[i+5]=f.0;
- self.mem[i+6]=g.0; self.mem[i+7]=h.0;
+ self.mem[i ]=a; self.mem[i+1]=b;
+ self.mem[i+2]=c; self.mem[i+3]=d;
+ self.mem[i+4]=e; self.mem[i+5]=f;
+ self.mem[i+6]=g; self.mem[i+7]=h;
}
}}
}
} else {
for i in (0..RAND_SIZE_64 / 8).map(|i| i * 8) {
mix!();
- self.mem[i ]=a.0; self.mem[i+1]=b.0;
- self.mem[i+2]=c.0; self.mem[i+3]=d.0;
- self.mem[i+4]=e.0; self.mem[i+5]=f.0;
- self.mem[i+6]=g.0; self.mem[i+7]=h.0;
+ self.mem[i ]=a; self.mem[i+1]=b;
+ self.mem[i+2]=c; self.mem[i+3]=d;
+ self.mem[i+4]=e; self.mem[i+5]=f;
+ self.mem[i+6]=g; self.mem[i+7]=h;
}
}
/// Refills the output buffer (`self.rsl`)
fn isaac64(&mut self) {
- self.c += 1;
+ self.c = self.c + w(1);
// abbreviations
- let mut a = Wrapping(self.a);
- let mut b = Wrapping(self.b) + Wrapping(self.c);
- const MIDPOINT: uint = RAND_SIZE_64 / 2;
- const MP_VEC: [(uint, uint); 2] = [(0,MIDPOINT), (MIDPOINT, 0)];
+ let mut a = self.a;
+ let mut b = self.b + self.c;
+ const MIDPOINT: usize = RAND_SIZE_64 / 2;
+ const MP_VEC: [(usize, usize); 2] = [(0,MIDPOINT), (MIDPOINT, 0)];
macro_rules! ind {
($x:expr) => {
- *self.mem.get_unchecked(($x as uint >> 3) & (RAND_SIZE_64 - 1))
+ *self.mem.get_unchecked((($x >> 3).0 as usize) & (RAND_SIZE_64 - 1))
}
}
- for &(mr_offset, m2_offset) in &MP_VEC {
+ for &(mr_offset, m2_offset) in MP_VEC.iter() {
for base in (0..MIDPOINT / 4).map(|i| i * 4) {
macro_rules! rngstepp {
($j:expr, $shift:expr) => {{
let base = base + $j;
- let mix = a ^ (a << $shift as uint);
+ let mix = a ^ (a << $shift);
let mix = if $j == 0 {!mix} else {mix};
unsafe {
- let x = Wrapping(*self.mem.get_unchecked(base + mr_offset));
- a = mix + Wrapping(*self.mem.get_unchecked(base + m2_offset));
- let y = Wrapping(ind!(x.0)) + a + b;
- *self.mem.get_unchecked_mut(base + mr_offset) = y.0;
+ let x = *self.mem.get_unchecked(base + mr_offset);
+ a = mix + *self.mem.get_unchecked(base + m2_offset);
+ let y = ind!(x) + a + b;
+ *self.mem.get_unchecked_mut(base + mr_offset) = y;
- b = Wrapping(ind!(y.0 >> RAND_SIZE_64_LEN)) + x;
- *self.rsl.get_unchecked_mut(base + mr_offset) = b.0;
+ b = ind!(y >> RAND_SIZE_64_LEN) + x;
+ *self.rsl.get_unchecked_mut(base + mr_offset) = b;
}
}}
}
macro_rules! rngstepn {
($j:expr, $shift:expr) => {{
let base = base + $j;
- let mix = a ^ (a >> $shift as uint);
+ let mix = a ^ (a >> $shift);
let mix = if $j == 0 {!mix} else {mix};
unsafe {
- let x = Wrapping(*self.mem.get_unchecked(base + mr_offset));
- a = mix + Wrapping(*self.mem.get_unchecked(base + m2_offset));
- let y = Wrapping(ind!(x.0)) + a + b;
- *self.mem.get_unchecked_mut(base + mr_offset) = y.0;
+ let x = *self.mem.get_unchecked(base + mr_offset);
+ a = mix + *self.mem.get_unchecked(base + m2_offset);
+ let y = ind!(x) + a + b;
+ *self.mem.get_unchecked_mut(base + mr_offset) = y;
- b = Wrapping(ind!(y.0 >> RAND_SIZE_64_LEN)) + x;
- *self.rsl.get_unchecked_mut(base + mr_offset) = b.0;
+ b = ind!(y >> RAND_SIZE_64_LEN) + x;
+ *self.rsl.get_unchecked_mut(base + mr_offset) = b;
}
}}
}
}
}
- self.a = a.0;
- self.b = b.0;
+ self.a = a;
+ self.b = b;
self.cnt = RAND_SIZE_64;
}
}
// See corresponding location in IsaacRng.next_u32 for
// explanation.
debug_assert!(self.cnt < RAND_SIZE_64);
- self.rsl[(self.cnt % RAND_SIZE_64) as uint]
+ self.rsl[(self.cnt % RAND_SIZE_64) as usize].0
}
}
let seed_iter = seed.iter().cloned().chain(repeat(0));
for (rsl_elem, seed_elem) in self.rsl.iter_mut().zip(seed_iter) {
- *rsl_elem = seed_elem;
+ *rsl_elem = w(seed_elem);
}
self.cnt = 0;
- self.a = 0;
- self.b = 0;
- self.c = 0;
+ self.a = w(0);
+ self.b = w(0);
+ self.c = w(0);
self.init(true);
}
unsafe {
let ptr = ret.rsl.as_mut_ptr() as *mut u8;
- let slice = slice::from_raw_parts_mut(ptr, (RAND_SIZE_64 * 8) as uint);
+ let slice = slice::from_raw_parts_mut(ptr, RAND_SIZE_64 * 8);
other.fill_bytes(slice);
}
ret.cnt = 0;
- ret.a = 0;
- ret.b = 0;
- ret.c = 0;
+ ret.a = w(0);
+ ret.b = w(0);
+ ret.c = w(0);
ret.init(true);
return ret;
#[test]
fn test_rng_32_rand_seeded() {
let s = ::test::rng().gen_iter::<u32>().take(256).collect::<Vec<u32>>();
- let mut ra: IsaacRng = SeedableRng::from_seed(&*s);
- let mut rb: IsaacRng = SeedableRng::from_seed(&*s);
+ let mut ra: IsaacRng = SeedableRng::from_seed(&s[..]);
+ let mut rb: IsaacRng = SeedableRng::from_seed(&s[..]);
assert!(order::equals(ra.gen_ascii_chars().take(100),
rb.gen_ascii_chars().take(100)));
}
#[test]
fn test_rng_64_rand_seeded() {
let s = ::test::rng().gen_iter::<u64>().take(256).collect::<Vec<u64>>();
- let mut ra: Isaac64Rng = SeedableRng::from_seed(&*s);
- let mut rb: Isaac64Rng = SeedableRng::from_seed(&*s);
+ let mut ra: Isaac64Rng = SeedableRng::from_seed(&s[..]);
+ let mut rb: Isaac64Rng = SeedableRng::from_seed(&s[..]);
assert!(order::equals(ra.gen_ascii_chars().take(100),
rb.gen_ascii_chars().take(100)));
}
#[test]
fn test_rng_32_reseed() {
let s = ::test::rng().gen_iter::<u32>().take(256).collect::<Vec<u32>>();
- let mut r: IsaacRng = SeedableRng::from_seed(&*s);
+ let mut r: IsaacRng = SeedableRng::from_seed(&s[..]);
let string1: String = r.gen_ascii_chars().take(100).collect();
r.reseed(&s);
#[test]
fn test_rng_64_reseed() {
let s = ::test::rng().gen_iter::<u64>().take(256).collect::<Vec<u64>>();
- let mut r: Isaac64Rng = SeedableRng::from_seed(&*s);
+ let mut r: Isaac64Rng = SeedableRng::from_seed(&s[..]);
let string1: String = r.gen_ascii_chars().take(100).collect();
r.reseed(&s);
pub const tag_codemap_filemap: uint = 0xa2;
pub const tag_item_super_predicates: uint = 0xa3;
+
+pub const tag_defaulted_trait: uint = 0xa4;
};
let dylib = library.dylib.clone();
- let register = should_link && self.existing_match(info.name.as_slice(),
+ let register = should_link && self.existing_match(&info.name,
None,
PathKind::Crate).is_none();
let metadata = if register {
decoder::is_associated_type(&*cdata, def.node)
}
-pub fn is_default_trait(cstore: &cstore::CStore, def: ast::DefId) -> bool {
- let cdata = cstore.get_crate_data(def.krate);
- decoder::is_default_trait(&*cdata, def.node)
+pub fn is_defaulted_trait(cstore: &cstore::CStore, trait_def_id: ast::DefId) -> bool {
+ let cdata = cstore.get_crate_data(trait_def_id.krate);
+ decoder::is_defaulted_trait(&*cdata, trait_def_id.node)
}
}
}
-pub fn is_default_trait<'tcx>(cdata: Cmd, id: ast::NodeId) -> bool {
- let item_doc = lookup_item(id, cdata.data());
- match item_family(item_doc) {
- Family::DefaultImpl => true,
- _ => false
- }
+pub fn is_defaulted_trait<'tcx>(cdata: Cmd, trait_id: ast::NodeId) -> bool {
+ let trait_doc = lookup_item(trait_id, cdata.data());
+ assert!(item_family(trait_doc) == Family::Trait);
+ let defaulted_doc = reader::get_doc(trait_doc, tag_defaulted_trait);
+ reader::doc_as_u8(defaulted_doc) != 0
}
pub fn get_imported_filemaps(metadata: &[u8]) -> Vec<codemap::FileMap> {
let trait_predicates = ty::lookup_predicates(tcx, def_id);
encode_unsafety(rbml_w, trait_def.unsafety);
encode_paren_sugar(rbml_w, trait_def.paren_sugar);
+ encode_defaulted(rbml_w, ty::trait_has_default_impl(tcx, def_id));
encode_associated_type_names(rbml_w, &trait_def.associated_type_names);
encode_generics(rbml_w, ecx, &trait_def.generics, &trait_predicates, tag_item_generics);
encode_predicates(rbml_w, ecx, &ty::lookup_super_predicates(tcx, def_id),
rbml_w.wr_tagged_u8(tag_paren_sugar, byte);
}
+fn encode_defaulted(rbml_w: &mut Encoder, is_defaulted: bool) {
+ let byte: u8 = if is_defaulted {1} else {0};
+ rbml_w.wr_tagged_u8(tag_defaulted_trait, byte);
+}
+
fn encode_associated_type_names(rbml_w: &mut Encoder, names: &[ast::Name]) {
rbml_w.start_tag(tag_associated_type_names);
for &name in names {
let subspan = p.span.lo <= err.span.lo && err.span.hi <= p.span.hi;
cx.tcx.sess.span_err(err.span,
&format!("constant evaluation error: {}",
- err.description().as_slice()));
+ err.description()));
if !subspan {
cx.tcx.sess.span_note(p.span,
"in pattern here")
pub fn eval_const_expr(tcx: &ty::ctxt, e: &Expr) -> const_val {
match eval_const_expr_partial(tcx, e, None) {
Ok(r) => r,
- Err(s) => tcx.sess.span_fatal(s.span, s.description().as_slice())
+ Err(s) => tcx.sess.span_fatal(s.span, &s.description())
}
}
let a = match eval_const_expr_partial(tcx, a, ty_hint) {
Ok(a) => a,
Err(e) => {
- tcx.sess.span_err(a.span, e.description().as_slice());
+ tcx.sess.span_err(a.span, &e.description());
return None;
}
};
let b = match eval_const_expr_partial(tcx, b, ty_hint) {
Ok(b) => b,
Err(e) => {
- tcx.sess.span_err(b.span, e.description().as_slice());
+ tcx.sess.span_err(b.span, &e.description());
return None;
}
};
/// Maps a trait onto a list of impls of that trait.
pub trait_impls: RefCell<DefIdMap<Rc<RefCell<Vec<ast::DefId>>>>>,
- /// Maps a trait onto a list of *default* trait implementations
- default_trait_impls: RefCell<DefIdMap<ast::DefId>>,
+ /// A set of traits that have a default impl
+ traits_with_default_impls: RefCell<DefIdMap<()>>,
/// Maps a DefId of a type to a list of its inherent impls.
/// Contains implementations of methods that are inherent to a type.
destructor_for_type: RefCell::new(DefIdMap()),
destructors: RefCell::new(DefIdSet()),
trait_impls: RefCell::new(DefIdMap()),
- default_trait_impls: RefCell::new(DefIdMap()),
+ traits_with_default_impls: RefCell::new(DefIdMap()),
inherent_impls: RefCell::new(DefIdMap()),
impl_items: RefCell::new(DefIdMap()),
used_unsafe: RefCell::new(NodeSet()),
Err(err) => {
span_err!(cx.sess, err.span, E0305,
"constant evaluation error: {}",
- err.description().as_slice());
+ err.description());
}
}
} else {
|| Rc::new(csearch::get_item_variances(&tcx.sess.cstore, item_id)))
}
-pub fn trait_default_impl(tcx: &ctxt, trait_def_id: DefId) -> Option<ast::DefId> {
- match tcx.default_trait_impls.borrow().get(&trait_def_id) {
- Some(id) => Some(*id),
- None => None
- }
-}
-
pub fn trait_has_default_impl(tcx: &ctxt, trait_def_id: DefId) -> bool {
+ populate_implementations_for_trait_if_necessary(tcx, trait_def_id);
match tcx.lang_items.to_builtin_kind(trait_def_id) {
Some(BoundSend) | Some(BoundSync) => true,
- _ => tcx.default_trait_impls.borrow().contains_key(&trait_def_id)
+ _ => tcx.traits_with_default_impls.borrow().contains_key(&trait_def_id),
}
}
/// Records a trait-to-implementation mapping.
-pub fn record_default_trait_implementation(tcx: &ctxt,
- trait_def_id: DefId,
- impl_def_id: DefId) {
-
+pub fn record_trait_has_default_impl(tcx: &ctxt, trait_def_id: DefId) {
// We're using the latest implementation found as the reference one.
// Duplicated implementations are caught and reported in the coherence
// step.
- tcx.default_trait_impls.borrow_mut().insert(trait_def_id, impl_def_id);
+ tcx.traits_with_default_impls.borrow_mut().insert(trait_def_id, ());
}
-
/// Records a trait-to-implementation mapping.
pub fn record_trait_implementation(tcx: &ctxt,
trait_def_id: DefId,
debug!("populate_implementations_for_type_if_necessary: searching for {:?}", type_id);
let mut inherent_impls = Vec::new();
- csearch::each_implementation_for_type(&tcx.sess.cstore, type_id,
- |impl_def_id| {
+ csearch::each_implementation_for_type(&tcx.sess.cstore, type_id, |impl_def_id| {
let impl_items = csearch::get_impl_items(&tcx.sess.cstore, impl_def_id);
// Record the trait->implementation mappings, if applicable.
if trait_id.krate == LOCAL_CRATE {
return
}
+
if tcx.populated_external_traits.borrow().contains(&trait_id) {
return
}
- csearch::each_implementation_for_trait(&tcx.sess.cstore, trait_id,
- |implementation_def_id|{
- let impl_items = csearch::get_impl_items(&tcx.sess.cstore, implementation_def_id);
+ if csearch::is_defaulted_trait(&tcx.sess.cstore, trait_id) {
+ record_trait_has_default_impl(tcx, trait_id);
+ }
- if csearch::is_default_trait(&tcx.sess.cstore, implementation_def_id) {
- record_default_trait_implementation(tcx, trait_id,
- implementation_def_id);
- tcx.populated_external_traits.borrow_mut().insert(trait_id);
+ csearch::each_implementation_for_trait(&tcx.sess.cstore, trait_id, |implementation_def_id| {
+ let impl_items = csearch::get_impl_items(&tcx.sess.cstore, implementation_def_id);
- // Nothing else to do for default trait implementations since
- // they are not allowed to have type parameters, methods, or any
- // other item that could be associated to a trait implementation.
- return;
- } else {
- // Record the trait->implementation mapping.
- record_trait_implementation(tcx, trait_id, implementation_def_id);
- }
+ // Record the trait->implementation mapping.
+ record_trait_implementation(tcx, trait_id, implementation_def_id);
// For any methods that use a default implementation, add them to
// the map. This is a bit unfortunate.
MethodTraitItem(method) => {
if let Some(source) = method.provided_source {
tcx.provided_method_sources
- .borrow_mut()
- .insert(method_def_id, source);
+ .borrow_mut()
+ .insert(method_def_id, source);
}
}
TypeTraitItem(_) => {}
region::CodeExtent::Misc(_) => tag,
region::CodeExtent::DestructionScope(_) => {
new_string = format!("destruction scope surrounding {}", tag);
- new_string.as_slice()
+ &*new_string
}
region::CodeExtent::Remainder(r) => {
new_string = format!("block suffix following statement {}",
// A simple failure case - adding 1 to the max value
#[test]
- #[should_fail]
+ #[should_panic]
fn test_add_bytes_to_bits_overflow() {
super::add_bytes_to_bits::<u64>(Int::max_value(), 1);
}
/// let mut flags = FLAG_A | FLAG_B;
/// flags.clear();
/// assert!(flags.is_empty());
-/// assert_eq!(format!("{:?}", flags).as_slice(), "hi!");
+/// assert_eq!(format!("{:?}", flags), "hi!");
/// }
/// ```
///
self.tcx
.sess
.span_err(span,
- (format!("partial reinitialization of uninitialized \
+ &format!("partial reinitialization of uninitialized \
structure `{}`",
- self.loan_path_to_string(lp))).as_slice());
+ self.loan_path_to_string(lp)));
}
pub fn report_reassigned_immutable_variable(&self,
// We want to toss everything after the final '.'
let dirpath = match *odir {
Some(ref d) => d.clone(),
- None => PathBuf::new(".")
+ None => PathBuf::new("")
};
// If a crate name is present, we use it as the link name
if *odir != None {
sess.warn("ignoring --out-dir flag due to -o flag.");
}
+
+ let cur_dir = Path::new("");
+
OutputFilenames {
- out_directory: out_file.parent().unwrap().to_path_buf(),
+ out_directory: out_file.parent().unwrap_or(cur_dir).to_path_buf(),
out_filestem: out_file.file_stem().unwrap()
.to_str().unwrap().to_string(),
single_output_file: ofile,
!cx.exported_items.contains(&it.id) {
let msg = format!("static {} is marked #[no_mangle], but not exported",
it.ident);
- cx.span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, msg.as_slice());
+ cx.span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, &msg);
}
},
ast::ItemConst(..) => {
// panic occur before the ADT as a whole is ready.
let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
- // First we trans the base, if we have one, to the dest
- if let Some(base) = optbase {
+ if ty::type_is_simd(bcx.tcx(), ty) {
+ // Issue 23112: The original logic appeared vulnerable to same
+ // order-of-eval bug. But, SIMD values are tuple-structs;
+ // i.e. functional record update (FRU) syntax is unavailable.
+ //
+ // To be safe, double-check that we did not get here via FRU.
+ assert!(optbase.is_none());
+
+ // This is the constructor of a SIMD type, such types are
+ // always primitive machine types and so do not have a
+ // destructor or require any clean-up.
+ let llty = type_of::type_of(bcx.ccx(), ty);
+
+ // keep a vector as a register, and running through the field
+ // `insertelement`ing them directly into that register
+ // (i.e. avoid GEPi and `store`s to an alloca) .
+ let mut vec_val = C_undef(llty);
+
+ for &(i, ref e) in fields {
+ let block_datum = trans(bcx, &**e);
+ bcx = block_datum.bcx;
+ let position = C_uint(bcx.ccx(), i);
+ let value = block_datum.datum.to_llscalarish(bcx);
+ vec_val = InsertElement(bcx, vec_val, value, position);
+ }
+ Store(bcx, vec_val, addr);
+ } else if let Some(base) = optbase {
+ // Issue 23112: If there is a base, then order-of-eval
+ // requires field expressions eval'ed before base expression.
+
+ // First, trans field expressions to temporary scratch values.
+ let scratch_vals: Vec<_> = fields.iter().map(|&(i, ref e)| {
+ let datum = unpack_datum!(bcx, trans(bcx, &**e));
+ (i, datum)
+ }).collect();
+
+ debug_location.apply(bcx.fcx);
+
+ // Second, trans the base to the dest.
assert_eq!(discr, 0);
match ty::expr_kind(bcx.tcx(), &*base.expr) {
}
}
}
- }
-
- debug_location.apply(bcx.fcx);
-
- if ty::type_is_simd(bcx.tcx(), ty) {
- // This is the constructor of a SIMD type, such types are
- // always primitive machine types and so do not have a
- // destructor or require any clean-up.
- let llty = type_of::type_of(bcx.ccx(), ty);
-
- // keep a vector as a register, and running through the field
- // `insertelement`ing them directly into that register
- // (i.e. avoid GEPi and `store`s to an alloca) .
- let mut vec_val = C_undef(llty);
- for &(i, ref e) in fields {
- let block_datum = trans(bcx, &**e);
- bcx = block_datum.bcx;
- let position = C_uint(bcx.ccx(), i);
- let value = block_datum.datum.to_llscalarish(bcx);
- vec_val = InsertElement(bcx, vec_val, value, position);
+ // Finally, move scratch field values into actual field locations
+ for (i, datum) in scratch_vals.into_iter() {
+ let dest = adt::trans_field_ptr(bcx, &*repr, addr, discr, i);
+ bcx = datum.store_to(bcx, dest);
}
- Store(bcx, vec_val, addr);
} else {
- // Now, we just overwrite the fields we've explicitly specified
+ // No base means we can write all fields directly in place.
for &(i, ref e) in fields {
let dest = adt::trans_field_ptr(bcx, &*repr, addr, discr, i);
let e_ty = expr_ty_adjusted(bcx, &**e);
ast_ty.span.lo <= r.span.lo && r.span.hi <= ast_ty.span.hi;
span_err!(tcx.sess, r.span, E0250,
"array length constant evaluation error: {}",
- r.description().as_slice());
+ r.description());
if !subspan {
span_note!(tcx.sess, ast_ty.span, "for array length here")
}
match rcx.tcx().region_maps.opt_encl_scope(scope) {
Some(parent_scope) => ty::ReScope(parent_scope),
None => rcx.tcx().sess.span_bug(
- span, format!("no enclosing scope found for scope: {:?}",
- scope).as_slice()),
+ span, &format!("no enclosing scope found for scope: {:?}",
+ scope)),
};
regionck::type_must_outlive(rcx, origin(), typ, parent_region);
Err(ref err) => {
span_err!(ccx.tcx.sess, err.span, E0080,
"constant evaluation error: {}",
- err.description().as_slice());
+ err.description());
}
}
},
rcx.tcx()
.sess
.span_bug(span,
- format!("unexpected rvalue region in rvalue \
- destructor safety checking: `{}`",
- region.repr(rcx.tcx())).as_slice());
+ &format!("unexpected rvalue region in rvalue \
+ destructor safety checking: `{}`",
+ region.repr(rcx.tcx())));
}
}
}
Some(def_id) => {
self.tcx().sess.fileline_help(
span,
- format!("consider removing `{}` or using a marker such as `{}`",
- param_name.user_string(self.tcx()),
- ty::item_path_str(self.tcx(), def_id)).as_slice());
+ &format!("consider removing `{}` or using a marker such as `{}`",
+ param_name.user_string(self.tcx()),
+ ty::item_path_str(self.tcx(), def_id)));
}
None => {
// no lang items, no help!
+++ /dev/null
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Implementations checker: builtin traits and default impls are allowed just
-//! for structs and enums.
-
-use middle::ty;
-use syntax::ast::{Item, ItemImpl};
-use syntax::ast;
-use syntax::visit;
-
-pub fn check(tcx: &ty::ctxt) {
- let mut impls = ImplsChecker { tcx: tcx };
- visit::walk_crate(&mut impls, tcx.map.krate());
-}
-
-struct ImplsChecker<'cx, 'tcx:'cx> {
- tcx: &'cx ty::ctxt<'tcx>
-}
-
-impl<'cx, 'tcx,'v> visit::Visitor<'v> for ImplsChecker<'cx, 'tcx> {
- fn visit_item(&mut self, item: &'v ast::Item) {
- match item.node {
- ast::ItemImpl(_, _, _, Some(_), _, _) => {
- let trait_ref = ty::impl_id_to_trait_ref(self.tcx, item.id);
- if let Some(_) = self.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
- match trait_ref.self_ty().sty {
- ty::ty_struct(..) | ty::ty_enum(..) => {}
- _ => {
- span_err!(self.tcx.sess, item.span, E0209,
- "builtin traits can only be \
- implemented on structs or enums");
- }
- }
- }
- }
- _ => {}
- }
- }
-}
use util::nodemap::{DefIdMap, FnvHashMap};
use util::ppaux::Repr;
-mod impls;
mod orphan;
mod overlap;
mod unsafety;
inference_context: new_infer_ctxt(crate_context.tcx),
inherent_impls: RefCell::new(FnvHashMap()),
}.check(crate_context.tcx.map.krate());
- impls::check(crate_context.tcx);
unsafety::check(crate_context.tcx);
orphan::check(crate_context.tcx);
overlap::check(crate_context.tcx);
a trait or new type instead");
}
}
-}
-impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
- fn visit_item(&mut self, item: &ast::Item) {
+ /// Checks exactly one impl for orphan rules and other such
+ /// restrictions. In this fn, it can happen that multiple errors
+ /// apply to a specific impl, so just return after reporting one
+ /// to prevent inundating the user with a bunch of similar error
+ /// reports.
+ fn check_item(&self, item: &ast::Item) {
let def_id = ast_util::local_def(item.id);
match item.node {
ast::ItemImpl(_, _, _, None, _, _) => {
span_err!(self.tcx.sess, item.span, E0118,
"no base type found for inherent implementation; \
implement a trait or new type instead");
+ return;
}
}
}
ast::ItemImpl(_, _, _, Some(_), _, _) => {
// "Trait" impl
debug!("coherence2::orphan check: trait impl {}", item.repr(self.tcx));
- let trait_def_id = ty::impl_trait_ref(self.tcx, def_id).unwrap().def_id;
+ let trait_ref = ty::impl_trait_ref(self.tcx, def_id).unwrap();
+ let trait_def_id = trait_ref.def_id;
match traits::orphan_check(self.tcx, def_id) {
Ok(()) => { }
Err(traits::OrphanCheckErr::NoLocalInputType) => {
types defined in this crate; \
only traits defined in the current crate can be \
implemented for arbitrary types");
+ return;
}
}
Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
some local type (e.g. `MyStruct<T>`); only traits defined in \
the current crate can be implemented for a type parameter",
param_ty.user_string(self.tcx));
+ return;
}
}
}
+
+ // In addition to the above rules, we restrict impls of defaulted traits
+ // so that they can only be implemented on structs/enums. To see why this
+ // restriction exists, consider the following example (#22978). Imagine
+ // that crate A defines a defaulted trait `Foo` and a fn that operates
+ // on pairs of types:
+ //
+ // ```
+ // // Crate A
+ // trait Foo { }
+ // impl Foo for .. { }
+ // fn two_foos<A:Foo,B:Foo>(..) {
+ // one_foo::<(A,B)>(..)
+ // }
+ // fn one_foo<T:Foo>(..) { .. }
+ // ```
+ //
+ // This type-checks fine; in particular the fn
+ // `two_foos` is able to conclude that `(A,B):Foo`
+ // because `A:Foo` and `B:Foo`.
+ //
+ // Now imagine that crate B comes along and does the following:
+ //
+ // ```
+ // struct A { }
+ // struct B { }
+ // impl Foo for A { }
+ // impl Foo for B { }
+ // impl !Send for (A, B) { }
+ // ```
+ //
+ // This final impl is legal according to the orpan
+ // rules, but it invalidates the reasoning from
+ // `two_foos` above.
+ debug!("trait_ref={} trait_def_id={} trait_has_default_impl={}",
+ trait_ref.repr(self.tcx),
+ trait_def_id.repr(self.tcx),
+ ty::trait_has_default_impl(self.tcx, trait_def_id));
+ if
+ ty::trait_has_default_impl(self.tcx, trait_def_id) &&
+ trait_def_id.krate != ast::LOCAL_CRATE
+ {
+ let self_ty = trait_ref.self_ty();
+ let opt_self_def_id = match self_ty.sty {
+ ty::ty_struct(self_def_id, _) | ty::ty_enum(self_def_id, _) =>
+ Some(self_def_id),
+ ty::ty_uniq(..) =>
+ self.tcx.lang_items.owned_box(),
+ _ =>
+ None
+ };
+
+ let msg = match opt_self_def_id {
+ // We only want to permit structs/enums, but not *all* structs/enums.
+ // They must be local to the current crate, so that people
+ // can't do `unsafe impl Send for Rc<SomethingLocal>` or
+ // `impl !Send for Box<SomethingLocalAndSend>`.
+ Some(self_def_id) => {
+ if self_def_id.krate == ast::LOCAL_CRATE {
+ None
+ } else {
+ Some(format!(
+ "cross-crate traits with a default impl, like `{}`, \
+ can only be implemented for a struct/enum type \
+ defined in the current crate",
+ ty::item_path_str(self.tcx, trait_def_id)))
+ }
+ }
+ _ => {
+ Some(format!(
+ "cross-crate traits with a default impl, like `{}`, \
+ can only be implemented for a struct/enum type, \
+ not `{}`",
+ ty::item_path_str(self.tcx, trait_def_id),
+ self_ty.user_string(self.tcx)))
+ }
+ };
+
+ if let Some(msg) = msg {
+ span_err!(self.tcx.sess, item.span, E0321, "{}", msg);
+ return;
+ }
+ }
+
+ // Disallow *all* explicit impls of `Sized` for now.
+ if Some(trait_def_id) == self.tcx.lang_items.sized_trait() {
+ span_err!(self.tcx.sess, item.span, E0322,
+ "explicit impls for the `Sized` trait are not permitted");
+ return;
+ }
}
ast::ItemDefaultImpl(..) => {
// "Trait" impl
if trait_ref.def_id.krate != ast::LOCAL_CRATE {
span_err!(self.tcx.sess, item.span, E0318,
"cannot create default implementations for traits outside the \
- crate they're defined in; define a new trait instead.");
+ crate they're defined in; define a new trait instead");
+ return;
}
}
_ => {
// Not an impl
}
}
+ }
+}
+impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
+ fn visit_item(&mut self, item: &ast::Item) {
+ self.check_item(item);
visit::walk_item(self, item);
}
}
use syntax::ast_util;
use syntax::visit;
use syntax::codemap::Span;
+use util::nodemap::DefIdMap;
use util::ppaux::Repr;
pub fn check(tcx: &ty::ctxt) {
- let mut overlap = OverlapChecker { tcx: tcx };
+ let mut overlap = OverlapChecker { tcx: tcx, default_impls: DefIdMap() };
overlap.check_for_overlapping_impls();
// this secondary walk specifically checks for impls of defaulted
struct OverlapChecker<'cx, 'tcx:'cx> {
tcx: &'cx ty::ctxt<'tcx>,
+
+ // maps from a trait def-id to an impl id
+ default_impls: DefIdMap<ast::NodeId>,
}
impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
fn visit_item(&mut self, item: &'v ast::Item) {
match item.node {
ast::ItemDefaultImpl(_, _) => {
+ // look for another default impl; note that due to the
+ // general orphan/coherence rules, it must always be
+ // in this crate.
let impl_def_id = ast_util::local_def(item.id);
- match ty::impl_trait_ref(self.tcx, impl_def_id) {
- Some(ref trait_ref) => {
- match ty::trait_default_impl(self.tcx, trait_ref.def_id) {
- Some(other_impl) if other_impl != impl_def_id => {
- self.report_overlap_error(trait_ref.def_id,
- other_impl,
- impl_def_id);
- }
- Some(_) => {}
- None => {
- self.tcx.sess.bug(
- &format!("no default implementation recorded for `{:?}`",
- item));
- }
- }
+ let trait_ref = ty::impl_trait_ref(self.tcx, impl_def_id).unwrap();
+ let prev_default_impl = self.default_impls.insert(trait_ref.def_id, item.id);
+ match prev_default_impl {
+ Some(prev_id) => {
+ self.report_overlap_error(trait_ref.def_id,
+ impl_def_id,
+ ast_util::local_def(prev_id));
}
- _ => {}
+ None => { }
}
}
_ => {}
None,
None);
- ty::record_default_trait_implementation(tcx, trait_ref.def_id, local_def(it.id))
+ ty::record_trait_has_default_impl(tcx, trait_ref.def_id);
}
ast::ItemImpl(_, _,
ref generics,
ast::ItemMac(..) => {
tcx.sess.span_bug(
it.span,
- format!("compute_type_scheme_of_item: unexpected item type: {:?}",
- it.node).as_slice());
+ &format!("compute_type_scheme_of_item: unexpected item type: {:?}",
+ it.node));
}
}
}
E0250, // expected constant expr for array length
E0318, // can't create default impls for traits outside their crates
E0319, // trait impls for defaulted traits allowed just for structs/enums
- E0320 // recursive overflow during dropck
+ E0320, // recursive overflow during dropck
+ E0321, // extended coherence rules for defaulted traits violated
+ E0322 // cannot implement Sized explicitly
}
__build_diagnostic_array! { DIAGNOSTICS }
#[allow(deprecated)]
fn runtest(test: &str, cratename: &str, libs: SearchPaths,
externs: core::Externs,
- should_fail: bool, no_run: bool, as_test_harness: bool) {
+ should_panic: bool, no_run: bool, as_test_harness: bool) {
// the test harness wants its own `main` & top level functions, so
// never wrap the test in `fn main() { ... }`
let test = maketest(test, Some(cratename), true, as_test_harness);
" - maybe your tempdir is mounted with noexec?"
} else { "" }),
Ok(out) => {
- if should_fail && out.status.success() {
+ if should_panic && out.status.success() {
panic!("test executable succeeded when it should have failed");
- } else if !should_fail && !out.status.success() {
+ } else if !should_panic && !out.status.success() {
panic!("test executable failed:\n{:?}",
str::from_utf8(&out.stdout));
}
}
pub fn add_test(&mut self, test: String,
- should_fail: bool, no_run: bool, should_ignore: bool, as_test_harness: bool) {
+ should_panic: bool, no_run: bool, should_ignore: bool, as_test_harness: bool) {
let name = if self.use_headers {
let s = self.current_header.as_ref().map(|s| &**s).unwrap_or("");
format!("{}_{}", s, self.cnt)
desc: testing::TestDesc {
name: testing::DynTestName(name),
ignore: should_ignore,
- should_fail: testing::ShouldFail::No, // compiler failures are test failures
+ should_panic: testing::ShouldPanic::No, // compiler failures are test failures
},
testfn: testing::DynTestFn(Thunk::new(move|| {
runtest(&test,
&cratename,
libs,
externs,
- should_fail,
+ should_panic,
no_run,
as_test_harness);
}))
//! let json_str: String = json_obj.to_string();
//!
//! // Deserialize like before
-//! let decoded: TestStruct = json::decode(json_str.as_slice()).unwrap();
+//! let decoded: TestStruct = json::decode(json_str)).unwrap();
//! }
//! ```
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_index_nonexistent() {
let mut map = HashMap::new();
i += 1;
}
let n = make_rand_name();
- set_var(&n, s.as_slice());
- eq(var_os(&n), Some(s.as_slice()));
+ set_var(&n, &s);
+ eq(var_os(&n), Some(&s));
}
#[test]
let n = make_rand_name();
let s = repeat("x").take(10000).collect::<String>();
set_var(&n, &s);
- eq(var_os(&n), Some(s.as_slice()));
+ eq(var_os(&n), Some(&s));
remove_var(&n);
eq(var_os(&n), None);
}
macro_rules! error { ($e:expr, $s:expr) => (
match $e {
Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s),
- Err(ref err) => assert!(err.to_string().contains($s.as_slice()),
+ Err(ref err) => assert!(err.to_string().contains($s),
format!("`{}` did not contain `{}`", err, $s))
}
) }
-1|0 => panic!("shouldn't happen"),
n => str::from_utf8(&read_buf[..n]).unwrap().to_string()
};
- assert_eq!(read_str.as_slice(), message);
+ assert_eq!(read_str, message);
}
check!(fs::remove_file(filename));
}
check!(check!(File::open(&f)).read(&mut mem));
let read_str = str::from_utf8(&mem).unwrap();
let expected = format!("{}{}", prefix, n.to_str().unwrap());
- assert_eq!(expected.as_slice(), read_str);
+ assert_eq!(expected, read_str);
}
check!(fs::remove_file(&f));
}
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
use num::*;
use num::FpCategory as Fp;
+ #[test]
+ fn test_num_f32() {
+ test_num(10f32, 2f32);
+ }
+
#[test]
fn test_min_nan() {
assert_eq!(NAN.min(2.0), 2.0);
}
#[test]
- fn test_num_f32() {
- test_num(10f32, 2f32);
+ fn test_nan() {
+ let nan: f32 = Float::nan();
+ assert!(nan.is_nan());
+ assert!(!nan.is_infinite());
+ assert!(!nan.is_finite());
+ assert!(!nan.is_normal());
+ assert!(!nan.is_positive());
+ assert!(!nan.is_negative());
+ assert_eq!(Fp::Nan, nan.classify());
+ }
+
+ #[test]
+ fn test_infinity() {
+ let inf: f32 = Float::infinity();
+ assert!(inf.is_infinite());
+ assert!(!inf.is_finite());
+ assert!(inf.is_positive());
+ assert!(!inf.is_negative());
+ assert!(!inf.is_nan());
+ assert!(!inf.is_normal());
+ assert_eq!(Fp::Infinite, inf.classify());
+ }
+
+ #[test]
+ fn test_neg_infinity() {
+ let neg_inf: f32 = Float::neg_infinity();
+ assert!(neg_inf.is_infinite());
+ assert!(!neg_inf.is_finite());
+ assert!(!neg_inf.is_positive());
+ assert!(neg_inf.is_negative());
+ assert!(!neg_inf.is_nan());
+ assert!(!neg_inf.is_normal());
+ assert_eq!(Fp::Infinite, neg_inf.classify());
+ }
+
+ #[test]
+ fn test_zero() {
+ let zero: f32 = Float::zero();
+ assert_eq!(0.0, zero);
+ assert!(!zero.is_infinite());
+ assert!(zero.is_finite());
+ assert!(zero.is_positive());
+ assert!(!zero.is_negative());
+ assert!(!zero.is_nan());
+ assert!(!zero.is_normal());
+ assert_eq!(Fp::Zero, zero.classify());
+ }
+
+ #[test]
+ fn test_neg_zero() {
+ let neg_zero: f32 = Float::neg_zero();
+ assert_eq!(0.0, neg_zero);
+ assert!(!neg_zero.is_infinite());
+ assert!(neg_zero.is_finite());
+ assert!(!neg_zero.is_positive());
+ assert!(neg_zero.is_negative());
+ assert!(!neg_zero.is_nan());
+ assert!(!neg_zero.is_normal());
+ assert_eq!(Fp::Zero, neg_zero.classify());
+ }
+
+ #[test]
+ fn test_one() {
+ let one: f32 = Float::one();
+ assert_eq!(1.0, one);
+ assert!(!one.is_infinite());
+ assert!(one.is_finite());
+ assert!(one.is_positive());
+ assert!(!one.is_negative());
+ assert!(!one.is_nan());
+ assert!(one.is_normal());
+ assert_eq!(Fp::Normal, one.classify());
+ }
+
+ #[test]
+ fn test_is_nan() {
+ let nan: f32 = Float::nan();
+ let inf: f32 = Float::infinity();
+ let neg_inf: f32 = Float::neg_infinity();
+ assert!(nan.is_nan());
+ assert!(!0.0f32.is_nan());
+ assert!(!5.3f32.is_nan());
+ assert!(!(-10.732f32).is_nan());
+ assert!(!inf.is_nan());
+ assert!(!neg_inf.is_nan());
+ }
+
+ #[test]
+ fn test_is_infinite() {
+ let nan: f32 = Float::nan();
+ let inf: f32 = Float::infinity();
+ let neg_inf: f32 = Float::neg_infinity();
+ assert!(!nan.is_infinite());
+ assert!(inf.is_infinite());
+ assert!(neg_inf.is_infinite());
+ assert!(!0.0f32.is_infinite());
+ assert!(!42.8f32.is_infinite());
+ assert!(!(-109.2f32).is_infinite());
+ }
+
+ #[test]
+ fn test_is_finite() {
+ let nan: f32 = Float::nan();
+ let inf: f32 = Float::infinity();
+ let neg_inf: f32 = Float::neg_infinity();
+ assert!(!nan.is_finite());
+ assert!(!inf.is_finite());
+ assert!(!neg_inf.is_finite());
+ assert!(0.0f32.is_finite());
+ assert!(42.8f32.is_finite());
+ assert!((-109.2f32).is_finite());
+ }
+
+ #[test]
+ fn test_is_normal() {
+ let nan: f32 = Float::nan();
+ let inf: f32 = Float::infinity();
+ let neg_inf: f32 = Float::neg_infinity();
+ let zero: f32 = Float::zero();
+ let neg_zero: f32 = Float::neg_zero();
+ assert!(!nan.is_normal());
+ assert!(!inf.is_normal());
+ assert!(!neg_inf.is_normal());
+ assert!(!zero.is_normal());
+ assert!(!neg_zero.is_normal());
+ assert!(1f32.is_normal());
+ assert!(1e-37f32.is_normal());
+ assert!(!1e-38f32.is_normal());
+ }
+
+ #[test]
+ fn test_classify() {
+ let nan: f32 = Float::nan();
+ let inf: f32 = Float::infinity();
+ let neg_inf: f32 = Float::neg_infinity();
+ let zero: f32 = Float::zero();
+ let neg_zero: f32 = Float::neg_zero();
+ assert_eq!(nan.classify(), Fp::Nan);
+ assert_eq!(inf.classify(), Fp::Infinite);
+ assert_eq!(neg_inf.classify(), Fp::Infinite);
+ assert_eq!(zero.classify(), Fp::Zero);
+ assert_eq!(neg_zero.classify(), Fp::Zero);
+ assert_eq!(1f32.classify(), Fp::Normal);
+ assert_eq!(1e-37f32.classify(), Fp::Normal);
+ assert_eq!(1e-38f32.classify(), Fp::Subnormal);
+ }
+
+ #[test]
+ fn test_integer_decode() {
+ assert_eq!(3.14159265359f32.integer_decode(), (13176795, -22, 1));
+ assert_eq!((-8573.5918555f32).integer_decode(), (8779358, -10, -1));
+ assert_eq!(2f32.powf(100.0).integer_decode(), (8388608, 77, 1));
+ assert_eq!(0f32.integer_decode(), (0, -150, 1));
+ assert_eq!((-0f32).integer_decode(), (0, -150, -1));
+ assert_eq!(INFINITY.integer_decode(), (8388608, 105, 1));
+ assert_eq!(NEG_INFINITY.integer_decode(), (8388608, 105, -1));
+ assert_eq!(NAN.integer_decode(), (12582912, 105, 1));
}
#[test]
assert_approx_eq!((-1.7f32).fract(), -0.7f32);
}
+ #[test]
+ fn test_abs() {
+ assert_eq!(INFINITY.abs(), INFINITY);
+ assert_eq!(1f32.abs(), 1f32);
+ assert_eq!(0f32.abs(), 0f32);
+ assert_eq!((-0f32).abs(), 0f32);
+ assert_eq!((-1f32).abs(), 1f32);
+ assert_eq!(NEG_INFINITY.abs(), INFINITY);
+ assert_eq!((1f32/NEG_INFINITY).abs(), 0f32);
+ assert!(NAN.abs().is_nan());
+ }
+
+ #[test]
+ fn test_signum() {
+ assert_eq!(INFINITY.signum(), 1f32);
+ assert_eq!(1f32.signum(), 1f32);
+ assert_eq!(0f32.signum(), 1f32);
+ assert_eq!((-0f32).signum(), -1f32);
+ assert_eq!((-1f32).signum(), -1f32);
+ assert_eq!(NEG_INFINITY.signum(), -1f32);
+ assert_eq!((1f32/NEG_INFINITY).signum(), -1f32);
+ assert!(NAN.signum().is_nan());
+ }
+
+ #[test]
+ fn test_is_positive() {
+ assert!(INFINITY.is_positive());
+ assert!(1f32.is_positive());
+ assert!(0f32.is_positive());
+ assert!(!(-0f32).is_positive());
+ assert!(!(-1f32).is_positive());
+ assert!(!NEG_INFINITY.is_positive());
+ assert!(!(1f32/NEG_INFINITY).is_positive());
+ assert!(!NAN.is_positive());
+ }
+
+ #[test]
+ fn test_is_negative() {
+ assert!(!INFINITY.is_negative());
+ assert!(!1f32.is_negative());
+ assert!(!0f32.is_negative());
+ assert!((-0f32).is_negative());
+ assert!((-1f32).is_negative());
+ assert!(NEG_INFINITY.is_negative());
+ assert!((1f32/NEG_INFINITY).is_negative());
+ assert!(!NAN.is_negative());
+ }
+
+ #[test]
+ fn test_mul_add() {
+ let nan: f32 = Float::nan();
+ let inf: f32 = Float::infinity();
+ let neg_inf: f32 = Float::neg_infinity();
+ assert_approx_eq!(12.3f32.mul_add(4.5, 6.7), 62.05);
+ assert_approx_eq!((-12.3f32).mul_add(-4.5, -6.7), 48.65);
+ assert_approx_eq!(0.0f32.mul_add(8.9, 1.2), 1.2);
+ assert_approx_eq!(3.4f32.mul_add(-0.0, 5.6), 5.6);
+ assert!(nan.mul_add(7.8, 9.0).is_nan());
+ assert_eq!(inf.mul_add(7.8, 9.0), inf);
+ assert_eq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
+ assert_eq!(8.9f32.mul_add(inf, 3.2), inf);
+ assert_eq!((-3.2f32).mul_add(2.4, neg_inf), neg_inf);
+ }
+
+ #[test]
+ fn test_recip() {
+ let nan: f32 = Float::nan();
+ let inf: f32 = Float::infinity();
+ let neg_inf: f32 = Float::neg_infinity();
+ assert_eq!(1.0f32.recip(), 1.0);
+ assert_eq!(2.0f32.recip(), 0.5);
+ assert_eq!((-0.4f32).recip(), -2.5);
+ assert_eq!(0.0f32.recip(), inf);
+ assert!(nan.recip().is_nan());
+ assert_eq!(inf.recip(), 0.0);
+ assert_eq!(neg_inf.recip(), 0.0);
+ }
+
+ #[test]
+ fn test_powi() {
+ let nan: f32 = Float::nan();
+ let inf: f32 = Float::infinity();
+ let neg_inf: f32 = Float::neg_infinity();
+ assert_eq!(1.0f32.powi(1), 1.0);
+ assert_approx_eq!((-3.1f32).powi(2), 9.61);
+ assert_approx_eq!(5.9f32.powi(-2), 0.028727);
+ assert_eq!(8.3f32.powi(0), 1.0);
+ assert!(nan.powi(2).is_nan());
+ assert_eq!(inf.powi(3), inf);
+ assert_eq!(neg_inf.powi(2), inf);
+ }
+
+ #[test]
+ fn test_powf() {
+ let nan: f32 = Float::nan();
+ let inf: f32 = Float::infinity();
+ let neg_inf: f32 = Float::neg_infinity();
+ assert_eq!(1.0f32.powf(1.0), 1.0);
+ assert_approx_eq!(3.4f32.powf(4.5), 246.408218);
+ assert_approx_eq!(2.7f32.powf(-3.2), 0.041652);
+ assert_approx_eq!((-3.1f32).powf(2.0), 9.61);
+ assert_approx_eq!(5.9f32.powf(-2.0), 0.028727);
+ assert_eq!(8.3f32.powf(0.0), 1.0);
+ assert!(nan.powf(2.0).is_nan());
+ assert_eq!(inf.powf(2.0), inf);
+ assert_eq!(neg_inf.powf(3.0), neg_inf);
+ }
+
+ #[test]
+ fn test_sqrt_domain() {
+ assert!(NAN.sqrt().is_nan());
+ assert!(NEG_INFINITY.sqrt().is_nan());
+ assert!((-1.0f32).sqrt().is_nan());
+ assert_eq!((-0.0f32).sqrt(), -0.0);
+ assert_eq!(0.0f32.sqrt(), 0.0);
+ assert_eq!(1.0f32.sqrt(), 1.0);
+ assert_eq!(INFINITY.sqrt(), INFINITY);
+ }
+
+ #[test]
+ fn test_rsqrt() {
+ let nan: f32 = Float::nan();
+ let inf: f32 = Float::infinity();
+ let neg_inf: f32 = Float::neg_infinity();
+ assert!(nan.rsqrt().is_nan());
+ assert_eq!(inf.rsqrt(), 0.0);
+ assert!(neg_inf.rsqrt().is_nan());
+ assert!((-1.0f32).rsqrt().is_nan());
+ assert_eq!((-0.0f32).rsqrt(), neg_inf);
+ assert_eq!(0.0f32.rsqrt(), inf);
+ assert_eq!(1.0f32.rsqrt(), 1.0);
+ assert_eq!(4.0f32.rsqrt(), 0.5);
+ }
+
#[test]
fn test_exp() {
assert_eq!(1.0, 0.0f32.exp());
assert!(nan.exp2().is_nan());
}
+ #[test]
+ fn test_ln() {
+ let nan: f32 = Float::nan();
+ let inf: f32 = Float::infinity();
+ let neg_inf: f32 = Float::neg_infinity();
+ assert_approx_eq!(1.0f32.exp().ln(), 1.0);
+ assert!(nan.ln().is_nan());
+ assert_eq!(inf.ln(), inf);
+ assert!(neg_inf.ln().is_nan());
+ assert!((-2.3f32).ln().is_nan());
+ assert_eq!((-0.0f32).ln(), neg_inf);
+ assert_eq!(0.0f32.ln(), neg_inf);
+ assert_approx_eq!(4.0f32.ln(), 1.386294);
+ }
+
+ #[test]
+ fn test_log() {
+ let nan: f32 = Float::nan();
+ let inf: f32 = Float::infinity();
+ let neg_inf: f32 = Float::neg_infinity();
+ assert_eq!(10.0f32.log(10.0), 1.0);
+ assert_approx_eq!(2.3f32.log(3.5), 0.664858);
+ assert_eq!(1.0f32.exp().log(1.0.exp()), 1.0);
+ assert!(1.0f32.log(1.0).is_nan());
+ assert!(1.0f32.log(-13.9).is_nan());
+ assert!(nan.log(2.3).is_nan());
+ assert_eq!(inf.log(10.0), inf);
+ assert!(neg_inf.log(8.8).is_nan());
+ assert!((-2.3f32).log(0.1).is_nan());
+ assert_eq!((-0.0f32).log(2.0), neg_inf);
+ assert_eq!(0.0f32.log(7.0), neg_inf);
+ }
+
+ #[test]
+ fn test_log2() {
+ let nan: f32 = Float::nan();
+ let inf: f32 = Float::infinity();
+ let neg_inf: f32 = Float::neg_infinity();
+ assert_approx_eq!(10.0f32.log2(), 3.321928);
+ assert_approx_eq!(2.3f32.log2(), 1.201634);
+ assert_approx_eq!(1.0f32.exp().log2(), 1.442695);
+ assert!(nan.log2().is_nan());
+ assert_eq!(inf.log2(), inf);
+ assert!(neg_inf.log2().is_nan());
+ assert!((-2.3f32).log2().is_nan());
+ assert_eq!((-0.0f32).log2(), neg_inf);
+ assert_eq!(0.0f32.log2(), neg_inf);
+ }
+
+ #[test]
+ fn test_log10() {
+ let nan: f32 = Float::nan();
+ let inf: f32 = Float::infinity();
+ let neg_inf: f32 = Float::neg_infinity();
+ assert_eq!(10.0f32.log10(), 1.0);
+ assert_approx_eq!(2.3f32.log10(), 0.361728);
+ assert_approx_eq!(1.0f32.exp().log10(), 0.434294);
+ assert_eq!(1.0f32.log10(), 0.0);
+ assert!(nan.log10().is_nan());
+ assert_eq!(inf.log10(), inf);
+ assert!(neg_inf.log10().is_nan());
+ assert!((-2.3f32).log10().is_nan());
+ assert_eq!((-0.0f32).log10(), neg_inf);
+ assert_eq!(0.0f32.log10(), neg_inf);
+ }
+
+ #[test]
+ fn test_to_degrees() {
+ let pi: f32 = consts::PI;
+ let nan: f32 = Float::nan();
+ let inf: f32 = Float::infinity();
+ let neg_inf: f32 = Float::neg_infinity();
+ assert_eq!(0.0f32.to_degrees(), 0.0);
+ assert_approx_eq!((-5.8f32).to_degrees(), -332.315521);
+ assert_eq!(pi.to_degrees(), 180.0);
+ assert!(nan.to_degrees().is_nan());
+ assert_eq!(inf.to_degrees(), inf);
+ assert_eq!(neg_inf.to_degrees(), neg_inf);
+ }
+
+ #[test]
+ fn test_to_radians() {
+ let pi: f32 = consts::PI;
+ let nan: f32 = Float::nan();
+ let inf: f32 = Float::infinity();
+ let neg_inf: f32 = Float::neg_infinity();
+ assert_eq!(0.0f32.to_radians(), 0.0);
+ assert_approx_eq!(154.6f32.to_radians(), 2.698279);
+ assert_approx_eq!((-332.31f32).to_radians(), -5.799903);
+ assert_eq!(180.0f32.to_radians(), pi);
+ assert!(nan.to_radians().is_nan());
+ assert_eq!(inf.to_radians(), inf);
+ assert_eq!(neg_inf.to_radians(), neg_inf);
+ }
+
+ #[test]
+ fn test_ldexp() {
+ // We have to use from_str until base-2 exponents
+ // are supported in floating-point literals
+ let f1: f32 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
+ let f2: f32 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
+ let f3: f32 = FromStrRadix::from_str_radix("1.Cp-12", 16).unwrap();
+ assert_eq!(Float::ldexp(1f32, -123), f1);
+ assert_eq!(Float::ldexp(1f32, -111), f2);
+ assert_eq!(Float::ldexp(1.75f32, -12), f3);
+
+ assert_eq!(Float::ldexp(0f32, -123), 0f32);
+ assert_eq!(Float::ldexp(-0f32, -123), -0f32);
+
+ let inf: f32 = Float::infinity();
+ let neg_inf: f32 = Float::neg_infinity();
+ let nan: f32 = Float::nan();
+ assert_eq!(Float::ldexp(inf, -123), inf);
+ assert_eq!(Float::ldexp(neg_inf, -123), neg_inf);
+ assert!(Float::ldexp(nan, -123).is_nan());
+ }
+
+ #[test]
+ fn test_frexp() {
+ // We have to use from_str until base-2 exponents
+ // are supported in floating-point literals
+ let f1: f32 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
+ let f2: f32 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
+ let f3: f32 = FromStrRadix::from_str_radix("1.Cp-123", 16).unwrap();
+ let (x1, exp1) = f1.frexp();
+ let (x2, exp2) = f2.frexp();
+ let (x3, exp3) = f3.frexp();
+ assert_eq!((x1, exp1), (0.5f32, -122));
+ assert_eq!((x2, exp2), (0.5f32, -110));
+ assert_eq!((x3, exp3), (0.875f32, -122));
+ assert_eq!(Float::ldexp(x1, exp1), f1);
+ assert_eq!(Float::ldexp(x2, exp2), f2);
+ assert_eq!(Float::ldexp(x3, exp3), f3);
+
+ assert_eq!(0f32.frexp(), (0f32, 0));
+ assert_eq!((-0f32).frexp(), (-0f32, 0));
+ }
+
+ #[test] #[cfg_attr(windows, ignore)] // FIXME #8755
+ fn test_frexp_nowin() {
+ let inf: f32 = Float::infinity();
+ let neg_inf: f32 = Float::neg_infinity();
+ let nan: f32 = Float::nan();
+ assert_eq!(match inf.frexp() { (x, _) => x }, inf);
+ assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf);
+ assert!(match nan.frexp() { (x, _) => x.is_nan() })
+ }
+
+ #[test]
+ fn test_abs_sub() {
+ assert_eq!((-1f32).abs_sub(1f32), 0f32);
+ assert_eq!(1f32.abs_sub(1f32), 0f32);
+ assert_eq!(1f32.abs_sub(0f32), 1f32);
+ assert_eq!(1f32.abs_sub(-1f32), 2f32);
+ assert_eq!(NEG_INFINITY.abs_sub(0f32), 0f32);
+ assert_eq!(INFINITY.abs_sub(1f32), INFINITY);
+ assert_eq!(0f32.abs_sub(NEG_INFINITY), INFINITY);
+ assert_eq!(0f32.abs_sub(INFINITY), 0f32);
+ }
+
+ #[test]
+ fn test_abs_sub_nowin() {
+ assert!(NAN.abs_sub(-1f32).is_nan());
+ assert!(1f32.abs_sub(NAN).is_nan());
+ }
+
#[test]
fn test_asinh() {
assert_eq!(0.0f32.asinh(), 0.0f32);
assert_approx_eq!(ln_2, 2f32.ln());
assert_approx_eq!(ln_10, 10f32.ln());
}
-
- #[test]
- pub fn test_abs() {
- assert_eq!(INFINITY.abs(), INFINITY);
- assert_eq!(1f32.abs(), 1f32);
- assert_eq!(0f32.abs(), 0f32);
- assert_eq!((-0f32).abs(), 0f32);
- assert_eq!((-1f32).abs(), 1f32);
- assert_eq!(NEG_INFINITY.abs(), INFINITY);
- assert_eq!((1f32/NEG_INFINITY).abs(), 0f32);
- assert!(NAN.abs().is_nan());
- }
-
- #[test]
- fn test_abs_sub() {
- assert_eq!((-1f32).abs_sub(1f32), 0f32);
- assert_eq!(1f32.abs_sub(1f32), 0f32);
- assert_eq!(1f32.abs_sub(0f32), 1f32);
- assert_eq!(1f32.abs_sub(-1f32), 2f32);
- assert_eq!(NEG_INFINITY.abs_sub(0f32), 0f32);
- assert_eq!(INFINITY.abs_sub(1f32), INFINITY);
- assert_eq!(0f32.abs_sub(NEG_INFINITY), INFINITY);
- assert_eq!(0f32.abs_sub(INFINITY), 0f32);
- }
-
- #[test]
- fn test_abs_sub_nowin() {
- assert!(NAN.abs_sub(-1f32).is_nan());
- assert!(1f32.abs_sub(NAN).is_nan());
- }
-
- #[test]
- fn test_signum() {
- assert_eq!(INFINITY.signum(), 1f32);
- assert_eq!(1f32.signum(), 1f32);
- assert_eq!(0f32.signum(), 1f32);
- assert_eq!((-0f32).signum(), -1f32);
- assert_eq!((-1f32).signum(), -1f32);
- assert_eq!(NEG_INFINITY.signum(), -1f32);
- assert_eq!((1f32/NEG_INFINITY).signum(), -1f32);
- assert!(NAN.signum().is_nan());
- }
-
- #[test]
- fn test_is_positive() {
- assert!(INFINITY.is_positive());
- assert!(1f32.is_positive());
- assert!(0f32.is_positive());
- assert!(!(-0f32).is_positive());
- assert!(!(-1f32).is_positive());
- assert!(!NEG_INFINITY.is_positive());
- assert!(!(1f32/NEG_INFINITY).is_positive());
- assert!(!NAN.is_positive());
- }
-
- #[test]
- fn test_is_negative() {
- assert!(!INFINITY.is_negative());
- assert!(!1f32.is_negative());
- assert!(!0f32.is_negative());
- assert!((-0f32).is_negative());
- assert!((-1f32).is_negative());
- assert!(NEG_INFINITY.is_negative());
- assert!((1f32/NEG_INFINITY).is_negative());
- assert!(!NAN.is_negative());
- }
-
- #[test]
- fn test_is_normal() {
- let nan: f32 = Float::nan();
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
- let zero: f32 = Float::zero();
- let neg_zero: f32 = Float::neg_zero();
- assert!(!nan.is_normal());
- assert!(!inf.is_normal());
- assert!(!neg_inf.is_normal());
- assert!(!zero.is_normal());
- assert!(!neg_zero.is_normal());
- assert!(1f32.is_normal());
- assert!(1e-37f32.is_normal());
- assert!(!1e-38f32.is_normal());
- }
-
- #[test]
- fn test_classify() {
- let nan: f32 = Float::nan();
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
- let zero: f32 = Float::zero();
- let neg_zero: f32 = Float::neg_zero();
- assert_eq!(nan.classify(), Fp::Nan);
- assert_eq!(inf.classify(), Fp::Infinite);
- assert_eq!(neg_inf.classify(), Fp::Infinite);
- assert_eq!(zero.classify(), Fp::Zero);
- assert_eq!(neg_zero.classify(), Fp::Zero);
- assert_eq!(1f32.classify(), Fp::Normal);
- assert_eq!(1e-37f32.classify(), Fp::Normal);
- assert_eq!(1e-38f32.classify(), Fp::Subnormal);
- }
-
- #[test]
- fn test_ldexp() {
- // We have to use from_str until base-2 exponents
- // are supported in floating-point literals
- let f1: f32 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
- let f2: f32 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
- assert_eq!(Float::ldexp(1f32, -123), f1);
- assert_eq!(Float::ldexp(1f32, -111), f2);
-
- assert_eq!(Float::ldexp(0f32, -123), 0f32);
- assert_eq!(Float::ldexp(-0f32, -123), -0f32);
-
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
- let nan: f32 = Float::nan();
- assert_eq!(Float::ldexp(inf, -123), inf);
- assert_eq!(Float::ldexp(neg_inf, -123), neg_inf);
- assert!(Float::ldexp(nan, -123).is_nan());
- }
-
- #[test]
- fn test_frexp() {
- // We have to use from_str until base-2 exponents
- // are supported in floating-point literals
- let f1: f32 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
- let f2: f32 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
- let (x1, exp1) = f1.frexp();
- let (x2, exp2) = f2.frexp();
- assert_eq!((x1, exp1), (0.5f32, -122));
- assert_eq!((x2, exp2), (0.5f32, -110));
- assert_eq!(Float::ldexp(x1, exp1), f1);
- assert_eq!(Float::ldexp(x2, exp2), f2);
-
- assert_eq!(0f32.frexp(), (0f32, 0));
- assert_eq!((-0f32).frexp(), (-0f32, 0));
- }
-
- #[test] #[cfg_attr(windows, ignore)] // FIXME #8755
- fn test_frexp_nowin() {
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
- let nan: f32 = Float::nan();
- assert_eq!(match inf.frexp() { (x, _) => x }, inf);
- assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf);
- assert!(match nan.frexp() { (x, _) => x.is_nan() })
- }
-
- #[test]
- fn test_integer_decode() {
- assert_eq!(3.14159265359f32.integer_decode(), (13176795, -22, 1));
- assert_eq!((-8573.5918555f32).integer_decode(), (8779358, -10, -1));
- assert_eq!(2f32.powf(100.0).integer_decode(), (8388608, 77, 1));
- assert_eq!(0f32.integer_decode(), (0, -150, 1));
- assert_eq!((-0f32).integer_decode(), (0, -150, -1));
- assert_eq!(INFINITY.integer_decode(), (8388608, 105, 1));
- assert_eq!(NEG_INFINITY.integer_decode(), (8388608, 105, -1));
- assert_eq!(NAN.integer_decode(), (12582912, 105, 1));
- }
-
- #[test]
- fn test_sqrt_domain() {
- assert!(NAN.sqrt().is_nan());
- assert!(NEG_INFINITY.sqrt().is_nan());
- assert!((-1.0f32).sqrt().is_nan());
- assert_eq!((-0.0f32).sqrt(), -0.0);
- assert_eq!(0.0f32.sqrt(), 0.0);
- assert_eq!(1.0f32.sqrt(), 1.0);
- assert_eq!(INFINITY.sqrt(), INFINITY);
- }
}
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
use num::*;
use num::FpCategory as Fp;
+ #[test]
+ fn test_num_f64() {
+ test_num(10f64, 2f64);
+ }
+
#[test]
fn test_min_nan() {
assert_eq!(NAN.min(2.0), 2.0);
}
#[test]
- fn test_num_f64() {
- test_num(10f64, 2f64);
+ fn test_nan() {
+ let nan: f64 = Float::nan();
+ assert!(nan.is_nan());
+ assert!(!nan.is_infinite());
+ assert!(!nan.is_finite());
+ assert!(!nan.is_normal());
+ assert!(!nan.is_positive());
+ assert!(!nan.is_negative());
+ assert_eq!(Fp::Nan, nan.classify());
+ }
+
+ #[test]
+ fn test_infinity() {
+ let inf: f64 = Float::infinity();
+ assert!(inf.is_infinite());
+ assert!(!inf.is_finite());
+ assert!(inf.is_positive());
+ assert!(!inf.is_negative());
+ assert!(!inf.is_nan());
+ assert!(!inf.is_normal());
+ assert_eq!(Fp::Infinite, inf.classify());
+ }
+
+ #[test]
+ fn test_neg_infinity() {
+ let neg_inf: f64 = Float::neg_infinity();
+ assert!(neg_inf.is_infinite());
+ assert!(!neg_inf.is_finite());
+ assert!(!neg_inf.is_positive());
+ assert!(neg_inf.is_negative());
+ assert!(!neg_inf.is_nan());
+ assert!(!neg_inf.is_normal());
+ assert_eq!(Fp::Infinite, neg_inf.classify());
+ }
+
+ #[test]
+ fn test_zero() {
+ let zero: f64 = Float::zero();
+ assert_eq!(0.0, zero);
+ assert!(!zero.is_infinite());
+ assert!(zero.is_finite());
+ assert!(zero.is_positive());
+ assert!(!zero.is_negative());
+ assert!(!zero.is_nan());
+ assert!(!zero.is_normal());
+ assert_eq!(Fp::Zero, zero.classify());
+ }
+
+ #[test]
+ fn test_neg_zero() {
+ let neg_zero: f64 = Float::neg_zero();
+ assert_eq!(0.0, neg_zero);
+ assert!(!neg_zero.is_infinite());
+ assert!(neg_zero.is_finite());
+ assert!(!neg_zero.is_positive());
+ assert!(neg_zero.is_negative());
+ assert!(!neg_zero.is_nan());
+ assert!(!neg_zero.is_normal());
+ assert_eq!(Fp::Zero, neg_zero.classify());
+ }
+
+ #[test]
+ fn test_one() {
+ let one: f64 = Float::one();
+ assert_eq!(1.0, one);
+ assert!(!one.is_infinite());
+ assert!(one.is_finite());
+ assert!(one.is_positive());
+ assert!(!one.is_negative());
+ assert!(!one.is_nan());
+ assert!(one.is_normal());
+ assert_eq!(Fp::Normal, one.classify());
+ }
+
+ #[test]
+ fn test_is_nan() {
+ let nan: f64 = Float::nan();
+ let inf: f64 = Float::infinity();
+ let neg_inf: f64 = Float::neg_infinity();
+ assert!(nan.is_nan());
+ assert!(!0.0f64.is_nan());
+ assert!(!5.3f64.is_nan());
+ assert!(!(-10.732f64).is_nan());
+ assert!(!inf.is_nan());
+ assert!(!neg_inf.is_nan());
+ }
+
+ #[test]
+ fn test_is_infinite() {
+ let nan: f64 = Float::nan();
+ let inf: f64 = Float::infinity();
+ let neg_inf: f64 = Float::neg_infinity();
+ assert!(!nan.is_infinite());
+ assert!(inf.is_infinite());
+ assert!(neg_inf.is_infinite());
+ assert!(!0.0f64.is_infinite());
+ assert!(!42.8f64.is_infinite());
+ assert!(!(-109.2f64).is_infinite());
+ }
+
+ #[test]
+ fn test_is_finite() {
+ let nan: f64 = Float::nan();
+ let inf: f64 = Float::infinity();
+ let neg_inf: f64 = Float::neg_infinity();
+ assert!(!nan.is_finite());
+ assert!(!inf.is_finite());
+ assert!(!neg_inf.is_finite());
+ assert!(0.0f64.is_finite());
+ assert!(42.8f64.is_finite());
+ assert!((-109.2f64).is_finite());
+ }
+
+ #[test]
+ fn test_is_normal() {
+ let nan: f64 = Float::nan();
+ let inf: f64 = Float::infinity();
+ let neg_inf: f64 = Float::neg_infinity();
+ let zero: f64 = Float::zero();
+ let neg_zero: f64 = Float::neg_zero();
+ assert!(!nan.is_normal());
+ assert!(!inf.is_normal());
+ assert!(!neg_inf.is_normal());
+ assert!(!zero.is_normal());
+ assert!(!neg_zero.is_normal());
+ assert!(1f64.is_normal());
+ assert!(1e-307f64.is_normal());
+ assert!(!1e-308f64.is_normal());
+ }
+
+ #[test]
+ fn test_classify() {
+ let nan: f64 = Float::nan();
+ let inf: f64 = Float::infinity();
+ let neg_inf: f64 = Float::neg_infinity();
+ let zero: f64 = Float::zero();
+ let neg_zero: f64 = Float::neg_zero();
+ assert_eq!(nan.classify(), Fp::Nan);
+ assert_eq!(inf.classify(), Fp::Infinite);
+ assert_eq!(neg_inf.classify(), Fp::Infinite);
+ assert_eq!(zero.classify(), Fp::Zero);
+ assert_eq!(neg_zero.classify(), Fp::Zero);
+ assert_eq!(1e-307f64.classify(), Fp::Normal);
+ assert_eq!(1e-308f64.classify(), Fp::Subnormal);
+ }
+
+ #[test]
+ fn test_integer_decode() {
+ assert_eq!(3.14159265359f64.integer_decode(), (7074237752028906, -51, 1));
+ assert_eq!((-8573.5918555f64).integer_decode(), (4713381968463931, -39, -1));
+ assert_eq!(2f64.powf(100.0).integer_decode(), (4503599627370496, 48, 1));
+ assert_eq!(0f64.integer_decode(), (0, -1075, 1));
+ assert_eq!((-0f64).integer_decode(), (0, -1075, -1));
+ assert_eq!(INFINITY.integer_decode(), (4503599627370496, 972, 1));
+ assert_eq!(NEG_INFINITY.integer_decode(), (4503599627370496, 972, -1));
+ assert_eq!(NAN.integer_decode(), (6755399441055744, 972, 1));
}
#[test]
assert_approx_eq!((-1.7f64).fract(), -0.7f64);
}
+ #[test]
+ fn test_abs() {
+ assert_eq!(INFINITY.abs(), INFINITY);
+ assert_eq!(1f64.abs(), 1f64);
+ assert_eq!(0f64.abs(), 0f64);
+ assert_eq!((-0f64).abs(), 0f64);
+ assert_eq!((-1f64).abs(), 1f64);
+ assert_eq!(NEG_INFINITY.abs(), INFINITY);
+ assert_eq!((1f64/NEG_INFINITY).abs(), 0f64);
+ assert!(NAN.abs().is_nan());
+ }
+
+ #[test]
+ fn test_signum() {
+ assert_eq!(INFINITY.signum(), 1f64);
+ assert_eq!(1f64.signum(), 1f64);
+ assert_eq!(0f64.signum(), 1f64);
+ assert_eq!((-0f64).signum(), -1f64);
+ assert_eq!((-1f64).signum(), -1f64);
+ assert_eq!(NEG_INFINITY.signum(), -1f64);
+ assert_eq!((1f64/NEG_INFINITY).signum(), -1f64);
+ assert!(NAN.signum().is_nan());
+ }
+
+ #[test]
+ fn test_is_positive() {
+ assert!(INFINITY.is_positive());
+ assert!(1f64.is_positive());
+ assert!(0f64.is_positive());
+ assert!(!(-0f64).is_positive());
+ assert!(!(-1f64).is_positive());
+ assert!(!NEG_INFINITY.is_positive());
+ assert!(!(1f64/NEG_INFINITY).is_positive());
+ assert!(!NAN.is_positive());
+ }
+
+ #[test]
+ fn test_is_negative() {
+ assert!(!INFINITY.is_negative());
+ assert!(!1f64.is_negative());
+ assert!(!0f64.is_negative());
+ assert!((-0f64).is_negative());
+ assert!((-1f64).is_negative());
+ assert!(NEG_INFINITY.is_negative());
+ assert!((1f64/NEG_INFINITY).is_negative());
+ assert!(!NAN.is_negative());
+ }
+
+ #[test]
+ fn test_mul_add() {
+ let nan: f64 = Float::nan();
+ let inf: f64 = Float::infinity();
+ let neg_inf: f64 = Float::neg_infinity();
+ assert_approx_eq!(12.3f64.mul_add(4.5, 6.7), 62.05);
+ assert_approx_eq!((-12.3f64).mul_add(-4.5, -6.7), 48.65);
+ assert_approx_eq!(0.0f64.mul_add(8.9, 1.2), 1.2);
+ assert_approx_eq!(3.4f64.mul_add(-0.0, 5.6), 5.6);
+ assert!(nan.mul_add(7.8, 9.0).is_nan());
+ assert_eq!(inf.mul_add(7.8, 9.0), inf);
+ assert_eq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
+ assert_eq!(8.9f64.mul_add(inf, 3.2), inf);
+ assert_eq!((-3.2f64).mul_add(2.4, neg_inf), neg_inf);
+ }
+
+ #[test]
+ fn test_recip() {
+ let nan: f64 = Float::nan();
+ let inf: f64 = Float::infinity();
+ let neg_inf: f64 = Float::neg_infinity();
+ assert_eq!(1.0f64.recip(), 1.0);
+ assert_eq!(2.0f64.recip(), 0.5);
+ assert_eq!((-0.4f64).recip(), -2.5);
+ assert_eq!(0.0f64.recip(), inf);
+ assert!(nan.recip().is_nan());
+ assert_eq!(inf.recip(), 0.0);
+ assert_eq!(neg_inf.recip(), 0.0);
+ }
+
+ #[test]
+ fn test_powi() {
+ let nan: f64 = Float::nan();
+ let inf: f64 = Float::infinity();
+ let neg_inf: f64 = Float::neg_infinity();
+ assert_eq!(1.0f64.powi(1), 1.0);
+ assert_approx_eq!((-3.1f64).powi(2), 9.61);
+ assert_approx_eq!(5.9f64.powi(-2), 0.028727);
+ assert_eq!(8.3f64.powi(0), 1.0);
+ assert!(nan.powi(2).is_nan());
+ assert_eq!(inf.powi(3), inf);
+ assert_eq!(neg_inf.powi(2), inf);
+ }
+
+ #[test]
+ fn test_powf() {
+ let nan: f64 = Float::nan();
+ let inf: f64 = Float::infinity();
+ let neg_inf: f64 = Float::neg_infinity();
+ assert_eq!(1.0f64.powf(1.0), 1.0);
+ assert_approx_eq!(3.4f64.powf(4.5), 246.408183);
+ assert_approx_eq!(2.7f64.powf(-3.2), 0.041652);
+ assert_approx_eq!((-3.1f64).powf(2.0), 9.61);
+ assert_approx_eq!(5.9f64.powf(-2.0), 0.028727);
+ assert_eq!(8.3f64.powf(0.0), 1.0);
+ assert!(nan.powf(2.0).is_nan());
+ assert_eq!(inf.powf(2.0), inf);
+ assert_eq!(neg_inf.powf(3.0), neg_inf);
+ }
+
+ #[test]
+ fn test_sqrt_domain() {
+ assert!(NAN.sqrt().is_nan());
+ assert!(NEG_INFINITY.sqrt().is_nan());
+ assert!((-1.0f64).sqrt().is_nan());
+ assert_eq!((-0.0f64).sqrt(), -0.0);
+ assert_eq!(0.0f64.sqrt(), 0.0);
+ assert_eq!(1.0f64.sqrt(), 1.0);
+ assert_eq!(INFINITY.sqrt(), INFINITY);
+ }
+
+ #[test]
+ fn test_rsqrt() {
+ let nan: f64 = Float::nan();
+ let inf: f64 = Float::infinity();
+ let neg_inf: f64 = Float::neg_infinity();
+ assert!(nan.rsqrt().is_nan());
+ assert_eq!(inf.rsqrt(), 0.0);
+ assert!(neg_inf.rsqrt().is_nan());
+ assert!((-1.0f64).rsqrt().is_nan());
+ assert_eq!((-0.0f64).rsqrt(), neg_inf);
+ assert_eq!(0.0f64.rsqrt(), inf);
+ assert_eq!(1.0f64.rsqrt(), 1.0);
+ assert_eq!(4.0f64.rsqrt(), 0.5);
+ }
+
#[test]
fn test_exp() {
assert_eq!(1.0, 0.0f64.exp());
assert!(nan.exp2().is_nan());
}
+ #[test]
+ fn test_ln() {
+ let nan: f64 = Float::nan();
+ let inf: f64 = Float::infinity();
+ let neg_inf: f64 = Float::neg_infinity();
+ assert_approx_eq!(1.0f64.exp().ln(), 1.0);
+ assert!(nan.ln().is_nan());
+ assert_eq!(inf.ln(), inf);
+ assert!(neg_inf.ln().is_nan());
+ assert!((-2.3f64).ln().is_nan());
+ assert_eq!((-0.0f64).ln(), neg_inf);
+ assert_eq!(0.0f64.ln(), neg_inf);
+ assert_approx_eq!(4.0f64.ln(), 1.386294);
+ }
+
+ #[test]
+ fn test_log() {
+ let nan: f64 = Float::nan();
+ let inf: f64 = Float::infinity();
+ let neg_inf: f64 = Float::neg_infinity();
+ assert_eq!(10.0f64.log(10.0), 1.0);
+ assert_approx_eq!(2.3f64.log(3.5), 0.664858);
+ assert_eq!(1.0f64.exp().log(1.0.exp()), 1.0);
+ assert!(1.0f64.log(1.0).is_nan());
+ assert!(1.0f64.log(-13.9).is_nan());
+ assert!(nan.log(2.3).is_nan());
+ assert_eq!(inf.log(10.0), inf);
+ assert!(neg_inf.log(8.8).is_nan());
+ assert!((-2.3f64).log(0.1).is_nan());
+ assert_eq!((-0.0f64).log(2.0), neg_inf);
+ assert_eq!(0.0f64.log(7.0), neg_inf);
+ }
+
+ #[test]
+ fn test_log2() {
+ let nan: f64 = Float::nan();
+ let inf: f64 = Float::infinity();
+ let neg_inf: f64 = Float::neg_infinity();
+ assert_approx_eq!(10.0f64.log2(), 3.321928);
+ assert_approx_eq!(2.3f64.log2(), 1.201634);
+ assert_approx_eq!(1.0f64.exp().log2(), 1.442695);
+ assert!(nan.log2().is_nan());
+ assert_eq!(inf.log2(), inf);
+ assert!(neg_inf.log2().is_nan());
+ assert!((-2.3f64).log2().is_nan());
+ assert_eq!((-0.0f64).log2(), neg_inf);
+ assert_eq!(0.0f64.log2(), neg_inf);
+ }
+
+ #[test]
+ fn test_log10() {
+ let nan: f64 = Float::nan();
+ let inf: f64 = Float::infinity();
+ let neg_inf: f64 = Float::neg_infinity();
+ assert_eq!(10.0f64.log10(), 1.0);
+ assert_approx_eq!(2.3f64.log10(), 0.361728);
+ assert_approx_eq!(1.0f64.exp().log10(), 0.434294);
+ assert_eq!(1.0f64.log10(), 0.0);
+ assert!(nan.log10().is_nan());
+ assert_eq!(inf.log10(), inf);
+ assert!(neg_inf.log10().is_nan());
+ assert!((-2.3f64).log10().is_nan());
+ assert_eq!((-0.0f64).log10(), neg_inf);
+ assert_eq!(0.0f64.log10(), neg_inf);
+ }
+
+ #[test]
+ fn test_to_degrees() {
+ let pi: f64 = consts::PI;
+ let nan: f64 = Float::nan();
+ let inf: f64 = Float::infinity();
+ let neg_inf: f64 = Float::neg_infinity();
+ assert_eq!(0.0f64.to_degrees(), 0.0);
+ assert_approx_eq!((-5.8f64).to_degrees(), -332.315521);
+ assert_eq!(pi.to_degrees(), 180.0);
+ assert!(nan.to_degrees().is_nan());
+ assert_eq!(inf.to_degrees(), inf);
+ assert_eq!(neg_inf.to_degrees(), neg_inf);
+ }
+
+ #[test]
+ fn test_to_radians() {
+ let pi: f64 = consts::PI;
+ let nan: f64 = Float::nan();
+ let inf: f64 = Float::infinity();
+ let neg_inf: f64 = Float::neg_infinity();
+ assert_eq!(0.0f64.to_radians(), 0.0);
+ assert_approx_eq!(154.6f64.to_radians(), 2.698279);
+ assert_approx_eq!((-332.31f64).to_radians(), -5.799903);
+ assert_eq!(180.0f64.to_radians(), pi);
+ assert!(nan.to_radians().is_nan());
+ assert_eq!(inf.to_radians(), inf);
+ assert_eq!(neg_inf.to_radians(), neg_inf);
+ }
+
+ #[test]
+ fn test_ldexp() {
+ // We have to use from_str until base-2 exponents
+ // are supported in floating-point literals
+ let f1: f64 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
+ let f2: f64 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
+ let f3: f64 = FromStrRadix::from_str_radix("1.Cp-12", 16).unwrap();
+ assert_eq!(Float::ldexp(1f64, -123), f1);
+ assert_eq!(Float::ldexp(1f64, -111), f2);
+ assert_eq!(Float::ldexp(1.75f64, -12), f3);
+
+ assert_eq!(Float::ldexp(0f64, -123), 0f64);
+ assert_eq!(Float::ldexp(-0f64, -123), -0f64);
+
+ let inf: f64 = Float::infinity();
+ let neg_inf: f64 = Float::neg_infinity();
+ let nan: f64 = Float::nan();
+ assert_eq!(Float::ldexp(inf, -123), inf);
+ assert_eq!(Float::ldexp(neg_inf, -123), neg_inf);
+ assert!(Float::ldexp(nan, -123).is_nan());
+ }
+
+ #[test]
+ fn test_frexp() {
+ // We have to use from_str until base-2 exponents
+ // are supported in floating-point literals
+ let f1: f64 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
+ let f2: f64 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
+ let f3: f64 = FromStrRadix::from_str_radix("1.Cp-123", 16).unwrap();
+ let (x1, exp1) = f1.frexp();
+ let (x2, exp2) = f2.frexp();
+ let (x3, exp3) = f3.frexp();
+ assert_eq!((x1, exp1), (0.5f64, -122));
+ assert_eq!((x2, exp2), (0.5f64, -110));
+ assert_eq!((x3, exp3), (0.875f64, -122));
+ assert_eq!(Float::ldexp(x1, exp1), f1);
+ assert_eq!(Float::ldexp(x2, exp2), f2);
+ assert_eq!(Float::ldexp(x3, exp3), f3);
+
+ assert_eq!(0f64.frexp(), (0f64, 0));
+ assert_eq!((-0f64).frexp(), (-0f64, 0));
+ }
+
+ #[test] #[cfg_attr(windows, ignore)] // FIXME #8755
+ fn test_frexp_nowin() {
+ let inf: f64 = Float::infinity();
+ let neg_inf: f64 = Float::neg_infinity();
+ let nan: f64 = Float::nan();
+ assert_eq!(match inf.frexp() { (x, _) => x }, inf);
+ assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf);
+ assert!(match nan.frexp() { (x, _) => x.is_nan() })
+ }
+
+ #[test]
+ fn test_abs_sub() {
+ assert_eq!((-1f64).abs_sub(1f64), 0f64);
+ assert_eq!(1f64.abs_sub(1f64), 0f64);
+ assert_eq!(1f64.abs_sub(0f64), 1f64);
+ assert_eq!(1f64.abs_sub(-1f64), 2f64);
+ assert_eq!(NEG_INFINITY.abs_sub(0f64), 0f64);
+ assert_eq!(INFINITY.abs_sub(1f64), INFINITY);
+ assert_eq!(0f64.abs_sub(NEG_INFINITY), INFINITY);
+ assert_eq!(0f64.abs_sub(INFINITY), 0f64);
+ }
+
+ #[test]
+ fn test_abs_sub_nowin() {
+ assert!(NAN.abs_sub(-1f64).is_nan());
+ assert!(1f64.abs_sub(NAN).is_nan());
+ }
+
#[test]
fn test_asinh() {
assert_eq!(0.0f64.asinh(), 0.0f64);
assert_approx_eq!(ln_2, 2f64.ln());
assert_approx_eq!(ln_10, 10f64.ln());
}
-
- #[test]
- pub fn test_abs() {
- assert_eq!(INFINITY.abs(), INFINITY);
- assert_eq!(1f64.abs(), 1f64);
- assert_eq!(0f64.abs(), 0f64);
- assert_eq!((-0f64).abs(), 0f64);
- assert_eq!((-1f64).abs(), 1f64);
- assert_eq!(NEG_INFINITY.abs(), INFINITY);
- assert_eq!((1f64/NEG_INFINITY).abs(), 0f64);
- assert!(NAN.abs().is_nan());
- }
-
- #[test]
- fn test_abs_sub() {
- assert_eq!((-1f64).abs_sub(1f64), 0f64);
- assert_eq!(1f64.abs_sub(1f64), 0f64);
- assert_eq!(1f64.abs_sub(0f64), 1f64);
- assert_eq!(1f64.abs_sub(-1f64), 2f64);
- assert_eq!(NEG_INFINITY.abs_sub(0f64), 0f64);
- assert_eq!(INFINITY.abs_sub(1f64), INFINITY);
- assert_eq!(0f64.abs_sub(NEG_INFINITY), INFINITY);
- assert_eq!(0f64.abs_sub(INFINITY), 0f64);
- }
-
- #[test]
- fn test_abs_sub_nowin() {
- assert!(NAN.abs_sub(-1f64).is_nan());
- assert!(1f64.abs_sub(NAN).is_nan());
- }
-
- #[test]
- fn test_signum() {
- assert_eq!(INFINITY.signum(), 1f64);
- assert_eq!(1f64.signum(), 1f64);
- assert_eq!(0f64.signum(), 1f64);
- assert_eq!((-0f64).signum(), -1f64);
- assert_eq!((-1f64).signum(), -1f64);
- assert_eq!(NEG_INFINITY.signum(), -1f64);
- assert_eq!((1f64/NEG_INFINITY).signum(), -1f64);
- assert!(NAN.signum().is_nan());
- }
-
- #[test]
- fn test_is_positive() {
- assert!(INFINITY.is_positive());
- assert!(1f64.is_positive());
- assert!(0f64.is_positive());
- assert!(!(-0f64).is_positive());
- assert!(!(-1f64).is_positive());
- assert!(!NEG_INFINITY.is_positive());
- assert!(!(1f64/NEG_INFINITY).is_positive());
- assert!(!NAN.is_positive());
- }
-
- #[test]
- fn test_is_negative() {
- assert!(!INFINITY.is_negative());
- assert!(!1f64.is_negative());
- assert!(!0f64.is_negative());
- assert!((-0f64).is_negative());
- assert!((-1f64).is_negative());
- assert!(NEG_INFINITY.is_negative());
- assert!((1f64/NEG_INFINITY).is_negative());
- assert!(!NAN.is_negative());
- }
-
- #[test]
- fn test_is_normal() {
- let nan: f64 = Float::nan();
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
- let zero: f64 = Float::zero();
- let neg_zero: f64 = Float::neg_zero();
- assert!(!nan.is_normal());
- assert!(!inf.is_normal());
- assert!(!neg_inf.is_normal());
- assert!(!zero.is_normal());
- assert!(!neg_zero.is_normal());
- assert!(1f64.is_normal());
- assert!(1e-307f64.is_normal());
- assert!(!1e-308f64.is_normal());
- }
-
- #[test]
- fn test_classify() {
- let nan: f64 = Float::nan();
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
- let zero: f64 = Float::zero();
- let neg_zero: f64 = Float::neg_zero();
- assert_eq!(nan.classify(), Fp::Nan);
- assert_eq!(inf.classify(), Fp::Infinite);
- assert_eq!(neg_inf.classify(), Fp::Infinite);
- assert_eq!(zero.classify(), Fp::Zero);
- assert_eq!(neg_zero.classify(), Fp::Zero);
- assert_eq!(1e-307f64.classify(), Fp::Normal);
- assert_eq!(1e-308f64.classify(), Fp::Subnormal);
- }
-
- #[test]
- fn test_ldexp() {
- // We have to use from_str until base-2 exponents
- // are supported in floating-point literals
- let f1: f64 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
- let f2: f64 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
- assert_eq!(Float::ldexp(1f64, -123), f1);
- assert_eq!(Float::ldexp(1f64, -111), f2);
-
- assert_eq!(Float::ldexp(0f64, -123), 0f64);
- assert_eq!(Float::ldexp(-0f64, -123), -0f64);
-
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
- let nan: f64 = Float::nan();
- assert_eq!(Float::ldexp(inf, -123), inf);
- assert_eq!(Float::ldexp(neg_inf, -123), neg_inf);
- assert!(Float::ldexp(nan, -123).is_nan());
- }
-
- #[test]
- fn test_frexp() {
- // We have to use from_str until base-2 exponents
- // are supported in floating-point literals
- let f1: f64 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
- let f2: f64 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
- let (x1, exp1) = f1.frexp();
- let (x2, exp2) = f2.frexp();
- assert_eq!((x1, exp1), (0.5f64, -122));
- assert_eq!((x2, exp2), (0.5f64, -110));
- assert_eq!(Float::ldexp(x1, exp1), f1);
- assert_eq!(Float::ldexp(x2, exp2), f2);
-
- assert_eq!(0f64.frexp(), (0f64, 0));
- assert_eq!((-0f64).frexp(), (-0f64, 0));
- }
-
- #[test] #[cfg_attr(windows, ignore)] // FIXME #8755
- fn test_frexp_nowin() {
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
- let nan: f64 = Float::nan();
- assert_eq!(match inf.frexp() { (x, _) => x }, inf);
- assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf);
- assert!(match nan.frexp() { (x, _) => x.is_nan() })
- }
-
- #[test]
- fn test_integer_decode() {
- assert_eq!(3.14159265359f64.integer_decode(), (7074237752028906, -51, 1));
- assert_eq!((-8573.5918555f64).integer_decode(), (4713381968463931, -39, -1));
- assert_eq!(2f64.powf(100.0).integer_decode(), (4503599627370496, 48, 1));
- assert_eq!(0f64.integer_decode(), (0, -1075, 1));
- assert_eq!((-0f64).integer_decode(), (0, -1075, -1));
- assert_eq!(INFINITY.integer_decode(), (4503599627370496, 972, 1));
- assert_eq!(NEG_INFINITY.integer_decode(), (4503599627370496, 972, -1));
- assert_eq!(NAN.integer_decode(), (6755399441055744, 972, 1));
- }
-
- #[test]
- fn test_sqrt_domain() {
- assert!(NAN.sqrt().is_nan());
- assert!(NEG_INFINITY.sqrt().is_nan());
- assert!((-1.0f64).sqrt().is_nan());
- assert_eq!((-0.0f64).sqrt(), -0.0);
- assert_eq!(0.0f64.sqrt(), 0.0);
- assert_eq!(1.0f64.sqrt(), 1.0);
- assert_eq!(INFINITY.sqrt(), INFINITY);
- }
}
}
#[test]
- #[should_fail]
+ #[should_panic]
fn dont_panic_in_drop_on_panicked_flush() {
struct FailFlushWriter;
}
#[test]
- #[should_fail]
+ #[should_panic]
fn read_to_end_error() {
let mut reader = ThreeChunkReader {
count: 0,
}
#[test]
- #[should_fail]
+ #[should_panic]
fn oneshot_fail() {
let mut timer = Timer::new().unwrap();
let _rx = timer.oneshot(Duration::milliseconds(1));
}
#[test]
- #[should_fail]
+ #[should_panic]
fn period_fail() {
let mut timer = Timer::new().unwrap();
let _rx = timer.periodic(Duration::milliseconds(1));
}
#[test]
- #[should_fail]
+ #[should_panic]
fn normal_fail() {
let _timer = Timer::new().unwrap();
panic!();
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_not_utf8_panics() {
Path::new(b"hello\x80.txt");
}
/// By default, stdin, stdout and stderr are captured (and used to
/// provide the resulting output).
///
- /// # Example
+ /// # Examples
///
/// ```
/// # #![feature(process)]
/// });
///
/// println!("status: {}", output.status);
- /// println!("stdout: {}", String::from_utf8_lossy(output.stdout.as_slice()));
- /// println!("stderr: {}", String::from_utf8_lossy(output.stderr.as_slice()));
+ /// println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
+ /// println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
/// ```
#[stable(feature = "process", since = "1.0.0")]
pub fn output(&mut self) -> io::Result<Output> {
for (ref k, ref v) in env::vars() {
// don't check windows magical empty-named variables
assert!(k.is_empty() ||
- output.contains(format!("{}={}", *k, *v).as_slice()),
+ output.contains(&format!("{}={}", *k, *v)),
"output doesn't contain `{}={}`\n{}",
k, v, output);
}
for &(ref k, ref v) in &r {
// don't check android RANDOM variables
if *k != "RANDOM".to_string() {
- assert!(output.contains(format!("{}={}",
- *k,
- *v).as_slice()) ||
- output.contains(format!("{}=\'{}\'",
- *k,
- *v).as_slice()));
+ assert!(output.contains(&format!("{}={}",
+ *k,
+ *v)) ||
+ output.contains(&format!("{}=\'{}\'",
+ *k,
+ *v)));
}
}
}
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_gen_range_panic_int() {
let mut r = thread_rng();
r.gen_range(5, -2);
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_gen_range_panic_uint() {
let mut r = thread_rng();
r.gen_range(5, 2);
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_reader_rng_insufficient_bytes() {
let mut rng = ReaderRng::new(MemReader::new(vec!()));
let mut v = [0; 3];
}
#[test]
- #[should_fail]
+ #[should_panic]
fn two_mutexes() {
static M1: StaticMutex = MUTEX_INIT;
static M2: StaticMutex = MUTEX_INIT;
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_future_panic() {
let mut f = Future::spawn(move|| panic!());
let _x: String = f.get();
use prelude::v1::*;
use sync::Arc;
+use error;
use fmt;
use mem;
use cell::UnsafeCell;
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> error::Error for SendError<T> {
+
+ fn description(&self) -> &str {
+ "sending on a closed channel"
+ }
+
+ fn cause(&self) -> Option<&error::Error> {
+ None
+ }
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> fmt::Debug for TrySendError<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> error::Error for TrySendError<T> {
+
+ fn description(&self) -> &str {
+ match *self {
+ TrySendError::Full(..) => {
+ "sending on a full channel"
+ }
+ TrySendError::Disconnected(..) => {
+ "sending on a closed channel"
+ }
+ }
+ }
+
+ fn cause(&self) -> Option<&error::Error> {
+ None
+ }
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for RecvError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl error::Error for RecvError {
+
+ fn description(&self) -> &str {
+ "receiving on a closed channel"
+ }
+
+ fn cause(&self) -> Option<&error::Error> {
+ None
+ }
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for TryRecvError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl error::Error for TryRecvError {
+
+ fn description(&self) -> &str {
+ match *self {
+ TryRecvError::Empty => {
+ "receiving on an empty channel"
+ }
+ TryRecvError::Disconnected => {
+ "receiving on a closed channel"
+ }
+ }
+ }
+
+ fn cause(&self) -> Option<&error::Error> {
+ None
+ }
+}
+
#[cfg(test)]
mod test {
use prelude::v1::*;
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_zero_tasks_panic() {
TaskPool::new(0);
}
}
#[test]
- #[should_fail]
+ #[should_panic]
fn wtf8buf_truncate_fail_code_point_boundary() {
let mut string = Wtf8Buf::from_str("aé");
string.truncate(2);
}
#[test]
- #[should_fail]
+ #[should_panic]
fn wtf8buf_truncate_fail_longer() {
let mut string = Wtf8Buf::from_str("aé");
string.truncate(4);
}
#[test]
- #[should_fail]
+ #[should_panic]
fn wtf8_slice_not_code_point_boundary() {
&Wtf8::from_str("aé 💩")[2.. 4];
}
}
#[test]
- #[should_fail]
+ #[should_panic]
fn wtf8_slice_from_not_code_point_boundary() {
&Wtf8::from_str("aé 💩")[2..];
}
}
#[test]
- #[should_fail]
+ #[should_panic]
fn wtf8_slice_to_not_code_point_boundary() {
&Wtf8::from_str("aé 💩")[5..];
}
stack::record_os_managed_stack_bounds(my_stack_bottom, my_stack_top);
}
match their_thread.name() {
- Some(name) => unsafe { imp::set_name(name.as_slice()); },
+ Some(name) => unsafe { imp::set_name(name); },
None => {}
}
thread_info::set(
/// The different kinds of types recognized by the compiler
pub enum Ty_ {
TyVec(P<Ty>),
- /// A fixed length array (`[T, ..n]`)
+ /// A fixed length array (`[T; n]`)
TyFixedLengthVec(P<Ty>, P<Expr>),
/// A raw pointer (`*const T` or `*mut T`)
TyPtr(MutTy),
}
#[test]
- #[should_fail]
+ #[should_panic]
fn t2 () {
let cm = CodeMap::new();
let fm = cm.new_filemap("blork.rs".to_string(),
}
// make sure that macros can't escape fns
- #[should_fail]
+ #[should_panic]
#[test] fn macros_cant_escape_fns_test () {
let src = "fn bogus() {macro_rules! z (() => (3+4));}\
fn inty() -> i32 { z!() }".to_string();
}
// make sure that macros can't escape modules
- #[should_fail]
+ #[should_panic]
#[test] fn macros_cant_escape_mods_test () {
let src = "mod foo {macro_rules! z (() => (3+4));}\
fn inty() -> i32 { z!() }".to_string();
for the compiler");
} else {
self.gate_feature("custom_attribute", attr.span,
- format!("The attribute `{}` is currently \
+ &format!("The attribute `{}` is currently \
unknown to the the compiler and \
may have meaning \
added to it in the future",
- name).as_slice());
+ name));
}
}
}
}))
}
- #[should_fail]
+ #[should_panic]
#[test] fn bad_path_expr_1() {
string_to_expr("::abc::def::return".to_string());
}
use ptr::P;
use util::small_vector::SmallVector;
-enum ShouldFail {
+enum ShouldPanic {
No,
Yes(Option<InternedString>),
}
path: Vec<ast::Ident> ,
bench: bool,
ignore: bool,
- should_fail: ShouldFail
+ should_panic: ShouldPanic
}
struct TestCtxt<'a> {
path: self.cx.path.clone(),
bench: is_bench_fn(&self.cx, &*i),
ignore: is_ignored(&*i),
- should_fail: should_fail(&*i)
+ should_panic: should_panic(&*i, self.cx.span_diagnostic)
};
self.cx.testfns.push(test);
self.tests.push(i.ident);
i.attrs.iter().any(|attr| attr.check_name("ignore"))
}
-fn should_fail(i: &ast::Item) -> ShouldFail {
- match i.attrs.iter().find(|attr| attr.check_name("should_fail")) {
+fn should_panic(i: &ast::Item, diag: &diagnostic::SpanHandler) -> ShouldPanic {
+ match i.attrs.iter().find(|attr| {
+ if attr.check_name("should_panic") { return true; }
+ if attr.check_name("should_fail") {
+ diag.span_warn(attr.span, "`#[should_fail]` is deprecated. Use `#[should_panic]` \
+ instead");
+ return true;
+ }
+ false
+ }) {
Some(attr) => {
let msg = attr.meta_item_list()
.and_then(|list| list.iter().find(|mi| mi.check_name("expected")))
.and_then(|mi| mi.value_str());
- ShouldFail::Yes(msg)
+ ShouldPanic::Yes(msg)
}
- None => ShouldFail::No,
+ None => ShouldPanic::No,
}
}
vec![name_expr]);
let ignore_expr = ecx.expr_bool(span, test.ignore);
- let should_fail_path = |name| {
- ecx.path(span, vec![self_id, test_id, ecx.ident_of("ShouldFail"), ecx.ident_of(name)])
+ let should_panic_path = |name| {
+ ecx.path(span, vec![self_id, test_id, ecx.ident_of("ShouldPanic"), ecx.ident_of(name)])
};
- let fail_expr = match test.should_fail {
- ShouldFail::No => ecx.expr_path(should_fail_path("No")),
- ShouldFail::Yes(ref msg) => {
- let path = should_fail_path("Yes");
+ let fail_expr = match test.should_panic {
+ ShouldPanic::No => ecx.expr_path(should_panic_path("No")),
+ ShouldPanic::Yes(ref msg) => {
+ let path = should_panic_path("Yes");
let arg = match *msg {
Some(ref msg) => ecx.expr_some(span, ecx.expr_str(span, msg.clone())),
None => ecx.expr_none(span),
test_path("TestDesc"),
vec![field("name", name_expr),
field("ignore", ignore_expr),
- field("should_fail", fail_expr)]);
+ field("should_panic", fail_expr)]);
let mut visible_path = match cx.toplevel_reexport {
use ast::Name;
#[test]
- #[should_fail]
+ #[should_panic]
fn i1 () {
let i : Interner<RcStr> = Interner::new();
i.get(Name(13));
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_expect_one_zero() {
let _: isize = SmallVector::zero().expect_one("");
}
#[test]
- #[should_fail]
+ #[should_panic]
fn test_expect_one_many() {
SmallVector::many(vec!(1, 2)).expect_one("");
}
Metric, MetricMap,
StaticTestFn, StaticTestName, DynTestName, DynTestFn,
run_test, test_main, test_main_static, filter_tests,
- parse_opts, StaticBenchFn, ShouldFail};
+ parse_opts, StaticBenchFn, ShouldPanic};
}
pub mod stats;
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-pub enum ShouldFail {
+pub enum ShouldPanic {
No,
Yes(Option<&'static str>)
}
pub struct TestDesc {
pub name: TestName,
pub ignore: bool,
- pub should_fail: ShouldFail,
+ pub should_panic: ShouldPanic,
}
unsafe impl Send for TestDesc {}
takes no arguments.
#[bench] - Indicates a function is a benchmark to be run. This
function takes one argument (test::Bencher).
- #[should_fail] - This function (also labeled with #[test]) will only pass if
- the code causes a failure (an assertion failure or panic!)
+ #[should_panic] - This function (also labeled with #[test]) will only pass if
+ the code causes a panic (an assertion failure or panic!)
A message may be provided, which the failure string must
- contain: #[should_fail(expected = "foo")].
+ contain: #[should_panic(expected = "foo")].
#[ignore] - When applied to a function which is already attributed as a
test, then the test runner will ignore these tests during
normal test runs. Running with --ignored will run these
let test_a = TestDesc {
name: StaticTestName("a"),
ignore: false,
- should_fail: ShouldFail::No
+ should_panic: ShouldPanic::No
};
let test_b = TestDesc {
name: StaticTestName("b"),
ignore: false,
- should_fail: ShouldFail::No
+ should_panic: ShouldPanic::No
};
let mut st = ConsoleTestState {
}
fn calc_result(desc: &TestDesc, task_result: Result<(), Box<Any+Send>>) -> TestResult {
- match (&desc.should_fail, task_result) {
- (&ShouldFail::No, Ok(())) |
- (&ShouldFail::Yes(None), Err(_)) => TrOk,
- (&ShouldFail::Yes(Some(msg)), Err(ref err))
+ match (&desc.should_panic, task_result) {
+ (&ShouldPanic::No, Ok(())) |
+ (&ShouldPanic::Yes(None), Err(_)) => TrOk,
+ (&ShouldPanic::Yes(Some(msg)), Err(ref err))
if err.downcast_ref::<String>()
.map(|e| &**e)
.or_else(|| err.downcast_ref::<&'static str>().map(|e| *e))
use test::{TrFailed, TrIgnored, TrOk, filter_tests, parse_opts,
TestDesc, TestDescAndFn, TestOpts, run_test,
MetricMap,
- StaticTestName, DynTestName, DynTestFn, ShouldFail};
+ StaticTestName, DynTestName, DynTestFn, ShouldPanic};
use std::thunk::Thunk;
use std::sync::mpsc::channel;
desc: TestDesc {
name: StaticTestName("whatever"),
ignore: true,
- should_fail: ShouldFail::No,
+ should_panic: ShouldPanic::No,
},
testfn: DynTestFn(Thunk::new(move|| f())),
};
desc: TestDesc {
name: StaticTestName("whatever"),
ignore: true,
- should_fail: ShouldFail::No,
+ should_panic: ShouldPanic::No,
},
testfn: DynTestFn(Thunk::new(move|| f())),
};
}
#[test]
- fn test_should_fail() {
+ fn test_should_panic() {
fn f() { panic!(); }
let desc = TestDescAndFn {
desc: TestDesc {
name: StaticTestName("whatever"),
ignore: false,
- should_fail: ShouldFail::Yes(None)
+ should_panic: ShouldPanic::Yes(None)
},
testfn: DynTestFn(Thunk::new(move|| f())),
};
}
#[test]
- fn test_should_fail_good_message() {
+ fn test_should_panic_good_message() {
fn f() { panic!("an error message"); }
let desc = TestDescAndFn {
desc: TestDesc {
name: StaticTestName("whatever"),
ignore: false,
- should_fail: ShouldFail::Yes(Some("error message"))
+ should_panic: ShouldPanic::Yes(Some("error message"))
},
testfn: DynTestFn(Thunk::new(move|| f())),
};
}
#[test]
- fn test_should_fail_bad_message() {
+ fn test_should_panic_bad_message() {
fn f() { panic!("an error message"); }
let desc = TestDescAndFn {
desc: TestDesc {
name: StaticTestName("whatever"),
ignore: false,
- should_fail: ShouldFail::Yes(Some("foobar"))
+ should_panic: ShouldPanic::Yes(Some("foobar"))
},
testfn: DynTestFn(Thunk::new(move|| f())),
};
}
#[test]
- fn test_should_fail_but_succeeds() {
+ fn test_should_panic_but_succeeds() {
fn f() { }
let desc = TestDescAndFn {
desc: TestDesc {
name: StaticTestName("whatever"),
ignore: false,
- should_fail: ShouldFail::Yes(None)
+ should_panic: ShouldPanic::Yes(None)
},
testfn: DynTestFn(Thunk::new(move|| f())),
};
desc: TestDesc {
name: StaticTestName("1"),
ignore: true,
- should_fail: ShouldFail::No,
+ should_panic: ShouldPanic::No,
},
testfn: DynTestFn(Thunk::new(move|| {})),
},
desc: TestDesc {
name: StaticTestName("2"),
ignore: false,
- should_fail: ShouldFail::No,
+ should_panic: ShouldPanic::No,
},
testfn: DynTestFn(Thunk::new(move|| {})),
});
desc: TestDesc {
name: DynTestName((*name).clone()),
ignore: false,
- should_fail: ShouldFail::No,
+ should_panic: ShouldPanic::No,
},
testfn: DynTestFn(Thunk::new(testfn)),
};
+S 2015-03-07 270a677
+ freebsd-x86_64 3c147d8e4cfdcb02c2569f5aca689a1d8920d17b
+ linux-i386 50a47ef247610fb089d2c4f24e4b641eb0ba4afb
+ linux-x86_64 ccb20709b3c984f960ddde996451be8ce2268d7c
+ macos-i386 ad263bdeadcf9bf1889426e0c1391a7cf277364e
+ macos-x86_64 01c8275828042264206b7acd8e86dc719a2f27aa
+ winnt-i386 cb73ac7a9bf408e8b5cdb92d595082a537a90794
+ winnt-x86_64 b9b47e80101f726ae4f5919373ea20b92d827f3c
+
S 2015-02-25 880fb89
bitrig-x86_64 8cdc4ca0a80103100f46cbf8caa9fe497df048c5
freebsd-x86_64 f4cbe4227739de986444211f8ee8d74745ab8f7f
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(optin_builtin_traits)]
+#![crate_type = "rlib"]
+
+use std::marker::MarkerTrait;
+
+pub trait DefaultedTrait : MarkerTrait { }
+impl DefaultedTrait for .. { }
+
+pub struct Something<T> { t: T }
+++ /dev/null
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(optin_builtin_traits)]
-
-use std::marker::Send;
-
-enum TestE {
- A
-}
-
-struct MyType;
-
-struct NotSync;
-impl !Sync for NotSync {}
-
-unsafe impl Send for TestE {}
-unsafe impl Send for MyType {}
-unsafe impl Send for (MyType, MyType) {}
-//~^ ERROR builtin traits can only be implemented on structs or enums
-
-unsafe impl Send for &'static NotSync {}
-//~^ ERROR builtin traits can only be implemented on structs or enums
-
-unsafe impl Send for [MyType] {}
-//~^ ERROR builtin traits can only be implemented on structs or enums
-
-unsafe impl Send for &'static [NotSync] {}
-//~^ ERROR builtin traits can only be implemented on structs or enums
-//~^^ ERROR conflicting implementations for trait `core::marker::Send`
-
-fn is_send<T: Send>() {}
-
-fn main() {
- is_send::<(MyType, TestE)>();
-}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::Copy;
+
+enum TestE {
+ A
+}
+
+struct MyType;
+
+struct NotSync;
+impl !Sync for NotSync {}
+
+impl Copy for TestE {}
+impl Copy for MyType {}
+impl Copy for (MyType, MyType) {}
+//~^ ERROR E0206
+
+impl Copy for &'static NotSync {}
+//~^ ERROR E0206
+
+impl Copy for [MyType] {}
+//~^ ERROR E0206
+
+impl Copy for &'static [NotSync] {}
+//~^ ERROR E0206
+
+fn main() {
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::Copy;
+
+enum TestE {
+ A
+}
+
+struct MyType;
+
+struct NotSync;
+impl !Sync for NotSync {}
+
+unsafe impl Send for TestE {}
+unsafe impl Send for MyType {}
+unsafe impl Send for (MyType, MyType) {}
+//~^ ERROR E0321
+
+unsafe impl Send for &'static NotSync {}
+//~^ ERROR E0321
+
+unsafe impl Send for [MyType] {}
+//~^ ERROR E0321
+
+unsafe impl Send for &'static [NotSync] {}
+//~^ ERROR E0321
+//~| ERROR conflicting implementations
+
+fn main() {
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::Copy;
+
+enum TestE {
+ A
+}
+
+struct MyType;
+
+struct NotSync;
+impl !Sync for NotSync {}
+
+impl Sized for TestE {} //~ ERROR E0322
+impl Sized for MyType {} //~ ERROR E0322
+impl Sized for (MyType, MyType) {} //~ ERROR E0322
+impl Sized for &'static NotSync {} //~ ERROR E0322
+impl Sized for [MyType] {} //~ ERROR E0322
+//~^ ERROR E0277
+impl Sized for &'static [NotSync] {} //~ ERROR E0322
+
+fn main() {
+}
struct TheType;
-impl TheTrait<usize> for isize { } //~ ERROR E0117
+impl TheTrait<usize> for isize { }
+//~^ ERROR E0117
impl TheTrait<TheType> for isize { }
impl TheTrait<isize> for TheType { }
-impl !Send for Vec<isize> { } //~ ERROR E0117
-//~^ ERROR conflicting
+impl !Send for Vec<isize> { }
+//~^ ERROR E0117
+//~| ERROR E0119
fn main() { }
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:typeck-default-trait-impl-cross-crate-coherence-lib.rs
+
+// Test that we do not consider associated types to be sendable without
+// some applicable trait bound (and we don't ICE).
+
+#![feature(optin_builtin_traits)]
+
+extern crate "typeck-default-trait-impl-cross-crate-coherence-lib" as lib;
+
+use lib::DefaultedTrait;
+
+struct A;
+impl DefaultedTrait for (A,) { } //~ ERROR E0321
+
+struct B;
+impl !DefaultedTrait for (B,) { } //~ ERROR E0321
+
+struct C;
+struct D<T>(T);
+impl DefaultedTrait for Box<C> { } //~ ERROR E0321
+impl DefaultedTrait for lib::Something<C> { } //~ ERROR E0321
+impl DefaultedTrait for D<C> { } // OK
+
+fn main() { }
#![feature(optin_builtin_traits)]
impl Copy for .. {}
-//~^ ERROR cannot create default implementations for traits outside the crate they're defined in; define a new trait instead.
+//~^ ERROR E0318
fn main() {}
// ignore-pretty: does not work well with `--test`
#[test]
-#[should_fail(expected = "foobar")]
+#[should_panic(expected = "foobar")]
fn test_foo() {
panic!("blah")
}
--- /dev/null
+-include ../tools.mk
+
+all:
+ $(rustc) -o foo foo.rs
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+}
.arg(format!("{} {}",
rustc,
main_file.as_str()
- .unwrap()).as_slice())
+ .unwrap()))
.output().unwrap();
let err = String::from_utf8_lossy(result.error.as_slice());
// <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.
-//
-// ignore-lexer-test FIXME #15877
trait U { fn f(self); }
-impl U for int { fn f(self) {} }
+impl U for isize { fn f(self) {} }
pub fn main() { 4.f(); }
pub fn main() {
let s = "Hello, world!".to_string();
- let _s = S {
+ let s = S {
f0: s.to_string(),
..S {
f0: s,
f1: 23
}
};
+ assert_eq!(s.f0, "Hello, world!");
}
pub fn main() {
let s = "Hello, world!".to_string();
- let _s = S {
+ let s = S {
f1: s.to_string(),
f0: s
};
+ assert_eq!(s.f0, "Hello, world!");
}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Checks that functional-record-update order-of-eval is as expected
+// even when no Drop-implementations are involved.
+
+use std::sync::atomic::{Ordering, AtomicUsize, ATOMIC_USIZE_INIT};
+
+struct W { wrapped: u32 }
+struct S { f0: W, _f1: i32 }
+
+pub fn main() {
+ const VAL: u32 = 0x89AB_CDEF;
+ let w = W { wrapped: VAL };
+ let s = S {
+ f0: { event(0x01); W { wrapped: w.wrapped + 1 } },
+ ..S {
+ f0: { event(0x02); w},
+ _f1: 23
+ }
+ };
+ assert_eq!(s.f0.wrapped, VAL + 1);
+ let actual = event_log();
+ let expect = 0x01_02;
+ assert!(expect == actual,
+ "expect: 0x{:x} actual: 0x{:x}", expect, actual);
+}
+
+static LOG: AtomicUsize = ATOMIC_USIZE_INIT;
+
+fn event_log() -> usize {
+ LOG.load(Ordering::SeqCst)
+}
+
+fn event(tag: u8) {
+ let old_log = LOG.load(Ordering::SeqCst);
+ let new_log = (old_log << 8) + tag as usize;
+ LOG.store(new_log, Ordering::SeqCst);
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Checks that struct-literal expression order-of-eval is as expected
+// even when no Drop-implementations are involved.
+
+use std::sync::atomic::{Ordering, AtomicUsize, ATOMIC_USIZE_INIT};
+
+struct W { wrapped: u32 }
+struct S { f0: W, _f1: i32 }
+
+pub fn main() {
+ const VAL: u32 = 0x89AB_CDEF;
+ let w = W { wrapped: VAL };
+ let s = S {
+ _f1: { event(0x01); 23 },
+ f0: { event(0x02); w },
+ };
+ assert_eq!(s.f0.wrapped, VAL);
+ let actual = event_log();
+ let expect = 0x01_02;
+ assert!(expect == actual,
+ "expect: 0x{:x} actual: 0x{:x}", expect, actual);
+}
+
+static LOG: AtomicUsize = ATOMIC_USIZE_INIT;
+
+fn event_log() -> usize {
+ LOG.load(Ordering::SeqCst)
+}
+
+fn event(tag: u8) {
+ let old_log = LOG.load(Ordering::SeqCst);
+ let new_log = (old_log << 8) + tag as usize;
+ LOG.store(new_log, Ordering::SeqCst);
+}
// ignore-pretty: does not work well with `--test`
#[test]
-#[should_fail(expected = "foo")]
+#[should_panic(expected = "foo")]
fn test_foo() {
panic!("foo bar")
}
#[test]
-#[should_fail(expected = "foo")]
+#[should_panic(expected = "foo")]
fn test_foo_dynamic() {
panic!("{} bar", "foo")
}
// <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.
-//
-// ignore-lexer-test FIXME #15879
// Test syntax checks for `?Sized` syntax.
// <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.
-//
-// ignore-lexer-test FIXME #15879
#![allow(unknown_features)]
#![feature(box_syntax)]