```
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;
## 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
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.
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
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; }
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="$@"
// 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],
/// 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;
}
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);
/// 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 {
/// 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))
}
}
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;
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
}
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>,
}
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;
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
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.
}
// 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;
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())
}
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;
/// 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) => {
#![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]
// 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 {
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())
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");
}
_ => {}
}
- /// 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 {
// 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); });
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());
}
_ => {}
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);
}
_ => {}
}
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,
};
#[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 {
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;
}
}
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,
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)
+ }
_ => ()
}
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;
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;
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);
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(..) => {}
}
}
-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);
+ }
+ _ => {}
}
- _ => {}
- },
+ }
_ => {}
}
}
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
};
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));
})
};
}
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,
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,
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);
}
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))
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>;
// 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
}
/// `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) => {
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
// 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;
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;
// 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);
// 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});
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
// 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) {
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, _) => {
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
{
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),
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)
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
}
};
// 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),
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);
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;
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,
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));
}
}
_ => {}
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();
// 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)));
}
// 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
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);
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))
}
}
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.
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(_) => {
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,
}
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()
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 => {
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();
};
declare_local(bcx,
- argument_ident,
+ path1.node,
llarg.ty,
scope_metadata,
DirectVariable { alloca: llarg.val },
// 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) });
})
}
// 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
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(
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 {
}
}
- 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);
_ => ()
}
}
- 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);
// 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)));
}
// 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,
/**
* 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.
/**
* 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();
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) => {
#[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),
}
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)) {
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| {
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"),
// (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 {
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;
/// 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`
// 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).
// 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);
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);
}
}
// 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
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();
// 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
/// 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 {
}.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`
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;
/// 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| {
}
#[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.
_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.)
-
- 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 {
+ #[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;
+
+ 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);
+ }
+ parsed.push(Path::new(in_progress));
+ 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)
}
- if in_progress.len() > 0 {
- parsed.push(Path::new(in_progress));
+ #[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)
}
- parsed
+ _join_paths(paths)
}
/// A low-level OS in-memory pipe.
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;
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\"]));
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
}
}
// 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() };
}
// 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();
// 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) {
// 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
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();
// 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),
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 {
}).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 }
}
})
}
+// 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,
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 }
}
use codemap::Span;
use ext::base;
use ext::base::*;
-use parse;
use parse::token::InternedString;
use parse::token;
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();
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;
}
}
+ 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() }
}
/// 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
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()));
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> {
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 {
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)
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| {
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));
}
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));
}
// 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, ())
}
// 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
use ext::build::AstBuilder;
use parse::token::InternedString;
use parse::token;
-use rsparse = parse;
use parse = fmt_macros;
use std::collections::HashMap;
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();
use ext::build::AstBuilder;
use parse::token::*;
use parse::token;
-use parse;
use std::gc::Gc;
// 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();
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)),
#[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);
}
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
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;
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),
}
_ => {}
}
+ // at this point, token != _, ~, &, &&, (, [
if (!is_ident_or_path(&self.token) && self.token != token::MOD_SEP)
|| self.is_keyword(keywords::True)
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)
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) {
// or just foo
None
};
- pat = PatIdent(BindByValue(MutImmutable), name, sub);
+ pat = PatIdent(BindByValue(MutImmutable), pth1, sub);
}
} else {
// parse an enum pat
// 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));
}
"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 {
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 {
""
);
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 {
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 {
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"));
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, "@"));
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.
}
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),
* 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 {
}
/**
- * 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"
--- /dev/null
+// 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});
+}
+
--- /dev/null
+// 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
+}
+