Merge remote-tracking branch 'rust-lang/master'
Conflicts: src/libcore/cmp.rs src/libcore/fmt/mod.rs src/libcore/iter.rs src/libcore/marker.rs src/libcore/num/f32.rs src/libcore/num/f64.rs src/libcore/result.rs src/libcore/str/mod.rs src/librustc/lint/builtin.rs src/librustc/lint/context.rs src/libstd/sync/mpsc/mod.rs src/libstd/sync/poison.rs
This commit is contained in:
commit
d179ba3b8e
7
configure
vendored
7
configure
vendored
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -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).
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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))
|
||||
|
@ -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
342
src/grammar/lexer.l
Normal file
@ -0,0 +1,342 @@
|
||||
%{
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static int num_hashes;
|
||||
static int end_hashes;
|
||||
static int saw_non_hash;
|
||||
|
||||
%}
|
||||
|
||||
%option stack
|
||||
%option yylineno
|
||||
|
||||
%x str
|
||||
%x rawstr
|
||||
%x rawstr_esc_begin
|
||||
%x rawstr_esc_body
|
||||
%x rawstr_esc_end
|
||||
%x byte
|
||||
%x bytestr
|
||||
%x rawbytestr
|
||||
%x rawbytestr_nohash
|
||||
%x pound
|
||||
%x shebang_or_attr
|
||||
%x ltorchar
|
||||
%x linecomment
|
||||
%x doc_line
|
||||
%x blockcomment
|
||||
%x doc_block
|
||||
%x suffix
|
||||
|
||||
ident [a-zA-Z\x80-\xff_][a-zA-Z0-9\x80-\xff_]*
|
||||
|
||||
%%
|
||||
|
||||
<suffix>{ident} { BEGIN(INITIAL); }
|
||||
<suffix>(.|\n) { yyless(0); BEGIN(INITIAL); }
|
||||
|
||||
[ \n\t\r] { }
|
||||
|
||||
\xef\xbb\xbf {
|
||||
// UTF-8 byte order mark (BOM), ignore if in line 1, error otherwise
|
||||
if (yyget_lineno() != 1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
\/\/(\/|\!) { BEGIN(doc_line); yymore(); }
|
||||
<doc_line>\n { BEGIN(INITIAL);
|
||||
yyleng--;
|
||||
yytext[yyleng] = 0;
|
||||
return ((yytext[2] == '!') ? INNER_DOC_COMMENT : OUTER_DOC_COMMENT);
|
||||
}
|
||||
<doc_line>[^\n]* { yymore(); }
|
||||
|
||||
\/\/|\/\/\/\/ { BEGIN(linecomment); }
|
||||
<linecomment>\n { BEGIN(INITIAL); }
|
||||
<linecomment>[^\n]* { }
|
||||
|
||||
\/\*(\*|\!)[^*] { yy_push_state(INITIAL); yy_push_state(doc_block); yymore(); }
|
||||
<doc_block>\/\* { yy_push_state(doc_block); yymore(); }
|
||||
<doc_block>\*\/ {
|
||||
yy_pop_state();
|
||||
if (yy_top_state() == doc_block) {
|
||||
yymore();
|
||||
} else {
|
||||
return ((yytext[2] == '!') ? INNER_DOC_COMMENT : OUTER_DOC_COMMENT);
|
||||
}
|
||||
}
|
||||
<doc_block>(.|\n) { yymore(); }
|
||||
|
||||
\/\* { yy_push_state(blockcomment); }
|
||||
<blockcomment>\/\* { yy_push_state(blockcomment); }
|
||||
<blockcomment>\*\/ { yy_pop_state(); }
|
||||
<blockcomment>(.|\n) { }
|
||||
|
||||
_ { return UNDERSCORE; }
|
||||
as { return AS; }
|
||||
box { return BOX; }
|
||||
break { return BREAK; }
|
||||
const { return CONST; }
|
||||
continue { return CONTINUE; }
|
||||
crate { return CRATE; }
|
||||
else { return ELSE; }
|
||||
enum { return ENUM; }
|
||||
extern { return EXTERN; }
|
||||
false { return FALSE; }
|
||||
fn { return FN; }
|
||||
for { return FOR; }
|
||||
if { return IF; }
|
||||
impl { return IMPL; }
|
||||
in { return IN; }
|
||||
let { return LET; }
|
||||
loop { return LOOP; }
|
||||
match { return MATCH; }
|
||||
mod { return MOD; }
|
||||
move { return MOVE; }
|
||||
mut { return MUT; }
|
||||
priv { return PRIV; }
|
||||
proc { return PROC; }
|
||||
pub { return PUB; }
|
||||
ref { return REF; }
|
||||
return { return RETURN; }
|
||||
self { return SELF; }
|
||||
static { return STATIC; }
|
||||
struct { return STRUCT; }
|
||||
trait { return TRAIT; }
|
||||
true { return TRUE; }
|
||||
type { return TYPE; }
|
||||
typeof { return TYPEOF; }
|
||||
unsafe { return UNSAFE; }
|
||||
use { return USE; }
|
||||
where { return WHERE; }
|
||||
while { return WHILE; }
|
||||
|
||||
{ident} { return IDENT; }
|
||||
|
||||
0x[0-9a-fA-F_]+ { BEGIN(suffix); return LIT_INTEGER; }
|
||||
0o[0-8_]+ { BEGIN(suffix); return LIT_INTEGER; }
|
||||
0b[01_]+ { BEGIN(suffix); return LIT_INTEGER; }
|
||||
[0-9][0-9_]* { BEGIN(suffix); return LIT_INTEGER; }
|
||||
[0-9][0-9_]*\.(\.|[a-zA-Z]) { yyless(yyleng - 2); BEGIN(suffix); return LIT_INTEGER; }
|
||||
|
||||
[0-9][0-9_]*\.[0-9_]*([eE][-\+]?[0-9_]+)? { BEGIN(suffix); return LIT_FLOAT; }
|
||||
[0-9][0-9_]*(\.[0-9_]*)?[eE][-\+]?[0-9_]+ { BEGIN(suffix); return LIT_FLOAT; }
|
||||
|
||||
; { return ';'; }
|
||||
, { return ','; }
|
||||
\.\.\. { return DOTDOTDOT; }
|
||||
\.\. { return DOTDOT; }
|
||||
\. { return '.'; }
|
||||
\( { return '('; }
|
||||
\) { return ')'; }
|
||||
\{ { return '{'; }
|
||||
\} { return '}'; }
|
||||
\[ { return '['; }
|
||||
\] { return ']'; }
|
||||
@ { return '@'; }
|
||||
# { BEGIN(pound); yymore(); }
|
||||
<pound>\! { BEGIN(shebang_or_attr); yymore(); }
|
||||
<shebang_or_attr>\[ {
|
||||
BEGIN(INITIAL);
|
||||
yyless(2);
|
||||
return SHEBANG;
|
||||
}
|
||||
<shebang_or_attr>[^\[\n]*\n {
|
||||
// Since the \n was eaten as part of the token, yylineno will have
|
||||
// been incremented to the value 2 if the shebang was on the first
|
||||
// line. This yyless undoes that, setting yylineno back to 1.
|
||||
yyless(yyleng - 1);
|
||||
if (yyget_lineno() == 1) {
|
||||
BEGIN(INITIAL);
|
||||
return SHEBANG_LINE;
|
||||
} else {
|
||||
BEGIN(INITIAL);
|
||||
yyless(2);
|
||||
return SHEBANG;
|
||||
}
|
||||
}
|
||||
<pound>. { BEGIN(INITIAL); yyless(1); return '#'; }
|
||||
|
||||
\~ { return '~'; }
|
||||
:: { return MOD_SEP; }
|
||||
: { return ':'; }
|
||||
\$ { return '$'; }
|
||||
\? { return '?'; }
|
||||
|
||||
== { return EQEQ; }
|
||||
=> { return FAT_ARROW; }
|
||||
= { return '='; }
|
||||
\!= { return NE; }
|
||||
\! { return '!'; }
|
||||
\<= { return LE; }
|
||||
\<\< { return SHL; }
|
||||
\<\<= { return SHLEQ; }
|
||||
\< { return '<'; }
|
||||
\>= { return GE; }
|
||||
\>\> { return SHR; }
|
||||
\>\>= { return SHREQ; }
|
||||
\> { return '>'; }
|
||||
|
||||
\x27 { BEGIN(ltorchar); yymore(); }
|
||||
<ltorchar>static { BEGIN(INITIAL); return STATIC_LIFETIME; }
|
||||
<ltorchar>{ident} { BEGIN(INITIAL); return LIFETIME; }
|
||||
<ltorchar>\\[nrt\\\x27\x220]\x27 { BEGIN(suffix); return LIT_CHAR; }
|
||||
<ltorchar>\\x[0-9a-fA-F]{2}\x27 { BEGIN(suffix); return LIT_CHAR; }
|
||||
<ltorchar>\\u\{[0-9a-fA-F]?{6}\}\x27 { BEGIN(suffix); return LIT_CHAR; }
|
||||
<ltorchar>.\x27 { BEGIN(suffix); return LIT_CHAR; }
|
||||
<ltorchar>[\x80-\xff]{2,4}\x27 { BEGIN(suffix); return LIT_CHAR; }
|
||||
<ltorchar><<EOF>> { BEGIN(INITIAL); return -1; }
|
||||
|
||||
b\x22 { BEGIN(bytestr); yymore(); }
|
||||
<bytestr>\x22 { BEGIN(suffix); return LIT_BINARY; }
|
||||
|
||||
<bytestr><<EOF>> { return -1; }
|
||||
<bytestr>\\[n\nrt\\\x27\x220] { yymore(); }
|
||||
<bytestr>\\x[0-9a-fA-F]{2} { yymore(); }
|
||||
<bytestr>\\u\{[0-9a-fA-F]?{6}\} { yymore(); }
|
||||
<bytestr>\\[^n\nrt\\\x27\x220] { return -1; }
|
||||
<bytestr>(.|\n) { yymore(); }
|
||||
|
||||
br\x22 { BEGIN(rawbytestr_nohash); yymore(); }
|
||||
<rawbytestr_nohash>\x22 { BEGIN(suffix); return LIT_BINARY_RAW; }
|
||||
<rawbytestr_nohash>(.|\n) { yymore(); }
|
||||
<rawbytestr_nohash><<EOF>> { return -1; }
|
||||
|
||||
br/# {
|
||||
BEGIN(rawbytestr);
|
||||
yymore();
|
||||
num_hashes = 0;
|
||||
saw_non_hash = 0;
|
||||
end_hashes = 0;
|
||||
}
|
||||
<rawbytestr># {
|
||||
if (!saw_non_hash) {
|
||||
num_hashes++;
|
||||
} else if (end_hashes != 0) {
|
||||
end_hashes++;
|
||||
if (end_hashes == num_hashes) {
|
||||
BEGIN(INITIAL);
|
||||
return LIT_BINARY_RAW;
|
||||
}
|
||||
}
|
||||
yymore();
|
||||
}
|
||||
<rawbytestr>\x22# {
|
||||
end_hashes = 1;
|
||||
if (end_hashes == num_hashes) {
|
||||
BEGIN(INITIAL);
|
||||
return LIT_BINARY_RAW;
|
||||
}
|
||||
yymore();
|
||||
}
|
||||
<rawbytestr>(.|\n) {
|
||||
if (!saw_non_hash) {
|
||||
saw_non_hash = 1;
|
||||
}
|
||||
if (end_hashes != 0) {
|
||||
end_hashes = 0;
|
||||
}
|
||||
yymore();
|
||||
}
|
||||
<rawbytestr><<EOF>> { return -1; }
|
||||
|
||||
b\x27 { BEGIN(byte); yymore(); }
|
||||
<byte>\\[nrt\\\x27\x220]\x27 { BEGIN(INITIAL); return LIT_BYTE; }
|
||||
<byte>\\x[0-9a-fA-F]{2}\x27 { BEGIN(INITIAL); return LIT_BYTE; }
|
||||
<byte>\\u[0-9a-fA-F]{4}\x27 { BEGIN(INITIAL); return LIT_BYTE; }
|
||||
<byte>\\U[0-9a-fA-F]{8}\x27 { BEGIN(INITIAL); return LIT_BYTE; }
|
||||
<byte>.\x27 { BEGIN(INITIAL); return LIT_BYTE; }
|
||||
<byte><<EOF>> { BEGIN(INITIAL); return -1; }
|
||||
|
||||
r\x22 { BEGIN(rawstr); yymore(); }
|
||||
<rawstr>\x22 { BEGIN(suffix); return LIT_STR_RAW; }
|
||||
<rawstr>(.|\n) { yymore(); }
|
||||
<rawstr><<EOF>> { return -1; }
|
||||
|
||||
r/# {
|
||||
BEGIN(rawstr_esc_begin);
|
||||
yymore();
|
||||
num_hashes = 0;
|
||||
saw_non_hash = 0;
|
||||
end_hashes = 0;
|
||||
}
|
||||
|
||||
<rawstr_esc_begin># {
|
||||
num_hashes++;
|
||||
yymore();
|
||||
}
|
||||
<rawstr_esc_begin>\x22 {
|
||||
BEGIN(rawstr_esc_body);
|
||||
yymore();
|
||||
}
|
||||
<rawstr_esc_begin>(.|\n) { return -1; }
|
||||
|
||||
<rawstr_esc_body>\x22/# {
|
||||
BEGIN(rawstr_esc_end);
|
||||
yymore();
|
||||
}
|
||||
<rawstr_esc_body>(.|\n) {
|
||||
yymore();
|
||||
}
|
||||
|
||||
<rawstr_esc_end># {
|
||||
end_hashes++;
|
||||
if (end_hashes == num_hashes) {
|
||||
BEGIN(INITIAL);
|
||||
return LIT_STR_RAW;
|
||||
}
|
||||
yymore();
|
||||
}
|
||||
<rawstr_esc_end>[^#] {
|
||||
end_hashes = 0;
|
||||
BEGIN(rawstr_esc_body);
|
||||
yymore();
|
||||
}
|
||||
|
||||
<rawstr_esc_begin,rawstr_esc_body,rawstr_esc_end><<EOF>> { return -1; }
|
||||
|
||||
\x22 { BEGIN(str); yymore(); }
|
||||
<str>\x22 { BEGIN(suffix); return LIT_STR; }
|
||||
|
||||
<str><<EOF>> { return -1; }
|
||||
<str>\\[n\nrt\\\x27\x220] { yymore(); }
|
||||
<str>\\x[0-9a-fA-F]{2} { yymore(); }
|
||||
<str>\\u\{[0-9a-fA-F]?{6}\} { yymore(); }
|
||||
<str>\\[^n\nrt\\\x27\x220] { return -1; }
|
||||
<str>(.|\n) { yymore(); }
|
||||
|
||||
-\> { return RARROW; }
|
||||
- { return '-'; }
|
||||
-= { return MINUSEQ; }
|
||||
&& { return ANDAND; }
|
||||
& { return '&'; }
|
||||
&= { return ANDEQ; }
|
||||
\|\| { return OROR; }
|
||||
\| { return '|'; }
|
||||
\|= { return OREQ; }
|
||||
\+ { return '+'; }
|
||||
\+= { return PLUSEQ; }
|
||||
\* { return '*'; }
|
||||
\*= { return STAREQ; }
|
||||
\/ { return '/'; }
|
||||
\/= { return SLASHEQ; }
|
||||
\^ { return '^'; }
|
||||
\^= { return CARETEQ; }
|
||||
% { return '%'; }
|
||||
%= { return PERCENTEQ; }
|
||||
|
||||
<<EOF>> { return 0; }
|
||||
|
||||
%%
|
203
src/grammar/parser-lalr-main.c
Normal file
203
src/grammar/parser-lalr-main.c
Normal file
@ -0,0 +1,203 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
extern int yylex();
|
||||
extern int rsparse();
|
||||
|
||||
#define PUSHBACK_LEN 4
|
||||
|
||||
static char pushback[PUSHBACK_LEN];
|
||||
static int verbose;
|
||||
|
||||
void print(const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
if (verbose) {
|
||||
vprintf(format, args);
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
// If there is a non-null char at the head of the pushback queue,
|
||||
// dequeue it and shift the rest of the queue forwards. Otherwise,
|
||||
// return the token from calling yylex.
|
||||
int rslex() {
|
||||
if (pushback[0] == '\0') {
|
||||
return yylex();
|
||||
} else {
|
||||
char c = pushback[0];
|
||||
memmove(pushback, pushback + 1, PUSHBACK_LEN - 1);
|
||||
pushback[PUSHBACK_LEN - 1] = '\0';
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
// Note: this does nothing if the pushback queue is full. As long as
|
||||
// there aren't more than PUSHBACK_LEN consecutive calls to push_back
|
||||
// in an action, this shouldn't be a problem.
|
||||
void push_back(char c) {
|
||||
for (int i = 0; i < PUSHBACK_LEN; ++i) {
|
||||
if (pushback[i] == '\0') {
|
||||
pushback[i] = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern int rsdebug;
|
||||
|
||||
struct node {
|
||||
struct node *next;
|
||||
struct node *prev;
|
||||
int own_string;
|
||||
char const *name;
|
||||
int n_elems;
|
||||
struct node *elems[];
|
||||
};
|
||||
|
||||
struct node *nodes = NULL;
|
||||
int n_nodes;
|
||||
|
||||
struct node *mk_node(char const *name, int n, ...) {
|
||||
va_list ap;
|
||||
int i = 0;
|
||||
unsigned sz = sizeof(struct node) + (n * sizeof(struct node *));
|
||||
struct node *nn, *nd = (struct node *)malloc(sz);
|
||||
|
||||
print("# New %d-ary node: %s = %p\n", n, name, nd);
|
||||
|
||||
nd->own_string = 0;
|
||||
nd->prev = NULL;
|
||||
nd->next = nodes;
|
||||
if (nodes) {
|
||||
nodes->prev = nd;
|
||||
}
|
||||
nodes = nd;
|
||||
|
||||
nd->name = name;
|
||||
nd->n_elems = n;
|
||||
|
||||
va_start(ap, n);
|
||||
while (i < n) {
|
||||
nn = va_arg(ap, struct node *);
|
||||
print("# arg[%d]: %p\n", i, nn);
|
||||
print("# (%s ...)\n", nn->name);
|
||||
nd->elems[i++] = nn;
|
||||
}
|
||||
va_end(ap);
|
||||
n_nodes++;
|
||||
return nd;
|
||||
}
|
||||
|
||||
struct node *mk_atom(char *name) {
|
||||
struct node *nd = mk_node((char const *)strdup(name), 0);
|
||||
nd->own_string = 1;
|
||||
return nd;
|
||||
}
|
||||
|
||||
struct node *mk_none() {
|
||||
return mk_atom("<none>");
|
||||
}
|
||||
|
||||
struct node *ext_node(struct node *nd, int n, ...) {
|
||||
va_list ap;
|
||||
int i = 0, c = nd->n_elems + n;
|
||||
unsigned sz = sizeof(struct node) + (c * sizeof(struct node *));
|
||||
struct node *nn;
|
||||
|
||||
print("# Extending %d-ary node by %d nodes: %s = %p",
|
||||
nd->n_elems, c, nd->name, nd);
|
||||
|
||||
if (nd->next) {
|
||||
nd->next->prev = nd->prev;
|
||||
}
|
||||
if (nd->prev) {
|
||||
nd->prev->next = nd->next;
|
||||
}
|
||||
nd = realloc(nd, sz);
|
||||
nd->prev = NULL;
|
||||
nd->next = nodes;
|
||||
nodes->prev = nd;
|
||||
nodes = nd;
|
||||
|
||||
print(" ==> %p\n", nd);
|
||||
|
||||
va_start(ap, n);
|
||||
while (i < n) {
|
||||
nn = va_arg(ap, struct node *);
|
||||
print("# arg[%d]: %p\n", i, nn);
|
||||
print("# (%s ...)\n", nn->name);
|
||||
nd->elems[nd->n_elems++] = nn;
|
||||
++i;
|
||||
}
|
||||
va_end(ap);
|
||||
return nd;
|
||||
}
|
||||
|
||||
int const indent_step = 4;
|
||||
|
||||
void print_indent(int depth) {
|
||||
while (depth) {
|
||||
if (depth-- % indent_step == 0) {
|
||||
print("|");
|
||||
} else {
|
||||
print(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void print_node(struct node *n, int depth) {
|
||||
int i = 0;
|
||||
print_indent(depth);
|
||||
if (n->n_elems == 0) {
|
||||
print("%s\n", n->name);
|
||||
} else {
|
||||
print("(%s\n", n->name);
|
||||
for (i = 0; i < n->n_elems; ++i) {
|
||||
print_node(n->elems[i], depth + indent_step);
|
||||
}
|
||||
print_indent(depth);
|
||||
print(")\n");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc == 2 && strcmp(argv[1], "-v") == 0) {
|
||||
verbose = 1;
|
||||
} else {
|
||||
verbose = 0;
|
||||
}
|
||||
int ret = 0;
|
||||
struct node *tmp;
|
||||
memset(pushback, '\0', PUSHBACK_LEN);
|
||||
ret = rsparse();
|
||||
print("--- PARSE COMPLETE: ret:%d, n_nodes:%d ---\n", ret, n_nodes);
|
||||
if (nodes) {
|
||||
print_node(nodes, 0);
|
||||
}
|
||||
while (nodes) {
|
||||
tmp = nodes;
|
||||
nodes = tmp->next;
|
||||
if (tmp->own_string) {
|
||||
free((void*)tmp->name);
|
||||
}
|
||||
free(tmp);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void rserror(char const *s) {
|
||||
fprintf(stderr, "%s\n", s);
|
||||
}
|
1912
src/grammar/parser-lalr.y
Normal file
1912
src/grammar/parser-lalr.y
Normal file
File diff suppressed because it is too large
Load Diff
65
src/grammar/testparser.py
Executable file
65
src/grammar/testparser.py
Executable file
@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
# file at the top-level directory of this distribution and at
|
||||
# http://rust-lang.org/COPYRIGHT.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
# option. This file may not be copied, modified, or distributed
|
||||
# except according to those terms.
|
||||
import sys
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import argparse
|
||||
|
||||
# usage: testparser.py [-h] [-p PARSER [PARSER ...]] -s SOURCE_DIR
|
||||
|
||||
# Parsers should read from stdin and return exit status 0 for a
|
||||
# successful parse, and nonzero for an unsuccessful parse
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-p', '--parser', nargs='+')
|
||||
parser.add_argument('-s', '--source-dir', nargs=1, required=True)
|
||||
args = parser.parse_args(sys.argv[1:])
|
||||
|
||||
total = 0
|
||||
ok = {}
|
||||
bad = {}
|
||||
for parser in args.parser:
|
||||
ok[parser] = 0
|
||||
bad[parser] = []
|
||||
devnull = open(os.devnull, 'w')
|
||||
print "\n"
|
||||
|
||||
for base, dirs, files in os.walk(args.source_dir[0]):
|
||||
for f in filter(lambda p: p.endswith('.rs'), files):
|
||||
p = os.path.join(base, f)
|
||||
compile_fail = 'compile-fail' in p
|
||||
ignore = any('ignore-test' in line or 'ignore-lexer-test' in line
|
||||
for line in open(p).readlines())
|
||||
if compile_fail or ignore:
|
||||
continue
|
||||
total += 1
|
||||
for parser in args.parser:
|
||||
if subprocess.call(parser, stdin=open(p), stderr=subprocess.STDOUT, stdout=devnull) == 0:
|
||||
ok[parser] += 1
|
||||
else:
|
||||
bad[parser].append(p)
|
||||
parser_stats = ', '.join(['{}: {}'.format(parser, ok[parser]) for parser in args.parser])
|
||||
sys.stdout.write("\033[K\r total: {}, {}, scanned {}"
|
||||
.format(total, os.path.relpath(parser_stats), os.path.relpath(p)))
|
||||
|
||||
devnull.close()
|
||||
|
||||
print "\n"
|
||||
|
||||
for parser in args.parser:
|
||||
filename = os.path.basename(parser) + '.bad'
|
||||
print("writing {} files that failed to parse with {} to {}".format(len(bad[parser]), parser, filename))
|
||||
with open(filename, "w") as f:
|
||||
for p in bad[parser]:
|
||||
f.write(p)
|
||||
f.write("\n")
|
91
src/grammar/tokens.h
Normal file
91
src/grammar/tokens.h
Normal file
@ -0,0 +1,91 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
enum Token {
|
||||
SHL = 257, // Parser generators reserve 0-256 for char literals
|
||||
SHR,
|
||||
LE,
|
||||
EQEQ,
|
||||
NE,
|
||||
GE,
|
||||
ANDAND,
|
||||
OROR,
|
||||
SHLEQ,
|
||||
SHREQ,
|
||||
MINUSEQ,
|
||||
ANDEQ,
|
||||
OREQ,
|
||||
PLUSEQ,
|
||||
STAREQ,
|
||||
SLASHEQ,
|
||||
CARETEQ,
|
||||
PERCENTEQ,
|
||||
DOTDOT,
|
||||
DOTDOTDOT,
|
||||
MOD_SEP,
|
||||
RARROW,
|
||||
FAT_ARROW,
|
||||
LIT_BYTE,
|
||||
LIT_CHAR,
|
||||
LIT_INTEGER,
|
||||
LIT_FLOAT,
|
||||
LIT_STR,
|
||||
LIT_STR_RAW,
|
||||
LIT_BINARY,
|
||||
LIT_BINARY_RAW,
|
||||
IDENT,
|
||||
UNDERSCORE,
|
||||
LIFETIME,
|
||||
|
||||
// keywords
|
||||
SELF,
|
||||
STATIC,
|
||||
AS,
|
||||
BREAK,
|
||||
CRATE,
|
||||
ELSE,
|
||||
ENUM,
|
||||
EXTERN,
|
||||
FALSE,
|
||||
FN,
|
||||
FOR,
|
||||
IF,
|
||||
IMPL,
|
||||
IN,
|
||||
LET,
|
||||
LOOP,
|
||||
MATCH,
|
||||
MOD,
|
||||
MOVE,
|
||||
MUT,
|
||||
PRIV,
|
||||
PUB,
|
||||
REF,
|
||||
RETURN,
|
||||
STRUCT,
|
||||
TRUE,
|
||||
TRAIT,
|
||||
TYPE,
|
||||
UNSAFE,
|
||||
USE,
|
||||
WHILE,
|
||||
CONTINUE,
|
||||
PROC,
|
||||
BOX,
|
||||
CONST,
|
||||
WHERE,
|
||||
TYPEOF,
|
||||
INNER_DOC_COMMENT,
|
||||
OUTER_DOC_COMMENT,
|
||||
|
||||
SHEBANG,
|
||||
SHEBANG_LINE,
|
||||
STATIC_LIFETIME
|
||||
};
|
@ -589,7 +589,7 @@ impl AtomicUsize {
|
||||
/// ```
|
||||
/// use std::sync::atomic::AtomicUsize;
|
||||
///
|
||||
/// 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);
|
||||
/// ```
|
||||
|
@ -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);
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 }
|
||||
|
@ -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,
|
||||
|
@ -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, ", "));
|
||||
|
@ -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")]
|
||||
|
@ -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;
|
||||
|
@ -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]);
|
||||
/// }
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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")]
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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")]
|
||||
|
@ -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> {
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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")]
|
||||
|
@ -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,
|
||||
|
@ -212,6 +212,7 @@ impl LintStore {
|
||||
MissingCopyImplementations,
|
||||
UnstableFeatures,
|
||||
Stability,
|
||||
UnconditionalRecursion,
|
||||
);
|
||||
|
||||
add_builtin_with_new!(sess,
|
||||
|
@ -627,6 +627,7 @@ impl<'tcx> tr for MethodOrigin<'tcx> {
|
||||
// def-id is already translated when we read it out
|
||||
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()
|
||||
|
@ -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]
|
||||
// |
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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) => {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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)),
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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) }
|
||||
|
@ -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),
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
};
|
||||
|
@ -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>,
|
||||
|
@ -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
|
||||
|
@ -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
260
src/libstd/ffi/os_str.rs
Normal file
@ -0,0 +1,260 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! A type that can represent all platform-native strings, but is cheaply
|
||||
//! interconvertable with Rust strings.
|
||||
//!
|
||||
//! The need for this type arises from the fact that:
|
||||
//!
|
||||
//! * On Unix systems, strings are often arbitrary sequences of non-zero
|
||||
//! bytes, in many cases interpreted as UTF-8.
|
||||
//!
|
||||
//! * On Windows, strings are often arbitrary sequences of non-zero 16-bit
|
||||
//! values, interpreted as UTF-16 when it is valid to do so.
|
||||
//!
|
||||
//! * In Rust, strings are always valid UTF-8, but may contain zeros.
|
||||
//!
|
||||
//! The types in this module bridge this gap by simultaneously representing Rust
|
||||
//! and platform-native string values, and in particular allowing a Rust string
|
||||
//! to be converted into an "OS" string with no cost.
|
||||
//!
|
||||
//! **Note**: At the moment, these types are extremely bare-bones, usable only
|
||||
//! for conversion to/from various other string types. Eventually these types
|
||||
//! will offer a full-fledged string API.
|
||||
|
||||
#![unstable(feature = "os",
|
||||
reason = "recently added as part of path/io reform")]
|
||||
|
||||
use core::prelude::*;
|
||||
|
||||
use core::borrow::{BorrowFrom, ToOwned};
|
||||
use fmt::{self, Debug};
|
||||
use mem;
|
||||
use string::{String, CowString};
|
||||
use ops;
|
||||
use cmp;
|
||||
use hash::{Hash, Hasher, Writer};
|
||||
|
||||
use sys::os_str::{Buf, Slice};
|
||||
use sys_common::{AsInner, IntoInner, FromInner};
|
||||
|
||||
/// Owned, mutable OS strings.
|
||||
#[derive(Clone)]
|
||||
pub struct OsString {
|
||||
inner: Buf
|
||||
}
|
||||
|
||||
/// Slices into OS strings.
|
||||
pub struct OsStr {
|
||||
inner: Slice
|
||||
}
|
||||
|
||||
impl OsString {
|
||||
/// Constructs an `OsString` at no cost by consuming a `String`.
|
||||
pub fn from_string(s: String) -> OsString {
|
||||
OsString { inner: Buf::from_string(s) }
|
||||
}
|
||||
|
||||
/// Constructs an `OsString` by copying from a `&str` slice.
|
||||
///
|
||||
/// Equivalent to: `OsString::from_string(String::from_str(s))`.
|
||||
pub fn from_str(s: &str) -> OsString {
|
||||
OsString { inner: Buf::from_str(s) }
|
||||
}
|
||||
|
||||
/// Convert the `OsString` into a `String` if it contains valid Unicode data.
|
||||
///
|
||||
/// On failure, ownership of the original `OsString` is returned.
|
||||
pub fn into_string(self) -> Result<String, OsString> {
|
||||
self.inner.into_string().map_err(|buf| OsString { inner: buf} )
|
||||
}
|
||||
|
||||
/// Extend the string with the given `&OsStr` slice.
|
||||
pub fn push_os_str(&mut self, s: &OsStr) {
|
||||
self.inner.push_slice(&s.inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Index<ops::FullRange> for OsString {
|
||||
type Output = OsStr;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, _index: &ops::FullRange) -> &OsStr {
|
||||
unsafe { mem::transmute(self.inner.as_slice()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Deref for OsString {
|
||||
type Target = OsStr;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &OsStr {
|
||||
&self[]
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for OsString {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
fmt::Debug::fmt(&**self, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl OsStr {
|
||||
/// Coerce directly from a `&str` slice to a `&OsStr` slice.
|
||||
pub fn from_str(s: &str) -> &OsStr {
|
||||
unsafe { mem::transmute(Slice::from_str(s)) }
|
||||
}
|
||||
|
||||
/// Yield a `&str` slice if the `OsStr` is valid unicode.
|
||||
///
|
||||
/// This conversion may entail doing a check for UTF-8 validity.
|
||||
pub fn to_str(&self) -> Option<&str> {
|
||||
self.inner.to_str()
|
||||
}
|
||||
|
||||
/// Convert an `OsStr` to a `CowString`.
|
||||
///
|
||||
/// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
|
||||
pub fn to_string_lossy(&self) -> CowString {
|
||||
self.inner.to_string_lossy()
|
||||
}
|
||||
|
||||
/// Copy the slice into an onwed `OsString`.
|
||||
pub fn to_os_string(&self) -> OsString {
|
||||
OsString { inner: self.inner.to_owned() }
|
||||
}
|
||||
|
||||
/// Get the underlying byte representation.
|
||||
///
|
||||
/// Note: it is *crucial* that this API is private, to avoid
|
||||
/// revealing the internal, platform-specific encodings.
|
||||
fn bytes(&self) -> &[u8] {
|
||||
unsafe { mem::transmute(&self.inner) }
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for OsStr {
|
||||
fn eq(&self, other: &OsStr) -> bool {
|
||||
self.bytes().eq(other.bytes())
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<str> for OsStr {
|
||||
fn eq(&self, other: &str) -> bool {
|
||||
*self == *OsStr::from_str(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<OsStr> for str {
|
||||
fn eq(&self, other: &OsStr) -> bool {
|
||||
*other == *OsStr::from_str(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for OsStr {}
|
||||
|
||||
impl PartialOrd for OsStr {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &OsStr) -> Option<cmp::Ordering> {
|
||||
self.bytes().partial_cmp(other.bytes())
|
||||
}
|
||||
#[inline]
|
||||
fn lt(&self, other: &OsStr) -> bool { self.bytes().lt(other.bytes()) }
|
||||
#[inline]
|
||||
fn le(&self, other: &OsStr) -> bool { self.bytes().le(other.bytes()) }
|
||||
#[inline]
|
||||
fn gt(&self, other: &OsStr) -> bool { self.bytes().gt(other.bytes()) }
|
||||
#[inline]
|
||||
fn ge(&self, other: &OsStr) -> bool { self.bytes().ge(other.bytes()) }
|
||||
}
|
||||
|
||||
impl PartialOrd<str> for OsStr {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
|
||||
self.partial_cmp(OsStr::from_str(other))
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME (#19470): cannot provide PartialOrd<OsStr> for str until we
|
||||
// have more flexible coherence rules.
|
||||
|
||||
impl Ord for OsStr {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) }
|
||||
}
|
||||
|
||||
impl<'a, S: Hasher + Writer> Hash<S> for OsStr {
|
||||
#[inline]
|
||||
fn hash(&self, state: &mut S) {
|
||||
self.bytes().hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for OsStr {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
self.inner.fmt(formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl BorrowFrom<OsString> for OsStr {
|
||||
fn borrow_from(owned: &OsString) -> &OsStr { &owned[] }
|
||||
}
|
||||
|
||||
impl ToOwned<OsString> for OsStr {
|
||||
fn to_owned(&self) -> OsString { self.to_os_string() }
|
||||
}
|
||||
|
||||
/// Freely convertible to an `&OsStr` slice.
|
||||
pub trait AsOsStr {
|
||||
/// Convert to an `&OsStr` slice.
|
||||
fn as_os_str(&self) -> &OsStr;
|
||||
}
|
||||
|
||||
impl AsOsStr for OsStr {
|
||||
fn as_os_str(&self) -> &OsStr {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl AsOsStr for OsString {
|
||||
fn as_os_str(&self) -> &OsStr {
|
||||
&self[]
|
||||
}
|
||||
}
|
||||
|
||||
impl AsOsStr for str {
|
||||
fn as_os_str(&self) -> &OsStr {
|
||||
OsStr::from_str(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsOsStr for String {
|
||||
fn as_os_str(&self) -> &OsStr {
|
||||
OsStr::from_str(&self[])
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<Buf> for OsString {
|
||||
fn from_inner(buf: Buf) -> OsString {
|
||||
OsString { inner: buf }
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoInner<Buf> for OsString {
|
||||
fn into_inner(self) -> Buf {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInner<Slice> for OsStr {
|
||||
fn as_inner(&self) -> &Slice {
|
||||
&self.inner
|
||||
}
|
||||
}
|
@ -382,7 +382,7 @@ impl<T> !Sync for SyncSender<T> {}
|
||||
/// A `send` operation can only fail if the receiving end of a channel is
|
||||
/// 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 {
|
||||
|
@ -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 {
|
||||
|
@ -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];
|
||||
|
1212
src/libstd/sys/common/wtf8.rs
Normal file
1212
src/libstd/sys/common/wtf8.rs
Normal file
File diff suppressed because it is too large
Load Diff
@ -31,7 +31,10 @@
|
||||
|
||||
#![unstable(feature = "std_misc")]
|
||||
|
||||
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.
|
||||
|
@ -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;
|
||||
|
86
src/libstd/sys/unix/os_str.rs
Normal file
86
src/libstd/sys/unix/os_str.rs
Normal file
@ -0,0 +1,86 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
/// The underlying OsString/OsStr implementation on Unix systems: just
|
||||
/// a `Vec<u8>`/`[u8]`.
|
||||
|
||||
use core::prelude::*;
|
||||
|
||||
use fmt::{self, Debug};
|
||||
use vec::Vec;
|
||||
use slice::SliceExt as StdSliceExt;
|
||||
use str;
|
||||
use string::{String, CowString};
|
||||
use mem;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Buf {
|
||||
pub inner: Vec<u8>
|
||||
}
|
||||
|
||||
pub struct Slice {
|
||||
pub inner: [u8]
|
||||
}
|
||||
|
||||
impl Debug for Slice {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
self.to_string_lossy().fmt(formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Buf {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
self.as_slice().fmt(formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl Buf {
|
||||
pub fn from_string(s: String) -> Buf {
|
||||
Buf { inner: s.into_bytes() }
|
||||
}
|
||||
|
||||
pub fn from_str(s: &str) -> Buf {
|
||||
Buf { inner: s.as_bytes().to_vec() }
|
||||
}
|
||||
|
||||
pub fn as_slice(&self) -> &Slice {
|
||||
unsafe { mem::transmute(self.inner.as_slice()) }
|
||||
}
|
||||
|
||||
pub fn into_string(self) -> Result<String, Buf> {
|
||||
String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() } )
|
||||
}
|
||||
|
||||
pub fn push_slice(&mut self, s: &Slice) {
|
||||
self.inner.push_all(&s.inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl Slice {
|
||||
fn from_u8_slice(s: &[u8]) -> &Slice {
|
||||
unsafe { mem::transmute(s) }
|
||||
}
|
||||
|
||||
pub fn from_str(s: &str) -> &Slice {
|
||||
unsafe { mem::transmute(s.as_bytes()) }
|
||||
}
|
||||
|
||||
pub fn to_str(&self) -> Option<&str> {
|
||||
str::from_utf8(&self.inner).ok()
|
||||
}
|
||||
|
||||
pub fn to_string_lossy(&self) -> CowString {
|
||||
String::from_utf8_lossy(&self.inner)
|
||||
}
|
||||
|
||||
pub fn to_owned(&self) -> Buf {
|
||||
Buf { inner: self.inner.to_vec() }
|
||||
}
|
||||
}
|
@ -11,14 +11,22 @@
|
||||
use prelude::v1::*;
|
||||
|
||||
use 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 }
|
||||
}
|
||||
|
@ -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};
|
||||
}
|
||||
|
@ -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;
|
||||
|
82
src/libstd/sys/windows/os_str.rs
Normal file
82
src/libstd/sys/windows/os_str.rs
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
/// The underlying OsString/OsStr implementation on Windows is a
|
||||
/// wrapper around the "WTF-8" encoding; see the `wtf8` module for more.
|
||||
|
||||
use fmt::{self, Debug};
|
||||
use sys_common::wtf8::{Wtf8, Wtf8Buf};
|
||||
use string::{String, CowString};
|
||||
use result::Result;
|
||||
use option::Option;
|
||||
use mem;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Buf {
|
||||
pub inner: Wtf8Buf
|
||||
}
|
||||
|
||||
impl Debug for Buf {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
self.as_slice().fmt(formatter)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Slice {
|
||||
pub inner: Wtf8
|
||||
}
|
||||
|
||||
impl Debug for Slice {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
self.inner.fmt(formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl Buf {
|
||||
pub fn from_string(s: String) -> Buf {
|
||||
Buf { inner: Wtf8Buf::from_string(s) }
|
||||
}
|
||||
|
||||
pub fn from_str(s: &str) -> Buf {
|
||||
Buf { inner: Wtf8Buf::from_str(s) }
|
||||
}
|
||||
|
||||
pub fn as_slice(&self) -> &Slice {
|
||||
unsafe { mem::transmute(self.inner.as_slice()) }
|
||||
}
|
||||
|
||||
pub fn into_string(self) -> Result<String, Buf> {
|
||||
self.inner.into_string().map_err(|buf| Buf { inner: buf })
|
||||
}
|
||||
|
||||
pub fn push_slice(&mut self, s: &Slice) {
|
||||
self.inner.push_wtf8(&s.inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl Slice {
|
||||
pub fn from_str(s: &str) -> &Slice {
|
||||
unsafe { mem::transmute(Wtf8::from_str(s)) }
|
||||
}
|
||||
|
||||
pub fn to_str(&self) -> Option<&str> {
|
||||
self.inner.as_str()
|
||||
}
|
||||
|
||||
pub fn to_string_lossy(&self) -> CowString {
|
||||
self.inner.to_string_lossy()
|
||||
}
|
||||
|
||||
pub fn to_owned(&self) -> Buf {
|
||||
let mut buf = Wtf8Buf::with_capacity(self.inner.len());
|
||||
buf.push_wtf8(&self.inner);
|
||||
Buf { inner: buf }
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@
|
||||
pub use self::AsmDialect::*;
|
||||
pub use self::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,
|
||||
|
@ -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,
|
||||
|
@ -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> {
|
||||
|
@ -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> {
|
||||
|
@ -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..`.
|
||||
|
@ -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),
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
22
src/test/compile-fail/issue-19660.rs
Normal file
22
src/test/compile-fail/issue-19660.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// error-pattern: requires `copy` lang_item
|
||||
|
||||
#![feature(lang_items, start)]
|
||||
#![no_std]
|
||||
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
|
||||
#[start]
|
||||
fn main(_: int, _: *const *const u8) -> int {
|
||||
0
|
||||
}
|
66
src/test/compile-fail/lint-unconditional-recursion.rs
Normal file
66
src/test/compile-fail/lint-unconditional-recursion.rs
Normal file
@ -0,0 +1,66 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![deny(unconditional_recursion)]
|
||||
#![allow(dead_code)]
|
||||
fn foo() { //~ ERROR function cannot return without recurring
|
||||
foo(); //~ NOTE recursive call site
|
||||
}
|
||||
|
||||
fn bar() {
|
||||
if true {
|
||||
bar()
|
||||
}
|
||||
}
|
||||
|
||||
fn baz() { //~ ERROR function cannot return without recurring
|
||||
if true {
|
||||
baz() //~ NOTE recursive call site
|
||||
} else {
|
||||
baz() //~ NOTE recursive call site
|
||||
}
|
||||
}
|
||||
|
||||
fn qux() {
|
||||
loop {}
|
||||
}
|
||||
|
||||
fn quz() -> bool { //~ ERROR function cannot return without recurring
|
||||
if true {
|
||||
while quz() {} //~ NOTE recursive call site
|
||||
true
|
||||
} else {
|
||||
loop { quz(); } //~ NOTE recursive call site
|
||||
}
|
||||
}
|
||||
|
||||
trait Foo {
|
||||
fn bar(&self) { //~ ERROR function cannot return without recurring
|
||||
self.bar() //~ NOTE recursive call site
|
||||
}
|
||||
}
|
||||
|
||||
impl Foo for Box<Foo+'static> {
|
||||
fn bar(&self) { //~ ERROR function cannot return without recurring
|
||||
loop {
|
||||
self.bar() //~ NOTE recursive call site
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct Baz;
|
||||
impl Baz {
|
||||
fn qux(&self) { //~ ERROR function cannot return without recurring
|
||||
self.qux(); //~ NOTE recursive call site
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -12,12 +12,12 @@ fn f<T>() {}
|
||||
|
||||
fn main() {
|
||||
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 `<...>`
|
||||
}
|
||||
|
@ -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 `::<
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,20 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: --test
|
||||
// no-pretty-expanded
|
||||
extern crate test;
|
||||
|
||||
#[bench]
|
||||
fn bench_explicit_return_type(_: &mut ::test::Bencher) -> () {}
|
||||
|
||||
#[test]
|
||||
fn test_explicit_return_type() -> () {}
|
||||
|
Loading…
Reference in New Issue
Block a user