diff --git a/configure b/configure index b2f8c33380ce7..e2f8b162cd790 100755 --- a/configure +++ b/configure @@ -28,8 +28,8 @@ need_ok() { need_cmd() { if command -v $1 >/dev/null 2>&1 - then msg "found $1" - else err "need $1" + then msg "found program $1" + else err "need program $1" fi } @@ -340,6 +340,7 @@ need_cmd date need_cmd tr need_cmd sed need_cmd file +need_cmd make msg "inspecting environment" diff --git a/src/compiletest/common.rs b/src/compiletest/common.rs index c21785c45a3ac..eb8c013de0e68 100644 --- a/src/compiletest/common.rs +++ b/src/compiletest/common.rs @@ -13,6 +13,20 @@ use std::fmt; use std::str::FromStr; use regex::Regex; +#[cfg(stage0)] // NOTE: remove impl after snapshot +#[derive(Clone, PartialEq, Show)] +pub enum Mode { + CompileFail, + RunFail, + RunPass, + RunPassValgrind, + Pretty, + DebugInfoGdb, + DebugInfoLldb, + Codegen +} + +#[cfg(not(stage0))] // NOTE: remove cfg after snapshot #[derive(Clone, PartialEq, Debug)] pub enum Mode { CompileFail, @@ -25,6 +39,7 @@ pub enum Mode { Codegen } + impl Copy for Mode {} impl FromStr for Mode { diff --git a/src/doc/reference.md b/src/doc/reference.md index d703607c1723c..3cbd71a1eb340 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -2291,136 +2291,7 @@ The name `str_eq` has a special meaning to the Rust compiler, and the presence of this definition means that it will use this definition when generating calls to the string equality function. -A complete list of the built-in language items follows: - -#### Built-in Traits - -* `copy` - : Types that do not move ownership when used by-value. -* `drop` - : Have destructors. -* `send` - : Able to be sent across thread boundaries. -* `sized` - : Has a size known at compile time. -* `sync` - : Able to be safely shared between threads when aliased. - -#### Operators - -These language items are traits: - -* `add` - : Elements can be added (for example, integers and floats). -* `sub` - : Elements can be subtracted. -* `mul` - : Elements can be multiplied. -* `div` - : Elements have a division operation. -* `rem` - : Elements have a remainder operation. -* `neg` - : Elements can be negated arithmetically. -* `not` - : Elements can be negated logically. -* `bitxor` - : Elements have an exclusive-or operation. -* `bitand` - : Elements have a bitwise `and` operation. -* `bitor` - : Elements have a bitwise `or` operation. -* `shl` - : Elements have a left shift operation. -* `shr` - : Elements have a right shift operation. -* `index` - : Elements can be indexed. -* `index_mut` - : ___Needs filling in___ -* `eq` - : Elements can be compared for equality. -* `ord` - : Elements have a partial ordering. -* `deref` - : `*` can be applied, yielding a reference to another type. -* `deref_mut` - : `*` can be applied, yielding a mutable reference to another type. - -These are functions: - -* `fn` - : ___Needs filling in___ -* `fn_mut` - : ___Needs filling in___ -* `fn_once` - : ___Needs filling in___ -* `str_eq` - : Compare two strings (`&str`) for equality. -* `strdup_uniq` - : Return a new unique string - containing a copy of the contents of a unique string. - -#### Types - -* `type_id` - : The type returned by the `type_id` intrinsic. -* `unsafe` - : A type whose contents can be mutated through an immutable reference. - -#### Marker types - -These types help drive the compiler's analysis - -* `begin_unwind` - : ___Needs filling in___ -* `no_copy_bound` - : This type does not implement "copy", even if eligible. -* `eh_personality` - : ___Needs filling in___ -* `exchange_free` - : Free memory that was allocated on the exchange heap. -* `exchange_malloc` - : Allocate memory on the exchange heap. -* `closure_exchange_malloc` - : ___Needs filling in___ -* `panic` - : Abort the program with an error. -* `fail_bounds_check` - : Abort the program with a bounds check error. -* `free` - : Free memory that was allocated on the managed heap. -* `gc` - : ___Needs filling in___ -* `exchange_heap` - : ___Needs filling in___ -* `iterator` - : ___Needs filling in___ -* `contravariant_lifetime` - : The lifetime parameter should be considered contravariant. -* `covariant_lifetime` - : The lifetime parameter should be considered covariant. -* `invariant_lifetime` - : The lifetime parameter should be considered invariant. -* `malloc` - : Allocate memory on the managed heap. -* `owned_box` - : ___Needs filling in___ -* `stack_exhausted` - : ___Needs filling in___ -* `start` - : ___Needs filling in___ -* `contravariant_type` - : The type parameter should be considered contravariant. -* `covariant_type` - : The type parameter should be considered covariant. -* `invariant_type` - : The type parameter should be considered invariant. -* `ty_desc` - : ___Needs filling in___ - -> **Note:** This list is likely to become out of date. We should auto-generate -> it from `librustc/middle/lang_items.rs`. +A complete list of the built-in language items will be added in the future. ### Inline attributes @@ -2652,9 +2523,7 @@ The currently implemented features of the reference compiler are: declare a `static` as being unique per-thread leveraging LLVM's implementation which works in concert with the kernel loader and dynamic linker. This is not necessarily available - on all platforms, and usage of it is discouraged (rust - focuses more on thread-local data instead of thread-local - data). + on all platforms, and usage of it is discouraged. * `trace_macros` - Allows use of the `trace_macros` macro, which is a nasty hack that will certainly be removed. diff --git a/src/doc/trpl/method-syntax.md b/src/doc/trpl/method-syntax.md index 3d8de00991c95..e6570c2ee74c8 100644 --- a/src/doc/trpl/method-syntax.md +++ b/src/doc/trpl/method-syntax.md @@ -18,6 +18,8 @@ x.foo().bar().baz(); Luckily, as you may have guessed with the leading question, you can! Rust provides the ability to use this *method call syntax* via the `impl` keyword. +## Method calls + Here's how it works: ```{rust} @@ -56,11 +58,56 @@ other parameter. Because we know it's a `Circle`, we can access the `radius` just like we would with any other struct. An import of π and some multiplications later, and we have our area. +## Chaining method calls + +So, now we know how to call a method, such as `foo.bar()`. But what about our +original example, `foo.bar().baz()`? This is called 'method chaining', and we +can do it by returning `self`. + +``` +struct Circle { + x: f64, + y: f64, + radius: f64, +} + +impl Circle { + fn area(&self) -> f64 { + std::f64::consts::PI * (self.radius * self.radius) + } + + fn grow(&self) -> Circle { + Circle { x: self.x, y: self.y, radius: (self.radius * 10.0) } + } +} + +fn main() { + let c = Circle { x: 0.0, y: 0.0, radius: 2.0 }; + println!("{}", c.area()); + + let d = c.grow().area(); + println!("{}", d); +} +``` + +Check the return type: + +``` +# struct Circle; +# impl Circle { +fn grow(&self) -> Circle { +# Circle } } +``` + +We just say we're returning a `Circle`. With this, we can grow a new circle +that's twice as big as the old one. + +## Static methods + You can also define methods that do not take a `self` parameter. Here's a pattern that's very common in Rust code: -```{rust} -# #![allow(non_shorthand_field_patterns)] +``` struct Circle { x: f64, y: f64, @@ -86,3 +133,66 @@ This *static method* builds a new `Circle` for us. Note that static methods are called with the `Struct::method()` syntax, rather than the `ref.method()` syntax. +## Builder Pattern + +Let's say that we want our users to be able to create Circles, but we will +allow them to only set the properties they care about. Otherwise, the `x` +and `y` attributes will be `0.0`, and the `radius` will be `1.0`. Rust doesn't +have method overloading, named arguments, or variable arguments. We employ +the builder pattern instead. It looks like this: + +``` +struct Circle { + x: f64, + y: f64, + radius: f64, +} + +impl Circle { + fn area(&self) -> f64 { + std::f64::consts::PI * (self.radius * self.radius) + } +} + +struct CircleBuilder { + coordinate: f64, + radius: f64, +} + +impl CircleBuilder { + fn new() -> CircleBuilder { + CircleBuilder { coordinate: 0.0, radius: 0.0, } + } + + fn coordinate(&mut self, coordinate: f64) -> &mut CircleBuilder { + self.coordinate = coordinate; + self + } + + fn radius(&mut self, radius: f64) -> &mut CircleBuilder { + self.radius = radius; + self + } + + fn finalize(&self) -> Circle { + Circle { x: self.coordinate, y: self.coordinate, radius: self.radius } + } +} + +fn main() { + let c = CircleBuilder::new() + .coordinate(10.0) + .radius(5.0) + .finalize(); + + + println!("area: {}", c.area()); +} +``` + +What we've done here is make another struct, `CircleBuilder`. We've defined our +builder methods on it. We've also defined our `area()` method on `Circle`. We +also made one more method on `CircleBuilder`: `finalize()`. This method creates +our final `Circle` from the builder. Now, we've used the type system to enforce +our concerns: we can use the methods on `CircleBuilder` to constrain making +`Circle`s in any way we choose. diff --git a/src/etc/errorck.py b/src/etc/errorck.py index 17659309d3b0d..952e299265d85 100644 --- a/src/etc/errorck.py +++ b/src/etc/errorck.py @@ -14,11 +14,10 @@ import sys, os, re src_dir = sys.argv[1] - -errcode_map = { } +errcode_map = {} +error_re = re.compile("(E\d\d\d\d)") for (dirpath, dirnames, filenames) in os.walk(src_dir): - if "src/test" in dirpath or "src/llvm" in dirpath: # Short circuit for fast continue @@ -28,15 +27,12 @@ continue path = os.path.join(dirpath, filename) - line_num = 1 - with open(path, 'r') as f: - for line in f: - - p = re.compile("(E\d\d\d\d)") - m = p.search(line) - if not m is None: - errcode = m.group(1) + with open(path, 'r') as f: + for line_num, line in enumerate(f, start=1): + match = error_re.search(line) + if match: + errcode = match.group(1) new_record = [(errcode, path, line_num, line)] existing = errcode_map.get(errcode) if existing is not None: @@ -45,26 +41,19 @@ else: errcode_map[errcode] = new_record - line_num += 1 - errors = False all_errors = [] -for errcode in errcode_map: - entries = errcode_map[errcode] - all_errors += [entries[0][0]] + +for errcode, entries in errcode_map.items(): + all_errors.append(entries[0][0]) if len(entries) > 1: - print "error: duplicate error code " + errcode + print("error: duplicate error code " + errcode) for entry in entries: - print entry[1] + ": " + str(entry[2]) - print entry[3] + print("{1}: {2}\n{3}".format(*entry)) errors = True -print str(len(errcode_map)) + " error codes" - -all_errors.sort() -all_errors.reverse() - -print "highest error code: " + all_errors[0] +print("{0} error codes".format(len(errcode_map))) +print("highest error code: " + max(all_errors)) if errors: sys.exit(1) diff --git a/src/etc/licenseck.py b/src/etc/licenseck.py index 9ac0acc38a73e..f38583ee1fb37 100644 --- a/src/etc/licenseck.py +++ b/src/etc/licenseck.py @@ -8,29 +8,18 @@ # option. This file may not be copied, modified, or distributed # except according to those terms. -license1 = """// Copyright """ -license2 = """ The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -""" +import re -license3 = """# Copyright """ -license4 = """ The Rust Project Developers. See the COPYRIGHT -# file at the top-level directory of this distribution and at -# http://rust-lang.org/COPYRIGHT. -# -# Licensed under the Apache License, Version 2.0 or the MIT license -# , at your -# option. This file may not be copied, modified, or distributed -# except according to those terms. -""" +license_re = re.compile( +u"""(#|//) Copyright .* The Rust Project Developers. See the COPYRIGHT +\\1 file at the top-level directory of this distribution and at +\\1 http://rust-lang.org/COPYRIGHT. +\\1 +\\1 Licensed under the Apache License, Version 2.0 or the MIT license +\\1 , at your +\\1 option. This file may not be copied, modified, or distributed +\\1 except according to those terms.""") exceptions = [ "rt/rust_android_dummy.cpp", # BSD, chromium @@ -57,18 +46,14 @@ def check_license(name, contents): # Whitelist check - for exception in exceptions: - if name.endswith(exception): - return True + if any(name.endswith(e) for e in exceptions): + return True # Xfail check firstlineish = contents[:100] - if firstlineish.find("ignore-license") != -1: + if "ignore-license" in firstlineish: return True # License check boilerplate = contents[:500] - if (boilerplate.find(license1) == -1 or boilerplate.find(license2) == -1) and \ - (boilerplate.find(license3) == -1 or boilerplate.find(license4) == -1): - return False - return True + return bool(license_re.search(boilerplate)) diff --git a/src/etc/tidy.py b/src/etc/tidy.py index 536ab7f30b9fa..c65b762e51731 100644 --- a/src/etc/tidy.py +++ b/src/etc/tidy.py @@ -113,7 +113,7 @@ def do_license_check(name, contents): if current_name != "": do_license_check(current_name, current_contents) -except UnicodeDecodeError, e: +except UnicodeDecodeError as e: report_err("UTF-8 decoding error " + str(e)) diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 6608d0ee9a7ec..19930a3cbff62 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -435,12 +435,9 @@ pub trait StrExt: Index { /// # Examples /// /// ```rust - /// let s = "Do you know the muffin man, - /// The muffin man, the muffin man, ...".to_string(); + /// let s = "this is old"; /// - /// assert_eq!(s.replace("muffin man", "little lamb"), - /// "Do you know the little lamb, - /// The little lamb, the little lamb, ...".to_string()); + /// assert_eq!(s.replace("old", "new"), "this is new") /// /// // not found, so no change. /// assert_eq!(s.replace("cookie monster", "little lamb"), s); diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index e5d8e4e5143a7..8933d3a966957 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -295,6 +295,7 @@ fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool { &ast::ItemFn(ref decl, _, _, ref generics, _) => { let no_output = match decl.output { ast::DefaultReturn(..) => true, + ast::Return(ref t) if t.node == ast::TyTup(vec![]) => true, _ => false }; if decl.inputs.is_empty() @@ -331,6 +332,7 @@ fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool { let input_cnt = decl.inputs.len(); let no_output = match decl.output { ast::DefaultReturn(..) => true, + ast::Return(ref t) if t.node == ast::TyTup(vec![]) => true, _ => false }; let tparm_cnt = generics.ty_params.len(); diff --git a/src/test/run-pass/issue-15149.rs b/src/test/run-pass/issue-15149.rs index 57dc6fd75f08c..5d3571e4d748b 100644 --- a/src/test/run-pass/issue-15149.rs +++ b/src/test/run-pass/issue-15149.rs @@ -8,33 +8,50 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::io::{TempDir, Command, fs}; +use std::io::{Command, fs, USER_RWX}; use std::os; +use std::path::BytesContainer; +use std::rand::random; fn main() { // If we're the child, make sure we were invoked correctly let args = os::args(); if args.len() > 1 && args[1].as_slice() == "child" { - return assert_eq!(args[0].as_slice(), "mytest"); + return assert_eq!(args[0], + format!("mytest{}", os::consts::EXE_SUFFIX)); } test(); } fn test() { - // If we're the parent, copy our own binary to a tempr directory, and then - // make it executable. - let dir = TempDir::new("mytest").unwrap(); - let me = os::self_exe_name().unwrap(); - let dest = dir.path().join(format!("mytest{}", os::consts::EXE_SUFFIX)); - fs::copy(&me, &dest).unwrap(); - - // Append the temp directory to our own PATH. + // If we're the parent, copy our own binary to a new directory. + let my_path = os::self_exe_name().unwrap(); + let my_dir = my_path.dir_path(); + + let random_u32: u32 = random(); + let child_dir = Path::new(my_dir.join(format!("issue-15149-child-{}", + random_u32))); + fs::mkdir(&child_dir, USER_RWX).unwrap(); + + let child_path = child_dir.join(format!("mytest{}", + os::consts::EXE_SUFFIX)); + fs::copy(&my_path, &child_path).unwrap(); + + // Append the new directory to our own PATH. let mut path = os::split_paths(os::getenv("PATH").unwrap_or(String::new())); - path.push(dir.path().clone()); + path.push(child_dir.clone()); let path = os::join_paths(path.as_slice()).unwrap(); - Command::new("mytest").env("PATH", path.as_slice()) - .arg("child") - .spawn().unwrap(); + let child_output = Command::new("mytest").env("PATH", path.as_slice()) + .arg("child") + .output().unwrap(); + + assert!(child_output.status.success(), + format!("child assertion failed\n child stdout:\n {}\n child stderr:\n {}", + child_output.output.container_as_str().unwrap(), + child_output.error.container_as_str().unwrap())); + + fs::rmdir_recursive(&child_dir).unwrap(); + } diff --git a/src/test/run-pass/test-fn-signature-verification-for-explicit-return-type.rs b/src/test/run-pass/test-fn-signature-verification-for-explicit-return-type.rs new file mode 100644 index 0000000000000..65a6ed2b332ff --- /dev/null +++ b/src/test/run-pass/test-fn-signature-verification-for-explicit-return-type.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: --test +extern crate test; + +#[bench] +fn bench_explicit_return_type(_: &mut ::test::Bencher) -> () {} + +#[test] +fn test_explicit_return_type() -> () {} +