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:
Brian Anderson 2015-01-25 19:03:10 -08:00
commit d179ba3b8e
88 changed files with 5485 additions and 559 deletions

7
configure vendored
View File

@ -28,8 +28,8 @@ need_ok() {
need_cmd() {
if command -v $1 >/dev/null 2>&1
then msg "found $1"
else err "need $1"
then msg "found program $1"
else err "need program $1"
fi
}
@ -340,6 +340,7 @@ need_cmd date
need_cmd tr
need_cmd sed
need_cmd file
need_cmd make
msg "inspecting environment"
@ -645,6 +646,8 @@ probe CFG_ISCC iscc
probe CFG_JAVAC javac
probe CFG_ANTLR4 antlr4
probe CFG_GRUN grun
probe CFG_FLEX flex
probe CFG_BISON bison
probe CFG_PANDOC pandoc
probe CFG_PDFLATEX pdflatex
probe CFG_XELATEX xelatex

View File

@ -14,6 +14,11 @@ B = $(CFG_BUILD_DIR)/$(CFG_BUILD)/stage2/
L = $(B)lib/rustlib/$(CFG_BUILD)/lib
LD = $(CFG_BUILD)/stage2/lib/rustlib/$(CFG_BUILD)/lib/
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.
# 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:
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

View File

@ -30,8 +30,8 @@ CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)
CFG_DISABLE_UNSTABLE_FEATURES=1
endif
ifeq ($(CFG_RELEASE_CHANNEL),beta)
CFG_RELEASE=$(CFG_RELEASE_NUM)-beta(CFG_PRERELEASE_VERSION)
CFG_PACKAGE_VERS=$(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_DISABLE_UNSTABLE_FEATURES=1
endif
ifeq ($(CFG_RELEASE_CHANNEL),nightly)

View File

@ -12,6 +12,20 @@ pub use self::Mode::*;
use std::fmt;
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)]
pub enum Mode {
CompileFail,
@ -24,6 +38,7 @@ pub enum Mode {
Codegen
}
impl Copy for Mode {}
impl FromStr for Mode {

View File

@ -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
to the string equality function.
A complete list of the built-in language items follows:
#### 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`.
A complete list of the built-in language items will be added in the future.
### Inline attributes
@ -2581,9 +2452,7 @@ The currently implemented features of the reference compiler are:
declare a `static` as being unique per-thread leveraging
LLVM's implementation which works in concert with the kernel
loader and dynamic linker. This is not necessarily available
on all platforms, and usage of it is discouraged (rust
focuses more on thread-local data instead of thread-local
data).
on all platforms, and usage of it is discouraged.
* `trace_macros` - Allows use of the `trace_macros` macro, which is a nasty
hack that will certainly be removed.

View File

@ -83,7 +83,6 @@ If not, there are a number of places where you can get help. The easiest is
you can access through
[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
call ourselves), and we can help you out. Other great resources include [our
forum](http://discuss.rust-lang.org/), [the /r/rust
subreddit](http://www.reddit.com/r/rust), and [Stack
call ourselves), and we can help you out. Other great resources include [the
/r/rust subreddit](http://www.reddit.com/r/rust), and [Stack
Overflow](http://stackoverflow.com/questions/tagged/rust).

View File

@ -18,6 +18,8 @@ x.foo().bar().baz();
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.
## Method calls
Here's how it works:
```{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
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
pattern that's very common in Rust code:
```{rust}
# #![allow(non_shorthand_field_patterns)]
```
struct Circle {
x: 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()`
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.

View File

@ -14,11 +14,10 @@
import sys, os, re
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):
if "src/test" in dirpath or "src/llvm" in dirpath:
# Short circuit for fast
continue
@ -28,15 +27,12 @@ for (dirpath, dirnames, filenames) in os.walk(src_dir):
continue
path = os.path.join(dirpath, filename)
line_num = 1
with open(path, 'r') as f:
for line in f:
p = re.compile("(E\d\d\d\d)")
m = p.search(line)
if not m is None:
errcode = m.group(1)
for line_num, line in enumerate(f, start=1):
match = error_re.search(line)
if match:
errcode = match.group(1)
new_record = [(errcode, path, line_num, line)]
existing = errcode_map.get(errcode)
if existing is not None:
@ -45,26 +41,19 @@ for (dirpath, dirnames, filenames) in os.walk(src_dir):
else:
errcode_map[errcode] = new_record
line_num += 1
errors = False
all_errors = []
for errcode in errcode_map:
entries = errcode_map[errcode]
all_errors += [entries[0][0]]
for errcode, entries in errcode_map.items():
all_errors.append(entries[0][0])
if len(entries) > 1:
print "error: duplicate error code " + errcode
print("error: duplicate error code " + errcode)
for entry in entries:
print entry[1] + ": " + str(entry[2])
print entry[3]
print("{1}: {2}\n{3}".format(*entry))
errors = True
print str(len(errcode_map)) + " error codes"
all_errors.sort()
all_errors.reverse()
print "highest error code: " + all_errors[0]
print("{0} error codes".format(len(errcode_map)))
print("highest error code: " + max(all_errors))
if errors:
sys.exit(1)

View File

@ -8,29 +8,18 @@
# option. This file may not be copied, modified, or distributed
# except according to those terms.
license1 = """// Copyright """
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.
"""
import re
license3 = """# Copyright """
license4 = """ 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.
"""
license_re = re.compile(
u"""(#|//) Copyright .* The Rust Project Developers. See the COPYRIGHT
\\1 file at the top-level directory of this distribution and at
\\1 http://rust-lang.org/COPYRIGHT.
\\1
\\1 Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
\\1 http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
\\1 <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
\\1 option. This file may not be copied, modified, or distributed
\\1 except according to those terms.""")
exceptions = [
"rt/rust_android_dummy.cpp", # BSD, chromium
@ -57,18 +46,14 @@ exceptions = [
def check_license(name, contents):
# Whitelist check
for exception in exceptions:
if name.endswith(exception):
return True
if any(name.endswith(e) for e in exceptions):
return True
# Xfail check
firstlineish = contents[:100]
if firstlineish.find("ignore-license") != -1:
if "ignore-license" in firstlineish:
return True
# License check
boilerplate = contents[:500]
if (boilerplate.find(license1) == -1 or boilerplate.find(license2) == -1) and \
(boilerplate.find(license3) == -1 or boilerplate.find(license4) == -1):
return False
return True
return bool(license_re.search(boilerplate))

View File

@ -113,7 +113,7 @@ try:
if current_name != "":
do_license_check(current_name, current_contents)
except UnicodeDecodeError, e:
except UnicodeDecodeError as e:
report_err("UTF-8 decoding error " + str(e))

342
src/grammar/lexer.l Normal file
View 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; }
%%

View 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

File diff suppressed because it is too large Load Diff

65
src/grammar/testparser.py Executable file
View 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
View 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
};

View File

@ -589,7 +589,7 @@ impl AtomicUsize {
/// ```
/// use std::sync::atomic::AtomicUsize;
///
/// let atomic_forty_two = AtomicUsize::new(42u);
/// let atomic_forty_two = AtomicUsize::new(42);
/// ```
#[inline]
pub fn new(v: usize) -> AtomicUsize {
@ -765,7 +765,7 @@ impl<T> AtomicPtr<T> {
/// ```
/// use std::sync::atomic::AtomicPtr;
///
/// let ptr = &mut 5i;
/// let ptr = &mut 5;
/// let atomic_ptr = AtomicPtr::new(ptr);
/// ```
#[inline]
@ -787,7 +787,7 @@ impl<T> AtomicPtr<T> {
/// ```
/// use std::sync::atomic::{AtomicPtr, Ordering};
///
/// let ptr = &mut 5i;
/// let ptr = &mut 5;
/// let some_ptr = AtomicPtr::new(ptr);
///
/// let value = some_ptr.load(Ordering::Relaxed);
@ -809,10 +809,10 @@ impl<T> AtomicPtr<T> {
/// ```
/// use std::sync::atomic::{AtomicPtr, Ordering};
///
/// let ptr = &mut 5i;
/// let ptr = &mut 5;
/// let some_ptr = AtomicPtr::new(ptr);
///
/// let other_ptr = &mut 10i;
/// let other_ptr = &mut 10;
///
/// some_ptr.store(other_ptr, Ordering::Relaxed);
/// ```
@ -835,10 +835,10 @@ impl<T> AtomicPtr<T> {
/// ```
/// use std::sync::atomic::{AtomicPtr, Ordering};
///
/// let ptr = &mut 5i;
/// let ptr = &mut 5;
/// 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);
/// ```
@ -860,11 +860,11 @@ impl<T> AtomicPtr<T> {
/// ```
/// use std::sync::atomic::{AtomicPtr, Ordering};
///
/// let ptr = &mut 5i;
/// let ptr = &mut 5;
/// let some_ptr = AtomicPtr::new(ptr);
///
/// let other_ptr = &mut 10i;
/// let another_ptr = &mut 10i;
/// let other_ptr = &mut 10;
/// let another_ptr = &mut 10;
///
/// let value = some_ptr.compare_and_swap(other_ptr, another_ptr, Ordering::Relaxed);
/// ```

View File

@ -67,10 +67,10 @@
//!
//! fn main() {
//! let shared_map: Rc<RefCell<_>> = Rc::new(RefCell::new(HashMap::new()));
//! shared_map.borrow_mut().insert("africa", 92388i);
//! shared_map.borrow_mut().insert("kyoto", 11837i);
//! shared_map.borrow_mut().insert("piccadilly", 11826i);
//! shared_map.borrow_mut().insert("marbles", 38i);
//! shared_map.borrow_mut().insert("africa", 92388);
//! shared_map.borrow_mut().insert("kyoto", 11837);
//! shared_map.borrow_mut().insert("piccadilly", 11826);
//! shared_map.borrow_mut().insert("marbles", 38);
//! }
//! ```
//!

View File

@ -102,7 +102,7 @@ pub fn from_digit(num: uint, radix: uint) -> Option<char> {
if num < 10 {
Some(transmute(('0' as uint + num) as u32))
} else {
Some(transmute(('a' as uint + num - 10u) as u32))
Some(transmute(('a' as uint + num - 10) as u32))
}
}
} else {
@ -212,8 +212,8 @@ impl CharExt for char {
}
let val = match self {
'0' ... '9' => self as uint - ('0' as uint),
'a' ... 'z' => self as uint + 10u - ('a' 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 + 10 - ('A' as uint),
_ => return None,
};
if val < radix { Some(val) }
@ -245,10 +245,10 @@ impl CharExt for char {
fn len_utf8(self) -> uint {
let code = self as u32;
match () {
_ if code < MAX_ONE_B => 1u,
_ if code < MAX_TWO_B => 2u,
_ if code < MAX_THREE_B => 3u,
_ => 4u,
_ if code < MAX_ONE_B => 1,
_ if code < MAX_TWO_B => 2,
_ if code < MAX_THREE_B => 3,
_ => 4,
}
}
@ -263,50 +263,70 @@ impl CharExt for char {
#[unstable(feature = "core",
reason = "pending decision about Iterator/Writer/Reader")]
fn encode_utf8(self, dst: &mut [u8]) -> Option<uint> {
// Marked #[inline] to allow llvm optimizing it away
let code = self as u32;
if code < MAX_ONE_B && dst.len() >= 1 {
dst[0] = code as u8;
Some(1)
} else if code < MAX_TWO_B && dst.len() >= 2 {
dst[0] = (code >> 6u & 0x1F_u32) as u8 | TAG_TWO_B;
dst[1] = (code & 0x3F_u32) as u8 | TAG_CONT;
Some(2)
} else if code < MAX_THREE_B && dst.len() >= 3 {
dst[0] = (code >> 12u & 0x0F_u32) as u8 | TAG_THREE_B;
dst[1] = (code >> 6u & 0x3F_u32) as u8 | TAG_CONT;
dst[2] = (code & 0x3F_u32) as u8 | TAG_CONT;
Some(3)
} else if dst.len() >= 4 {
dst[0] = (code >> 18u & 0x07_u32) as u8 | TAG_FOUR_B;
dst[1] = (code >> 12u & 0x3F_u32) as u8 | TAG_CONT;
dst[2] = (code >> 6u & 0x3F_u32) as u8 | TAG_CONT;
dst[3] = (code & 0x3F_u32) as u8 | TAG_CONT;
Some(4)
} else {
None
}
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> {
// Marked #[inline] to allow llvm optimizing it away
let mut ch = self as u32;
if (ch & 0xFFFF_u32) == ch && dst.len() >= 1 {
// The BMP falls through (assuming non-surrogate, as it should)
dst[0] = ch as u16;
Some(1)
} else if dst.len() >= 2 {
// Supplementary planes break into surrogates.
ch -= 0x1_0000_u32;
dst[0] = 0xD800_u16 | ((ch >> 10) as u16);
dst[1] = 0xDC00_u16 | ((ch as u16) & 0x3FF_u16);
Some(2)
} else {
None
}
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
if code < MAX_ONE_B && dst.len() >= 1 {
dst[0] = code as u8;
Some(1)
} else if code < MAX_TWO_B && dst.len() >= 2 {
dst[0] = (code >> 6u & 0x1F_u32) as u8 | TAG_TWO_B;
dst[1] = (code & 0x3F_u32) as u8 | TAG_CONT;
Some(2)
} else if code < MAX_THREE_B && dst.len() >= 3 {
dst[0] = (code >> 12u & 0x0F_u32) as u8 | TAG_THREE_B;
dst[1] = (code >> 6u & 0x3F_u32) as u8 | TAG_CONT;
dst[2] = (code & 0x3F_u32) as u8 | TAG_CONT;
Some(3)
} else if dst.len() >= 4 {
dst[0] = (code >> 18u & 0x07_u32) as u8 | TAG_FOUR_B;
dst[1] = (code >> 12u & 0x3F_u32) as u8 | TAG_CONT;
dst[2] = (code >> 6u & 0x3F_u32) as u8 | TAG_CONT;
dst[3] = (code & 0x3F_u32) as u8 | TAG_CONT;
Some(4)
} else {
None
}
}
/// Encodes a raw u32 value as UTF-16 into the provided `u16` buffer,
/// and then returns the number of `u16`s written.
///
/// If the buffer is not large enough, nothing will be written into it
/// and a `None` will be returned.
#[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
if (ch & 0xFFFF_u32) == ch && dst.len() >= 1 {
// The BMP falls through (assuming non-surrogate, as it should)
dst[0] = ch as u16;
Some(1)
} else if dst.len() >= 2 {
// Supplementary planes break into surrogates.
ch -= 0x1_0000_u32;
dst[0] = 0xD800_u16 | ((ch >> 10) as u16);
dst[1] = 0xDC00_u16 | ((ch as u16) & 0x3FF_u16);
Some(2)
} else {
None
}
}
@ -345,7 +365,7 @@ impl Iterator for EscapeUnicode {
Some('u')
}
EscapeUnicodeState::LeftBrace => {
let mut n = 0u;
let mut n = 0;
while (self.c as u32) >> (4 * (n + 1)) != 0 {
n += 1;
}

View File

@ -110,13 +110,13 @@ pub trait Eq: PartialEq<Self> {
pub enum Ordering {
/// An ordering where a compared value is less [than another].
#[stable(feature = "rust1", since = "1.0.0")]
Less = -1i,
Less = -1,
/// An ordering where a compared value is equal [to another].
#[stable(feature = "rust1", since = "1.0.0")]
Equal = 0i,
Equal = 0,
/// An ordering where a compared value is greater [than another].
#[stable(feature = "rust1", since = "1.0.0")]
Greater = 1i,
Greater = 1,
}
impl Ordering {
@ -132,12 +132,12 @@ impl Ordering {
/// assert_eq!(Equal.reverse(), Equal);
/// 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.
/// 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);
/// ```
#[inline]
@ -174,9 +174,9 @@ pub trait Ord: Eq + PartialOrd<Self> {
/// ```
/// use std::cmp::Ordering::{Less, Equal, Greater};
///
/// assert_eq!( 5u.cmp(&10), Less); // because 5 < 10
/// assert_eq!(10u.cmp(&5), Greater); // because 10 > 5
/// assert_eq!( 5u.cmp(&5), Equal); // because 5 == 5
/// assert_eq!( 5.cmp(&10), Less); // because 5 < 10
/// assert_eq!(10.cmp(&5), Greater); // because 10 > 5
/// assert_eq!( 5.cmp(&5), Equal); // because 5 == 5
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn cmp(&self, other: &Self) -> Ordering;

View File

@ -150,17 +150,17 @@ default_impl! { (), () }
default_impl! { bool, false }
default_impl! { char, '\x00' }
default_impl! { uint, 0u }
default_impl! { u8, 0u8 }
default_impl! { u16, 0u16 }
default_impl! { u32, 0u32 }
default_impl! { u64, 0u64 }
default_impl! { uint, 0 }
default_impl! { u8, 0 }
default_impl! { u16, 0 }
default_impl! { u32, 0 }
default_impl! { u64, 0 }
default_impl! { int, 0i }
default_impl! { i8, 0i8 }
default_impl! { i16, 0i16 }
default_impl! { i32, 0i32 }
default_impl! { i64, 0i64 }
default_impl! { int, 0 }
default_impl! { i8, 0 }
default_impl! { i16, 0 }
default_impl! { i32, 0 }
default_impl! { i64, 0 }
default_impl! { f32, 0.0f32 }
default_impl! { f64, 0.0f64 }

View File

@ -53,7 +53,7 @@ pub enum SignFormat {
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.
/// 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) {
buf[end] = b'.';
end += 1;
let mut dig = 0u;
let mut dig = 0;
// calculate new digits while
// - 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
deccum = deccum.fract();
dig += 1u;
dig += 1;
}
// If digits are limited, and that limit has been reached,

View File

@ -253,6 +253,8 @@ pub trait Show {
/// should implement this.
#[unstable(feature = "core",
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 {
/// Formats the value using the given formatter.
fn fmt(&self, &mut Formatter) -> Result;
@ -278,6 +280,8 @@ pub trait String {
/// used. It corresponds to the default format, `{}`.
#[unstable(feature = "core",
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 {
/// Formats the value using the given formatter.
fn fmt(&self, &mut Formatter) -> Result;
@ -582,8 +586,8 @@ impl<'a> Formatter<'a> {
};
let (pre_pad, post_pad) = match align {
rt::AlignLeft => (0u, padding),
rt::AlignRight | rt::AlignUnknown => (padding, 0u),
rt::AlignLeft => (0, padding),
rt::AlignRight | rt::AlignUnknown => (padding, 0),
rt::AlignCenter => (padding / 2, (padding + 1) / 2),
};
@ -873,7 +877,7 @@ macro_rules! tuple {
fn fmt(&self, f: &mut Formatter) -> Result {
try!(write!(f, "("));
let ($(ref $name,)*) = *self;
let mut n = 0i;
let mut n = 0;
$(
if n > 0 {
try!(write!(f, ", "));

View File

@ -147,7 +147,7 @@ pub struct RadixFmt<T, R>(T, R);
///
/// ```
/// 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",
reason = "may be renamed or move to a different module")]

View File

@ -123,7 +123,7 @@ impl Writer for SipHasher {
let length = msg.len();
self.length += length;
let mut needed = 0u;
let mut needed = 0;
if self.ntail != 0 {
needed = 8 - self.ntail;

View File

@ -33,7 +33,7 @@
//! translated to the `loop` below.
//!
//! ```
//! let values = vec![1i, 2, 3];
//! let values = vec![1, 2, 3];
//!
//! // "Syntactical sugar" taking advantage of an iterator
//! for &x in values.iter() {
@ -82,6 +82,8 @@ use usize;
/// else.
#[lang="iterator"]
#[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 {
#[stable(feature = "rust1", since = "1.0.0")]
type Item;
@ -616,7 +618,7 @@ pub trait IteratorExt: Iterator + Sized {
/// # 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 > 2));
/// ```
@ -1147,7 +1149,7 @@ pub trait AdditiveIterator<A> {
/// ```
/// 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);
/// assert!(it.sum() == 15);
/// ```
@ -1190,7 +1192,7 @@ pub trait MultiplicativeIterator<A> {
/// use std::iter::{count, MultiplicativeIterator};
///
/// 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(1) == 1);
@ -2537,7 +2539,7 @@ pub struct Range<A> {
/// ```
/// let array = [0, 1, 2, 3, 4];
///
/// for i in range(0, 5u) {
/// for i in range(0, 5) {
/// println!("{}", i);
/// assert_eq!(i, array[i]);
/// }

View File

@ -48,7 +48,7 @@ macro_rules! panic {
/// let x = 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);
/// ```
#[macro_export]
@ -74,8 +74,8 @@ macro_rules! assert {
/// # Example
///
/// ```
/// let a = 3i;
/// let b = 1i + 2i;
/// let a = 3;
/// let b = 1 + 2;
/// assert_eq!(a, b);
/// ```
#[macro_export]
@ -141,8 +141,8 @@ macro_rules! debug_assert {
/// # Example
///
/// ```
/// let a = 3i;
/// let b = 1i + 2i;
/// let a = 3;
/// let b = 1 + 2;
/// debug_assert_eq!(a, b);
/// ```
#[macro_export]

View File

@ -27,10 +27,11 @@
use clone::Clone;
/// Types able to be transferred across task boundaries.
/// Types able to be transferred across thread boundaries.
#[unstable(feature = "core",
reason = "will be overhauled with new lifetime rules; see RFC 458")]
#[lang="send"]
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
pub unsafe trait Send: 'static {
// empty.
}
@ -38,6 +39,7 @@ pub unsafe trait Send: 'static {
/// Types with a constant size known at compile-time.
#[stable(feature = "rust1", since = "1.0.0")]
#[lang="sized"]
#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
pub trait Sized {
// Empty.
}
@ -147,11 +149,11 @@ pub trait Copy {
// 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
/// 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
/// `Sync`, and so are simple aggregate types containing them (like
@ -195,6 +197,7 @@ pub trait Copy {
#[unstable(feature = "core",
reason = "will be overhauled with new lifetime rules; see RFC 458")]
#[lang="sync"]
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
pub unsafe trait Sync {
// Empty
}

View File

@ -187,13 +187,13 @@ pub unsafe fn uninitialized<T>() -> T {
/// ```
/// use std::mem;
///
/// let x = &mut 5i;
/// let y = &mut 42i;
/// let x = &mut 5;
/// let y = &mut 42;
///
/// mem::swap(x, y);
///
/// assert_eq!(42i, *x);
/// assert_eq!(5i, *y);
/// assert_eq!(42, *x);
/// assert_eq!(5, *y);
/// ```
#[inline]
#[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;
///
/// let x = RefCell::new(1i);
/// let x = RefCell::new(1);
///
/// let mut mutable_borrow = x.borrow_mut();
/// *mutable_borrow = 1;
@ -306,9 +306,9 @@ pub fn drop<T>(_x: T) { }
/// ```
/// 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]
#[stable(feature = "rust1", since = "1.0.0")]

View File

@ -23,12 +23,12 @@ use num::FpCategory as Fp;
use option::Option;
#[unstable(feature = "core", reason = "pending integer conventions")]
pub const RADIX: uint = 2u;
pub const RADIX: uint = 2;
#[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")]
pub const DIGITS: uint = 6u;
pub const DIGITS: uint = 6;
#[stable(feature = "rust1", since = "1.0.0")]
pub const EPSILON: f32 = 1.19209290e-07_f32;

View File

@ -27,11 +27,11 @@ use option::Option;
// members of `Bounded` and `Float`.
#[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")]
pub const DIGITS: uint = 15u;
pub const DIGITS: uint = 15;
#[stable(feature = "rust1", since = "1.0.0")]
pub const EPSILON: f64 = 2.2204460492503131e-16_f64;

View File

@ -366,7 +366,7 @@ pub trait Int
/// ```rust
/// use std::num::Int;
///
/// assert_eq!(2i.pow(4), 16);
/// assert_eq!(2.pow(4), 16);
/// ```
#[unstable(feature = "core",
reason = "pending integer conventions")]
@ -1196,7 +1196,7 @@ impl_from_primitive! { f64, to_f64 }
/// ```
/// use std::num;
///
/// let twenty: f32 = num::cast(0x14i).unwrap();
/// let twenty: f32 = num::cast(0x14).unwrap();
/// assert_eq!(twenty, 20f32);
/// ```
///
@ -1607,8 +1607,8 @@ macro_rules! from_str_radix_float_impl {
let exp = match exp_info {
Some((c, offset)) => {
let base = match c {
'E' | 'e' if radix == 10 => 10u as $T,
'P' | 'p' if radix == 16 => 2u as $T,
'E' | 'e' if radix == 10 => 10.0,
'P' | 'p' if radix == 16 => 2.0,
_ => return None,
};

View File

@ -254,12 +254,12 @@ impl<T> Option<T> {
/// # Example
///
/// ```
/// let mut x = Some(2u);
/// let mut x = Some(2);
/// match x.as_mut() {
/// Some(v) => *v = 42,
/// None => {},
/// }
/// assert_eq!(x, Some(42u));
/// assert_eq!(x, Some(42));
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@ -385,9 +385,9 @@ impl<T> Option<T> {
/// # Example
///
/// ```
/// let k = 10u;
/// assert_eq!(Some(4u).unwrap_or_else(|| 2 * k), 4u);
/// assert_eq!(None.unwrap_or_else(|| 2 * k), 20u);
/// let k = 10i32;
/// assert_eq!(Some(4).unwrap_or_else(|| 2 * k), 4);
/// assert_eq!(None.unwrap_or_else(|| 2 * k), 20);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@ -428,10 +428,10 @@ impl<T> Option<T> {
///
/// ```
/// 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;
/// assert_eq!(x.map_or(42u, |v| v.len()), 42u);
/// assert_eq!(x.map_or(42, |v| v.len()), 42);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@ -447,13 +447,13 @@ impl<T> Option<T> {
/// # Example
///
/// ```
/// let k = 21u;
/// let k = 21;
///
/// 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;
/// 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]
#[stable(feature = "rust1", since = "1.0.0")]
@ -471,10 +471,10 @@ impl<T> Option<T> {
///
/// ```
/// 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;
/// assert_eq!(x.ok_or(0i), Err(0i));
/// assert_eq!(x.ok_or(0), Err(0));
/// ```
#[inline]
#[unstable(feature = "core")]
@ -492,10 +492,10 @@ impl<T> Option<T> {
///
/// ```
/// 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;
/// assert_eq!(x.ok_or_else(|| 0i), Err(0i));
/// assert_eq!(x.ok_or_else(|| 0), Err(0));
/// ```
#[inline]
#[unstable(feature = "core")]
@ -515,7 +515,7 @@ impl<T> Option<T> {
/// # Example
///
/// ```
/// let x = Some(4u);
/// let x = Some(4);
/// assert_eq!(x.iter().next(), Some(&4));
///
/// let x: Option<uint> = None;
@ -532,9 +532,9 @@ impl<T> Option<T> {
/// # Example
///
/// ```
/// let mut x = Some(4u);
/// let mut x = Some(4);
/// match x.iter_mut().next() {
/// Some(&mut ref mut v) => *v = 42u,
/// Some(&mut ref mut v) => *v = 42,
/// None => {},
/// }
/// assert_eq!(x, Some(42));
@ -577,7 +577,7 @@ impl<T> Option<T> {
/// # Example
///
/// ```
/// let x = Some(2u);
/// let x = Some(2);
/// let y: Option<&str> = None;
/// assert_eq!(x.and(y), None);
///
@ -585,7 +585,7 @@ impl<T> Option<T> {
/// let y = Some("foo");
/// assert_eq!(x.and(y), None);
///
/// let x = Some(2u);
/// let x = Some(2);
/// let y = Some("foo");
/// assert_eq!(x.and(y), Some("foo"));
///
@ -630,17 +630,17 @@ impl<T> Option<T> {
/// # Example
///
/// ```
/// let x = Some(2u);
/// let x = Some(2);
/// let y = None;
/// assert_eq!(x.or(y), Some(2u));
/// assert_eq!(x.or(y), Some(2));
///
/// let x = None;
/// let y = Some(100u);
/// assert_eq!(x.or(y), Some(100u));
/// let y = Some(100);
/// assert_eq!(x.or(y), Some(100));
///
/// let x = Some(2u);
/// let y = Some(100u);
/// assert_eq!(x.or(y), Some(2u));
/// let x = Some(2);
/// let y = Some(100);
/// assert_eq!(x.or(y), Some(2));
///
/// let x: Option<uint> = None;
/// let y = None;
@ -686,7 +686,7 @@ impl<T> Option<T> {
/// # Example
///
/// ```
/// let mut x = Some(2u);
/// let mut x = Some(2);
/// x.take();
/// 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 bad_year = bad_year_from_input.parse().unwrap_or_default();
///
/// assert_eq!(1909i, good_year);
/// assert_eq!(0i, bad_year);
/// assert_eq!(1909, good_year);
/// assert_eq!(0, bad_year);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@ -898,12 +898,12 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
/// ```rust
/// use std::uint;
///
/// let v = vec!(1u, 2u);
/// let v = vec!(1, 2);
/// let res: Option<Vec<uint>> = v.iter().map(|&x: &uint|
/// if x == uint::MAX { None }
/// else { Some(x + 1) }
/// ).collect();
/// assert!(res == Some(vec!(2u, 3u)));
/// assert!(res == Some(vec!(2, 3)));
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]

View File

@ -229,7 +229,7 @@
use self::Result::{Ok, Err};
use clone::Clone;
use fmt::Display;
use fmt::Debug;
use iter::{Iterator, IteratorExt, DoubleEndedIterator, FromIterator, ExactSizeIterator};
use ops::{FnMut, FnOnce};
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) }
///
/// let x: Result<uint, uint> = Ok(2u);
/// assert_eq!(x.map_err(stringify), Ok(2u));
/// let x: Result<uint, uint> = Ok(2);
/// assert_eq!(x.map_err(stringify), Ok(2));
///
/// let x: Result<uint, uint> = Err(13);
/// 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 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 v: Vec<uint> = x.into_iter().collect();
@ -677,9 +677,9 @@ impl<T, E> Result<T, E> {
/// # Example
///
/// ```
/// let optb = 2u;
/// let x: Result<uint, &str> = Ok(9u);
/// assert_eq!(x.unwrap_or(optb), 9u);
/// let optb = 2;
/// let x: Result<uint, &str> = Ok(9);
/// assert_eq!(x.unwrap_or(optb), 9);
///
/// let x: Result<uint, &str> = Err("error");
/// assert_eq!(x.unwrap_or(optb), optb);
@ -701,8 +701,8 @@ impl<T, E> Result<T, E> {
/// ```
/// fn count(x: &str) -> uint { x.len() }
///
/// assert_eq!(Ok(2u).unwrap_or_else(count), 2u);
/// assert_eq!(Err("foo").unwrap_or_else(count), 3u);
/// assert_eq!(Ok(2).unwrap_or_else(count), 2);
/// assert_eq!(Err("foo").unwrap_or_else(count), 3);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@ -715,7 +715,7 @@ impl<T, E> Result<T, E> {
}
#[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`.
///
/// # Panics
@ -726,8 +726,8 @@ impl<T, E: Display> Result<T, E> {
/// # Example
///
/// ```
/// let x: Result<uint, &str> = Ok(2u);
/// assert_eq!(x.unwrap(), 2u);
/// let x: Result<uint, &str> = Ok(2);
/// assert_eq!(x.unwrap(), 2);
/// ```
///
/// ```{.should_fail}
@ -740,13 +740,13 @@ impl<T, E: Display> Result<T, E> {
match self {
Ok(t) => t,
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")]
impl<T: Display, E> Result<T, E> {
impl<T: Debug, E> Result<T, E> {
/// Unwraps a result, yielding the content of an `Err`.
///
/// # Panics
@ -757,7 +757,7 @@ impl<T: Display, E> Result<T, E> {
/// # Example
///
/// ```{.should_fail}
/// let x: Result<uint, &str> = Ok(2u);
/// let x: Result<uint, &str> = Ok(2);
/// x.unwrap_err(); // panics with `2`
/// ```
///
@ -770,7 +770,7 @@ impl<T: Display, E> Result<T, E> {
pub fn unwrap_err(self) -> E {
match self {
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
}
}
@ -898,12 +898,12 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
/// ```rust
/// 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|
/// if x == uint::MAX { Err("Overflow!") }
/// else { Ok(x + 1) }
/// ).collect();
/// assert!(res == Ok(vec!(2u, 3u)));
/// assert!(res == Ok(vec!(2, 3)));
/// ```
#[inline]
fn from_iter<I: Iterator<Item=Result<A, E>>>(iter: I) -> Result<V, E> {

View File

@ -654,7 +654,7 @@ macro_rules! iterator {
self.ptr = transmute(self.ptr as uint + 1);
// Use a non-null pointer value
Some(transmute(1u))
Some(&mut *(1 as *mut _))
} else {
let old = self.ptr;
self.ptr = self.ptr.offset(1);
@ -688,7 +688,7 @@ macro_rules! iterator {
self.end = transmute(self.end as uint - 1);
// Use a non-null pointer value
Some(transmute(1u))
Some(&mut *(1 as *mut _))
} else {
self.end = self.end.offset(-1);
@ -796,7 +796,7 @@ impl<'a, T> RandomAccessIterator for Iter<'a, T> {
if index < self.indexable() {
if mem::size_of::<T>() == 0 {
// Use a non-null pointer value
Some(transmute(1u))
Some(&mut *(1 as *mut _))
} else {
Some(transmute(self.ptr.offset(index as int)))
}
@ -1176,7 +1176,7 @@ impl<'a, T> Iterator for Windows<'a, T> {
(0, Some(0))
} else {
let x = self.v.len() - self.size;
(x.saturating_add(1), x.checked_add(1u))
(x.saturating_add(1), x.checked_add(1))
}
}
}

View File

@ -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")]
pub unsafe fn from_c_str(s: *const i8) -> &'static str {
let s = s as *const u8;
let mut len = 0u;
let mut len = 0;
while *s.offset(len as int) != 0 {
len += 1u;
len += 1;
}
let v: &'static [u8] = ::mem::transmute(Slice { data: s, len: len });
from_utf8(v).ok().expect("from_c_str passed invalid utf-8 data")
@ -310,43 +310,52 @@ fn unwrap_or_0(opt: Option<&u8>) -> u8 {
}
}
/// Reads the next code point out of a byte iterator (assuming a
/// UTF-8-like encoding).
#[unstable(feature = "core")]
pub fn next_code_point(bytes: &mut slice::Iter<u8>) -> Option<u32> {
// Decode UTF-8
let x = match bytes.next() {
None => return None,
Some(&next_byte) if next_byte < 128 => return Some(next_byte as u32),
Some(&next_byte) => next_byte,
};
// Multibyte case follows
// Decode from a byte combination out of: [[[x y] z] w]
// NOTE: Performance is sensitive to the exact formulation here
let init = utf8_first_byte!(x, 2);
let y = unwrap_or_0(bytes.next());
let mut ch = utf8_acc_cont_byte!(init, y);
if x >= 0xE0 {
// [[x y z] w] case
// 5th bit in 0xE0 .. 0xEF is always clear, so `init` is still valid
let z = unwrap_or_0(bytes.next());
let y_z = utf8_acc_cont_byte!((y & CONT_MASK) as u32, z);
ch = init << 12 | y_z;
if x >= 0xF0 {
// [x y z w] case
// use only the lower 3 bits of `init`
let w = unwrap_or_0(bytes.next());
ch = (init & 7) << 18 | utf8_acc_cont_byte!(y_z, w);
}
}
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> {
// Decode UTF-8, using the valid UTF-8 invariant
let x = match self.iter.next() {
None => return None,
Some(&next_byte) if next_byte < 128 => return Some(next_byte as char),
Some(&next_byte) => next_byte,
};
// Multibyte case follows
// Decode from a byte combination out of: [[[x y] z] w]
// NOTE: Performance is sensitive to the exact formulation here
let init = utf8_first_byte!(x, 2);
let y = unwrap_or_0(self.iter.next());
let mut ch = utf8_acc_cont_byte!(init, y);
if x >= 0xE0 {
// [[x y z] w] case
// 5th bit in 0xE0 .. 0xEF is always clear, so `init` is still valid
let z = unwrap_or_0(self.iter.next());
let y_z = utf8_acc_cont_byte!((y & CONT_MASK) as u32, z);
ch = init << 12 | y_z;
if x >= 0xF0 {
// [x y z w] case
// use only the lower 3 bits of `init`
let w = unwrap_or_0(self.iter.next());
ch = (init & 7) << 18 | utf8_acc_cont_byte!(y_z, w);
next_code_point(&mut self.iter).map(|ch| {
// str invariant says `ch` is a valid Unicode Scalar Value
unsafe {
mem::transmute(ch)
}
}
// str invariant says `ch` is a valid Unicode Scalar Value
unsafe {
Some(mem::transmute(ch))
}
})
}
#[inline]
@ -1509,7 +1518,7 @@ impl StrExt for str {
None => "",
Some(last) => {
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]
fn char_range_at(&self, i: uint) -> CharRange {
if self.as_bytes()[i] < 128u8 {
return CharRange {ch: self.as_bytes()[i] as char, next: i + 1 };
}
// 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);
let (c, n) = char_range_at_raw(self.as_bytes(), i);
CharRange { ch: unsafe { mem::transmute(c) }, next: n }
}
#[inline]
@ -1559,7 +1551,7 @@ impl StrExt for str {
fn multibyte_char_range_at_reverse(s: &str, mut i: uint) -> CharRange {
// while there is a previous byte == 10......
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;
@ -1629,7 +1621,7 @@ impl StrExt for str {
if self.is_empty() {
None
} 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()) };
Some((ch, next_s))
}
@ -1661,6 +1653,32 @@ impl StrExt for str {
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")]
impl<'a> Default for &'a str {
#[stable(feature = "rust1", since = "1.0.0")]

View File

@ -32,10 +32,12 @@ use middle::subst::Substs;
use middle::ty::{self, Ty};
use middle::{def, pat_util, stability};
use middle::const_eval::{eval_const_expr_partial, const_int, const_uint};
use middle::cfg;
use util::ppaux::{ty_to_string};
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::num::SignedInt;
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::ast_util::is_shift_binop;
use syntax::attr::{self, AttrMetaMethods};
use syntax::codemap::Span;
use syntax::codemap::{self, Span};
use syntax::parse::token;
use syntax::ast::{TyIs, TyUs, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64};
use syntax::ast_util;
@ -185,7 +187,7 @@ impl LintPass for TypeLimits {
"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 {
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)),
@ -272,7 +274,7 @@ impl LintPass for TypeLimits {
fn is_valid<T:cmp::PartialOrd>(binop: ast::BinOp, v: T,
min: T, max: T) -> bool {
match binop {
match binop.node {
ast::BiLt => v > min && v <= max,
ast::BiLe => 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 {
match binop {
codemap::respan(binop.span, match binop.node {
ast::BiLt => ast::BiGt,
ast::BiLe => ast::BiGe,
ast::BiGt => ast::BiLt,
ast::BiGe => ast::BiLe,
_ => binop
}
_ => return binop
})
}
// 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 {
match binop {
match binop.node {
ast::BiEq | ast::BiLt | ast::BiLe |
ast::BiNe | ast::BiGe | ast::BiGt => true,
_ => 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! {
pub UNUSED_IMPORTS,
Warn,

View File

@ -212,6 +212,7 @@ impl LintStore {
MissingCopyImplementations,
UnstableFeatures,
Stability,
UnconditionalRecursion,
);
add_builtin_with_new!(sess,

View File

@ -627,6 +627,7 @@ impl<'tcx> tr for MethodOrigin<'tcx> {
// def-id is already translated when we read it out
trait_ref: mp.trait_ref.clone(),
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| {
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(())
})
})
@ -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_uint()
}).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()

View File

@ -372,7 +372,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
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]
// |

View File

@ -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),
eval_const_expr_partial(tcx, &**b)) {
(Ok(const_float(a)), Ok(const_float(b))) => {
match op {
match op.node {
ast::BiAdd => Ok(const_float(a + b)),
ast::BiSub => 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))) => {
match op {
match op.node {
ast::BiAdd => Ok(const_int(a + b)),
ast::BiSub => 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))) => {
match op {
match op.node {
ast::BiAdd => Ok(const_uint(a + b)),
ast::BiSub => 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
(Ok(const_int(a)), Ok(const_uint(b))) => {
match op {
match op.node {
ast::BiShl => 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())
}
}
(Ok(const_uint(a)), Ok(const_int(b))) => {
match op {
match op.node {
ast::BiShl => 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())
}
}
(Ok(const_bool(a)), Ok(const_bool(b))) => {
Ok(const_bool(match op {
Ok(const_bool(match op.node {
ast::BiAnd => a && b,
ast::BiOr => a || b,
ast::BiBitXor => a ^ b,

View File

@ -568,7 +568,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
}
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
} else {
PassArgs::ByRef

View File

@ -504,7 +504,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
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));
visit::walk_expr(ir, expr);
}
@ -1177,7 +1177,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
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 ln = self.live_node(expr.id, expr.span);

View File

@ -22,7 +22,7 @@ use util::nodemap::{FnvHashMap, FnvHashSet, NodeMap};
use util::common::can_reach;
use std::cell::RefCell;
use syntax::codemap::Span;
use syntax::codemap::{self, Span};
use syntax::{ast, visit};
use syntax::ast::{Block, Item, FnDecl, NodeId, Arm, Pat, Stmt, Expr, Local};
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.
// This ensures fixed size stacks.
ast::ExprBinary(ast::BiAnd, _, ref r) |
ast::ExprBinary(ast::BiOr, _, ref r) => {
ast::ExprBinary(codemap::Spanned { node: ast::BiAnd, .. }, _, ref r) |
ast::ExprBinary(codemap::Spanned { node: ast::BiOr, .. }, _, ref r) => {
// For shortcircuiting operators, mark the RHS as a terminating
// scope since it only executes conditionally.
terminating(r.id);

View File

@ -453,9 +453,14 @@ pub struct MethodParam<'tcx> {
// never contains bound regions; those regions should have been
// instantiated with fresh variables at this point.
pub trait_ref: Rc<ty::TraitRef<'tcx>>,
// index of uint in the list of methods for the trait
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
@ -5716,7 +5721,7 @@ pub fn is_binopable<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>, op: ast::BinOp) -> bool
static opcat_mod: int = 8;
fn opcat(op: ast::BinOp) -> int {
match op {
match op.node {
ast::BiAdd => opcat_add,
ast::BiSub => opcat_sub,
ast::BiMul => opcat_mult,

View File

@ -310,7 +310,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::MethodOrigin<'tcx> {
ty::MethodTypeParam(ref param) => {
ty::MethodTypeParam(ty::MethodParam {
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) => {

View File

@ -544,7 +544,7 @@ impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Option<T> {
impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for P<T> {
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
(*self).repr(tcx)
(**self).repr(tcx)
}
}

View File

@ -231,7 +231,7 @@ mod svh_visitor {
SawExprCall,
SawExprMethodCall,
SawExprTup,
SawExprBinary(ast::BinOp),
SawExprBinary(ast::BinOp_),
SawExprUnary(ast::UnOp),
SawExprLit(ast::Lit_),
SawExprCast,
@ -241,7 +241,7 @@ mod svh_visitor {
SawExprClosure,
SawExprBlock,
SawExprAssign,
SawExprAssignOp(ast::BinOp),
SawExprAssignOp(ast::BinOp_),
SawExprIndex,
SawExprRange,
SawExprPath,
@ -262,7 +262,7 @@ mod svh_visitor {
ExprCall(..) => SawExprCall,
ExprMethodCall(..) => SawExprMethodCall,
ExprTup(..) => SawExprTup,
ExprBinary(op, _, _) => SawExprBinary(op),
ExprBinary(op, _, _) => SawExprBinary(op.node),
ExprUnary(op, _) => SawExprUnary(op),
ExprLit(ref lit) => SawExprLit(lit.node.clone()),
ExprCast(..) => SawExprCast,
@ -273,7 +273,7 @@ mod svh_visitor {
ExprClosure(..) => SawExprClosure,
ExprBlock(..) => SawExprBlock,
ExprAssign(..) => SawExprAssign,
ExprAssignOp(op, _, _) => SawExprAssignOp(op),
ExprAssignOp(op, _, _) => SawExprAssignOp(op.node),
ExprField(_, id) => SawExprField(content(id.node)),
ExprTupField(_, id) => SawExprTupField(id.node),
ExprIndex(..) => SawExprIndex,

View File

@ -13,7 +13,7 @@
pub use self::OptimizationDiagnosticKind::*;
pub use self::Diagnostic::*;
use libc::c_char;
use libc::{c_char, c_uint};
use std::ptr;
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)]
pub enum Diagnostic {
Optimization(OptimizationDiagnostic),
InlineAsm(InlineAsmDiagnostic),
/// LLVM has other types that we do not wrap here.
UnknownDiagnostic(DiagnosticInfoRef),
@ -82,6 +110,9 @@ impl Diagnostic {
let kind = super::LLVMGetDiagInfoKind(di);
match kind {
super::DK_InlineAsm
=> InlineAsm(InlineAsmDiagnostic::unpack(di)),
super::DK_OptimizationRemark
=> Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di)),

View File

@ -2055,6 +2055,10 @@ extern {
function_out: *mut ValueRef,
debugloc_out: *mut DebugLocRef,
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 LLVMGetDiagInfoSeverity(DI: DiagnosticInfoRef) -> DiagnosticSeverity;

View File

@ -336,30 +336,36 @@ struct HandlerFreeVars<'a> {
cgcx: &'a CodegenContext<'a>,
}
unsafe extern "C" fn report_inline_asm<'a, 'b>(cgcx: &'a CodegenContext<'a>,
msg: &'b str,
cookie: c_uint) {
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) {
use syntax::codemap::ExpnId;
let HandlerFreeVars { cgcx, .. }
= *mem::transmute::<_, *const HandlerFreeVars>(user);
let msg = llvm::build_string(|s| llvm::LLVMWriteSMDiagnosticToString(diag, s))
.expect("non-UTF8 SMDiagnostic");
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");
}
}
report_inline_asm(cgcx, &msg[], cookie);
}
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);
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) => {
let pass_name = str::from_utf8(ffi::c_str_to_bytes(&opt.pass_name))
.ok()
@ -407,10 +419,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
let fv = &fv as *const HandlerFreeVars as *mut c_void;
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 {
let ext = format!("{}.no-opt.bc", name_extra);

View File

@ -540,7 +540,7 @@ pub fn compare_scalar_types<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
lhs: ValueRef,
rhs: ValueRef,
t: Ty<'tcx>,
op: ast::BinOp)
op: ast::BinOp_)
-> Result<'blk, 'tcx> {
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,
rhs: ValueRef,
nt: scalar_type,
op: ast::BinOp)
op: ast::BinOp_)
-> ValueRef {
let _icx = push_ctxt("compare_scalar_values");
fn die(cx: Block) -> ! {
@ -635,7 +635,7 @@ pub fn compare_simd_types<'blk, 'tcx>(
not supported for floating point SIMD types")
},
ty::ty_uint(_) | ty::ty_int(_) => {
let cmp = match op {
let cmp = match op.node {
ast::BiEq => llvm::IntEQ,
ast::BiNe => llvm::IntNE,
ast::BiLt => llvm::IntSLT,
@ -823,7 +823,7 @@ pub fn cast_shift_rhs<F, G>(op: ast::BinOp,
G: FnOnce(ValueRef, Type) -> ValueRef,
{
// 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 lhs_llty = val_ty(lhs);
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_t: Ty<'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 with overflow")
} else {

View File

@ -310,7 +310,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef {
let ty = ty::expr_ty(cx.tcx(), &**e1);
let is_float = ty::type_is_fp(ty);
let signed = ty::type_is_signed(ty);
return match b {
return match b.node {
ast::BiAdd => {
if is_float { llvm::LLVMConstFAdd(te1, te2) }
else { llvm::LLVMConstAdd(te1, te2) }

View File

@ -207,7 +207,7 @@ use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
use util::nodemap::{DefIdMap, NodeMap, FnvHashMap, FnvHashSet};
use util::ppaux;
use libc::c_uint;
use libc::{c_uint, c_longlong};
use std::ffi::CString;
use std::cell::{Cell, RefCell};
use std::ptr;
@ -2764,7 +2764,7 @@ fn create_struct_stub(cx: &CrateContext,
fn fixed_vec_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
unique_type_id: UniqueTypeId,
element_type: Ty<'tcx>,
len: uint,
len: Option<u64>,
span: Span)
-> MetadataCreationResult {
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_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 {
llvm::LLVMDIBuilderGetOrCreateSubrange(
DIB(cx),
0,
len as i64)
llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)
};
let subscripts = create_DIArray(DIB(cx), &[subrange]);
let metadata = unsafe {
llvm::LLVMDIBuilderCreateArrayType(
DIB(cx),
bytes_to_bits(element_type_size * (len as u64)),
bytes_to_bits(array_size_in_bytes),
bytes_to_bits(element_type_align),
element_type_metadata,
subscripts)
@ -2991,12 +2993,12 @@ fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
ty::ty_enum(def_id, _) => {
prepare_enum_metadata(cx, t, def_id, unique_type_id, usage_site_span).finalize(cx)
}
ty::ty_vec(typ, Some(len)) => {
fixed_vec_metadata(cx, unique_type_id, typ, len, usage_site_span)
ty::ty_vec(typ, len) => {
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(..) => {
MetadataCreationResult::new(
trait_pointer_metadata(cx, t, None, unique_type_id),

View File

@ -1132,7 +1132,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let rhs_datum = unpack_datum!(bcx, trans(bcx, &**rhs));
trans_overloaded_op(bcx, expr, MethodCall::expr(expr.id), lhs,
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) => {
// 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 mut bcx = bcx;
let val = match op {
let val = match op.node {
ast::BiAdd => {
if is_float {
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 => {
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 {
base::compare_simd_types(bcx, lhs, rhs, intype, ty::simd_size(tcx, lhs_t), op)
} else {
@ -1811,7 +1811,7 @@ fn trans_binary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// if overloaded, would be RvalueDpsExpr
assert!(!ccx.tcx().method_map.borrow().contains_key(&MethodCall::expr(expr.id)));
match op {
match op.node {
ast::BiAnd => {
trans_lazy_binop(bcx, expr, lazy_and, lhs, rhs)
}

View File

@ -132,7 +132,8 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
ty::MethodTypeParam(ty::MethodParam {
ref trait_ref,
method_num
method_num,
impl_def_id: _
}) => {
let trait_ref = ty::Binder(bcx.monomorphize(trait_ref));
let span = bcx.tcx().map.span(method_call.expr_id);

View File

@ -256,7 +256,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
&impl_polytype.substs,
&ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap());
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)
}
@ -275,7 +276,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
let trait_ref =
Rc::new(ty::TraitRef::new(trait_def_id, self.tcx().mk_substs(substs.clone())));
let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
method_num: method_num });
method_num: method_num,
impl_def_id: None });
(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 substs = trait_ref.substs.clone();
let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
method_num: method_num });
method_num: method_num,
impl_def_id: None });
(substs, origin)
}
}

View File

@ -287,7 +287,8 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
let callee = MethodCallee {
origin: MethodTypeParam(MethodParam{trait_ref: trait_ref.clone(),
method_num: method_num}),
method_num: method_num,
impl_def_id: None}),
ty: fty,
substs: trait_ref.substs.clone()
};

View File

@ -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,
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
check_expr(fcx, &**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);
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::BiGt => {
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 \
supported for floating \
point SIMD vector `{}`",
ast_util::binop_to_string(op),
ast_util::binop_to_string(op.node),
actual)
},
lhs_t,
@ -2919,7 +2919,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
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
// type
fcx.write_error(expr.id);
@ -2928,7 +2928,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|actual| {
format!("binary operation `{}` cannot be applied \
to type `{}`",
ast_util::binop_to_string(op),
ast_util::binop_to_string(op.node),
actual)
},
lhs_t,
@ -2945,7 +2945,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
operation `{}=` \
cannot be applied to \
type `{}`",
ast_util::binop_to_string(op),
ast_util::binop_to_string(op.node),
actual)
},
lhs_t,
@ -2968,7 +2968,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
rhs: &P<ast::Expr>) -> Ty<'tcx> {
let tcx = fcx.ccx.tcx;
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::BiSub => ("sub", lang.sub_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), || {
fcx.type_error_message(ex.span, |actual| {
format!("binary operation `{}` cannot be applied to type `{}`",
ast_util::binop_to_string(op),
ast_util::binop_to_string(op.node),
actual)
}, 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>,

View File

@ -564,7 +564,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
},
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
// overloaded op. Note that we (sadly) currently use an

View File

@ -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_with_nul;
pub use self::os_str::OsString;
pub use self::os_str::OsStr;
pub use self::os_str::AsOsStr;
mod c_str;
mod os_str;

260
src/libstd/ffi/os_str.rs Normal file
View 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
}
}

View File

@ -382,7 +382,7 @@ impl<T> !Sync for SyncSender<T> {}
/// 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
/// 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")]
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
/// `SyncSender::try_send` method.
#[derive(PartialEq, Clone, Show)]
#[derive(PartialEq, Clone)]
#[stable(feature = "rust1", since = "1.0.0")]
pub enum TrySendError<T> {
/// 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")]
impl<T> fmt::Display for SendError<T> {
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")]
impl<T> fmt::Display for TrySendError<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

View File

@ -53,7 +53,6 @@ pub struct Guard {
/// 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
/// return this error.
#[derive(Show)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct PoisonError<T> {
guard: T,
@ -61,7 +60,6 @@ pub struct PoisonError<T> {
/// An enumeration of possible errors which can occur while calling the
/// `try_lock` method.
#[derive(Show)]
#[stable(feature = "rust1", since = "1.0.0")]
pub enum TryLockError<T> {
/// 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")]
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")]
impl<T> fmt::Display for PoisonError<T> {
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")]
impl<T> fmt::Display for TryLockError<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

View File

@ -29,6 +29,7 @@ pub mod stack;
pub mod thread;
pub mod thread_info;
pub mod thread_local;
pub mod wtf8;
// common error constructors
@ -93,11 +94,21 @@ pub fn keep_going<F>(data: &[u8], mut f: F) -> i64 where
return (origamt - amt) as i64;
}
// A trait for extracting representations from std::io types
pub trait AsInner<Inner> {
/// A trait for viewing representations from std types
pub trait AsInner<Inner: ?Sized> {
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> {
fn program(&self) -> &CString;
fn args(&self) -> &[CString];

File diff suppressed because it is too large Load Diff

View File

@ -31,7 +31,10 @@
#![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 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.
///
/// Includes all extension traits, and some important type definitions.

View File

@ -44,6 +44,7 @@ pub mod fs;
pub mod helper_signal;
pub mod mutex;
pub mod os;
pub mod os_str;
pub mod pipe;
pub mod process;
pub mod rwlock;

View 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() }
}
}

View File

@ -11,14 +11,22 @@
use prelude::v1::*;
use sys::fs::FileDesc;
use libc::{self, c_int};
use libc::{self, c_int, c_ulong, funcs};
use io::{self, IoResult, IoError};
use sys::c;
use sys_common;
pub struct TTY {
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 {
pub fn new(fd: c_int) -> IoResult<TTY> {
if unsafe { libc::isatty(fd) } != 0 {
@ -41,8 +49,39 @@ impl TTY {
pub fn set_raw(&mut self, _raw: bool) -> IoResult<()> {
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)> {
Err(sys_common::unimpl())
}
pub fn isatty(&self) -> bool { false }
}

View File

@ -16,7 +16,11 @@
#![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 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.
///
/// Includes all extension traits, and some important type definitions.
pub mod prelude {
pub use super::{Socket, Handle, AsRawSocket, AsRawHandle};
pub use super::{Socket, Handle, AsRawSocket, AsRawHandle, OsStrExt, OsStringExt};
}

View File

@ -44,6 +44,7 @@ pub mod fs;
pub mod helper_signal;
pub mod mutex;
pub mod os;
pub mod os_str;
pub mod pipe;
pub mod process;
pub mod rwlock;

View 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 }
}
}

View File

@ -13,7 +13,7 @@
pub use self::AsmDialect::*;
pub use self::AttrStyle::*;
pub use self::BindingMode::*;
pub use self::BinOp::*;
pub use self::BinOp_::*;
pub use self::BlockCheckMode::*;
pub use self::CaptureClause::*;
pub use self::Decl_::*;
@ -582,7 +582,7 @@ pub enum Mutability {
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)]
pub enum BinOp {
pub enum BinOp_ {
BiAdd,
BiSub,
BiMul,
@ -603,6 +603,8 @@ pub enum BinOp {
BiGt,
}
pub type BinOp = Spanned<BinOp_>;
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)]
pub enum UnOp {
UnUniq,

View File

@ -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 {
BiAdd => "+",
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 {
BiAnd => 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 {
BiShl => 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 {
BiEq | BiLt | BiLe | BiNe | BiGt | BiGe => true,
_ => false
@ -93,7 +93,7 @@ pub fn is_comparison_binop(b: BinOp) -> bool {
}
/// 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 {
BiAdd | BiSub | BiMul | BiDiv | BiRem | BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr => {
true
@ -319,7 +319,7 @@ pub fn struct_field_visibility(field: ast::StructField) -> Visibility {
}
/// 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 {
// 'as' sits here with 12
BiMul | BiDiv | BiRem => 11us,

View File

@ -106,7 +106,7 @@ pub trait AstBuilder {
fn expr_ident(&self, span: Span, id: ast::Ident) -> 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>;
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>;
@ -561,9 +561,9 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
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> {
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> {

View File

@ -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
/// on all the fields.
#[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,
cx: &mut ExtCtxt, trait_span: Span,
substructure: &Substructure) -> P<Expr> {

View File

@ -2840,6 +2840,7 @@ impl<'a> Parser<'a> {
self.expected_tokens.push(TokenType::Operator);
let cur_op_span = self.span;
let cur_opt = self.token.to_binop();
match cur_opt {
Some(cur_op) => {
@ -2853,7 +2854,7 @@ impl<'a> Parser<'a> {
let rhs = self.parse_more_binops(expr, cur_prec + 1);
let lhs_span = lhs.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);
self.parse_more_binops(bin, min_prec)
} else {
@ -2877,16 +2878,17 @@ impl<'a> Parser<'a> {
/// Produce an error if comparison operators are chained (RFC #558).
/// We only need to check lhs, not rhs, because all comparison ops
/// 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));
match lhs.node {
ExprBinary(op, _, _) if ast_util::is_comparison_binop(op) => {
let op_span = self.span;
ExprBinary(op, _, _) if ast_util::is_comparison_binop(op.node) => {
// respan to include both operators
let op_span = mk_sp(op.span.lo, self.span.hi);
self.span_err(op_span,
"Chained comparison operators require parentheses");
if op == BiLt && outer_op == BiGt {
"chained comparison operators require parentheses");
if op.node == BiLt && outer_op == BiGt {
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> {
let restrictions = self.restrictions & RESTRICTION_NO_STRUCT_LITERAL;
let op_span = self.span;
match self.token {
token::Eq => {
self.bump();
@ -2942,7 +2945,7 @@ impl<'a> Parser<'a> {
};
let rhs_span = rhs.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)
}
// A range expression, either `expr..expr` or `expr..`.

View File

@ -249,7 +249,7 @@ impl Token {
}
/// 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 {
BinOp(Star) => Some(ast::BiMul),
BinOp(Slash) => Some(ast::BiDiv),

View File

@ -1627,7 +1627,7 @@ impl<'a> State<'a> {
rhs: &ast::Expr) -> IoResult<()> {
try!(self.print_expr(lhs));
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)
}
@ -1795,7 +1795,7 @@ impl<'a> State<'a> {
ast::ExprAssignOp(op, ref lhs, ref rhs) => {
try!(self.print_expr(&**lhs));
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.print_expr(&**rhs));
}

View File

@ -313,6 +313,7 @@ fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
&ast::ItemFn(ref decl, _, _, ref generics, _) => {
let no_output = match decl.output {
ast::DefaultReturn(..) => true,
ast::Return(ref t) if t.node == ast::TyTup(vec![]) => true,
_ => false
};
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 no_output = match decl.output {
ast::DefaultReturn(..) => true,
ast::Return(ref t) if t.node == ast::TyTup(vec![]) => true,
_ => false
};
let tparm_cnt = generics.ty_params.len();

View File

@ -894,6 +894,22 @@ LLVMUnpackOptimizationDiagnostic(
*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) {
raw_rust_string_ostream os(str);
DiagnosticPrinterRawOStream dp(os);

View 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
}

View 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() {}

View File

@ -12,12 +12,12 @@ fn f<T>() {}
fn main() {
false == false == false;
//~^ ERROR: Chained comparison operators require parentheses
//~^ ERROR: chained comparison operators require parentheses
false == 0 < 2;
//~^ ERROR: Chained comparison operators require parentheses
//~^ ERROR: chained comparison operators require parentheses
f<X>();
//~^ ERROR: Chained comparison operators require parentheses
//~^^ HELP: use ::< instead of < if you meant to specify type arguments
//~^ ERROR: chained comparison operators require parentheses
//~^^ HELP: use `::<...>` instead of `<...>`
}

View File

@ -15,6 +15,6 @@ fn f<X>() {}
pub fn main() {
f<type>();
//~^ ERROR expected identifier, found keyword `type`
//~^^ ERROR: Chained comparison operators require parentheses
//~^^^ HELP: use ::< instead of < if you meant to specify type arguments
//~^^ ERROR: chained comparison
//~^^^ HELP: use `::<
}

View File

@ -36,6 +36,12 @@
// gdb-command:print void_droid_gdb->internals
// 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
@ -67,6 +73,12 @@
// lldb-command:print none_str
// 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]
@ -102,6 +114,17 @@ struct NamedFieldsRepr<'a> {
internals: &'a isize
}
struct NestedNonZeroField<'a> {
a: u16,
b: u32,
c: &'a char,
}
enum NestedNonZero<'a> {
Yep(f64, NestedNonZeroField<'a>),
Nope
}
fn main() {
let some_str: Option<&'static str> = Some("abc");
@ -124,6 +147,17 @@ fn main() {
let void_droid = 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
}

View File

@ -8,33 +8,54 @@
// option. This file may not be copied, modified, or distributed
// 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::path::BytesContainer;
use std::rand::random;
fn main() {
// If we're the child, make sure we were invoked correctly
let args = os::args();
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();
}
fn test() {
// If we're the parent, copy our own binary to a tempr directory, and then
// make it executable.
let dir = TempDir::new("mytest").unwrap();
let me = os::self_exe_name().unwrap();
let dest = dir.path().join(format!("mytest{}", os::consts::EXE_SUFFIX));
fs::copy(&me, &dest).unwrap();
// If we're the parent, copy our own binary to a new directory.
let my_path = os::self_exe_name().unwrap();
let my_dir = my_path.dir_path();
// 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()));
path.push(dir.path().clone());
path.push(child_dir.clone());
let path = os::join_paths(path.as_slice()).unwrap();
Command::new("mytest").env("PATH", path.as_slice())
.arg("child")
.spawn().unwrap();
let child_output = Command::new("mytest").env("PATH", path.as_slice())
.arg("child")
.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();
}

View File

@ -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() -> () {}