Merge remote-tracking branch 'rust-lang/master'
Conflicts: src/libcore/cmp.rs src/libcore/fmt/mod.rs src/libcore/iter.rs src/libcore/marker.rs src/libcore/num/f32.rs src/libcore/num/f64.rs src/libcore/result.rs src/libcore/str/mod.rs src/librustc/lint/builtin.rs src/librustc/lint/context.rs src/libstd/sync/mpsc/mod.rs src/libstd/sync/poison.rs
This commit is contained in:
commit
d179ba3b8e
88 changed files with 5485 additions and 559 deletions
7
configure
vendored
7
configure
vendored
|
@ -28,8 +28,8 @@ need_ok() {
|
||||||
|
|
||||||
need_cmd() {
|
need_cmd() {
|
||||||
if command -v $1 >/dev/null 2>&1
|
if command -v $1 >/dev/null 2>&1
|
||||||
then msg "found $1"
|
then msg "found program $1"
|
||||||
else err "need $1"
|
else err "need program $1"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,6 +340,7 @@ need_cmd date
|
||||||
need_cmd tr
|
need_cmd tr
|
||||||
need_cmd sed
|
need_cmd sed
|
||||||
need_cmd file
|
need_cmd file
|
||||||
|
need_cmd make
|
||||||
|
|
||||||
msg "inspecting environment"
|
msg "inspecting environment"
|
||||||
|
|
||||||
|
@ -645,6 +646,8 @@ probe CFG_ISCC iscc
|
||||||
probe CFG_JAVAC javac
|
probe CFG_JAVAC javac
|
||||||
probe CFG_ANTLR4 antlr4
|
probe CFG_ANTLR4 antlr4
|
||||||
probe CFG_GRUN grun
|
probe CFG_GRUN grun
|
||||||
|
probe CFG_FLEX flex
|
||||||
|
probe CFG_BISON bison
|
||||||
probe CFG_PANDOC pandoc
|
probe CFG_PANDOC pandoc
|
||||||
probe CFG_PDFLATEX pdflatex
|
probe CFG_PDFLATEX pdflatex
|
||||||
probe CFG_XELATEX xelatex
|
probe CFG_XELATEX xelatex
|
||||||
|
|
|
@ -14,6 +14,11 @@ B = $(CFG_BUILD_DIR)/$(CFG_BUILD)/stage2/
|
||||||
L = $(B)lib/rustlib/$(CFG_BUILD)/lib
|
L = $(B)lib/rustlib/$(CFG_BUILD)/lib
|
||||||
LD = $(CFG_BUILD)/stage2/lib/rustlib/$(CFG_BUILD)/lib/
|
LD = $(CFG_BUILD)/stage2/lib/rustlib/$(CFG_BUILD)/lib/
|
||||||
RUSTC = $(STAGE2_T_$(CFG_BUILD)_H_$(CFG_BUILD))
|
RUSTC = $(STAGE2_T_$(CFG_BUILD)_H_$(CFG_BUILD))
|
||||||
|
ifeq ($(CFG_OSTYPE),apple-darwin)
|
||||||
|
FLEX_LDFLAGS=-ll
|
||||||
|
else
|
||||||
|
FLEX_LDFLAGS=-lfl
|
||||||
|
endif
|
||||||
|
|
||||||
# Run the reference lexer against libsyntax and compare the tokens and spans.
|
# Run the reference lexer against libsyntax and compare the tokens and spans.
|
||||||
# If "// ignore-lexer-test" is present in the file, it will be ignored.
|
# If "// ignore-lexer-test" is present in the file, it will be ignored.
|
||||||
|
@ -67,3 +72,46 @@ $(info cfg: javac not available, skipping lexer test...)
|
||||||
check-lexer:
|
check-lexer:
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
$(BG)lex.yy.c: $(SG)lexer.l $(BG)
|
||||||
|
@$(call E, flex: $@)
|
||||||
|
$(Q)$(CFG_FLEX) -o $@ $<
|
||||||
|
|
||||||
|
$(BG)lexer-lalr.o: $(BG)lex.yy.c $(BG)parser-lalr.tab.h
|
||||||
|
@$(call E, cc: $@)
|
||||||
|
$(Q)$(CFG_CC) -include $(BG)parser-lalr.tab.h -c -o $@ $<
|
||||||
|
|
||||||
|
$(BG)parser-lalr.tab.c $(BG)parser-lalr.tab.h: $(SG)parser-lalr.y
|
||||||
|
@$(call E, bison: $@)
|
||||||
|
$(Q)$(CFG_BISON) $< --output=$(BG)parser-lalr.tab.c --defines=$(BG)parser-lalr.tab.h \
|
||||||
|
--name-prefix=rs --warnings=error=all
|
||||||
|
|
||||||
|
$(BG)parser-lalr.o: $(BG)parser-lalr.tab.c
|
||||||
|
@$(call E, cc: $@)
|
||||||
|
$(Q)$(CFG_CC) -c -o $@ $<
|
||||||
|
|
||||||
|
$(BG)parser-lalr-main.o: $(SG)parser-lalr-main.c
|
||||||
|
@$(call E, cc: $@)
|
||||||
|
$(Q)$(CFG_CC) -std=c99 -c -o $@ $<
|
||||||
|
|
||||||
|
$(BG)parser-lalr: $(BG)parser-lalr.o $(BG)parser-lalr-main.o $(BG)lexer-lalr.o
|
||||||
|
@$(call E, cc: $@)
|
||||||
|
$(Q)$(CFG_CC) -o $@ $^ $(FLEX_LDFLAGS)
|
||||||
|
|
||||||
|
|
||||||
|
ifdef CFG_FLEX
|
||||||
|
ifdef CFG_BISON
|
||||||
|
check-grammar: $(BG) $(BG)parser-lalr
|
||||||
|
$(info Verifying grammar ...)
|
||||||
|
$(SG)testparser.py -p $(BG)parser-lalr -s $(S)src
|
||||||
|
|
||||||
|
else
|
||||||
|
$(info cfg: bison not available, skipping parser test...)
|
||||||
|
check-grammar:
|
||||||
|
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
$(info cfg: flex not available, skipping parser test...)
|
||||||
|
check-grammar:
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
|
@ -30,8 +30,8 @@ CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)
|
||||||
CFG_DISABLE_UNSTABLE_FEATURES=1
|
CFG_DISABLE_UNSTABLE_FEATURES=1
|
||||||
endif
|
endif
|
||||||
ifeq ($(CFG_RELEASE_CHANNEL),beta)
|
ifeq ($(CFG_RELEASE_CHANNEL),beta)
|
||||||
CFG_RELEASE=$(CFG_RELEASE_NUM)-beta(CFG_PRERELEASE_VERSION)
|
CFG_RELEASE=$(CFG_RELEASE_NUM)-beta$(CFG_PRERELEASE_VERSION)
|
||||||
CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)-beta(CFG_PRERELEASE_VERSION)
|
CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)-beta$(CFG_PRERELEASE_VERSION)
|
||||||
CFG_DISABLE_UNSTABLE_FEATURES=1
|
CFG_DISABLE_UNSTABLE_FEATURES=1
|
||||||
endif
|
endif
|
||||||
ifeq ($(CFG_RELEASE_CHANNEL),nightly)
|
ifeq ($(CFG_RELEASE_CHANNEL),nightly)
|
||||||
|
|
|
@ -12,6 +12,20 @@ pub use self::Mode::*;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
#[cfg(stage0)] // NOTE: remove impl after snapshot
|
||||||
|
#[derive(Clone, PartialEq, Show)]
|
||||||
|
pub enum Mode {
|
||||||
|
CompileFail,
|
||||||
|
RunFail,
|
||||||
|
RunPass,
|
||||||
|
RunPassValgrind,
|
||||||
|
Pretty,
|
||||||
|
DebugInfoGdb,
|
||||||
|
DebugInfoLldb,
|
||||||
|
Codegen
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(stage0))] // NOTE: remove cfg after snapshot
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
pub enum Mode {
|
pub enum Mode {
|
||||||
CompileFail,
|
CompileFail,
|
||||||
|
@ -24,6 +38,7 @@ pub enum Mode {
|
||||||
Codegen
|
Codegen
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Copy for Mode {}
|
impl Copy for Mode {}
|
||||||
|
|
||||||
impl FromStr for Mode {
|
impl FromStr for Mode {
|
||||||
|
|
|
@ -2291,136 +2291,7 @@ The name `str_eq` has a special meaning to the Rust compiler, and the presence
|
||||||
of this definition means that it will use this definition when generating calls
|
of this definition means that it will use this definition when generating calls
|
||||||
to the string equality function.
|
to the string equality function.
|
||||||
|
|
||||||
A complete list of the built-in language items follows:
|
A complete list of the built-in language items will be added in the future.
|
||||||
|
|
||||||
#### Built-in Traits
|
|
||||||
|
|
||||||
* `copy`
|
|
||||||
: Types that do not move ownership when used by-value.
|
|
||||||
* `drop`
|
|
||||||
: Have destructors.
|
|
||||||
* `send`
|
|
||||||
: Able to be sent across thread boundaries.
|
|
||||||
* `sized`
|
|
||||||
: Has a size known at compile time.
|
|
||||||
* `sync`
|
|
||||||
: Able to be safely shared between threads when aliased.
|
|
||||||
|
|
||||||
#### Operators
|
|
||||||
|
|
||||||
These language items are traits:
|
|
||||||
|
|
||||||
* `add`
|
|
||||||
: Elements can be added (for example, integers and floats).
|
|
||||||
* `sub`
|
|
||||||
: Elements can be subtracted.
|
|
||||||
* `mul`
|
|
||||||
: Elements can be multiplied.
|
|
||||||
* `div`
|
|
||||||
: Elements have a division operation.
|
|
||||||
* `rem`
|
|
||||||
: Elements have a remainder operation.
|
|
||||||
* `neg`
|
|
||||||
: Elements can be negated arithmetically.
|
|
||||||
* `not`
|
|
||||||
: Elements can be negated logically.
|
|
||||||
* `bitxor`
|
|
||||||
: Elements have an exclusive-or operation.
|
|
||||||
* `bitand`
|
|
||||||
: Elements have a bitwise `and` operation.
|
|
||||||
* `bitor`
|
|
||||||
: Elements have a bitwise `or` operation.
|
|
||||||
* `shl`
|
|
||||||
: Elements have a left shift operation.
|
|
||||||
* `shr`
|
|
||||||
: Elements have a right shift operation.
|
|
||||||
* `index`
|
|
||||||
: Elements can be indexed.
|
|
||||||
* `index_mut`
|
|
||||||
: ___Needs filling in___
|
|
||||||
* `eq`
|
|
||||||
: Elements can be compared for equality.
|
|
||||||
* `ord`
|
|
||||||
: Elements have a partial ordering.
|
|
||||||
* `deref`
|
|
||||||
: `*` can be applied, yielding a reference to another type.
|
|
||||||
* `deref_mut`
|
|
||||||
: `*` can be applied, yielding a mutable reference to another type.
|
|
||||||
|
|
||||||
These are functions:
|
|
||||||
|
|
||||||
* `fn`
|
|
||||||
: ___Needs filling in___
|
|
||||||
* `fn_mut`
|
|
||||||
: ___Needs filling in___
|
|
||||||
* `fn_once`
|
|
||||||
: ___Needs filling in___
|
|
||||||
* `str_eq`
|
|
||||||
: Compare two strings (`&str`) for equality.
|
|
||||||
* `strdup_uniq`
|
|
||||||
: Return a new unique string
|
|
||||||
containing a copy of the contents of a unique string.
|
|
||||||
|
|
||||||
#### Types
|
|
||||||
|
|
||||||
* `type_id`
|
|
||||||
: The type returned by the `type_id` intrinsic.
|
|
||||||
* `unsafe`
|
|
||||||
: A type whose contents can be mutated through an immutable reference.
|
|
||||||
|
|
||||||
#### Marker types
|
|
||||||
|
|
||||||
These types help drive the compiler's analysis
|
|
||||||
|
|
||||||
* `begin_unwind`
|
|
||||||
: ___Needs filling in___
|
|
||||||
* `no_copy_bound`
|
|
||||||
: This type does not implement "copy", even if eligible.
|
|
||||||
* `eh_personality`
|
|
||||||
: ___Needs filling in___
|
|
||||||
* `exchange_free`
|
|
||||||
: Free memory that was allocated on the exchange heap.
|
|
||||||
* `exchange_malloc`
|
|
||||||
: Allocate memory on the exchange heap.
|
|
||||||
* `closure_exchange_malloc`
|
|
||||||
: ___Needs filling in___
|
|
||||||
* `panic`
|
|
||||||
: Abort the program with an error.
|
|
||||||
* `fail_bounds_check`
|
|
||||||
: Abort the program with a bounds check error.
|
|
||||||
* `free`
|
|
||||||
: Free memory that was allocated on the managed heap.
|
|
||||||
* `gc`
|
|
||||||
: ___Needs filling in___
|
|
||||||
* `exchange_heap`
|
|
||||||
: ___Needs filling in___
|
|
||||||
* `iterator`
|
|
||||||
: ___Needs filling in___
|
|
||||||
* `contravariant_lifetime`
|
|
||||||
: The lifetime parameter should be considered contravariant.
|
|
||||||
* `covariant_lifetime`
|
|
||||||
: The lifetime parameter should be considered covariant.
|
|
||||||
* `invariant_lifetime`
|
|
||||||
: The lifetime parameter should be considered invariant.
|
|
||||||
* `malloc`
|
|
||||||
: Allocate memory on the managed heap.
|
|
||||||
* `owned_box`
|
|
||||||
: ___Needs filling in___
|
|
||||||
* `stack_exhausted`
|
|
||||||
: ___Needs filling in___
|
|
||||||
* `start`
|
|
||||||
: ___Needs filling in___
|
|
||||||
* `contravariant_type`
|
|
||||||
: The type parameter should be considered contravariant.
|
|
||||||
* `covariant_type`
|
|
||||||
: The type parameter should be considered covariant.
|
|
||||||
* `invariant_type`
|
|
||||||
: The type parameter should be considered invariant.
|
|
||||||
* `ty_desc`
|
|
||||||
: ___Needs filling in___
|
|
||||||
|
|
||||||
> **Note:** This list is likely to become out of date. We should auto-generate
|
|
||||||
> it from `librustc/middle/lang_items.rs`.
|
|
||||||
|
|
||||||
### Inline attributes
|
### Inline attributes
|
||||||
|
|
||||||
|
@ -2581,9 +2452,7 @@ The currently implemented features of the reference compiler are:
|
||||||
declare a `static` as being unique per-thread leveraging
|
declare a `static` as being unique per-thread leveraging
|
||||||
LLVM's implementation which works in concert with the kernel
|
LLVM's implementation which works in concert with the kernel
|
||||||
loader and dynamic linker. This is not necessarily available
|
loader and dynamic linker. This is not necessarily available
|
||||||
on all platforms, and usage of it is discouraged (rust
|
on all platforms, and usage of it is discouraged.
|
||||||
focuses more on thread-local data instead of thread-local
|
|
||||||
data).
|
|
||||||
|
|
||||||
* `trace_macros` - Allows use of the `trace_macros` macro, which is a nasty
|
* `trace_macros` - Allows use of the `trace_macros` macro, which is a nasty
|
||||||
hack that will certainly be removed.
|
hack that will certainly be removed.
|
||||||
|
|
|
@ -83,7 +83,6 @@ If not, there are a number of places where you can get help. The easiest is
|
||||||
you can access through
|
you can access through
|
||||||
[Mibbit](http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust). Click
|
[Mibbit](http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust). Click
|
||||||
that link, and you'll be chatting with other Rustaceans (a silly nickname we
|
that link, and you'll be chatting with other Rustaceans (a silly nickname we
|
||||||
call ourselves), and we can help you out. Other great resources include [our
|
call ourselves), and we can help you out. Other great resources include [the
|
||||||
forum](http://discuss.rust-lang.org/), [the /r/rust
|
/r/rust subreddit](http://www.reddit.com/r/rust), and [Stack
|
||||||
subreddit](http://www.reddit.com/r/rust), and [Stack
|
|
||||||
Overflow](http://stackoverflow.com/questions/tagged/rust).
|
Overflow](http://stackoverflow.com/questions/tagged/rust).
|
||||||
|
|
|
@ -18,6 +18,8 @@ x.foo().bar().baz();
|
||||||
Luckily, as you may have guessed with the leading question, you can! Rust provides
|
Luckily, as you may have guessed with the leading question, you can! Rust provides
|
||||||
the ability to use this *method call syntax* via the `impl` keyword.
|
the ability to use this *method call syntax* via the `impl` keyword.
|
||||||
|
|
||||||
|
## Method calls
|
||||||
|
|
||||||
Here's how it works:
|
Here's how it works:
|
||||||
|
|
||||||
```{rust}
|
```{rust}
|
||||||
|
@ -56,11 +58,56 @@ other parameter. Because we know it's a `Circle`, we can access the `radius`
|
||||||
just like we would with any other struct. An import of π and some
|
just like we would with any other struct. An import of π and some
|
||||||
multiplications later, and we have our area.
|
multiplications later, and we have our area.
|
||||||
|
|
||||||
|
## Chaining method calls
|
||||||
|
|
||||||
|
So, now we know how to call a method, such as `foo.bar()`. But what about our
|
||||||
|
original example, `foo.bar().baz()`? This is called 'method chaining', and we
|
||||||
|
can do it by returning `self`.
|
||||||
|
|
||||||
|
```
|
||||||
|
struct Circle {
|
||||||
|
x: f64,
|
||||||
|
y: f64,
|
||||||
|
radius: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Circle {
|
||||||
|
fn area(&self) -> f64 {
|
||||||
|
std::f64::consts::PI * (self.radius * self.radius)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn grow(&self) -> Circle {
|
||||||
|
Circle { x: self.x, y: self.y, radius: (self.radius * 10.0) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let c = Circle { x: 0.0, y: 0.0, radius: 2.0 };
|
||||||
|
println!("{}", c.area());
|
||||||
|
|
||||||
|
let d = c.grow().area();
|
||||||
|
println!("{}", d);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Check the return type:
|
||||||
|
|
||||||
|
```
|
||||||
|
# struct Circle;
|
||||||
|
# impl Circle {
|
||||||
|
fn grow(&self) -> Circle {
|
||||||
|
# Circle } }
|
||||||
|
```
|
||||||
|
|
||||||
|
We just say we're returning a `Circle`. With this, we can grow a new circle
|
||||||
|
that's twice as big as the old one.
|
||||||
|
|
||||||
|
## Static methods
|
||||||
|
|
||||||
You can also define methods that do not take a `self` parameter. Here's a
|
You can also define methods that do not take a `self` parameter. Here's a
|
||||||
pattern that's very common in Rust code:
|
pattern that's very common in Rust code:
|
||||||
|
|
||||||
```{rust}
|
```
|
||||||
# #![allow(non_shorthand_field_patterns)]
|
|
||||||
struct Circle {
|
struct Circle {
|
||||||
x: f64,
|
x: f64,
|
||||||
y: f64,
|
y: f64,
|
||||||
|
@ -86,3 +133,66 @@ This *static method* builds a new `Circle` for us. Note that static methods
|
||||||
are called with the `Struct::method()` syntax, rather than the `ref.method()`
|
are called with the `Struct::method()` syntax, rather than the `ref.method()`
|
||||||
syntax.
|
syntax.
|
||||||
|
|
||||||
|
## Builder Pattern
|
||||||
|
|
||||||
|
Let's say that we want our users to be able to create Circles, but we will
|
||||||
|
allow them to only set the properties they care about. Otherwise, the `x`
|
||||||
|
and `y` attributes will be `0.0`, and the `radius` will be `1.0`. Rust doesn't
|
||||||
|
have method overloading, named arguments, or variable arguments. We employ
|
||||||
|
the builder pattern instead. It looks like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
struct Circle {
|
||||||
|
x: f64,
|
||||||
|
y: f64,
|
||||||
|
radius: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Circle {
|
||||||
|
fn area(&self) -> f64 {
|
||||||
|
std::f64::consts::PI * (self.radius * self.radius)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CircleBuilder {
|
||||||
|
coordinate: f64,
|
||||||
|
radius: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CircleBuilder {
|
||||||
|
fn new() -> CircleBuilder {
|
||||||
|
CircleBuilder { coordinate: 0.0, radius: 0.0, }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn coordinate(&mut self, coordinate: f64) -> &mut CircleBuilder {
|
||||||
|
self.coordinate = coordinate;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn radius(&mut self, radius: f64) -> &mut CircleBuilder {
|
||||||
|
self.radius = radius;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize(&self) -> Circle {
|
||||||
|
Circle { x: self.coordinate, y: self.coordinate, radius: self.radius }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let c = CircleBuilder::new()
|
||||||
|
.coordinate(10.0)
|
||||||
|
.radius(5.0)
|
||||||
|
.finalize();
|
||||||
|
|
||||||
|
|
||||||
|
println!("area: {}", c.area());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
What we've done here is make another struct, `CircleBuilder`. We've defined our
|
||||||
|
builder methods on it. We've also defined our `area()` method on `Circle`. We
|
||||||
|
also made one more method on `CircleBuilder`: `finalize()`. This method creates
|
||||||
|
our final `Circle` from the builder. Now, we've used the type system to enforce
|
||||||
|
our concerns: we can use the methods on `CircleBuilder` to constrain making
|
||||||
|
`Circle`s in any way we choose.
|
||||||
|
|
|
@ -14,11 +14,10 @@
|
||||||
import sys, os, re
|
import sys, os, re
|
||||||
|
|
||||||
src_dir = sys.argv[1]
|
src_dir = sys.argv[1]
|
||||||
|
errcode_map = {}
|
||||||
errcode_map = { }
|
error_re = re.compile("(E\d\d\d\d)")
|
||||||
|
|
||||||
for (dirpath, dirnames, filenames) in os.walk(src_dir):
|
for (dirpath, dirnames, filenames) in os.walk(src_dir):
|
||||||
|
|
||||||
if "src/test" in dirpath or "src/llvm" in dirpath:
|
if "src/test" in dirpath or "src/llvm" in dirpath:
|
||||||
# Short circuit for fast
|
# Short circuit for fast
|
||||||
continue
|
continue
|
||||||
|
@ -28,15 +27,12 @@ for (dirpath, dirnames, filenames) in os.walk(src_dir):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
path = os.path.join(dirpath, filename)
|
path = os.path.join(dirpath, filename)
|
||||||
line_num = 1
|
|
||||||
with open(path, 'r') as f:
|
with open(path, 'r') as f:
|
||||||
for line in f:
|
for line_num, line in enumerate(f, start=1):
|
||||||
|
match = error_re.search(line)
|
||||||
p = re.compile("(E\d\d\d\d)")
|
if match:
|
||||||
m = p.search(line)
|
errcode = match.group(1)
|
||||||
if not m is None:
|
|
||||||
errcode = m.group(1)
|
|
||||||
|
|
||||||
new_record = [(errcode, path, line_num, line)]
|
new_record = [(errcode, path, line_num, line)]
|
||||||
existing = errcode_map.get(errcode)
|
existing = errcode_map.get(errcode)
|
||||||
if existing is not None:
|
if existing is not None:
|
||||||
|
@ -45,26 +41,19 @@ for (dirpath, dirnames, filenames) in os.walk(src_dir):
|
||||||
else:
|
else:
|
||||||
errcode_map[errcode] = new_record
|
errcode_map[errcode] = new_record
|
||||||
|
|
||||||
line_num += 1
|
|
||||||
|
|
||||||
errors = False
|
errors = False
|
||||||
all_errors = []
|
all_errors = []
|
||||||
for errcode in errcode_map:
|
|
||||||
entries = errcode_map[errcode]
|
for errcode, entries in errcode_map.items():
|
||||||
all_errors += [entries[0][0]]
|
all_errors.append(entries[0][0])
|
||||||
if len(entries) > 1:
|
if len(entries) > 1:
|
||||||
print "error: duplicate error code " + errcode
|
print("error: duplicate error code " + errcode)
|
||||||
for entry in entries:
|
for entry in entries:
|
||||||
print entry[1] + ": " + str(entry[2])
|
print("{1}: {2}\n{3}".format(*entry))
|
||||||
print entry[3]
|
|
||||||
errors = True
|
errors = True
|
||||||
|
|
||||||
print str(len(errcode_map)) + " error codes"
|
print("{0} error codes".format(len(errcode_map)))
|
||||||
|
print("highest error code: " + max(all_errors))
|
||||||
all_errors.sort()
|
|
||||||
all_errors.reverse()
|
|
||||||
|
|
||||||
print "highest error code: " + all_errors[0]
|
|
||||||
|
|
||||||
if errors:
|
if errors:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
|
@ -8,29 +8,18 @@
|
||||||
# option. This file may not be copied, modified, or distributed
|
# option. This file may not be copied, modified, or distributed
|
||||||
# except according to those terms.
|
# except according to those terms.
|
||||||
|
|
||||||
license1 = """// Copyright """
|
import re
|
||||||
license2 = """ 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.
|
|
||||||
"""
|
|
||||||
|
|
||||||
license3 = """# Copyright """
|
license_re = re.compile(
|
||||||
license4 = """ The Rust Project Developers. See the COPYRIGHT
|
u"""(#|//) Copyright .* The Rust Project Developers. See the COPYRIGHT
|
||||||
# file at the top-level directory of this distribution and at
|
\\1 file at the top-level directory of this distribution and at
|
||||||
# http://rust-lang.org/COPYRIGHT.
|
\\1 http://rust-lang.org/COPYRIGHT.
|
||||||
#
|
\\1
|
||||||
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
\\1 Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
\\1 http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
\\1 <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
# option. This file may not be copied, modified, or distributed
|
\\1 option. This file may not be copied, modified, or distributed
|
||||||
# except according to those terms.
|
\\1 except according to those terms.""")
|
||||||
"""
|
|
||||||
|
|
||||||
exceptions = [
|
exceptions = [
|
||||||
"rt/rust_android_dummy.cpp", # BSD, chromium
|
"rt/rust_android_dummy.cpp", # BSD, chromium
|
||||||
|
@ -57,18 +46,14 @@ exceptions = [
|
||||||
|
|
||||||
def check_license(name, contents):
|
def check_license(name, contents):
|
||||||
# Whitelist check
|
# Whitelist check
|
||||||
for exception in exceptions:
|
if any(name.endswith(e) for e in exceptions):
|
||||||
if name.endswith(exception):
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# Xfail check
|
# Xfail check
|
||||||
firstlineish = contents[:100]
|
firstlineish = contents[:100]
|
||||||
if firstlineish.find("ignore-license") != -1:
|
if "ignore-license" in firstlineish:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# License check
|
# License check
|
||||||
boilerplate = contents[:500]
|
boilerplate = contents[:500]
|
||||||
if (boilerplate.find(license1) == -1 or boilerplate.find(license2) == -1) and \
|
return bool(license_re.search(boilerplate))
|
||||||
(boilerplate.find(license3) == -1 or boilerplate.find(license4) == -1):
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
|
@ -113,7 +113,7 @@ try:
|
||||||
if current_name != "":
|
if current_name != "":
|
||||||
do_license_check(current_name, current_contents)
|
do_license_check(current_name, current_contents)
|
||||||
|
|
||||||
except UnicodeDecodeError, e:
|
except UnicodeDecodeError as e:
|
||||||
report_err("UTF-8 decoding error " + str(e))
|
report_err("UTF-8 decoding error " + str(e))
|
||||||
|
|
||||||
|
|
||||||
|
|
342
src/grammar/lexer.l
Normal file
342
src/grammar/lexer.l
Normal file
|
@ -0,0 +1,342 @@
|
||||||
|
%{
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
static int num_hashes;
|
||||||
|
static int end_hashes;
|
||||||
|
static int saw_non_hash;
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
%option stack
|
||||||
|
%option yylineno
|
||||||
|
|
||||||
|
%x str
|
||||||
|
%x rawstr
|
||||||
|
%x rawstr_esc_begin
|
||||||
|
%x rawstr_esc_body
|
||||||
|
%x rawstr_esc_end
|
||||||
|
%x byte
|
||||||
|
%x bytestr
|
||||||
|
%x rawbytestr
|
||||||
|
%x rawbytestr_nohash
|
||||||
|
%x pound
|
||||||
|
%x shebang_or_attr
|
||||||
|
%x ltorchar
|
||||||
|
%x linecomment
|
||||||
|
%x doc_line
|
||||||
|
%x blockcomment
|
||||||
|
%x doc_block
|
||||||
|
%x suffix
|
||||||
|
|
||||||
|
ident [a-zA-Z\x80-\xff_][a-zA-Z0-9\x80-\xff_]*
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
<suffix>{ident} { BEGIN(INITIAL); }
|
||||||
|
<suffix>(.|\n) { yyless(0); BEGIN(INITIAL); }
|
||||||
|
|
||||||
|
[ \n\t\r] { }
|
||||||
|
|
||||||
|
\xef\xbb\xbf {
|
||||||
|
// UTF-8 byte order mark (BOM), ignore if in line 1, error otherwise
|
||||||
|
if (yyget_lineno() != 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
\/\/(\/|\!) { BEGIN(doc_line); yymore(); }
|
||||||
|
<doc_line>\n { BEGIN(INITIAL);
|
||||||
|
yyleng--;
|
||||||
|
yytext[yyleng] = 0;
|
||||||
|
return ((yytext[2] == '!') ? INNER_DOC_COMMENT : OUTER_DOC_COMMENT);
|
||||||
|
}
|
||||||
|
<doc_line>[^\n]* { yymore(); }
|
||||||
|
|
||||||
|
\/\/|\/\/\/\/ { BEGIN(linecomment); }
|
||||||
|
<linecomment>\n { BEGIN(INITIAL); }
|
||||||
|
<linecomment>[^\n]* { }
|
||||||
|
|
||||||
|
\/\*(\*|\!)[^*] { yy_push_state(INITIAL); yy_push_state(doc_block); yymore(); }
|
||||||
|
<doc_block>\/\* { yy_push_state(doc_block); yymore(); }
|
||||||
|
<doc_block>\*\/ {
|
||||||
|
yy_pop_state();
|
||||||
|
if (yy_top_state() == doc_block) {
|
||||||
|
yymore();
|
||||||
|
} else {
|
||||||
|
return ((yytext[2] == '!') ? INNER_DOC_COMMENT : OUTER_DOC_COMMENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
<doc_block>(.|\n) { yymore(); }
|
||||||
|
|
||||||
|
\/\* { yy_push_state(blockcomment); }
|
||||||
|
<blockcomment>\/\* { yy_push_state(blockcomment); }
|
||||||
|
<blockcomment>\*\/ { yy_pop_state(); }
|
||||||
|
<blockcomment>(.|\n) { }
|
||||||
|
|
||||||
|
_ { return UNDERSCORE; }
|
||||||
|
as { return AS; }
|
||||||
|
box { return BOX; }
|
||||||
|
break { return BREAK; }
|
||||||
|
const { return CONST; }
|
||||||
|
continue { return CONTINUE; }
|
||||||
|
crate { return CRATE; }
|
||||||
|
else { return ELSE; }
|
||||||
|
enum { return ENUM; }
|
||||||
|
extern { return EXTERN; }
|
||||||
|
false { return FALSE; }
|
||||||
|
fn { return FN; }
|
||||||
|
for { return FOR; }
|
||||||
|
if { return IF; }
|
||||||
|
impl { return IMPL; }
|
||||||
|
in { return IN; }
|
||||||
|
let { return LET; }
|
||||||
|
loop { return LOOP; }
|
||||||
|
match { return MATCH; }
|
||||||
|
mod { return MOD; }
|
||||||
|
move { return MOVE; }
|
||||||
|
mut { return MUT; }
|
||||||
|
priv { return PRIV; }
|
||||||
|
proc { return PROC; }
|
||||||
|
pub { return PUB; }
|
||||||
|
ref { return REF; }
|
||||||
|
return { return RETURN; }
|
||||||
|
self { return SELF; }
|
||||||
|
static { return STATIC; }
|
||||||
|
struct { return STRUCT; }
|
||||||
|
trait { return TRAIT; }
|
||||||
|
true { return TRUE; }
|
||||||
|
type { return TYPE; }
|
||||||
|
typeof { return TYPEOF; }
|
||||||
|
unsafe { return UNSAFE; }
|
||||||
|
use { return USE; }
|
||||||
|
where { return WHERE; }
|
||||||
|
while { return WHILE; }
|
||||||
|
|
||||||
|
{ident} { return IDENT; }
|
||||||
|
|
||||||
|
0x[0-9a-fA-F_]+ { BEGIN(suffix); return LIT_INTEGER; }
|
||||||
|
0o[0-8_]+ { BEGIN(suffix); return LIT_INTEGER; }
|
||||||
|
0b[01_]+ { BEGIN(suffix); return LIT_INTEGER; }
|
||||||
|
[0-9][0-9_]* { BEGIN(suffix); return LIT_INTEGER; }
|
||||||
|
[0-9][0-9_]*\.(\.|[a-zA-Z]) { yyless(yyleng - 2); BEGIN(suffix); return LIT_INTEGER; }
|
||||||
|
|
||||||
|
[0-9][0-9_]*\.[0-9_]*([eE][-\+]?[0-9_]+)? { BEGIN(suffix); return LIT_FLOAT; }
|
||||||
|
[0-9][0-9_]*(\.[0-9_]*)?[eE][-\+]?[0-9_]+ { BEGIN(suffix); return LIT_FLOAT; }
|
||||||
|
|
||||||
|
; { return ';'; }
|
||||||
|
, { return ','; }
|
||||||
|
\.\.\. { return DOTDOTDOT; }
|
||||||
|
\.\. { return DOTDOT; }
|
||||||
|
\. { return '.'; }
|
||||||
|
\( { return '('; }
|
||||||
|
\) { return ')'; }
|
||||||
|
\{ { return '{'; }
|
||||||
|
\} { return '}'; }
|
||||||
|
\[ { return '['; }
|
||||||
|
\] { return ']'; }
|
||||||
|
@ { return '@'; }
|
||||||
|
# { BEGIN(pound); yymore(); }
|
||||||
|
<pound>\! { BEGIN(shebang_or_attr); yymore(); }
|
||||||
|
<shebang_or_attr>\[ {
|
||||||
|
BEGIN(INITIAL);
|
||||||
|
yyless(2);
|
||||||
|
return SHEBANG;
|
||||||
|
}
|
||||||
|
<shebang_or_attr>[^\[\n]*\n {
|
||||||
|
// Since the \n was eaten as part of the token, yylineno will have
|
||||||
|
// been incremented to the value 2 if the shebang was on the first
|
||||||
|
// line. This yyless undoes that, setting yylineno back to 1.
|
||||||
|
yyless(yyleng - 1);
|
||||||
|
if (yyget_lineno() == 1) {
|
||||||
|
BEGIN(INITIAL);
|
||||||
|
return SHEBANG_LINE;
|
||||||
|
} else {
|
||||||
|
BEGIN(INITIAL);
|
||||||
|
yyless(2);
|
||||||
|
return SHEBANG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
<pound>. { BEGIN(INITIAL); yyless(1); return '#'; }
|
||||||
|
|
||||||
|
\~ { return '~'; }
|
||||||
|
:: { return MOD_SEP; }
|
||||||
|
: { return ':'; }
|
||||||
|
\$ { return '$'; }
|
||||||
|
\? { return '?'; }
|
||||||
|
|
||||||
|
== { return EQEQ; }
|
||||||
|
=> { return FAT_ARROW; }
|
||||||
|
= { return '='; }
|
||||||
|
\!= { return NE; }
|
||||||
|
\! { return '!'; }
|
||||||
|
\<= { return LE; }
|
||||||
|
\<\< { return SHL; }
|
||||||
|
\<\<= { return SHLEQ; }
|
||||||
|
\< { return '<'; }
|
||||||
|
\>= { return GE; }
|
||||||
|
\>\> { return SHR; }
|
||||||
|
\>\>= { return SHREQ; }
|
||||||
|
\> { return '>'; }
|
||||||
|
|
||||||
|
\x27 { BEGIN(ltorchar); yymore(); }
|
||||||
|
<ltorchar>static { BEGIN(INITIAL); return STATIC_LIFETIME; }
|
||||||
|
<ltorchar>{ident} { BEGIN(INITIAL); return LIFETIME; }
|
||||||
|
<ltorchar>\\[nrt\\\x27\x220]\x27 { BEGIN(suffix); return LIT_CHAR; }
|
||||||
|
<ltorchar>\\x[0-9a-fA-F]{2}\x27 { BEGIN(suffix); return LIT_CHAR; }
|
||||||
|
<ltorchar>\\u\{[0-9a-fA-F]?{6}\}\x27 { BEGIN(suffix); return LIT_CHAR; }
|
||||||
|
<ltorchar>.\x27 { BEGIN(suffix); return LIT_CHAR; }
|
||||||
|
<ltorchar>[\x80-\xff]{2,4}\x27 { BEGIN(suffix); return LIT_CHAR; }
|
||||||
|
<ltorchar><<EOF>> { BEGIN(INITIAL); return -1; }
|
||||||
|
|
||||||
|
b\x22 { BEGIN(bytestr); yymore(); }
|
||||||
|
<bytestr>\x22 { BEGIN(suffix); return LIT_BINARY; }
|
||||||
|
|
||||||
|
<bytestr><<EOF>> { return -1; }
|
||||||
|
<bytestr>\\[n\nrt\\\x27\x220] { yymore(); }
|
||||||
|
<bytestr>\\x[0-9a-fA-F]{2} { yymore(); }
|
||||||
|
<bytestr>\\u\{[0-9a-fA-F]?{6}\} { yymore(); }
|
||||||
|
<bytestr>\\[^n\nrt\\\x27\x220] { return -1; }
|
||||||
|
<bytestr>(.|\n) { yymore(); }
|
||||||
|
|
||||||
|
br\x22 { BEGIN(rawbytestr_nohash); yymore(); }
|
||||||
|
<rawbytestr_nohash>\x22 { BEGIN(suffix); return LIT_BINARY_RAW; }
|
||||||
|
<rawbytestr_nohash>(.|\n) { yymore(); }
|
||||||
|
<rawbytestr_nohash><<EOF>> { return -1; }
|
||||||
|
|
||||||
|
br/# {
|
||||||
|
BEGIN(rawbytestr);
|
||||||
|
yymore();
|
||||||
|
num_hashes = 0;
|
||||||
|
saw_non_hash = 0;
|
||||||
|
end_hashes = 0;
|
||||||
|
}
|
||||||
|
<rawbytestr># {
|
||||||
|
if (!saw_non_hash) {
|
||||||
|
num_hashes++;
|
||||||
|
} else if (end_hashes != 0) {
|
||||||
|
end_hashes++;
|
||||||
|
if (end_hashes == num_hashes) {
|
||||||
|
BEGIN(INITIAL);
|
||||||
|
return LIT_BINARY_RAW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yymore();
|
||||||
|
}
|
||||||
|
<rawbytestr>\x22# {
|
||||||
|
end_hashes = 1;
|
||||||
|
if (end_hashes == num_hashes) {
|
||||||
|
BEGIN(INITIAL);
|
||||||
|
return LIT_BINARY_RAW;
|
||||||
|
}
|
||||||
|
yymore();
|
||||||
|
}
|
||||||
|
<rawbytestr>(.|\n) {
|
||||||
|
if (!saw_non_hash) {
|
||||||
|
saw_non_hash = 1;
|
||||||
|
}
|
||||||
|
if (end_hashes != 0) {
|
||||||
|
end_hashes = 0;
|
||||||
|
}
|
||||||
|
yymore();
|
||||||
|
}
|
||||||
|
<rawbytestr><<EOF>> { return -1; }
|
||||||
|
|
||||||
|
b\x27 { BEGIN(byte); yymore(); }
|
||||||
|
<byte>\\[nrt\\\x27\x220]\x27 { BEGIN(INITIAL); return LIT_BYTE; }
|
||||||
|
<byte>\\x[0-9a-fA-F]{2}\x27 { BEGIN(INITIAL); return LIT_BYTE; }
|
||||||
|
<byte>\\u[0-9a-fA-F]{4}\x27 { BEGIN(INITIAL); return LIT_BYTE; }
|
||||||
|
<byte>\\U[0-9a-fA-F]{8}\x27 { BEGIN(INITIAL); return LIT_BYTE; }
|
||||||
|
<byte>.\x27 { BEGIN(INITIAL); return LIT_BYTE; }
|
||||||
|
<byte><<EOF>> { BEGIN(INITIAL); return -1; }
|
||||||
|
|
||||||
|
r\x22 { BEGIN(rawstr); yymore(); }
|
||||||
|
<rawstr>\x22 { BEGIN(suffix); return LIT_STR_RAW; }
|
||||||
|
<rawstr>(.|\n) { yymore(); }
|
||||||
|
<rawstr><<EOF>> { return -1; }
|
||||||
|
|
||||||
|
r/# {
|
||||||
|
BEGIN(rawstr_esc_begin);
|
||||||
|
yymore();
|
||||||
|
num_hashes = 0;
|
||||||
|
saw_non_hash = 0;
|
||||||
|
end_hashes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
<rawstr_esc_begin># {
|
||||||
|
num_hashes++;
|
||||||
|
yymore();
|
||||||
|
}
|
||||||
|
<rawstr_esc_begin>\x22 {
|
||||||
|
BEGIN(rawstr_esc_body);
|
||||||
|
yymore();
|
||||||
|
}
|
||||||
|
<rawstr_esc_begin>(.|\n) { return -1; }
|
||||||
|
|
||||||
|
<rawstr_esc_body>\x22/# {
|
||||||
|
BEGIN(rawstr_esc_end);
|
||||||
|
yymore();
|
||||||
|
}
|
||||||
|
<rawstr_esc_body>(.|\n) {
|
||||||
|
yymore();
|
||||||
|
}
|
||||||
|
|
||||||
|
<rawstr_esc_end># {
|
||||||
|
end_hashes++;
|
||||||
|
if (end_hashes == num_hashes) {
|
||||||
|
BEGIN(INITIAL);
|
||||||
|
return LIT_STR_RAW;
|
||||||
|
}
|
||||||
|
yymore();
|
||||||
|
}
|
||||||
|
<rawstr_esc_end>[^#] {
|
||||||
|
end_hashes = 0;
|
||||||
|
BEGIN(rawstr_esc_body);
|
||||||
|
yymore();
|
||||||
|
}
|
||||||
|
|
||||||
|
<rawstr_esc_begin,rawstr_esc_body,rawstr_esc_end><<EOF>> { return -1; }
|
||||||
|
|
||||||
|
\x22 { BEGIN(str); yymore(); }
|
||||||
|
<str>\x22 { BEGIN(suffix); return LIT_STR; }
|
||||||
|
|
||||||
|
<str><<EOF>> { return -1; }
|
||||||
|
<str>\\[n\nrt\\\x27\x220] { yymore(); }
|
||||||
|
<str>\\x[0-9a-fA-F]{2} { yymore(); }
|
||||||
|
<str>\\u\{[0-9a-fA-F]?{6}\} { yymore(); }
|
||||||
|
<str>\\[^n\nrt\\\x27\x220] { return -1; }
|
||||||
|
<str>(.|\n) { yymore(); }
|
||||||
|
|
||||||
|
-\> { return RARROW; }
|
||||||
|
- { return '-'; }
|
||||||
|
-= { return MINUSEQ; }
|
||||||
|
&& { return ANDAND; }
|
||||||
|
& { return '&'; }
|
||||||
|
&= { return ANDEQ; }
|
||||||
|
\|\| { return OROR; }
|
||||||
|
\| { return '|'; }
|
||||||
|
\|= { return OREQ; }
|
||||||
|
\+ { return '+'; }
|
||||||
|
\+= { return PLUSEQ; }
|
||||||
|
\* { return '*'; }
|
||||||
|
\*= { return STAREQ; }
|
||||||
|
\/ { return '/'; }
|
||||||
|
\/= { return SLASHEQ; }
|
||||||
|
\^ { return '^'; }
|
||||||
|
\^= { return CARETEQ; }
|
||||||
|
% { return '%'; }
|
||||||
|
%= { return PERCENTEQ; }
|
||||||
|
|
||||||
|
<<EOF>> { return 0; }
|
||||||
|
|
||||||
|
%%
|
203
src/grammar/parser-lalr-main.c
Normal file
203
src/grammar/parser-lalr-main.c
Normal file
|
@ -0,0 +1,203 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
extern int yylex();
|
||||||
|
extern int rsparse();
|
||||||
|
|
||||||
|
#define PUSHBACK_LEN 4
|
||||||
|
|
||||||
|
static char pushback[PUSHBACK_LEN];
|
||||||
|
static int verbose;
|
||||||
|
|
||||||
|
void print(const char* format, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
if (verbose) {
|
||||||
|
vprintf(format, args);
|
||||||
|
}
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is a non-null char at the head of the pushback queue,
|
||||||
|
// dequeue it and shift the rest of the queue forwards. Otherwise,
|
||||||
|
// return the token from calling yylex.
|
||||||
|
int rslex() {
|
||||||
|
if (pushback[0] == '\0') {
|
||||||
|
return yylex();
|
||||||
|
} else {
|
||||||
|
char c = pushback[0];
|
||||||
|
memmove(pushback, pushback + 1, PUSHBACK_LEN - 1);
|
||||||
|
pushback[PUSHBACK_LEN - 1] = '\0';
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: this does nothing if the pushback queue is full. As long as
|
||||||
|
// there aren't more than PUSHBACK_LEN consecutive calls to push_back
|
||||||
|
// in an action, this shouldn't be a problem.
|
||||||
|
void push_back(char c) {
|
||||||
|
for (int i = 0; i < PUSHBACK_LEN; ++i) {
|
||||||
|
if (pushback[i] == '\0') {
|
||||||
|
pushback[i] = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int rsdebug;
|
||||||
|
|
||||||
|
struct node {
|
||||||
|
struct node *next;
|
||||||
|
struct node *prev;
|
||||||
|
int own_string;
|
||||||
|
char const *name;
|
||||||
|
int n_elems;
|
||||||
|
struct node *elems[];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct node *nodes = NULL;
|
||||||
|
int n_nodes;
|
||||||
|
|
||||||
|
struct node *mk_node(char const *name, int n, ...) {
|
||||||
|
va_list ap;
|
||||||
|
int i = 0;
|
||||||
|
unsigned sz = sizeof(struct node) + (n * sizeof(struct node *));
|
||||||
|
struct node *nn, *nd = (struct node *)malloc(sz);
|
||||||
|
|
||||||
|
print("# New %d-ary node: %s = %p\n", n, name, nd);
|
||||||
|
|
||||||
|
nd->own_string = 0;
|
||||||
|
nd->prev = NULL;
|
||||||
|
nd->next = nodes;
|
||||||
|
if (nodes) {
|
||||||
|
nodes->prev = nd;
|
||||||
|
}
|
||||||
|
nodes = nd;
|
||||||
|
|
||||||
|
nd->name = name;
|
||||||
|
nd->n_elems = n;
|
||||||
|
|
||||||
|
va_start(ap, n);
|
||||||
|
while (i < n) {
|
||||||
|
nn = va_arg(ap, struct node *);
|
||||||
|
print("# arg[%d]: %p\n", i, nn);
|
||||||
|
print("# (%s ...)\n", nn->name);
|
||||||
|
nd->elems[i++] = nn;
|
||||||
|
}
|
||||||
|
va_end(ap);
|
||||||
|
n_nodes++;
|
||||||
|
return nd;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct node *mk_atom(char *name) {
|
||||||
|
struct node *nd = mk_node((char const *)strdup(name), 0);
|
||||||
|
nd->own_string = 1;
|
||||||
|
return nd;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct node *mk_none() {
|
||||||
|
return mk_atom("<none>");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct node *ext_node(struct node *nd, int n, ...) {
|
||||||
|
va_list ap;
|
||||||
|
int i = 0, c = nd->n_elems + n;
|
||||||
|
unsigned sz = sizeof(struct node) + (c * sizeof(struct node *));
|
||||||
|
struct node *nn;
|
||||||
|
|
||||||
|
print("# Extending %d-ary node by %d nodes: %s = %p",
|
||||||
|
nd->n_elems, c, nd->name, nd);
|
||||||
|
|
||||||
|
if (nd->next) {
|
||||||
|
nd->next->prev = nd->prev;
|
||||||
|
}
|
||||||
|
if (nd->prev) {
|
||||||
|
nd->prev->next = nd->next;
|
||||||
|
}
|
||||||
|
nd = realloc(nd, sz);
|
||||||
|
nd->prev = NULL;
|
||||||
|
nd->next = nodes;
|
||||||
|
nodes->prev = nd;
|
||||||
|
nodes = nd;
|
||||||
|
|
||||||
|
print(" ==> %p\n", nd);
|
||||||
|
|
||||||
|
va_start(ap, n);
|
||||||
|
while (i < n) {
|
||||||
|
nn = va_arg(ap, struct node *);
|
||||||
|
print("# arg[%d]: %p\n", i, nn);
|
||||||
|
print("# (%s ...)\n", nn->name);
|
||||||
|
nd->elems[nd->n_elems++] = nn;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
va_end(ap);
|
||||||
|
return nd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int const indent_step = 4;
|
||||||
|
|
||||||
|
void print_indent(int depth) {
|
||||||
|
while (depth) {
|
||||||
|
if (depth-- % indent_step == 0) {
|
||||||
|
print("|");
|
||||||
|
} else {
|
||||||
|
print(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_node(struct node *n, int depth) {
|
||||||
|
int i = 0;
|
||||||
|
print_indent(depth);
|
||||||
|
if (n->n_elems == 0) {
|
||||||
|
print("%s\n", n->name);
|
||||||
|
} else {
|
||||||
|
print("(%s\n", n->name);
|
||||||
|
for (i = 0; i < n->n_elems; ++i) {
|
||||||
|
print_node(n->elems[i], depth + indent_step);
|
||||||
|
}
|
||||||
|
print_indent(depth);
|
||||||
|
print(")\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
if (argc == 2 && strcmp(argv[1], "-v") == 0) {
|
||||||
|
verbose = 1;
|
||||||
|
} else {
|
||||||
|
verbose = 0;
|
||||||
|
}
|
||||||
|
int ret = 0;
|
||||||
|
struct node *tmp;
|
||||||
|
memset(pushback, '\0', PUSHBACK_LEN);
|
||||||
|
ret = rsparse();
|
||||||
|
print("--- PARSE COMPLETE: ret:%d, n_nodes:%d ---\n", ret, n_nodes);
|
||||||
|
if (nodes) {
|
||||||
|
print_node(nodes, 0);
|
||||||
|
}
|
||||||
|
while (nodes) {
|
||||||
|
tmp = nodes;
|
||||||
|
nodes = tmp->next;
|
||||||
|
if (tmp->own_string) {
|
||||||
|
free((void*)tmp->name);
|
||||||
|
}
|
||||||
|
free(tmp);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rserror(char const *s) {
|
||||||
|
fprintf(stderr, "%s\n", s);
|
||||||
|
}
|
1912
src/grammar/parser-lalr.y
Normal file
1912
src/grammar/parser-lalr.y
Normal file
File diff suppressed because it is too large
Load diff
65
src/grammar/testparser.py
Executable file
65
src/grammar/testparser.py
Executable file
|
@ -0,0 +1,65 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
# usage: testparser.py [-h] [-p PARSER [PARSER ...]] -s SOURCE_DIR
|
||||||
|
|
||||||
|
# Parsers should read from stdin and return exit status 0 for a
|
||||||
|
# successful parse, and nonzero for an unsuccessful parse
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('-p', '--parser', nargs='+')
|
||||||
|
parser.add_argument('-s', '--source-dir', nargs=1, required=True)
|
||||||
|
args = parser.parse_args(sys.argv[1:])
|
||||||
|
|
||||||
|
total = 0
|
||||||
|
ok = {}
|
||||||
|
bad = {}
|
||||||
|
for parser in args.parser:
|
||||||
|
ok[parser] = 0
|
||||||
|
bad[parser] = []
|
||||||
|
devnull = open(os.devnull, 'w')
|
||||||
|
print "\n"
|
||||||
|
|
||||||
|
for base, dirs, files in os.walk(args.source_dir[0]):
|
||||||
|
for f in filter(lambda p: p.endswith('.rs'), files):
|
||||||
|
p = os.path.join(base, f)
|
||||||
|
compile_fail = 'compile-fail' in p
|
||||||
|
ignore = any('ignore-test' in line or 'ignore-lexer-test' in line
|
||||||
|
for line in open(p).readlines())
|
||||||
|
if compile_fail or ignore:
|
||||||
|
continue
|
||||||
|
total += 1
|
||||||
|
for parser in args.parser:
|
||||||
|
if subprocess.call(parser, stdin=open(p), stderr=subprocess.STDOUT, stdout=devnull) == 0:
|
||||||
|
ok[parser] += 1
|
||||||
|
else:
|
||||||
|
bad[parser].append(p)
|
||||||
|
parser_stats = ', '.join(['{}: {}'.format(parser, ok[parser]) for parser in args.parser])
|
||||||
|
sys.stdout.write("\033[K\r total: {}, {}, scanned {}"
|
||||||
|
.format(total, os.path.relpath(parser_stats), os.path.relpath(p)))
|
||||||
|
|
||||||
|
devnull.close()
|
||||||
|
|
||||||
|
print "\n"
|
||||||
|
|
||||||
|
for parser in args.parser:
|
||||||
|
filename = os.path.basename(parser) + '.bad'
|
||||||
|
print("writing {} files that failed to parse with {} to {}".format(len(bad[parser]), parser, filename))
|
||||||
|
with open(filename, "w") as f:
|
||||||
|
for p in bad[parser]:
|
||||||
|
f.write(p)
|
||||||
|
f.write("\n")
|
91
src/grammar/tokens.h
Normal file
91
src/grammar/tokens.h
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
enum Token {
|
||||||
|
SHL = 257, // Parser generators reserve 0-256 for char literals
|
||||||
|
SHR,
|
||||||
|
LE,
|
||||||
|
EQEQ,
|
||||||
|
NE,
|
||||||
|
GE,
|
||||||
|
ANDAND,
|
||||||
|
OROR,
|
||||||
|
SHLEQ,
|
||||||
|
SHREQ,
|
||||||
|
MINUSEQ,
|
||||||
|
ANDEQ,
|
||||||
|
OREQ,
|
||||||
|
PLUSEQ,
|
||||||
|
STAREQ,
|
||||||
|
SLASHEQ,
|
||||||
|
CARETEQ,
|
||||||
|
PERCENTEQ,
|
||||||
|
DOTDOT,
|
||||||
|
DOTDOTDOT,
|
||||||
|
MOD_SEP,
|
||||||
|
RARROW,
|
||||||
|
FAT_ARROW,
|
||||||
|
LIT_BYTE,
|
||||||
|
LIT_CHAR,
|
||||||
|
LIT_INTEGER,
|
||||||
|
LIT_FLOAT,
|
||||||
|
LIT_STR,
|
||||||
|
LIT_STR_RAW,
|
||||||
|
LIT_BINARY,
|
||||||
|
LIT_BINARY_RAW,
|
||||||
|
IDENT,
|
||||||
|
UNDERSCORE,
|
||||||
|
LIFETIME,
|
||||||
|
|
||||||
|
// keywords
|
||||||
|
SELF,
|
||||||
|
STATIC,
|
||||||
|
AS,
|
||||||
|
BREAK,
|
||||||
|
CRATE,
|
||||||
|
ELSE,
|
||||||
|
ENUM,
|
||||||
|
EXTERN,
|
||||||
|
FALSE,
|
||||||
|
FN,
|
||||||
|
FOR,
|
||||||
|
IF,
|
||||||
|
IMPL,
|
||||||
|
IN,
|
||||||
|
LET,
|
||||||
|
LOOP,
|
||||||
|
MATCH,
|
||||||
|
MOD,
|
||||||
|
MOVE,
|
||||||
|
MUT,
|
||||||
|
PRIV,
|
||||||
|
PUB,
|
||||||
|
REF,
|
||||||
|
RETURN,
|
||||||
|
STRUCT,
|
||||||
|
TRUE,
|
||||||
|
TRAIT,
|
||||||
|
TYPE,
|
||||||
|
UNSAFE,
|
||||||
|
USE,
|
||||||
|
WHILE,
|
||||||
|
CONTINUE,
|
||||||
|
PROC,
|
||||||
|
BOX,
|
||||||
|
CONST,
|
||||||
|
WHERE,
|
||||||
|
TYPEOF,
|
||||||
|
INNER_DOC_COMMENT,
|
||||||
|
OUTER_DOC_COMMENT,
|
||||||
|
|
||||||
|
SHEBANG,
|
||||||
|
SHEBANG_LINE,
|
||||||
|
STATIC_LIFETIME
|
||||||
|
};
|
|
@ -589,7 +589,7 @@ impl AtomicUsize {
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::sync::atomic::AtomicUsize;
|
/// use std::sync::atomic::AtomicUsize;
|
||||||
///
|
///
|
||||||
/// let atomic_forty_two = AtomicUsize::new(42u);
|
/// let atomic_forty_two = AtomicUsize::new(42);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(v: usize) -> AtomicUsize {
|
pub fn new(v: usize) -> AtomicUsize {
|
||||||
|
@ -765,7 +765,7 @@ impl<T> AtomicPtr<T> {
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::sync::atomic::AtomicPtr;
|
/// use std::sync::atomic::AtomicPtr;
|
||||||
///
|
///
|
||||||
/// let ptr = &mut 5i;
|
/// let ptr = &mut 5;
|
||||||
/// let atomic_ptr = AtomicPtr::new(ptr);
|
/// let atomic_ptr = AtomicPtr::new(ptr);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -787,7 +787,7 @@ impl<T> AtomicPtr<T> {
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::sync::atomic::{AtomicPtr, Ordering};
|
/// use std::sync::atomic::{AtomicPtr, Ordering};
|
||||||
///
|
///
|
||||||
/// let ptr = &mut 5i;
|
/// let ptr = &mut 5;
|
||||||
/// let some_ptr = AtomicPtr::new(ptr);
|
/// let some_ptr = AtomicPtr::new(ptr);
|
||||||
///
|
///
|
||||||
/// let value = some_ptr.load(Ordering::Relaxed);
|
/// let value = some_ptr.load(Ordering::Relaxed);
|
||||||
|
@ -809,10 +809,10 @@ impl<T> AtomicPtr<T> {
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::sync::atomic::{AtomicPtr, Ordering};
|
/// use std::sync::atomic::{AtomicPtr, Ordering};
|
||||||
///
|
///
|
||||||
/// let ptr = &mut 5i;
|
/// let ptr = &mut 5;
|
||||||
/// let some_ptr = AtomicPtr::new(ptr);
|
/// let some_ptr = AtomicPtr::new(ptr);
|
||||||
///
|
///
|
||||||
/// let other_ptr = &mut 10i;
|
/// let other_ptr = &mut 10;
|
||||||
///
|
///
|
||||||
/// some_ptr.store(other_ptr, Ordering::Relaxed);
|
/// some_ptr.store(other_ptr, Ordering::Relaxed);
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -835,10 +835,10 @@ impl<T> AtomicPtr<T> {
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::sync::atomic::{AtomicPtr, Ordering};
|
/// use std::sync::atomic::{AtomicPtr, Ordering};
|
||||||
///
|
///
|
||||||
/// let ptr = &mut 5i;
|
/// let ptr = &mut 5;
|
||||||
/// let some_ptr = AtomicPtr::new(ptr);
|
/// let some_ptr = AtomicPtr::new(ptr);
|
||||||
///
|
///
|
||||||
/// let other_ptr = &mut 10i;
|
/// let other_ptr = &mut 10;
|
||||||
///
|
///
|
||||||
/// let value = some_ptr.swap(other_ptr, Ordering::Relaxed);
|
/// let value = some_ptr.swap(other_ptr, Ordering::Relaxed);
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -860,11 +860,11 @@ impl<T> AtomicPtr<T> {
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::sync::atomic::{AtomicPtr, Ordering};
|
/// use std::sync::atomic::{AtomicPtr, Ordering};
|
||||||
///
|
///
|
||||||
/// let ptr = &mut 5i;
|
/// let ptr = &mut 5;
|
||||||
/// let some_ptr = AtomicPtr::new(ptr);
|
/// let some_ptr = AtomicPtr::new(ptr);
|
||||||
///
|
///
|
||||||
/// let other_ptr = &mut 10i;
|
/// let other_ptr = &mut 10;
|
||||||
/// let another_ptr = &mut 10i;
|
/// let another_ptr = &mut 10;
|
||||||
///
|
///
|
||||||
/// let value = some_ptr.compare_and_swap(other_ptr, another_ptr, Ordering::Relaxed);
|
/// let value = some_ptr.compare_and_swap(other_ptr, another_ptr, Ordering::Relaxed);
|
||||||
/// ```
|
/// ```
|
||||||
|
|
|
@ -67,10 +67,10 @@
|
||||||
//!
|
//!
|
||||||
//! fn main() {
|
//! fn main() {
|
||||||
//! let shared_map: Rc<RefCell<_>> = Rc::new(RefCell::new(HashMap::new()));
|
//! let shared_map: Rc<RefCell<_>> = Rc::new(RefCell::new(HashMap::new()));
|
||||||
//! shared_map.borrow_mut().insert("africa", 92388i);
|
//! shared_map.borrow_mut().insert("africa", 92388);
|
||||||
//! shared_map.borrow_mut().insert("kyoto", 11837i);
|
//! shared_map.borrow_mut().insert("kyoto", 11837);
|
||||||
//! shared_map.borrow_mut().insert("piccadilly", 11826i);
|
//! shared_map.borrow_mut().insert("piccadilly", 11826);
|
||||||
//! shared_map.borrow_mut().insert("marbles", 38i);
|
//! shared_map.borrow_mut().insert("marbles", 38);
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
|
|
@ -102,7 +102,7 @@ pub fn from_digit(num: uint, radix: uint) -> Option<char> {
|
||||||
if num < 10 {
|
if num < 10 {
|
||||||
Some(transmute(('0' as uint + num) as u32))
|
Some(transmute(('0' as uint + num) as u32))
|
||||||
} else {
|
} else {
|
||||||
Some(transmute(('a' as uint + num - 10u) as u32))
|
Some(transmute(('a' as uint + num - 10) as u32))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -212,8 +212,8 @@ impl CharExt for char {
|
||||||
}
|
}
|
||||||
let val = match self {
|
let val = match self {
|
||||||
'0' ... '9' => self as uint - ('0' as uint),
|
'0' ... '9' => self as uint - ('0' as uint),
|
||||||
'a' ... 'z' => self as uint + 10u - ('a' as uint),
|
'a' ... 'z' => self as uint + 10 - ('a' as uint),
|
||||||
'A' ... 'Z' => self as uint + 10u - ('A' as uint),
|
'A' ... 'Z' => self as uint + 10 - ('A' as uint),
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
if val < radix { Some(val) }
|
if val < radix { Some(val) }
|
||||||
|
@ -245,10 +245,10 @@ impl CharExt for char {
|
||||||
fn len_utf8(self) -> uint {
|
fn len_utf8(self) -> uint {
|
||||||
let code = self as u32;
|
let code = self as u32;
|
||||||
match () {
|
match () {
|
||||||
_ if code < MAX_ONE_B => 1u,
|
_ if code < MAX_ONE_B => 1,
|
||||||
_ if code < MAX_TWO_B => 2u,
|
_ if code < MAX_TWO_B => 2,
|
||||||
_ if code < MAX_THREE_B => 3u,
|
_ if code < MAX_THREE_B => 3,
|
||||||
_ => 4u,
|
_ => 4,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,8 +263,26 @@ impl CharExt for char {
|
||||||
#[unstable(feature = "core",
|
#[unstable(feature = "core",
|
||||||
reason = "pending decision about Iterator/Writer/Reader")]
|
reason = "pending decision about Iterator/Writer/Reader")]
|
||||||
fn encode_utf8(self, dst: &mut [u8]) -> Option<uint> {
|
fn encode_utf8(self, dst: &mut [u8]) -> Option<uint> {
|
||||||
|
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<uint> {
|
||||||
|
encode_utf16_raw(self as u32, dst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encodes a raw u32 value 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.
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "core")]
|
||||||
|
pub fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> Option<uint> {
|
||||||
// Marked #[inline] to allow llvm optimizing it away
|
// Marked #[inline] to allow llvm optimizing it away
|
||||||
let code = self as u32;
|
|
||||||
if code < MAX_ONE_B && dst.len() >= 1 {
|
if code < MAX_ONE_B && dst.len() >= 1 {
|
||||||
dst[0] = code as u8;
|
dst[0] = code as u8;
|
||||||
Some(1)
|
Some(1)
|
||||||
|
@ -286,14 +304,17 @@ impl CharExt for char {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
/// Encodes a raw u32 value as UTF-16 into the provided `u16` buffer,
|
||||||
#[unstable(feature = "core",
|
/// and then returns the number of `u16`s written.
|
||||||
reason = "pending decision about Iterator/Writer/Reader")]
|
///
|
||||||
fn encode_utf16(self, dst: &mut [u16]) -> Option<uint> {
|
/// 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<uint> {
|
||||||
// Marked #[inline] to allow llvm optimizing it away
|
// Marked #[inline] to allow llvm optimizing it away
|
||||||
let mut ch = self as u32;
|
|
||||||
if (ch & 0xFFFF_u32) == ch && dst.len() >= 1 {
|
if (ch & 0xFFFF_u32) == ch && dst.len() >= 1 {
|
||||||
// The BMP falls through (assuming non-surrogate, as it should)
|
// The BMP falls through (assuming non-surrogate, as it should)
|
||||||
dst[0] = ch as u16;
|
dst[0] = ch as u16;
|
||||||
|
@ -307,7 +328,6 @@ impl CharExt for char {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An iterator over the characters that represent a `char`, as escaped by
|
/// An iterator over the characters that represent a `char`, as escaped by
|
||||||
|
@ -345,7 +365,7 @@ impl Iterator for EscapeUnicode {
|
||||||
Some('u')
|
Some('u')
|
||||||
}
|
}
|
||||||
EscapeUnicodeState::LeftBrace => {
|
EscapeUnicodeState::LeftBrace => {
|
||||||
let mut n = 0u;
|
let mut n = 0;
|
||||||
while (self.c as u32) >> (4 * (n + 1)) != 0 {
|
while (self.c as u32) >> (4 * (n + 1)) != 0 {
|
||||||
n += 1;
|
n += 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,13 +110,13 @@ pub trait Eq: PartialEq<Self> {
|
||||||
pub enum Ordering {
|
pub enum Ordering {
|
||||||
/// An ordering where a compared value is less [than another].
|
/// An ordering where a compared value is less [than another].
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
Less = -1i,
|
Less = -1,
|
||||||
/// An ordering where a compared value is equal [to another].
|
/// An ordering where a compared value is equal [to another].
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
Equal = 0i,
|
Equal = 0,
|
||||||
/// An ordering where a compared value is greater [than another].
|
/// An ordering where a compared value is greater [than another].
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
Greater = 1i,
|
Greater = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ordering {
|
impl Ordering {
|
||||||
|
@ -132,12 +132,12 @@ impl Ordering {
|
||||||
/// assert_eq!(Equal.reverse(), Equal);
|
/// assert_eq!(Equal.reverse(), Equal);
|
||||||
/// assert_eq!(Greater.reverse(), Less);
|
/// assert_eq!(Greater.reverse(), Less);
|
||||||
///
|
///
|
||||||
/// let mut data: &mut [_] = &mut [2u, 10, 5, 8];
|
/// let mut data: &mut [_] = &mut [2, 10, 5, 8];
|
||||||
///
|
///
|
||||||
/// // sort the array from largest to smallest.
|
/// // sort the array from largest to smallest.
|
||||||
/// data.sort_by(|a, b| a.cmp(b).reverse());
|
/// data.sort_by(|a, b| a.cmp(b).reverse());
|
||||||
///
|
///
|
||||||
/// let b: &mut [_] = &mut [10u, 8, 5, 2];
|
/// let b: &mut [_] = &mut [10, 8, 5, 2];
|
||||||
/// assert!(data == b);
|
/// assert!(data == b);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -174,9 +174,9 @@ pub trait Ord: Eq + PartialOrd<Self> {
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::cmp::Ordering::{Less, Equal, Greater};
|
/// use std::cmp::Ordering::{Less, Equal, Greater};
|
||||||
///
|
///
|
||||||
/// assert_eq!( 5u.cmp(&10), Less); // because 5 < 10
|
/// assert_eq!( 5.cmp(&10), Less); // because 5 < 10
|
||||||
/// assert_eq!(10u.cmp(&5), Greater); // because 10 > 5
|
/// assert_eq!(10.cmp(&5), Greater); // because 10 > 5
|
||||||
/// assert_eq!( 5u.cmp(&5), Equal); // because 5 == 5
|
/// assert_eq!( 5.cmp(&5), Equal); // because 5 == 5
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn cmp(&self, other: &Self) -> Ordering;
|
fn cmp(&self, other: &Self) -> Ordering;
|
||||||
|
|
|
@ -150,17 +150,17 @@ default_impl! { (), () }
|
||||||
default_impl! { bool, false }
|
default_impl! { bool, false }
|
||||||
default_impl! { char, '\x00' }
|
default_impl! { char, '\x00' }
|
||||||
|
|
||||||
default_impl! { uint, 0u }
|
default_impl! { uint, 0 }
|
||||||
default_impl! { u8, 0u8 }
|
default_impl! { u8, 0 }
|
||||||
default_impl! { u16, 0u16 }
|
default_impl! { u16, 0 }
|
||||||
default_impl! { u32, 0u32 }
|
default_impl! { u32, 0 }
|
||||||
default_impl! { u64, 0u64 }
|
default_impl! { u64, 0 }
|
||||||
|
|
||||||
default_impl! { int, 0i }
|
default_impl! { int, 0 }
|
||||||
default_impl! { i8, 0i8 }
|
default_impl! { i8, 0 }
|
||||||
default_impl! { i16, 0i16 }
|
default_impl! { i16, 0 }
|
||||||
default_impl! { i32, 0i32 }
|
default_impl! { i32, 0 }
|
||||||
default_impl! { i64, 0i64 }
|
default_impl! { i64, 0 }
|
||||||
|
|
||||||
default_impl! { f32, 0.0f32 }
|
default_impl! { f32, 0.0f32 }
|
||||||
default_impl! { f64, 0.0f64 }
|
default_impl! { f64, 0.0f64 }
|
||||||
|
|
|
@ -53,7 +53,7 @@ pub enum SignFormat {
|
||||||
SignNeg
|
SignNeg
|
||||||
}
|
}
|
||||||
|
|
||||||
static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u;
|
static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11;
|
||||||
|
|
||||||
/// Converts a number to its string representation as a byte vector.
|
/// Converts a number to its string representation as a byte vector.
|
||||||
/// This is meant to be a common base implementation for all numeric string
|
/// This is meant to be a common base implementation for all numeric string
|
||||||
|
@ -191,7 +191,7 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
|
||||||
if deccum != _0 || (limit_digits && exact && digit_count > 0) {
|
if deccum != _0 || (limit_digits && exact && digit_count > 0) {
|
||||||
buf[end] = b'.';
|
buf[end] = b'.';
|
||||||
end += 1;
|
end += 1;
|
||||||
let mut dig = 0u;
|
let mut dig = 0;
|
||||||
|
|
||||||
// calculate new digits while
|
// calculate new digits while
|
||||||
// - there is no limit and there are digits left
|
// - there is no limit and there are digits left
|
||||||
|
@ -218,7 +218,7 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
|
||||||
|
|
||||||
// Decrease the deccumulator one fractional digit at a time
|
// Decrease the deccumulator one fractional digit at a time
|
||||||
deccum = deccum.fract();
|
deccum = deccum.fract();
|
||||||
dig += 1u;
|
dig += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If digits are limited, and that limit has been reached,
|
// If digits are limited, and that limit has been reached,
|
||||||
|
|
|
@ -253,6 +253,8 @@ pub trait Show {
|
||||||
/// should implement this.
|
/// should implement this.
|
||||||
#[unstable(feature = "core",
|
#[unstable(feature = "core",
|
||||||
reason = "I/O and core have yet to be reconciled")]
|
reason = "I/O and core have yet to be reconciled")]
|
||||||
|
#[rustc_on_unimplemented = "`{Self}` cannot be formatted using `:?`; if it is defined in your \
|
||||||
|
crate, add `#[derive(Debug)]` or manually implement it"]
|
||||||
pub trait Debug {
|
pub trait Debug {
|
||||||
/// Formats the value using the given formatter.
|
/// Formats the value using the given formatter.
|
||||||
fn fmt(&self, &mut Formatter) -> Result;
|
fn fmt(&self, &mut Formatter) -> Result;
|
||||||
|
@ -278,6 +280,8 @@ pub trait String {
|
||||||
/// used. It corresponds to the default format, `{}`.
|
/// used. It corresponds to the default format, `{}`.
|
||||||
#[unstable(feature = "core",
|
#[unstable(feature = "core",
|
||||||
reason = "I/O and core have yet to be reconciled")]
|
reason = "I/O and core have yet to be reconciled")]
|
||||||
|
#[rustc_on_unimplemented = "`{Self}` cannot be formatted with the default formatter; try using \
|
||||||
|
`:?` instead if you are using a format string"]
|
||||||
pub trait Display {
|
pub trait Display {
|
||||||
/// Formats the value using the given formatter.
|
/// Formats the value using the given formatter.
|
||||||
fn fmt(&self, &mut Formatter) -> Result;
|
fn fmt(&self, &mut Formatter) -> Result;
|
||||||
|
@ -582,8 +586,8 @@ impl<'a> Formatter<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let (pre_pad, post_pad) = match align {
|
let (pre_pad, post_pad) = match align {
|
||||||
rt::AlignLeft => (0u, padding),
|
rt::AlignLeft => (0, padding),
|
||||||
rt::AlignRight | rt::AlignUnknown => (padding, 0u),
|
rt::AlignRight | rt::AlignUnknown => (padding, 0),
|
||||||
rt::AlignCenter => (padding / 2, (padding + 1) / 2),
|
rt::AlignCenter => (padding / 2, (padding + 1) / 2),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -873,7 +877,7 @@ macro_rules! tuple {
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||||
try!(write!(f, "("));
|
try!(write!(f, "("));
|
||||||
let ($(ref $name,)*) = *self;
|
let ($(ref $name,)*) = *self;
|
||||||
let mut n = 0i;
|
let mut n = 0;
|
||||||
$(
|
$(
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
try!(write!(f, ", "));
|
try!(write!(f, ", "));
|
||||||
|
|
|
@ -147,7 +147,7 @@ pub struct RadixFmt<T, R>(T, R);
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::fmt::radix;
|
/// use std::fmt::radix;
|
||||||
/// assert_eq!(format!("{}", radix(55i, 36)), "1j".to_string());
|
/// assert_eq!(format!("{}", radix(55, 36)), "1j".to_string());
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "core",
|
#[unstable(feature = "core",
|
||||||
reason = "may be renamed or move to a different module")]
|
reason = "may be renamed or move to a different module")]
|
||||||
|
|
|
@ -123,7 +123,7 @@ impl Writer for SipHasher {
|
||||||
let length = msg.len();
|
let length = msg.len();
|
||||||
self.length += length;
|
self.length += length;
|
||||||
|
|
||||||
let mut needed = 0u;
|
let mut needed = 0;
|
||||||
|
|
||||||
if self.ntail != 0 {
|
if self.ntail != 0 {
|
||||||
needed = 8 - self.ntail;
|
needed = 8 - self.ntail;
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
//! translated to the `loop` below.
|
//! translated to the `loop` below.
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! let values = vec![1i, 2, 3];
|
//! let values = vec![1, 2, 3];
|
||||||
//!
|
//!
|
||||||
//! // "Syntactical sugar" taking advantage of an iterator
|
//! // "Syntactical sugar" taking advantage of an iterator
|
||||||
//! for &x in values.iter() {
|
//! for &x in values.iter() {
|
||||||
|
@ -82,6 +82,8 @@ use usize;
|
||||||
/// else.
|
/// else.
|
||||||
#[lang="iterator"]
|
#[lang="iterator"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_on_unimplemented = "`{Self}` is not an iterator; maybe try calling `.iter()` or a similar \
|
||||||
|
method"]
|
||||||
pub trait Iterator {
|
pub trait Iterator {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
type Item;
|
type Item;
|
||||||
|
@ -616,7 +618,7 @@ pub trait IteratorExt: Iterator + Sized {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let a = [1i, 2, 3, 4, 5];
|
/// let a = [1, 2, 3, 4, 5];
|
||||||
/// assert!(a.iter().all(|x| *x > 0));
|
/// assert!(a.iter().all(|x| *x > 0));
|
||||||
/// assert!(!a.iter().all(|x| *x > 2));
|
/// assert!(!a.iter().all(|x| *x > 2));
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -1147,7 +1149,7 @@ pub trait AdditiveIterator<A> {
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::iter::AdditiveIterator;
|
/// use std::iter::AdditiveIterator;
|
||||||
///
|
///
|
||||||
/// let a = [1i, 2, 3, 4, 5];
|
/// let a = [1i32, 2, 3, 4, 5];
|
||||||
/// let mut it = a.iter().map(|&x| x);
|
/// let mut it = a.iter().map(|&x| x);
|
||||||
/// assert!(it.sum() == 15);
|
/// assert!(it.sum() == 15);
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -1190,7 +1192,7 @@ pub trait MultiplicativeIterator<A> {
|
||||||
/// use std::iter::{count, MultiplicativeIterator};
|
/// use std::iter::{count, MultiplicativeIterator};
|
||||||
///
|
///
|
||||||
/// fn factorial(n: usize) -> usize {
|
/// fn factorial(n: usize) -> usize {
|
||||||
/// count(1u, 1).take_while(|&i| i <= n).product()
|
/// count(1, 1).take_while(|&i| i <= n).product()
|
||||||
/// }
|
/// }
|
||||||
/// assert!(factorial(0) == 1);
|
/// assert!(factorial(0) == 1);
|
||||||
/// assert!(factorial(1) == 1);
|
/// assert!(factorial(1) == 1);
|
||||||
|
@ -2537,7 +2539,7 @@ pub struct Range<A> {
|
||||||
/// ```
|
/// ```
|
||||||
/// let array = [0, 1, 2, 3, 4];
|
/// let array = [0, 1, 2, 3, 4];
|
||||||
///
|
///
|
||||||
/// for i in range(0, 5u) {
|
/// for i in range(0, 5) {
|
||||||
/// println!("{}", i);
|
/// println!("{}", i);
|
||||||
/// assert_eq!(i, array[i]);
|
/// assert_eq!(i, array[i]);
|
||||||
/// }
|
/// }
|
||||||
|
|
|
@ -48,7 +48,7 @@ macro_rules! panic {
|
||||||
/// let x = true;
|
/// let x = true;
|
||||||
/// assert!(x, "x wasn't true!");
|
/// assert!(x, "x wasn't true!");
|
||||||
///
|
///
|
||||||
/// let a = 3i; let b = 27i;
|
/// let a = 3; let b = 27;
|
||||||
/// assert!(a + b == 30, "a = {}, b = {}", a, b);
|
/// assert!(a + b == 30, "a = {}, b = {}", a, b);
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
@ -74,8 +74,8 @@ macro_rules! assert {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let a = 3i;
|
/// let a = 3;
|
||||||
/// let b = 1i + 2i;
|
/// let b = 1 + 2;
|
||||||
/// assert_eq!(a, b);
|
/// assert_eq!(a, b);
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
@ -141,8 +141,8 @@ macro_rules! debug_assert {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let a = 3i;
|
/// let a = 3;
|
||||||
/// let b = 1i + 2i;
|
/// let b = 1 + 2;
|
||||||
/// debug_assert_eq!(a, b);
|
/// debug_assert_eq!(a, b);
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
|
|
@ -27,10 +27,11 @@
|
||||||
|
|
||||||
use clone::Clone;
|
use clone::Clone;
|
||||||
|
|
||||||
/// Types able to be transferred across task boundaries.
|
/// Types able to be transferred across thread boundaries.
|
||||||
#[unstable(feature = "core",
|
#[unstable(feature = "core",
|
||||||
reason = "will be overhauled with new lifetime rules; see RFC 458")]
|
reason = "will be overhauled with new lifetime rules; see RFC 458")]
|
||||||
#[lang="send"]
|
#[lang="send"]
|
||||||
|
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
|
||||||
pub unsafe trait Send: 'static {
|
pub unsafe trait Send: 'static {
|
||||||
// empty.
|
// empty.
|
||||||
}
|
}
|
||||||
|
@ -38,6 +39,7 @@ pub unsafe trait Send: 'static {
|
||||||
/// Types with a constant size known at compile-time.
|
/// Types with a constant size known at compile-time.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[lang="sized"]
|
#[lang="sized"]
|
||||||
|
#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
|
||||||
pub trait Sized {
|
pub trait Sized {
|
||||||
// Empty.
|
// Empty.
|
||||||
}
|
}
|
||||||
|
@ -147,11 +149,11 @@ pub trait Copy {
|
||||||
// Empty.
|
// Empty.
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Types that can be safely shared between tasks when aliased.
|
/// Types that can be safely shared between threads when aliased.
|
||||||
///
|
///
|
||||||
/// The precise definition is: a type `T` is `Sync` if `&T` is
|
/// The precise definition is: a type `T` is `Sync` if `&T` is
|
||||||
/// thread-safe. In other words, there is no possibility of data races
|
/// thread-safe. In other words, there is no possibility of data races
|
||||||
/// when passing `&T` references between tasks.
|
/// when passing `&T` references between threads.
|
||||||
///
|
///
|
||||||
/// As one would expect, primitive types like `u8` and `f64` are all
|
/// As one would expect, primitive types like `u8` and `f64` are all
|
||||||
/// `Sync`, and so are simple aggregate types containing them (like
|
/// `Sync`, and so are simple aggregate types containing them (like
|
||||||
|
@ -195,6 +197,7 @@ pub trait Copy {
|
||||||
#[unstable(feature = "core",
|
#[unstable(feature = "core",
|
||||||
reason = "will be overhauled with new lifetime rules; see RFC 458")]
|
reason = "will be overhauled with new lifetime rules; see RFC 458")]
|
||||||
#[lang="sync"]
|
#[lang="sync"]
|
||||||
|
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
|
||||||
pub unsafe trait Sync {
|
pub unsafe trait Sync {
|
||||||
// Empty
|
// Empty
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,13 +187,13 @@ pub unsafe fn uninitialized<T>() -> T {
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::mem;
|
/// use std::mem;
|
||||||
///
|
///
|
||||||
/// let x = &mut 5i;
|
/// let x = &mut 5;
|
||||||
/// let y = &mut 42i;
|
/// let y = &mut 42;
|
||||||
///
|
///
|
||||||
/// mem::swap(x, y);
|
/// mem::swap(x, y);
|
||||||
///
|
///
|
||||||
/// assert_eq!(42i, *x);
|
/// assert_eq!(42, *x);
|
||||||
/// assert_eq!(5i, *y);
|
/// assert_eq!(5, *y);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -277,7 +277,7 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::cell::RefCell;
|
/// use std::cell::RefCell;
|
||||||
///
|
///
|
||||||
/// let x = RefCell::new(1i);
|
/// let x = RefCell::new(1);
|
||||||
///
|
///
|
||||||
/// let mut mutable_borrow = x.borrow_mut();
|
/// let mut mutable_borrow = x.borrow_mut();
|
||||||
/// *mutable_borrow = 1;
|
/// *mutable_borrow = 1;
|
||||||
|
@ -306,9 +306,9 @@ pub fn drop<T>(_x: T) { }
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::mem;
|
/// use std::mem;
|
||||||
///
|
///
|
||||||
/// let one = unsafe { mem::transmute_copy(&1i) };
|
/// let one = unsafe { mem::transmute_copy(&1) };
|
||||||
///
|
///
|
||||||
/// assert_eq!(1u, one);
|
/// assert_eq!(1, one);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
|
@ -23,12 +23,12 @@ use num::FpCategory as Fp;
|
||||||
use option::Option;
|
use option::Option;
|
||||||
|
|
||||||
#[unstable(feature = "core", reason = "pending integer conventions")]
|
#[unstable(feature = "core", reason = "pending integer conventions")]
|
||||||
pub const RADIX: uint = 2u;
|
pub const RADIX: uint = 2;
|
||||||
|
|
||||||
#[unstable(feature = "core", reason = "pending integer conventions")]
|
#[unstable(feature = "core", reason = "pending integer conventions")]
|
||||||
pub const MANTISSA_DIGITS: uint = 24u;
|
pub const MANTISSA_DIGITS: uint = 24;
|
||||||
#[unstable(feature = "core", reason = "pending integer conventions")]
|
#[unstable(feature = "core", reason = "pending integer conventions")]
|
||||||
pub const DIGITS: uint = 6u;
|
pub const DIGITS: uint = 6;
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub const EPSILON: f32 = 1.19209290e-07_f32;
|
pub const EPSILON: f32 = 1.19209290e-07_f32;
|
||||||
|
|
|
@ -27,11 +27,11 @@ use option::Option;
|
||||||
// members of `Bounded` and `Float`.
|
// members of `Bounded` and `Float`.
|
||||||
|
|
||||||
#[unstable(feature = "core", reason = "pending integer conventions")]
|
#[unstable(feature = "core", reason = "pending integer conventions")]
|
||||||
pub const RADIX: uint = 2u;
|
pub const RADIX: uint = 2;
|
||||||
|
|
||||||
pub const MANTISSA_DIGITS: uint = 53u;
|
pub const MANTISSA_DIGITS: uint = 53;
|
||||||
#[unstable(feature = "core", reason = "pending integer conventions")]
|
#[unstable(feature = "core", reason = "pending integer conventions")]
|
||||||
pub const DIGITS: uint = 15u;
|
pub const DIGITS: uint = 15;
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub const EPSILON: f64 = 2.2204460492503131e-16_f64;
|
pub const EPSILON: f64 = 2.2204460492503131e-16_f64;
|
||||||
|
|
|
@ -366,7 +366,7 @@ pub trait Int
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use std::num::Int;
|
/// use std::num::Int;
|
||||||
///
|
///
|
||||||
/// assert_eq!(2i.pow(4), 16);
|
/// assert_eq!(2.pow(4), 16);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "core",
|
#[unstable(feature = "core",
|
||||||
reason = "pending integer conventions")]
|
reason = "pending integer conventions")]
|
||||||
|
@ -1196,7 +1196,7 @@ impl_from_primitive! { f64, to_f64 }
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::num;
|
/// use std::num;
|
||||||
///
|
///
|
||||||
/// let twenty: f32 = num::cast(0x14i).unwrap();
|
/// let twenty: f32 = num::cast(0x14).unwrap();
|
||||||
/// assert_eq!(twenty, 20f32);
|
/// assert_eq!(twenty, 20f32);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
@ -1607,8 +1607,8 @@ macro_rules! from_str_radix_float_impl {
|
||||||
let exp = match exp_info {
|
let exp = match exp_info {
|
||||||
Some((c, offset)) => {
|
Some((c, offset)) => {
|
||||||
let base = match c {
|
let base = match c {
|
||||||
'E' | 'e' if radix == 10 => 10u as $T,
|
'E' | 'e' if radix == 10 => 10.0,
|
||||||
'P' | 'p' if radix == 16 => 2u as $T,
|
'P' | 'p' if radix == 16 => 2.0,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -254,12 +254,12 @@ impl<T> Option<T> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let mut x = Some(2u);
|
/// let mut x = Some(2);
|
||||||
/// match x.as_mut() {
|
/// match x.as_mut() {
|
||||||
/// Some(v) => *v = 42,
|
/// Some(v) => *v = 42,
|
||||||
/// None => {},
|
/// None => {},
|
||||||
/// }
|
/// }
|
||||||
/// assert_eq!(x, Some(42u));
|
/// assert_eq!(x, Some(42));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -385,9 +385,9 @@ impl<T> Option<T> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let k = 10u;
|
/// let k = 10i32;
|
||||||
/// assert_eq!(Some(4u).unwrap_or_else(|| 2 * k), 4u);
|
/// assert_eq!(Some(4).unwrap_or_else(|| 2 * k), 4);
|
||||||
/// assert_eq!(None.unwrap_or_else(|| 2 * k), 20u);
|
/// assert_eq!(None.unwrap_or_else(|| 2 * k), 20);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -428,10 +428,10 @@ impl<T> Option<T> {
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let x = Some("foo");
|
/// let x = Some("foo");
|
||||||
/// assert_eq!(x.map_or(42u, |v| v.len()), 3u);
|
/// assert_eq!(x.map_or(42, |v| v.len()), 3);
|
||||||
///
|
///
|
||||||
/// let x: Option<&str> = None;
|
/// let x: Option<&str> = None;
|
||||||
/// assert_eq!(x.map_or(42u, |v| v.len()), 42u);
|
/// assert_eq!(x.map_or(42, |v| v.len()), 42);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -447,13 +447,13 @@ impl<T> Option<T> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let k = 21u;
|
/// let k = 21;
|
||||||
///
|
///
|
||||||
/// let x = Some("foo");
|
/// let x = Some("foo");
|
||||||
/// assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 3u);
|
/// assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 3);
|
||||||
///
|
///
|
||||||
/// let x: Option<&str> = None;
|
/// let x: Option<&str> = None;
|
||||||
/// assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 42u);
|
/// assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 42);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -471,10 +471,10 @@ impl<T> Option<T> {
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let x = Some("foo");
|
/// let x = Some("foo");
|
||||||
/// assert_eq!(x.ok_or(0i), Ok("foo"));
|
/// assert_eq!(x.ok_or(0), Ok("foo"));
|
||||||
///
|
///
|
||||||
/// let x: Option<&str> = None;
|
/// let x: Option<&str> = None;
|
||||||
/// assert_eq!(x.ok_or(0i), Err(0i));
|
/// assert_eq!(x.ok_or(0), Err(0));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "core")]
|
#[unstable(feature = "core")]
|
||||||
|
@ -492,10 +492,10 @@ impl<T> Option<T> {
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let x = Some("foo");
|
/// let x = Some("foo");
|
||||||
/// assert_eq!(x.ok_or_else(|| 0i), Ok("foo"));
|
/// assert_eq!(x.ok_or_else(|| 0), Ok("foo"));
|
||||||
///
|
///
|
||||||
/// let x: Option<&str> = None;
|
/// let x: Option<&str> = None;
|
||||||
/// assert_eq!(x.ok_or_else(|| 0i), Err(0i));
|
/// assert_eq!(x.ok_or_else(|| 0), Err(0));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "core")]
|
#[unstable(feature = "core")]
|
||||||
|
@ -515,7 +515,7 @@ impl<T> Option<T> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let x = Some(4u);
|
/// let x = Some(4);
|
||||||
/// assert_eq!(x.iter().next(), Some(&4));
|
/// assert_eq!(x.iter().next(), Some(&4));
|
||||||
///
|
///
|
||||||
/// let x: Option<uint> = None;
|
/// let x: Option<uint> = None;
|
||||||
|
@ -532,9 +532,9 @@ impl<T> Option<T> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let mut x = Some(4u);
|
/// let mut x = Some(4);
|
||||||
/// match x.iter_mut().next() {
|
/// match x.iter_mut().next() {
|
||||||
/// Some(&mut ref mut v) => *v = 42u,
|
/// Some(&mut ref mut v) => *v = 42,
|
||||||
/// None => {},
|
/// None => {},
|
||||||
/// }
|
/// }
|
||||||
/// assert_eq!(x, Some(42));
|
/// assert_eq!(x, Some(42));
|
||||||
|
@ -577,7 +577,7 @@ impl<T> Option<T> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let x = Some(2u);
|
/// let x = Some(2);
|
||||||
/// let y: Option<&str> = None;
|
/// let y: Option<&str> = None;
|
||||||
/// assert_eq!(x.and(y), None);
|
/// assert_eq!(x.and(y), None);
|
||||||
///
|
///
|
||||||
|
@ -585,7 +585,7 @@ impl<T> Option<T> {
|
||||||
/// let y = Some("foo");
|
/// let y = Some("foo");
|
||||||
/// assert_eq!(x.and(y), None);
|
/// assert_eq!(x.and(y), None);
|
||||||
///
|
///
|
||||||
/// let x = Some(2u);
|
/// let x = Some(2);
|
||||||
/// let y = Some("foo");
|
/// let y = Some("foo");
|
||||||
/// assert_eq!(x.and(y), Some("foo"));
|
/// assert_eq!(x.and(y), Some("foo"));
|
||||||
///
|
///
|
||||||
|
@ -630,17 +630,17 @@ impl<T> Option<T> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let x = Some(2u);
|
/// let x = Some(2);
|
||||||
/// let y = None;
|
/// let y = None;
|
||||||
/// assert_eq!(x.or(y), Some(2u));
|
/// assert_eq!(x.or(y), Some(2));
|
||||||
///
|
///
|
||||||
/// let x = None;
|
/// let x = None;
|
||||||
/// let y = Some(100u);
|
/// let y = Some(100);
|
||||||
/// assert_eq!(x.or(y), Some(100u));
|
/// assert_eq!(x.or(y), Some(100));
|
||||||
///
|
///
|
||||||
/// let x = Some(2u);
|
/// let x = Some(2);
|
||||||
/// let y = Some(100u);
|
/// let y = Some(100);
|
||||||
/// assert_eq!(x.or(y), Some(2u));
|
/// assert_eq!(x.or(y), Some(2));
|
||||||
///
|
///
|
||||||
/// let x: Option<uint> = None;
|
/// let x: Option<uint> = None;
|
||||||
/// let y = None;
|
/// let y = None;
|
||||||
|
@ -686,7 +686,7 @@ impl<T> Option<T> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let mut x = Some(2u);
|
/// let mut x = Some(2);
|
||||||
/// x.take();
|
/// x.take();
|
||||||
/// assert_eq!(x, None);
|
/// assert_eq!(x, None);
|
||||||
///
|
///
|
||||||
|
@ -731,8 +731,8 @@ impl<T: Default> Option<T> {
|
||||||
/// let good_year = good_year_from_input.parse().unwrap_or_default();
|
/// let good_year = good_year_from_input.parse().unwrap_or_default();
|
||||||
/// let bad_year = bad_year_from_input.parse().unwrap_or_default();
|
/// let bad_year = bad_year_from_input.parse().unwrap_or_default();
|
||||||
///
|
///
|
||||||
/// assert_eq!(1909i, good_year);
|
/// assert_eq!(1909, good_year);
|
||||||
/// assert_eq!(0i, bad_year);
|
/// assert_eq!(0, bad_year);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -898,12 +898,12 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use std::uint;
|
/// use std::uint;
|
||||||
///
|
///
|
||||||
/// let v = vec!(1u, 2u);
|
/// let v = vec!(1, 2);
|
||||||
/// let res: Option<Vec<uint>> = v.iter().map(|&x: &uint|
|
/// let res: Option<Vec<uint>> = v.iter().map(|&x: &uint|
|
||||||
/// if x == uint::MAX { None }
|
/// if x == uint::MAX { None }
|
||||||
/// else { Some(x + 1) }
|
/// else { Some(x + 1) }
|
||||||
/// ).collect();
|
/// ).collect();
|
||||||
/// assert!(res == Some(vec!(2u, 3u)));
|
/// assert!(res == Some(vec!(2, 3)));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
|
@ -229,7 +229,7 @@
|
||||||
use self::Result::{Ok, Err};
|
use self::Result::{Ok, Err};
|
||||||
|
|
||||||
use clone::Clone;
|
use clone::Clone;
|
||||||
use fmt::Display;
|
use fmt::Debug;
|
||||||
use iter::{Iterator, IteratorExt, DoubleEndedIterator, FromIterator, ExactSizeIterator};
|
use iter::{Iterator, IteratorExt, DoubleEndedIterator, FromIterator, ExactSizeIterator};
|
||||||
use ops::{FnMut, FnOnce};
|
use ops::{FnMut, FnOnce};
|
||||||
use option::Option::{self, None, Some};
|
use option::Option::{self, None, Some};
|
||||||
|
@ -483,8 +483,8 @@ impl<T, E> Result<T, E> {
|
||||||
/// ```
|
/// ```
|
||||||
/// fn stringify(x: uint) -> String { format!("error code: {}", x) }
|
/// fn stringify(x: uint) -> String { format!("error code: {}", x) }
|
||||||
///
|
///
|
||||||
/// let x: Result<uint, uint> = Ok(2u);
|
/// let x: Result<uint, uint> = Ok(2);
|
||||||
/// assert_eq!(x.map_err(stringify), Ok(2u));
|
/// assert_eq!(x.map_err(stringify), Ok(2));
|
||||||
///
|
///
|
||||||
/// let x: Result<uint, uint> = Err(13);
|
/// let x: Result<uint, uint> = Err(13);
|
||||||
/// assert_eq!(x.map_err(stringify), Err("error code: 13".to_string()));
|
/// assert_eq!(x.map_err(stringify), Err("error code: 13".to_string()));
|
||||||
|
@ -547,7 +547,7 @@ impl<T, E> Result<T, E> {
|
||||||
/// ```
|
/// ```
|
||||||
/// let x: Result<uint, &str> = Ok(5);
|
/// let x: Result<uint, &str> = Ok(5);
|
||||||
/// let v: Vec<uint> = x.into_iter().collect();
|
/// let v: Vec<uint> = x.into_iter().collect();
|
||||||
/// assert_eq!(v, vec![5u]);
|
/// assert_eq!(v, vec![5]);
|
||||||
///
|
///
|
||||||
/// let x: Result<uint, &str> = Err("nothing!");
|
/// let x: Result<uint, &str> = Err("nothing!");
|
||||||
/// let v: Vec<uint> = x.into_iter().collect();
|
/// let v: Vec<uint> = x.into_iter().collect();
|
||||||
|
@ -677,9 +677,9 @@ impl<T, E> Result<T, E> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let optb = 2u;
|
/// let optb = 2;
|
||||||
/// let x: Result<uint, &str> = Ok(9u);
|
/// let x: Result<uint, &str> = Ok(9);
|
||||||
/// assert_eq!(x.unwrap_or(optb), 9u);
|
/// assert_eq!(x.unwrap_or(optb), 9);
|
||||||
///
|
///
|
||||||
/// let x: Result<uint, &str> = Err("error");
|
/// let x: Result<uint, &str> = Err("error");
|
||||||
/// assert_eq!(x.unwrap_or(optb), optb);
|
/// assert_eq!(x.unwrap_or(optb), optb);
|
||||||
|
@ -701,8 +701,8 @@ impl<T, E> Result<T, E> {
|
||||||
/// ```
|
/// ```
|
||||||
/// fn count(x: &str) -> uint { x.len() }
|
/// fn count(x: &str) -> uint { x.len() }
|
||||||
///
|
///
|
||||||
/// assert_eq!(Ok(2u).unwrap_or_else(count), 2u);
|
/// assert_eq!(Ok(2).unwrap_or_else(count), 2);
|
||||||
/// assert_eq!(Err("foo").unwrap_or_else(count), 3u);
|
/// assert_eq!(Err("foo").unwrap_or_else(count), 3);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -715,7 +715,7 @@ impl<T, E> Result<T, E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T, E: Display> Result<T, E> {
|
impl<T, E: Debug> Result<T, E> {
|
||||||
/// Unwraps a result, yielding the content of an `Ok`.
|
/// Unwraps a result, yielding the content of an `Ok`.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
|
@ -726,8 +726,8 @@ impl<T, E: Display> Result<T, E> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let x: Result<uint, &str> = Ok(2u);
|
/// let x: Result<uint, &str> = Ok(2);
|
||||||
/// assert_eq!(x.unwrap(), 2u);
|
/// assert_eq!(x.unwrap(), 2);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```{.should_fail}
|
/// ```{.should_fail}
|
||||||
|
@ -740,13 +740,13 @@ impl<T, E: Display> Result<T, E> {
|
||||||
match self {
|
match self {
|
||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
Err(e) =>
|
Err(e) =>
|
||||||
panic!("called `Result::unwrap()` on an `Err` value: {}", e)
|
panic!("called `Result::unwrap()` on an `Err` value: {:?}", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: Display, E> Result<T, E> {
|
impl<T: Debug, E> Result<T, E> {
|
||||||
/// Unwraps a result, yielding the content of an `Err`.
|
/// Unwraps a result, yielding the content of an `Err`.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
|
@ -757,7 +757,7 @@ impl<T: Display, E> Result<T, E> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```{.should_fail}
|
/// ```{.should_fail}
|
||||||
/// let x: Result<uint, &str> = Ok(2u);
|
/// let x: Result<uint, &str> = Ok(2);
|
||||||
/// x.unwrap_err(); // panics with `2`
|
/// x.unwrap_err(); // panics with `2`
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
@ -770,7 +770,7 @@ impl<T: Display, E> Result<T, E> {
|
||||||
pub fn unwrap_err(self) -> E {
|
pub fn unwrap_err(self) -> E {
|
||||||
match self {
|
match self {
|
||||||
Ok(t) =>
|
Ok(t) =>
|
||||||
panic!("called `Result::unwrap_err()` on an `Ok` value: {}", t),
|
panic!("called `Result::unwrap_err()` on an `Ok` value: {:?}", t),
|
||||||
Err(e) => e
|
Err(e) => e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -898,12 +898,12 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use std::uint;
|
/// use std::uint;
|
||||||
///
|
///
|
||||||
/// let v = vec!(1u, 2u);
|
/// let v = vec!(1, 2);
|
||||||
/// let res: Result<Vec<uint>, &'static str> = v.iter().map(|&x: &uint|
|
/// let res: Result<Vec<uint>, &'static str> = v.iter().map(|&x: &uint|
|
||||||
/// if x == uint::MAX { Err("Overflow!") }
|
/// if x == uint::MAX { Err("Overflow!") }
|
||||||
/// else { Ok(x + 1) }
|
/// else { Ok(x + 1) }
|
||||||
/// ).collect();
|
/// ).collect();
|
||||||
/// assert!(res == Ok(vec!(2u, 3u)));
|
/// assert!(res == Ok(vec!(2, 3)));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_iter<I: Iterator<Item=Result<A, E>>>(iter: I) -> Result<V, E> {
|
fn from_iter<I: Iterator<Item=Result<A, E>>>(iter: I) -> Result<V, E> {
|
||||||
|
|
|
@ -654,7 +654,7 @@ macro_rules! iterator {
|
||||||
self.ptr = transmute(self.ptr as uint + 1);
|
self.ptr = transmute(self.ptr as uint + 1);
|
||||||
|
|
||||||
// Use a non-null pointer value
|
// Use a non-null pointer value
|
||||||
Some(transmute(1u))
|
Some(&mut *(1 as *mut _))
|
||||||
} else {
|
} else {
|
||||||
let old = self.ptr;
|
let old = self.ptr;
|
||||||
self.ptr = self.ptr.offset(1);
|
self.ptr = self.ptr.offset(1);
|
||||||
|
@ -688,7 +688,7 @@ macro_rules! iterator {
|
||||||
self.end = transmute(self.end as uint - 1);
|
self.end = transmute(self.end as uint - 1);
|
||||||
|
|
||||||
// Use a non-null pointer value
|
// Use a non-null pointer value
|
||||||
Some(transmute(1u))
|
Some(&mut *(1 as *mut _))
|
||||||
} else {
|
} else {
|
||||||
self.end = self.end.offset(-1);
|
self.end = self.end.offset(-1);
|
||||||
|
|
||||||
|
@ -796,7 +796,7 @@ impl<'a, T> RandomAccessIterator for Iter<'a, T> {
|
||||||
if index < self.indexable() {
|
if index < self.indexable() {
|
||||||
if mem::size_of::<T>() == 0 {
|
if mem::size_of::<T>() == 0 {
|
||||||
// Use a non-null pointer value
|
// Use a non-null pointer value
|
||||||
Some(transmute(1u))
|
Some(&mut *(1 as *mut _))
|
||||||
} else {
|
} else {
|
||||||
Some(transmute(self.ptr.offset(index as int)))
|
Some(transmute(self.ptr.offset(index as int)))
|
||||||
}
|
}
|
||||||
|
@ -1176,7 +1176,7 @@ impl<'a, T> Iterator for Windows<'a, T> {
|
||||||
(0, Some(0))
|
(0, Some(0))
|
||||||
} else {
|
} else {
|
||||||
let x = self.v.len() - self.size;
|
let x = self.v.len() - self.size;
|
||||||
(x.saturating_add(1), x.checked_add(1u))
|
(x.saturating_add(1), x.checked_add(1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,9 +202,9 @@ pub unsafe fn from_utf8_unchecked<'a>(v: &'a [u8]) -> &'a str {
|
||||||
reason = "use std::ffi::c_str_to_bytes + str::from_utf8")]
|
reason = "use std::ffi::c_str_to_bytes + str::from_utf8")]
|
||||||
pub unsafe fn from_c_str(s: *const i8) -> &'static str {
|
pub unsafe fn from_c_str(s: *const i8) -> &'static str {
|
||||||
let s = s as *const u8;
|
let s = s as *const u8;
|
||||||
let mut len = 0u;
|
let mut len = 0;
|
||||||
while *s.offset(len as int) != 0 {
|
while *s.offset(len as int) != 0 {
|
||||||
len += 1u;
|
len += 1;
|
||||||
}
|
}
|
||||||
let v: &'static [u8] = ::mem::transmute(Slice { data: s, len: len });
|
let v: &'static [u8] = ::mem::transmute(Slice { data: s, len: len });
|
||||||
from_utf8(v).ok().expect("from_c_str passed invalid utf-8 data")
|
from_utf8(v).ok().expect("from_c_str passed invalid utf-8 data")
|
||||||
|
@ -310,16 +310,14 @@ fn unwrap_or_0(opt: Option<&u8>) -> u8 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
/// Reads the next code point out of a byte iterator (assuming a
|
||||||
impl<'a> Iterator for Chars<'a> {
|
/// UTF-8-like encoding).
|
||||||
type Item = char;
|
#[unstable(feature = "core")]
|
||||||
|
pub fn next_code_point(bytes: &mut slice::Iter<u8>) -> Option<u32> {
|
||||||
#[inline]
|
// Decode UTF-8
|
||||||
fn next(&mut self) -> Option<char> {
|
let x = match bytes.next() {
|
||||||
// Decode UTF-8, using the valid UTF-8 invariant
|
|
||||||
let x = match self.iter.next() {
|
|
||||||
None => return None,
|
None => return None,
|
||||||
Some(&next_byte) if next_byte < 128 => return Some(next_byte as char),
|
Some(&next_byte) if next_byte < 128 => return Some(next_byte as u32),
|
||||||
Some(&next_byte) => next_byte,
|
Some(&next_byte) => next_byte,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -327,26 +325,37 @@ impl<'a> Iterator for Chars<'a> {
|
||||||
// Decode from a byte combination out of: [[[x y] z] w]
|
// Decode from a byte combination out of: [[[x y] z] w]
|
||||||
// NOTE: Performance is sensitive to the exact formulation here
|
// 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(self.iter.next());
|
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 {
|
if x >= 0xE0 {
|
||||||
// [[x y z] w] case
|
// [[x y z] w] case
|
||||||
// 5th bit in 0xE0 .. 0xEF is always clear, so `init` is still valid
|
// 5th bit in 0xE0 .. 0xEF is always clear, so `init` is still valid
|
||||||
let z = unwrap_or_0(self.iter.next());
|
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;
|
ch = init << 12 | y_z;
|
||||||
if x >= 0xF0 {
|
if x >= 0xF0 {
|
||||||
// [x y z w] case
|
// [x y z w] case
|
||||||
// use only the lower 3 bits of `init`
|
// use only the lower 3 bits of `init`
|
||||||
let w = unwrap_or_0(self.iter.next());
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some(ch)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a> Iterator for Chars<'a> {
|
||||||
|
type Item = char;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> Option<char> {
|
||||||
|
next_code_point(&mut self.iter).map(|ch| {
|
||||||
// str invariant says `ch` is a valid Unicode Scalar Value
|
// str invariant says `ch` is a valid Unicode Scalar Value
|
||||||
unsafe {
|
unsafe {
|
||||||
Some(mem::transmute(ch))
|
mem::transmute(ch)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1509,7 +1518,7 @@ impl StrExt for str {
|
||||||
None => "",
|
None => "",
|
||||||
Some(last) => {
|
Some(last) => {
|
||||||
let next = self.char_range_at(last).next;
|
let next = self.char_range_at(last).next;
|
||||||
unsafe { self.slice_unchecked(0u, next) }
|
unsafe { self.slice_unchecked(0, next) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1525,25 +1534,8 @@ impl StrExt for str {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn char_range_at(&self, i: uint) -> CharRange {
|
fn char_range_at(&self, i: uint) -> CharRange {
|
||||||
if self.as_bytes()[i] < 128u8 {
|
let (c, n) = char_range_at_raw(self.as_bytes(), i);
|
||||||
return CharRange {ch: self.as_bytes()[i] as char, next: i + 1 };
|
CharRange { ch: unsafe { mem::transmute(c) }, next: n }
|
||||||
}
|
|
||||||
|
|
||||||
// Multibyte case is a fn to allow char_range_at to inline cleanly
|
|
||||||
fn multibyte_char_range_at(s: &str, i: uint) -> CharRange {
|
|
||||||
let mut val = s.as_bytes()[i] as u32;
|
|
||||||
let w = UTF8_CHAR_WIDTH[val as uint] as uint;
|
|
||||||
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]); }
|
|
||||||
|
|
||||||
return CharRange {ch: unsafe { mem::transmute(val) }, next: i + w};
|
|
||||||
}
|
|
||||||
|
|
||||||
return multibyte_char_range_at(self, i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1559,7 +1551,7 @@ impl StrExt for str {
|
||||||
fn multibyte_char_range_at_reverse(s: &str, mut i: uint) -> CharRange {
|
fn multibyte_char_range_at_reverse(s: &str, mut i: uint) -> CharRange {
|
||||||
// while there is a previous byte == 10......
|
// while there is a previous byte == 10......
|
||||||
while i > 0 && s.as_bytes()[i] & !CONT_MASK == TAG_CONT_U8 {
|
while i > 0 && s.as_bytes()[i] & !CONT_MASK == TAG_CONT_U8 {
|
||||||
i -= 1u;
|
i -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut val = s.as_bytes()[i] as u32;
|
let mut val = s.as_bytes()[i] as u32;
|
||||||
|
@ -1629,7 +1621,7 @@ impl StrExt for str {
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let CharRange {ch, next} = self.char_range_at(0u);
|
let CharRange {ch, next} = self.char_range_at(0);
|
||||||
let next_s = unsafe { self.slice_unchecked(next, self.len()) };
|
let next_s = unsafe { self.slice_unchecked(next, self.len()) };
|
||||||
Some((ch, next_s))
|
Some((ch, next_s))
|
||||||
}
|
}
|
||||||
|
@ -1661,6 +1653,32 @@ impl StrExt for str {
|
||||||
fn parse<T: FromStr>(&self) -> Option<T> { FromStr::from_str(self) }
|
fn parse<T: FromStr>(&self) -> Option<T> { FromStr::from_str(self) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pluck a code point out of a UTF-8-like byte slice and return the
|
||||||
|
/// index of the next code point.
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "core")]
|
||||||
|
pub fn char_range_at_raw(bytes: &[u8], i: uint) -> (u32, usize) {
|
||||||
|
if bytes[i] < 128u8 {
|
||||||
|
return (bytes[i] as u32, i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multibyte case is a fn to allow char_range_at to inline cleanly
|
||||||
|
fn multibyte_char_range_at(bytes: &[u8], i: uint) -> (u32, usize) {
|
||||||
|
let mut val = bytes[i] as u32;
|
||||||
|
let w = UTF8_CHAR_WIDTH[val as uint] as uint;
|
||||||
|
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]); }
|
||||||
|
|
||||||
|
return (val, i + w);
|
||||||
|
}
|
||||||
|
|
||||||
|
multibyte_char_range_at(bytes, i)
|
||||||
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<'a> Default for &'a str {
|
impl<'a> Default for &'a str {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
|
@ -32,10 +32,12 @@ use middle::subst::Substs;
|
||||||
use middle::ty::{self, Ty};
|
use middle::ty::{self, Ty};
|
||||||
use middle::{def, pat_util, stability};
|
use middle::{def, pat_util, stability};
|
||||||
use middle::const_eval::{eval_const_expr_partial, const_int, const_uint};
|
use middle::const_eval::{eval_const_expr_partial, const_int, const_uint};
|
||||||
|
use middle::cfg;
|
||||||
use util::ppaux::{ty_to_string};
|
use util::ppaux::{ty_to_string};
|
||||||
use util::nodemap::{FnvHashMap, NodeSet};
|
use util::nodemap::{FnvHashMap, NodeSet};
|
||||||
use lint::{Context, LintPass, LintArray, Lint};
|
use lint::{Level, Context, LintPass, LintArray, Lint};
|
||||||
|
|
||||||
|
use std::collections::BitvSet;
|
||||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||||
use std::num::SignedInt;
|
use std::num::SignedInt;
|
||||||
use std::{cmp, slice};
|
use std::{cmp, slice};
|
||||||
|
@ -44,7 +46,7 @@ use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
|
||||||
use syntax::{abi, ast, ast_map};
|
use syntax::{abi, ast, ast_map};
|
||||||
use syntax::ast_util::is_shift_binop;
|
use syntax::ast_util::is_shift_binop;
|
||||||
use syntax::attr::{self, AttrMetaMethods};
|
use syntax::attr::{self, AttrMetaMethods};
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::{self, Span};
|
||||||
use syntax::parse::token;
|
use syntax::parse::token;
|
||||||
use syntax::ast::{TyIs, TyUs, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64};
|
use syntax::ast::{TyIs, TyUs, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64};
|
||||||
use syntax::ast_util;
|
use syntax::ast_util;
|
||||||
|
@ -185,7 +187,7 @@ impl LintPass for TypeLimits {
|
||||||
"comparison is useless due to type limits");
|
"comparison is useless due to type limits");
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_shift_binop(binop) {
|
if is_shift_binop(binop.node) {
|
||||||
let opt_ty_bits = match ty::expr_ty(cx.tcx, &**l).sty {
|
let opt_ty_bits = match ty::expr_ty(cx.tcx, &**l).sty {
|
||||||
ty::ty_int(t) => Some(int_ty_bits(t, cx.sess().target.int_type)),
|
ty::ty_int(t) => Some(int_ty_bits(t, cx.sess().target.int_type)),
|
||||||
ty::ty_uint(t) => Some(uint_ty_bits(t, cx.sess().target.uint_type)),
|
ty::ty_uint(t) => Some(uint_ty_bits(t, cx.sess().target.uint_type)),
|
||||||
|
@ -272,7 +274,7 @@ impl LintPass for TypeLimits {
|
||||||
|
|
||||||
fn is_valid<T:cmp::PartialOrd>(binop: ast::BinOp, v: T,
|
fn is_valid<T:cmp::PartialOrd>(binop: ast::BinOp, v: T,
|
||||||
min: T, max: T) -> bool {
|
min: T, max: T) -> bool {
|
||||||
match binop {
|
match binop.node {
|
||||||
ast::BiLt => v > min && v <= max,
|
ast::BiLt => v > min && v <= max,
|
||||||
ast::BiLe => v >= min && v < max,
|
ast::BiLe => v >= min && v < max,
|
||||||
ast::BiGt => v >= min && v < max,
|
ast::BiGt => v >= min && v < max,
|
||||||
|
@ -283,13 +285,13 @@ impl LintPass for TypeLimits {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rev_binop(binop: ast::BinOp) -> ast::BinOp {
|
fn rev_binop(binop: ast::BinOp) -> ast::BinOp {
|
||||||
match binop {
|
codemap::respan(binop.span, match binop.node {
|
||||||
ast::BiLt => ast::BiGt,
|
ast::BiLt => ast::BiGt,
|
||||||
ast::BiLe => ast::BiGe,
|
ast::BiLe => ast::BiGe,
|
||||||
ast::BiGt => ast::BiLt,
|
ast::BiGt => ast::BiLt,
|
||||||
ast::BiGe => ast::BiLe,
|
ast::BiGe => ast::BiLe,
|
||||||
_ => binop
|
_ => return binop
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// for int & uint, be conservative with the warnings, so that the
|
// for int & uint, be conservative with the warnings, so that the
|
||||||
|
@ -382,7 +384,7 @@ impl LintPass for TypeLimits {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_comparison(binop: ast::BinOp) -> bool {
|
fn is_comparison(binop: ast::BinOp) -> bool {
|
||||||
match binop {
|
match binop.node {
|
||||||
ast::BiEq | ast::BiLt | ast::BiLe |
|
ast::BiEq | ast::BiLt | ast::BiLe |
|
||||||
ast::BiNe | ast::BiGe | ast::BiGt => true,
|
ast::BiNe | ast::BiGe | ast::BiGt => true,
|
||||||
_ => false
|
_ => false
|
||||||
|
@ -1674,6 +1676,194 @@ impl LintPass for Stability {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare_lint! {
|
||||||
|
pub UNCONDITIONAL_RECURSION,
|
||||||
|
Warn,
|
||||||
|
"functions that cannot return without calling themselves"
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy)]
|
||||||
|
pub struct UnconditionalRecursion;
|
||||||
|
|
||||||
|
|
||||||
|
impl LintPass for UnconditionalRecursion {
|
||||||
|
fn get_lints(&self) -> LintArray {
|
||||||
|
lint_array![UNCONDITIONAL_RECURSION]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_fn(&mut self, cx: &Context, fn_kind: visit::FnKind, _: &ast::FnDecl,
|
||||||
|
blk: &ast::Block, sp: Span, id: ast::NodeId) {
|
||||||
|
type F = for<'tcx> fn(&ty::ctxt<'tcx>,
|
||||||
|
ast::NodeId, ast::NodeId, ast::Ident, ast::NodeId) -> bool;
|
||||||
|
|
||||||
|
let (name, checker) = match fn_kind {
|
||||||
|
visit::FkItemFn(name, _, _, _) => (name, id_refers_to_this_fn as F),
|
||||||
|
visit::FkMethod(name, _, _) => (name, id_refers_to_this_method as F),
|
||||||
|
// closures can't recur, so they don't matter.
|
||||||
|
visit::FkFnBlock => return
|
||||||
|
};
|
||||||
|
|
||||||
|
let impl_def_id = ty::impl_of_method(cx.tcx, ast_util::local_def(id))
|
||||||
|
.unwrap_or(ast_util::local_def(ast::DUMMY_NODE_ID));
|
||||||
|
assert!(ast_util::is_local(impl_def_id));
|
||||||
|
let impl_node_id = impl_def_id.node;
|
||||||
|
|
||||||
|
// Walk through this function (say `f`) looking to see if
|
||||||
|
// every possible path references itself, i.e. the function is
|
||||||
|
// called recursively unconditionally. This is done by trying
|
||||||
|
// to find a path from the entry node to the exit node that
|
||||||
|
// *doesn't* call `f` by traversing from the entry while
|
||||||
|
// pretending that calls of `f` are sinks (i.e. ignoring any
|
||||||
|
// exit edges from them).
|
||||||
|
//
|
||||||
|
// NB. this has an edge case with non-returning statements,
|
||||||
|
// like `loop {}` or `panic!()`: control flow never reaches
|
||||||
|
// the exit node through these, so one can have a function
|
||||||
|
// that never actually calls itselfs but is still picked up by
|
||||||
|
// this lint:
|
||||||
|
//
|
||||||
|
// fn f(cond: bool) {
|
||||||
|
// if !cond { panic!() } // could come from `assert!(cond)`
|
||||||
|
// f(false)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// In general, functions of that form may be able to call
|
||||||
|
// itself a finite number of times and then diverge. The lint
|
||||||
|
// considers this to be an error for two reasons, (a) it is
|
||||||
|
// easier to implement, and (b) it seems rare to actually want
|
||||||
|
// to have behaviour like the above, rather than
|
||||||
|
// e.g. accidentally recurring after an assert.
|
||||||
|
|
||||||
|
let cfg = cfg::CFG::new(cx.tcx, blk);
|
||||||
|
|
||||||
|
let mut work_queue = vec![cfg.entry];
|
||||||
|
let mut reached_exit_without_self_call = false;
|
||||||
|
let mut self_call_spans = vec![];
|
||||||
|
let mut visited = BitvSet::new();
|
||||||
|
|
||||||
|
while let Some(idx) = work_queue.pop() {
|
||||||
|
let cfg_id = idx.node_id();
|
||||||
|
if idx == cfg.exit {
|
||||||
|
// found a path!
|
||||||
|
reached_exit_without_self_call = true;
|
||||||
|
break
|
||||||
|
} else if visited.contains(&cfg_id) {
|
||||||
|
// already done
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
visited.insert(cfg_id);
|
||||||
|
let node_id = cfg.graph.node_data(idx).id;
|
||||||
|
|
||||||
|
// is this a recursive call?
|
||||||
|
if node_id != ast::DUMMY_NODE_ID && checker(cx.tcx, impl_node_id, id, name, node_id) {
|
||||||
|
|
||||||
|
self_call_spans.push(cx.tcx.map.span(node_id));
|
||||||
|
// this is a self call, so we shouldn't explore past
|
||||||
|
// this node in the CFG.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// add the successors of this node to explore the graph further.
|
||||||
|
cfg.graph.each_outgoing_edge(idx, |_, edge| {
|
||||||
|
let target_idx = edge.target();
|
||||||
|
let target_cfg_id = target_idx.node_id();
|
||||||
|
if !visited.contains(&target_cfg_id) {
|
||||||
|
work_queue.push(target_idx)
|
||||||
|
}
|
||||||
|
true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// check the number of sell calls because a function that
|
||||||
|
// doesn't return (e.g. calls a `-> !` function or `loop { /*
|
||||||
|
// no break */ }`) shouldn't be linted unless it actually
|
||||||
|
// recurs.
|
||||||
|
if !reached_exit_without_self_call && self_call_spans.len() > 0 {
|
||||||
|
cx.span_lint(UNCONDITIONAL_RECURSION, sp,
|
||||||
|
"function cannot return without recurring");
|
||||||
|
|
||||||
|
// FIXME #19668: these could be span_lint_note's instead of this manual guard.
|
||||||
|
if cx.current_level(UNCONDITIONAL_RECURSION) != Level::Allow {
|
||||||
|
let sess = cx.sess();
|
||||||
|
// offer some help to the programmer.
|
||||||
|
for call in self_call_spans.iter() {
|
||||||
|
sess.span_note(*call, "recursive call site")
|
||||||
|
}
|
||||||
|
sess.span_help(sp, "a `loop` may express intention better if this is on purpose")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// all done
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Functions for identifying if the given NodeId `id`
|
||||||
|
// represents a call to the function `fn_id`/method
|
||||||
|
// `method_id`.
|
||||||
|
|
||||||
|
fn id_refers_to_this_fn<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||||
|
_: ast::NodeId,
|
||||||
|
fn_id: ast::NodeId,
|
||||||
|
_: ast::Ident,
|
||||||
|
id: ast::NodeId) -> bool {
|
||||||
|
tcx.def_map.borrow().get(&id)
|
||||||
|
.map_or(false, |def| {
|
||||||
|
let did = def.def_id();
|
||||||
|
ast_util::is_local(did) && did.node == fn_id
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the method call `id` refers to method `method_id`
|
||||||
|
// (with name `method_name` contained in impl `impl_id`).
|
||||||
|
fn id_refers_to_this_method<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||||
|
impl_id: ast::NodeId,
|
||||||
|
method_id: ast::NodeId,
|
||||||
|
method_name: ast::Ident,
|
||||||
|
id: ast::NodeId) -> bool {
|
||||||
|
let did = match tcx.method_map.borrow().get(&ty::MethodCall::expr(id)) {
|
||||||
|
None => return false,
|
||||||
|
Some(m) => match m.origin {
|
||||||
|
// There's no way to know if a method call via a
|
||||||
|
// vtable is recursion, so we assume it's not.
|
||||||
|
ty::MethodTraitObject(_) => return false,
|
||||||
|
|
||||||
|
// This `did` refers directly to the method definition.
|
||||||
|
ty::MethodStatic(did) | ty::MethodStaticUnboxedClosure(did) => did,
|
||||||
|
|
||||||
|
// MethodTypeParam are methods from traits:
|
||||||
|
|
||||||
|
// The `impl ... for ...` of this method call
|
||||||
|
// isn't known, e.g. it might be a default method
|
||||||
|
// in a trait, so we get the def-id of the trait
|
||||||
|
// method instead.
|
||||||
|
ty::MethodTypeParam(
|
||||||
|
ty::MethodParam { ref trait_ref, method_num, impl_def_id: None, }) => {
|
||||||
|
ty::trait_item(tcx, trait_ref.def_id, method_num).def_id()
|
||||||
|
}
|
||||||
|
|
||||||
|
// The `impl` is known, so we check that with a
|
||||||
|
// special case:
|
||||||
|
ty::MethodTypeParam(
|
||||||
|
ty::MethodParam { impl_def_id: Some(impl_def_id), .. }) => {
|
||||||
|
|
||||||
|
let name = match tcx.map.expect_expr(id).node {
|
||||||
|
ast::ExprMethodCall(ref sp_ident, _, _) => sp_ident.node,
|
||||||
|
_ => tcx.sess.span_bug(
|
||||||
|
tcx.map.span(id),
|
||||||
|
"non-method call expr behaving like a method call?")
|
||||||
|
};
|
||||||
|
// it matches if it comes from the same impl,
|
||||||
|
// and has the same method name.
|
||||||
|
return ast_util::is_local(impl_def_id)
|
||||||
|
&& impl_def_id.node == impl_id
|
||||||
|
&& method_name.name == name.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ast_util::is_local(did) && did.node == method_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
pub UNUSED_IMPORTS,
|
pub UNUSED_IMPORTS,
|
||||||
Warn,
|
Warn,
|
||||||
|
|
|
@ -212,6 +212,7 @@ impl LintStore {
|
||||||
MissingCopyImplementations,
|
MissingCopyImplementations,
|
||||||
UnstableFeatures,
|
UnstableFeatures,
|
||||||
Stability,
|
Stability,
|
||||||
|
UnconditionalRecursion,
|
||||||
);
|
);
|
||||||
|
|
||||||
add_builtin_with_new!(sess,
|
add_builtin_with_new!(sess,
|
||||||
|
|
|
@ -627,6 +627,7 @@ impl<'tcx> tr for MethodOrigin<'tcx> {
|
||||||
// def-id is already translated when we read it out
|
// def-id is already translated when we read it out
|
||||||
trait_ref: mp.trait_ref.clone(),
|
trait_ref: mp.trait_ref.clone(),
|
||||||
method_num: mp.method_num,
|
method_num: mp.method_num,
|
||||||
|
impl_def_id: mp.impl_def_id.tr(dcx),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -879,6 +880,16 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
|
||||||
try!(this.emit_struct_field("method_num", 0, |this| {
|
try!(this.emit_struct_field("method_num", 0, |this| {
|
||||||
this.emit_uint(p.method_num)
|
this.emit_uint(p.method_num)
|
||||||
}));
|
}));
|
||||||
|
try!(this.emit_struct_field("impl_def_id", 0, |this| {
|
||||||
|
this.emit_option(|this| {
|
||||||
|
match p.impl_def_id {
|
||||||
|
None => this.emit_option_none(),
|
||||||
|
Some(did) => this.emit_option_some(|this| {
|
||||||
|
Ok(this.emit_def_id(did))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}));
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1452,6 +1463,17 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
|
||||||
this.read_struct_field("method_num", 1, |this| {
|
this.read_struct_field("method_num", 1, |this| {
|
||||||
this.read_uint()
|
this.read_uint()
|
||||||
}).unwrap()
|
}).unwrap()
|
||||||
|
},
|
||||||
|
impl_def_id: {
|
||||||
|
this.read_struct_field("impl_def_id", 2, |this| {
|
||||||
|
this.read_option(|this, b| {
|
||||||
|
if b {
|
||||||
|
Ok(Some(this.read_def_id(dcx)))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}).unwrap()
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}).unwrap()
|
}).unwrap()
|
||||||
|
|
|
@ -372,7 +372,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||||
expr_exit
|
expr_exit
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprBinary(op, ref l, ref r) if ast_util::lazy_binop(op) => {
|
ast::ExprBinary(op, ref l, ref r) if ast_util::lazy_binop(op.node) => {
|
||||||
//
|
//
|
||||||
// [pred]
|
// [pred]
|
||||||
// |
|
// |
|
||||||
|
|
|
@ -400,7 +400,7 @@ pub fn eval_const_expr_partial(tcx: &ty::ctxt, e: &Expr) -> Result<const_val, St
|
||||||
match (eval_const_expr_partial(tcx, &**a),
|
match (eval_const_expr_partial(tcx, &**a),
|
||||||
eval_const_expr_partial(tcx, &**b)) {
|
eval_const_expr_partial(tcx, &**b)) {
|
||||||
(Ok(const_float(a)), Ok(const_float(b))) => {
|
(Ok(const_float(a)), Ok(const_float(b))) => {
|
||||||
match op {
|
match op.node {
|
||||||
ast::BiAdd => Ok(const_float(a + b)),
|
ast::BiAdd => Ok(const_float(a + b)),
|
||||||
ast::BiSub => Ok(const_float(a - b)),
|
ast::BiSub => Ok(const_float(a - b)),
|
||||||
ast::BiMul => Ok(const_float(a * b)),
|
ast::BiMul => Ok(const_float(a * b)),
|
||||||
|
@ -416,7 +416,7 @@ pub fn eval_const_expr_partial(tcx: &ty::ctxt, e: &Expr) -> Result<const_val, St
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Ok(const_int(a)), Ok(const_int(b))) => {
|
(Ok(const_int(a)), Ok(const_int(b))) => {
|
||||||
match op {
|
match op.node {
|
||||||
ast::BiAdd => Ok(const_int(a + b)),
|
ast::BiAdd => Ok(const_int(a + b)),
|
||||||
ast::BiSub => Ok(const_int(a - b)),
|
ast::BiSub => Ok(const_int(a - b)),
|
||||||
ast::BiMul => Ok(const_int(a * b)),
|
ast::BiMul => Ok(const_int(a * b)),
|
||||||
|
@ -443,7 +443,7 @@ pub fn eval_const_expr_partial(tcx: &ty::ctxt, e: &Expr) -> Result<const_val, St
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Ok(const_uint(a)), Ok(const_uint(b))) => {
|
(Ok(const_uint(a)), Ok(const_uint(b))) => {
|
||||||
match op {
|
match op.node {
|
||||||
ast::BiAdd => Ok(const_uint(a + b)),
|
ast::BiAdd => Ok(const_uint(a + b)),
|
||||||
ast::BiSub => Ok(const_uint(a - b)),
|
ast::BiSub => Ok(const_uint(a - b)),
|
||||||
ast::BiMul => Ok(const_uint(a * b)),
|
ast::BiMul => Ok(const_uint(a * b)),
|
||||||
|
@ -471,21 +471,21 @@ pub fn eval_const_expr_partial(tcx: &ty::ctxt, e: &Expr) -> Result<const_val, St
|
||||||
}
|
}
|
||||||
// shifts can have any integral type as their rhs
|
// shifts can have any integral type as their rhs
|
||||||
(Ok(const_int(a)), Ok(const_uint(b))) => {
|
(Ok(const_int(a)), Ok(const_uint(b))) => {
|
||||||
match op {
|
match op.node {
|
||||||
ast::BiShl => Ok(const_int(a << b as uint)),
|
ast::BiShl => Ok(const_int(a << b as uint)),
|
||||||
ast::BiShr => Ok(const_int(a >> b as uint)),
|
ast::BiShr => Ok(const_int(a >> b as uint)),
|
||||||
_ => Err("can't do this op on an int and uint".to_string())
|
_ => Err("can't do this op on an int and uint".to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Ok(const_uint(a)), Ok(const_int(b))) => {
|
(Ok(const_uint(a)), Ok(const_int(b))) => {
|
||||||
match op {
|
match op.node {
|
||||||
ast::BiShl => Ok(const_uint(a << b as uint)),
|
ast::BiShl => Ok(const_uint(a << b as uint)),
|
||||||
ast::BiShr => Ok(const_uint(a >> b as uint)),
|
ast::BiShr => Ok(const_uint(a >> b as uint)),
|
||||||
_ => Err("can't do this op on a uint and int".to_string())
|
_ => Err("can't do this op on a uint and int".to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Ok(const_bool(a)), Ok(const_bool(b))) => {
|
(Ok(const_bool(a)), Ok(const_bool(b))) => {
|
||||||
Ok(const_bool(match op {
|
Ok(const_bool(match op.node {
|
||||||
ast::BiAnd => a && b,
|
ast::BiAnd => a && b,
|
||||||
ast::BiOr => a || b,
|
ast::BiOr => a || b,
|
||||||
ast::BiBitXor => a ^ b,
|
ast::BiBitXor => a ^ b,
|
||||||
|
|
|
@ -568,7 +568,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprBinary(op, ref lhs, ref rhs) => {
|
ast::ExprBinary(op, ref lhs, ref rhs) => {
|
||||||
let pass_args = if ast_util::is_by_value_binop(op) {
|
let pass_args = if ast_util::is_by_value_binop(op.node) {
|
||||||
PassArgs::ByValue
|
PassArgs::ByValue
|
||||||
} else {
|
} else {
|
||||||
PassArgs::ByRef
|
PassArgs::ByRef
|
||||||
|
|
|
@ -504,7 +504,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
|
||||||
ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
|
ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
|
||||||
visit::walk_expr(ir, expr);
|
visit::walk_expr(ir, expr);
|
||||||
}
|
}
|
||||||
ast::ExprBinary(op, _, _) if ast_util::lazy_binop(op) => {
|
ast::ExprBinary(op, _, _) if ast_util::lazy_binop(op.node) => {
|
||||||
ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
|
ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
|
||||||
visit::walk_expr(ir, expr);
|
visit::walk_expr(ir, expr);
|
||||||
}
|
}
|
||||||
|
@ -1177,7 +1177,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||||
self.propagate_through_exprs(&exprs[], succ)
|
self.propagate_through_exprs(&exprs[], succ)
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprBinary(op, ref l, ref r) if ast_util::lazy_binop(op) => {
|
ast::ExprBinary(op, ref l, ref r) if ast_util::lazy_binop(op.node) => {
|
||||||
let r_succ = self.propagate_through_expr(&**r, succ);
|
let r_succ = self.propagate_through_expr(&**r, succ);
|
||||||
|
|
||||||
let ln = self.live_node(expr.id, expr.span);
|
let ln = self.live_node(expr.id, expr.span);
|
||||||
|
|
|
@ -22,7 +22,7 @@ use util::nodemap::{FnvHashMap, FnvHashSet, NodeMap};
|
||||||
use util::common::can_reach;
|
use util::common::can_reach;
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::{self, Span};
|
||||||
use syntax::{ast, visit};
|
use syntax::{ast, visit};
|
||||||
use syntax::ast::{Block, Item, FnDecl, NodeId, Arm, Pat, Stmt, Expr, Local};
|
use syntax::ast::{Block, Item, FnDecl, NodeId, Arm, Pat, Stmt, Expr, Local};
|
||||||
use syntax::ast_util::{stmt_id};
|
use syntax::ast_util::{stmt_id};
|
||||||
|
@ -496,8 +496,8 @@ fn resolve_expr(visitor: &mut RegionResolutionVisitor, expr: &ast::Expr) {
|
||||||
// scopes, meaning that temporaries cannot outlive them.
|
// scopes, meaning that temporaries cannot outlive them.
|
||||||
// This ensures fixed size stacks.
|
// This ensures fixed size stacks.
|
||||||
|
|
||||||
ast::ExprBinary(ast::BiAnd, _, ref r) |
|
ast::ExprBinary(codemap::Spanned { node: ast::BiAnd, .. }, _, ref r) |
|
||||||
ast::ExprBinary(ast::BiOr, _, ref r) => {
|
ast::ExprBinary(codemap::Spanned { node: ast::BiOr, .. }, _, ref r) => {
|
||||||
// For shortcircuiting operators, mark the RHS as a terminating
|
// For shortcircuiting operators, mark the RHS as a terminating
|
||||||
// scope since it only executes conditionally.
|
// scope since it only executes conditionally.
|
||||||
terminating(r.id);
|
terminating(r.id);
|
||||||
|
|
|
@ -453,9 +453,14 @@ pub struct MethodParam<'tcx> {
|
||||||
// never contains bound regions; those regions should have been
|
// never contains bound regions; those regions should have been
|
||||||
// instantiated with fresh variables at this point.
|
// instantiated with fresh variables at this point.
|
||||||
pub trait_ref: Rc<ty::TraitRef<'tcx>>,
|
pub trait_ref: Rc<ty::TraitRef<'tcx>>,
|
||||||
|
|
||||||
// index of uint in the list of methods for the trait
|
// index of uint in the list of methods for the trait
|
||||||
pub method_num: uint,
|
pub method_num: uint,
|
||||||
|
|
||||||
|
/// The impl for the trait from which the method comes. This
|
||||||
|
/// should only be used for certain linting/heuristic purposes
|
||||||
|
/// since there is no guarantee that this is Some in every
|
||||||
|
/// situation that it could/should be.
|
||||||
|
pub impl_def_id: Option<ast::DefId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// details for a method invoked with a receiver whose type is an object
|
// details for a method invoked with a receiver whose type is an object
|
||||||
|
@ -5716,7 +5721,7 @@ pub fn is_binopable<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>, op: ast::BinOp) -> bool
|
||||||
static opcat_mod: int = 8;
|
static opcat_mod: int = 8;
|
||||||
|
|
||||||
fn opcat(op: ast::BinOp) -> int {
|
fn opcat(op: ast::BinOp) -> int {
|
||||||
match op {
|
match op.node {
|
||||||
ast::BiAdd => opcat_add,
|
ast::BiAdd => opcat_add,
|
||||||
ast::BiSub => opcat_sub,
|
ast::BiSub => opcat_sub,
|
||||||
ast::BiMul => opcat_mult,
|
ast::BiMul => opcat_mult,
|
||||||
|
|
|
@ -310,7 +310,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::MethodOrigin<'tcx> {
|
||||||
ty::MethodTypeParam(ref param) => {
|
ty::MethodTypeParam(ref param) => {
|
||||||
ty::MethodTypeParam(ty::MethodParam {
|
ty::MethodTypeParam(ty::MethodParam {
|
||||||
trait_ref: param.trait_ref.fold_with(folder),
|
trait_ref: param.trait_ref.fold_with(folder),
|
||||||
method_num: param.method_num
|
method_num: param.method_num,
|
||||||
|
impl_def_id: param.impl_def_id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ty::MethodTraitObject(ref object) => {
|
ty::MethodTraitObject(ref object) => {
|
||||||
|
|
|
@ -544,7 +544,7 @@ impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Option<T> {
|
||||||
|
|
||||||
impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for P<T> {
|
impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for P<T> {
|
||||||
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
|
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
|
||||||
(*self).repr(tcx)
|
(**self).repr(tcx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -231,7 +231,7 @@ mod svh_visitor {
|
||||||
SawExprCall,
|
SawExprCall,
|
||||||
SawExprMethodCall,
|
SawExprMethodCall,
|
||||||
SawExprTup,
|
SawExprTup,
|
||||||
SawExprBinary(ast::BinOp),
|
SawExprBinary(ast::BinOp_),
|
||||||
SawExprUnary(ast::UnOp),
|
SawExprUnary(ast::UnOp),
|
||||||
SawExprLit(ast::Lit_),
|
SawExprLit(ast::Lit_),
|
||||||
SawExprCast,
|
SawExprCast,
|
||||||
|
@ -241,7 +241,7 @@ mod svh_visitor {
|
||||||
SawExprClosure,
|
SawExprClosure,
|
||||||
SawExprBlock,
|
SawExprBlock,
|
||||||
SawExprAssign,
|
SawExprAssign,
|
||||||
SawExprAssignOp(ast::BinOp),
|
SawExprAssignOp(ast::BinOp_),
|
||||||
SawExprIndex,
|
SawExprIndex,
|
||||||
SawExprRange,
|
SawExprRange,
|
||||||
SawExprPath,
|
SawExprPath,
|
||||||
|
@ -262,7 +262,7 @@ mod svh_visitor {
|
||||||
ExprCall(..) => SawExprCall,
|
ExprCall(..) => SawExprCall,
|
||||||
ExprMethodCall(..) => SawExprMethodCall,
|
ExprMethodCall(..) => SawExprMethodCall,
|
||||||
ExprTup(..) => SawExprTup,
|
ExprTup(..) => SawExprTup,
|
||||||
ExprBinary(op, _, _) => SawExprBinary(op),
|
ExprBinary(op, _, _) => SawExprBinary(op.node),
|
||||||
ExprUnary(op, _) => SawExprUnary(op),
|
ExprUnary(op, _) => SawExprUnary(op),
|
||||||
ExprLit(ref lit) => SawExprLit(lit.node.clone()),
|
ExprLit(ref lit) => SawExprLit(lit.node.clone()),
|
||||||
ExprCast(..) => SawExprCast,
|
ExprCast(..) => SawExprCast,
|
||||||
|
@ -273,7 +273,7 @@ mod svh_visitor {
|
||||||
ExprClosure(..) => SawExprClosure,
|
ExprClosure(..) => SawExprClosure,
|
||||||
ExprBlock(..) => SawExprBlock,
|
ExprBlock(..) => SawExprBlock,
|
||||||
ExprAssign(..) => SawExprAssign,
|
ExprAssign(..) => SawExprAssign,
|
||||||
ExprAssignOp(op, _, _) => SawExprAssignOp(op),
|
ExprAssignOp(op, _, _) => SawExprAssignOp(op.node),
|
||||||
ExprField(_, id) => SawExprField(content(id.node)),
|
ExprField(_, id) => SawExprField(content(id.node)),
|
||||||
ExprTupField(_, id) => SawExprTupField(id.node),
|
ExprTupField(_, id) => SawExprTupField(id.node),
|
||||||
ExprIndex(..) => SawExprIndex,
|
ExprIndex(..) => SawExprIndex,
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
pub use self::OptimizationDiagnosticKind::*;
|
pub use self::OptimizationDiagnosticKind::*;
|
||||||
pub use self::Diagnostic::*;
|
pub use self::Diagnostic::*;
|
||||||
|
|
||||||
use libc::c_char;
|
use libc::{c_char, c_uint};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
use {ValueRef, TwineRef, DebugLocRef, DiagnosticInfoRef};
|
use {ValueRef, TwineRef, DebugLocRef, DiagnosticInfoRef};
|
||||||
|
@ -69,9 +69,37 @@ impl OptimizationDiagnostic {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct InlineAsmDiagnostic {
|
||||||
|
pub cookie: c_uint,
|
||||||
|
pub message: TwineRef,
|
||||||
|
pub instruction: ValueRef,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Copy for InlineAsmDiagnostic {}
|
||||||
|
|
||||||
|
impl InlineAsmDiagnostic {
|
||||||
|
unsafe fn unpack(di: DiagnosticInfoRef)
|
||||||
|
-> InlineAsmDiagnostic {
|
||||||
|
|
||||||
|
let mut opt = InlineAsmDiagnostic {
|
||||||
|
cookie: 0,
|
||||||
|
message: ptr::null_mut(),
|
||||||
|
instruction: ptr::null_mut(),
|
||||||
|
};
|
||||||
|
|
||||||
|
super::LLVMUnpackInlineAsmDiagnostic(di,
|
||||||
|
&mut opt.cookie,
|
||||||
|
&mut opt.message,
|
||||||
|
&mut opt.instruction);
|
||||||
|
|
||||||
|
opt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy)]
|
#[derive(Copy)]
|
||||||
pub enum Diagnostic {
|
pub enum Diagnostic {
|
||||||
Optimization(OptimizationDiagnostic),
|
Optimization(OptimizationDiagnostic),
|
||||||
|
InlineAsm(InlineAsmDiagnostic),
|
||||||
|
|
||||||
/// LLVM has other types that we do not wrap here.
|
/// LLVM has other types that we do not wrap here.
|
||||||
UnknownDiagnostic(DiagnosticInfoRef),
|
UnknownDiagnostic(DiagnosticInfoRef),
|
||||||
|
@ -82,6 +110,9 @@ impl Diagnostic {
|
||||||
let kind = super::LLVMGetDiagInfoKind(di);
|
let kind = super::LLVMGetDiagInfoKind(di);
|
||||||
|
|
||||||
match kind {
|
match kind {
|
||||||
|
super::DK_InlineAsm
|
||||||
|
=> InlineAsm(InlineAsmDiagnostic::unpack(di)),
|
||||||
|
|
||||||
super::DK_OptimizationRemark
|
super::DK_OptimizationRemark
|
||||||
=> Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di)),
|
=> Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di)),
|
||||||
|
|
||||||
|
|
|
@ -2055,6 +2055,10 @@ extern {
|
||||||
function_out: *mut ValueRef,
|
function_out: *mut ValueRef,
|
||||||
debugloc_out: *mut DebugLocRef,
|
debugloc_out: *mut DebugLocRef,
|
||||||
message_out: *mut TwineRef);
|
message_out: *mut TwineRef);
|
||||||
|
pub fn LLVMUnpackInlineAsmDiagnostic(DI: DiagnosticInfoRef,
|
||||||
|
cookie_out: *mut c_uint,
|
||||||
|
message_out: *mut TwineRef,
|
||||||
|
instruction_out: *mut ValueRef);
|
||||||
|
|
||||||
pub fn LLVMWriteDiagnosticInfoToString(DI: DiagnosticInfoRef, s: RustStringRef);
|
pub fn LLVMWriteDiagnosticInfoToString(DI: DiagnosticInfoRef, s: RustStringRef);
|
||||||
pub fn LLVMGetDiagInfoSeverity(DI: DiagnosticInfoRef) -> DiagnosticSeverity;
|
pub fn LLVMGetDiagInfoSeverity(DI: DiagnosticInfoRef) -> DiagnosticSeverity;
|
||||||
|
|
|
@ -336,30 +336,36 @@ struct HandlerFreeVars<'a> {
|
||||||
cgcx: &'a CodegenContext<'a>,
|
cgcx: &'a CodegenContext<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn inline_asm_handler(diag: SMDiagnosticRef,
|
unsafe extern "C" fn report_inline_asm<'a, 'b>(cgcx: &'a CodegenContext<'a>,
|
||||||
user: *const c_void,
|
msg: &'b str,
|
||||||
cookie: c_uint) {
|
cookie: c_uint) {
|
||||||
use syntax::codemap::ExpnId;
|
use syntax::codemap::ExpnId;
|
||||||
|
|
||||||
|
match cgcx.lto_ctxt {
|
||||||
|
Some((sess, _)) => {
|
||||||
|
sess.codemap().with_expn_info(ExpnId::from_llvm_cookie(cookie), |info| match info {
|
||||||
|
Some(ei) => sess.span_err(ei.call_site, msg),
|
||||||
|
None => sess.err(msg),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
None => {
|
||||||
|
cgcx.handler.err(msg);
|
||||||
|
cgcx.handler.note("build without -C codegen-units for more exact errors");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn inline_asm_handler(diag: SMDiagnosticRef,
|
||||||
|
user: *const c_void,
|
||||||
|
cookie: c_uint) {
|
||||||
let HandlerFreeVars { cgcx, .. }
|
let HandlerFreeVars { cgcx, .. }
|
||||||
= *mem::transmute::<_, *const HandlerFreeVars>(user);
|
= *mem::transmute::<_, *const HandlerFreeVars>(user);
|
||||||
|
|
||||||
let msg = llvm::build_string(|s| llvm::LLVMWriteSMDiagnosticToString(diag, s))
|
let msg = llvm::build_string(|s| llvm::LLVMWriteSMDiagnosticToString(diag, s))
|
||||||
.expect("non-UTF8 SMDiagnostic");
|
.expect("non-UTF8 SMDiagnostic");
|
||||||
|
|
||||||
match cgcx.lto_ctxt {
|
report_inline_asm(cgcx, &msg[], cookie);
|
||||||
Some((sess, _)) => {
|
|
||||||
sess.codemap().with_expn_info(ExpnId::from_llvm_cookie(cookie), |info| match info {
|
|
||||||
Some(ei) => sess.span_err(ei.call_site, &msg[]),
|
|
||||||
None => sess.err(&msg[]),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
None => {
|
|
||||||
cgcx.handler.err(&msg[]);
|
|
||||||
cgcx.handler.note("build without -C codegen-units for more exact errors");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_void) {
|
unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_void) {
|
||||||
|
@ -367,6 +373,12 @@ unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_vo
|
||||||
= *mem::transmute::<_, *const HandlerFreeVars>(user);
|
= *mem::transmute::<_, *const HandlerFreeVars>(user);
|
||||||
|
|
||||||
match llvm::diagnostic::Diagnostic::unpack(info) {
|
match llvm::diagnostic::Diagnostic::unpack(info) {
|
||||||
|
llvm::diagnostic::InlineAsm(inline) => {
|
||||||
|
report_inline_asm(cgcx,
|
||||||
|
llvm::twine_to_string(inline.message).as_slice(),
|
||||||
|
inline.cookie);
|
||||||
|
}
|
||||||
|
|
||||||
llvm::diagnostic::Optimization(opt) => {
|
llvm::diagnostic::Optimization(opt) => {
|
||||||
let pass_name = str::from_utf8(ffi::c_str_to_bytes(&opt.pass_name))
|
let pass_name = str::from_utf8(ffi::c_str_to_bytes(&opt.pass_name))
|
||||||
.ok()
|
.ok()
|
||||||
|
@ -407,10 +419,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
|
||||||
let fv = &fv as *const HandlerFreeVars as *mut c_void;
|
let fv = &fv as *const HandlerFreeVars as *mut c_void;
|
||||||
|
|
||||||
llvm::LLVMSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, fv);
|
llvm::LLVMSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, fv);
|
||||||
|
|
||||||
if !cgcx.remark.is_empty() {
|
|
||||||
llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, fv);
|
llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, fv);
|
||||||
}
|
|
||||||
|
|
||||||
if config.emit_no_opt_bc {
|
if config.emit_no_opt_bc {
|
||||||
let ext = format!("{}.no-opt.bc", name_extra);
|
let ext = format!("{}.no-opt.bc", name_extra);
|
||||||
|
|
|
@ -540,7 +540,7 @@ pub fn compare_scalar_types<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
|
||||||
lhs: ValueRef,
|
lhs: ValueRef,
|
||||||
rhs: ValueRef,
|
rhs: ValueRef,
|
||||||
t: Ty<'tcx>,
|
t: Ty<'tcx>,
|
||||||
op: ast::BinOp)
|
op: ast::BinOp_)
|
||||||
-> Result<'blk, 'tcx> {
|
-> Result<'blk, 'tcx> {
|
||||||
let f = |&: a| Result::new(cx, compare_scalar_values(cx, lhs, rhs, a, op));
|
let f = |&: a| Result::new(cx, compare_scalar_values(cx, lhs, rhs, a, op));
|
||||||
|
|
||||||
|
@ -561,7 +561,7 @@ pub fn compare_scalar_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
|
||||||
lhs: ValueRef,
|
lhs: ValueRef,
|
||||||
rhs: ValueRef,
|
rhs: ValueRef,
|
||||||
nt: scalar_type,
|
nt: scalar_type,
|
||||||
op: ast::BinOp)
|
op: ast::BinOp_)
|
||||||
-> ValueRef {
|
-> ValueRef {
|
||||||
let _icx = push_ctxt("compare_scalar_values");
|
let _icx = push_ctxt("compare_scalar_values");
|
||||||
fn die(cx: Block) -> ! {
|
fn die(cx: Block) -> ! {
|
||||||
|
@ -635,7 +635,7 @@ pub fn compare_simd_types<'blk, 'tcx>(
|
||||||
not supported for floating point SIMD types")
|
not supported for floating point SIMD types")
|
||||||
},
|
},
|
||||||
ty::ty_uint(_) | ty::ty_int(_) => {
|
ty::ty_uint(_) | ty::ty_int(_) => {
|
||||||
let cmp = match op {
|
let cmp = match op.node {
|
||||||
ast::BiEq => llvm::IntEQ,
|
ast::BiEq => llvm::IntEQ,
|
||||||
ast::BiNe => llvm::IntNE,
|
ast::BiNe => llvm::IntNE,
|
||||||
ast::BiLt => llvm::IntSLT,
|
ast::BiLt => llvm::IntSLT,
|
||||||
|
@ -823,7 +823,7 @@ pub fn cast_shift_rhs<F, G>(op: ast::BinOp,
|
||||||
G: FnOnce(ValueRef, Type) -> ValueRef,
|
G: FnOnce(ValueRef, Type) -> ValueRef,
|
||||||
{
|
{
|
||||||
// Shifts may have any size int on the rhs
|
// Shifts may have any size int on the rhs
|
||||||
if ast_util::is_shift_binop(op) {
|
if ast_util::is_shift_binop(op.node) {
|
||||||
let mut rhs_llty = val_ty(rhs);
|
let mut rhs_llty = val_ty(rhs);
|
||||||
let mut lhs_llty = val_ty(lhs);
|
let mut lhs_llty = val_ty(lhs);
|
||||||
if rhs_llty.kind() == Vector { rhs_llty = rhs_llty.element_type() }
|
if rhs_llty.kind() == Vector { rhs_llty = rhs_llty.element_type() }
|
||||||
|
@ -852,7 +852,7 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>(
|
||||||
rhs: ValueRef,
|
rhs: ValueRef,
|
||||||
rhs_t: Ty<'tcx>)
|
rhs_t: Ty<'tcx>)
|
||||||
-> Block<'blk, 'tcx> {
|
-> Block<'blk, 'tcx> {
|
||||||
let (zero_text, overflow_text) = if divrem == ast::BiDiv {
|
let (zero_text, overflow_text) = if divrem.node == ast::BiDiv {
|
||||||
("attempted to divide by zero",
|
("attempted to divide by zero",
|
||||||
"attempted to divide with overflow")
|
"attempted to divide with overflow")
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -310,7 +310,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef {
|
||||||
let ty = ty::expr_ty(cx.tcx(), &**e1);
|
let ty = ty::expr_ty(cx.tcx(), &**e1);
|
||||||
let is_float = ty::type_is_fp(ty);
|
let is_float = ty::type_is_fp(ty);
|
||||||
let signed = ty::type_is_signed(ty);
|
let signed = ty::type_is_signed(ty);
|
||||||
return match b {
|
return match b.node {
|
||||||
ast::BiAdd => {
|
ast::BiAdd => {
|
||||||
if is_float { llvm::LLVMConstFAdd(te1, te2) }
|
if is_float { llvm::LLVMConstFAdd(te1, te2) }
|
||||||
else { llvm::LLVMConstAdd(te1, te2) }
|
else { llvm::LLVMConstAdd(te1, te2) }
|
||||||
|
|
|
@ -207,7 +207,7 @@ use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
|
||||||
use util::nodemap::{DefIdMap, NodeMap, FnvHashMap, FnvHashSet};
|
use util::nodemap::{DefIdMap, NodeMap, FnvHashMap, FnvHashSet};
|
||||||
use util::ppaux;
|
use util::ppaux;
|
||||||
|
|
||||||
use libc::c_uint;
|
use libc::{c_uint, c_longlong};
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
@ -2764,7 +2764,7 @@ fn create_struct_stub(cx: &CrateContext,
|
||||||
fn fixed_vec_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
fn fixed_vec_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||||
unique_type_id: UniqueTypeId,
|
unique_type_id: UniqueTypeId,
|
||||||
element_type: Ty<'tcx>,
|
element_type: Ty<'tcx>,
|
||||||
len: uint,
|
len: Option<u64>,
|
||||||
span: Span)
|
span: Span)
|
||||||
-> MetadataCreationResult {
|
-> MetadataCreationResult {
|
||||||
let element_type_metadata = type_metadata(cx, element_type, span);
|
let element_type_metadata = type_metadata(cx, element_type, span);
|
||||||
|
@ -2774,18 +2774,20 @@ fn fixed_vec_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||||
let element_llvm_type = type_of::type_of(cx, element_type);
|
let element_llvm_type = type_of::type_of(cx, element_type);
|
||||||
let (element_type_size, element_type_align) = size_and_align_of(cx, element_llvm_type);
|
let (element_type_size, element_type_align) = size_and_align_of(cx, element_llvm_type);
|
||||||
|
|
||||||
|
let (array_size_in_bytes, upper_bound) = match len {
|
||||||
|
Some(len) => (element_type_size * len, len as c_longlong),
|
||||||
|
None => (0, -1)
|
||||||
|
};
|
||||||
|
|
||||||
let subrange = unsafe {
|
let subrange = unsafe {
|
||||||
llvm::LLVMDIBuilderGetOrCreateSubrange(
|
llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)
|
||||||
DIB(cx),
|
|
||||||
0,
|
|
||||||
len as i64)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let subscripts = create_DIArray(DIB(cx), &[subrange]);
|
let subscripts = create_DIArray(DIB(cx), &[subrange]);
|
||||||
let metadata = unsafe {
|
let metadata = unsafe {
|
||||||
llvm::LLVMDIBuilderCreateArrayType(
|
llvm::LLVMDIBuilderCreateArrayType(
|
||||||
DIB(cx),
|
DIB(cx),
|
||||||
bytes_to_bits(element_type_size * (len as u64)),
|
bytes_to_bits(array_size_in_bytes),
|
||||||
bytes_to_bits(element_type_align),
|
bytes_to_bits(element_type_align),
|
||||||
element_type_metadata,
|
element_type_metadata,
|
||||||
subscripts)
|
subscripts)
|
||||||
|
@ -2991,12 +2993,12 @@ fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||||
ty::ty_enum(def_id, _) => {
|
ty::ty_enum(def_id, _) => {
|
||||||
prepare_enum_metadata(cx, t, def_id, unique_type_id, usage_site_span).finalize(cx)
|
prepare_enum_metadata(cx, t, def_id, unique_type_id, usage_site_span).finalize(cx)
|
||||||
}
|
}
|
||||||
ty::ty_vec(typ, Some(len)) => {
|
ty::ty_vec(typ, len) => {
|
||||||
fixed_vec_metadata(cx, unique_type_id, typ, len, usage_site_span)
|
fixed_vec_metadata(cx, unique_type_id, typ, len.map(|x| x as u64), usage_site_span)
|
||||||
|
}
|
||||||
|
ty::ty_str => {
|
||||||
|
fixed_vec_metadata(cx, unique_type_id, cx.tcx().types.i8, None, usage_site_span)
|
||||||
}
|
}
|
||||||
// FIXME Can we do better than this for unsized vec/str fields?
|
|
||||||
ty::ty_vec(typ, None) => fixed_vec_metadata(cx, unique_type_id, typ, 0, usage_site_span),
|
|
||||||
ty::ty_str => fixed_vec_metadata(cx, unique_type_id, cx.tcx().types.i8, 0, usage_site_span),
|
|
||||||
ty::ty_trait(..) => {
|
ty::ty_trait(..) => {
|
||||||
MetadataCreationResult::new(
|
MetadataCreationResult::new(
|
||||||
trait_pointer_metadata(cx, t, None, unique_type_id),
|
trait_pointer_metadata(cx, t, None, unique_type_id),
|
||||||
|
|
|
@ -1132,7 +1132,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||||
let rhs_datum = unpack_datum!(bcx, trans(bcx, &**rhs));
|
let rhs_datum = unpack_datum!(bcx, trans(bcx, &**rhs));
|
||||||
trans_overloaded_op(bcx, expr, MethodCall::expr(expr.id), lhs,
|
trans_overloaded_op(bcx, expr, MethodCall::expr(expr.id), lhs,
|
||||||
vec![(rhs_datum, rhs.id)], Some(dest),
|
vec![(rhs_datum, rhs.id)], Some(dest),
|
||||||
!ast_util::is_by_value_binop(op)).bcx
|
!ast_util::is_by_value_binop(op.node)).bcx
|
||||||
}
|
}
|
||||||
ast::ExprUnary(op, ref subexpr) => {
|
ast::ExprUnary(op, ref subexpr) => {
|
||||||
// if not overloaded, would be RvalueDatumExpr
|
// if not overloaded, would be RvalueDatumExpr
|
||||||
|
@ -1676,7 +1676,7 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||||
let binop_debug_loc = binop_expr.debug_loc();
|
let binop_debug_loc = binop_expr.debug_loc();
|
||||||
|
|
||||||
let mut bcx = bcx;
|
let mut bcx = bcx;
|
||||||
let val = match op {
|
let val = match op.node {
|
||||||
ast::BiAdd => {
|
ast::BiAdd => {
|
||||||
if is_float {
|
if is_float {
|
||||||
FAdd(bcx, lhs, rhs, binop_debug_loc)
|
FAdd(bcx, lhs, rhs, binop_debug_loc)
|
||||||
|
@ -1739,7 +1739,7 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||||
}
|
}
|
||||||
ast::BiEq | ast::BiNe | ast::BiLt | ast::BiGe | ast::BiLe | ast::BiGt => {
|
ast::BiEq | ast::BiNe | ast::BiLt | ast::BiGe | ast::BiLe | ast::BiGt => {
|
||||||
if ty::type_is_scalar(rhs_t) {
|
if ty::type_is_scalar(rhs_t) {
|
||||||
unpack_result!(bcx, base::compare_scalar_types(bcx, lhs, rhs, rhs_t, op))
|
unpack_result!(bcx, base::compare_scalar_types(bcx, lhs, rhs, rhs_t, op.node))
|
||||||
} else if is_simd {
|
} else if is_simd {
|
||||||
base::compare_simd_types(bcx, lhs, rhs, intype, ty::simd_size(tcx, lhs_t), op)
|
base::compare_simd_types(bcx, lhs, rhs, intype, ty::simd_size(tcx, lhs_t), op)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1811,7 +1811,7 @@ fn trans_binary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||||
// if overloaded, would be RvalueDpsExpr
|
// if overloaded, would be RvalueDpsExpr
|
||||||
assert!(!ccx.tcx().method_map.borrow().contains_key(&MethodCall::expr(expr.id)));
|
assert!(!ccx.tcx().method_map.borrow().contains_key(&MethodCall::expr(expr.id)));
|
||||||
|
|
||||||
match op {
|
match op.node {
|
||||||
ast::BiAnd => {
|
ast::BiAnd => {
|
||||||
trans_lazy_binop(bcx, expr, lazy_and, lhs, rhs)
|
trans_lazy_binop(bcx, expr, lazy_and, lhs, rhs)
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,7 +132,8 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||||
|
|
||||||
ty::MethodTypeParam(ty::MethodParam {
|
ty::MethodTypeParam(ty::MethodParam {
|
||||||
ref trait_ref,
|
ref trait_ref,
|
||||||
method_num
|
method_num,
|
||||||
|
impl_def_id: _
|
||||||
}) => {
|
}) => {
|
||||||
let trait_ref = ty::Binder(bcx.monomorphize(trait_ref));
|
let trait_ref = ty::Binder(bcx.monomorphize(trait_ref));
|
||||||
let span = bcx.tcx().map.span(method_call.expr_id);
|
let span = bcx.tcx().map.span(method_call.expr_id);
|
||||||
|
|
|
@ -256,7 +256,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
||||||
&impl_polytype.substs,
|
&impl_polytype.substs,
|
||||||
&ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap());
|
&ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap());
|
||||||
let origin = MethodTypeParam(MethodParam { trait_ref: impl_trait_ref.clone(),
|
let origin = MethodTypeParam(MethodParam { trait_ref: impl_trait_ref.clone(),
|
||||||
method_num: method_num });
|
method_num: method_num,
|
||||||
|
impl_def_id: Some(impl_def_id) });
|
||||||
(impl_trait_ref.substs.clone(), origin)
|
(impl_trait_ref.substs.clone(), origin)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,7 +276,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
||||||
let trait_ref =
|
let trait_ref =
|
||||||
Rc::new(ty::TraitRef::new(trait_def_id, self.tcx().mk_substs(substs.clone())));
|
Rc::new(ty::TraitRef::new(trait_def_id, self.tcx().mk_substs(substs.clone())));
|
||||||
let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
|
let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
|
||||||
method_num: method_num });
|
method_num: method_num,
|
||||||
|
impl_def_id: None });
|
||||||
(substs, origin)
|
(substs, origin)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,7 +287,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
||||||
let trait_ref = self.replace_late_bound_regions_with_fresh_var(&*poly_trait_ref);
|
let trait_ref = self.replace_late_bound_regions_with_fresh_var(&*poly_trait_ref);
|
||||||
let substs = trait_ref.substs.clone();
|
let substs = trait_ref.substs.clone();
|
||||||
let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
|
let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
|
||||||
method_num: method_num });
|
method_num: method_num,
|
||||||
|
impl_def_id: None });
|
||||||
(substs, origin)
|
(substs, origin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -287,7 +287,8 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
|
|
||||||
let callee = MethodCallee {
|
let callee = MethodCallee {
|
||||||
origin: MethodTypeParam(MethodParam{trait_ref: trait_ref.clone(),
|
origin: MethodTypeParam(MethodParam{trait_ref: trait_ref.clone(),
|
||||||
method_num: method_num}),
|
method_num: method_num,
|
||||||
|
impl_def_id: None}),
|
||||||
ty: fty,
|
ty: fty,
|
||||||
substs: trait_ref.substs.clone()
|
substs: trait_ref.substs.clone()
|
||||||
};
|
};
|
||||||
|
|
|
@ -2859,7 +2859,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
let lhs_t = structurally_resolved_type(fcx, lhs.span,
|
let lhs_t = structurally_resolved_type(fcx, lhs.span,
|
||||||
fcx.expr_ty(&*lhs));
|
fcx.expr_ty(&*lhs));
|
||||||
|
|
||||||
if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
|
if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op.node) {
|
||||||
// Shift is a special case: rhs must be uint, no matter what lhs is
|
// Shift is a special case: rhs must be uint, no matter what lhs is
|
||||||
check_expr(fcx, &**rhs);
|
check_expr(fcx, &**rhs);
|
||||||
let rhs_ty = fcx.expr_ty(&**rhs);
|
let rhs_ty = fcx.expr_ty(&**rhs);
|
||||||
|
@ -2887,7 +2887,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
demand::suptype(fcx, expr.span, tvar, lhs_t);
|
demand::suptype(fcx, expr.span, tvar, lhs_t);
|
||||||
check_expr_has_type(fcx, &**rhs, tvar);
|
check_expr_has_type(fcx, &**rhs, tvar);
|
||||||
|
|
||||||
let result_t = match op {
|
let result_t = match op.node {
|
||||||
ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
|
ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
|
||||||
ast::BiGt => {
|
ast::BiGt => {
|
||||||
if ty::type_is_simd(tcx, lhs_t) {
|
if ty::type_is_simd(tcx, lhs_t) {
|
||||||
|
@ -2898,7 +2898,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
operation `{}` not \
|
operation `{}` not \
|
||||||
supported for floating \
|
supported for floating \
|
||||||
point SIMD vector `{}`",
|
point SIMD vector `{}`",
|
||||||
ast_util::binop_to_string(op),
|
ast_util::binop_to_string(op.node),
|
||||||
actual)
|
actual)
|
||||||
},
|
},
|
||||||
lhs_t,
|
lhs_t,
|
||||||
|
@ -2919,7 +2919,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if op == ast::BiOr || op == ast::BiAnd {
|
if op.node == ast::BiOr || op.node == ast::BiAnd {
|
||||||
// This is an error; one of the operands must have the wrong
|
// This is an error; one of the operands must have the wrong
|
||||||
// type
|
// type
|
||||||
fcx.write_error(expr.id);
|
fcx.write_error(expr.id);
|
||||||
|
@ -2928,7 +2928,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
|actual| {
|
|actual| {
|
||||||
format!("binary operation `{}` cannot be applied \
|
format!("binary operation `{}` cannot be applied \
|
||||||
to type `{}`",
|
to type `{}`",
|
||||||
ast_util::binop_to_string(op),
|
ast_util::binop_to_string(op.node),
|
||||||
actual)
|
actual)
|
||||||
},
|
},
|
||||||
lhs_t,
|
lhs_t,
|
||||||
|
@ -2945,7 +2945,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
operation `{}=` \
|
operation `{}=` \
|
||||||
cannot be applied to \
|
cannot be applied to \
|
||||||
type `{}`",
|
type `{}`",
|
||||||
ast_util::binop_to_string(op),
|
ast_util::binop_to_string(op.node),
|
||||||
actual)
|
actual)
|
||||||
},
|
},
|
||||||
lhs_t,
|
lhs_t,
|
||||||
|
@ -2968,7 +2968,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
rhs: &P<ast::Expr>) -> Ty<'tcx> {
|
rhs: &P<ast::Expr>) -> Ty<'tcx> {
|
||||||
let tcx = fcx.ccx.tcx;
|
let tcx = fcx.ccx.tcx;
|
||||||
let lang = &tcx.lang_items;
|
let lang = &tcx.lang_items;
|
||||||
let (name, trait_did) = match op {
|
let (name, trait_did) = match op.node {
|
||||||
ast::BiAdd => ("add", lang.add_trait()),
|
ast::BiAdd => ("add", lang.add_trait()),
|
||||||
ast::BiSub => ("sub", lang.sub_trait()),
|
ast::BiSub => ("sub", lang.sub_trait()),
|
||||||
ast::BiMul => ("mul", lang.mul_trait()),
|
ast::BiMul => ("mul", lang.mul_trait()),
|
||||||
|
@ -2994,10 +2994,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
trait_did, lhs_expr, Some(rhs), || {
|
trait_did, lhs_expr, Some(rhs), || {
|
||||||
fcx.type_error_message(ex.span, |actual| {
|
fcx.type_error_message(ex.span, |actual| {
|
||||||
format!("binary operation `{}` cannot be applied to type `{}`",
|
format!("binary operation `{}` cannot be applied to type `{}`",
|
||||||
ast_util::binop_to_string(op),
|
ast_util::binop_to_string(op.node),
|
||||||
actual)
|
actual)
|
||||||
}, lhs_resolved_t, None)
|
}, lhs_resolved_t, None)
|
||||||
}, if ast_util::is_by_value_binop(op) { AutorefArgs::No } else { AutorefArgs::Yes })
|
}, if ast_util::is_by_value_binop(op.node) { AutorefArgs::No } else { AutorefArgs::Yes })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
|
|
|
@ -564,7 +564,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
|
||||||
},
|
},
|
||||||
|
|
||||||
ast::ExprBinary(op, ref lhs, ref rhs) if has_method_map => {
|
ast::ExprBinary(op, ref lhs, ref rhs) if has_method_map => {
|
||||||
let implicitly_ref_args = !ast_util::is_by_value_binop(op);
|
let implicitly_ref_args = !ast_util::is_by_value_binop(op.node);
|
||||||
|
|
||||||
// As `expr_method_call`, but the call is via an
|
// As `expr_method_call`, but the call is via an
|
||||||
// overloaded op. Note that we (sadly) currently use an
|
// overloaded op. Note that we (sadly) currently use an
|
||||||
|
|
|
@ -18,4 +18,9 @@ pub use self::c_str::CString;
|
||||||
pub use self::c_str::c_str_to_bytes;
|
pub use self::c_str::c_str_to_bytes;
|
||||||
pub use self::c_str::c_str_to_bytes_with_nul;
|
pub use self::c_str::c_str_to_bytes_with_nul;
|
||||||
|
|
||||||
|
pub use self::os_str::OsString;
|
||||||
|
pub use self::os_str::OsStr;
|
||||||
|
pub use self::os_str::AsOsStr;
|
||||||
|
|
||||||
mod c_str;
|
mod c_str;
|
||||||
|
mod os_str;
|
||||||
|
|
260
src/libstd/ffi/os_str.rs
Normal file
260
src/libstd/ffi/os_str.rs
Normal file
|
@ -0,0 +1,260 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
//! A type that can represent all platform-native strings, but is cheaply
|
||||||
|
//! interconvertable with Rust strings.
|
||||||
|
//!
|
||||||
|
//! The need for this type arises from the fact that:
|
||||||
|
//!
|
||||||
|
//! * On Unix systems, strings are often arbitrary sequences of non-zero
|
||||||
|
//! bytes, in many cases interpreted as UTF-8.
|
||||||
|
//!
|
||||||
|
//! * On Windows, strings are often arbitrary sequences of non-zero 16-bit
|
||||||
|
//! values, interpreted as UTF-16 when it is valid to do so.
|
||||||
|
//!
|
||||||
|
//! * In Rust, strings are always valid UTF-8, but may contain zeros.
|
||||||
|
//!
|
||||||
|
//! The types in this module bridge this gap by simultaneously representing Rust
|
||||||
|
//! and platform-native string values, and in particular allowing a Rust string
|
||||||
|
//! to be converted into an "OS" string with no cost.
|
||||||
|
//!
|
||||||
|
//! **Note**: At the moment, these types are extremely bare-bones, usable only
|
||||||
|
//! for conversion to/from various other string types. Eventually these types
|
||||||
|
//! will offer a full-fledged string API.
|
||||||
|
|
||||||
|
#![unstable(feature = "os",
|
||||||
|
reason = "recently added as part of path/io reform")]
|
||||||
|
|
||||||
|
use core::prelude::*;
|
||||||
|
|
||||||
|
use core::borrow::{BorrowFrom, ToOwned};
|
||||||
|
use fmt::{self, Debug};
|
||||||
|
use mem;
|
||||||
|
use string::{String, CowString};
|
||||||
|
use ops;
|
||||||
|
use cmp;
|
||||||
|
use hash::{Hash, Hasher, Writer};
|
||||||
|
|
||||||
|
use sys::os_str::{Buf, Slice};
|
||||||
|
use sys_common::{AsInner, IntoInner, FromInner};
|
||||||
|
|
||||||
|
/// Owned, mutable OS strings.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct OsString {
|
||||||
|
inner: Buf
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Slices into OS strings.
|
||||||
|
pub struct OsStr {
|
||||||
|
inner: Slice
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OsString {
|
||||||
|
/// Constructs an `OsString` at no cost by consuming a `String`.
|
||||||
|
pub fn from_string(s: String) -> OsString {
|
||||||
|
OsString { inner: Buf::from_string(s) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constructs an `OsString` by copying from a `&str` slice.
|
||||||
|
///
|
||||||
|
/// Equivalent to: `OsString::from_string(String::from_str(s))`.
|
||||||
|
pub fn from_str(s: &str) -> OsString {
|
||||||
|
OsString { inner: Buf::from_str(s) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert the `OsString` into a `String` if it contains valid Unicode data.
|
||||||
|
///
|
||||||
|
/// On failure, ownership of the original `OsString` is returned.
|
||||||
|
pub fn into_string(self) -> Result<String, OsString> {
|
||||||
|
self.inner.into_string().map_err(|buf| OsString { inner: buf} )
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extend the string with the given `&OsStr` slice.
|
||||||
|
pub fn push_os_str(&mut self, s: &OsStr) {
|
||||||
|
self.inner.push_slice(&s.inner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Index<ops::FullRange> for OsString {
|
||||||
|
type Output = OsStr;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn index(&self, _index: &ops::FullRange) -> &OsStr {
|
||||||
|
unsafe { mem::transmute(self.inner.as_slice()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Deref for OsString {
|
||||||
|
type Target = OsStr;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn deref(&self) -> &OsStr {
|
||||||
|
&self[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for OsString {
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
|
fmt::Debug::fmt(&**self, formatter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OsStr {
|
||||||
|
/// Coerce directly from a `&str` slice to a `&OsStr` slice.
|
||||||
|
pub fn from_str(s: &str) -> &OsStr {
|
||||||
|
unsafe { mem::transmute(Slice::from_str(s)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Yield a `&str` slice if the `OsStr` is valid unicode.
|
||||||
|
///
|
||||||
|
/// This conversion may entail doing a check for UTF-8 validity.
|
||||||
|
pub fn to_str(&self) -> Option<&str> {
|
||||||
|
self.inner.to_str()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert an `OsStr` to a `CowString`.
|
||||||
|
///
|
||||||
|
/// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
|
||||||
|
pub fn to_string_lossy(&self) -> CowString {
|
||||||
|
self.inner.to_string_lossy()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Copy the slice into an onwed `OsString`.
|
||||||
|
pub fn to_os_string(&self) -> OsString {
|
||||||
|
OsString { inner: self.inner.to_owned() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the underlying byte representation.
|
||||||
|
///
|
||||||
|
/// Note: it is *crucial* that this API is private, to avoid
|
||||||
|
/// revealing the internal, platform-specific encodings.
|
||||||
|
fn bytes(&self) -> &[u8] {
|
||||||
|
unsafe { mem::transmute(&self.inner) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for OsStr {
|
||||||
|
fn eq(&self, other: &OsStr) -> bool {
|
||||||
|
self.bytes().eq(other.bytes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq<str> for OsStr {
|
||||||
|
fn eq(&self, other: &str) -> bool {
|
||||||
|
*self == *OsStr::from_str(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq<OsStr> for str {
|
||||||
|
fn eq(&self, other: &OsStr) -> bool {
|
||||||
|
*other == *OsStr::from_str(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for OsStr {}
|
||||||
|
|
||||||
|
impl PartialOrd for OsStr {
|
||||||
|
#[inline]
|
||||||
|
fn partial_cmp(&self, other: &OsStr) -> Option<cmp::Ordering> {
|
||||||
|
self.bytes().partial_cmp(other.bytes())
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn lt(&self, other: &OsStr) -> bool { self.bytes().lt(other.bytes()) }
|
||||||
|
#[inline]
|
||||||
|
fn le(&self, other: &OsStr) -> bool { self.bytes().le(other.bytes()) }
|
||||||
|
#[inline]
|
||||||
|
fn gt(&self, other: &OsStr) -> bool { self.bytes().gt(other.bytes()) }
|
||||||
|
#[inline]
|
||||||
|
fn ge(&self, other: &OsStr) -> bool { self.bytes().ge(other.bytes()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd<str> for OsStr {
|
||||||
|
#[inline]
|
||||||
|
fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
|
||||||
|
self.partial_cmp(OsStr::from_str(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME (#19470): cannot provide PartialOrd<OsStr> for str until we
|
||||||
|
// have more flexible coherence rules.
|
||||||
|
|
||||||
|
impl Ord for OsStr {
|
||||||
|
#[inline]
|
||||||
|
fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, S: Hasher + Writer> Hash<S> for OsStr {
|
||||||
|
#[inline]
|
||||||
|
fn hash(&self, state: &mut S) {
|
||||||
|
self.bytes().hash(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for OsStr {
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
|
self.inner.fmt(formatter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BorrowFrom<OsString> for OsStr {
|
||||||
|
fn borrow_from(owned: &OsString) -> &OsStr { &owned[] }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToOwned<OsString> for OsStr {
|
||||||
|
fn to_owned(&self) -> OsString { self.to_os_string() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Freely convertible to an `&OsStr` slice.
|
||||||
|
pub trait AsOsStr {
|
||||||
|
/// Convert to an `&OsStr` slice.
|
||||||
|
fn as_os_str(&self) -> &OsStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsOsStr for OsStr {
|
||||||
|
fn as_os_str(&self) -> &OsStr {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsOsStr for OsString {
|
||||||
|
fn as_os_str(&self) -> &OsStr {
|
||||||
|
&self[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsOsStr for str {
|
||||||
|
fn as_os_str(&self) -> &OsStr {
|
||||||
|
OsStr::from_str(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsOsStr for String {
|
||||||
|
fn as_os_str(&self) -> &OsStr {
|
||||||
|
OsStr::from_str(&self[])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromInner<Buf> for OsString {
|
||||||
|
fn from_inner(buf: Buf) -> OsString {
|
||||||
|
OsString { inner: buf }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoInner<Buf> for OsString {
|
||||||
|
fn into_inner(self) -> Buf {
|
||||||
|
self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsInner<Slice> for OsStr {
|
||||||
|
fn as_inner(&self) -> &Slice {
|
||||||
|
&self.inner
|
||||||
|
}
|
||||||
|
}
|
|
@ -382,7 +382,7 @@ impl<T> !Sync for SyncSender<T> {}
|
||||||
/// A `send` operation can only fail if the receiving end of a channel is
|
/// A `send` operation can only fail if the receiving end of a channel is
|
||||||
/// disconnected, implying that the data could never be received. The error
|
/// disconnected, implying that the data could never be received. The error
|
||||||
/// contains the data being sent as a payload so it can be recovered.
|
/// contains the data being sent as a payload so it can be recovered.
|
||||||
#[derive(PartialEq, Eq, Show)]
|
#[derive(PartialEq, Eq)]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct SendError<T>(pub T);
|
pub struct SendError<T>(pub T);
|
||||||
|
|
||||||
|
@ -412,7 +412,7 @@ pub enum TryRecvError {
|
||||||
|
|
||||||
/// This enumeration is the list of the possible error outcomes for the
|
/// This enumeration is the list of the possible error outcomes for the
|
||||||
/// `SyncSender::try_send` method.
|
/// `SyncSender::try_send` method.
|
||||||
#[derive(PartialEq, Clone, Show)]
|
#[derive(PartialEq, Clone)]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub enum TrySendError<T> {
|
pub enum TrySendError<T> {
|
||||||
/// The data could not be sent on the channel because it would require that
|
/// The data could not be sent on the channel because it would require that
|
||||||
|
@ -961,6 +961,13 @@ impl<T: Send> Drop for Receiver<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<T> fmt::Debug for SendError<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
"SendError(..)".fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T> fmt::Display for SendError<T> {
|
impl<T> fmt::Display for SendError<T> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
@ -968,6 +975,16 @@ impl<T> fmt::Display for SendError<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<T> fmt::Debug for TrySendError<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
TrySendError::Full(..) => "Full(..)".fmt(f),
|
||||||
|
TrySendError::Disconnected(..) => "Disconnected(..)".fmt(f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T> fmt::Display for TrySendError<T> {
|
impl<T> fmt::Display for TrySendError<T> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
|
|
@ -53,7 +53,6 @@ pub struct Guard {
|
||||||
/// is held. The precise semantics for when a lock is poisoned is documented on
|
/// is held. The precise semantics for when a lock is poisoned is documented on
|
||||||
/// each lock, but once a lock is poisoned then all future acquisitions will
|
/// each lock, but once a lock is poisoned then all future acquisitions will
|
||||||
/// return this error.
|
/// return this error.
|
||||||
#[derive(Show)]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct PoisonError<T> {
|
pub struct PoisonError<T> {
|
||||||
guard: T,
|
guard: T,
|
||||||
|
@ -61,7 +60,6 @@ pub struct PoisonError<T> {
|
||||||
|
|
||||||
/// An enumeration of possible errors which can occur while calling the
|
/// An enumeration of possible errors which can occur while calling the
|
||||||
/// `try_lock` method.
|
/// `try_lock` method.
|
||||||
#[derive(Show)]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub enum TryLockError<T> {
|
pub enum TryLockError<T> {
|
||||||
/// The lock could not be acquired because another task failed while holding
|
/// The lock could not be acquired because another task failed while holding
|
||||||
|
@ -92,6 +90,13 @@ pub type LockResult<Guard> = Result<Guard, PoisonError<Guard>>;
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub type TryLockResult<Guard> = Result<Guard, TryLockError<Guard>>;
|
pub type TryLockResult<Guard> = Result<Guard, TryLockError<Guard>>;
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<T> fmt::Debug for PoisonError<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
"PoisonError { inner: .. }".fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T> fmt::Display for PoisonError<T> {
|
impl<T> fmt::Display for PoisonError<T> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
@ -134,6 +139,16 @@ impl<T> FromError<PoisonError<T>> for TryLockError<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<T> fmt::Debug for TryLockError<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
TryLockError::Poisoned(..) => "Poisoned(..)".fmt(f),
|
||||||
|
TryLockError::WouldBlock => "WouldBlock".fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T> fmt::Display for TryLockError<T> {
|
impl<T> fmt::Display for TryLockError<T> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
|
|
@ -29,6 +29,7 @@ pub mod stack;
|
||||||
pub mod thread;
|
pub mod thread;
|
||||||
pub mod thread_info;
|
pub mod thread_info;
|
||||||
pub mod thread_local;
|
pub mod thread_local;
|
||||||
|
pub mod wtf8;
|
||||||
|
|
||||||
// common error constructors
|
// common error constructors
|
||||||
|
|
||||||
|
@ -93,11 +94,21 @@ pub fn keep_going<F>(data: &[u8], mut f: F) -> i64 where
|
||||||
return (origamt - amt) as i64;
|
return (origamt - amt) as i64;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A trait for extracting representations from std::io types
|
/// A trait for viewing representations from std types
|
||||||
pub trait AsInner<Inner> {
|
pub trait AsInner<Inner: ?Sized> {
|
||||||
fn as_inner(&self) -> &Inner;
|
fn as_inner(&self) -> &Inner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A trait for extracting representations from std types
|
||||||
|
pub trait IntoInner<Inner> {
|
||||||
|
fn into_inner(self) -> Inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A trait for creating std types from internal representations
|
||||||
|
pub trait FromInner<Inner> {
|
||||||
|
fn from_inner(inner: Inner) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
pub trait ProcessConfig<K: BytesContainer, V: BytesContainer> {
|
pub trait ProcessConfig<K: BytesContainer, V: BytesContainer> {
|
||||||
fn program(&self) -> &CString;
|
fn program(&self) -> &CString;
|
||||||
fn args(&self) -> &[CString];
|
fn args(&self) -> &[CString];
|
||||||
|
|
1212
src/libstd/sys/common/wtf8.rs
Normal file
1212
src/libstd/sys/common/wtf8.rs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -31,7 +31,10 @@
|
||||||
|
|
||||||
#![unstable(feature = "std_misc")]
|
#![unstable(feature = "std_misc")]
|
||||||
|
|
||||||
use sys_common::AsInner;
|
use vec::Vec;
|
||||||
|
use sys::os_str::Buf;
|
||||||
|
use sys_common::{AsInner, IntoInner, FromInner};
|
||||||
|
use ffi::{OsStr, OsString};
|
||||||
use libc;
|
use libc;
|
||||||
|
|
||||||
use io;
|
use io;
|
||||||
|
@ -99,6 +102,36 @@ impl AsRawFd for io::net::udp::UdpSocket {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unix-specific extensions to `OsString`.
|
||||||
|
pub trait OsStringExt {
|
||||||
|
/// Create an `OsString` from a byte vector.
|
||||||
|
fn from_vec(vec: Vec<u8>) -> Self;
|
||||||
|
|
||||||
|
/// Yield the underlying byte vector of this `OsString`.
|
||||||
|
fn into_vec(self) -> Vec<u8>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OsStringExt for OsString {
|
||||||
|
fn from_vec(vec: Vec<u8>) -> OsString {
|
||||||
|
FromInner::from_inner(Buf { inner: vec })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_vec(self) -> Vec<u8> {
|
||||||
|
self.into_inner().inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unix-specific extensions to `OsStr`.
|
||||||
|
pub trait OsStrExt {
|
||||||
|
fn as_byte_slice(&self) -> &[u8];
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OsStrExt for OsStr {
|
||||||
|
fn as_byte_slice(&self) -> &[u8] {
|
||||||
|
&self.as_inner().inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A prelude for conveniently writing platform-specific code.
|
/// A prelude for conveniently writing platform-specific code.
|
||||||
///
|
///
|
||||||
/// Includes all extension traits, and some important type definitions.
|
/// Includes all extension traits, and some important type definitions.
|
||||||
|
|
|
@ -44,6 +44,7 @@ pub mod fs;
|
||||||
pub mod helper_signal;
|
pub mod helper_signal;
|
||||||
pub mod mutex;
|
pub mod mutex;
|
||||||
pub mod os;
|
pub mod os;
|
||||||
|
pub mod os_str;
|
||||||
pub mod pipe;
|
pub mod pipe;
|
||||||
pub mod process;
|
pub mod process;
|
||||||
pub mod rwlock;
|
pub mod rwlock;
|
||||||
|
|
86
src/libstd/sys/unix/os_str.rs
Normal file
86
src/libstd/sys/unix/os_str.rs
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
/// The underlying OsString/OsStr implementation on Unix systems: just
|
||||||
|
/// a `Vec<u8>`/`[u8]`.
|
||||||
|
|
||||||
|
use core::prelude::*;
|
||||||
|
|
||||||
|
use fmt::{self, Debug};
|
||||||
|
use vec::Vec;
|
||||||
|
use slice::SliceExt as StdSliceExt;
|
||||||
|
use str;
|
||||||
|
use string::{String, CowString};
|
||||||
|
use mem;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Buf {
|
||||||
|
pub inner: Vec<u8>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Slice {
|
||||||
|
pub inner: [u8]
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for Slice {
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
|
self.to_string_lossy().fmt(formatter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for Buf {
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
|
self.as_slice().fmt(formatter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Buf {
|
||||||
|
pub fn from_string(s: String) -> Buf {
|
||||||
|
Buf { inner: s.into_bytes() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_str(s: &str) -> Buf {
|
||||||
|
Buf { inner: s.as_bytes().to_vec() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_slice(&self) -> &Slice {
|
||||||
|
unsafe { mem::transmute(self.inner.as_slice()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_string(self) -> Result<String, Buf> {
|
||||||
|
String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() } )
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_slice(&mut self, s: &Slice) {
|
||||||
|
self.inner.push_all(&s.inner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Slice {
|
||||||
|
fn from_u8_slice(s: &[u8]) -> &Slice {
|
||||||
|
unsafe { mem::transmute(s) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_str(s: &str) -> &Slice {
|
||||||
|
unsafe { mem::transmute(s.as_bytes()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_str(&self) -> Option<&str> {
|
||||||
|
str::from_utf8(&self.inner).ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_string_lossy(&self) -> CowString {
|
||||||
|
String::from_utf8_lossy(&self.inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_owned(&self) -> Buf {
|
||||||
|
Buf { inner: self.inner.to_vec() }
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,14 +11,22 @@
|
||||||
use prelude::v1::*;
|
use prelude::v1::*;
|
||||||
|
|
||||||
use sys::fs::FileDesc;
|
use sys::fs::FileDesc;
|
||||||
use libc::{self, c_int};
|
use libc::{self, c_int, c_ulong, funcs};
|
||||||
use io::{self, IoResult, IoError};
|
use io::{self, IoResult, IoError};
|
||||||
|
use sys::c;
|
||||||
use sys_common;
|
use sys_common;
|
||||||
|
|
||||||
pub struct TTY {
|
pub struct TTY {
|
||||||
pub fd: FileDesc,
|
pub fd: FileDesc,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "macos",
|
||||||
|
target_os = "freebsd"))]
|
||||||
|
const TIOCGWINSZ: c_ulong = 0x40087468;
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
|
const TIOCGWINSZ: c_ulong = 0x00005413;
|
||||||
|
|
||||||
impl TTY {
|
impl TTY {
|
||||||
pub fn new(fd: c_int) -> IoResult<TTY> {
|
pub fn new(fd: c_int) -> IoResult<TTY> {
|
||||||
if unsafe { libc::isatty(fd) } != 0 {
|
if unsafe { libc::isatty(fd) } != 0 {
|
||||||
|
@ -41,8 +49,39 @@ impl TTY {
|
||||||
pub fn set_raw(&mut self, _raw: bool) -> IoResult<()> {
|
pub fn set_raw(&mut self, _raw: bool) -> IoResult<()> {
|
||||||
Err(sys_common::unimpl())
|
Err(sys_common::unimpl())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "linux",
|
||||||
|
target_os = "android",
|
||||||
|
target_os = "macos",
|
||||||
|
target_os = "freebsd"))]
|
||||||
|
pub fn get_winsize(&mut self) -> IoResult<(int, int)> {
|
||||||
|
unsafe {
|
||||||
|
#[repr(C)]
|
||||||
|
struct winsize {
|
||||||
|
ws_row: u16,
|
||||||
|
ws_col: u16,
|
||||||
|
ws_xpixel: u16,
|
||||||
|
ws_ypixel: u16
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut size = winsize { ws_row: 0, ws_col: 0, ws_xpixel: 0, ws_ypixel: 0 };
|
||||||
|
if c::ioctl(self.fd.fd(), TIOCGWINSZ, &mut size) == -1 {
|
||||||
|
Err(IoError {
|
||||||
|
kind: io::OtherIoError,
|
||||||
|
desc: "Size of terminal could not be determined",
|
||||||
|
detail: None,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Ok((size.ws_col as int, size.ws_row as int))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "ios",
|
||||||
|
target_os = "dragonfly"))]
|
||||||
pub fn get_winsize(&mut self) -> IoResult<(int, int)> {
|
pub fn get_winsize(&mut self) -> IoResult<(int, int)> {
|
||||||
Err(sys_common::unimpl())
|
Err(sys_common::unimpl())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isatty(&self) -> bool { false }
|
pub fn isatty(&self) -> bool { false }
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,11 @@
|
||||||
|
|
||||||
#![unstable(feature = "std_misc")]
|
#![unstable(feature = "std_misc")]
|
||||||
|
|
||||||
use sys_common::AsInner;
|
pub use sys_common::wtf8::{Wtf8Buf, EncodeWide};
|
||||||
|
|
||||||
|
use sys::os_str::Buf;
|
||||||
|
use sys_common::{AsInner, FromInner};
|
||||||
|
use ffi::{OsStr, OsString};
|
||||||
use libc;
|
use libc;
|
||||||
|
|
||||||
use io;
|
use io;
|
||||||
|
@ -92,9 +96,35 @@ impl AsRawSocket for io::net::udp::UdpSocket {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Windows-specific extensions to `OsString`.
|
||||||
|
pub trait OsStringExt {
|
||||||
|
/// Create an `OsString` from a potentially ill-formed UTF-16 slice of 16-bit code units.
|
||||||
|
///
|
||||||
|
/// This is lossless: calling `.encode_wide()` on the resulting string
|
||||||
|
/// will always return the original code units.
|
||||||
|
fn from_wide(wide: &[u16]) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OsStringExt for OsString {
|
||||||
|
fn from_wide(wide: &[u16]) -> OsString {
|
||||||
|
FromInner::from_inner(Buf { inner: Wtf8Buf::from_wide(wide) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Windows-specific extensions to `OsStr`.
|
||||||
|
pub trait OsStrExt {
|
||||||
|
fn encode_wide(&self) -> EncodeWide;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OsStrExt for OsStr {
|
||||||
|
fn encode_wide(&self) -> EncodeWide {
|
||||||
|
self.as_inner().inner.encode_wide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A prelude for conveniently writing platform-specific code.
|
/// A prelude for conveniently writing platform-specific code.
|
||||||
///
|
///
|
||||||
/// Includes all extension traits, and some important type definitions.
|
/// Includes all extension traits, and some important type definitions.
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use super::{Socket, Handle, AsRawSocket, AsRawHandle};
|
pub use super::{Socket, Handle, AsRawSocket, AsRawHandle, OsStrExt, OsStringExt};
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ pub mod fs;
|
||||||
pub mod helper_signal;
|
pub mod helper_signal;
|
||||||
pub mod mutex;
|
pub mod mutex;
|
||||||
pub mod os;
|
pub mod os;
|
||||||
|
pub mod os_str;
|
||||||
pub mod pipe;
|
pub mod pipe;
|
||||||
pub mod process;
|
pub mod process;
|
||||||
pub mod rwlock;
|
pub mod rwlock;
|
||||||
|
|
82
src/libstd/sys/windows/os_str.rs
Normal file
82
src/libstd/sys/windows/os_str.rs
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
/// The underlying OsString/OsStr implementation on Windows is a
|
||||||
|
/// wrapper around the "WTF-8" encoding; see the `wtf8` module for more.
|
||||||
|
|
||||||
|
use fmt::{self, Debug};
|
||||||
|
use sys_common::wtf8::{Wtf8, Wtf8Buf};
|
||||||
|
use string::{String, CowString};
|
||||||
|
use result::Result;
|
||||||
|
use option::Option;
|
||||||
|
use mem;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Buf {
|
||||||
|
pub inner: Wtf8Buf
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for Buf {
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
|
self.as_slice().fmt(formatter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Slice {
|
||||||
|
pub inner: Wtf8
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for Slice {
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
|
self.inner.fmt(formatter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Buf {
|
||||||
|
pub fn from_string(s: String) -> Buf {
|
||||||
|
Buf { inner: Wtf8Buf::from_string(s) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_str(s: &str) -> Buf {
|
||||||
|
Buf { inner: Wtf8Buf::from_str(s) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_slice(&self) -> &Slice {
|
||||||
|
unsafe { mem::transmute(self.inner.as_slice()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_string(self) -> Result<String, Buf> {
|
||||||
|
self.inner.into_string().map_err(|buf| Buf { inner: buf })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_slice(&mut self, s: &Slice) {
|
||||||
|
self.inner.push_wtf8(&s.inner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Slice {
|
||||||
|
pub fn from_str(s: &str) -> &Slice {
|
||||||
|
unsafe { mem::transmute(Wtf8::from_str(s)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_str(&self) -> Option<&str> {
|
||||||
|
self.inner.as_str()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_string_lossy(&self) -> CowString {
|
||||||
|
self.inner.to_string_lossy()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_owned(&self) -> Buf {
|
||||||
|
let mut buf = Wtf8Buf::with_capacity(self.inner.len());
|
||||||
|
buf.push_wtf8(&self.inner);
|
||||||
|
Buf { inner: buf }
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,7 +13,7 @@
|
||||||
pub use self::AsmDialect::*;
|
pub use self::AsmDialect::*;
|
||||||
pub use self::AttrStyle::*;
|
pub use self::AttrStyle::*;
|
||||||
pub use self::BindingMode::*;
|
pub use self::BindingMode::*;
|
||||||
pub use self::BinOp::*;
|
pub use self::BinOp_::*;
|
||||||
pub use self::BlockCheckMode::*;
|
pub use self::BlockCheckMode::*;
|
||||||
pub use self::CaptureClause::*;
|
pub use self::CaptureClause::*;
|
||||||
pub use self::Decl_::*;
|
pub use self::Decl_::*;
|
||||||
|
@ -582,7 +582,7 @@ pub enum Mutability {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)]
|
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)]
|
||||||
pub enum BinOp {
|
pub enum BinOp_ {
|
||||||
BiAdd,
|
BiAdd,
|
||||||
BiSub,
|
BiSub,
|
||||||
BiMul,
|
BiMul,
|
||||||
|
@ -603,6 +603,8 @@ pub enum BinOp {
|
||||||
BiGt,
|
BiGt,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type BinOp = Spanned<BinOp_>;
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)]
|
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)]
|
||||||
pub enum UnOp {
|
pub enum UnOp {
|
||||||
UnUniq,
|
UnUniq,
|
||||||
|
|
|
@ -46,7 +46,7 @@ pub fn stmt_id(s: &Stmt) -> NodeId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn binop_to_string(op: BinOp) -> &'static str {
|
pub fn binop_to_string(op: BinOp_) -> &'static str {
|
||||||
match op {
|
match op {
|
||||||
BiAdd => "+",
|
BiAdd => "+",
|
||||||
BiSub => "-",
|
BiSub => "-",
|
||||||
|
@ -69,7 +69,7 @@ pub fn binop_to_string(op: BinOp) -> &'static str {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lazy_binop(b: BinOp) -> bool {
|
pub fn lazy_binop(b: BinOp_) -> bool {
|
||||||
match b {
|
match b {
|
||||||
BiAnd => true,
|
BiAnd => true,
|
||||||
BiOr => true,
|
BiOr => true,
|
||||||
|
@ -77,7 +77,7 @@ pub fn lazy_binop(b: BinOp) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_shift_binop(b: BinOp) -> bool {
|
pub fn is_shift_binop(b: BinOp_) -> bool {
|
||||||
match b {
|
match b {
|
||||||
BiShl => true,
|
BiShl => true,
|
||||||
BiShr => true,
|
BiShr => true,
|
||||||
|
@ -85,7 +85,7 @@ pub fn is_shift_binop(b: BinOp) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_comparison_binop(b: BinOp) -> bool {
|
pub fn is_comparison_binop(b: BinOp_) -> bool {
|
||||||
match b {
|
match b {
|
||||||
BiEq | BiLt | BiLe | BiNe | BiGt | BiGe => true,
|
BiEq | BiLt | BiLe | BiNe | BiGt | BiGe => true,
|
||||||
_ => false
|
_ => false
|
||||||
|
@ -93,7 +93,7 @@ pub fn is_comparison_binop(b: BinOp) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the binary operator takes its arguments by value
|
/// Returns `true` if the binary operator takes its arguments by value
|
||||||
pub fn is_by_value_binop(b: BinOp) -> bool {
|
pub fn is_by_value_binop(b: BinOp_) -> bool {
|
||||||
match b {
|
match b {
|
||||||
BiAdd | BiSub | BiMul | BiDiv | BiRem | BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr => {
|
BiAdd | BiSub | BiMul | BiDiv | BiRem | BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr => {
|
||||||
true
|
true
|
||||||
|
@ -319,7 +319,7 @@ pub fn struct_field_visibility(field: ast::StructField) -> Visibility {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Maps a binary operator to its precedence
|
/// Maps a binary operator to its precedence
|
||||||
pub fn operator_prec(op: ast::BinOp) -> usize {
|
pub fn operator_prec(op: ast::BinOp_) -> usize {
|
||||||
match op {
|
match op {
|
||||||
// 'as' sits here with 12
|
// 'as' sits here with 12
|
||||||
BiMul | BiDiv | BiRem => 11us,
|
BiMul | BiDiv | BiRem => 11us,
|
||||||
|
|
|
@ -106,7 +106,7 @@ pub trait AstBuilder {
|
||||||
fn expr_ident(&self, span: Span, id: ast::Ident) -> P<ast::Expr>;
|
fn expr_ident(&self, span: Span, id: ast::Ident) -> P<ast::Expr>;
|
||||||
|
|
||||||
fn expr_self(&self, span: Span) -> P<ast::Expr>;
|
fn expr_self(&self, span: Span) -> P<ast::Expr>;
|
||||||
fn expr_binary(&self, sp: Span, op: ast::BinOp,
|
fn expr_binary(&self, sp: Span, op: ast::BinOp_,
|
||||||
lhs: P<ast::Expr>, rhs: P<ast::Expr>) -> P<ast::Expr>;
|
lhs: P<ast::Expr>, rhs: P<ast::Expr>) -> P<ast::Expr>;
|
||||||
fn expr_deref(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr>;
|
fn expr_deref(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr>;
|
||||||
fn expr_unary(&self, sp: Span, op: ast::UnOp, e: P<ast::Expr>) -> P<ast::Expr>;
|
fn expr_unary(&self, sp: Span, op: ast::UnOp, e: P<ast::Expr>) -> P<ast::Expr>;
|
||||||
|
@ -561,9 +561,9 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||||
self.expr_ident(span, special_idents::self_)
|
self.expr_ident(span, special_idents::self_)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expr_binary(&self, sp: Span, op: ast::BinOp,
|
fn expr_binary(&self, sp: Span, op: ast::BinOp_,
|
||||||
lhs: P<ast::Expr>, rhs: P<ast::Expr>) -> P<ast::Expr> {
|
lhs: P<ast::Expr>, rhs: P<ast::Expr>) -> P<ast::Expr> {
|
||||||
self.expr(sp, ast::ExprBinary(op, lhs, rhs))
|
self.expr(sp, ast::ExprBinary(Spanned { node: op, span: sp }, lhs, rhs))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expr_deref(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
|
fn expr_deref(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
|
||||||
|
|
|
@ -1449,7 +1449,7 @@ pub fn cs_same_method_fold<F>(use_foldl: bool,
|
||||||
/// Use a given binop to combine the result of calling the derived method
|
/// Use a given binop to combine the result of calling the derived method
|
||||||
/// on all the fields.
|
/// on all the fields.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn cs_binop(binop: ast::BinOp, base: P<Expr>,
|
pub fn cs_binop(binop: ast::BinOp_, base: P<Expr>,
|
||||||
enum_nonmatch_f: EnumNonMatchCollapsedFunc,
|
enum_nonmatch_f: EnumNonMatchCollapsedFunc,
|
||||||
cx: &mut ExtCtxt, trait_span: Span,
|
cx: &mut ExtCtxt, trait_span: Span,
|
||||||
substructure: &Substructure) -> P<Expr> {
|
substructure: &Substructure) -> P<Expr> {
|
||||||
|
|
|
@ -2840,6 +2840,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
self.expected_tokens.push(TokenType::Operator);
|
self.expected_tokens.push(TokenType::Operator);
|
||||||
|
|
||||||
|
let cur_op_span = self.span;
|
||||||
let cur_opt = self.token.to_binop();
|
let cur_opt = self.token.to_binop();
|
||||||
match cur_opt {
|
match cur_opt {
|
||||||
Some(cur_op) => {
|
Some(cur_op) => {
|
||||||
|
@ -2853,7 +2854,7 @@ impl<'a> Parser<'a> {
|
||||||
let rhs = self.parse_more_binops(expr, cur_prec + 1);
|
let rhs = self.parse_more_binops(expr, cur_prec + 1);
|
||||||
let lhs_span = lhs.span;
|
let lhs_span = lhs.span;
|
||||||
let rhs_span = rhs.span;
|
let rhs_span = rhs.span;
|
||||||
let binary = self.mk_binary(cur_op, lhs, rhs);
|
let binary = self.mk_binary(codemap::respan(cur_op_span, cur_op), lhs, rhs);
|
||||||
let bin = self.mk_expr(lhs_span.lo, rhs_span.hi, binary);
|
let bin = self.mk_expr(lhs_span.lo, rhs_span.hi, binary);
|
||||||
self.parse_more_binops(bin, min_prec)
|
self.parse_more_binops(bin, min_prec)
|
||||||
} else {
|
} else {
|
||||||
|
@ -2877,16 +2878,17 @@ impl<'a> Parser<'a> {
|
||||||
/// Produce an error if comparison operators are chained (RFC #558).
|
/// Produce an error if comparison operators are chained (RFC #558).
|
||||||
/// We only need to check lhs, not rhs, because all comparison ops
|
/// We only need to check lhs, not rhs, because all comparison ops
|
||||||
/// have same precedence and are left-associative
|
/// have same precedence and are left-associative
|
||||||
fn check_no_chained_comparison(&mut self, lhs: &Expr, outer_op: ast::BinOp) {
|
fn check_no_chained_comparison(&mut self, lhs: &Expr, outer_op: ast::BinOp_) {
|
||||||
debug_assert!(ast_util::is_comparison_binop(outer_op));
|
debug_assert!(ast_util::is_comparison_binop(outer_op));
|
||||||
match lhs.node {
|
match lhs.node {
|
||||||
ExprBinary(op, _, _) if ast_util::is_comparison_binop(op) => {
|
ExprBinary(op, _, _) if ast_util::is_comparison_binop(op.node) => {
|
||||||
let op_span = self.span;
|
// respan to include both operators
|
||||||
|
let op_span = mk_sp(op.span.lo, self.span.hi);
|
||||||
self.span_err(op_span,
|
self.span_err(op_span,
|
||||||
"Chained comparison operators require parentheses");
|
"chained comparison operators require parentheses");
|
||||||
if op == BiLt && outer_op == BiGt {
|
if op.node == BiLt && outer_op == BiGt {
|
||||||
self.span_help(op_span,
|
self.span_help(op_span,
|
||||||
"use ::< instead of < if you meant to specify type arguments");
|
"use `::<...>` instead of `<...>` if you meant to specify type arguments");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -2919,6 +2921,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
pub fn parse_assign_expr_with(&mut self, lhs: P<Expr>) -> P<Expr> {
|
pub fn parse_assign_expr_with(&mut self, lhs: P<Expr>) -> P<Expr> {
|
||||||
let restrictions = self.restrictions & RESTRICTION_NO_STRUCT_LITERAL;
|
let restrictions = self.restrictions & RESTRICTION_NO_STRUCT_LITERAL;
|
||||||
|
let op_span = self.span;
|
||||||
match self.token {
|
match self.token {
|
||||||
token::Eq => {
|
token::Eq => {
|
||||||
self.bump();
|
self.bump();
|
||||||
|
@ -2942,7 +2945,7 @@ impl<'a> Parser<'a> {
|
||||||
};
|
};
|
||||||
let rhs_span = rhs.span;
|
let rhs_span = rhs.span;
|
||||||
let span = lhs.span;
|
let span = lhs.span;
|
||||||
let assign_op = self.mk_assign_op(aop, lhs, rhs);
|
let assign_op = self.mk_assign_op(codemap::respan(op_span, aop), lhs, rhs);
|
||||||
self.mk_expr(span.lo, rhs_span.hi, assign_op)
|
self.mk_expr(span.lo, rhs_span.hi, assign_op)
|
||||||
}
|
}
|
||||||
// A range expression, either `expr..expr` or `expr..`.
|
// A range expression, either `expr..expr` or `expr..`.
|
||||||
|
|
|
@ -249,7 +249,7 @@ impl Token {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Maps a token to its corresponding binary operator.
|
/// Maps a token to its corresponding binary operator.
|
||||||
pub fn to_binop(&self) -> Option<ast::BinOp> {
|
pub fn to_binop(&self) -> Option<ast::BinOp_> {
|
||||||
match *self {
|
match *self {
|
||||||
BinOp(Star) => Some(ast::BiMul),
|
BinOp(Star) => Some(ast::BiMul),
|
||||||
BinOp(Slash) => Some(ast::BiDiv),
|
BinOp(Slash) => Some(ast::BiDiv),
|
||||||
|
|
|
@ -1627,7 +1627,7 @@ impl<'a> State<'a> {
|
||||||
rhs: &ast::Expr) -> IoResult<()> {
|
rhs: &ast::Expr) -> IoResult<()> {
|
||||||
try!(self.print_expr(lhs));
|
try!(self.print_expr(lhs));
|
||||||
try!(space(&mut self.s));
|
try!(space(&mut self.s));
|
||||||
try!(self.word_space(ast_util::binop_to_string(op)));
|
try!(self.word_space(ast_util::binop_to_string(op.node)));
|
||||||
self.print_expr(rhs)
|
self.print_expr(rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1795,7 +1795,7 @@ impl<'a> State<'a> {
|
||||||
ast::ExprAssignOp(op, ref lhs, ref rhs) => {
|
ast::ExprAssignOp(op, ref lhs, ref rhs) => {
|
||||||
try!(self.print_expr(&**lhs));
|
try!(self.print_expr(&**lhs));
|
||||||
try!(space(&mut self.s));
|
try!(space(&mut self.s));
|
||||||
try!(word(&mut self.s, ast_util::binop_to_string(op)));
|
try!(word(&mut self.s, ast_util::binop_to_string(op.node)));
|
||||||
try!(self.word_space("="));
|
try!(self.word_space("="));
|
||||||
try!(self.print_expr(&**rhs));
|
try!(self.print_expr(&**rhs));
|
||||||
}
|
}
|
||||||
|
|
|
@ -313,6 +313,7 @@ fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
|
||||||
&ast::ItemFn(ref decl, _, _, ref generics, _) => {
|
&ast::ItemFn(ref decl, _, _, ref generics, _) => {
|
||||||
let no_output = match decl.output {
|
let no_output = match decl.output {
|
||||||
ast::DefaultReturn(..) => true,
|
ast::DefaultReturn(..) => true,
|
||||||
|
ast::Return(ref t) if t.node == ast::TyTup(vec![]) => true,
|
||||||
_ => false
|
_ => false
|
||||||
};
|
};
|
||||||
if decl.inputs.is_empty()
|
if decl.inputs.is_empty()
|
||||||
|
@ -349,6 +350,7 @@ fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
|
||||||
let input_cnt = decl.inputs.len();
|
let input_cnt = decl.inputs.len();
|
||||||
let no_output = match decl.output {
|
let no_output = match decl.output {
|
||||||
ast::DefaultReturn(..) => true,
|
ast::DefaultReturn(..) => true,
|
||||||
|
ast::Return(ref t) if t.node == ast::TyTup(vec![]) => true,
|
||||||
_ => false
|
_ => false
|
||||||
};
|
};
|
||||||
let tparm_cnt = generics.ty_params.len();
|
let tparm_cnt = generics.ty_params.len();
|
||||||
|
|
|
@ -894,6 +894,22 @@ LLVMUnpackOptimizationDiagnostic(
|
||||||
*message_out = wrap(&opt->getMsg());
|
*message_out = wrap(&opt->getMsg());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
LLVMUnpackInlineAsmDiagnostic(
|
||||||
|
LLVMDiagnosticInfoRef di,
|
||||||
|
unsigned *cookie_out,
|
||||||
|
LLVMTwineRef *message_out,
|
||||||
|
LLVMValueRef *instruction_out)
|
||||||
|
{
|
||||||
|
// Undefined to call this not on an inline assembly diagnostic!
|
||||||
|
llvm::DiagnosticInfoInlineAsm *ia
|
||||||
|
= static_cast<llvm::DiagnosticInfoInlineAsm*>(unwrap(di));
|
||||||
|
|
||||||
|
*cookie_out = ia->getLocCookie();
|
||||||
|
*message_out = wrap(&ia->getMsgStr());
|
||||||
|
*instruction_out = wrap(ia->getInstruction());
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" void LLVMWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef di, RustStringRef str) {
|
extern "C" void LLVMWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef di, RustStringRef str) {
|
||||||
raw_rust_string_ostream os(str);
|
raw_rust_string_ostream os(str);
|
||||||
DiagnosticPrinterRawOStream dp(os);
|
DiagnosticPrinterRawOStream dp(os);
|
||||||
|
|
22
src/test/compile-fail/issue-19660.rs
Normal file
22
src/test/compile-fail/issue-19660.rs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// error-pattern: requires `copy` lang_item
|
||||||
|
|
||||||
|
#![feature(lang_items, start)]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
#[lang = "sized"]
|
||||||
|
trait Sized {}
|
||||||
|
|
||||||
|
#[start]
|
||||||
|
fn main(_: int, _: *const *const u8) -> int {
|
||||||
|
0
|
||||||
|
}
|
66
src/test/compile-fail/lint-unconditional-recursion.rs
Normal file
66
src/test/compile-fail/lint-unconditional-recursion.rs
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
// Copyright 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.
|
||||||
|
|
||||||
|
#![deny(unconditional_recursion)]
|
||||||
|
#![allow(dead_code)]
|
||||||
|
fn foo() { //~ ERROR function cannot return without recurring
|
||||||
|
foo(); //~ NOTE recursive call site
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bar() {
|
||||||
|
if true {
|
||||||
|
bar()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn baz() { //~ ERROR function cannot return without recurring
|
||||||
|
if true {
|
||||||
|
baz() //~ NOTE recursive call site
|
||||||
|
} else {
|
||||||
|
baz() //~ NOTE recursive call site
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn qux() {
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn quz() -> bool { //~ ERROR function cannot return without recurring
|
||||||
|
if true {
|
||||||
|
while quz() {} //~ NOTE recursive call site
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
loop { quz(); } //~ NOTE recursive call site
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Foo {
|
||||||
|
fn bar(&self) { //~ ERROR function cannot return without recurring
|
||||||
|
self.bar() //~ NOTE recursive call site
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Foo for Box<Foo+'static> {
|
||||||
|
fn bar(&self) { //~ ERROR function cannot return without recurring
|
||||||
|
loop {
|
||||||
|
self.bar() //~ NOTE recursive call site
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Baz;
|
||||||
|
impl Baz {
|
||||||
|
fn qux(&self) { //~ ERROR function cannot return without recurring
|
||||||
|
self.qux(); //~ NOTE recursive call site
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -12,12 +12,12 @@ fn f<T>() {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
false == false == false;
|
false == false == false;
|
||||||
//~^ ERROR: Chained comparison operators require parentheses
|
//~^ ERROR: chained comparison operators require parentheses
|
||||||
|
|
||||||
false == 0 < 2;
|
false == 0 < 2;
|
||||||
//~^ ERROR: Chained comparison operators require parentheses
|
//~^ ERROR: chained comparison operators require parentheses
|
||||||
|
|
||||||
f<X>();
|
f<X>();
|
||||||
//~^ ERROR: Chained comparison operators require parentheses
|
//~^ ERROR: chained comparison operators require parentheses
|
||||||
//~^^ HELP: use ::< instead of < if you meant to specify type arguments
|
//~^^ HELP: use `::<...>` instead of `<...>`
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,6 @@ fn f<X>() {}
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
f<type>();
|
f<type>();
|
||||||
//~^ ERROR expected identifier, found keyword `type`
|
//~^ ERROR expected identifier, found keyword `type`
|
||||||
//~^^ ERROR: Chained comparison operators require parentheses
|
//~^^ ERROR: chained comparison
|
||||||
//~^^^ HELP: use ::< instead of < if you meant to specify type arguments
|
//~^^^ HELP: use `::<
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,12 @@
|
||||||
// gdb-command:print void_droid_gdb->internals
|
// gdb-command:print void_droid_gdb->internals
|
||||||
// gdb-check:$6 = (isize *) 0x0
|
// gdb-check:$6 = (isize *) 0x0
|
||||||
|
|
||||||
|
// gdb-command:print nested_non_zero_yep
|
||||||
|
// gdb-check:$7 = {RUST$ENCODED$ENUM$1$2$Nope = {10.5, {a = 10, b = 20, c = [...]}}}
|
||||||
|
|
||||||
|
// gdb-command:print nested_non_zero_nope
|
||||||
|
// gdb-check:$8 = {RUST$ENCODED$ENUM$1$2$Nope = {[...], {a = [...], b = [...], c = 0x0}}}
|
||||||
|
|
||||||
// gdb-command:continue
|
// gdb-command:continue
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,6 +73,12 @@
|
||||||
// lldb-command:print none_str
|
// lldb-command:print none_str
|
||||||
// lldb-check:[...]$7 = None
|
// lldb-check:[...]$7 = None
|
||||||
|
|
||||||
|
// lldb-command:print nested_non_zero_yep
|
||||||
|
// lldb-check:[...]$8 = Yep(10.5, NestedNonZeroField { a: 10, b: 20, c: &[...] })
|
||||||
|
|
||||||
|
// lldb-command:print nested_non_zero_nope
|
||||||
|
// lldb-check:[...]$9 = Nope
|
||||||
|
|
||||||
|
|
||||||
#![omit_gdb_pretty_printer_section]
|
#![omit_gdb_pretty_printer_section]
|
||||||
|
|
||||||
|
@ -102,6 +114,17 @@ struct NamedFieldsRepr<'a> {
|
||||||
internals: &'a isize
|
internals: &'a isize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct NestedNonZeroField<'a> {
|
||||||
|
a: u16,
|
||||||
|
b: u32,
|
||||||
|
c: &'a char,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum NestedNonZero<'a> {
|
||||||
|
Yep(f64, NestedNonZeroField<'a>),
|
||||||
|
Nope
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
||||||
let some_str: Option<&'static str> = Some("abc");
|
let some_str: Option<&'static str> = Some("abc");
|
||||||
|
@ -124,6 +147,17 @@ fn main() {
|
||||||
let void_droid = NamedFields::Void;
|
let void_droid = NamedFields::Void;
|
||||||
let void_droid_gdb: &NamedFieldsRepr = unsafe { std::mem::transmute(&NamedFields::Void) };
|
let void_droid_gdb: &NamedFieldsRepr = unsafe { std::mem::transmute(&NamedFields::Void) };
|
||||||
|
|
||||||
|
let x = 'x';
|
||||||
|
let nested_non_zero_yep = NestedNonZero::Yep(
|
||||||
|
10.5,
|
||||||
|
NestedNonZeroField {
|
||||||
|
a: 10,
|
||||||
|
b: 20,
|
||||||
|
c: &x
|
||||||
|
});
|
||||||
|
|
||||||
|
let nested_non_zero_nope = NestedNonZero::Nope;
|
||||||
|
|
||||||
zzz(); // #break
|
zzz(); // #break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,33 +8,54 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::io::{TempDir, Command, fs};
|
use std::slice::SliceExt;
|
||||||
|
use std::io::{Command, fs, USER_RWX};
|
||||||
use std::os;
|
use std::os;
|
||||||
|
use std::path::BytesContainer;
|
||||||
|
use std::rand::random;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// If we're the child, make sure we were invoked correctly
|
// If we're the child, make sure we were invoked correctly
|
||||||
let args = os::args();
|
let args = os::args();
|
||||||
if args.len() > 1 && args[1].as_slice() == "child" {
|
if args.len() > 1 && args[1].as_slice() == "child" {
|
||||||
return assert_eq!(args[0].as_slice(), "mytest");
|
// FIXME: This should check the whole `args[0]` instead of just
|
||||||
|
// checking that it ends_with the executable name. This
|
||||||
|
// is needed because of Windows, which has a different behavior.
|
||||||
|
// See #15149 for more info.
|
||||||
|
return assert!(args[0].ends_with(&format!("mytest{}", os::consts::EXE_SUFFIX)[]));
|
||||||
}
|
}
|
||||||
|
|
||||||
test();
|
test();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test() {
|
fn test() {
|
||||||
// If we're the parent, copy our own binary to a tempr directory, and then
|
// If we're the parent, copy our own binary to a new directory.
|
||||||
// make it executable.
|
let my_path = os::self_exe_name().unwrap();
|
||||||
let dir = TempDir::new("mytest").unwrap();
|
let my_dir = my_path.dir_path();
|
||||||
let me = os::self_exe_name().unwrap();
|
|
||||||
let dest = dir.path().join(format!("mytest{}", os::consts::EXE_SUFFIX));
|
|
||||||
fs::copy(&me, &dest).unwrap();
|
|
||||||
|
|
||||||
// Append the temp directory to our own PATH.
|
let random_u32: u32 = random();
|
||||||
|
let child_dir = Path::new(my_dir.join(format!("issue-15149-child-{}",
|
||||||
|
random_u32)));
|
||||||
|
fs::mkdir(&child_dir, USER_RWX).unwrap();
|
||||||
|
|
||||||
|
let child_path = child_dir.join(format!("mytest{}",
|
||||||
|
os::consts::EXE_SUFFIX));
|
||||||
|
fs::copy(&my_path, &child_path).unwrap();
|
||||||
|
|
||||||
|
// Append the new directory to our own PATH.
|
||||||
let mut path = os::split_paths(os::getenv("PATH").unwrap_or(String::new()));
|
let mut path = os::split_paths(os::getenv("PATH").unwrap_or(String::new()));
|
||||||
path.push(dir.path().clone());
|
path.push(child_dir.clone());
|
||||||
let path = os::join_paths(path.as_slice()).unwrap();
|
let path = os::join_paths(path.as_slice()).unwrap();
|
||||||
|
|
||||||
Command::new("mytest").env("PATH", path.as_slice())
|
let child_output = Command::new("mytest").env("PATH", path.as_slice())
|
||||||
.arg("child")
|
.arg("child")
|
||||||
.spawn().unwrap();
|
.output().unwrap();
|
||||||
|
|
||||||
|
assert!(child_output.status.success(),
|
||||||
|
format!("child assertion failed\n child stdout:\n {}\n child stderr:\n {}",
|
||||||
|
child_output.output.container_as_str().unwrap(),
|
||||||
|
child_output.error.container_as_str().unwrap()));
|
||||||
|
|
||||||
|
fs::rmdir_recursive(&child_dir).unwrap();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// compile-flags: --test
|
||||||
|
// no-pretty-expanded
|
||||||
|
extern crate test;
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn bench_explicit_return_type(_: &mut ::test::Bencher) -> () {}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_explicit_return_type() -> () {}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue