auto merge of #15377 : alexcrichton/rust/rollup, r=alexcrichton

Closes #15276 (Guide: if)
Closes #15280 (std::os - Add join_paths, make setenv non-utf8 capable)
Closes #15314 (Guide: functions)
Closes #15327 (Simplify PatIdent to contain an Ident rather than a Path)
Closes #15340 (Guide: add mutable binding section)
Closes #15342 (Fix ICE with nested macro_rules!-style macros)
Closes #15350 (Remove duplicated slash in install script path)
Closes #15351 (correct a few spelling mistakes in the tutorial)
Closes #15352 (librustc: Have the kind checker check sub-bounds in trait casts.)
Closes #15359 (Fix spelling errors.)
Closes #15361 (Rename set_broadast() to set_broadcast().)
Closes #15366 (Simplify creating a parser from a token tree)
Closes #15367 (Add examples for StrVector methods)
Closes #15372 (Vec::grow should use reserve_additional, Vec::reserve should check against capacity)
Closes #15373 (Fix minor issues in the documentation of libtime.)
This commit is contained in:
bors 2014-07-03 21:46:47 +00:00
commit 5d5c20647f
68 changed files with 869 additions and 423 deletions

View File

@ -515,9 +515,45 @@ let x: int = 5;
```
If I asked you to read this out loud to the rest of the class, you'd say "`x`
is a binding with the type `int` and the value `five`." Rust requires you to
initialize the binding with a value before you're allowed to use it. If
we try...
is a binding with the type `int` and the value `five`."
By default, bindings are **immutable**. This code will not compile:
```{ignore}
let x = 5i;
x = 10i;
```
It will give you this error:
```{ignore,notrust}
error: re-assignment of immutable variable `x`
x = 10i;
^~~~~~~
```
If you want a binding to be mutable, you can use `mut`:
```{rust}
let mut x = 5i;
x = 10i;
```
There is no single reason that bindings are immutable by default, but we can
think about it through one of Rust's primary focuses: safety. If you forget to
say `mut`, the compiler will catch it, and let you know that you have mutated
something you may not have cared to mutate. If bindings were mutable by
default, the compiler would not be able to tell you this. If you _did_ intend
mutation, then the solution is quite easy: add `mut`.
There are other good reasons to avoid mutable state when possible, but they're
out of the scope of this guide. In general, you can often avoid explicit
mutation, and so it is preferable in Rust. That said, sometimes, mutation is
what you need, so it's not verboten.
Let's get back to bindings. Rust variable bindings have one more aspect that
differs from other languages: bindings are required to be initialized with a
value before you're allowed to use it. If we try...
```{ignore}
let x;
@ -611,8 +647,301 @@ concept: `if`.
## If
Rust's take on `if` is not particularly complex, but it's much more like the
`if` you'll find in a dynamically typed language than in a more traditional
systems language. So let's talk about it, to make sure you grasp the nuances.
`if` is a specific form of a more general concept, the 'branch.' The name comes
from a branch in a tree: a decision point, where depending on a choice,
multiple paths can be taken.
In the case of `if`, there is one choice that leads down two paths:
```rust
let x = 5i;
if x == 5i {
println!("x is five!");
}
```
If we changed the value of `x` to something else, this line would not print.
More specifically, if the expression after the `if` evaluates to `true`, then
the block is executed. If it's `false`, then it is not.
If you want something to happen in the `false` case, use an `else`:
```
let x = 5i;
if x == 5i {
println!("x is five!");
} else {
println!("x is not five :(");
}
```
This is all pretty standard. However, you can also do this:
```
let x = 5i;
let y = if x == 5i {
10i
} else {
15i
};
```
Which we can (and probably should) write like this:
```
let x = 5i;
let y = if x == 5i { 10i } else { 15i };
```
This reveals two interesting things about Rust: it is an expression-based
language, and semicolons are different than in other 'curly brace and
semicolon'-based languages. These two things are related.
### Expressions vs. Statements
Rust is primarily an expression based language. There are only two kinds of
statements, and everything else is an expression.
So what's the difference? Expressions return a value, and statements do not.
In many languages, `if` is a statement, and therefore, `let x = if ...` would
make no sense. But in Rust, `if` is an expression, which means that it returns
a value. We can then use this value to initialize the binding.
Speaking of which, bindings are a kind of the first of Rust's two statements.
The proper name is a **declaration statement**. So far, `let` is the only kind
of declaration statement we've seen. Let's talk about that some more.
In some languages, variable bindings can be written as expressions, not just
statements. Like Ruby:
```{ruby}
x = y = 5
```
In Rust, however, using `let` to introduce a binding is _not_ an expression. The
following will produce a compile-time error:
```{ignore}
let x = (let y = 5i); // found `let` in ident position
```
The compiler is telling us here that it was expecting to see the beginning of
an expression, and a `let` can only begin a statement, not an expression.
However, re-assigning to a mutable binding is an expression:
```{rust}
let mut x = 0i;
let y = x = 5i;
```
In this case, we have an assignment expression (`x = 5`) whose value is
being used as part of a `let` declaration statement (`let y = ...`).
The second kind of statement in Rust is the **expression statement**. Its
purpose is to turn any expression into a statement. In practical terms, Rust's
grammar expects statements to follow other statements. This means that you use
semicolons to separate expressions from each other. This means that Rust
looks a lot like most other languages that require you to use semicolons
at the end of every line, and you will see semicolons at the end of almost
every line of Rust code you see.
What is this exception that makes us say 'almost?' You saw it already, in this
code:
```
let x = 5i;
let y: int = if x == 5i { 10i } else { 15i };
```
Note that I've added the type annotation to `y`, to specify explicitly that I
want `y` to be an integer.
This is not the same as this, which won't compile:
```{ignore}
let x = 5i;
let y: int = if x == 5 { 10i; } else { 15i; };
```
Note the semicolons after the 10 and 15. Rust will give us the following error:
```{ignore,notrust}
error: mismatched types: expected `int` but found `()` (expected int but found ())
```
We expected an integer, but we got `()`. `()` is pronounced 'unit', and is a
special type in Rust's type system. `()` is different than `null` in other
languages, because `()` is distinct from other types. For example, in C, `null`
is a valid value for a variable of type `int`. In Rust, `()` is _not_ a valid
value for a variable of type `int`. It's only a valid value for variables of
the type `()`, which aren't very useful. Remember how we said statements don't
return a value? Well, that's the purpose of unit in this case. The semicolon
turns any expression into a statement by throwing away its value and returning
unit instead.
There's one more time in which you won't see a semicolon at the end of a line
of Rust code. For that, we'll need our next concept: functions.
## Functions
You've already seen one function so far, the `main` function:
```{rust}
fn main() {
}
```
This is the simplest possible function declaration. As we mentioned before,
`fn` says 'this is a function,' followed by the name, some parenthesis because
this function takes no arguments, and then some curly braces to indicate the
body. Here's a function named `foo`:
```{rust}
fn foo() {
}
```
So, what about taking arguments? Here's a function that prints a number:
```{rust}
fn print_number(x: int) {
println!("x is: {}", x);
}
```
Here's a complete program that uses `print_number`:
```{rust}
fn main() {
print_number(5);
}
fn print_number(x: int) {
println!("x is: {}", x);
}
```
As you can see, function arguments work very similar to `let` declarations:
you add a type to the argument name, after a colon.
Here's a complete program that adds two numbers together and prints them:
```{rust}
fn main() {
print_sum(5, 6);
}
fn print_sum(x: int, y: int) {
println!("sum is: {}", x + y);
}
```
You separate arguments with a comma, both when you call the function, as well
as when you declare it.
Unlike `let`, you _must_ declare the types of function arguments. This does
not work:
```{ignore}
fn print_number(x, y) {
println!("x is: {}", x + y);
}
```
You get this error:
```{ignore,notrust}
hello.rs:5:18: 5:19 error: expected `:` but found `,`
hello.rs:5 fn print_number(x, y) {
```
This is a deliberate design decision. While full-program inference is possible,
languages which have it, like Haskell, often suggest that documenting your
types explicitly is a best-practice. We agree that forcing functions to declare
types while allowing for inference inside of function bodies is a wonderful
compromise between full inference and no inference.
What about returning a value? Here's a function that adds one to an integer:
```{rust}
fn add_one(x: int) -> int {
x + 1
}
```
Rust functions return exactly one value, and you declare the type after an
'arrow', which is a dash (`-`) followed by a greater-than sign (`>`).
You'll note the lack of a semicolon here. If we added it in:
```{ignore}
fn add_one(x: int) -> int {
x + 1;
}
```
We would get an error:
```{ignore,notrust}
note: consider removing this semicolon:
x + 1;
^
error: not all control paths return a value
fn add_one(x: int) -> int {
x + 1;
}
```
Remember our earlier discussions about semicolons and `()`? Our function claims
to return an `int`, but with a semicolon, it would return `()` instead. Rust
realizes this probably isn't what we want, and suggests removing the semicolon.
This is very much like our `if` statement before: the result of the block
(`{}`) is the value of the expression. Other expression-oriented languages,
such as Ruby, work like this, but it's a bit unusual in the systems programming
world. When people first learn about this, they usually assume that it
introduces bugs. But because Rust's type system is so strong, and because unit
is its own unique type, we have never seen an issue where adding or removing a
semicolon in a return position would cause a bug.
But what about early returns? Rust does have a keyword for that, `return`:
```{rust}
fn foo(x: int) -> int {
if x < 5 { return x; }
x + 1
}
```
Using a `return` as the last line of a function works, but is considered poor
style:
```{rust}
fn foo(x: int) -> int {
if x < 5 { return x; }
return x + 1;
}
```
There are some additional ways to define functions, but they involve features
that we haven't learned about yet, so let's just leave it at that for now.
## Comments
return
comments

View File

