From 06d401948ba7451d8ed10b4a58e1e2d08c0094f7 Mon Sep 17 00:00:00 2001 From: Sean Patrick Santos Date: Thu, 15 Jan 2015 13:49:23 -0700 Subject: [PATCH 01/20] For issue 15149 test, don't execute from tmpfs, and wait to see if the child panics before passing. --- src/test/run-pass/issue-15149.rs | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/test/run-pass/issue-15149.rs b/src/test/run-pass/issue-15149.rs index 57dc6fd75f08c..59b1bb287fa74 100644 --- a/src/test/run-pass/issue-15149.rs +++ b/src/test/run-pass/issue-15149.rs @@ -8,7 +8,7 @@ // 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; fn main() { @@ -22,19 +22,23 @@ fn main() { } 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 child_dir = Path::new(my_dir.join("issue-15149-child")); + drop(fs::mkdir(&child_dir, USER_RWX)); + + 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(); + assert!(Command::new("mytest").env("PATH", path.as_slice()) + .arg("child") + .status().unwrap().success()); } From be138ed2bd6a4c4bf1c80287569709a9905e4891 Mon Sep 17 00:00:00 2001 From: P1start Date: Wed, 21 Jan 2015 11:04:17 +1300 Subject: [PATCH 02/20] Add `#[rustc_on_unimplemented]` annotations to more traits --- src/libcore/fmt/mod.rs | 4 ++++ src/libcore/iter.rs | 2 ++ src/libcore/marker.rs | 3 +++ 3 files changed, 9 insertions(+) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 0e8d31a62eed9..60403d1c01179 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -243,6 +243,8 @@ pub trait Show { /// Format trait for the `:?` format. Useful for debugging, most all types /// should implement this. #[unstable = "I/O and core have yet to be reconciled"] +#[rustc_on_unimplemented = "`{Self}` cannot be formatted using `:?`; if it is defined in your \ + crate, add `#[derive(Debug)]` or manually implement it"] pub trait Debug { /// Formats the value using the given formatter. fn fmt(&self, &mut Formatter) -> Result; @@ -266,6 +268,8 @@ pub trait String { /// When a value can be semantically expressed as a String, this trait may be /// used. It corresponds to the default format, `{}`. #[unstable = "I/O and core have yet to be reconciled"] +#[rustc_on_unimplemented = "`{Self}` cannot be formatted with the default formatter; try using \ + `:?` instead if you are using a format string"] pub trait Display { /// Formats the value using the given formatter. fn fmt(&self, &mut Formatter) -> Result; diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 773ac99b0dee2..c31ad56fe5bab 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -82,6 +82,8 @@ use uint; /// else. #[lang="iterator"] #[stable] +#[rustc_on_unimplemented = "`{Self}` is not an iterator; maybe try calling `.iter()` or a similar \ + method"] pub trait Iterator { #[stable] type Item; diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index a987a0a5068a8..f32552f300cc2 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -30,6 +30,7 @@ use clone::Clone; /// Types able to be transferred across task boundaries. #[unstable = "will be overhauled with new lifetime rules; see RFC 458"] #[lang="send"] +#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"] pub unsafe trait Send: 'static { // empty. } @@ -37,6 +38,7 @@ pub unsafe trait Send: 'static { /// Types with a constant size known at compile-time. #[stable] #[lang="sized"] +#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"] pub trait Sized { // Empty. } @@ -193,6 +195,7 @@ pub trait Copy { /// `transmute`-ing from `&T` to `&mut T` is illegal). #[unstable = "will be overhauled with new lifetime rules; see RFC 458"] #[lang="sync"] +#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"] pub unsafe trait Sync { // Empty } From 87db16cecd165ab8ed57dfa308a429868716fdc9 Mon Sep 17 00:00:00 2001 From: P1start Date: Thu, 22 Jan 2015 22:22:16 +1300 Subject: [PATCH 03/20] core::marker: s/task/thread/ --- src/libcore/marker.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index f32552f300cc2..688f048440152 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -27,7 +27,7 @@ use clone::Clone; -/// Types able to be transferred across task boundaries. +/// Types able to be transferred across thread boundaries. #[unstable = "will be overhauled with new lifetime rules; see RFC 458"] #[lang="send"] #[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"] @@ -148,11 +148,11 @@ pub trait Copy { // Empty. } -/// Types that can be safely shared between tasks when aliased. +/// Types that can be safely shared between threads when aliased. /// /// The precise definition is: a type `T` is `Sync` if `&T` is /// thread-safe. In other words, there is no possibility of data races -/// when passing `&T` references between tasks. +/// when passing `&T` references between threads. /// /// As one would expect, primitive types like `u8` and `f64` are all /// `Sync`, and so are simple aggregate types containing them (like From 3dbac7882e27d680112cf172b789f9741c7ab25d Mon Sep 17 00:00:00 2001 From: blackbeam Date: Thu, 22 Jan 2015 12:29:49 +0300 Subject: [PATCH 04/20] libsyntax: fix for `has_test_signature` --- src/libsyntax/test.rs | 2 ++ 1 file changed, 2 insertions(+) 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(); From fd029209ec4901580b1cc0180098e0b4024bee5b Mon Sep 17 00:00:00 2001 From: blackbeam Date: Thu, 22 Jan 2015 21:38:00 +0300 Subject: [PATCH 05/20] Add test for `has_test_signature` for explicit return --- ...e-verification-for-explicit-return-type.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/test/run-pass/test-fn-signature-verification-for-explicit-return-type.rs 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() -> () {} + From 918dd3488f450383c5ce27f0a27f45fa3fc9d0d6 Mon Sep 17 00:00:00 2001 From: Sean Patrick Santos Date: Thu, 22 Jan 2015 11:54:45 -0700 Subject: [PATCH 06/20] Attempt fix for assertion on Windows, and add extra output for debugging. --- src/test/run-pass/issue-15149.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/test/run-pass/issue-15149.rs b/src/test/run-pass/issue-15149.rs index 59b1bb287fa74..4b345f639e4cb 100644 --- a/src/test/run-pass/issue-15149.rs +++ b/src/test/run-pass/issue-15149.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::path::BytesContainer; use std::io::{Command, fs, USER_RWX}; use std::os; @@ -15,7 +16,8 @@ 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(); @@ -38,7 +40,12 @@ fn test() { path.push(child_dir.clone()); let path = os::join_paths(path.as_slice()).unwrap(); - assert!(Command::new("mytest").env("PATH", path.as_slice()) - .arg("child") - .status().unwrap().success()); + 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())); } From ea6dc180fe145176e20ae7ecd6b9b0b7afffe67c Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Thu, 22 Jan 2015 18:59:33 -0500 Subject: [PATCH 07/20] remove weird sentence Fixes #21531 --- src/doc/reference.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 9ec4708eb2f36..e5fefc9e4c2fa 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -2640,9 +2640,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. From 7f45dc9e68ffe80d399560644af48383a25427fd Mon Sep 17 00:00:00 2001 From: Sean Patrick Santos Date: Thu, 22 Jan 2015 18:34:58 -0700 Subject: [PATCH 08/20] Add a random number string to the end of the issue-15149 test's child directory's name, and remove the directory after a successful test. --- src/test/run-pass/issue-15149.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/test/run-pass/issue-15149.rs b/src/test/run-pass/issue-15149.rs index 4b345f639e4cb..5d3571e4d748b 100644 --- a/src/test/run-pass/issue-15149.rs +++ b/src/test/run-pass/issue-15149.rs @@ -8,9 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::path::BytesContainer; 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 @@ -28,8 +29,10 @@ fn test() { let my_path = os::self_exe_name().unwrap(); let my_dir = my_path.dir_path(); - let child_dir = Path::new(my_dir.join("issue-15149-child")); - drop(fs::mkdir(&child_dir, USER_RWX)); + 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)); @@ -48,4 +51,7 @@ fn test() { 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(); + } From a80807028a027c0a677777c8120237c5b3047993 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Thu, 22 Jan 2015 22:35:28 -0500 Subject: [PATCH 09/20] Language tweak in configure Fixes #13082 --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index b2f8c33380ce7..5d26d4e7ed522 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 } From 7aa3ed1ee8b04df11ed42aeea64495cc1190aaf5 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Thu, 22 Jan 2015 22:44:43 -0500 Subject: [PATCH 10/20] Check for make in configure Fixes #13179 --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index b2f8c33380ce7..d3867b850748d 100755 --- a/configure +++ b/configure @@ -340,6 +340,7 @@ need_cmd date need_cmd tr need_cmd sed need_cmd file +need_cmd make msg "inspecting environment" From fc5bbdf70f8a9b0bfd7e377cc7df732b119bdac7 Mon Sep 17 00:00:00 2001 From: Kevin Yap Date: Thu, 22 Jan 2015 17:54:49 -0800 Subject: [PATCH 11/20] Make `make tidy` Python scripts more idiomatic Also makes errorck.py and tidy.py compatible with Python 3. --- src/etc/errorck.py | 39 ++++++++++++++------------------------- src/etc/licenseck.py | 12 ++++++------ src/etc/tidy.py | 2 +- 3 files changed, 21 insertions(+), 32 deletions(-) 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..44a50efcd09ee 100644 --- a/src/etc/licenseck.py +++ b/src/etc/licenseck.py @@ -57,18 +57,18 @@ 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): + if (license1 not in boilerplate or license2 not in boilerplate) and \ + (license3 not in boilerplate or license4 not in boilerplate): return False + return True 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)) From 76c279a4cfc9e54327bcc668a895ec19185139e9 Mon Sep 17 00:00:00 2001 From: Kevin Yap Date: Thu, 22 Jan 2015 20:40:15 -0800 Subject: [PATCH 12/20] Use a regex to perform license check --- src/etc/licenseck.py | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/src/etc/licenseck.py b/src/etc/licenseck.py index 44a50efcd09ee..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 @@ -67,8 +56,4 @@ def check_license(name, contents): # License check boilerplate = contents[:500] - if (license1 not in boilerplate or license2 not in boilerplate) and \ - (license3 not in boilerplate or license4 not in boilerplate): - return False - - return True + return bool(license_re.search(boilerplate)) From 06714c2bceb1ec7803e1a3c52e613fa003722fbc Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Fri, 23 Jan 2015 15:21:11 +0100 Subject: [PATCH 13/20] Fix compile test for stage0 --- src/compiletest/common.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) 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 { From aca793966a84dfec785c3e300e62588dad35dfeb Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Tue, 13 Jan 2015 15:00:49 -0500 Subject: [PATCH 14/20] Soup up 'method syntax' chapter of the Book Fixes #16969 --- src/doc/trpl/method-syntax.md | 114 +++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 2 deletions(-) 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. From dc2b3ac889d9841bff3cd9ddc7c63f5955212313 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Thu, 22 Jan 2015 19:09:59 -0500 Subject: [PATCH 15/20] Remove lang items from the reference. Fixes #19759 --- src/doc/reference.md | 131 +------------------------------------------ 1 file changed, 1 insertion(+), 130 deletions(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 9ec4708eb2f36..a0d4675009789 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -2279,136 +2279,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 From 91037a417ed9bd19608f3f06fd6214fcc0daf9cf Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Fri, 23 Jan 2015 13:53:19 -0500 Subject: [PATCH 16/20] remove discuss link from the book --- src/doc/trpl/installing-rust.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/doc/trpl/installing-rust.md b/src/doc/trpl/installing-rust.md index 5893b51a4208c..80288c4c3d9ca 100644 --- a/src/doc/trpl/installing-rust.md +++ b/src/doc/trpl/installing-rust.md @@ -83,7 +83,6 @@ If not, there are a number of places where you can get help. The easiest is you can access through [Mibbit](http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust). Click that link, and you'll be chatting with other Rustaceans (a silly nickname we -call ourselves), and we can help you out. Other great resources include [our -forum](http://discuss.rust-lang.org/), [the /r/rust -subreddit](http://www.reddit.com/r/rust), and [Stack +call ourselves), and we can help you out. Other great resources include [the +/r/rust subreddit](http://www.reddit.com/r/rust), and [Stack Overflow](http://stackoverflow.com/questions/tagged/rust). From 6f7c0b16d3bb0be438a0394595c74904ab868770 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Fri, 23 Jan 2015 19:35:10 -0500 Subject: [PATCH 17/20] add test for issue 19660 closes #19660 --- src/test/compile-fail/issue-19660.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/test/compile-fail/issue-19660.rs diff --git a/src/test/compile-fail/issue-19660.rs b/src/test/compile-fail/issue-19660.rs new file mode 100644 index 0000000000000..f83037d47bbb1 --- /dev/null +++ b/src/test/compile-fail/issue-19660.rs @@ -0,0 +1,22 @@ +// 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. + +// error-pattern: requires `copy` lang_item + +#![feature(lang_items, start)] +#![no_std] + +#[lang = "sized"] +trait Sized {} + +#[start] +fn main(_: int, _: *const *const u8) -> int { + 0 +} From 2595780e2690364f081c4c33a78286e7ddaa1953 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 23 Jan 2015 21:13:35 -0800 Subject: [PATCH 18/20] Fix beta naming --- mk/main.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mk/main.mk b/mk/main.mk index 8c910f4759610..0e52f168f59ed 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -30,8 +30,8 @@ CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM) CFG_DISABLE_UNSTABLE_FEATURES=1 endif ifeq ($(CFG_RELEASE_CHANNEL),beta) -CFG_RELEASE=$(CFG_RELEASE_NUM)-beta(CFG_PRERELEASE_VERSION) -CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)-beta(CFG_PRERELEASE_VERSION) +CFG_RELEASE=$(CFG_RELEASE_NUM)-beta$(CFG_PRERELEASE_VERSION) +CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)-beta$(CFG_PRERELEASE_VERSION) CFG_DISABLE_UNSTABLE_FEATURES=1 endif ifeq ($(CFG_RELEASE_CHANNEL),nightly) From 577c4643dd3f098697c17606e64d92477247d4b5 Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Sat, 24 Jan 2015 15:10:37 +0100 Subject: [PATCH 19/20] don't run pretty-rpass for tests using #![main] --- .../test-fn-signature-verification-for-explicit-return-type.rs | 1 + 1 file changed, 1 insertion(+) 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 index 65a6ed2b332ff..7c99c968e3523 100644 --- 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 @@ -9,6 +9,7 @@ // except according to those terms. // compile-flags: --test +// no-pretty-expanded extern crate test; #[bench] From 7e83e46556fea9f448e47f7879f5970c400fb24c Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Sun, 25 Jan 2015 10:52:55 +0100 Subject: [PATCH 20/20] assert path ends with executable. On Windows the process executable contains the full path --- src/test/run-pass/issue-15149.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/test/run-pass/issue-15149.rs b/src/test/run-pass/issue-15149.rs index 5d3571e4d748b..bf395b14eb4ec 100644 --- a/src/test/run-pass/issue-15149.rs +++ b/src/test/run-pass/issue-15149.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::slice::SliceExt; use std::io::{Command, fs, USER_RWX}; use std::os; use std::path::BytesContainer; @@ -17,8 +18,11 @@ 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], - format!("mytest{}", os::consts::EXE_SUFFIX)); + // FIXME: This should check the whole `args[0]` instead of just + // checking that it ends_with the executable name. This + // is needed because of Windows, which has a different behavior. + // See #15149 for more info. + return assert!(args[0].ends_with(&format!("mytest{}", os::consts::EXE_SUFFIX)[])); } test();