diff --git a/src/doc/guide.md b/src/doc/guide.md index 0fc9671c4db29..aca726812d2c6 100644 --- a/src/doc/guide.md +++ b/src/doc/guide.md @@ -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 diff --git a/src/doc/tutorial.md b/src/doc/tutorial.md index 5fe6a5f14c2b4..2a788d7e7934c 100644 --- a/src/doc/tutorial.md +++ b/src/doc/tutorial.md @@ -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; } diff --git a/src/etc/install.sh b/src/etc/install.sh index fd4c20d73c5d1..2ed7a9dd6c28a 100644 --- a/src/etc/install.sh +++ b/src/etc/install.sh @@ -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="$@" diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 38ed511c4589a..9b4f879e61ea4 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -185,7 +185,7 @@ impl Drop for Arc { // 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], diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index fd8ce11d0b5a4..ddba4b34e3a2a 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -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); diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 2ffc168f82c0e..d53ecabd5a9cb 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -253,8 +253,7 @@ impl Vec { /// 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 Vec { /// 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)) } } diff --git a/src/libfourcc/lib.rs b/src/libfourcc/lib.rs index a5880f3247242..848509cbab278 100644 --- a/src/libfourcc/lib.rs +++ b/src/libfourcc/lib.rs @@ -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, Option) { - 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 diff --git a/src/libgreen/stack.rs b/src/libgreen/stack.rs index c4885edb7d3a7..5faa9cfe6f6a2 100644 --- a/src/libgreen/stack.rs +++ b/src/libgreen/stack.rs @@ -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, } diff --git a/src/libhexfloat/lib.rs b/src/libhexfloat/lib.rs index 1b43f236e69b5..369de484e8e84 100644 --- a/src/libhexfloat/lib.rs +++ b/src/libhexfloat/lib.rs @@ -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, Option) { - 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 diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index ba102a85c1bcb..17349f41b98f7 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -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. diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs index dfc2c55cde7cb..f052826d30386 100644 --- a/src/libnative/io/net.rs +++ b/src/libnative/io/net.rs @@ -877,7 +877,7 @@ pub fn write(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; diff --git a/src/libnative/io/pipe_win32.rs b/src/libnative/io/pipe_win32.rs index da713e3f2a931..e5e8cdeffd7e4 100644 --- a/src/libnative/io/pipe_win32.rs +++ b/src/libnative/io/pipe_win32.rs @@ -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()) } diff --git a/src/libnum/rational.rs b/src/libnum/rational.rs index 9a455edf2c086..c35b2976b407f 100644 --- a/src/libnum/rational.rs +++ b/src/libnum/rational.rs @@ -274,12 +274,17 @@ impl Num for Ratio {} /* String conversions */ -impl fmt::Show for Ratio { - /// Renders as `numer/denom`. +impl fmt::Show for Ratio { + /// Renders as `numer/denom`. If denom=1, renders as numer. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}/{}", self.numer, self.denom) + if self.denom == One::one() { + write!(f, "{}", self.numer) + } else { + write!(f, "{}/{}", self.numer, self.denom) + } } } + impl ToStrRadix for Ratio { /// Renders as `numer/denom` where the numbers are in base `radix`. fn to_str_radix(&self, radix: uint) -> String { @@ -291,21 +296,20 @@ impl ToStrRadix for Ratio { impl FromStr for Ratio { - /// Parses `numer/denom`. + /// Parses `numer/denom` or just `numer` fn from_str(s: &str) -> Option> { - let split: Vec<&str> = s.splitn('/', 1).collect(); - if split.len() < 2 { - return None + let mut split = s.splitn('/', 1); + + let num = split.next().and_then(|n| FromStr::from_str(n)); + let den = split.next().or(Some("1")).and_then(|d| FromStr::from_str(d)); + + match (num, den) { + (Some(n), Some(d)) => Some(Ratio::new(n, d)), + _ => None } - let a_option: Option = FromStr::from_str(*split.get(0)); - a_option.and_then(|a| { - let b_option: Option = FromStr::from_str(*split.get(1)); - b_option.and_then(|b| { - Some(Ratio::new(a.clone(), b.clone())) - }) - }) } } + impl FromStrRadix for Ratio { /// Parses `numer/denom` where the numbers are in base `radix`. @@ -429,6 +433,13 @@ mod test { assert!(!_neg1_2.is_integer()); } + #[test] + fn test_show() { + assert_eq!(format!("{}", _2), "2".to_string()); + assert_eq!(format!("{}", _1_2), "1/2".to_string()); + assert_eq!(format!("{}", _0), "0".to_string()); + assert_eq!(format!("{}", Ratio::from_integer(-2i)), "-2".to_string()); + } mod arith { use super::{_0, _1, _2, _1_2, _3_2, _neg1_2, to_big}; @@ -562,11 +573,11 @@ mod test { assert_eq!(FromStr::from_str(s.as_slice()), Some(r)); assert_eq!(r.to_str(), s); } - test(_1, "1/1".to_string()); - test(_0, "0/1".to_string()); + test(_1, "1".to_string()); + test(_0, "0".to_string()); test(_1_2, "1/2".to_string()); test(_3_2, "3/2".to_string()); - test(_2, "2/1".to_string()); + test(_2, "2".to_string()); test(_neg1_2, "-1/2".to_string()); } #[test] diff --git a/src/libregex_macros/lib.rs b/src/libregex_macros/lib.rs index ff5cada05ea2e..4108388e77669 100644 --- a/src/libregex_macros/lib.rs +++ b/src/libregex_macros/lib.rs @@ -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 { - 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) => { diff --git a/src/librlibc/lib.rs b/src/librlibc/lib.rs index c85e0099ab832..4423ab62f0dcf 100644 --- a/src/librlibc/lib.rs +++ b/src/librlibc/lib.rs @@ -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] diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 17f29639601dd..a190d9309cc8d 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -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 { diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 30296cb318617..a8f778934ae47 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -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); }); diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 96284f8de261a..6eb7c5a4310e6 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -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); } _ => {} } diff --git a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs index 6df474809779a..de77fa602c9b4 100644 --- a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs @@ -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, }; diff --git a/src/librustc/middle/borrowck/gather_loans/move_error.rs b/src/librustc/middle/borrowck/gather_loans/move_error.rs index 925244849bc8a..f5c91f7b1b3bf 100644 --- a/src/librustc/middle/borrowck/gather_loans/move_error.rs +++ b/src/librustc/middle/borrowck/gather_loans/move_error.rs @@ -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) { 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, diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index e7457f370d9ad..70db3e964abb3 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -247,6 +247,10 @@ impl<'a> Visitor 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) + } _ => () } diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index 34754f045ffce..a7154e78bc586 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -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 }; diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 5c09466cd9682..d48f7f541f0da 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -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); } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index e1a2a5741fbe1..54cca082e0de8 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -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)) diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs index 24d97f5aac354..2d53d742ee44b 100644 --- a/src/librustc/middle/pat_util.rs +++ b/src/librustc/middle/pat_util.rs @@ -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; @@ -23,8 +23,8 @@ pub type PatIdMap = HashMap; // 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 diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 414aac47cdcc0..76e962a3bc4da 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -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; diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index d42befc65421b..b7b4618a79046 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -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 diff --git a/src/librustc/middle/save/mod.rs b/src/librustc/middle/save/mod.rs index 2b2f3b8fb0b5f..bdb7d30339d66 100644 --- a/src/librustc/middle/save/mod.rs +++ b/src/librustc/middle/save/mod.rs @@ -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(""), 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); diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 595203fdefb2d..55939e6ea7a9f 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -231,8 +231,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; @@ -435,13 +433,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, @@ -479,9 +477,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)); } } _ => {} @@ -1431,8 +1429,8 @@ fn create_bindings_map(bcx: &Block, pat: Gc) -> 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); @@ -1586,10 +1584,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))); } @@ -1621,10 +1619,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 @@ -1652,7 +1650,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); @@ -1667,7 +1665,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)) } } @@ -1685,17 +1683,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. @@ -1753,13 +1750,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(_) => { diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index f401989800376..afa0b3041550e 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -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() @@ -990,7 +990,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 => { @@ -1005,8 +1005,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(); @@ -1015,7 +1013,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 }, @@ -3220,10 +3218,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) }); }) } @@ -3331,13 +3328,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 diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 79630be7c5e08..9629fb38af80f 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -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( diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index 60ce9508dc46b..697c5d367ee5a 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -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); diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index f5e34e9307764..b68991aed7096 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -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))); } diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 33e0d0331be6c..bda47d99ed714 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -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, diff --git a/src/librustc/middle/typeck/infer/unify.rs b/src/librustc/middle/typeck/infer/unify.rs index f106ce18a4adb..44afc04d3f0ef 100644 --- a/src/librustc/middle/typeck/infer/unify.rs +++ b/src/librustc/middle/typeck/infer/unify.rs @@ -93,7 +93,7 @@ pub struct UnificationTable { /** * 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 { // Ensure that this snapshot is keyed to the table type. @@ -152,7 +152,7 @@ impl> UnificationTable { /** * 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 { let length = self.undo_log.len(); @@ -188,12 +188,12 @@ impl> UnificationTable { 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) => { diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index e159d0d00c82c..7b6935df42079 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -216,9 +216,9 @@ pub type vtable_res = VecPerParamSpace; #[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), diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 87151708812e5..d0873d4c66afc 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1583,8 +1583,6 @@ impl Clean 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> for ast::ViewItem { fn clean(&self) -> Vec { - // 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"), diff --git a/src/librustrt/c_str.rs b/src/librustrt/c_str.rs index 9734ba2d7518e..161d3ed5e65e1 100644 --- a/src/librustrt/c_str.rs +++ b/src/librustrt/c_str.rs @@ -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 { diff --git a/src/librustrt/libunwind.rs b/src/librustrt/libunwind.rs index 6811a62c74f52..f018b3fc16b3b 100644 --- a/src/librustrt/libunwind.rs +++ b/src/librustrt/libunwind.rs @@ -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; diff --git a/src/librustrt/task.rs b/src/librustrt/task.rs index 891d0d5a8e359..59401a8b66604 100644 --- a/src/librustrt/task.rs +++ b/src/librustrt/task.rs @@ -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). diff --git a/src/librustrt/thread.rs b/src/librustrt/thread.rs index 9908e87e86a47..59784328cdb50 100644 --- a/src/librustrt/thread.rs +++ b/src/librustrt/thread.rs @@ -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); diff --git a/src/librustuv/lib.rs b/src/librustuv/lib.rs index 968a283995bef..a1712394634b8 100644 --- a/src/librustuv/lib.rs +++ b/src/librustuv/lib.rs @@ -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); } } diff --git a/src/librustuv/stream.rs b/src/librustuv/stream.rs index f6b9226588ca3..875c2dee46b4f 100644 --- a/src/librustuv/stream.rs +++ b/src/librustuv/stream.rs @@ -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 diff --git a/src/librustuv/timer.rs b/src/librustuv/timer.rs index 9d0a56b3c851d..f6c1cdd297754 100644 --- a/src/librustuv/timer.rs +++ b/src/librustuv/timer.rs @@ -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(); diff --git a/src/libstd/io/net/ip.rs b/src/libstd/io/net/ip.rs index 2c54bd895e952..ca59849202b08 100644 --- a/src/libstd/io/net/ip.rs +++ b/src/libstd/io/net/ip.rs @@ -410,7 +410,7 @@ mod test { // colon after v4 let none: Option = FromStr::from_str("::127.0.0.1:"); assert_eq!(None, none); - // not enought groups + // not enough groups let none: Option = FromStr::from_str("1.2.3.4.5:127.0.0.1"); assert_eq!(None, none); // too many groups diff --git a/src/libstd/io/net/udp.rs b/src/libstd/io/net/udp.rs index cd78898d46bb8..21903eb26439c 100644 --- a/src/libstd/io/net/udp.rs +++ b/src/libstd/io/net/udp.rs @@ -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` diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 6674dd532aeb0..b3f25914c8f56 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -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> { /// None => println!("{} is not defined in the environment.", key) /// } /// ``` -pub fn setenv(n: &str, v: &str) { +pub fn setenv(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 = n.utf16_units().collect(); let n = n.append_one(0); - let v: Vec = v.utf16_units().collect(); + let v: Vec = 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. -/// 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(unparsed: T) -> Vec { - unparsed.container_as_bytes() - .split(|b| *b == ':' as u8) - .filter(|s| s.len() > 0) - .map(Path::new) - .collect() -} + #[cfg(unix)] + fn _split_paths(unparsed: T) -> Vec { + 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(unparsed: T) -> Vec { - // 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(unparsed: T) -> Vec { + // 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` 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(paths: &[T]) -> Result, &'static str> { + #[cfg(windows)] + fn _join_paths(paths: &[T]) -> Result, &'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(paths: &[T]) -> Result, &'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. @@ -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 } diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs index 8f51e834c6a02..2e0dcdd8eb69f 100644 --- a/src/libstd/rt/backtrace.rs +++ b/src/libstd/rt/backtrace.rs @@ -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() }; diff --git a/src/libsync/comm/oneshot.rs b/src/libsync/comm/oneshot.rs index bf2d9aa52fd24..742686069e283 100644 --- a/src/libsync/comm/oneshot.rs +++ b/src/libsync/comm/oneshot.rs @@ -354,7 +354,7 @@ impl Packet { } // 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(); diff --git a/src/libsync/comm/shared.rs b/src/libsync/comm/shared.rs index a50a6bbc8d31f..5ad4dea5d2a89 100644 --- a/src/libsync/comm/shared.rs +++ b/src/libsync/comm/shared.rs @@ -81,7 +81,7 @@ impl Packet { // 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 Packet { // 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 diff --git a/src/libsync/mutex.rs b/src/libsync/mutex.rs index ef558d3f9241b..a10ec7458690a 100644 --- a/src/libsync/mutex.rs +++ b/src/libsync/mutex.rs @@ -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 = Local::take(); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 529b460adcd34..237d0660a41dc 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -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>), + // set (of "PatIdents that refer to nullary enums") + PatIdent(BindingMode, SpannedIdent, Option>), PatEnum(Path, Option>>), /* "none" means a * pattern where * we don't bind the fields to names */ PatStruct(Path, Vec, 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 { diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 2a6f7bdb87e35..036d6b4b43adc 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -33,12 +33,6 @@ pub fn path_name_i(idents: &[Ident]) -> String { }).collect::>().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) -> P { }) } +// 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 { 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 } } diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs index 50b1639484d94..f0494e1812013 100644 --- a/src/libsyntax/ext/asm.rs +++ b/src/libsyntax/ext/asm.rs @@ -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 { - 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(); diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 0d8373eac3c7f..d2e69204d333c 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -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>> { - 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())); diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 8d48401f9c2a4..46bc4ec11ce4f 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -759,8 +759,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { span: Span, ident: ast::Ident, bm: ast::BindingMode) -> Gc { - 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 { diff --git a/src/libsyntax/ext/cfg.rs b/src/libsyntax/ext/cfg.rs index 3e74b2680e060..c2930662bc459 100644 --- a/src/libsyntax/ext/cfg.rs +++ b/src/libsyntax/ext/cfg.rs @@ -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 { - 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 { diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 2b97687dbf8c9..157b64fb47c0a 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -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 , + field_paths: Vec , mutbl: ast::Mutability) -> Vec> { 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)); } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index b9cedb7a7797a..c3413293e52ae 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -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 diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index 857eadfe57cc4..f39e50ad1313f 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -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::>::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(); diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 35702b1b3cd46..7b24b97d5da4d 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -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(); diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index c6177ce31f5f8..f9d7078da3dcb 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -791,9 +791,10 @@ pub fn noop_fold_pat(p: Gc, folder: &mut T) -> Gc { 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)), diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 331a49c83beac..4b5252bfba311 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -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 diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 0fd5a7086b78c..f3789e25bc8a7 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -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 { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index a9cf4fbd9f0f1..4660bb337ab23 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -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, 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. } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 6f0fc217533fc..4ab064a88b795 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -454,8 +454,8 @@ pub fn walk_pat>(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), diff --git a/src/libtime/lib.rs b/src/libtime/lib.rs index f52a032961dd9..98544a1218aad 100644 --- a/src/libtime/lib.rs +++ b/src/libtime/lib.rs @@ -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" diff --git a/src/test/compile-fail/issue-10536.rs b/src/test/compile-fail/issue-10536.rs new file mode 100644 index 0000000000000..36afc729de959 --- /dev/null +++ b/src/test/compile-fail/issue-10536.rs @@ -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 or the MIT license +// , 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}); +} + diff --git a/src/test/compile-fail/kindck-impl-type-params.rs b/src/test/compile-fail/kindck-impl-type-params.rs new file mode 100644 index 0000000000000..48e1bdd671a11 --- /dev/null +++ b/src/test/compile-fail/kindck-impl-type-params.rs @@ -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 or the MIT license +// , 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; + +trait Gettable {} + +impl Gettable for S {} + +fn f(val: T) { + let t: S = S; + let a = &t as &Gettable; + //~^ ERROR instantiating a type parameter with an incompatible type `T` + let a: &Gettable = &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> = box S; + let a = t as Box>; + //~^ ERROR instantiating a type parameter with an incompatible type + let t: Box> = box S; + let a: Box> = t; + //~^ ERROR instantiating a type parameter with an incompatible type +} +