@ -469,7 +469,7 @@ fn signum(x: int) -> int {
Rust's `match` construct is a generalized, cleaned-up version of C's
`switch` construct. You provide it with a value and a number of
*arms*, each labelled with a pattern, and the code compares the value
*arms*, each labeled with a pattern, and the code compares the value
against each pattern in order until one matches. The matching pattern
executes its corresponding arm.
@ -2524,7 +2524,7 @@ of the components of types. By design, trait objects don't know the exact type
of their contents and so the compiler cannot reason about those properties.
You can instruct the compiler, however, that the contents of a trait object must
acribe to a particular bound with a trailing colon (`:`). These are examples of
ascribe to a particular bound with a trailing colon (`:`). These are examples of
valid types:
~~~rust
@ -2579,7 +2579,7 @@ This is a silly way to compute the radius of a circle
In type-parameterized functions,
methods of the supertrait may be called on values of subtrait-bound type parameters.
Refering to the previous example of `trait Circle : Shape`:
Referring to the previous example of `trait Circle : Shape`:
~~~
# trait Shape { fn area(&self) -> f64; }

View File

@ -214,7 +214,7 @@ need_cmd uname
need_cmd tr
need_cmd sed
CFG_SRC_DIR="$(cd $(dirname $0) && pwd)/"
CFG_SRC_DIR="$(cd $(dirname $0) && pwd)"
CFG_SELF="$0"
CFG_ARGS="$@"

View File

@ -185,7 +185,7 @@ impl<T: Share + Send> Drop for Arc<T> {
// deletion of the data. Because it is marked `Release`, the
// decreasing of the reference count synchronizes with this `Acquire`
// fence. This means that use of the data happens before decreasing
// the refernce count, which happens before this fence, which
// the reference count, which happens before this fence, which
// happens before the deletion of the data.
//
// As explained in the [Boost documentation][1],

View File

@ -160,9 +160,27 @@ pub fn from_chars(chs: &[char]) -> String {
/// Methods for vectors of strings
pub trait StrVector {
/// Concatenate a vector of strings.
///
/// # Example
///
/// ```rust
/// let first = "Restaurant at the End of the".to_string();
/// let second = " Universe".to_string();
/// let string_vec = vec![first, second];
/// assert_eq!(string_vec.concat(), "Restaurant at the End of the Universe".to_string());
/// ```
fn concat(&self) -> String;
/// Concatenate a vector of strings, placing a given separator between each.
///
/// # Example
///
/// ```rust
/// let first = "Roast".to_string();
/// let second = "Sirloin Steak".to_string();
/// let string_vec = vec![first, second];
/// assert_eq!(string_vec.connect(", "), "Roast, Sirloin Steak".to_string());
/// ```
fn connect(&self, sep: &str) -> String;
}
@ -172,7 +190,7 @@ impl<'a, S: Str> StrVector for &'a [S] {
return String::new();
}
// `len` calculation may overflow but push_str but will check boundaries
// `len` calculation may overflow but push_str will check boundaries
let len = self.iter().map(|s| s.as_slice().len()).sum();
let mut result = String::with_capacity(len);

View File

@ -253,8 +253,7 @@ impl<T: Clone> Vec<T> {
/// assert_eq!(vec, vec!("hello", "world", "world"));
/// ```
pub fn grow(&mut self, n: uint, value: &T) {
let new_len = self.len() + n;
self.reserve(new_len);
self.reserve_additional(n);
let mut i: uint = 0u;
while i < n {
@ -497,7 +496,7 @@ impl<T> Vec<T> {
/// assert!(vec.capacity() >= 10);
/// ```
pub fn reserve(&mut self, capacity: uint) {
if capacity >= self.len {
if capacity > self.cap {
self.reserve_exact(num::next_power_of_two(capacity))
}
}

View File

@ -59,7 +59,6 @@ use syntax::codemap::{Span, mk_sp};
use syntax::ext::base;
use syntax::ext::base::{ExtCtxt, MacExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse;
use syntax::parse::token;
use syntax::parse::token::InternedString;
use rustc::plugin::Registry;
@ -135,11 +134,7 @@ struct Ident {
fn parse_tts(cx: &ExtCtxt,
tts: &[ast::TokenTree]) -> (Gc<ast::Expr>, Option<Ident>) {
let p = &mut parse::new_parser_from_tts(cx.parse_sess(),
cx.cfg(),
tts.iter()
.map(|x| (*x).clone())
.collect());
let p = &mut cx.new_parser_from_tts(tts);
let ex = p.parse_expr();
let id = if p.token == token::EOF {
None

View File

@ -124,7 +124,7 @@ impl Drop for Stack {
}
pub struct StackPool {
// Ideally this would be some datastructure that preserved ordering on
// Ideally this would be some data structure that preserved ordering on
// Stack.min_size.
stacks: Vec<Stack>,
}

View File

@ -54,7 +54,6 @@ use syntax::codemap::{Span, mk_sp};
use syntax::ext::base;
use syntax::ext::base::{ExtCtxt, MacExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse;
use syntax::parse::token;
use rustc::plugin::Registry;
@ -167,11 +166,7 @@ struct Ident {
fn parse_tts(cx: &ExtCtxt,
tts: &[ast::TokenTree]) -> (Gc<ast::Expr>, Option<Ident>) {
let p = &mut parse::new_parser_from_tts(cx.parse_sess(),
cx.cfg(),
tts.iter()
.map(|x| (*x).clone())
.collect());
let p = &mut cx.new_parser_from_tts(tts);
let ex = p.parse_expr();
let id = if p.token == token::EOF {
None

View File

@ -288,7 +288,7 @@ pub fn mod_enabled(level: u32, module: &str) -> bool {
unsafe { INIT.doit(init); }
// It's possible for many threads are in this function, only one of them
// will peform the global initialization, but all of them will need to check
// will perform the global initialization, but all of them will need to check
// again to whether they should really be here or not. Hence, despite this
// check being expanded manually in the logging macro, this function checks
// the log level again.

View File

@ -877,7 +877,7 @@ pub fn write<T>(fd: sock_t,
}
// Also as with read(), we use MSG_DONTWAIT to guard ourselves
// against unforseen circumstances.
// against unforeseen circumstances.
let _guard = lock();
let ptr = buf.slice_from(written).as_ptr();
let len = buf.len() - written;

View File

@ -376,7 +376,7 @@ impl rtio::RtioPipe for UnixStream {
if ret != 0 { return Ok(bytes_read as uint) }
// If our errno doesn't say that the I/O is pending, then we hit some
// legitimate error and reeturn immediately.
// legitimate error and return immediately.
if os::errno() != libc::ERROR_IO_PENDING as uint {
return Err(super::last_error())
}

View File

@ -32,7 +32,6 @@ use syntax::ast;
use syntax::codemap;
use syntax::ext::build::AstBuilder;
use syntax::ext::base::{ExtCtxt, MacResult, MacExpr, DummyResult};
use syntax::parse;
use syntax::parse::token;
use syntax::print::pprust;
@ -615,8 +614,7 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
/// Looks for a single string literal and returns it.
/// Otherwise, logs an error with cx.span_err and returns None.
fn parse(cx: &mut ExtCtxt, tts: &[ast::TokenTree]) -> Option<String> {
let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
Vec::from_slice(tts));
let mut parser = cx.new_parser_from_tts(tts);
let entry = cx.expand_expr(parser.parse_expr());
let regex = match entry.node {
ast::ExprLit(lit) => {

View File

@ -31,7 +31,7 @@
#![no_std]
#![experimental]
// This library is definining the builtin functions, so it would be a shame for
// This library defines the builtin functions, so it would be a shame for
// LLVM to optimize these function calls to themselves!
#![no_builtins]

View File

@ -119,7 +119,7 @@ pub mod write {
// get all hardware potential via VFP3 (hardware floating point)
// and NEON (SIMD) instructions supported by LLVM.
// Note that without those flags various linking errors might
// arise as some of intrinsicts are converted into function calls
// arise as some of intrinsics are converted into function calls
// and nobody provides implementations those functions
fn target_feature<'a>(sess: &'a Session) -> &'a str {
match sess.targ_cfg.os {

View File

@ -902,12 +902,10 @@ impl LintPass for NonUppercasePatternStatics {
fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
// Lint for constants that look like binding identifiers (#7526)
match (&p.node, cx.tcx.def_map.borrow().find(&p.id)) {
(&ast::PatIdent(_, ref path, _), Some(&def::DefStatic(_, false))) => {
// last identifier alone is right choice for this lint.
let ident = path.segments.last().unwrap().identifier;
let s = token::get_ident(ident);
(&ast::PatIdent(_, ref path1, _), Some(&def::DefStatic(_, false))) => {
let s = token::get_ident(path1.node);
if s.get().chars().any(|c| c.is_lowercase()) {
cx.span_lint(NON_UPPERCASE_PATTERN_STATICS, path.span,
cx.span_lint(NON_UPPERCASE_PATTERN_STATICS, path1.span,
format!("static constant in pattern `{}` should have an uppercase \
name such as `{}`",
s.get(), s.get().chars().map(|c| c.to_uppercase())
@ -931,15 +929,13 @@ impl LintPass for UppercaseVariables {
fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
match &p.node {
&ast::PatIdent(_, ref path, _) => {
&ast::PatIdent(_, ref path1, _) => {
match cx.tcx.def_map.borrow().find(&p.id) {
Some(&def::DefLocal(_, _)) | Some(&def::DefBinding(_, _)) |
Some(&def::DefArg(_, _)) => {
// last identifier alone is right choice for this lint.
let ident = path.segments.last().unwrap().identifier;
let s = token::get_ident(ident);
let s = token::get_ident(path1.node);
if s.get().len() > 0 && s.get().char_at(0).is_uppercase() {
cx.span_lint(UPPERCASE_VARIABLES, path.span,
cx.span_lint(UPPERCASE_VARIABLES, path1.span,
"variable names should start with \
a lowercase character");
}
@ -989,7 +985,7 @@ impl UnnecessaryParens {
_ => {}
}
/// Expressions that syntatically contain an "exterior" struct
/// Expressions that syntactically contain an "exterior" struct
/// literal i.e. not surrounded by any parens or other
/// delimiters, e.g. `X { y: 1 }`, `X { y: 1 }.method()`, `foo
/// == X { y: 1 }` and `X { y: 1 } == foo` all do, but `(X {
@ -1113,15 +1109,10 @@ impl UnusedMut {
// avoid false warnings in match arms with multiple patterns
let mut mutables = HashMap::new();
for &p in pats.iter() {
pat_util::pat_bindings(&cx.tcx.def_map, &*p, |mode, id, _, path| {
pat_util::pat_bindings(&cx.tcx.def_map, &*p, |mode, id, _, path1| {
let ident = path1.node;
match mode {
ast::BindByValue(ast::MutMutable) => {
if path.segments.len() != 1 {
cx.sess().span_bug(p.span,
"mutable binding that doesn't consist \
of exactly one segment");
}
let ident = path.segments.get(0).identifier;
if !token::get_ident(ident).get().starts_with("_") {
mutables.insert_or_update_with(ident.name as uint,
vec!(id), |_, old| { old.push(id); });

View File

@ -809,9 +809,8 @@ fn encode_method_argument_names(ebml_w: &mut Encoder,
for arg in decl.inputs.iter() {
ebml_w.start_tag(tag_method_argument_name);
match arg.pat.node {
ast::PatIdent(_, ref name, _) => {
let name = name.segments.last().unwrap().identifier;
let name = token::get_ident(name);
ast::PatIdent(_, ref path1, _) => {
let name = token::get_ident(path1.node);
ebml_w.writer.write(name.get().as_bytes());
}
_ => {}
@ -1106,8 +1105,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
match ty.node {
ast::TyPath(ref path, ref bounds, _) if path.segments
.len() == 1 => {
let ident = path.segments.last().unwrap().identifier;
assert!(bounds.is_none());
encode_impl_type_basename(ebml_w, ast_util::path_to_ident(path));
encode_impl_type_basename(ebml_w, ident);
}
_ => {}
}

View File

@ -66,9 +66,9 @@ pub fn gather_move_from_pat(bccx: &BorrowckCtxt,
move_pat: &ast::Pat,
cmt: mc::cmt) {
let pat_span_path_opt = match move_pat.node {
ast::PatIdent(_, ref path, _) => {
Some(MoveSpanAndPath::with_span_and_path(move_pat.span,
(*path).clone()))
ast::PatIdent(_, ref path1, _) => {
Some(MoveSpanAndPath{span: move_pat.span,
ident: path1.node})
},
_ => None,
};

View File

@ -56,19 +56,8 @@ impl MoveError {
#[deriving(Clone)]
pub struct MoveSpanAndPath {
span: codemap::Span,
path: ast::Path
}
impl MoveSpanAndPath {
pub fn with_span_and_path(span: codemap::Span,
path: ast::Path)
-> MoveSpanAndPath {
MoveSpanAndPath {
span: span,
path: path,
}
}
pub span: codemap::Span,
pub ident: ast::Ident
}
pub struct GroupedMoveErrors {
@ -83,7 +72,7 @@ fn report_move_errors(bccx: &BorrowckCtxt, errors: &Vec<MoveError>) {
let mut is_first_note = true;
for move_to in error.move_to_places.iter() {
note_move_destination(bccx, move_to.span,
&move_to.path, is_first_note);
&move_to.ident, is_first_note);
is_first_note = false;
}
}
@ -154,9 +143,9 @@ fn report_cannot_move_out_of(bccx: &BorrowckCtxt, move_from: mc::cmt) {
fn note_move_destination(bccx: &BorrowckCtxt,
move_to_span: codemap::Span,
pat_ident_path: &ast::Path,
pat_ident: &ast::Ident,
is_first_note: bool) {
let pat_name = pprust::path_to_str(pat_ident_path);
let pat_name = pprust::ident_to_str(pat_ident);
if is_first_note {
bccx.span_note(
move_to_span,

View File

@ -247,6 +247,10 @@ impl<'a> Visitor<MarkSymbolVisitorContext> for MarkSymbolVisitor<'a> {
ast::PatStruct(_, ref fields, _) => {
self.handle_field_pattern_match(pat, fields.as_slice());
}
ast::PatIdent(_, _, _) => {
// it might be the only use of a static:
self.lookup_and_handle_definition(&pat.id)
}
_ => ()
}

View File

@ -13,6 +13,7 @@ use middle::freevars::freevar_entry;
use middle::freevars;
use middle::subst;
use middle::ty;
use middle::typeck::{MethodCall, NoAdjustment};
use middle::typeck;
use util::ppaux::{Repr, ty_to_str};
use util::ppaux::UserString;
@ -20,7 +21,7 @@ use util::ppaux::UserString;
use syntax::ast::*;
use syntax::attr;
use syntax::codemap::Span;
use syntax::print::pprust::{expr_to_str,path_to_str};
use syntax::print::pprust::{expr_to_str, ident_to_str};
use syntax::{visit};
use syntax::visit::Visitor;
@ -261,7 +262,15 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
ExprCast(ref source, _) => {
let source_ty = ty::expr_ty(cx.tcx, &**source);
let target_ty = ty::expr_ty(cx.tcx, e);
check_trait_cast(cx, source_ty, target_ty, source.span);
let method_call = MethodCall {
expr_id: e.id,
adjustment: NoAdjustment,
};
check_trait_cast(cx,
source_ty,
target_ty,
source.span,
method_call);
}
ExprRepeat(ref element, ref count_expr) => {
let count = ty::eval_repeat_count(cx.tcx, &**count_expr);
@ -281,7 +290,15 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
ty::AutoObject(..) => {
let source_ty = ty::expr_ty(cx.tcx, e);
let target_ty = ty::expr_ty_adjusted(cx.tcx, e);
check_trait_cast(cx, source_ty, target_ty, e.span);
let method_call = MethodCall {
expr_id: e.id,
adjustment: typeck::AutoObject,
};
check_trait_cast(cx,
source_ty,
target_ty,
e.span,
method_call);
}
ty::AutoAddEnv(..) |
ty::AutoDerefRef(..) => {}
@ -364,15 +381,62 @@ fn check_bounds_on_type_parameters(cx: &mut Context, e: &Expr) {
}
}
fn check_trait_cast(cx: &mut Context, source_ty: ty::t, target_ty: ty::t, span: Span) {
fn check_type_parameter_bounds_in_vtable_result(
cx: &mut Context,
span: Span,
vtable_res: &typeck::vtable_res) {
for origins in vtable_res.iter() {
for origin in origins.iter() {
let (type_param_defs, substs) = match *origin {
typeck::vtable_static(def_id, ref tys, _) => {
let type_param_defs =
ty::lookup_item_type(cx.tcx, def_id).generics
.types
.clone();
(type_param_defs, (*tys).clone())
}
_ => {
// Nothing to do here.
continue
}
};
for type_param_def in type_param_defs.iter() {
let typ = substs.types.get(type_param_def.space,
type_param_def.index);
check_typaram_bounds(cx, span, *typ, type_param_def)
}
}
}
}
fn check_trait_cast(cx: &mut Context,
source_ty: ty::t,
target_ty: ty::t,
span: Span,
method_call: MethodCall) {
check_cast_for_escaping_regions(cx, source_ty, target_ty, span);
match ty::get(target_ty).sty {
ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ ty, .. }) => match ty::get(ty).sty {
ty::ty_trait(box ty::TyTrait { bounds, .. }) => {
check_trait_cast_bounds(cx, span, source_ty, bounds);
ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ ty, .. }) => {
match ty::get(ty).sty {
ty::ty_trait(box ty::TyTrait { bounds, .. }) => {
match cx.tcx.vtable_map.borrow().find(&method_call) {
None => {
cx.tcx.sess.span_bug(span,
"trait cast not in vtable \
map?!")
}
Some(vtable_res) => {
check_type_parameter_bounds_in_vtable_result(
cx,
span,
vtable_res)
}
};
check_trait_cast_bounds(cx, span, source_ty, bounds);
}
_ => {}
}
_ => {}
},
}
_ => {}
}
}
@ -627,7 +691,7 @@ fn check_sized(tcx: &ty::ctxt, ty: ty::t, name: String, sp: Span) {
fn check_pat(cx: &mut Context, pat: &Pat) {
let var_name = match pat.node {
PatWild => Some("_".to_string()),
PatIdent(_, ref path, _) => Some(path_to_str(path).to_string()),
PatIdent(_, ref path1, _) => Some(ident_to_str(&path1.node).to_string()),
_ => None
};

View File

@ -367,9 +367,9 @@ fn visit_fn(ir: &mut IrMaps,
for arg in decl.inputs.iter() {
pat_util::pat_bindings(&ir.tcx.def_map,
&*arg.pat,
|_bm, arg_id, _x, path| {
|_bm, arg_id, _x, path1| {
debug!("adding argument {}", arg_id);
let ident = ast_util::path_to_ident(path);
let ident = path1.node;
fn_maps.add_variable(Arg(arg_id, ident));
})
};
@ -399,9 +399,9 @@ fn visit_fn(ir: &mut IrMaps,
}
fn visit_local(ir: &mut IrMaps, local: &Local) {
pat_util::pat_bindings(&ir.tcx.def_map, &*local.pat, |_, p_id, sp, path| {
pat_util::pat_bindings(&ir.tcx.def_map, &*local.pat, |_, p_id, sp, path1| {
debug!("adding local variable {}", p_id);
let name = ast_util::path_to_ident(path);
let name = path1.node;
ir.add_live_node_for_node(p_id, VarDefNode(sp));
ir.add_variable(Local(LocalInfo {
id: p_id,
@ -413,10 +413,10 @@ fn visit_local(ir: &mut IrMaps, local: &Local) {
fn visit_arm(ir: &mut IrMaps, arm: &Arm) {
for pat in arm.pats.iter() {
pat_util::pat_bindings(&ir.tcx.def_map, &**pat, |bm, p_id, sp, path| {
pat_util::pat_bindings(&ir.tcx.def_map, &**pat, |bm, p_id, sp, path1| {
debug!("adding local variable {} from match with bm {:?}",
p_id, bm);
let name = ast_util::path_to_ident(path);
let name = path1.node;
ir.add_live_node_for_node(p_id, VarDefNode(sp));
ir.add_variable(Local(LocalInfo {
id: p_id,
@ -1522,10 +1522,10 @@ impl<'a> Liveness<'a> {
for arg in decl.inputs.iter() {
pat_util::pat_bindings(&self.ir.tcx.def_map,
&*arg.pat,
|_bm, p_id, sp, path| {
|_bm, p_id, sp, path1| {
let var = self.variable(p_id, sp);
// Ignore unused self.
let ident = ast_util::path_to_ident(path);
let ident = path1.node;
if ident.name != special_idents::self_.name {
self.warn_about_unused(sp, p_id, entry_ln, var);
}

View File

@ -383,7 +383,7 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
Some(adjustment) => {
match *adjustment {
ty::AutoObject(..) => {
// Implicity cast a concrete object to trait object.
// Implicitly cast a concrete object to trait object.
// Result is an rvalue.
let expr_ty = if_ok!(self.expr_ty_adjusted(expr));
Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))

View File

@ -14,7 +14,7 @@ use middle::resolve;
use std::collections::HashMap;
use std::gc::{Gc, GC};
use syntax::ast::*;
use syntax::ast_util::{path_to_ident, walk_pat};
use syntax::ast_util::{walk_pat};
use syntax::codemap::{Span, DUMMY_SP};
pub type PatIdMap = HashMap<Ident, NodeId>;
@ -23,8 +23,8 @@ pub type PatIdMap = HashMap<Ident, NodeId>;
// use the NodeId of their namesake in the first pattern.
pub fn pat_id_map(dm: &resolve::DefMap, pat: &Pat) -> PatIdMap {
let mut map = HashMap::new();
pat_bindings(dm, pat, |_bm, p_id, _s, n| {
map.insert(path_to_ident(n), p_id);
pat_bindings(dm, pat, |_bm, p_id, _s, path1| {
map.insert(path1.node, p_id);
});
map
}
@ -75,7 +75,7 @@ pub fn pat_is_binding_or_wild(dm: &resolve::DefMap, pat: &Pat) -> bool {
/// `match foo() { Some(a) => (), None => () }`
pub fn pat_bindings(dm: &resolve::DefMap,
pat: &Pat,
it: |BindingMode, NodeId, Span, &Path|) {
it: |BindingMode, NodeId, Span, &SpannedIdent|) {
walk_pat(pat, |p| {
match p.node {
PatIdent(binding_mode, ref pth, _) if pat_is_binding(dm, p) => {
@ -102,10 +102,10 @@ pub fn pat_contains_bindings(dm: &resolve::DefMap, pat: &Pat) -> bool {
contains_bindings
}
pub fn simple_identifier<'a>(pat: &'a Pat) -> Option<&'a Path> {
pub fn simple_identifier<'a>(pat: &'a Pat) -> Option<&'a Ident> {
match pat.node {
PatIdent(BindByValue(_), ref path, None) => {
Some(path)
PatIdent(BindByValue(_), ref path1, None) => {
Some(&path1.node)
}
_ => {
None

View File

@ -1267,7 +1267,7 @@ impl<'a> Visitor<()> for VisiblePrivateTypesVisitor<'a> {
// error messages without (too many) false positives
// (i.e. we could just return here to not check them at
// all, or some worse estimation of whether an impl is
// publically visible.
// publicly visible.
ast::ItemImpl(ref g, ref trait_ref, self_, ref methods) => {
// `impl [... for] Private` is never visible.
let self_contains_private;

View File

@ -23,11 +23,10 @@ use util::nodemap::{NodeMap, DefIdSet, FnvHashMap};
use syntax::ast::*;
use syntax::ast;
use syntax::ast_util::{local_def};
use syntax::ast_util::{path_to_ident, walk_pat, trait_method_to_ty_method};
use syntax::ast_util::{walk_pat, trait_method_to_ty_method};
use syntax::ext::mtwt;
use syntax::parse::token::special_idents;
use syntax::parse::token;
use syntax::print::pprust::path_to_str;
use syntax::codemap::{Span, DUMMY_SP, Pos};
use syntax::owned_slice::OwnedSlice;
use syntax::visit;
@ -1247,7 +1246,7 @@ impl<'a> Resolver<'a> {
// Create the module and add all methods.
match ty.node {
TyPath(ref path, _, _) if path.segments.len() == 1 => {
let name = path_to_ident(path);
let name = path.segments.last().unwrap().identifier;
let parent_opt = parent.module().children.borrow()
.find_copy(&name.name);
@ -4104,8 +4103,8 @@ impl<'a> Resolver<'a> {
// user and one 'x' came from the macro.
fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
let mut result = HashMap::new();
pat_bindings(&self.def_map, pat, |binding_mode, _id, sp, path| {
let name = mtwt::resolve(path_to_ident(path));
pat_bindings(&self.def_map, pat, |binding_mode, _id, sp, path1| {
let name = mtwt::resolve(path1.node);
result.insert(name,
binding_info {span: sp,
binding_mode: binding_mode});
@ -4314,8 +4313,7 @@ impl<'a> Resolver<'a> {
let pat_id = pattern.id;
walk_pat(pattern, |pattern| {
match pattern.node {
PatIdent(binding_mode, ref path, _)
if !path.global && path.segments.len() == 1 => {
PatIdent(binding_mode, ref path1, _) => {
// The meaning of pat_ident with no type parameters
// depends on whether an enum variant or unit-like struct
@ -4326,7 +4324,7 @@ impl<'a> Resolver<'a> {
// such a value is simply disallowed (since it's rarely
// what you want).
let ident = path.segments.get(0).identifier;
let ident = path1.node;
let renamed = mtwt::resolve(ident);
match self.resolve_bare_identifier_pattern(ident) {
@ -4416,57 +4414,12 @@ impl<'a> Resolver<'a> {
format!("identifier `{}` is bound \
more than once in the same \
pattern",
path_to_str(path)).as_slice());
token::get_ident(ident)).as_slice());
}
// Else, not bound in the same pattern: do
// nothing.
}
}
// Check the types in the path pattern.
for ty in path.segments
.iter()
.flat_map(|seg| seg.types.iter()) {
self.resolve_type(&**ty);
}
}
PatIdent(binding_mode, ref path, _) => {
// This must be an enum variant, struct, or constant.
match self.resolve_path(pat_id, path, ValueNS, false) {
Some(def @ (DefVariant(..), _)) |
Some(def @ (DefStruct(..), _)) => {
self.record_def(pattern.id, def);
}
Some(def @ (DefStatic(..), _)) => {
self.enforce_default_binding_mode(
pattern,
binding_mode,
"a constant");
self.record_def(pattern.id, def);
}
Some(_) => {
self.resolve_error(
path.span,
format!("`{}` is not an enum variant or constant",
token::get_ident(
path.segments
.last()
.unwrap()
.identifier)).as_slice())
}
None => {
self.resolve_error(path.span,
"unresolved enum variant");
}
}
// Check the types in the path pattern.
for ty in path.segments
.iter()
.flat_map(|s| s.types.iter()) {
self.resolve_type(&**ty);
}
}
PatEnum(ref path, _) => {
@ -5202,8 +5155,8 @@ impl<'a> Resolver<'a> {
in a static method. Maybe a \
`self` argument is missing?");
} else {
let name = path_to_ident(path).name;
let mut msg = match self.find_fallback_in_self_type(name) {
let last_name = path.segments.last().unwrap().identifier.name;
let mut msg = match self.find_fallback_in_self_type(last_name) {
NoSuggestion => {
// limit search to 5 to reduce the number
// of stupid suggestions

View File

@ -484,7 +484,7 @@ impl <'l> DxrVisitor<'l> {
{
let qualname = self.analysis.ty_cx.map.path_to_str(item.id);
// If the variable is immutable, save the initialising expresion.
// If the variable is immutable, save the initialising expression.
let value = match mt {
ast::MutMutable => String::from_str("<mutable>"),
ast::MutImmutable => self.span.snippet(expr.span),
@ -845,7 +845,7 @@ impl <'l> DxrVisitor<'l> {
let decl_id = ty::trait_method_of_method(&self.analysis.ty_cx, def_id);
// This incantation is required if the method referenced is a trait's
// defailt implementation.
// default implementation.
let def_id = ty::method(&self.analysis.ty_cx, def_id).provided_source
.unwrap_or(def_id);
(Some(def_id), decl_id)
@ -926,7 +926,7 @@ impl <'l> DxrVisitor<'l> {
self.collected_paths.push((p.id, path.clone(), false, recorder::VarRef));
visit::walk_pat(self, p, e);
}
ast::PatIdent(bm, ref path, ref optional_subpattern) => {
ast::PatIdent(bm, ref path1, ref optional_subpattern) => {
let immut = match bm {
// Even if the ref is mut, you can't change the ref, only
// the data pointed at, so showing the initialising expression
@ -940,7 +940,8 @@ impl <'l> DxrVisitor<'l> {
}
};
// collect path for either visit_local or visit_arm
self.collected_paths.push((p.id, path.clone(), immut, recorder::VarRef));
let path = ast_util::ident_to_path(path1.span,path1.node);
self.collected_paths.push((p.id, path, immut, recorder::VarRef));
match *optional_subpattern {
None => {}
Some(subpattern) => self.visit_pat(&*subpattern, e),
@ -1402,7 +1403,7 @@ pub fn process_crate(sess: &Session,
info!("Writing output to {}", disp);
}
// Create ouput file.
// Create output file.
let mut out_name = cratename.clone();
out_name.push_str(".csv");
root_path.push(out_name);

View File

@ -224,8 +224,6 @@ use std::rc::Rc;
use std::gc::{Gc};
use syntax::ast;
use syntax::ast::Ident;
use syntax::ast_util::path_to_ident;
use syntax::ast_util;
use syntax::codemap::Span;
use syntax::parse::token::InternedString;
@ -429,13 +427,13 @@ fn expand_nested_bindings<'a, 'b>(
m.iter().map(|br| {
match br.pats.get(col).node {
ast::PatIdent(_, ref path, Some(inner)) => {
ast::PatIdent(_, ref path1, Some(inner)) => {
let pats = Vec::from_slice(br.pats.slice(0u, col))
.append((vec!(inner))
.append(br.pats.slice(col + 1u, br.pats.len())).as_slice());
let mut bound_ptrs = br.bound_ptrs.clone();
bound_ptrs.push((path_to_ident(path), val));
bound_ptrs.push((path1.node, val));
Match {
pats: pats,
data: &*br.data,
@ -473,9 +471,9 @@ fn enter_match<'a, 'b>(
let this = *br.pats.get(col);
let mut bound_ptrs = br.bound_ptrs.clone();
match this.node {
ast::PatIdent(_, ref path, None) => {
ast::PatIdent(_, ref path1, None) => {
if pat_is_binding(dm, &*this) {
bound_ptrs.push((path_to_ident(path), val));
bound_ptrs.push((path1.node, val));
}
}
_ => {}
@ -1366,8 +1364,8 @@ fn create_bindings_map(bcx: &Block, pat: Gc<ast::Pat>) -> BindingsMap {
let ccx = bcx.ccx();
let tcx = bcx.tcx();
let mut bindings_map = HashMap::new();
pat_bindings(&tcx.def_map, &*pat, |bm, p_id, span, path| {
let ident = path_to_ident(path);
pat_bindings(&tcx.def_map, &*pat, |bm, p_id, span, path1| {
let ident = path1.node;
let variable_ty = node_id_type(bcx, p_id);
let llvariable_ty = type_of::type_of(ccx, variable_ty);
let tcx = bcx.tcx();
@ -1520,10 +1518,10 @@ pub fn store_local<'a>(bcx: &'a Block<'a>,
// In such cases, the more general path is unsafe, because
// it assumes it is matching against a valid value.
match simple_identifier(&*pat) {
Some(path) => {
Some(ident) => {
let var_scope = cleanup::var_scope(tcx, local.id);
return mk_binding_alloca(
bcx, pat.id, path, BindLocal, var_scope, (),
bcx, pat.id, ident, BindLocal, var_scope, (),
|(), bcx, v, _| expr::trans_into(bcx, &*init_expr,
expr::SaveIn(v)));
}
@ -1555,10 +1553,10 @@ pub fn store_local<'a>(bcx: &'a Block<'a>,
// create dummy memory for the variables if we have no
// value to store into them immediately
let tcx = bcx.tcx();
pat_bindings(&tcx.def_map, &*pat, |_, p_id, _, path| {
pat_bindings(&tcx.def_map, &*pat, |_, p_id, _, path1| {
let scope = cleanup::var_scope(tcx, p_id);
bcx = mk_binding_alloca(
bcx, p_id, path, BindLocal, scope, (),
bcx, p_id, &path1.node, BindLocal, scope, (),
|(), bcx, llval, ty| { zero_mem(bcx, llval, ty); bcx });
});
bcx
@ -1586,7 +1584,7 @@ pub fn store_arg<'a>(mut bcx: &'a Block<'a>,
let _icx = push_ctxt("match::store_arg");
match simple_identifier(&*pat) {
Some(path) => {
Some(ident) => {
// Generate nicer LLVM for the common case of fn a pattern
// like `x: T`
let arg_ty = node_id_type(bcx, pat.id);
@ -1601,7 +1599,7 @@ pub fn store_arg<'a>(mut bcx: &'a Block<'a>,
bcx
} else {
mk_binding_alloca(
bcx, pat.id, path, BindArgument, arg_scope, arg,
bcx, pat.id, ident, BindArgument, arg_scope, arg,
|arg, bcx, llval, _| arg.store_to(bcx, llval))
}
}
@ -1619,17 +1617,16 @@ pub fn store_arg<'a>(mut bcx: &'a Block<'a>,
fn mk_binding_alloca<'a,A>(bcx: &'a Block<'a>,
p_id: ast::NodeId,
path: &ast::Path,
ident: &ast::Ident,
binding_mode: IrrefutablePatternBindingMode,
cleanup_scope: cleanup::ScopeId,
arg: A,
populate: |A, &'a Block<'a>, ValueRef, ty::t| -> &'a Block<'a>)
-> &'a Block<'a> {
let var_ty = node_id_type(bcx, p_id);
let ident = ast_util::path_to_ident(path);
// Allocate memory on stack for the binding.
let llval = alloc_ty(bcx, var_ty, bcx.ident(ident).as_slice());
let llval = alloc_ty(bcx, var_ty, bcx.ident(*ident).as_slice());
// Subtle: be sure that we *populate* the memory *before*
// we schedule the cleanup.
@ -1687,13 +1684,13 @@ fn bind_irrefutable_pat<'a>(
let tcx = bcx.tcx();
let ccx = bcx.ccx();
match pat.node {
ast::PatIdent(pat_binding_mode, ref path, inner) => {
ast::PatIdent(pat_binding_mode, ref path1, inner) => {
if pat_is_binding(&tcx.def_map, &*pat) {
// Allocate the stack slot where the value of this
// binding will live and place it into the appropriate
// map.
bcx = mk_binding_alloca(
bcx, pat.id, path, binding_mode, cleanup_scope, (),
bcx, pat.id, &path1.node, binding_mode, cleanup_scope, (),
|(), bcx, llval, ty| {
match pat_binding_mode {
ast::BindByValue(_) => {

View File

@ -842,8 +842,8 @@ pub fn create_local_var_metadata(bcx: &Block, local: &ast::Local) {
let cx = bcx.ccx();
let def_map = &cx.tcx.def_map;
pat_util::pat_bindings(def_map, &*local.pat, |_, node_id, span, path_ref| {
let var_ident = ast_util::path_to_ident(path_ref);
pat_util::pat_bindings(def_map, &*local.pat, |_, node_id, span, path1| {
let var_ident = path1.node;
let datum = match bcx.fcx.lllocals.borrow().find_copy(&node_id) {
Some(datum) => datum,
@ -890,8 +890,8 @@ pub fn create_captured_var_metadata(bcx: &Block,
}
Some(ast_map::NodeLocal(pat)) | Some(ast_map::NodeArg(pat)) => {
match pat.node {
ast::PatIdent(_, ref path, _) => {
ast_util::path_to_ident(path)
ast::PatIdent(_, ref path1, _) => {
path1.node
}
_ => {
cx.sess()
@ -1007,7 +1007,7 @@ pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
let def_map = &cx.tcx.def_map;
let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata;
pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, span, path_ref| {
pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, span, path1| {
let llarg = match bcx.fcx.llargs.borrow().find_copy(&node_id) {
Some(v) => v,
None => {
@ -1022,8 +1022,6 @@ pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
Referenced variable location is not an alloca!");
}
let argument_ident = ast_util::path_to_ident(path_ref);
let argument_index = {
let counter = &fcx.debug_context.get_ref(cx, span).argument_counter;
let argument_index = counter.get();
@ -1032,7 +1030,7 @@ pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
};
declare_local(bcx,
argument_ident,
path1.node,
llarg.ty,
scope_metadata,
DirectVariable { alloca: llarg.val },
@ -3237,10 +3235,9 @@ fn populate_scope_map(cx: &CrateContext,
// Push argument identifiers onto the stack so arguments integrate nicely
// with variable shadowing.
for &arg_pat in arg_pats.iter() {
pat_util::pat_bindings(def_map, &*arg_pat, |_, _, _, path_ref| {
let ident = ast_util::path_to_ident(path_ref);
pat_util::pat_bindings(def_map, &*arg_pat, |_, _, _, path1| {
scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata,
ident: Some(ident) });
ident: Some(path1.node) });
})
}
@ -3348,13 +3345,13 @@ fn populate_scope_map(cx: &CrateContext,
// ast_util::walk_pat() here because we have to visit *all* nodes in
// order to put them into the scope map. The above functions don't do that.
match pat.node {
ast::PatIdent(_, ref path_ref, ref sub_pat_opt) => {
ast::PatIdent(_, ref path1, ref sub_pat_opt) => {
// Check if this is a binding. If so we need to put it on the
// scope stack and maybe introduce an artificial scope
if pat_util::pat_is_binding(def_map, &*pat) {
let ident = ast_util::path_to_ident(path_ref);
let ident = path1.node;
// LLVM does not properly generate 'DW_AT_start_scope' fields
// for variable DIEs. For this reason we have to introduce

View File

@ -2771,8 +2771,8 @@ pub fn local_var_name_str(cx: &ctxt, id: NodeId) -> InternedString {
match cx.map.find(id) {
Some(ast_map::NodeLocal(pat)) => {
match pat.node {
ast::PatIdent(_, ref path, _) => {
token::get_ident(ast_util::path_to_ident(path))
ast::PatIdent(_, ref path1, _) => {
token::get_ident(path1.node)
}
_ => {
cx.sess.bug(

View File

@ -485,7 +485,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
demand::suptype(fcx, pat.span, expected, const_pty.ty);
fcx.write_ty(pat.id, const_pty.ty);
}
ast::PatIdent(bm, ref name, sub) if pat_is_binding(&tcx.def_map, pat) => {
ast::PatIdent(bm, ref path1, sub) if pat_is_binding(&tcx.def_map, pat) => {
let typ = fcx.local_ty(pat.span, pat.id);
match bm {
@ -507,7 +507,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
}
}
let canon_id = *pcx.map.get(&ast_util::path_to_ident(name));
let canon_id = *pcx.map.get(&path1.node);
if canon_id != pat.id {
let ct = fcx.local_ty(pat.span, canon_id);
demand::eqtype(fcx, pat.span, ct, typ);
@ -521,8 +521,10 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
_ => ()
}
}
ast::PatIdent(_, ref path, _) => {
check_pat_variant(pcx, pat, path, &Some(Vec::new()), expected);
// it's not a binding, it's an enum in disguise:
ast::PatIdent(_, ref path1, _) => {
let path = ast_util::ident_to_path(path1.span,path1.node);
check_pat_variant(pcx, pat, &path, &Some(Vec::new()), expected);
}
ast::PatEnum(ref path, ref subpats) => {
check_pat_variant(pcx, pat, path, subpats, expected);

View File

@ -406,11 +406,11 @@ impl<'a> Visitor<()> for GatherLocalsVisitor<'a> {
// Add pattern bindings.
fn visit_pat(&mut self, p: &ast::Pat, _: ()) {
match p.node {
ast::PatIdent(_, ref path, _)
ast::PatIdent(_, ref path1, _)
if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) => {
self.assign(p.id, None);
debug!("Pattern binding {} is assigned to {}",
token::get_ident(path.segments.get(0).identifier),
token::get_ident(path1.node),
self.fcx.infcx().ty_to_str(
self.fcx.inh.locals.borrow().get_copy(&p.id)));
}

View File

@ -398,6 +398,9 @@ fn search_for_vtable(vcx: &VtableContext,
// Resolve any sub bounds. Note that there still may be free
// type variables in substs. This might still be OK: the
// process of looking up bounds might constrain some of them.
//
// This does not check built-in traits because those are handled
// later in the kind checking pass.
let im_generics =
ty::lookup_item_type(tcx, impl_did).generics;
let subres = lookup_vtables(vcx,

View File

@ -93,7 +93,7 @@ pub struct UnificationTable<K,V> {
/**
* At any time, users may snapshot a unification table. The changes
* made during the snapshot may either be *commited* or *rolled back*.
* made during the snapshot may either be *committed* or *rolled back*.
*/
pub struct Snapshot<K> {
// Ensure that this snapshot is keyed to the table type.
@ -152,7 +152,7 @@ impl<V:PartialEq+Clone+Repr,K:UnifyKey<V>> UnificationTable<K,V> {
/**
* Starts a new snapshot. Each snapshot must be either
* rolled back or commited in a "LIFO" (stack) order.
* rolled back or committed in a "LIFO" (stack) order.
*/
pub fn snapshot(&mut self) -> Snapshot<K> {
let length = self.undo_log.len();
@ -188,12 +188,12 @@ impl<V:PartialEq+Clone+Repr,K:UnifyKey<V>> UnificationTable<K,V> {
match self.undo_log.pop().unwrap() {
OpenSnapshot => {
// This indicates a failure to obey the stack discipline.
tcx.sess.bug("Cannot rollback an uncommited snapshot");
tcx.sess.bug("Cannot rollback an uncommitted snapshot");
}
CommittedSnapshot => {
// This occurs when there are nested snapshots and
// the inner is commited but outer is rolled back.
// the inner is committed but outer is rolled back.
}
NewVar(i) => {

View File

@ -216,9 +216,9 @@ pub type vtable_res = VecPerParamSpace<vtable_param_res>;
#[deriving(Clone)]
pub enum vtable_origin {
/*
Statically known vtable. def_id gives the class or impl item
Statically known vtable. def_id gives the impl item
from whence comes the vtable, and tys are the type substs.
vtable_res is the vtable itself
vtable_res is the vtable itself.
*/
vtable_static(ast::DefId, subst::Substs, vtable_res),

View File

@ -1583,8 +1583,6 @@ impl Clean<PathSegment> for ast::PathSegment {
}
fn path_to_str(p: &ast::Path) -> String {
use syntax::parse::token;
let mut s = String::new();
let mut first = true;
for i in p.segments.iter().map(|x| token::get_ident(x.identifier)) {
@ -1739,7 +1737,7 @@ pub struct ViewItem {
impl Clean<Vec<Item>> for ast::ViewItem {
fn clean(&self) -> Vec<Item> {
// We consider inlining the documentation of `pub use` statments, but we
// We consider inlining the documentation of `pub use` statements, but we
// forcefully don't inline if this is not public or if the
// #[doc(no_inline)] attribute is present.
let denied = self.vis != ast::Public || self.attrs.iter().any(|a| {
@ -1953,7 +1951,7 @@ fn name_from_pat(p: &ast::Pat) -> String {
match p.node {
PatWild => "_".to_string(),
PatWildMulti => "..".to_string(),
PatIdent(_, ref p, _) => path_to_str(p),
PatIdent(_, ref p, _) => token::get_ident(p.node).get().to_string(),
PatEnum(ref p, _) => path_to_str(p),
PatStruct(..) => fail!("tried to get argument name from pat_struct, \
which is not allowed in function arguments"),

View File

@ -376,7 +376,7 @@ pub trait ToCStr {
// (without forcing an additional & around &str). So we are instead
// temporarily adding an instance for ~str and String, so that we can
// take ToCStr as owned. When DST lands, the string instances should
// be revisted, and arguments bound by ToCStr should be passed by
// be revisited, and arguments bound by ToCStr should be passed by
// reference.
impl<'a> ToCStr for &'a str {

View File

@ -97,7 +97,7 @@ extern {}
extern "C" {
// iOS on armv7 uses SjLj exceptions and requires to link
// agains corresponding routine (..._SjLj_...)
// against corresponding routine (..._SjLj_...)
#[cfg(not(target_os = "ios", target_arch = "arm"))]
pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception)
-> _Unwind_Reason_Code;

View File

@ -170,7 +170,7 @@ impl Task {
/// This function can be used as an emulated "try/catch" to interoperate
/// with the rust runtime at the outermost boundary. It is not possible to
/// use this function in a nested fashion (a try/catch inside of another
/// try/catch). Invoking this funciton is quite cheap.
/// try/catch). Invoking this function is quite cheap.
///
/// If the closure `f` succeeds, then the returned task can be used again
/// for another invocation of `run`. If the closure `f` fails then `self`
@ -276,7 +276,7 @@ impl Task {
// 1. If TLD destruction fails, heap destruction will be attempted.
// There is a test for this at fail-during-tld-destroy.rs. Sadly the
// other way can't be tested due to point 2 above. Note that we must
// immortalize the heap first becuase if any deallocations are
// immortalize the heap first because if any deallocations are
// attempted while TLD is being dropped it will attempt to free the
// allocation from the wrong heap (because the current one has been
// replaced).

View File

@ -243,7 +243,7 @@ mod imp {
// EINVAL means |stack_size| is either too small or not a
// multiple of the system page size. Because it's definitely
// >= PTHREAD_STACK_MIN, it must be an alignment issue.
// Round up to the neareast page and try again.
// Round up to the nearest page and try again.
let page_size = libc::sysconf(libc::_SC_PAGESIZE) as uint;
let stack_size = (stack_size + page_size - 1) &
(-(page_size as int - 1) as uint - 1);

View File

@ -234,7 +234,7 @@ impl ForbidUnwind {
impl Drop for ForbidUnwind {
fn drop(&mut self) {
assert!(self.failing_before == task::failing(),
"didnt want an unwind during: {}", self.msg);
"didn't want an unwind during: {}", self.msg);
}
}

View File

@ -87,7 +87,7 @@ impl StreamWatcher {
// immediately as part of the call to alloc_cb. What this means is that
// we must be ready for this to happen (by setting the data in the uv
// handle). In theory this otherwise doesn't need to happen until after
// the read is succesfully started.
// the read is successfully started.
unsafe { uvll::set_data_for_uv_handle(self.handle, &mut rcx) }
// Send off the read request, but don't block until we're sure that the

View File

@ -77,7 +77,7 @@ impl RtioTimer for TimerWatcher {
fn sleep(&mut self, msecs: u64) {
// As with all of the below functions, we must be extra careful when
// destroying the previous action. If the previous action was a channel,
// destroying it could invoke a context switch. For these situtations,
// destroying it could invoke a context switch. For these situations,
// we must temporarily un-home ourselves, then destroy the action, and
// then re-home again.
let missile = self.fire_homing_missile();

View File

@ -410,7 +410,7 @@ mod test {
// colon after v4
let none: Option<IpAddr> = FromStr::from_str("::127.0.0.1:");
assert_eq!(None, none);
// not enought groups
// not enough groups
let none: Option<IpAddr> = FromStr::from_str("1.2.3.4.5:127.0.0.1");
assert_eq!(None, none);
// too many groups

View File

@ -165,7 +165,7 @@ impl UdpSocket {
/// Sets the broadcast flag on or off
#[experimental]
pub fn set_broadast(&mut self, broadcast: bool) -> IoResult<()> {
pub fn set_broadcast(&mut self, broadcast: bool) -> IoResult<()> {
if broadcast {
self.obj.hear_broadcasts()
} else {
@ -173,6 +173,12 @@ impl UdpSocket {
}.map_err(IoError::from_rtio_error)
}
/// Sets the broadcast flag on or off
#[deprecated="renamed to `set_broadcast`"]
pub fn set_broadast(&mut self, broadcast: bool) -> IoResult<()> {
self.set_broadcast(broadcast)
}
/// Sets the read/write timeout for this socket.
///
/// For more information, see `TcpStream::set_timeout`

View File

@ -45,7 +45,7 @@ use path::{Path, GenericPath, BytesContainer};
use ptr::RawPtr;
use ptr;
use result::{Err, Ok, Result};
use slice::{Vector, ImmutableVector, MutableVector};
use slice::{Vector, ImmutableVector, MutableVector, ImmutableEqVector};
use str::{Str, StrSlice, StrAllocating};
use str;
use string::String;
@ -398,9 +398,9 @@ pub fn getenv_as_bytes(n: &str) -> Option<Vec<u8>> {
/// None => println!("{} is not defined in the environment.", key)
/// }
/// ```
pub fn setenv(n: &str, v: &str) {
pub fn setenv<T: BytesContainer>(n: &str, v: T) {
#[cfg(unix)]
fn _setenv(n: &str, v: &str) {
fn _setenv(n: &str, v: &[u8]) {
unsafe {
with_env_lock(|| {
n.with_c_str(|nbuf| {
@ -413,18 +413,20 @@ pub fn setenv(n: &str, v: &str) {
}
#[cfg(windows)]
fn _setenv(n: &str, v: &str) {
fn _setenv(n: &str, v: &[u8]) {
let n: Vec<u16> = n.utf16_units().collect();
let n = n.append_one(0);
let v: Vec<u16> = v.utf16_units().collect();
let v: Vec<u16> = str::from_utf8(v).unwrap().utf16_units().collect();
let v = v.append_one(0);
unsafe {
with_env_lock(|| {
libc::SetEnvironmentVariableW(n.as_ptr(), v.as_ptr());
})
}
}
_setenv(n, v)
_setenv(n, v.container_as_bytes())
}
/// Remove a variable from the environment entirely.
@ -453,77 +455,130 @@ pub fn unsetenv(n: &str) {
_unsetenv(n);
}
#[cfg(unix)]
/// Parse a string or vector according to the platform's conventions
/// for the `PATH` environment variable and return a Vec<Path>.
/// Drops empty paths.
/// Parses input according to platform conventions for the `PATH`
/// environment variable.
///
/// # Example
/// ```rust
/// use std::os;
///
/// let key = "PATH";
/// match os::getenv(key) {
/// match os::getenv_as_bytes(key) {
/// Some(paths) => {
/// for path in os::split_paths(paths).iter() {
/// println!("'{}'", path.display());
/// }
/// }
/// None => println!("{} is not defined in the environnement.", key)
/// None => println!("{} is not defined in the environment.", key)
/// }
/// ```
pub fn split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
unparsed.container_as_bytes()
.split(|b| *b == ':' as u8)
.filter(|s| s.len() > 0)
.map(Path::new)
.collect()
}
#[cfg(unix)]
fn _split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
unparsed.container_as_bytes()
.split(|b| *b == b':')
.map(Path::new)
.collect()
}
#[cfg(windows)]
/// Parse a string or vector according to the platform's conventions
/// for the `PATH` environment variable. Drops empty paths.
pub fn split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
// On Windows, the PATH environment variable is semicolon separated. Double
// quotes are used as a way of introducing literal semicolons (since
// c:\some;dir is a valid Windows path). Double quotes are not themselves
// permitted in path names, so there is no way to escape a double quote.
// Quoted regions can appear in arbitrary locations, so
//
// c:\foo;c:\som"e;di"r;c:\bar
//
// Should parse as [c:\foo, c:\some;dir, c:\bar].
//
// (The above is based on testing; there is no clear reference available
// for the grammar.)
#[cfg(windows)]
fn _split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
// On Windows, the PATH environment variable is semicolon separated. Double
// quotes are used as a way of introducing literal semicolons (since
// c:\some;dir is a valid Windows path). Double quotes are not themselves
// permitted in path names, so there is no way to escape a double quote.
// Quoted regions can appear in arbitrary locations, so
//
// c:\foo;c:\som"e;di"r;c:\bar
//
// Should parse as [c:\foo, c:\some;dir, c:\bar].
//
// (The above is based on testing; there is no clear reference available
// for the grammar.)
let mut parsed = Vec::new();
let mut in_progress = Vec::new();
let mut in_quote = false;
let mut parsed = Vec::new();
let mut in_progress = Vec::new();
let mut in_quote = false;
for b in unparsed.container_as_bytes().iter() {
match *b as char {
';' if !in_quote => {
// ignore zero-length path strings
if in_progress.len() > 0 {
for b in unparsed.container_as_bytes().iter() {
match *b {
b';' if !in_quote => {
parsed.push(Path::new(in_progress.as_slice()));
in_progress.truncate(0)
}
b'"' => {
in_quote = !in_quote;
}
_ => {
in_progress.push(*b);
}
in_progress.truncate(0)
}
'\"' => {
in_quote = !in_quote;
}
_ => {
in_progress.push(*b);
}
}
}
if in_progress.len() > 0 {
parsed.push(Path::new(in_progress));
parsed
}
parsed
_split_paths(unparsed)
}
/// Joins a collection of `Path`s appropriately for the `PATH`
/// environment variable.
///
/// Returns a `Vec<u8>` on success, since `Path`s are not utf-8
/// encoded on all platforms.
///
/// Returns an `Err` (containing an error message) if one of the input
/// `Path`s contains an invalid character for constructing the `PATH`
/// variable (a double quote on Windows or a colon on Unix).
///
/// # Example
///
/// ```rust
/// use std::os;
/// use std::path::Path;
///
/// let key = "PATH";
/// let mut paths = os::getenv_as_bytes(key).map_or(Vec::new(), os::split_paths);
/// paths.push(Path::new("/home/xyz/bin"));
/// os::setenv(key, os::join_paths(paths.as_slice()).unwrap());
/// ```
pub fn join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
#[cfg(windows)]
fn _join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
let mut joined = Vec::new();
let sep = b';';
for (i, path) in paths.iter().map(|p| p.container_as_bytes()).enumerate() {
if i > 0 { joined.push(sep) }
if path.contains(&b'"') {
return Err("path segment contains `\"`");
} else if path.contains(&sep) {
joined.push(b'"');
joined.push_all(path);
joined.push(b'"');
} else {
joined.push_all(path);
}
}
Ok(joined)
}
#[cfg(unix)]
fn _join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
let mut joined = Vec::new();
let sep = b':';
for (i, path) in paths.iter().map(|p| p.container_as_bytes()).enumerate() {
if i > 0 { joined.push(sep) }
if path.contains(&sep) { return Err("path segment contains separator `:`") }
joined.push_all(path);
}
Ok(joined)
}
_join_paths(paths)
}
/// A low-level OS in-memory pipe.
@ -1767,7 +1822,7 @@ mod tests {
use c_str::ToCStr;
use option;
use os::{env, getcwd, getenv, make_absolute};
use os::{split_paths, setenv, unsetenv};
use os::{split_paths, join_paths, setenv, unsetenv};
use os;
use rand::Rng;
use rand;
@ -2032,11 +2087,11 @@ mod tests {
parsed.iter().map(|s| Path::new(*s)).collect()
}
assert!(check_parse("", []));
assert!(check_parse(r#""""#, []));
assert!(check_parse(";;", []));
assert!(check_parse("", [""]));
assert!(check_parse(r#""""#, [""]));
assert!(check_parse(";;", ["", "", ""]));
assert!(check_parse(r"c:\", [r"c:\"]));
assert!(check_parse(r"c:\;", [r"c:\"]));
assert!(check_parse(r"c:\;", [r"c:\", ""]));
assert!(check_parse(r"c:\;c:\Program Files\",
[r"c:\", r"c:\Program Files\"]));
assert!(check_parse(r#"c:\;c:\"foo"\"#, [r"c:\", r"c:\foo\"]));
@ -2052,12 +2107,44 @@ mod tests {
parsed.iter().map(|s| Path::new(*s)).collect()
}
assert!(check_parse("", []));
assert!(check_parse("::", []));
assert!(check_parse("", [""]));
assert!(check_parse("::", ["", "", ""]));
assert!(check_parse("/", ["/"]));
assert!(check_parse("/:", ["/"]));
assert!(check_parse("/:", ["/", ""]));
assert!(check_parse("/:/usr/local", ["/", "/usr/local"]));
}
#[test]
#[cfg(unix)]
fn join_paths_unix() {
fn test_eq(input: &[&str], output: &str) -> bool {
join_paths(input).unwrap().as_slice() == output.as_bytes()
}
assert!(test_eq([], ""));
assert!(test_eq(["/bin", "/usr/bin", "/usr/local/bin"],
"/bin:/usr/bin:/usr/local/bin"));
assert!(test_eq(["", "/bin", "", "", "/usr/bin", ""],
":/bin:::/usr/bin:"));
assert!(join_paths(["/te:st"]).is_err());
}
#[test]
#[cfg(windows)]
fn join_paths_windows() {
fn test_eq(input: &[&str], output: &str) -> bool {
join_paths(input).unwrap().as_slice() == output.as_bytes()
}
assert!(test_eq([], ""));
assert!(test_eq([r"c:\windows", r"c:\"],
r"c:\windows;c:\"));
assert!(test_eq(["", r"c:\windows", "", "", r"c:\", ""],
r";c:\windows;;;c:\;"));
assert!(test_eq([r"c:\te;st", r"c:\"],
r#""c:\te;st";c:\"#));
assert!(join_paths([r#"c:\te"st"#]).is_err());
}
// More recursive_mkdir tests are in extra::tempfile
}

View File

@ -266,7 +266,7 @@ mod imp {
}
// while it doesn't requires lock for work as everything is
// local, it still displays much nicier backtraces when a
// local, it still displays much nicer backtraces when a
// couple of tasks fail simultaneously
static mut LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
let _g = unsafe { LOCK.lock() };

View File

@ -354,7 +354,7 @@ impl<T: Send> Packet<T> {
}
// We woke ourselves up from select. Assert that the task should be
// trashed and returne that we don't have any data.
// trashed and returned that we don't have any data.
n => {
let t = unsafe { BlockedTask::cast_from_uint(n) };
t.trash();

View File

@ -81,7 +81,7 @@ impl<T: Send> Packet<T> {
// This function should be used after newly created Packet
// was wrapped with an Arc
// In other case mutex data will be duplicated while clonning
// In other case mutex data will be duplicated while cloning
// and that could cause problems on platforms where it is
// represented by opaque data structure
pub fn postinit_lock(&mut self) {
@ -140,7 +140,7 @@ impl<T: Send> Packet<T> {
// See Port::drop for what's going on
if self.port_dropped.load(atomics::SeqCst) { return Err(t) }
// Note that the multiple sender case is a little tricker
// Note that the multiple sender case is a little trickier
// semantically than the single sender case. The logic for
// incrementing is "add and if disconnected store disconnected".
// This could end up leading some senders to believe that there

View File

@ -215,7 +215,7 @@ impl StaticMutex {
None => {}
}
// After we've failed the fast path, then we delegate to the differnet
// After we've failed the fast path, then we delegate to the different
// locking protocols for green/native tasks. This will select two tasks
// to continue further (one native, one green).
let t: Box<Task> = Local::take();

View File

@ -293,8 +293,8 @@ pub enum Pat_ {
// In the nullary enum case, the parser can't determine
// which it is. The resolver determines this, and
// records this pattern's NodeId in an auxiliary
// set (of "pat_idents that refer to nullary enums")
PatIdent(BindingMode, Path, Option<Gc<Pat>>),
// set (of "PatIdents that refer to nullary enums")
PatIdent(BindingMode, SpannedIdent, Option<Gc<Pat>>),
PatEnum(Path, Option<Vec<Gc<Pat>>>), /* "none" means a * pattern where
* we don't bind the fields to names */
PatStruct(Path, Vec<FieldPat>, bool),
@ -818,7 +818,7 @@ pub struct Arg {
impl Arg {
pub fn new_self(span: Span, mutability: Mutability) -> Arg {
let path = ast_util::ident_to_path(span, special_idents::self_);
let path = Spanned{span:span,node:special_idents::self_};
Arg {
// HACK(eddyb) fake type for the self argument.
ty: P(Ty {

View File

@ -33,12 +33,6 @@ pub fn path_name_i(idents: &[Ident]) -> String {
}).collect::<Vec<String>>().connect("::")
}
// totally scary function: ignores all but the last element, should have
// a different name
pub fn path_to_ident(path: &Path) -> Ident {
path.segments.last().unwrap().identifier
}
pub fn local_def(id: NodeId) -> DefId {
ast::DefId { krate: LOCAL_CRATE, node: id }
}
@ -186,6 +180,8 @@ pub fn block_from_expr(e: Gc<Expr>) -> P<Block> {
})
}
// convert a span and an identifier to the corresponding
// 1-segment path
pub fn ident_to_path(s: Span, identifier: Ident) -> Path {
ast::Path {
span: s,
@ -202,7 +198,7 @@ pub fn ident_to_path(s: Span, identifier: Ident) -> Path {
pub fn ident_to_pat(id: NodeId, s: Span, i: Ident) -> Gc<Pat> {
box(GC) ast::Pat { id: id,
node: PatIdent(BindByValue(MutImmutable), ident_to_path(s, i), None),
node: PatIdent(BindByValue(MutImmutable), codemap::Spanned{span:s, node:i}, None),
span: s }
}

View File

@ -16,7 +16,6 @@ use ast;
use codemap::Span;
use ext::base;
use ext::base::*;
use parse;
use parse::token::InternedString;
use parse::token;
@ -48,12 +47,7 @@ static OPTIONS: &'static [&'static str] = &["volatile", "alignstack", "intel"];
pub fn expand_asm(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-> Box<base::MacResult> {
let mut p = parse::new_parser_from_tts(cx.parse_sess(),
cx.cfg(),
tts.iter()
.map(|x| (*x).clone())
.collect());
let mut p = cx.new_parser_from_tts(tts);
let mut asm = InternedString::new("");
let mut asm_str_style = None;
let mut outputs = Vec::new();

View File

@ -15,6 +15,7 @@ use codemap::{CodeMap, Span, ExpnInfo};
use ext;
use ext::expand;
use parse;
use parse::parser;
use parse::token;
use parse::token::{InternedString, intern, str_to_ident};
use util::small_vector::SmallVector;
@ -433,6 +434,11 @@ impl<'a> ExtCtxt<'a> {
}
}
pub fn new_parser_from_tts(&self, tts: &[ast::TokenTree])
-> parser::Parser<'a> {
parse::tts_to_parser(self.parse_sess, Vec::from_slice(tts), self.cfg())
}
pub fn codemap(&self) -> &'a CodeMap { &self.parse_sess.span_diagnostic.cm }
pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess }
pub fn cfg(&self) -> ast::CrateConfig { self.cfg.clone() }
@ -472,7 +478,7 @@ impl<'a> ExtCtxt<'a> {
}
/// Emit `msg` attached to `sp`, and stop compilation immediately.
///
/// `span_err` should be strongly prefered where-ever possible:
/// `span_err` should be strongly preferred where-ever possible:
/// this should *only* be used when
/// - continuing has a high risk of flow-on errors (e.g. errors in
/// declaring a macro would cause all uses of that macro to
@ -586,11 +592,7 @@ pub fn get_single_str_from_tts(cx: &ExtCtxt,
pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
sp: Span,
tts: &[ast::TokenTree]) -> Option<Vec<Gc<ast::Expr>>> {
let mut p = parse::new_parser_from_tts(cx.parse_sess(),
cx.cfg(),
tts.iter()
.map(|x| (*x).clone())
.collect());
let mut p = cx.new_parser_from_tts(tts);
let mut es = Vec::new();
while p.token != token::EOF {
es.push(cx.expand_expr(p.parse_expr()));

View File

@ -759,8 +759,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
span: Span,
ident: ast::Ident,
bm: ast::BindingMode) -> Gc<ast::Pat> {
let path = self.path_ident(span, ident);
let pat = ast::PatIdent(bm, path, None);
let pat = ast::PatIdent(bm, Spanned{span: span, node: ident}, None);
self.pat(span, pat)
}
fn pat_enum(&self, span: Span, path: ast::Path, subpats: Vec<Gc<ast::Pat>> ) -> Gc<ast::Pat> {

View File

@ -24,17 +24,11 @@ use attr::*;
use parse::attr::ParserAttr;
use parse::token::InternedString;
use parse::token;
use parse;
pub fn expand_cfg(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-> Box<base::MacResult> {
let mut p = parse::new_parser_from_tts(cx.parse_sess(),
cx.cfg(),
tts.iter()
.map(|x| (*x).clone())
.collect());
let mut p = cx.new_parser_from_tts(tts);
let mut cfgs = Vec::new();
// parse `cfg!(meta_item, meta_item(x,y), meta_item="foo", ...)`
while p.token != token::EOF {

View File

@ -834,7 +834,7 @@ impl<'a> MethodDef<'a> {
generic `deriving`");
}
// `ref` inside let matches is buggy. Causes havoc wih rusc.
// `ref` inside let matches is buggy. Causes havoc with rusc.
// let (variant_index, ref self_vec) = matches_so_far[0];
let (variant, self_vec) = match matches_so_far.get(0) {
&(_, v, ref s) => (v, s)
@ -1049,7 +1049,7 @@ impl<'a> TraitDef<'a> {
fn create_subpatterns(&self,
cx: &mut ExtCtxt,
field_paths: Vec<ast::Path> ,
field_paths: Vec<ast::SpannedIdent> ,
mutbl: ast::Mutability)
-> Vec<Gc<ast::Pat>> {
field_paths.iter().map(|path| {
@ -1095,15 +1095,10 @@ impl<'a> TraitDef<'a> {
cx.span_bug(sp, "a struct with named and unnamed fields in `deriving`");
}
};
let path =
cx.path_ident(sp,
cx.ident_of(format!("{}_{}",
prefix,
i).as_slice()));
paths.push(path.clone());
let ident = cx.ident_of(format!("{}_{}", prefix, i).as_slice());
paths.push(codemap::Spanned{span: sp, node: ident});
let val = cx.expr(
sp, ast::ExprParen(
cx.expr_deref(sp, cx.expr_path(path))));
sp, ast::ExprParen(cx.expr_deref(sp, cx.expr_path(cx.path_ident(sp,ident)))));
ident_expr.push((sp, opt_id, val));
}
@ -1145,15 +1140,11 @@ impl<'a> TraitDef<'a> {
let mut ident_expr = Vec::new();
for (i, va) in variant_args.iter().enumerate() {
let sp = self.set_expn_info(cx, va.ty.span);
let path =
cx.path_ident(sp,
cx.ident_of(format!("{}_{}",
prefix,
i).as_slice()));
paths.push(path.clone());
let val = cx.expr(
sp, ast::ExprParen(cx.expr_deref(sp, cx.expr_path(path))));
let ident = cx.ident_of(format!("{}_{}", prefix, i).as_slice());
let path1 = codemap::Spanned{span: sp, node: ident};
paths.push(path1);
let expr_path = cx.expr_path(cx.path_ident(sp, ident));
let val = cx.expr(sp, ast::ExprParen(cx.expr_deref(sp, expr_path)));
ident_expr.push((sp, None, val));
}

View File

@ -705,22 +705,10 @@ impl Visitor<()> for NameFinderContext {
// we found a pat_ident!
ast::Pat {
id: _,
node: ast::PatIdent(_, ref path, ref inner),
node: ast::PatIdent(_, ref path1, ref inner),
span: _
} => {
match path {
// a path of length one:
&ast::Path {
global: false,
span: _,
segments: ref segments
} if segments.len() == 1 => {
self.ident_accumulator.push(segments.get(0)
.identifier)
}
// I believe these must be enums...
_ => ()
}
self.ident_accumulator.push(path1.node);
// visit optional subpattern of pat_ident:
for subpat in inner.iter() {
self.visit_pat(&**subpat, ())
@ -1307,7 +1295,7 @@ mod test {
}
// create a really evil test case where a $x appears inside a binding of $x
// but *shouldnt* bind because it was inserted by a different macro....
// but *shouldn't* bind because it was inserted by a different macro....
// can't write this test case until we have macro-generating macros.
// FIXME #9383 : lambda var hygiene

View File

@ -16,7 +16,6 @@ use ext::base;
use ext::build::AstBuilder;
use parse::token::InternedString;
use parse::token;
use rsparse = parse;
use parse = fmt_macros;
use std::collections::HashMap;
@ -81,11 +80,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, allow_method: bool,
let mut names = HashMap::<String, Gc<ast::Expr>>::new();
let mut order = Vec::new();
let mut p = rsparse::new_parser_from_tts(ecx.parse_sess(),
ecx.cfg(),
tts.iter()
.map(|x| (*x).clone())
.collect());
let mut p = ecx.new_parser_from_tts(tts);
// Parse the leading function expression (maybe a block, maybe a path)
let invocation = if allow_method {
let e = p.parse_expr();

View File

@ -15,7 +15,6 @@ use ext::base;
use ext::build::AstBuilder;
use parse::token::*;
use parse::token;
use parse;
use std::gc::Gc;
@ -583,11 +582,7 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree])
// it has to do with transition away from supporting old-style macros, so
// try removing it when enough of them are gone.
let mut p = parse::new_parser_from_tts(cx.parse_sess(),
cx.cfg(),
tts.iter()
.map(|x| (*x).clone())
.collect());
let mut p = cx.new_parser_from_tts(tts);
p.quote_depth += 1u;
let cx_expr = p.parse_expr();

View File

@ -791,9 +791,10 @@ pub fn noop_fold_pat<T: Folder>(p: Gc<Pat>, folder: &mut T) -> Gc<Pat> {
let node = match p.node {
PatWild => PatWild,
PatWildMulti => PatWildMulti,
PatIdent(binding_mode, ref pth, ref sub) => {
PatIdent(binding_mode, ref pth1, ref sub) => {
PatIdent(binding_mode,
folder.fold_path(pth),
Spanned{span: folder.new_span(pth1.span),
node: folder.fold_ident(pth1.node)},
sub.map(|x| folder.fold_pat(x)))
}
PatLit(e) => PatLit(folder.fold_expr(e)),

View File

@ -594,23 +594,15 @@ mod test {
#[test] fn parse_ident_pat () {
let sess = new_parse_sess();
let mut parser = string_to_parser(&sess, "b".to_string());
assert!(parser.parse_pat() ==
box(GC) ast::Pat{id: ast::DUMMY_NODE_ID,
node: ast::PatIdent(
ast::BindByValue(ast::MutImmutable),
ast::Path {
span:sp(0,1),
global:false,
segments: vec!(
ast::PathSegment {
identifier: str_to_ident("b"),
lifetimes: Vec::new(),
types: OwnedSlice::empty(),
}
),
},
None /* no idea */),
span: sp(0,1)});
assert!(parser.parse_pat()
== box(GC) ast::Pat{
id: ast::DUMMY_NODE_ID,
node: ast::PatIdent(ast::BindByValue(ast::MutImmutable),
Spanned{ span:sp(0, 1),
node: str_to_ident("b")
},
None),
span: sp(0,1)});
parser_done(parser);
}
@ -643,24 +635,15 @@ mod test {
id: ast::DUMMY_NODE_ID,
node: ast::PatIdent(
ast::BindByValue(ast::MutImmutable),
ast::Path {
span:sp(6,7),
global:false,
segments: vec!(
ast::PathSegment {
identifier:
str_to_ident("b"),
lifetimes: Vec::new(),
types: OwnedSlice::empty(),
}
),
},
None // no idea
),
span: sp(6,7)
},
id: ast::DUMMY_NODE_ID
}),
Spanned{
span: sp(6,7),
node: str_to_ident("b")},
None
),
span: sp(6,7)
},
id: ast::DUMMY_NODE_ID
}),
output: ast::P(ast::Ty{id: ast::DUMMY_NODE_ID,
node: ast::TyNil,
span:sp(15,15)}), // not sure

View File

@ -58,7 +58,7 @@ use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse};
use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
use ast::Visibility;
use ast;
use ast_util::{as_prec, lit_is_str, operator_prec};
use ast_util::{as_prec, ident_to_path, lit_is_str, operator_prec};
use ast_util;
use codemap::{Span, BytePos, Spanned, spanned, mk_sp};
use codemap;
@ -2854,8 +2854,7 @@ impl<'a> Parser<'a> {
self.bump();
self.parse_pat()
} else {
let fieldpath = ast_util::ident_to_path(self.last_span,
fieldname);
let fieldpath = codemap::Spanned{span:self.last_span, node: fieldname};
box(GC) ast::Pat {
id: ast::DUMMY_NODE_ID,
node: PatIdent(bind_type, fieldpath, None),
@ -2961,6 +2960,7 @@ impl<'a> Parser<'a> {
}
_ => {}
}
// at this point, token != _, ~, &, &&, (, [
if (!is_ident_or_path(&self.token) && self.token != token::MOD_SEP)
|| self.is_keyword(keywords::True)
@ -3017,7 +3017,9 @@ impl<'a> Parser<'a> {
let end = self.parse_expr_res(RESTRICT_NO_BAR_OP);
pat = PatRange(start, end);
} else if is_plain_ident(&self.token) && !can_be_enum_or_struct {
let name = self.parse_path(NoTypesAllowed).path;
let id = self.parse_ident();
let id_span = self.last_span;
let pth1 = codemap::Spanned{span:id_span, node: id};
if self.eat(&token::NOT) {
// macro invocation
let ket = token::close_delimiter_for(&self.token)
@ -3028,7 +3030,7 @@ impl<'a> Parser<'a> {
seq_sep_none(),
|p| p.parse_token_tree());
let mac = MacInvocTT(name, tts, EMPTY_CTXT);
let mac = MacInvocTT(ident_to_path(id_span,id), tts, EMPTY_CTXT);
pat = ast::PatMac(codemap::Spanned {node: mac, span: self.span});
} else {
let sub = if self.eat(&token::AT) {
@ -3038,7 +3040,7 @@ impl<'a> Parser<'a> {
// or just foo
None
};
pat = PatIdent(BindByValue(MutImmutable), name, sub);
pat = PatIdent(BindByValue(MutImmutable), pth1, sub);
}
} else {
// parse an enum pat
@ -3084,8 +3086,11 @@ impl<'a> Parser<'a> {
// or an identifier pattern, resolve
// will sort it out:
pat = PatIdent(BindByValue(MutImmutable),
enum_path,
None);
codemap::Spanned{
span: enum_path.span,
node: enum_path.segments.get(0)
.identifier},
None);
} else {
pat = PatEnum(enum_path, Some(args));
}
@ -3115,7 +3120,7 @@ impl<'a> Parser<'a> {
"expected identifier, found path");
}
// why a path here, and not just an identifier?
let name = self.parse_path(NoTypesAllowed).path;
let name = codemap::Spanned{span: self.last_span, node: self.parse_ident()};
let sub = if self.eat(&token::AT) {
Some(self.parse_pat())
} else {
@ -3243,7 +3248,7 @@ impl<'a> Parser<'a> {
None => {
// we only expect an ident if we didn't parse one
// above.
let ident_str = if id == token::special_idents::invalid {
let ident_str = if id.name == token::special_idents::invalid.name {
"identifier, "
} else {
""
@ -3263,7 +3268,7 @@ impl<'a> Parser<'a> {
);
let hi = self.span.hi;
if id == token::special_idents::invalid {
if id.name == token::special_idents::invalid.name {
return box(GC) spanned(lo, hi, StmtMac(
spanned(lo, hi, MacInvocTT(pth, tts, EMPTY_CTXT)), false));
} else {

View File

@ -196,6 +196,10 @@ pub fn path_to_str(p: &ast::Path) -> String {
to_str(|s| s.print_path(p, false))
}
pub fn ident_to_str(id: &ast::Ident) -> String {
to_str(|s| s.print_ident(*id))
}
pub fn fun_to_str(decl: &ast::FnDecl, fn_style: ast::FnStyle, name: ast::Ident,
opt_explicit_self: Option<ast::ExplicitSelf_>,
generics: &ast::Generics) -> String {
@ -1705,7 +1709,7 @@ impl<'a> State<'a> {
match pat.node {
ast::PatWild => try!(word(&mut self.s, "_")),
ast::PatWildMulti => try!(word(&mut self.s, "..")),
ast::PatIdent(binding_mode, ref path, sub) => {
ast::PatIdent(binding_mode, ref path1, sub) => {
match binding_mode {
ast::BindByRef(mutbl) => {
try!(self.word_nbsp("ref"));
@ -1716,7 +1720,7 @@ impl<'a> State<'a> {
try!(self.word_nbsp("mut"));
}
}
try!(self.print_path(path, true));
try!(self.print_ident(path1.node));
match sub {
Some(ref p) => {
try!(word(&mut self.s, "@"));
@ -2148,9 +2152,8 @@ impl<'a> State<'a> {
ast::TyInfer => try!(self.print_pat(&*input.pat)),
_ => {
match input.pat.node {
ast::PatIdent(_, ref path, _) if
path.segments.len() == 1 &&
path.segments.get(0).identifier.name ==
ast::PatIdent(_, ref path1, _) if
path1.node.name ==
parse::token::special_idents::invalid.name => {
// Do nothing.
}

View File

@ -454,8 +454,8 @@ pub fn walk_pat<E: Clone, V: Visitor<E>>(visitor: &mut V, pattern: &Pat, env: E)
PatRegion(ref subpattern) => {
visitor.visit_pat(&**subpattern, env)
}
PatIdent(_, ref path, ref optional_subpattern) => {
visitor.visit_path(path, pattern.id, env.clone());
PatIdent(_, ref pth1, ref optional_subpattern) => {
visitor.visit_ident(pth1.span, pth1.node, env.clone());
match *optional_subpattern {
None => {}
Some(ref subpattern) => visitor.visit_pat(&**subpattern, env),

View File

@ -330,7 +330,7 @@ impl Tm {
* Returns a time string formatted according to RFC 822.
*
* local: "Thu, 22 Mar 2012 07:53:18 PST"
* utc: "Thu, 22 Mar 2012 14:53:18 UTC"
* utc: "Thu, 22 Mar 2012 14:53:18 GMT"
*/
pub fn rfc822(&self) -> String {
if self.tm_gmtoff == 0_i32 {
@ -351,7 +351,8 @@ impl Tm {
}
/**
* Returns a time string formatted according to ISO 8601.
* Returns a time string formatted according to RFC 3999. RFC 3999 is
* compatible with ISO 8601.
*
* local: "2012-02-22T07:53:18-07:00"
* utc: "2012-02-22T14:53:18Z"

View File

@ -0,0 +1,34 @@
// 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.
// We only want to assert that this doesn't ICE, we don't particularly care
// about whether it nor it fails to compile.
// error-pattern:
#![feature(macro_rules)]
macro_rules! foo{
() => {{
macro_rules! bar{() => (())}
1
}}
}
pub fn main() {
foo!();
assert!({one! two()});
// regardless of whether nested macro_rules works, the following should at
// least throw a conventional error.
assert!({one! two});
}

View File

@ -0,0 +1,39 @@
// Copyright 2012 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.
// Issue #14061: tests the interaction between generic implementation
// parameter bounds and trait objects.
struct S<T>;
trait Gettable<T> {}
impl<T: Send + Copy> Gettable<T> for S<T> {}
fn f<T>(val: T) {
let t: S<T> = S;
let a = &t as &Gettable<T>;
//~^ ERROR instantiating a type parameter with an incompatible type `T`
let a: &Gettable<T> = &t;
//~^ ERROR instantiating a type parameter with an incompatible type `T`
}
fn main() {
let t: S<&int> = S;
let a = &t as &Gettable<&int>;
//~^ ERROR instantiating a type parameter with an incompatible type `&int`
let t: Box<S<String>> = box S;
let a = t as Box<Gettable<String>>;
//~^ ERROR instantiating a type parameter with an incompatible type
let t: Box<S<String>> = box S;
let a: Box<Gettable<String>> = t;
//~^ ERROR instantiating a type parameter with an incompatible type
}