This is the implementation of the [RFC 584](https://github.com/rust-lang/rfcs/pull/584).
## 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.
if [ ! -z "$CFG_PANDOC" ]
then
+ # Extract "MAJOR MINOR" from Pandoc's version number
PV_MAJOR_MINOR=$(pandoc --version | grep '^pandoc' |
- # Extract "MAJOR MINOR" from Pandoc's version number
sed -E 's/pandoc(.exe)? ([0-9]+)\.([0-9]+).*/\2 \3/')
MIN_PV_MAJOR="1"
.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.
#![feature(unboxed_closures)]
#![feature(std_misc)]
#![feature(test)]
-#![feature(unicode)]
#![feature(core)]
#![feature(path)]
#![feature(io)]
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(),
}
let letters = line[kind_start..].chars();
let kind = letters.skip_while(|c| c.is_whitespace())
.take_while(|c| !c.is_whitespace())
- .map(|c| c.to_lowercase())
+ .flat_map(|c| c.to_lowercase())
.collect::<String>();
let letters = line[kind_start..].chars();
let msg = letters.skip_while(|c| c.is_whitespace())
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();
}
```
##### Characters and strings
-| | Example | Number of `#` pairs allowed | Available characters | Escapes | Equivalent to |
-|---|---------|-----------------------------|----------------------|---------|---------------|
-| [Character](#character-literals) | `'H'` | `N/A` | All unicode | `\'` & [Byte escapes](#byte-escapes) & [Unicode escapes](#unicode-escapes) | `N/A` |
-| [String](#string-literals) | `"hello"` | `N/A` | All unicode | `\"` & [Byte escapes](#byte-escapes) & [Unicode escapes](#unicode-escapes) | `N/A` |
-| [Raw](#raw-string-literals) | `r##"hello"##` | `0...` | All unicode | `N/A` | `N/A` |
-| [Byte](#byte-literals) | `b'H'` | `N/A` | All ASCII | `\'` & [Byte escapes](#byte-escapes) | `u8` |
-| [Byte string](#byte-string-literals) | `b"hello"` | `N/A` | All ASCII | `\"` & [Byte escapes](#byte-escapes) | `&'static [u8]` |
-| [Raw byte string](#raw-byte-string-literals) | `br##"hello"##` | `0...` | All ASCII | `N/A` | `&'static [u8]` (unsure...not stated) |
+| | Example | # sets | Characters | Escapes |
+|----------------------------------------------|---------------|--------|-------------|---------------------|
+| [Character](#character-literals) | 'H' | N/A | All Unicode | \' & [Byte](#byte-escapes) & [Unicode](#unicode-escapes) |
+| [String](#string-literals) | "hello" | N/A | All Unicode | \" & [Byte](#byte-escapes) & [Unicode](#unicode-escapes) |
+| [Raw](#raw-string-literals) | r#"hello"# | 0... | All Unicode | N/A |
+| [Byte](#byte-literals) | b'H' | N/A | All ASCII | \' & [Byte](#byte-escapes) |
+| [Byte string](#byte-string-literals) | b"hello" | N/A | All ASCII | \" & [Byte](#byte-escapes) |
+| [Raw byte string](#raw-byte-string-literals) | br#"hello"# | 0... | All ASCII | N/A |
##### Byte escapes
### 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:
`japanese` scope. We could alternatively use the wildcard syntax to include
everything from `greetings` into the current scope: `pub use self::greetings::*`.
+What about the `self`? Well, by default, `use` declarations are absolute paths,
+starting from your crate root. `self` makes that path relative to your current
+place in the hierarchy instead. There's one more special form of `use`: you can
+`use super::` to reach one level up the tree from your current location. Some
+people like to think of `self` as `.` and `super` as `..`, from many shells'
+display for the current directory and the parent directory.
+
Also, note that we `pub use`d before we declared our `mod`s. Rust requires that
`use` declarations go first.
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)
//! }
//! }
//!
}
/// An endpoint of a range of keys.
+#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
pub enum Bound<T> {
/// An inclusive bound.
Included(T),
}
#[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);
//! Unicode string manipulation (the [`str`](../primitive.str.html) type).
//!
-//! Rust's [`str`](../primitive.str.html) type is one of the core primitive types of the
-//! language. `&str` is the borrowed string type. This type of string can only be created
-//! from other strings, unless it is a `&'static str` (see below). It is not possible to
-//! move out of borrowed strings because they are owned elsewhere.
+//! Rust's [`str`](../primitive.str.html) type is one of the core primitive
+//! types of the language. `&str` is the borrowed string type. This type of
+//! string can only be created from other strings, unless it is a `&'static str`
+//! (see below). It is not possible to move out of borrowed strings because they
+//! are owned elsewhere.
//!
-//! Basic operations are implemented directly by the compiler, but more advanced operations are
-//! defined on the [`StrExt`](trait.StrExt.html) trait.
+//! Basic operations are implemented directly by the compiler, but more advanced
+//! operations are defined on the [`StrExt`](trait.StrExt.html) trait.
//!
//! # Examples
//!
//! let s = "Hello, world.";
//! ```
//!
-//! This `&str` is a `&'static str`, which is the type of string literals. They're `'static`
-//! because literals are available for the entire lifetime of the program.
+//! This `&str` is a `&'static str`, which is the type of string literals.
+//! They're `'static` because literals are available for the entire lifetime of
+//! the program.
//!
//! You can get a non-`'static` `&str` by taking a slice of a `String`:
//!
//!
//! # Representation
//!
-//! Rust's string type, `str`, is a sequence of Unicode scalar values encoded as a stream of UTF-8
-//! bytes. All [strings](../../reference.html#literals) are guaranteed to be validly encoded UTF-8
-//! sequences. Additionally, strings are not null-terminated and can thus contain null bytes.
+//! Rust's string type, `str`, is a sequence of Unicode scalar values encoded as
+//! a stream of UTF-8 bytes. All [strings](../../reference.html#literals) are
+//! guaranteed to be validly encoded UTF-8 sequences. Additionally, strings are
+//! not null-terminated and can thus contain null bytes.
//!
-//! The actual representation of `str`s have direct mappings to slices: `&str` is the same as
-//! `&[u8]`.
+//! The actual representation of `str`s have direct mappings to slices: `&str`
+//! is the same as `&[u8]`.
#![doc(primitive = "str")]
#![stable(feature = "rust1", since = "1.0.0")]
use self::RecompositionState::*;
use self::DecompositionType::*;
-use core::char::CharExt;
use core::clone::Clone;
use core::iter::AdditiveIterator;
-use core::iter::{Iterator, IteratorExt};
+use core::iter::{Iterator, IteratorExt, Extend};
use core::ops::Index;
use core::ops::RangeFull;
use core::option::Option::{self, Some, None};
use core::result::Result;
use core::slice::AsSlice;
use core::str as core_str;
+use unicode::char::CharExt;
use unicode::str::{UnicodeStr, Utf16Encoder};
use vec_deque::VecDeque;
/// Returns a slice of the string from the character range [`begin`..`end`).
///
- /// That is, start at the `begin`-th code point of the string and continue to the `end`-th code
- /// point. This does not detect or handle edge cases such as leaving a combining character as
- /// the first code point of the string.
+ /// That is, start at the `begin`-th code point of the string and continue
+ /// to the `end`-th code point. This does not detect or handle edge cases
+ /// such as leaving a combining character as the first code point of the
+ /// string.
///
- /// Due to the design of UTF-8, this operation is `O(end)`. See `slice`, `slice_to` and
- /// `slice_from` for `O(1)` variants that use byte indices rather than code point indices.
+ /// Due to the design of UTF-8, this operation is `O(end)`. See `slice`,
+ /// `slice_to` and `slice_from` for `O(1)` variants that use byte indices
+ /// rather than code point indices.
///
/// # Panics
///
- /// Panics if `begin` > `end` or the either `begin` or `end` are beyond the last character of
- /// the string.
+ /// Panics if `begin` > `end` or the either `begin` or `end` are beyond the
+ /// last character of the string.
///
/// # Examples
///
///
/// # Unsafety
///
- /// Caller must check both UTF-8 character boundaries and the boundaries of the entire slice as
- /// well.
+ /// Caller must check both UTF-8 character boundaries and the boundaries of
+ /// the entire slice as well.
///
/// # Examples
///
fn trim_right(&self) -> &str {
UnicodeStr::trim_right(&self[..])
}
+
+ /// Returns the lowercase equivalent of this string.
+ ///
+ /// # Examples
+ ///
+ /// let s = "HELLO";
+ /// assert_eq!(s.to_lowercase(), "hello");
+ #[unstable(feature = "collections")]
+ fn to_lowercase(&self) -> String {
+ let mut s = String::with_capacity(self.len());
+ s.extend(self[..].chars().flat_map(|c| c.to_lowercase()));
+ return s;
+ }
+
+ /// Returns the uppercase equivalent of this string.
+ ///
+ /// # Examples
+ ///
+ /// let s = "hello";
+ /// assert_eq!(s.to_uppercase(), "HELLO");
+ #[unstable(feature = "collections")]
+ fn to_uppercase(&self) -> String {
+ let mut s = String::with_capacity(self.len());
+ s.extend(self[..].chars().flat_map(|c| c.to_uppercase()));
+ return s;
+ }
}
#[stable(feature = "rust1", since = "1.0.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
///
/// ```
/// assert_eq!(c, Some('4'));
/// ```
#[inline]
-#[unstable(feature = "core", reason = "pending integer conventions")]
+#[stable(feature = "rust1", since = "1.0.0")]
pub fn from_digit(num: u32, radix: u32) -> Option<char> {
if radix > 36 {
panic!("from_digit: radix is too high (maximum 36)");
}
}
-/// Basic `char` manipulations.
-#[stable(feature = "rust1", since = "1.0.0")]
+// NB: the stabilization and documentation for this trait is in
+// unicode/char.rs, not here
+#[allow(missing_docs)] // docs in libunicode/u_char.rs
pub trait CharExt {
- /// Checks if a `char` parses as a numeric digit in the given radix.
- ///
- /// Compared to `is_numeric()`, this function only recognizes the characters
- /// `0-9`, `a-z` and `A-Z`.
- ///
- /// # Return value
- ///
- /// Returns `true` if `c` is a valid digit under `radix`, and `false`
- /// otherwise.
- ///
- /// # Panics
- ///
- /// Panics if given a radix > 36.
- ///
- /// # Examples
- ///
- /// ```
- /// let c = '1';
- ///
- /// assert!(c.is_digit(10));
- ///
- /// assert!('f'.is_digit(16));
- /// ```
- #[unstable(feature = "core",
- reason = "pending integer conventions")]
fn is_digit(self, radix: u32) -> bool;
-
- /// Converts a character to the corresponding digit.
- ///
- /// # Return value
- ///
- /// If `c` is between '0' and '9', the corresponding value between 0 and
- /// 9. If `c` is 'a' or 'A', 10. If `c` is 'b' or 'B', 11, etc. Returns
- /// none if the character does not refer to a digit in the given radix.
- ///
- /// # Panics
- ///
- /// Panics if given a radix outside the range [0..36].
- ///
- /// # Examples
- ///
- /// ```
- /// let c = '1';
- ///
- /// assert_eq!(c.to_digit(10), Some(1));
- ///
- /// assert_eq!('f'.to_digit(16), Some(15));
- /// ```
- #[unstable(feature = "core",
- reason = "pending integer conventions")]
fn to_digit(self, radix: u32) -> Option<u32>;
-
- /// Returns an iterator that yields the hexadecimal Unicode escape of a character, as `char`s.
- ///
- /// All characters are escaped with Rust syntax of the form `\\u{NNNN}` where `NNNN` is the
- /// shortest hexadecimal representation of the code point.
- ///
- /// # Examples
- ///
- /// ```
- /// for i in '❤'.escape_unicode() {
- /// println!("{}", i);
- /// }
- /// ```
- ///
- /// This prints:
- ///
- /// ```text
- /// \
- /// u
- /// {
- /// 2
- /// 7
- /// 6
- /// 4
- /// }
- /// ```
- ///
- /// Collecting into a `String`:
- ///
- /// ```
- /// let heart: String = '❤'.escape_unicode().collect();
- ///
- /// assert_eq!(heart, r"\u{2764}");
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
fn escape_unicode(self) -> EscapeUnicode;
-
- /// Returns an iterator that yields the 'default' ASCII and
- /// C++11-like literal escape of a character, as `char`s.
- ///
- /// The default is chosen with a bias toward producing literals that are
- /// legal in a variety of languages, including C++11 and similar C-family
- /// languages. The exact rules are:
- ///
- /// * Tab, CR and LF are escaped as '\t', '\r' and '\n' respectively.
- /// * Single-quote, double-quote and backslash chars are backslash-
- /// escaped.
- /// * Any other chars in the range [0x20,0x7e] are not escaped.
- /// * Any other chars are given hex Unicode escapes; see `escape_unicode`.
- ///
- /// # Examples
- ///
- /// ```
- /// for i in '"'.escape_default() {
- /// println!("{}", i);
- /// }
- /// ```
- ///
- /// This prints:
- ///
- /// ```text
- /// \
- /// "
- /// ```
- ///
- /// Collecting into a `String`:
- ///
- /// ```
- /// let quote: String = '"'.escape_default().collect();
- ///
- /// assert_eq!(quote, "\\\"");
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
fn escape_default(self) -> EscapeDefault;
-
- /// Returns the number of bytes this character would need if encoded in UTF-8.
- ///
- /// # Examples
- ///
- /// ```
- /// let n = 'ß'.len_utf8();
- ///
- /// assert_eq!(n, 2);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
fn len_utf8(self) -> usize;
-
- /// Returns the number of bytes this character would need if encoded in UTF-16.
- ///
- /// # Examples
- ///
- /// ```
- /// let n = 'ß'.len_utf16();
- ///
- /// assert_eq!(n, 1);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
fn len_utf16(self) -> usize;
-
- /// Encodes this character as UTF-8 into the provided byte buffer, and then returns the number
- /// of bytes written.
- ///
- /// If the buffer is not large enough, nothing will be written into it and a `None` will be
- /// returned.
- ///
- /// # Examples
- ///
- /// In both of these examples, 'ß' takes two bytes to encode.
- ///
- /// ```
- /// let mut b = [0; 2];
- ///
- /// let result = 'ß'.encode_utf8(&mut b);
- ///
- /// assert_eq!(result, Some(2));
- /// ```
- ///
- /// A buffer that's too small:
- ///
- /// ```
- /// let mut b = [0; 1];
- ///
- /// let result = 'ß'.encode_utf8(&mut b);
- ///
- /// assert_eq!(result, None);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
fn encode_utf8(self, dst: &mut [u8]) -> Option<usize>;
-
- /// Encodes this character as UTF-16 into the provided `u16` buffer, and then returns the
- /// number of `u16`s written.
- ///
- /// If the buffer is not large enough, nothing will be written into it and a `None` will be
- /// returned.
- ///
- /// # Examples
- ///
- /// In both of these examples, 'ß' takes one byte to encode.
- ///
- /// ```
- /// let mut b = [0; 1];
- ///
- /// let result = 'ß'.encode_utf16(&mut b);
- ///
- /// assert_eq!(result, Some(1));
- /// ```
- ///
- /// A buffer that's too small:
- ///
- /// ```
- /// let mut b = [0; 0];
- ///
- /// let result = 'ß'.encode_utf8(&mut b);
- ///
- /// assert_eq!(result, None);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
fn encode_utf16(self, dst: &mut [u16]) -> Option<usize>;
}
-#[stable(feature = "rust1", since = "1.0.0")]
impl CharExt for char {
- #[unstable(feature = "core",
- reason = "pending integer conventions")]
fn is_digit(self, radix: u32) -> bool {
self.to_digit(radix).is_some()
}
- #[unstable(feature = "core",
- reason = "pending integer conventions")]
fn to_digit(self, radix: u32) -> Option<u32> {
if radix > 36 {
panic!("to_digit: radix is too high (maximum 36)");
else { None }
}
- #[stable(feature = "rust1", since = "1.0.0")]
fn escape_unicode(self) -> EscapeUnicode {
EscapeUnicode { c: self, state: EscapeUnicodeState::Backslash }
}
- #[stable(feature = "rust1", since = "1.0.0")]
fn escape_default(self) -> EscapeDefault {
let init_state = match self {
'\t' => EscapeDefaultState::Backslash('t'),
}
#[inline]
- #[stable(feature = "rust1", since = "1.0.0")]
fn len_utf8(self) -> usize {
let code = self as u32;
if code < MAX_ONE_B {
}
#[inline]
- #[stable(feature = "rust1", since = "1.0.0")]
fn len_utf16(self) -> usize {
let ch = self as u32;
if (ch & 0xFFFF) == ch { 1 } else { 2 }
}
#[inline]
- #[unstable(feature = "core",
- reason = "pending decision about Iterator/Writer/Reader")]
fn encode_utf8(self, dst: &mut [u8]) -> Option<usize> {
encode_utf8_raw(self as u32, dst)
}
#[inline]
- #[unstable(feature = "core",
- reason = "pending decision about Iterator/Writer/Reader")]
fn encode_utf16(self, dst: &mut [u16]) -> Option<usize> {
encode_utf16_raw(self as u32, dst)
}
/// If the buffer is not large enough, nothing will be written into it
/// and a `None` will be returned.
#[inline]
-#[unstable(feature = "core")]
pub fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> Option<usize> {
// Marked #[inline] to allow llvm optimizing it away
if code < MAX_ONE_B && dst.len() >= 1 {
/// If the buffer is not large enough, nothing will be written into it
/// and a `None` will be returned.
#[inline]
-#[unstable(feature = "core")]
pub fn encode_utf16_raw(mut ch: u32, dst: &mut [u16]) -> Option<usize> {
// Marked #[inline] to allow llvm optimizing it away
if (ch & 0xFFFF) == ch && dst.len() >= 1 {
}
#[derive(Clone)]
-#[unstable(feature = "core")]
enum EscapeUnicodeState {
Backslash,
Type,
}
#[derive(Clone)]
-#[unstable(feature = "core")]
enum EscapeDefaultState {
Backslash(char),
Char(char),
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(());
//! }
//! ```
iter: slice::Iter<'a, u8>
}
-// Return the initial codepoint accumulator for the first byte.
-// The first byte is special, only want bottom 5 bits for width 2, 4 bits
-// for width 3, and 3 bits for width 4
-macro_rules! utf8_first_byte {
- ($byte:expr, $width:expr) => (($byte & (0x7F >> $width)) as u32)
-}
+/// Return the initial codepoint accumulator for the first byte.
+/// The first byte is special, only want bottom 5 bits for width 2, 4 bits
+/// for width 3, and 3 bits for width 4.
+#[inline]
+fn utf8_first_byte(byte: u8, width: u32) -> u32 { (byte & (0x7F >> width)) as u32 }
-// return the value of $ch updated with continuation byte $byte
-macro_rules! utf8_acc_cont_byte {
- ($ch:expr, $byte:expr) => (($ch << 6) | ($byte & CONT_MASK) as u32)
-}
+/// Return the value of `ch` updated with continuation byte `byte`.
+#[inline]
+fn utf8_acc_cont_byte(ch: u32, byte: u8) -> u32 { (ch << 6) | (byte & CONT_MASK) as u32 }
-macro_rules! utf8_is_cont_byte {
- ($byte:expr) => (($byte & !CONT_MASK) == TAG_CONT_U8)
-}
+/// Checks whether the byte is a UTF-8 continuation byte (i.e. starts with the
+/// bits `10`).
+#[inline]
+fn utf8_is_cont_byte(byte: u8) -> bool { (byte & !CONT_MASK) == TAG_CONT_U8 }
#[inline]
fn unwrap_or_0(opt: Option<&u8>) -> u8 {
// Multibyte case follows
// Decode from a byte combination out of: [[[x y] z] w]
// NOTE: Performance is sensitive to the exact formulation here
- let init = utf8_first_byte!(x, 2);
+ let init = utf8_first_byte(x, 2);
let y = unwrap_or_0(bytes.next());
- let mut ch = utf8_acc_cont_byte!(init, y);
+ let mut ch = utf8_acc_cont_byte(init, y);
if x >= 0xE0 {
// [[x y z] w] case
// 5th bit in 0xE0 .. 0xEF is always clear, so `init` is still valid
let z = unwrap_or_0(bytes.next());
- let y_z = utf8_acc_cont_byte!((y & CONT_MASK) as u32, z);
+ let y_z = utf8_acc_cont_byte((y & CONT_MASK) as u32, z);
ch = init << 12 | y_z;
if x >= 0xF0 {
// [x y z w] case
// use only the lower 3 bits of `init`
let w = unwrap_or_0(bytes.next());
- ch = (init & 7) << 18 | utf8_acc_cont_byte!(y_z, w);
+ ch = (init & 7) << 18 | utf8_acc_cont_byte(y_z, w);
}
}
// Decode from a byte combination out of: [x [y [z w]]]
let mut ch;
let z = unwrap_or_0(bytes.next_back());
- ch = utf8_first_byte!(z, 2);
- if utf8_is_cont_byte!(z) {
+ ch = utf8_first_byte(z, 2);
+ if utf8_is_cont_byte(z) {
let y = unwrap_or_0(bytes.next_back());
- ch = utf8_first_byte!(y, 3);
- if utf8_is_cont_byte!(y) {
+ ch = utf8_first_byte(y, 3);
+ if utf8_is_cont_byte(y) {
let x = unwrap_or_0(bytes.next_back());
- ch = utf8_first_byte!(x, 4);
- ch = utf8_acc_cont_byte!(ch, y);
+ ch = utf8_first_byte(x, 4);
+ ch = utf8_acc_cont_byte(ch, y);
}
- ch = utf8_acc_cont_byte!(ch, z);
+ ch = utf8_acc_cont_byte(ch, z);
}
- ch = utf8_acc_cont_byte!(ch, w);
+ ch = utf8_acc_cont_byte(ch, w);
Some(ch)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (len, _) = self.iter.size_hint();
- (len.saturating_add(3) / 4, Some(len))
+ // `(len + 3)` can't overflow, because we know that the `slice::Iter`
+ // belongs to a slice in memory which has a maximum length of
+ // `isize::MAX` (that's well below `usize::MAX`).
+ ((len + 3) / 4, Some(len))
}
}
// ASCII characters are always valid, so only large
// bytes need more examination.
if first >= 128 {
- let w = UTF8_CHAR_WIDTH[first as usize] as usize;
+ let w = UTF8_CHAR_WIDTH[first as usize];
let second = next!();
// 2-byte encoding is for codepoints \u{0080} to \u{07ff}
// first C2 80 last DF BF
i -= 1;
}
- let mut val = s.as_bytes()[i] as u32;
- let w = UTF8_CHAR_WIDTH[val as usize] as usize;
- assert!((w != 0));
+ let first= s.as_bytes()[i];
+ let w = UTF8_CHAR_WIDTH[first as usize];
+ assert!(w != 0);
- val = utf8_first_byte!(val, w);
- val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 1]);
- if w > 2 { val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 2]); }
- if w > 3 { val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 3]); }
+ let mut val = utf8_first_byte(first, w as u32);
+ val = utf8_acc_cont_byte(val, s.as_bytes()[i + 1]);
+ if w > 2 { val = utf8_acc_cont_byte(val, s.as_bytes()[i + 2]); }
+ if w > 3 { val = utf8_acc_cont_byte(val, s.as_bytes()[i + 3]); }
return CharRange {ch: unsafe { mem::transmute(val) }, next: i};
}
// Multibyte case is a fn to allow char_range_at to inline cleanly
fn multibyte_char_range_at(bytes: &[u8], i: usize) -> (u32, usize) {
- let mut val = bytes[i] as u32;
- let w = UTF8_CHAR_WIDTH[val as usize] as usize;
- assert!((w != 0));
+ let first = bytes[i];
+ let w = UTF8_CHAR_WIDTH[first as usize];
+ assert!(w != 0);
- val = utf8_first_byte!(val, w);
- val = utf8_acc_cont_byte!(val, bytes[i + 1]);
- if w > 2 { val = utf8_acc_cont_byte!(val, bytes[i + 2]); }
- if w > 3 { val = utf8_acc_cont_byte!(val, bytes[i + 3]); }
+ let mut val = utf8_first_byte(first, w as u32);
+ val = utf8_acc_cont_byte(val, bytes[i + 1]);
+ if w > 2 { val = utf8_acc_cont_byte(val, bytes[i + 2]); }
+ if w > 3 { val = utf8_acc_cont_byte(val, bytes[i + 3]); }
- return (val, i + w);
+ return (val, i + w as usize);
}
multibyte_char_range_at(bytes, i)
}
#[test]
-#[should_fail]
+#[should_panic]
fn discard_doesnt_unborrow() {
let x = RefCell::new(0);
let _b = x.borrow();
#[test]
fn test_to_lowercase() {
- assert_eq!('A'.to_lowercase(), 'a');
- assert_eq!('Ö'.to_lowercase(), 'ö');
- assert_eq!('ß'.to_lowercase(), 'ß');
- assert_eq!('Ü'.to_lowercase(), 'ü');
- assert_eq!('💩'.to_lowercase(), '💩');
- assert_eq!('Σ'.to_lowercase(), 'σ');
- assert_eq!('Τ'.to_lowercase(), 'τ');
- assert_eq!('Ι'.to_lowercase(), 'ι');
- assert_eq!('Γ'.to_lowercase(), 'γ');
- assert_eq!('Μ'.to_lowercase(), 'μ');
- assert_eq!('Α'.to_lowercase(), 'α');
- assert_eq!('Σ'.to_lowercase(), 'σ');
+ fn lower(c: char) -> char {
+ let mut it = c.to_lowercase();
+ let c = it.next().unwrap();
+ assert!(it.next().is_none());
+ c
+ }
+ assert_eq!(lower('A'), 'a');
+ assert_eq!(lower('Ö'), 'ö');
+ assert_eq!(lower('ß'), 'ß');
+ assert_eq!(lower('Ü'), 'ü');
+ assert_eq!(lower('💩'), '💩');
+ assert_eq!(lower('Σ'), 'σ');
+ assert_eq!(lower('Τ'), 'τ');
+ assert_eq!(lower('Ι'), 'ι');
+ assert_eq!(lower('Γ'), 'γ');
+ assert_eq!(lower('Μ'), 'μ');
+ assert_eq!(lower('Α'), 'α');
+ assert_eq!(lower('Σ'), 'σ');
}
#[test]
fn test_to_uppercase() {
- assert_eq!('a'.to_uppercase(), 'A');
- assert_eq!('ö'.to_uppercase(), 'Ö');
- assert_eq!('ß'.to_uppercase(), 'ß'); // not ẞ: Latin capital letter sharp s
- assert_eq!('ü'.to_uppercase(), 'Ü');
- assert_eq!('💩'.to_uppercase(), '💩');
-
- assert_eq!('σ'.to_uppercase(), 'Σ');
- assert_eq!('τ'.to_uppercase(), 'Τ');
- assert_eq!('ι'.to_uppercase(), 'Ι');
- assert_eq!('γ'.to_uppercase(), 'Γ');
- assert_eq!('μ'.to_uppercase(), 'Μ');
- assert_eq!('α'.to_uppercase(), 'Α');
- assert_eq!('ς'.to_uppercase(), 'Σ');
+ fn upper(c: char) -> char {
+ let mut it = c.to_uppercase();
+ let c = it.next().unwrap();
+ assert!(it.next().is_none());
+ c
+ }
+ assert_eq!(upper('a'), 'A');
+ assert_eq!(upper('ö'), 'Ö');
+ assert_eq!(upper('ß'), 'ß'); // not ẞ: Latin capital letter sharp s
+ assert_eq!(upper('ü'), 'Ü');
+ assert_eq!(upper('💩'), '💩');
+
+ assert_eq!(upper('σ'), 'Σ');
+ assert_eq!(upper('τ'), 'Τ');
+ assert_eq!(upper('ι'), 'Ι');
+ assert_eq!(upper('γ'), 'Γ');
+ assert_eq!(upper('μ'), 'Μ');
+ assert_eq!(upper('α'), 'Α');
+ assert_eq!(upper('ς'), 'Σ');
}
#[test]
}
#[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 {
pub fn get_attrs<'tcx>(tcx: &'tcx ctxt, did: DefId)
-> Cow<'tcx, [ast::Attribute]> {
if is_local(did) {
- let item = tcx.map.expect_item(did.node);
- Cow::Borrowed(&item.attrs)
+ Cow::Borrowed(tcx.map.attrs(did.node))
} else {
Cow::Owned(csearch::get_item_attrs(&tcx.sess.cstore, did))
}
|| 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,
#![feature(rustc_private)]
#![feature(unsafe_destructor)]
#![feature(staged_api)]
-#![feature(unicode)]
#![feature(exit_status)]
#![feature(path)]
#![feature(io)]
let print_lint_groups = |lints: Vec<(&'static str, Vec<lint::LintId>)>| {
for (name, to) in lints {
- let name = name.chars().map(|x| x.to_lowercase())
- .collect::<String>().replace("_", "-");
+ let name = name.to_lowercase().replace("_", "-");
let desc = to.into_iter().map(|x| x.as_str().replace("_", "-"))
.collect::<Vec<String>>().connect(", ");
println!(" {} {}",
fn to_camel_case(s: &str) -> String {
s.split('_').flat_map(|word| word.chars().enumerate().map(|(i, c)|
if i == 0 {
- c.to_uppercase()
+ c.to_uppercase().collect::<String>()
} else {
- c
+ c.to_string()
}
- )).collect()
+ )).collect::<Vec<_>>().concat()
}
let s = token::get_ident(ident);
buf = String::new();
}
last_upper = ch.is_uppercase();
- buf.push(ch.to_lowercase());
+ buf.extend(ch.to_lowercase());
}
words.push(buf);
}
let s = token::get_ident(ident);
if s.chars().any(|c| c.is_lowercase()) {
- let uc: String = NonSnakeCase::to_snake_case(&s).chars()
- .map(|c| c.to_uppercase()).collect();
+ let uc = NonSnakeCase::to_snake_case(&s).to_uppercase();
if uc != &s[..] {
cx.span_lint(NON_UPPER_CASE_GLOBALS, span,
&format!("{} `{}` should have an upper case name such as `{}`",
!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(..) => {
#![feature(unsafe_destructor)]
#![feature(staged_api)]
#![feature(std_misc)]
-#![feature(unicode)]
#![cfg_attr(test, feature(test))]
extern crate syntax;
// 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 }
let short = short.to_string();
let v = map.entry(short).get().unwrap_or_else(
|vacant_entry| vacant_entry.insert(Vec::with_capacity(1)));
- v.push((myname, Some(shorter_line(item.doc_value()))));
+ v.push((myname, Some(plain_summary_line(item.doc_value()))));
}
for (_, items) in &mut map {
}
#[inline]
-fn shorter_line(s: Option<&str>) -> String {
- shorter(s).replace("\n", " ")
+fn plain_summary_line(s: Option<&str>) -> String {
+ let line = shorter(s).replace("\n", " ");
+ markdown::plain_summary_line(&line[..])
}
fn document(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::Result {
h3 {
font-size: 1.3em;
}
-h1, h2, h3:not(.impl):not(.method):not(.type), h4:not(.method):not(.type) {
+h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) {
color: black;
font-weight: 500;
margin: 20px 0 15px 0;
border-bottom: 1px dashed #D5D5D5;
margin-top: 0;
}
-h2, h3:not(.impl):not(.method):not(.type), h4:not(.method):not(.type) {
+h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) {
border-bottom: 1px solid #DDDDDD;
}
h3.impl, h3.method, h4.method, h3.type, h4.type {
#[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,
pub fn from_errno(errno: i32, detail: bool) -> IoError {
let mut err = sys::decode_error(errno as i32);
if detail && err.kind == OtherIoError {
- err.detail = Some(os::error_string(errno).chars()
- .map(|c| c.to_lowercase()).collect())
+ err.detail = Some(os::error_string(errno).to_lowercase());
}
err
}
#[cfg(windows)]
impl hash::Hash for EnvKey {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
+ use ascii::AsciiExt;
let &EnvKey(ref x) = self;
match str::from_utf8(x.as_bytes()) {
Ok(s) => for ch in s.chars() {
- (ch as u8 as char).to_lowercase().hash(state);
+ ch.to_ascii_lowercase().hash(state);
},
Err(..) => x.hash(state)
}
#[cfg(windows)]
impl PartialEq for EnvKey {
fn eq(&self, other: &EnvKey) -> bool {
+ use ascii::AsciiExt;
let &EnvKey(ref x) = self;
let &EnvKey(ref y) = other;
match (str::from_utf8(x.as_bytes()), str::from_utf8(y.as_bytes())) {
return false
} else {
for (xch, ych) in xs.chars().zip(ys.chars()) {
- if xch.to_lowercase() != ych.to_lowercase() {
+ if xch.to_ascii_lowercase() != ych.to_ascii_lowercase() {
return false;
}
}
}
#[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),
}
}
- /// Given a node ID and a closure, apply the closure to the array
- /// of attributes associated with the AST corresponding to the Node ID
- pub fn with_attrs<T, F>(&self, id: NodeId, f: F) -> T where
- F: FnOnce(Option<&[Attribute]>) -> T,
- {
- let attrs = match self.get(id) {
- NodeItem(i) => Some(&i.attrs[..]),
- NodeForeignItem(fi) => Some(&fi.attrs[..]),
- NodeTraitItem(ref tm) => match **tm {
+ /// Given a node ID, get a list of of attributes associated with the AST
+ /// corresponding to the Node ID
+ pub fn attrs(&self, id: NodeId) -> &[Attribute] {
+ let attrs = match self.find(id) {
+ Some(NodeItem(i)) => Some(&i.attrs[..]),
+ Some(NodeForeignItem(fi)) => Some(&fi.attrs[..]),
+ Some(NodeTraitItem(ref tm)) => match **tm {
RequiredMethod(ref type_m) => Some(&type_m.attrs[..]),
ProvidedMethod(ref m) => Some(&m.attrs[..]),
TypeTraitItem(ref typ) => Some(&typ.attrs[..]),
},
- NodeImplItem(ref ii) => {
+ Some(NodeImplItem(ref ii)) => {
match **ii {
MethodImplItem(ref m) => Some(&m.attrs[..]),
TypeImplItem(ref t) => Some(&t.attrs[..]),
}
}
- NodeVariant(ref v) => Some(&v.node.attrs[..]),
+ Some(NodeVariant(ref v)) => Some(&v.node.attrs[..]),
// unit/tuple structs take the attributes straight from
// the struct definition.
- // FIXME(eddyb) make this work again (requires access to the map).
- NodeStructCtor(_) => {
- return self.with_attrs(self.get_parent(id), f);
+ Some(NodeStructCtor(_)) => {
+ return self.attrs(self.get_parent(id));
}
_ => None
};
- f(attrs)
+ attrs.unwrap_or(&[])
}
/// Returns an iterator that yields the node id's with paths that
}
#[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("");
}
#![feature(rustc_private)]
#![feature(staged_api)]
#![feature(std_misc)]
-#![feature(unicode)]
#![feature(path_ext)]
#![cfg_attr(windows, feature(libc))]
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))
return summ5;
}
- n *= 2;
+ // If we overflow here just return the results so far. We check a
+ // multiplier of 10 because we're about to multiply by 2 and the
+ // next iteration of the loop will also multiply by 5 (to calculate
+ // the summ5 result)
+ n = match n.checked_mul(10) {
+ Some(_) => n * 2,
+ None => return summ5,
+ };
}
}
}
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)),
};
--- /dev/null
+// Copyright 2012-2014 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.
+
+//! Character manipulation (`char` type, Unicode Scalar Value)
+//!
+//! This module provides the `CharExt` trait, as well as its
+//! implementation for the primitive `char` type, in order to allow
+//! basic character manipulation.
+//!
+//! A `char` actually represents a
+//! *[Unicode Scalar
+//! Value](http://www.unicode.org/glossary/#unicode_scalar_value)*, as it can
+//! contain any Unicode code point except high-surrogate and low-surrogate code
+//! points.
+//!
+//! As such, only values in the ranges \[0x0,0xD7FF\] and \[0xE000,0x10FFFF\]
+//! (inclusive) are allowed. A `char` can always be safely cast to a `u32`;
+//! however the converse is not always true due to the above range limits
+//! and, as such, should be performed via the `from_u32` function.
+
+#![stable(feature = "rust1", since = "1.0.0")]
+#![doc(primitive = "char")]
+
+use core::char::CharExt as C;
+use core::option::Option::{self, Some};
+use core::iter::Iterator;
+use tables::{derived_property, property, general_category, conversions, charwidth};
+
+// stable reexports
+pub use core::char::{MAX, from_u32, from_digit, EscapeUnicode, EscapeDefault};
+
+// unstable reexports
+pub use normalize::{decompose_canonical, decompose_compatible, compose};
+pub use tables::normalization::canonical_combining_class;
+pub use tables::UNICODE_VERSION;
+
+/// Functionality for manipulating `char`.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait CharExt {
+ /// Checks if a `char` parses as a numeric digit in the given radix.
+ ///
+ /// Compared to `is_numeric()`, this function only recognizes the characters
+ /// `0-9`, `a-z` and `A-Z`.
+ ///
+ /// # Return value
+ ///
+ /// Returns `true` if `c` is a valid digit under `radix`, and `false`
+ /// otherwise.
+ ///
+ /// # Panics
+ ///
+ /// Panics if given a radix > 36.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let c = '1';
+ ///
+ /// assert!(c.is_digit(10));
+ ///
+ /// assert!('f'.is_digit(16));
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn is_digit(self, radix: u32) -> bool;
+
+ /// Converts a character to the corresponding digit.
+ ///
+ /// # Return value
+ ///
+ /// If `c` is between '0' and '9', the corresponding value between 0 and
+ /// 9. If `c` is 'a' or 'A', 10. If `c` is 'b' or 'B', 11, etc. Returns
+ /// none if the character does not refer to a digit in the given radix.
+ ///
+ /// # Panics
+ ///
+ /// Panics if given a radix outside the range [0..36].
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let c = '1';
+ ///
+ /// assert_eq!(c.to_digit(10), Some(1));
+ ///
+ /// assert_eq!('f'.to_digit(16), Some(15));
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn to_digit(self, radix: u32) -> Option<u32>;
+
+ /// Returns an iterator that yields the hexadecimal Unicode escape of a
+ /// character, as `char`s.
+ ///
+ /// All characters are escaped with Rust syntax of the form `\\u{NNNN}`
+ /// where `NNNN` is the shortest hexadecimal representation of the code
+ /// point.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// for i in '❤'.escape_unicode() {
+ /// println!("{}", i);
+ /// }
+ /// ```
+ ///
+ /// This prints:
+ ///
+ /// ```text
+ /// \
+ /// u
+ /// {
+ /// 2
+ /// 7
+ /// 6
+ /// 4
+ /// }
+ /// ```
+ ///
+ /// Collecting into a `String`:
+ ///
+ /// ```
+ /// let heart: String = '❤'.escape_unicode().collect();
+ ///
+ /// assert_eq!(heart, r"\u{2764}");
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn escape_unicode(self) -> EscapeUnicode;
+
+ /// Returns an iterator that yields the 'default' ASCII and
+ /// C++11-like literal escape of a character, as `char`s.
+ ///
+ /// The default is chosen with a bias toward producing literals that are
+ /// legal in a variety of languages, including C++11 and similar C-family
+ /// languages. The exact rules are:
+ ///
+ /// * Tab, CR and LF are escaped as '\t', '\r' and '\n' respectively.
+ /// * Single-quote, double-quote and backslash chars are backslash-
+ /// escaped.
+ /// * Any other chars in the range [0x20,0x7e] are not escaped.
+ /// * Any other chars are given hex Unicode escapes; see `escape_unicode`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// for i in '"'.escape_default() {
+ /// println!("{}", i);
+ /// }
+ /// ```
+ ///
+ /// This prints:
+ ///
+ /// ```text
+ /// \
+ /// "
+ /// ```
+ ///
+ /// Collecting into a `String`:
+ ///
+ /// ```
+ /// let quote: String = '"'.escape_default().collect();
+ ///
+ /// assert_eq!(quote, "\\\"");
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn escape_default(self) -> EscapeDefault;
+
+ /// Returns the number of bytes this character would need if encoded in
+ /// UTF-8.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let n = 'ß'.len_utf8();
+ ///
+ /// assert_eq!(n, 2);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn len_utf8(self) -> usize;
+
+ /// Returns the number of 16-bit code units this character would need if
+ /// encoded in UTF-16.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let n = 'ß'.len_utf16();
+ ///
+ /// assert_eq!(n, 1);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn len_utf16(self) -> usize;
+
+ /// Encodes this character as UTF-8 into the provided byte buffer, and then
+ /// returns the number of bytes written.
+ ///
+ /// If the buffer is not large enough, nothing will be written into it and a
+ /// `None` will be returned. A buffer of length four is large enough to
+ /// encode any `char`.
+ ///
+ /// # Examples
+ ///
+ /// In both of these examples, 'ß' takes two bytes to encode.
+ ///
+ /// ```
+ /// let mut b = [0; 2];
+ ///
+ /// let result = 'ß'.encode_utf8(&mut b);
+ ///
+ /// assert_eq!(result, Some(2));
+ /// ```
+ ///
+ /// A buffer that's too small:
+ ///
+ /// ```
+ /// let mut b = [0; 1];
+ ///
+ /// let result = 'ß'.encode_utf8(&mut b);
+ ///
+ /// assert_eq!(result, None);
+ /// ```
+ #[unstable(feature = "unicode",
+ reason = "pending decision about Iterator/Writer/Reader")]
+ fn encode_utf8(self, dst: &mut [u8]) -> Option<usize>;
+
+ /// Encodes this character as UTF-16 into the provided `u16` buffer, and
+ /// then returns the number of `u16`s written.
+ ///
+ /// If the buffer is not large enough, nothing will be written into it and a
+ /// `None` will be returned. A buffer of length 2 is large enough to encode
+ /// any `char`.
+ ///
+ /// # Examples
+ ///
+ /// In both of these examples, 'ß' takes one `u16` to encode.
+ ///
+ /// ```
+ /// let mut b = [0; 1];
+ ///
+ /// let result = 'ß'.encode_utf16(&mut b);
+ ///
+ /// assert_eq!(result, Some(1));
+ /// ```
+ ///
+ /// A buffer that's too small:
+ ///
+ /// ```
+ /// let mut b = [0; 0];
+ ///
+ /// let result = 'ß'.encode_utf8(&mut b);
+ ///
+ /// assert_eq!(result, None);
+ /// ```
+ #[unstable(feature = "unicode",
+ reason = "pending decision about Iterator/Writer/Reader")]
+ fn encode_utf16(self, dst: &mut [u16]) -> Option<usize>;
+
+ /// Returns whether the specified character is considered a Unicode
+ /// alphabetic code point.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn is_alphabetic(self) -> bool;
+
+ /// Returns whether the specified character satisfies the 'XID_Start'
+ /// Unicode property.
+ ///
+ /// 'XID_Start' is a Unicode Derived Property specified in
+ /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
+ /// mostly similar to ID_Start but modified for closure under NFKx.
+ #[unstable(feature = "unicode",
+ reason = "mainly needed for compiler internals")]
+ fn is_xid_start(self) -> bool;
+
+ /// Returns whether the specified `char` satisfies the 'XID_Continue'
+ /// Unicode property.
+ ///
+ /// 'XID_Continue' is a Unicode Derived Property specified in
+ /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
+ /// mostly similar to 'ID_Continue' but modified for closure under NFKx.
+ #[unstable(feature = "unicode",
+ reason = "mainly needed for compiler internals")]
+ fn is_xid_continue(self) -> bool;
+
+ /// Indicates whether a character is in lowercase.
+ ///
+ /// This is defined according to the terms of the Unicode Derived Core
+ /// Property `Lowercase`.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn is_lowercase(self) -> bool;
+
+ /// Indicates whether a character is in uppercase.
+ ///
+ /// This is defined according to the terms of the Unicode Derived Core
+ /// Property `Uppercase`.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn is_uppercase(self) -> bool;
+
+ /// Indicates whether a character is whitespace.
+ ///
+ /// Whitespace is defined in terms of the Unicode Property `White_Space`.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn is_whitespace(self) -> bool;
+
+ /// Indicates whether a character is alphanumeric.
+ ///
+ /// Alphanumericness is defined in terms of the Unicode General Categories
+ /// 'Nd', 'Nl', 'No' and the Derived Core Property 'Alphabetic'.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn is_alphanumeric(self) -> bool;
+
+ /// Indicates whether a character is a control code point.
+ ///
+ /// Control code points are defined in terms of the Unicode General
+ /// Category `Cc`.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn is_control(self) -> bool;
+
+ /// Indicates whether the character is numeric (Nd, Nl, or No).
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn is_numeric(self) -> bool;
+
+ /// Converts a character to its lowercase equivalent.
+ ///
+ /// The case-folding performed is the common or simple mapping. See
+ /// `to_uppercase()` for references and more information.
+ ///
+ /// # Return value
+ ///
+ /// Returns an iterator which yields the characters corresponding to the
+ /// lowercase equivalent of the character. If no conversion is possible then
+ /// the input character is returned.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn to_lowercase(self) -> ToLowercase;
+
+ /// Converts a character to its uppercase equivalent.
+ ///
+ /// The case-folding performed is the common or simple mapping: it maps
+ /// one Unicode codepoint to its uppercase equivalent according to the
+ /// Unicode database [1]. The additional [`SpecialCasing.txt`] is not yet
+ /// considered here, but the iterator returned will soon support this form
+ /// of case folding.
+ ///
+ /// A full reference can be found here [2].
+ ///
+ /// # Return value
+ ///
+ /// Returns an iterator which yields the characters corresponding to the
+ /// uppercase equivalent of the character. If no conversion is possible then
+ /// the input character is returned.
+ ///
+ /// [1]: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
+ ///
+ /// [`SpecialCasing`.txt`]: ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt
+ ///
+ /// [2]: http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf#G33992
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn to_uppercase(self) -> ToUppercase;
+
+ /// Returns this character's displayed width in columns, or `None` if it is a
+ /// control character other than `'\x00'`.
+ ///
+ /// `is_cjk` determines behavior for characters in the Ambiguous category:
+ /// if `is_cjk` is `true`, these are 2 columns wide; otherwise, they are 1.
+ /// In CJK contexts, `is_cjk` should be `true`, else it should be `false`.
+ /// [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/)
+ /// recommends that these characters be treated as 1 column (i.e.,
+ /// `is_cjk` = `false`) if the context cannot be reliably determined.
+ #[unstable(feature = "unicode",
+ reason = "needs expert opinion. is_cjk flag stands out as ugly")]
+ fn width(self, is_cjk: bool) -> Option<usize>;
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl CharExt for char {
+ fn is_digit(self, radix: u32) -> bool { C::is_digit(self, radix) }
+ fn to_digit(self, radix: u32) -> Option<u32> { C::to_digit(self, radix) }
+ fn escape_unicode(self) -> EscapeUnicode { C::escape_unicode(self) }
+ fn escape_default(self) -> EscapeDefault { C::escape_default(self) }
+ fn len_utf8(self) -> usize { C::len_utf8(self) }
+ fn len_utf16(self) -> usize { C::len_utf16(self) }
+ fn encode_utf8(self, dst: &mut [u8]) -> Option<usize> { C::encode_utf8(self, dst) }
+ fn encode_utf16(self, dst: &mut [u16]) -> Option<usize> { C::encode_utf16(self, dst) }
+
+ fn is_alphabetic(self) -> bool {
+ match self {
+ 'a' ... 'z' | 'A' ... 'Z' => true,
+ c if c > '\x7f' => derived_property::Alphabetic(c),
+ _ => false
+ }
+ }
+
+ fn is_xid_start(self) -> bool { derived_property::XID_Start(self) }
+
+ fn is_xid_continue(self) -> bool { derived_property::XID_Continue(self) }
+
+ fn is_lowercase(self) -> bool {
+ match self {
+ 'a' ... 'z' => true,
+ c if c > '\x7f' => derived_property::Lowercase(c),
+ _ => false
+ }
+ }
+
+ fn is_uppercase(self) -> bool {
+ match self {
+ 'A' ... 'Z' => true,
+ c if c > '\x7f' => derived_property::Uppercase(c),
+ _ => false
+ }
+ }
+
+ fn is_whitespace(self) -> bool {
+ match self {
+ ' ' | '\x09' ... '\x0d' => true,
+ c if c > '\x7f' => property::White_Space(c),
+ _ => false
+ }
+ }
+
+ fn is_alphanumeric(self) -> bool {
+ self.is_alphabetic() || self.is_numeric()
+ }
+
+ fn is_control(self) -> bool { general_category::Cc(self) }
+
+ fn is_numeric(self) -> bool {
+ match self {
+ '0' ... '9' => true,
+ c if c > '\x7f' => general_category::N(c),
+ _ => false
+ }
+ }
+
+ fn to_lowercase(self) -> ToLowercase {
+ ToLowercase(Some(conversions::to_lower(self)))
+ }
+
+ fn to_uppercase(self) -> ToUppercase {
+ ToUppercase(Some(conversions::to_upper(self)))
+ }
+
+ fn width(self, is_cjk: bool) -> Option<usize> { charwidth::width(self, is_cjk) }
+}
+
+/// An iterator over the lowercase mapping of a given character, returned from
+/// the `lowercase` method on characters.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct ToLowercase(Option<char>);
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Iterator for ToLowercase {
+ type Item = char;
+ fn next(&mut self) -> Option<char> { self.0.take() }
+}
+
+/// An iterator over the uppercase mapping of a given character, returned from
+/// the `uppercase` method on characters.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct ToUppercase(Option<char>);
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Iterator for ToUppercase {
+ type Item = char;
+ fn next(&mut self) -> Option<char> { self.0.take() }
+}
mod normalize;
mod tables;
-mod u_char;
mod u_str;
-
-// re-export char so that std et al see it correctly
-/// Character manipulation (`char` type, Unicode Scalar Value)
-///
-/// This module provides the `CharExt` trait, as well as its
-/// implementation for the primitive `char` type, in order to allow
-/// basic character manipulation.
-///
-/// A `char` actually represents a
-/// *[Unicode Scalar Value](http://www.unicode.org/glossary/#unicode_scalar_value)*,
-/// as it can contain any Unicode code point except high-surrogate and
-/// low-surrogate code points.
-///
-/// As such, only values in the ranges \[0x0,0xD7FF\] and \[0xE000,0x10FFFF\]
-/// (inclusive) are allowed. A `char` can always be safely cast to a `u32`;
-/// however the converse is not always true due to the above range limits
-/// and, as such, should be performed via the `from_u32` function.
-#[stable(feature = "rust1", since = "1.0.0")]
-#[doc(primitive = "char")]
-pub mod char {
- pub use core::char::{MAX, from_u32, from_digit};
-
- pub use normalize::{decompose_canonical, decompose_compatible, compose};
-
- pub use tables::normalization::canonical_combining_class;
- pub use tables::UNICODE_VERSION;
-
- pub use u_char::CharExt;
-}
+pub mod char;
pub mod str {
pub use u_str::{UnicodeStr, Words, Graphemes, GraphemeIndices};
+++ /dev/null
-// Copyright 2012-2014 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.
-
-//! Unicode-intensive `char` methods along with the `core` methods.
-//!
-//! These methods implement functionality for `char` that requires knowledge of
-//! Unicode definitions, including normalization, categorization, and display information.
-
-use core::char;
-use core::char::CharExt as C;
-use core::option::Option;
-use tables::{derived_property, property, general_category, conversions, charwidth};
-
-/// Functionality for manipulating `char`.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub trait CharExt {
- /// Checks if a `char` parses as a numeric digit in the given radix.
- ///
- /// Compared to `is_numeric()`, this function only recognizes the characters
- /// `0-9`, `a-z` and `A-Z`.
- ///
- /// # Return value
- ///
- /// Returns `true` if `c` is a valid digit under `radix`, and `false`
- /// otherwise.
- ///
- /// # Panics
- ///
- /// Panics if given a radix > 36.
- #[unstable(feature = "unicode",
- reason = "pending integer conventions")]
- fn is_digit(self, radix: u32) -> bool;
-
- /// Converts a character to the corresponding digit.
- ///
- /// # Return value
- ///
- /// If `c` is between '0' and '9', the corresponding value between 0 and
- /// 9. If `c` is 'a' or 'A', 10. If `c` is 'b' or 'B', 11, etc. Returns
- /// none if the character does not refer to a digit in the given radix.
- ///
- /// # Panics
- ///
- /// Panics if given a radix outside the range [0..36].
- #[unstable(feature = "unicode",
- reason = "pending integer conventions")]
- fn to_digit(self, radix: u32) -> Option<u32>;
-
- /// Returns an iterator that yields the hexadecimal Unicode escape
- /// of a character, as `char`s.
- ///
- /// All characters are escaped with Rust syntax of the form `\\u{NNNN}`
- /// where `NNNN` is the shortest hexadecimal representation of the code
- /// point.
- #[stable(feature = "rust1", since = "1.0.0")]
- fn escape_unicode(self) -> char::EscapeUnicode;
-
- /// Returns an iterator that yields the 'default' ASCII and
- /// C++11-like literal escape of a character, as `char`s.
- ///
- /// The default is chosen with a bias toward producing literals that are
- /// legal in a variety of languages, including C++11 and similar C-family
- /// languages. The exact rules are:
- ///
- /// * Tab, CR and LF are escaped as '\t', '\r' and '\n' respectively.
- /// * Single-quote, double-quote and backslash chars are backslash-
- /// escaped.
- /// * Any other chars in the range [0x20,0x7e] are not escaped.
- /// * Any other chars are given hex Unicode escapes; see `escape_unicode`.
- #[stable(feature = "rust1", since = "1.0.0")]
- fn escape_default(self) -> char::EscapeDefault;
-
- /// Returns the amount of bytes this character would need if encoded in
- /// UTF-8.
- #[stable(feature = "rust1", since = "1.0.0")]
- fn len_utf8(self) -> usize;
-
- /// Returns the amount of bytes this character would need if encoded in
- /// UTF-16.
- #[stable(feature = "rust1", since = "1.0.0")]
- fn len_utf16(self) -> usize;
-
- /// Encodes this character as UTF-8 into the provided byte buffer,
- /// and then returns the number of bytes written.
- ///
- /// If the buffer is not large enough, nothing will be written into it
- /// and a `None` will be returned.
- #[unstable(feature = "unicode",
- reason = "pending decision about Iterator/Writer/Reader")]
- fn encode_utf8(self, dst: &mut [u8]) -> Option<usize>;
-
- /// Encodes this character as UTF-16 into the provided `u16` buffer,
- /// and then returns the number of `u16`s written.
- ///
- /// If the buffer is not large enough, nothing will be written into it
- /// and a `None` will be returned.
- #[unstable(feature = "unicode",
- reason = "pending decision about Iterator/Writer/Reader")]
- fn encode_utf16(self, dst: &mut [u16]) -> Option<usize>;
-
- /// Returns whether the specified character is considered a Unicode
- /// alphabetic code point.
- #[stable(feature = "rust1", since = "1.0.0")]
- fn is_alphabetic(self) -> bool;
-
- /// Returns whether the specified character satisfies the 'XID_Start'
- /// Unicode property.
- ///
- /// 'XID_Start' is a Unicode Derived Property specified in
- /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
- /// mostly similar to ID_Start but modified for closure under NFKx.
- #[unstable(feature = "unicode",
- reason = "mainly needed for compiler internals")]
- fn is_xid_start(self) -> bool;
-
- /// Returns whether the specified `char` satisfies the 'XID_Continue'
- /// Unicode property.
- ///
- /// 'XID_Continue' is a Unicode Derived Property specified in
- /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
- /// mostly similar to 'ID_Continue' but modified for closure under NFKx.
- #[unstable(feature = "unicode",
- reason = "mainly needed for compiler internals")]
- fn is_xid_continue(self) -> bool;
-
- /// Indicates whether a character is in lowercase.
- ///
- /// This is defined according to the terms of the Unicode Derived Core
- /// Property `Lowercase`.
- #[stable(feature = "rust1", since = "1.0.0")]
- fn is_lowercase(self) -> bool;
-
- /// Indicates whether a character is in uppercase.
- ///
- /// This is defined according to the terms of the Unicode Derived Core
- /// Property `Uppercase`.
- #[stable(feature = "rust1", since = "1.0.0")]
- fn is_uppercase(self) -> bool;
-
- /// Indicates whether a character is whitespace.
- ///
- /// Whitespace is defined in terms of the Unicode Property `White_Space`.
- #[stable(feature = "rust1", since = "1.0.0")]
- fn is_whitespace(self) -> bool;
-
- /// Indicates whether a character is alphanumeric.
- ///
- /// Alphanumericness is defined in terms of the Unicode General Categories
- /// 'Nd', 'Nl', 'No' and the Derived Core Property 'Alphabetic'.
- #[stable(feature = "rust1", since = "1.0.0")]
- fn is_alphanumeric(self) -> bool;
-
- /// Indicates whether a character is a control code point.
- ///
- /// Control code points are defined in terms of the Unicode General
- /// Category `Cc`.
- #[stable(feature = "rust1", since = "1.0.0")]
- fn is_control(self) -> bool;
-
- /// Indicates whether the character is numeric (Nd, Nl, or No).
- #[stable(feature = "rust1", since = "1.0.0")]
- fn is_numeric(self) -> bool;
-
- /// Converts a character to its lowercase equivalent.
- ///
- /// The case-folding performed is the common or simple mapping. See
- /// `to_uppercase()` for references and more information.
- ///
- /// # Return value
- ///
- /// Returns the lowercase equivalent of the character, or the character
- /// itself if no conversion is possible.
- #[unstable(feature = "unicode",
- reason = "pending case transformation decisions")]
- fn to_lowercase(self) -> char;
-
- /// Converts a character to its uppercase equivalent.
- ///
- /// The case-folding performed is the common or simple mapping: it maps
- /// one Unicode codepoint (one character in Rust) to its uppercase
- /// equivalent according to the Unicode database [1]. The additional
- /// [`SpecialCasing.txt`] is not considered here, as it expands to multiple
- /// codepoints in some cases.
- ///
- /// A full reference can be found here [2].
- ///
- /// # Return value
- ///
- /// Returns the uppercase equivalent of the character, or the character
- /// itself if no conversion was made.
- ///
- /// [1]: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
- ///
- /// [`SpecialCasing`.txt`]: ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt
- ///
- /// [2]: http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf#G33992
- #[unstable(feature = "unicode",
- reason = "pending case transformation decisions")]
- fn to_uppercase(self) -> char;
-
- /// Returns this character's displayed width in columns, or `None` if it is a
- /// control character other than `'\x00'`.
- ///
- /// `is_cjk` determines behavior for characters in the Ambiguous category:
- /// if `is_cjk` is `true`, these are 2 columns wide; otherwise, they are 1.
- /// In CJK contexts, `is_cjk` should be `true`, else it should be `false`.
- /// [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/)
- /// recommends that these characters be treated as 1 column (i.e.,
- /// `is_cjk` = `false`) if the context cannot be reliably determined.
- #[unstable(feature = "unicode",
- reason = "needs expert opinion. is_cjk flag stands out as ugly")]
- fn width(self, is_cjk: bool) -> Option<usize>;
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl CharExt for char {
- #[unstable(feature = "unicode",
- reason = "pending integer conventions")]
- fn is_digit(self, radix: u32) -> bool { C::is_digit(self, radix) }
- #[unstable(feature = "unicode",
- reason = "pending integer conventions")]
- fn to_digit(self, radix: u32) -> Option<u32> { C::to_digit(self, radix) }
- #[stable(feature = "rust1", since = "1.0.0")]
- fn escape_unicode(self) -> char::EscapeUnicode { C::escape_unicode(self) }
- #[stable(feature = "rust1", since = "1.0.0")]
- fn escape_default(self) -> char::EscapeDefault { C::escape_default(self) }
- #[stable(feature = "rust1", since = "1.0.0")]
- fn len_utf8(self) -> usize { C::len_utf8(self) }
- #[stable(feature = "rust1", since = "1.0.0")]
- fn len_utf16(self) -> usize { C::len_utf16(self) }
- #[unstable(feature = "unicode",
- reason = "pending decision about Iterator/Writer/Reader")]
- fn encode_utf8(self, dst: &mut [u8]) -> Option<usize> { C::encode_utf8(self, dst) }
- #[unstable(feature = "unicode",
- reason = "pending decision about Iterator/Writer/Reader")]
- fn encode_utf16(self, dst: &mut [u16]) -> Option<usize> { C::encode_utf16(self, dst) }
-
- #[stable(feature = "rust1", since = "1.0.0")]
- fn is_alphabetic(self) -> bool {
- match self {
- 'a' ... 'z' | 'A' ... 'Z' => true,
- c if c > '\x7f' => derived_property::Alphabetic(c),
- _ => false
- }
- }
-
- #[unstable(feature = "unicode",
- reason = "mainly needed for compiler internals")]
- fn is_xid_start(self) -> bool { derived_property::XID_Start(self) }
-
- #[unstable(feature = "unicode",
- reason = "mainly needed for compiler internals")]
- fn is_xid_continue(self) -> bool { derived_property::XID_Continue(self) }
-
- #[stable(feature = "rust1", since = "1.0.0")]
- fn is_lowercase(self) -> bool {
- match self {
- 'a' ... 'z' => true,
- c if c > '\x7f' => derived_property::Lowercase(c),
- _ => false
- }
- }
-
- #[stable(feature = "rust1", since = "1.0.0")]
- fn is_uppercase(self) -> bool {
- match self {
- 'A' ... 'Z' => true,
- c if c > '\x7f' => derived_property::Uppercase(c),
- _ => false
- }
- }
-
- #[stable(feature = "rust1", since = "1.0.0")]
- fn is_whitespace(self) -> bool {
- match self {
- ' ' | '\x09' ... '\x0d' => true,
- c if c > '\x7f' => property::White_Space(c),
- _ => false
- }
- }
-
- #[stable(feature = "rust1", since = "1.0.0")]
- fn is_alphanumeric(self) -> bool {
- self.is_alphabetic() || self.is_numeric()
- }
-
- #[stable(feature = "rust1", since = "1.0.0")]
- fn is_control(self) -> bool { general_category::Cc(self) }
-
- #[stable(feature = "rust1", since = "1.0.0")]
- fn is_numeric(self) -> bool {
- match self {
- '0' ... '9' => true,
- c if c > '\x7f' => general_category::N(c),
- _ => false
- }
- }
-
- #[unstable(feature = "unicode",
- reason = "pending case transformation decisions")]
- fn to_lowercase(self) -> char { conversions::to_lower(self) }
-
- #[unstable(feature = "unicode",
- reason = "pending case transformation decisions")]
- fn to_uppercase(self) -> char { conversions::to_upper(self) }
-
- #[unstable(feature = "unicode",
- reason = "needs expert opinion. is_cjk flag stands out as ugly")]
- fn width(self, is_cjk: bool) -> Option<usize> { charwidth::width(self, is_cjk) }
-}
use core::slice;
use core::str::Split;
-use u_char::CharExt as UCharExt; // conflicts with core::prelude::CharExt
+use char::CharExt as UCharExt; // conflicts with core::prelude::CharExt
use tables::grapheme::GraphemeCat;
/// An iterator over the words of a string, separated by a sequence of whitespace
+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.
+
+// Test that `quote`-related macro are gated by `quote` feature gate.
+
+// (To sanity-check the code, uncomment this.)
+// #![feature(quote)]
+
+// FIXME the error message that is current emitted seems pretty bad.
+
+#![feature(rustc_private)]
+#![allow(dead_code, unused_imports, unused_variables)]
+
+#[macro_use]
+extern crate syntax;
+
+use syntax::ast;
+use syntax::codemap::Span;
+use syntax::parse;
+
+struct ParseSess;
+
+impl ParseSess {
+ fn cfg(&self) -> ast::CrateConfig { loop { } }
+ fn parse_sess<'a>(&'a self) -> &'a parse::ParseSess { loop { } }
+ fn call_site(&self) -> Span { loop { } }
+ fn ident_of(&self, st: &str) -> ast::Ident { loop { } }
+ fn name_of(&self, st: &str) -> ast::Name { loop { } }
+}
+
+pub fn main() {
+ let ecx = &ParseSess;
+ let x = quote_tokens!(ecx, 3); //~ ERROR macro undefined: 'quote_tokens!'
+ let x = quote_expr!(ecx, 3); //~ ERROR macro undefined: 'quote_expr!'
+ let x = quote_ty!(ecx, 3); //~ ERROR macro undefined: 'quote_ty!'
+ let x = quote_method!(ecx, 3); //~ ERROR macro undefined: 'quote_method!'
+ let x = quote_item!(ecx, 3); //~ ERROR macro undefined: 'quote_item!'
+ let x = quote_pat!(ecx, 3); //~ ERROR macro undefined: 'quote_pat!'
+ let x = quote_arm!(ecx, 3); //~ ERROR macro undefined: 'quote_arm!'
+ let x = quote_stmt!(ecx, 3); //~ ERROR macro undefined: 'quote_stmt!'
+ let x = quote_matcher!(ecx, 3); //~ ERROR macro undefined: 'quote_matcher!'
+ let x = quote_attr!(ecx, 3); //~ ERROR macro undefined: 'quote_attr!'
+}
+++ /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.
+
+// Test that `#[link_args]` attribute is gated by `link_args`
+// feature gate.
+
+#[link_args = "aFdEfSeVEEE"]
+extern {}
+//~^ ERROR the `link_args` attribute is not portable across platforms
+//~| HELP add #![feature(link_args)] to the crate attributes to enable
+
+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.
+
+extern {
+ #[link_name = "llvm.sqrt.f32"]
+ fn sqrt(x: f32) -> f32;
+ //~^ ERROR linking to LLVM intrinsics is experimental
+ //~| HELP add #![feature(link_llvm_intrinsics)] to the crate attributes
+}
+
+fn main(){
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// Test that `#[plugin_registrar]` attribute is gated by `plugin_registrar`
+// feature gate.
+
// the registration function isn't typechecked yet
#[plugin_registrar]
-pub fn registrar() {} //~ ERROR compiler plugins are experimental
-
+pub fn registrar() {}
+//~^ ERROR compiler plugins are experimental
+//~| HELP add #![feature(plugin_registrar)] to the crate attributes to enable
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.
+
+// Test that `#[thread_local]` attribute is gated by `thread_local`
+// feature gate.
+//
+// (Note that the `thread_local!` macro is explicitly *not* gated; it
+// is given permission to expand into this unstable attribute even
+// when the surrounding context does not have permission to use it.)
+
+#[thread_local] //~ ERROR `#[thread_local]` is an experimental feature
+static FOO: i32 = 3;
+
+pub fn main() {
+ FOO.with(|x| {
+ println!("x: {}", x);
+ });
+}
--- /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.
+
+// Test that `#[unsafe_destructor]` attribute is gated by `unsafe_destructor`
+// feature gate.
+
+struct D<'a>(&'a u32);
+
+#[unsafe_destructor]
+impl<'a> Drop for D<'a> {
+ //~^ ERROR `#[unsafe_destructor]` allows too many unsafe patterns
+ fn drop(&mut self) { }
+}
+//~^ HELP: add #![feature(unsafe_destructor)] to the crate attributes to enable
+
+pub 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)]