From 748b9477f8b0c0fdbb3a45a83bf6f26b5b6c3378 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Mon, 30 Jun 2014 12:17:52 -0400 Subject: [PATCH 01/18] Guide: if --- src/doc/guide.md | 147 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) diff --git a/src/doc/guide.md b/src/doc/guide.md index 0fc9671c4db..024bb8ce89b 100644 --- a/src/doc/guide.md +++ b/src/doc/guide.md @@ -611,6 +611,153 @@ 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 return From 8877b81f2cccfbbd6720e9ef81a8238fd188a63e Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Mon, 30 Jun 2014 10:19:02 -0700 Subject: [PATCH 02/18] Add os::join_paths, make setenv non-utf8 capable This commit changes `os` in three ways: * It adds a `join_paths` function that is the converse to `split_paths`, easing manipulation of the `PATH` environment variable according to platform conventions. * **Breaking change**: It changes `split_paths` to no longer drop empty paths, since they are meaningful to some shells (where they are synonymous with the current working directory). * It changes `setenv` to take a `BytesContainer` rather than a `&str` value, since environment variables may have non-utf8 values on some platforms. Since `&str` is a `BytesContainer`, this is *not* a breaking change. Along the way, it also refactors the `split_paths` function so that `cfg` switches are applied internally (and the function header is given only once). This fixes a bug: the doc comment had an example for only one platform. [breaking-change] --- src/libstd/os.rs | 207 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 147 insertions(+), 60 deletions(-) diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 6674dd532ae..c69209acbdd 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,17 +455,15 @@ 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()); @@ -473,57 +473,112 @@ pub fn unsetenv(n: &str) { /// } /// ``` 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.) + #[cfg(windows)] + 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; + let mut parsed = Vec::new(); + let mut in_progress = Vec::new(); + let mut in_quote = false; - for b in unparsed.container_as_bytes().iter() { - match *b as char { - ';' if !in_quote => { - // ignore zero-length path strings - if in_progress.len() > 0 { + for b in unparsed.container_as_bytes().iter() { + match *b { + b';' if !in_quote => { parsed.push(Path::new(in_progress.as_slice())); + in_progress.truncate(0) + } + b'"' => { + in_quote = !in_quote; + } + _ => { + in_progress.push(*b); } - in_progress.truncate(0) - } - '\"' => { - in_quote = !in_quote; - } - _ => { - in_progress.push(*b); } } - } - - if in_progress.len() > 0 { parsed.push(Path::new(in_progress)); + parsed } - parsed + _split_paths(unparsed) +} + +/// Joins a collection of `Path`s appropriately for the `PATH` +/// environment variable. +/// +/// Returns a `Vec` 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) + } + + #[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) + } + + _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 } From faf5d926ec21efb04d308fc71214e0afa55649d9 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Tue, 1 Jul 2014 18:05:50 -0400 Subject: [PATCH 03/18] Guide: functions Just a few words about functions and defining them. --- src/doc/guide.md | 146 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) diff --git a/src/doc/guide.md b/src/doc/guide.md index 024bb8ce89b..7ecfe7ce578 100644 --- a/src/doc/guide.md +++ b/src/doc/guide.md @@ -760,6 +760,152 @@ 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 From cff79ab5633f0900eb71a53ccb924632f7b1090c Mon Sep 17 00:00:00 2001 From: Paolo Falabella Date: Wed, 2 Jul 2014 16:39:43 +0100 Subject: [PATCH 04/18] Rationals that have a 1 denom should print like ints --- src/libnum/rational.rs | 45 ++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/src/libnum/rational.rs b/src/libnum/rational.rs index 9a455edf2c0..c35b2976b40 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] From e38cb972dcfc0fdab44270257eac3405a39bd996 Mon Sep 17 00:00:00 2001 From: John Clements Date: Mon, 30 Jun 2014 18:02:14 -0700 Subject: [PATCH 05/18] Simplify PatIdent to contain an Ident rather than a Path Rationale: for what appear to be historical reasons only, the PatIdent contains a Path rather than an Ident. This means that there are many places in the code where an ident is artificially promoted to a path, and---much more problematically--- a bunch of elements from a path are simply thrown away, which seems like an invitation to some really nasty bugs. This commit replaces the Path in a PatIdent with a SpannedIdent, which just contains an ident and a span. --- src/librustc/lint/builtin.rs | 25 +++---- src/librustc/metadata/encoder.rs | 8 +-- .../borrowck/gather_loans/gather_moves.rs | 6 +- .../borrowck/gather_loans/move_error.rs | 21 ++---- src/librustc/middle/dead.rs | 4 ++ src/librustc/middle/kind.rs | 4 +- src/librustc/middle/liveness.rs | 16 ++--- src/librustc/middle/pat_util.rs | 14 ++-- src/librustc/middle/resolve.rs | 65 +++---------------- src/librustc/middle/save/mod.rs | 5 +- src/librustc/middle/trans/_match.rs | 35 +++++----- src/librustc/middle/trans/debuginfo.rs | 23 +++---- src/librustc/middle/ty.rs | 4 +- src/librustc/middle/typeck/check/_match.rs | 10 +-- src/librustc/middle/typeck/check/mod.rs | 4 +- src/librustdoc/clean/mod.rs | 4 +- src/libsyntax/ast.rs | 6 +- src/libsyntax/ast_util.rs | 10 +-- src/libsyntax/ext/build.rs | 3 +- src/libsyntax/ext/deriving/generic/mod.rs | 27 +++----- src/libsyntax/ext/expand.rs | 16 +---- src/libsyntax/fold.rs | 5 +- src/libsyntax/parse/mod.rs | 53 +++++---------- src/libsyntax/parse/parser.rs | 23 ++++--- src/libsyntax/print/pprust.rs | 13 ++-- src/libsyntax/visit.rs | 4 +- 26 files changed, 153 insertions(+), 255 deletions(-) diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 30296cb3186..3e7c4912527 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"); } @@ -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 96284f8de26..6eb7c5a4310 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 6df47480977..de77fa602c9 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 925244849bc..f5c91f7b1b3 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 e7457f370d9..70db3e964ab 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 34754f045ff..81633316671 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -20,7 +20,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; @@ -627,7 +627,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 5c09466cd96..d48f7f541f0 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/pat_util.rs b/src/librustc/middle/pat_util.rs index 24d97f5aac3..2d53d742ee4 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/resolve.rs b/src/librustc/middle/resolve.rs index d42befc6542..b7b4618a790 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 2b2f3b8fb0b..56894ad3e5c 100644 --- a/src/librustc/middle/save/mod.rs +++ b/src/librustc/middle/save/mod.rs @@ -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), diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 595203fdefb..55939e6ea7a 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 f4019898003..afa0b304155 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 79630be7c5e..9629fb38af8 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 60ce9508dc4..697c5d367ee 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 f5e34e93077..b68991aed70 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/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 87151708812..58985f832ce 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)) { @@ -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/libsyntax/ast.rs b/src/libsyntax/ast.rs index 529b460adcd..237d0660a41 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 2a6f7bdb87e..036d6b4b43a 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/build.rs b/src/libsyntax/ext/build.rs index 8d48401f9c2..46bc4ec11ce 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/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 2b97687dbf8..b9bc5009337 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -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 b9cedb7a779..d1eb0147b9c 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, ()) diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index c6177ce31f5..f9d7078da3d 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 331a49c83be..4b5252bfba3 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 0fd5a7086b7..2aa2da3ba4b 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 { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index a9cf4fbd9f0..4660bb337ab 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 6f0fc217533..4ab064a88b7 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), From 9868b65b153a5bed9ca75eca750efae13e93cc44 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Wed, 2 Jul 2014 13:21:58 -0400 Subject: [PATCH 06/18] Guide: add mutable binding section Fixes #15334. --- src/doc/guide.md | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/src/doc/guide.md b/src/doc/guide.md index 7ecfe7ce578..aca726812d2 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; From b81905eedbf56e026e8144a32056fd5dd0265d3b Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Tue, 1 Jul 2014 22:11:47 -0700 Subject: [PATCH 07/18] Fix ICE with nested macro_rules!-style macros Fixes #10536. --- src/libsyntax/parse/parser.rs | 4 ++-- src/test/compile-fail/issue-10536.rs | 34 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 src/test/compile-fail/issue-10536.rs diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 2aa2da3ba4b..f3789e25bc8 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3248,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 { "" @@ -3268,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/test/compile-fail/issue-10536.rs b/src/test/compile-fail/issue-10536.rs new file mode 100644 index 00000000000..36afc729de9 --- /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}); +} + From 5d360050666ef6c884fbf9b7eec1f3da9f0d13bf Mon Sep 17 00:00:00 2001 From: Ruud van Asseldonk Date: Wed, 2 Jul 2014 21:37:33 +0200 Subject: [PATCH 08/18] remove duplicated slash in install script path --- src/etc/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/etc/install.sh b/src/etc/install.sh index fd4c20d73c5..2ed7a9dd6c2 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="$@" From 704f11d3d8a066eb5e8bb869af07fa33de530cc8 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Wed, 2 Jul 2014 16:27:08 -0400 Subject: [PATCH 09/18] correct a few spelling mistakes in the tutorial --- src/doc/tutorial.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/tutorial.md b/src/doc/tutorial.md index 5fe6a5f14c2..2a788d7e793 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; } From 8297edd54976d06f4753bc18684614516d156243 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 2 Jul 2014 13:27:14 -0700 Subject: [PATCH 10/18] librustc: Have the kind checker check sub-bounds in trait casts. This can break code that looked like: struct S { val: T, } trait Gettable { ... } impl Gettable for S { ... } let t: Box> = box S { val: "one".to_string(), }; let a = t as Box>; // ^ note no `Copy` bound Change this code to: impl Gettable for S { // ^ remove `Copy` bound ... } Closes #14061. [breaking-change] --- src/librustc/middle/kind.rs | 80 +++++++++++++++++-- src/librustc/middle/typeck/check/vtable.rs | 3 + src/librustc/middle/typeck/mod.rs | 4 +- .../compile-fail/kindck-impl-type-params.rs | 39 +++++++++ 4 files changed, 116 insertions(+), 10 deletions(-) create mode 100644 src/test/compile-fail/kindck-impl-type-params.rs diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index 81633316671..a7154e78bc5 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; @@ -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); + } + _ => {} } - _ => {} - }, + } _ => {} } } diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 33e0d0331be..bda47d99ed7 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/mod.rs b/src/librustc/middle/typeck/mod.rs index e159d0d00c8..7b6935df420 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/test/compile-fail/kindck-impl-type-params.rs b/src/test/compile-fail/kindck-impl-type-params.rs new file mode 100644 index 00000000000..48e1bdd671a --- /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 +} + From e3fa23bcb64064d50c2a9e3b5870bc82081359d9 Mon Sep 17 00:00:00 2001 From: Joseph Crail Date: Wed, 2 Jul 2014 21:27:07 -0400 Subject: [PATCH 11/18] Fix spelling errors. --- src/liballoc/arc.rs | 2 +- src/libgreen/stack.rs | 2 +- src/liblog/lib.rs | 2 +- src/libnative/io/net.rs | 2 +- src/libnative/io/pipe_win32.rs | 2 +- src/librlibc/lib.rs | 2 +- src/librustc/back/link.rs | 2 +- src/librustc/lint/builtin.rs | 2 +- src/librustc/middle/mem_categorization.rs | 2 +- src/librustc/middle/privacy.rs | 2 +- src/librustc/middle/save/mod.rs | 6 +++--- src/librustc/middle/typeck/infer/unify.rs | 8 ++++---- src/librustdoc/clean/mod.rs | 2 +- src/librustrt/c_str.rs | 2 +- src/librustrt/libunwind.rs | 2 +- src/librustrt/task.rs | 4 ++-- src/librustrt/thread.rs | 2 +- src/librustuv/lib.rs | 2 +- src/librustuv/stream.rs | 2 +- src/librustuv/timer.rs | 2 +- src/libstd/io/net/ip.rs | 2 +- src/libstd/os.rs | 2 +- src/libstd/rt/backtrace.rs | 2 +- src/libsync/comm/oneshot.rs | 2 +- src/libsync/comm/shared.rs | 4 ++-- src/libsync/mutex.rs | 2 +- src/libsyntax/ext/base.rs | 2 +- src/libsyntax/ext/deriving/generic/mod.rs | 2 +- src/libsyntax/ext/expand.rs | 2 +- 29 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 38ed511c458..9b4f879e61e 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/libgreen/stack.rs b/src/libgreen/stack.rs index c4885edb7d3..5faa9cfe6f6 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/liblog/lib.rs b/src/liblog/lib.rs index ba102a85c1b..17349f41b98 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 dfc2c55cde7..f052826d303 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 da713e3f2a9..e5e8cdeffd7 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/librlibc/lib.rs b/src/librlibc/lib.rs index c85e0099ab8..4423ab62f0d 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 17f29639601..a190d9309cc 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 3e7c4912527..a8f778934ae 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -985,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 { diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index e1a2a5741fb..54cca082e0d 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/privacy.rs b/src/librustc/middle/privacy.rs index 414aac47cdc..76e962a3bc4 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/save/mod.rs b/src/librustc/middle/save/mod.rs index 56894ad3e5c..bdb7d30339d 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) @@ -1403,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/typeck/infer/unify.rs b/src/librustc/middle/typeck/infer/unify.rs index f106ce18a4a..44afc04d3f0 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/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 58985f832ce..d0873d4c66a 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1737,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| { diff --git a/src/librustrt/c_str.rs b/src/librustrt/c_str.rs index 9734ba2d751..161d3ed5e65 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 6811a62c74f..f018b3fc16b 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 891d0d5a8e3..59401a8b666 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 9908e87e86a..59784328cdb 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 968a283995b..a1712394634 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 f6b9226588c..875c2dee46b 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 9d0a56b3c85..f6c1cdd2977 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 2c54bd895e9..ca59849202b 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/os.rs b/src/libstd/os.rs index c69209acbdd..4388de43f20 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -469,7 +469,7 @@ pub fn unsetenv(n: &str) { /// 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 { diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs index 8f51e834c6a..2e0dcdd8eb6 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 bf2d9aa52fd..742686069e2 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 a50a6bbc8d3..5ad4dea5d2a 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 ef558d3f924..a10ec745869 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/ext/base.rs b/src/libsyntax/ext/base.rs index 0d8373eac3c..ab5d7021746 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -472,7 +472,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 diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index b9bc5009337..157b64fb47c 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) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index d1eb0147b9c..c3413293e52 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1295,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 From 4a6fcc51a063a49c1b7a330828c857849d1e3119 Mon Sep 17 00:00:00 2001 From: Joseph Crail Date: Thu, 3 Jul 2014 01:30:00 -0400 Subject: [PATCH 12/18] Rename set_broadast() to set_broadcast(). --- src/libstd/io/net/udp.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libstd/io/net/udp.rs b/src/libstd/io/net/udp.rs index cd78898d46b..21903eb2643 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` From 2f355b79ddb49c45fb3396352f464458ad867234 Mon Sep 17 00:00:00 2001 From: Piotr Jawniak Date: Thu, 3 Jul 2014 11:42:24 +0200 Subject: [PATCH 13/18] Simplify creating a parser from a token tree Closes #15306 --- src/libfourcc/lib.rs | 7 +------ src/libhexfloat/lib.rs | 7 +------ src/libregex_macros/lib.rs | 4 +--- src/libsyntax/ext/asm.rs | 8 +------- src/libsyntax/ext/base.rs | 12 +++++++----- src/libsyntax/ext/cfg.rs | 8 +------- src/libsyntax/ext/format.rs | 7 +------ src/libsyntax/ext/quote.rs | 7 +------ 8 files changed, 14 insertions(+), 46 deletions(-) diff --git a/src/libfourcc/lib.rs b/src/libfourcc/lib.rs index a5880f32472..848509cbab2 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/libhexfloat/lib.rs b/src/libhexfloat/lib.rs index 1b43f236e69..369de484e8e 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/libregex_macros/lib.rs b/src/libregex_macros/lib.rs index ff5cada05ea..4108388e776 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/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs index 50b1639484d..f0494e18120 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 ab5d7021746..d2e69204d33 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() } @@ -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/cfg.rs b/src/libsyntax/ext/cfg.rs index 3e74b2680e0..c2930662bc4 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/format.rs b/src/libsyntax/ext/format.rs index 857eadfe57c..f39e50ad131 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 35702b1b3cd..7b24b97d5da 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(); From 7db691e010c34d156ff31eda2db0560738c45837 Mon Sep 17 00:00:00 2001 From: Jason Thompson Date: Thu, 3 Jul 2014 06:02:21 -0400 Subject: [PATCH 14/18] Add examples for StrVector methods - examples for connect and concat - also fixed extra word in existing docs --- src/libcollections/str.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index fd8ce11d0b5..ddba4b34e3a 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); From e7adb8434aed78b1b5b4bb01c45f680a4b8adebb Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Thu, 3 Jul 2014 08:40:08 -0700 Subject: [PATCH 15/18] collections: grow should use the overflow-checked reserve_additional --- src/libcollections/vec.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 2ffc168f82c..b8efaa78af3 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 { From 451b7495b03efbea1c1c50613620ca1e409e41da Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Thu, 3 Jul 2014 08:45:28 -0700 Subject: [PATCH 16/18] collections: Fix conditional when reserving extra vec space --- src/libcollections/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index b8efaa78af3..d53ecabd5a9 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -496,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)) } } From 0c5b627232bca6bd62d9862834a425038e19e4c1 Mon Sep 17 00:00:00 2001 From: OGINO Masanori Date: Fri, 4 Jul 2014 00:53:14 +0900 Subject: [PATCH 17/18] Fix minor issues in the documentation of libtime. - When the timezone is UTC, the "zone" field of the RFC 822 format is "GMT" (or "UT"), not "UTC." - Although the name of `rfc3999` refers to RFC 3999, the documentation of it refers only to ISO 8601. This commit adds a description of the relation between ISO 8601 and RFC 3999. Signed-off-by: OGINO Masanori --- src/libtime/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libtime/lib.rs b/src/libtime/lib.rs index f52a032961d..98544a1218a 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" From 9bd6479912990046947913f160f69bc550dd3817 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 3 Jul 2014 12:01:33 -0700 Subject: [PATCH 18/18] Test fixes from the rollup --- src/libstd/os.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 4388de43f20..b3f25914c8f 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -482,7 +482,7 @@ pub fn split_paths(unparsed: T) -> Vec { } #[cfg(windows)] - pub fn _split_paths(unparsed: T) -> Vec { + 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