From 8f7c2d518d1892c98d2ef57992a65669834f24e2 Mon Sep 17 00:00:00 2001 From: Andrea Canciani Date: Sat, 17 Jan 2015 17:00:32 +0100 Subject: [PATCH 01/41] Replace `be` with `become` As per rust-lang/rfcs#601, replace `be` with `become` as reserved keyword for tail call optimization. --- src/doc/grammar.md | 2 +- src/doc/reference.md | 2 +- src/libsyntax/parse/token.rs | 2 +- .../compile-fail/{reserved-be.rs => reserved-become.rs} | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) rename src/test/compile-fail/{reserved-be.rs => reserved-become.rs} (75%) diff --git a/src/doc/grammar.md b/src/doc/grammar.md index 59a1c8f828b..b4e023c2039 100644 --- a/src/doc/grammar.md +++ b/src/doc/grammar.md @@ -157,7 +157,7 @@ token : simple_token | ident | literal | symbol | whitespace token ; | | | | | | |----------|----------|----------|----------|--------| -| abstract | alignof | as | be | box | +| abstract | alignof | as | become | box | | break | const | continue | crate | do | | else | enum | extern | false | final | | fn | for | if | impl | in | diff --git a/src/doc/reference.md b/src/doc/reference.md index 64ddb3ffdd3..c83cbbce2b2 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -189,7 +189,7 @@ grammar as double-quoted strings. Other tokens have exact rules given. | | | | | | |----------|----------|----------|----------|---------| -| abstract | alignof | as | be | box | +| abstract | alignof | as | become | box | | break | const | continue | crate | do | | else | enum | extern | false | final | | fn | for | if | impl | in | diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 5c3892e49c0..b7357e13a56 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -562,7 +562,7 @@ declare_special_idents_and_keywords! { (45, Where, "where"); 'reserved: (46, Alignof, "alignof"); - (47, Be, "be"); + (47, Become, "become"); (48, Offsetof, "offsetof"); (49, Priv, "priv"); (50, Pure, "pure"); diff --git a/src/test/compile-fail/reserved-be.rs b/src/test/compile-fail/reserved-become.rs similarity index 75% rename from src/test/compile-fail/reserved-be.rs rename to src/test/compile-fail/reserved-become.rs index 386d53cc16e..82e9ebc10d1 100644 --- a/src/test/compile-fail/reserved-be.rs +++ b/src/test/compile-fail/reserved-become.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -9,6 +9,6 @@ // except according to those terms. fn main() { - let be = 0; - //~^ ERROR `be` is a reserved keyword + let become = 0; + //~^ ERROR `become` is a reserved keyword } From 6f872113ab05c0a23a8784e54d22b9e0641dde41 Mon Sep 17 00:00:00 2001 From: Hugo van der Wijst Date: Wed, 4 Feb 2015 20:00:28 +0100 Subject: [PATCH 02/41] Add QPath construction to ExtCtxt for UFCS support. --- src/libsyntax/ext/build.rs | 56 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 53c35ef34cd..4d618e560c5 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -41,6 +41,18 @@ pub trait AstBuilder { bindings: Vec> ) -> ast::Path; + fn qpath(&self, self_type: P, + trait_ref: P, + ident: ast::Ident ) + -> P; + fn qpath_all(&self, self_type: P, + trait_ref: P, + ident: ast::Ident, + lifetimes: Vec, + types: Vec>, + bindings: Vec> ) + -> P; + // types fn ty_mt(&self, ty: P, mutbl: ast::Mutability) -> ast::MutTy; @@ -103,6 +115,7 @@ pub trait AstBuilder { // expressions fn expr(&self, span: Span, node: ast::Expr_) -> P; fn expr_path(&self, path: ast::Path) -> P; + fn expr_qpath(&self, span: Span, qpath: P) -> P; fn expr_ident(&self, span: Span, id: ast::Ident) -> P; fn expr_self(&self, span: Span) -> P; @@ -331,6 +344,44 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } } + /// Constructs a qualified path. + /// + /// Constructs a path like `::ident`. + fn qpath(&self, + self_type: P, + trait_ref: P, + ident: ast::Ident) + -> P { + self.qpath_all(self_type, trait_ref, ident, Vec::new(), Vec::new(), Vec::new()) + } + + /// Constructs a qualified path. + /// + /// Constructs a path like `::ident`. + fn qpath_all(&self, + self_type: P, + trait_ref: P, + ident: ast::Ident, + lifetimes: Vec, + types: Vec>, + bindings: Vec> ) + -> P { + let segment = ast::PathSegment { + identifier: ident, + parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { + lifetimes: lifetimes, + types: OwnedSlice::from_vec(types), + bindings: OwnedSlice::from_vec(bindings), + }) + }; + + P(ast::QPath { + self_type: self_type, + trait_ref: trait_ref, + item_path: segment, + }) + } + fn ty_mt(&self, ty: P, mutbl: ast::Mutability) -> ast::MutTy { ast::MutTy { ty: ty, @@ -554,6 +605,11 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.expr(path.span, ast::ExprPath(path)) } + /// Constructs a QPath expression. + fn expr_qpath(&self, span: Span, qpath: P) -> P { + self.expr(span, ast::ExprQPath(qpath)) + } + fn expr_ident(&self, span: Span, id: ast::Ident) -> P { self.expr_path(self.path_ident(span, id)) } From 4ef7551ccacd4d2042493f2ed905813b297634d0 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Sun, 18 Jan 2015 19:43:35 +0900 Subject: [PATCH 03/41] Fix type inference related to upvars in closures --- src/librustc/middle/traits/select.rs | 8 +++++++ .../run-pass/unboxed-closures-infer-upvar.rs | 22 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 src/test/run-pass/unboxed-closures-infer-upvar.rs diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index b8af91add9e..2fe07df1709 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1587,6 +1587,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return Ok(ParameterBuiltin); } + // Upvars are always local variables or references to + // local variables, and local variables cannot be + // unsized, so the closure struct as a whole must be + // Sized. + if bound == ty::BoundSized { + return Ok(If(Vec::new())); + } + match self.closure_typer.closure_upvars(def_id, substs) { Some(upvars) => { Ok(If(upvars.iter().map(|c| c.ty).collect())) diff --git a/src/test/run-pass/unboxed-closures-infer-upvar.rs b/src/test/run-pass/unboxed-closures-infer-upvar.rs new file mode 100644 index 00000000000..087ef5dcf05 --- /dev/null +++ b/src/test/run-pass/unboxed-closures-infer-upvar.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. + +// Test that the type variable in the type(`Vec<_>`) of a closed over +// variable does not interfere with type inference. + +fn f(mut f: F) { + f(); +} + +fn main() { + let mut v: Vec<_> = vec![]; + f(|| v.push(0)); + assert_eq!(v, vec![0]); +} From 00d1873c4729f1e8c109b64a7eeb87877f075279 Mon Sep 17 00:00:00 2001 From: Kevin Yap Date: Sun, 1 Feb 2015 19:36:42 -0800 Subject: [PATCH 04/41] Use `for` instead of `while` in ascii.rs tests --- src/libstd/ascii.rs | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index 892747e79ed..ac48481027d 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -338,7 +338,6 @@ mod tests { assert!("".is_ascii()); assert!("a".is_ascii()); assert!(!"\u{2009}".is_ascii()); - } #[test] @@ -346,13 +345,11 @@ mod tests { assert_eq!("url()URL()uRl()ürl".to_ascii_uppercase(), "URL()URL()URL()üRL"); assert_eq!("hıKß".to_ascii_uppercase(), "HıKß"); - let mut i = 0; - while i <= 500 { + for i in 0u32..501 { let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 } else { i }; assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_uppercase(), (from_u32(upper).unwrap()).to_string()); - i += 1; } } @@ -362,13 +359,11 @@ mod tests { // Dotted capital I, Kelvin sign, Sharp S. assert_eq!("HİKß".to_ascii_lowercase(), "hİKß"); - let mut i = 0; - while i <= 500 { + for i in 0u32..501 { let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } else { i }; assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_lowercase(), (from_u32(lower).unwrap()).to_string()); - i += 1; } } @@ -378,13 +373,11 @@ mod tests { "URL()URL()URL()üRL".to_string()); assert_eq!(("hıKß".to_string()).into_ascii_uppercase(), "HıKß"); - let mut i = 0; - while i <= 500 { + for i in 0u32..501 { let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 } else { i }; assert_eq!((from_u32(i).unwrap()).to_string().into_ascii_uppercase(), (from_u32(upper).unwrap()).to_string()); - i += 1; } } @@ -395,13 +388,11 @@ mod tests { // Dotted capital I, Kelvin sign, Sharp S. assert_eq!(("HİKß".to_string()).into_ascii_lowercase(), "hİKß"); - let mut i = 0; - while i <= 500 { + for i in 0u32..501 { let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } else { i }; assert_eq!((from_u32(i).unwrap()).to_string().into_ascii_lowercase(), (from_u32(lower).unwrap()).to_string()); - i += 1; } } @@ -415,14 +406,11 @@ mod tests { assert!(!"K".eq_ignore_ascii_case("k")); assert!(!"ß".eq_ignore_ascii_case("s")); - let mut i = 0; - while i <= 500 { - let c = i; - let lower = if 'A' as u32 <= c && c <= 'Z' as u32 { c + 'a' as u32 - 'A' as u32 } - else { c }; + for i in 0u32..501 { + let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } + else { i }; assert!((from_u32(i).unwrap()).to_string().eq_ignore_ascii_case( &from_u32(lower).unwrap().to_string())); - i += 1; } } } From d3c787a94f2b66f337334e71634b1c80a359f0bd Mon Sep 17 00:00:00 2001 From: Thiago Carvalho Date: Fri, 6 Feb 2015 15:36:31 +0100 Subject: [PATCH 05/41] Book Compound Data Types update From Issue 21829 clarify equivalency of tuples --- src/doc/trpl/compound-data-types.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/doc/trpl/compound-data-types.md b/src/doc/trpl/compound-data-types.md index 901b44661b0..aaa016f5a25 100644 --- a/src/doc/trpl/compound-data-types.md +++ b/src/doc/trpl/compound-data-types.md @@ -72,6 +72,20 @@ if x == y { This will print `no`, because some of the values aren't equal. +Note that the order of the values is considered when checking for equality, +so the following example will also print `no`. + +```rust +let x = (1, 2, 3); +let y = (2, 1, 3); + +if x == y { + println!("yes"); +} else { + println!("no"); +} +``` + One other use of tuples is to return multiple values from a function: ```rust From 403869471871f7996ac09c7a8a5553d26b1c5d9a Mon Sep 17 00:00:00 2001 From: Caspar Krieger Date: Sat, 7 Feb 2015 22:21:01 +1100 Subject: [PATCH 06/41] Link to rustdoc page in the Rust book directly No point sending people to a page which just says "this is now part of the Rust book". --- src/doc/index.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/doc/index.md b/src/doc/index.md index 252a3125ebd..a4f79412220 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -59,8 +59,7 @@ tools we have are really nice. [Cargo](http://crates.io) is Rust's package manager, and its website contains lots of good documentation. -[The `rustdoc` manual](rustdoc.html) contains information about Rust's -documentation tool. +[`rustdoc`](book/documentation.html) is used to generate documentation for Rust code. # FAQs From b510b90916df3fb0b1c69861a41e0d194ec27b47 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Sat, 7 Feb 2015 15:41:21 +0200 Subject: [PATCH 07/41] =?UTF-8?q?Do=20not=20fail=20if=20--emit=E2=89=A0lin?= =?UTF-8?q?k=20and=20there=E2=80=99s=20no=20main=20fn?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #21813 --- src/librustc/middle/entry.rs | 5 ++++- src/librustc/session/config.rs | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index 0ce9db1c80f..b5904f23ef3 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -50,7 +50,10 @@ pub fn find_entry_point(session: &Session, ast_map: &ast_map::Map) { let any_exe = session.crate_types.borrow().iter().any(|ty| { *ty == config::CrateTypeExecutable }); - if !any_exe { + let emit_link = session.opts.output_types.iter().any(|ty| { + *ty == config::OutputTypeExe + }); + if !any_exe || !emit_link { // No need to find a main function return } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index efd2392e453..f42b25b9229 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -82,7 +82,7 @@ pub struct Options { pub debuginfo: DebugInfoLevel, pub lint_opts: Vec<(String, lint::Level)>, pub describe_lints: bool, - pub output_types: Vec , + pub output_types: Vec, // This was mutable for rustpkg, which updates search paths based on the // parsed code. It remains mutable in case its replacements wants to use // this. From d163f1f97bf6116e3fc68c528427b0cb2130db06 Mon Sep 17 00:00:00 2001 From: Alexis Date: Sat, 7 Feb 2015 17:09:07 -0500 Subject: [PATCH 08/41] add missing features to libcollections tests --- src/libcollections/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 57c799785e8..f2ec1eafcf2 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -30,7 +30,7 @@ #![feature(unboxed_closures)] #![feature(unicode)] #![feature(unsafe_destructor, slicing_syntax)] -#![cfg_attr(test, feature(test))] +#![cfg_attr(test, feature(rand, rustc_private, test))] #![cfg_attr(test, allow(deprecated))] // rand #![no_std] From 4f61e160326676cdcce94b9d5bca7d88c5f40ee9 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Sun, 8 Feb 2015 00:17:04 +0100 Subject: [PATCH 09/41] Fix std::ops::Range size_hint and ExactSizeIterator impls When self.start > self.end, these iterators simply return None, so we adjust the size_hint to just return zero in this case. Certain optimizations can be implemented in and outside libstd if we know we can trust the size_hint for all inputs to for example Range. This corrects the ExactSizeIterator implementations, which IMO were unsound and incorrect previously, since they allowed a range like (2..1) to return a size_hint of -1us in when debug assertions are turned off. --- src/libcore/iter.rs | 17 +++++++---------- src/libcoretest/iter.rs | 1 + 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index f3b42e4f0a5..fa6719a0312 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -2646,13 +2646,7 @@ impl Iterator for RangeStepInclusive { macro_rules! range_exact_iter_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl ExactSizeIterator for ::ops::Range<$t> { - #[inline] - fn len(&self) -> usize { - debug_assert!(self.end >= self.start); - (self.end - self.start) as usize - } - } + impl ExactSizeIterator for ::ops::Range<$t> { } )*) } @@ -2673,9 +2667,12 @@ impl Iterator for ::ops::Range { #[inline] fn size_hint(&self) -> (usize, Option) { - debug_assert!(self.end >= self.start); - let hint = (self.end - self.start).to_uint(); - (hint.unwrap_or(0), hint) + if self.start >= self.end { + (0, Some(0)) + } else { + let length = (self.end - self.start).to_uint(); + (length.unwrap_or(0), length) + } } } diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index c9cdf50fdbd..3f8e330b332 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -756,6 +756,7 @@ fn test_range() { // this test is only meaningful when sizeof uint < sizeof u64 assert_eq!((uint::MAX - 1..uint::MAX).size_hint(), (1, Some(1))); assert_eq!((-10..-1).size_hint(), (9, Some(9))); + assert_eq!((-1..-10).size_hint(), (0, Some(0))); } #[test] From bb49195d22105e11feffc604a2c25128617816b6 Mon Sep 17 00:00:00 2001 From: Geoffrey Thomas Date: Sat, 7 Feb 2015 19:06:49 -0500 Subject: [PATCH 10/41] reference.md: Byte string literals start with a 'b' This was correct in the EBNF, but not in the prose (which seems to have been copied-and-pasted from regular string literals). --- src/doc/reference.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 9851e1c28fb..26d9c60a614 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -381,11 +381,13 @@ character (`\`), or a single _escape_. It is equivalent to a `u8` unsigned ##### Byte string literals -A _byte string literal_ is a sequence of ASCII characters and _escapes_ -enclosed within two `U+0022` (double-quote) characters, with the exception of -`U+0022` itself, which must be _escaped_ by a preceding `U+005C` character -(`\`), or a _raw byte string literal_. It is equivalent to a `&'static [u8]` -borrowed array of unsigned 8-bit integers. +A non-raw _byte string literal_ is a sequence of ASCII characters and _escapes_, +preceded by the characters `U+0062` (`b`) and `U+0022` (double-quote), and +followed by the character `U+0022`. If the character `U+0022` is present within +the literal, it must be _escaped_ by a preceding `U+005C` (`\`) character. +Alternatively, a byte string literal can be a _raw byte string literal_, defined +below. A byte string literal is equivalent to a `&'static [u8]` borrowed array +of unsigned 8-bit integers. Some additional _escapes_ are available in either byte or non-raw byte string literals. An escape starts with a `U+005C` (`\`) and continues with one of the From 61b4823b77ffaf39e0825314d749eac3a115764d Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Sun, 8 Feb 2015 10:51:46 +0200 Subject: [PATCH 11/41] Add a test for mainless emit targets --- src/test/run-make/empty-file/Makefile | 5 +++++ src/test/run-make/empty-file/empty.rs | 0 2 files changed, 5 insertions(+) create mode 100644 src/test/run-make/empty-file/Makefile create mode 100644 src/test/run-make/empty-file/empty.rs diff --git a/src/test/run-make/empty-file/Makefile b/src/test/run-make/empty-file/Makefile new file mode 100644 index 00000000000..f55a2cc3bb1 --- /dev/null +++ b/src/test/run-make/empty-file/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + $(RUSTC) --emit=asm,llvm-bc,llvm-ir,obj,dep-info empty.rs + $(RUSTC) --emit=link --crate-type=rlib,dylib,staticlib empty.rs diff --git a/src/test/run-make/empty-file/empty.rs b/src/test/run-make/empty-file/empty.rs new file mode 100644 index 00000000000..e69de29bb2d From 8fb426469a4f7b08a240172c8f4295e868c65db8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Marie?= Date: Sun, 8 Feb 2015 09:36:08 +0100 Subject: [PATCH 12/41] adapt run-make test suite for openbsd - c-link-to-rust-staticlib: use EXTRACFLAGS defined by tools.mk for choose the good libraries to link to. - no-stack-check: disabled for openbsd (no segmented stacks here) - symbols-are-reasonable: use portable grep pattern - target-specs: use POSIX form for options when invoking grep - use-extern-for-plugins: disable as OpenBSD only support x86_64 for now --- src/test/run-make/c-link-to-rust-staticlib/Makefile | 4 +--- src/test/run-make/no-stack-check/Makefile | 5 +++++ src/test/run-make/symbols-are-reasonable/Makefile | 6 +++--- src/test/run-make/target-specs/Makefile | 4 ++-- src/test/run-make/use-extern-for-plugins/Makefile | 5 +++++ 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/test/run-make/c-link-to-rust-staticlib/Makefile b/src/test/run-make/c-link-to-rust-staticlib/Makefile index 8a6d6e4dd6d..477b85f362a 100644 --- a/src/test/run-make/c-link-to-rust-staticlib/Makefile +++ b/src/test/run-make/c-link-to-rust-staticlib/Makefile @@ -1,9 +1,7 @@ -include ../tools.mk ifndef IS_WINDOWS -ifneq ($(shell uname),Darwin) - EXTRAFLAGS := -lm -lrt -ldl -lpthread -endif +EXTRAFLAGS := $(EXTRACFLAGS) endif # FIXME: ignore freebsd diff --git a/src/test/run-make/no-stack-check/Makefile b/src/test/run-make/no-stack-check/Makefile index 561056d719e..5fce35e2beb 100644 --- a/src/test/run-make/no-stack-check/Makefile +++ b/src/test/run-make/no-stack-check/Makefile @@ -1,6 +1,7 @@ -include ../tools.mk ifndef IS_WINDOWS +ifneq ($(UNAME),OpenBSD) all: $(RUSTC) -O --emit asm attr.rs ! grep -q morestack $(TMPDIR)/attr.s @@ -9,6 +10,10 @@ all: $(RUSTC) -O --emit asm -C no-stack-check flag.rs ! grep -q morestack $(TMPDIR)/flag.s else +# On OpenBSD, morestack isn't used as the segmented stacks are disabled +all: +endif +else # On Windows we use __chkstk and it only appears in functions with large allocations, # so this test wouldn't be reliable. all: diff --git a/src/test/run-make/symbols-are-reasonable/Makefile b/src/test/run-make/symbols-are-reasonable/Makefile index 42a72f7ca39..89f610dee17 100644 --- a/src/test/run-make/symbols-are-reasonable/Makefile +++ b/src/test/run-make/symbols-are-reasonable/Makefile @@ -10,6 +10,6 @@ OUT=$(TMPDIR)/lib.s all: $(RUSTC) lib.rs --emit=asm --crate-type=staticlib # just check for symbol declarations with the names we're expecting. - grep 'str[0-9]\+:' $(OUT) - grep 'binary[0-9]\+:' $(OUT) - grep 'vtable[0-9]\+' $(OUT) + grep 'str[0-9][0-9]*:' $(OUT) + grep 'binary[0-9][0-9]*:' $(OUT) + grep 'vtable[0-9][0-9]*' $(OUT) diff --git a/src/test/run-make/target-specs/Makefile b/src/test/run-make/target-specs/Makefile index a352bc3a8cc..db2b253a6f1 100644 --- a/src/test/run-make/target-specs/Makefile +++ b/src/test/run-make/target-specs/Makefile @@ -1,11 +1,11 @@ -include ../tools.mk all: $(RUSTC) foo.rs --target=my-awesome-platform.json --crate-type=lib --emit=asm - grep --quiet --invert-match morestack < $(TMPDIR)/foo.s + grep -q -v morestack < $(TMPDIR)/foo.s $(RUSTC) foo.rs --target=my-invalid-platform.json 2>&1 | grep --quiet "Error loading target specification" $(RUSTC) foo.rs --target=my-incomplete-platform.json 2>&1 | grep 'Field llvm-target' RUST_TARGET_PATH=. $(RUSTC) foo.rs --target=my-awesome-platform --crate-type=lib --emit=asm RUST_TARGET_PATH=. $(RUSTC) foo.rs --target=x86_64-unknown-linux-gnu --crate-type=lib --emit=asm # The built-in target *should* override the one we have here, and thus we # should have morestack - grep --quiet morestack < $(TMPDIR)/foo.s + grep -q morestack < $(TMPDIR)/foo.s diff --git a/src/test/run-make/use-extern-for-plugins/Makefile b/src/test/run-make/use-extern-for-plugins/Makefile index 84032b45159..bdce7b7810a 100644 --- a/src/test/run-make/use-extern-for-plugins/Makefile +++ b/src/test/run-make/use-extern-for-plugins/Makefile @@ -1,5 +1,6 @@ -include ../tools.mk +ifneq ($(UNAME),OpenBSD) HOST := $(shell $(RUSTC) -vV | grep 'host:' | sed 's/host: //') ifeq ($(findstring i686,$(HOST)),i686) TARGET := $(subst i686,x86_64,$(HOST)) @@ -11,3 +12,7 @@ all: $(RUSTC) foo.rs -C extra-filename=-host $(RUSTC) bar.rs -C extra-filename=-targ --target $(TARGET) $(RUSTC) baz.rs --extern a=$(TMPDIR)/liba-targ.rlib --target $(TARGET) +else +# OpenBSD support only x86_64 architecture for now +all: +endif From dca49e06b18c63185a60e73f4ccde77ed541c079 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Wed, 4 Feb 2015 02:26:00 +0100 Subject: [PATCH 13/41] Move native thread name setting from thread_info to Thread, fixes #21911 --- src/libstd/sys/common/thread_info.rs | 4 ---- src/libstd/thread.rs | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libstd/sys/common/thread_info.rs b/src/libstd/sys/common/thread_info.rs index ce67a584a0a..92b936e74f6 100644 --- a/src/libstd/sys/common/thread_info.rs +++ b/src/libstd/sys/common/thread_info.rs @@ -56,10 +56,6 @@ pub fn stack_guard() -> uint { pub fn set(stack_bounds: (uint, uint), stack_guard: uint, thread: Thread) { THREAD_INFO.with(|c| assert!(c.borrow().is_none())); - match thread.name() { - Some(name) => unsafe { ::sys::thread::set_name(name); }, - None => {} - } THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{ stack_bounds: stack_bounds, stack_guard: stack_guard, diff --git a/src/libstd/thread.rs b/src/libstd/thread.rs index eb967c9f4e3..dda97bec925 100644 --- a/src/libstd/thread.rs +++ b/src/libstd/thread.rs @@ -280,6 +280,10 @@ impl Builder { unsafe { stack::record_os_managed_stack_bounds(my_stack_bottom, my_stack_top); } + match their_thread.name() { + Some(name) => unsafe { imp::set_name(name.as_slice()); }, + None => {} + } thread_info::set( (my_stack_bottom, my_stack_top), unsafe { imp::guard::current() }, From 34afe5e193182a0029abe1ae8258f79f4cd56cd9 Mon Sep 17 00:00:00 2001 From: Alexander Korolkov Date: Thu, 5 Feb 2015 15:04:07 +0300 Subject: [PATCH 14/41] Rename Show to Debug, String to Display Update reference.md: - derive() no longer supports Zero trait - derive() now supports Copy trait --- src/doc/reference.md | 4 ++-- src/libcore/any.rs | 2 +- src/libgetopts/lib.rs | 6 +++--- src/librustc/middle/ty.rs | 2 +- src/librustdoc/html/format.rs | 2 +- src/libserialize/json.rs | 4 ++-- src/libstd/old_path/mod.rs | 4 ++-- src/libstd/sys/windows/os.rs | 2 +- src/libsyntax/ast.rs | 1 - 9 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 9c8191a386d..999cb217f93 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -2354,8 +2354,8 @@ Supported traits for `derive` are: * `FromPrimitive`, to create an instance from a numeric primitive. * `Hash`, to iterate over the bytes in a data type. * `Rand`, to create a random instance of a data type. -* `Show`, to format a value using the `{}` formatter. -* `Zero`, to create a zero instance of a numeric data type. +* `Debug`, to format a value using the `{:?}` formatter. +* `Copy`, for "Plain Old Data" types which can be copied by simply moving bits. ### Compiler Features diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 40c2d82bf4b..462b6771b4a 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -27,7 +27,7 @@ //! # Examples //! //! Consider a situation where we want to log out a value passed to a function. -//! We know the value we're working on implements Show, but we don't know its +//! We know the value we're working on implements Debug, but we don't know its //! concrete type. We want to give special treatment to certain types: in this //! case printing out the length of String values prior to their value. //! We don't know the concrete type of our value at compile time, so we need to diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index 1b30bdf230e..72832cb9466 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -195,7 +195,7 @@ pub struct Matches { } /// The type returned when the command line does not conform to the -/// expected format. Use the `Show` implementation to output detailed +/// expected format. Use the `Debug` implementation to output detailed /// information. #[derive(Clone, PartialEq, Eq, Debug)] pub enum Fail { @@ -545,7 +545,7 @@ impl Fail { /// Convert a `Fail` enum into an error string. #[unstable(feature = "rustc_private")] #[deprecated(since = "1.0.0", - reason = "use `fmt::String` (`{}` format specifier)")] + reason = "use `fmt::Display` (`{}` format specifier)")] pub fn to_err_msg(self) -> String { self.to_string() } @@ -579,7 +579,7 @@ impl fmt::Display for Fail { /// `opt_str`, etc. to interrogate results. /// # Panics /// -/// Returns `Err(Fail)` on failure: use the `Show` implementation of `Fail` to display +/// Returns `Err(Fail)` on failure: use the `Debug` implementation of `Fail` to display /// information about it. pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result { let opts: Vec = optgrps.iter().map(|x| x.long_to_short()).collect(); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index b29a23924bb..034dbb4271d 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -70,7 +70,7 @@ use arena::TypedArena; use std::borrow::{BorrowFrom, Cow}; use std::cell::{Cell, RefCell}; use std::cmp; -use std::fmt::{self, Show}; +use std::fmt; use std::hash::{Hash, Writer, SipHasher, Hasher}; use std::mem; use std::ops; diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index cc2cf21095e..e916b63eb8d 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -10,7 +10,7 @@ //! HTML formatting module //! -//! This module contains a large number of `fmt::String` implementations for +//! This module contains a large number of `fmt::Display` implementations for //! various types in `rustdoc::clean`. These implementations all currently //! assume that HTML output is desired, although it may be possible to redesign //! them in the future to instead emit any format desired. diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index b8383577987..daa358647d8 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -1032,7 +1032,7 @@ pub fn as_pretty_json(t: &T) -> AsPrettyJson { impl Json { /// Borrow this json object as a pretty object to generate a pretty - /// representation for it via `Show`. + /// representation for it via `Display`. pub fn pretty(&self) -> PrettyJson { PrettyJson { inner: self } } @@ -3540,7 +3540,7 @@ mod tests { fn test_hashmap_with_enum_key() { use std::collections::HashMap; use json; - #[derive(RustcEncodable, Eq, Hash, PartialEq, RustcDecodable, Show)] + #[derive(RustcEncodable, Eq, Hash, PartialEq, RustcDecodable, Debug)] enum Enum { Foo, #[allow(dead_code)] diff --git a/src/libstd/old_path/mod.rs b/src/libstd/old_path/mod.rs index 0d80258d7e0..17cfe1c8297 100644 --- a/src/libstd/old_path/mod.rs +++ b/src/libstd/old_path/mod.rs @@ -228,7 +228,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// ``` fn into_vec(self) -> Vec; - /// Returns an object that implements `Show` for printing paths + /// Returns an object that implements `Display` for printing paths /// /// # Example /// @@ -244,7 +244,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { Display{ path: self, filename: false } } - /// Returns an object that implements `Show` for printing filenames + /// Returns an object that implements `Display` for printing filenames /// /// If there is no filename, nothing will be printed. /// diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index d8e3e6981df..7e684c52341 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -191,7 +191,7 @@ impl<'a> Iterator for SplitPaths<'a> { } } -#[derive(Show)] +#[derive(Debug)] pub struct JoinPathsError; pub fn join_paths(paths: I) -> Result diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 71259ff5d9a..5ec87eaf8d1 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -64,7 +64,6 @@ use parse::token; use ptr::P; use std::fmt; -use std::fmt::Show; use std::num::Int; use std::rc::Rc; use serialize::{Encodable, Decodable, Encoder, Decoder}; From 89b2e9f6f34ce00b3d6c24650922de26c8ed1e44 Mon Sep 17 00:00:00 2001 From: Piotr Czarnecki Date: Sun, 8 Feb 2015 23:26:12 +0100 Subject: [PATCH 15/41] syntax: Fix integer underflow in diagnostic Fixes #22091 --- src/libsyntax/diagnostic.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 454209bdba2..83a4d938bb5 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -518,10 +518,11 @@ fn highlight_lines(err: &mut EmitterWriter, let count = match lastc { // Most terminals have a tab stop every eight columns by default '\t' => 8 - col%8, - _ => lastc.width(false).unwrap_or(1), + _ => lastc.width(false).unwrap_or(0), }; col += count; - s.extend(::std::iter::repeat('~').take(count - 1)); + s.extend(::std::iter::repeat('~').take(count)); + let hi = cm.lookup_char_pos(sp.hi); if hi.col != lo.col { for (pos, ch) in iter { @@ -534,6 +535,12 @@ fn highlight_lines(err: &mut EmitterWriter, s.extend(::std::iter::repeat('~').take(count)); } } + + if s.len() > 1 { + // One extra squiggly is replaced by a "^" + s.pop(); + } + try!(print_maybe_styled(err, &format!("{}\n", s)[], term::attr::ForegroundColor(lvl.color()))); From 6a2bad32575c890105f3bc4914eea7c76fb85e30 Mon Sep 17 00:00:00 2001 From: we Date: Mon, 9 Feb 2015 10:00:46 +0300 Subject: [PATCH 16/41] int/uint => isize/usize in liblibc/liballoc/libarena --- src/liballoc/arc.rs | 8 ++-- src/liballoc/boxed_test.rs | 10 ++--- src/liballoc/heap.rs | 87 +++++++++++++++++++------------------- src/liballoc/lib.rs | 1 - src/liballoc/rc.rs | 18 ++++---- src/libarena/lib.rs | 75 ++++++++++++++++---------------- src/liblibc/lib.rs | 5 +-- 7 files changed, 101 insertions(+), 103 deletions(-) diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 24b4abbff4a..0617c604121 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -206,12 +206,12 @@ impl Arc { /// Get the number of weak references to this value. #[inline] #[unstable(feature = "alloc")] -pub fn weak_count(this: &Arc) -> uint { this.inner().weak.load(SeqCst) - 1 } +pub fn weak_count(this: &Arc) -> usize { this.inner().weak.load(SeqCst) - 1 } /// Get the number of strong references to this value. #[inline] #[unstable(feature = "alloc")] -pub fn strong_count(this: &Arc) -> uint { this.inner().strong.load(SeqCst) } +pub fn strong_count(this: &Arc) -> usize { this.inner().strong.load(SeqCst) } #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Arc { @@ -649,7 +649,7 @@ mod tests { let (tx, rx) = channel(); let _t = Thread::spawn(move || { - let arc_v: Arc> = rx.recv().unwrap(); + let arc_v: Arc> = rx.recv().unwrap(); assert_eq!((*arc_v)[3], 4); }); @@ -818,5 +818,5 @@ mod tests { // Make sure deriving works with Arc #[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug, Default)] - struct Foo { inner: Arc } + struct Foo { inner: Arc } } diff --git a/src/liballoc/boxed_test.rs b/src/liballoc/boxed_test.rs index 8f65b8c42c9..b7bacaa0cae 100644 --- a/src/liballoc/boxed_test.rs +++ b/src/liballoc/boxed_test.rs @@ -22,7 +22,7 @@ use std::boxed::BoxAny; #[test] fn test_owned_clone() { let a = Box::new(5); - let b: Box = a.clone(); + let b: Box = a.clone(); assert!(a == b); } @@ -31,11 +31,11 @@ struct Test; #[test] fn any_move() { - let a = Box::new(8us) as Box; + let a = Box::new(8) as Box; let b = Box::new(Test) as Box; - match a.downcast::() { - Ok(a) => { assert!(a == Box::new(8us)); } + match a.downcast::() { + Ok(a) => { assert!(a == Box::new(8)); } Err(..) => panic!() } match b.downcast::() { @@ -47,7 +47,7 @@ fn any_move() { let b = Box::new(Test) as Box; assert!(a.downcast::>().is_err()); - assert!(b.downcast::>().is_err()); + assert!(b.downcast::>().is_err()); } #[test] diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index 1d5637a6ad6..d3d86270d1e 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -21,7 +21,7 @@ use core::ptr::PtrExt; /// power of 2. The alignment must be no larger than the largest supported page /// size on the platform. #[inline] -pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 { +pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { imp::allocate(size, align) } @@ -37,7 +37,7 @@ pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 { /// create the allocation referenced by `ptr`. The `old_size` parameter may be /// any value in range_inclusive(requested_size, usable_size). #[inline] -pub unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8 { +pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 { imp::reallocate(ptr, old_size, size, align) } @@ -54,7 +54,8 @@ pub unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) /// create the allocation referenced by `ptr`. The `old_size` parameter may be /// any value in range_inclusive(requested_size, usable_size). #[inline] -pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> uint { +pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: usize, size: usize, + align: usize) -> usize { imp::reallocate_inplace(ptr, old_size, size, align) } @@ -66,14 +67,14 @@ pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint, align /// create the allocation referenced by `ptr`. The `old_size` parameter may be /// any value in range_inclusive(requested_size, usable_size). #[inline] -pub unsafe fn deallocate(ptr: *mut u8, old_size: uint, align: uint) { +pub unsafe fn deallocate(ptr: *mut u8, old_size: usize, align: usize) { imp::deallocate(ptr, old_size, align) } /// Returns the usable size of an allocation created with the specified the /// `size` and `align`. #[inline] -pub fn usable_size(size: uint, align: uint) -> uint { +pub fn usable_size(size: usize, align: usize) -> usize { imp::usable_size(size, align) } @@ -96,7 +97,7 @@ pub const EMPTY: *mut () = 0x1 as *mut (); #[cfg(not(test))] #[lang="exchange_malloc"] #[inline] -unsafe fn exchange_malloc(size: uint, align: uint) -> *mut u8 { +unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { if size == 0 { EMPTY as *mut u8 } else { @@ -109,7 +110,7 @@ unsafe fn exchange_malloc(size: uint, align: uint) -> *mut u8 { #[cfg(not(test))] #[lang="exchange_free"] #[inline] -unsafe fn exchange_free(ptr: *mut u8, old_size: uint, align: uint) { +unsafe fn exchange_free(ptr: *mut u8, old_size: usize, align: usize) { deallocate(ptr, old_size, align); } @@ -122,49 +123,49 @@ unsafe fn exchange_free(ptr: *mut u8, old_size: uint, align: uint) { target_arch = "mips", target_arch = "mipsel", target_arch = "powerpc")))] -const MIN_ALIGN: uint = 8; +const MIN_ALIGN: usize = 8; #[cfg(all(not(feature = "external_funcs"), not(feature = "external_crate"), any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")))] -const MIN_ALIGN: uint = 16; +const MIN_ALIGN: usize = 16; #[cfg(feature = "external_funcs")] mod imp { extern { - fn rust_allocate(size: uint, align: uint) -> *mut u8; - fn rust_deallocate(ptr: *mut u8, old_size: uint, align: uint); - fn rust_reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8; - fn rust_reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint, - align: uint) -> uint; - fn rust_usable_size(size: uint, align: uint) -> uint; + fn rust_allocate(size: usize, align: usize) -> *mut u8; + fn rust_deallocate(ptr: *mut u8, old_size: usize, align: usize); + fn rust_reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8; + fn rust_reallocate_inplace(ptr: *mut u8, old_size: usize, size: usize, + align: usize) -> usize; + fn rust_usable_size(size: usize, align: usize) -> usize; fn rust_stats_print(); } #[inline] - pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 { + pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { rust_allocate(size, align) } #[inline] - pub unsafe fn deallocate(ptr: *mut u8, old_size: uint, align: uint) { + pub unsafe fn deallocate(ptr: *mut u8, old_size: usize, align: usize) { rust_deallocate(ptr, old_size, align) } #[inline] - pub unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8 { + pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 { rust_reallocate(ptr, old_size, size, align) } #[inline] - pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint, - align: uint) -> uint { + pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: usize, size: usize, + align: usize) -> usize { rust_reallocate_inplace(ptr, old_size, size, align) } #[inline] - pub fn usable_size(size: uint, align: uint) -> uint { + pub fn usable_size(size: usize, align: usize) -> usize { unsafe { rust_usable_size(size, align) } } @@ -215,42 +216,42 @@ mod imp { // MALLOCX_ALIGN(a) macro #[inline(always)] - fn mallocx_align(a: uint) -> c_int { a.trailing_zeros() as c_int } + fn mallocx_align(a: usize) -> c_int { a.trailing_zeros() as c_int } #[inline(always)] - fn align_to_flags(align: uint) -> c_int { + fn align_to_flags(align: usize) -> c_int { if align <= MIN_ALIGN { 0 } else { mallocx_align(align) } } #[inline] - pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 { + pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { let flags = align_to_flags(align); je_mallocx(size as size_t, flags) as *mut u8 } #[inline] - pub unsafe fn reallocate(ptr: *mut u8, _old_size: uint, size: uint, align: uint) -> *mut u8 { + pub unsafe fn reallocate(ptr: *mut u8, _old_size: usize, size: usize, align: usize) -> *mut u8 { let flags = align_to_flags(align); je_rallocx(ptr as *mut c_void, size as size_t, flags) as *mut u8 } #[inline] - pub unsafe fn reallocate_inplace(ptr: *mut u8, _old_size: uint, size: uint, - align: uint) -> uint { + pub unsafe fn reallocate_inplace(ptr: *mut u8, _old_size: usize, size: usize, + align: usize) -> usize { let flags = align_to_flags(align); - je_xallocx(ptr as *mut c_void, size as size_t, 0, flags) as uint + je_xallocx(ptr as *mut c_void, size as size_t, 0, flags) as usize } #[inline] - pub unsafe fn deallocate(ptr: *mut u8, old_size: uint, align: uint) { + pub unsafe fn deallocate(ptr: *mut u8, old_size: usize, align: usize) { let flags = align_to_flags(align); je_sdallocx(ptr as *mut c_void, old_size as size_t, flags) } #[inline] - pub fn usable_size(size: uint, align: uint) -> uint { + pub fn usable_size(size: usize, align: usize) -> usize { let flags = align_to_flags(align); - unsafe { je_nallocx(size as size_t, flags) as uint } + unsafe { je_nallocx(size as size_t, flags) as usize } } pub fn stats_print() { @@ -277,7 +278,7 @@ mod imp { } #[inline] - pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 { + pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { if align <= MIN_ALIGN { libc::malloc(size as libc::size_t) as *mut u8 } else { @@ -294,7 +295,7 @@ mod imp { } #[inline] - pub unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8 { + pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 { if align <= MIN_ALIGN { libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8 } else { @@ -306,18 +307,18 @@ mod imp { } #[inline] - pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: uint, _size: uint, - _align: uint) -> uint { + pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: usize, _size: usize, + _align: usize) -> usize { old_size } #[inline] - pub unsafe fn deallocate(ptr: *mut u8, _old_size: uint, _align: uint) { + pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, _align: usize) { libc::free(ptr as *mut libc::c_void) } #[inline] - pub fn usable_size(size: uint, _align: uint) -> uint { + pub fn usable_size(size: usize, _align: usize) -> usize { size } @@ -341,7 +342,7 @@ mod imp { } #[inline] - pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 { + pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { if align <= MIN_ALIGN { libc::malloc(size as size_t) as *mut u8 } else { @@ -350,7 +351,7 @@ mod imp { } #[inline] - pub unsafe fn reallocate(ptr: *mut u8, _old_size: uint, size: uint, align: uint) -> *mut u8 { + pub unsafe fn reallocate(ptr: *mut u8, _old_size: usize, size: usize, align: usize) -> *mut u8 { if align <= MIN_ALIGN { libc::realloc(ptr as *mut c_void, size as size_t) as *mut u8 } else { @@ -359,13 +360,13 @@ mod imp { } #[inline] - pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: uint, _size: uint, - _align: uint) -> uint { + pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: usize, _size: usize, + _align: usize) -> usize { old_size } #[inline] - pub unsafe fn deallocate(ptr: *mut u8, _old_size: uint, align: uint) { + pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, align: usize) { if align <= MIN_ALIGN { libc::free(ptr as *mut libc::c_void) } else { @@ -374,7 +375,7 @@ mod imp { } #[inline] - pub fn usable_size(size: uint, _align: uint) -> uint { + pub fn usable_size(size: usize, _align: usize) -> usize { size } diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 81391fd63eb..0e6266f9cbc 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -70,7 +70,6 @@ #![feature(lang_items, unsafe_destructor)] #![feature(box_syntax)] #![feature(optin_builtin_traits)] -#![feature(int_uint)] #![feature(unboxed_closures)] #![feature(core)] #![feature(hash)] diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 54ff4c18654..ab3c0901bc9 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -40,7 +40,7 @@ //! } //! //! struct Gadget { -//! id: int, +//! id: i32, //! owner: Rc //! // ...other fields //! } @@ -99,7 +99,7 @@ //! } //! //! struct Gadget { -//! id: int, +//! id: i32, //! owner: Rc //! // ...other fields //! } @@ -166,8 +166,8 @@ use heap::deallocate; struct RcBox { value: T, - strong: Cell, - weak: Cell + strong: Cell, + weak: Cell } /// An immutable reference-counted pointer type. @@ -233,12 +233,12 @@ impl Rc { /// Get the number of weak references to this value. #[inline] #[unstable(feature = "alloc")] -pub fn weak_count(this: &Rc) -> uint { this.weak() - 1 } +pub fn weak_count(this: &Rc) -> usize { this.weak() - 1 } /// Get the number of strong references to this value. #[inline] #[unstable(feature = "alloc")] -pub fn strong_count(this: &Rc) -> uint { this.strong() } +pub fn strong_count(this: &Rc) -> usize { this.strong() } /// Returns true if there are no other `Rc` or `Weak` values that share the same inner value. /// @@ -447,7 +447,7 @@ impl Default for Rc { /// use std::rc::Rc; /// use std::default::Default; /// - /// let x: Rc = Default::default(); + /// let x: Rc = Default::default(); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -750,7 +750,7 @@ trait RcBoxPtr { fn inner(&self) -> &RcBox; #[inline] - fn strong(&self) -> uint { self.inner().strong.get() } + fn strong(&self) -> usize { self.inner().strong.get() } #[inline] fn inc_strong(&self) { self.inner().strong.set(self.strong() + 1); } @@ -759,7 +759,7 @@ trait RcBoxPtr { fn dec_strong(&self) { self.inner().strong.set(self.strong() - 1); } #[inline] - fn weak(&self) -> uint { self.inner().weak.get() } + fn weak(&self) -> usize { self.inner().weak.get() } #[inline] fn inc_weak(&self) { self.inner().weak.set(self.weak() + 1); } diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 62d103ae06a..223c5111f8f 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -31,7 +31,6 @@ #![feature(alloc)] #![feature(box_syntax)] #![feature(core)] -#![feature(int_uint)] #![feature(staged_api)] #![feature(unboxed_closures)] #![feature(unsafe_destructor)] @@ -55,12 +54,12 @@ use std::rt::heap::{allocate, deallocate}; #[derive(Clone, PartialEq)] struct Chunk { data: Rc>>, - fill: Cell, + fill: Cell, is_copy: Cell, } impl Chunk { - fn capacity(&self) -> uint { + fn capacity(&self) -> usize { self.data.borrow().capacity() } @@ -105,7 +104,7 @@ impl Arena { } /// Allocates a new Arena with `initial_size` bytes preallocated. - pub fn new_with_size(initial_size: uint) -> Arena { + pub fn new_with_size(initial_size: usize) -> Arena { Arena { head: RefCell::new(chunk(initial_size, false)), copy_head: RefCell::new(chunk(initial_size, true)), @@ -114,7 +113,7 @@ impl Arena { } } -fn chunk(size: uint, is_copy: bool) -> Chunk { +fn chunk(size: usize, is_copy: bool) -> Chunk { Chunk { data: Rc::new(RefCell::new(Vec::with_capacity(size))), fill: Cell::new(0), @@ -137,7 +136,7 @@ impl Drop for Arena { } #[inline] -fn round_up(base: uint, align: uint) -> uint { +fn round_up(base: usize, align: usize) -> usize { (base.checked_add(align - 1)).unwrap() & !(align - 1) } @@ -149,7 +148,7 @@ unsafe fn destroy_chunk(chunk: &Chunk) { let fill = chunk.fill.get(); while idx < fill { - let tydesc_data: *const uint = mem::transmute(buf.offset(idx as int)); + let tydesc_data: *const usize = mem::transmute(buf.offset(idx as isize)); let (tydesc, is_done) = un_bitpack_tydesc_ptr(*tydesc_data); let (size, align) = ((*tydesc).size, (*tydesc).align); @@ -160,7 +159,7 @@ unsafe fn destroy_chunk(chunk: &Chunk) { //debug!("freeing object: idx = {}, size = {}, align = {}, done = {}", // start, size, align, is_done); if is_done { - ((*tydesc).drop_glue)(buf.offset(start as int) as *const i8); + ((*tydesc).drop_glue)(buf.offset(start as isize) as *const i8); } // Find where the next tydesc lives @@ -173,21 +172,21 @@ unsafe fn destroy_chunk(chunk: &Chunk) { // is necessary in order to properly do cleanup if a panic occurs // during an initializer. #[inline] -fn bitpack_tydesc_ptr(p: *const TyDesc, is_done: bool) -> uint { - p as uint | (is_done as uint) +fn bitpack_tydesc_ptr(p: *const TyDesc, is_done: bool) -> usize { + p as usize | (is_done as usize) } #[inline] -fn un_bitpack_tydesc_ptr(p: uint) -> (*const TyDesc, bool) { +fn un_bitpack_tydesc_ptr(p: usize) -> (*const TyDesc, bool) { ((p & !1) as *const TyDesc, p & 1 == 1) } impl Arena { - fn chunk_size(&self) -> uint { + fn chunk_size(&self) -> usize { self.copy_head.borrow().capacity() } // Functions for the POD part of the arena - fn alloc_copy_grow(&self, n_bytes: uint, align: uint) -> *const u8 { + fn alloc_copy_grow(&self, n_bytes: usize, align: usize) -> *const u8 { // Allocate a new chunk. let new_min_chunk_size = cmp::max(n_bytes, self.chunk_size()); self.chunks.borrow_mut().push(self.copy_head.borrow().clone()); @@ -199,7 +198,7 @@ impl Arena { } #[inline] - fn alloc_copy_inner(&self, n_bytes: uint, align: uint) -> *const u8 { + fn alloc_copy_inner(&self, n_bytes: usize, align: usize) -> *const u8 { let start = round_up(self.copy_head.borrow().fill.get(), align); let end = start + n_bytes; @@ -211,7 +210,7 @@ impl Arena { copy_head.fill.set(end); unsafe { - copy_head.as_ptr().offset(start as int) + copy_head.as_ptr().offset(start as isize) } } @@ -227,8 +226,8 @@ impl Arena { } // Functions for the non-POD part of the arena - fn alloc_noncopy_grow(&self, n_bytes: uint, - align: uint) -> (*const u8, *const u8) { + fn alloc_noncopy_grow(&self, n_bytes: usize, + align: usize) -> (*const u8, *const u8) { // Allocate a new chunk. let new_min_chunk_size = cmp::max(n_bytes, self.chunk_size()); self.chunks.borrow_mut().push(self.head.borrow().clone()); @@ -240,8 +239,8 @@ impl Arena { } #[inline] - fn alloc_noncopy_inner(&self, n_bytes: uint, - align: uint) -> (*const u8, *const u8) { + fn alloc_noncopy_inner(&self, n_bytes: usize, + align: usize) -> (*const u8, *const u8) { // Be careful to not maintain any `head` borrows active, because // `alloc_noncopy_grow` borrows it mutably. let (start, end, tydesc_start, head_capacity) = { @@ -265,7 +264,7 @@ impl Arena { unsafe { let buf = head.as_ptr(); - return (buf.offset(tydesc_start as int), buf.offset(start as int)); + return (buf.offset(tydesc_start as isize), buf.offset(start as isize)); } } @@ -276,7 +275,7 @@ impl Arena { let (ty_ptr, ptr) = self.alloc_noncopy_inner(mem::size_of::(), mem::min_align_of::()); - let ty_ptr = ty_ptr as *mut uint; + let ty_ptr = ty_ptr as *mut usize; let ptr = ptr as *mut T; // Write in our tydesc along with a bit indicating that it // has *not* been initialized yet. @@ -320,7 +319,7 @@ fn test_arena_destructors() { #[test] fn test_arena_alloc_nested() { - struct Inner { value: uint } + struct Inner { value: usize } struct Outer<'a> { inner: &'a Inner } let arena = Arena::new(); @@ -343,10 +342,10 @@ fn test_arena_destructors_fail() { arena.alloc(|| { Rc::new(i) }); // Allocate something with funny size and alignment, to keep // things interesting. - arena.alloc(|| { [0u8, 1u8, 2u8] }); + arena.alloc(|| { [0u8, 1, 2] }); } // Now, panic while allocating - arena.alloc::, _>(|| { + arena.alloc::, _>(|| { panic!(); }); } @@ -373,12 +372,12 @@ struct TypedArenaChunk { next: *mut TypedArenaChunk, /// The number of elements that this chunk can hold. - capacity: uint, + capacity: usize, // Objects follow here, suitably aligned. } -fn calculate_size(capacity: uint) -> uint { +fn calculate_size(capacity: usize) -> usize { let mut size = mem::size_of::>(); size = round_up(size, mem::min_align_of::()); let elem_size = mem::size_of::(); @@ -389,7 +388,7 @@ fn calculate_size(capacity: uint) -> uint { impl TypedArenaChunk { #[inline] - unsafe fn new(next: *mut TypedArenaChunk, capacity: uint) + unsafe fn new(next: *mut TypedArenaChunk, capacity: usize) -> *mut TypedArenaChunk { let size = calculate_size::(capacity); let chunk = allocate(size, mem::min_align_of::>()) @@ -403,13 +402,13 @@ impl TypedArenaChunk { /// Destroys this arena chunk. If the type descriptor is supplied, the /// drop glue is called; otherwise, drop glue is not called. #[inline] - unsafe fn destroy(&mut self, len: uint) { + unsafe fn destroy(&mut self, len: usize) { // Destroy all the allocated objects. if intrinsics::needs_drop::() { let mut start = self.start(); for _ in 0..len { ptr::read(start as *const T); // run the destructor on the pointer - start = start.offset(mem::size_of::() as int) + start = start.offset(mem::size_of::() as isize) } } @@ -429,7 +428,7 @@ impl TypedArenaChunk { fn start(&self) -> *const u8 { let this: *const TypedArenaChunk = self; unsafe { - mem::transmute(round_up(this.offset(1) as uint, + mem::transmute(round_up(this.offset(1) as usize, mem::min_align_of::())) } } @@ -439,7 +438,7 @@ impl TypedArenaChunk { fn end(&self) -> *const u8 { unsafe { let size = mem::size_of::().checked_mul(self.capacity).unwrap(); - self.start().offset(size as int) + self.start().offset(size as isize) } } } @@ -454,7 +453,7 @@ impl TypedArena { /// Creates a new `TypedArena` with preallocated space for the given number of /// objects. #[inline] - pub fn with_capacity(capacity: uint) -> TypedArena { + pub fn with_capacity(capacity: usize) -> TypedArena { unsafe { let chunk = TypedArenaChunk::::new(ptr::null_mut(), capacity); TypedArena { @@ -501,8 +500,8 @@ impl Drop for TypedArena { fn drop(&mut self) { unsafe { // Determine how much was filled. - let start = self.first.borrow().as_ref().unwrap().start() as uint; - let end = self.ptr.get() as uint; + let start = self.first.borrow().as_ref().unwrap().start() as usize; + let end = self.ptr.get() as usize; let diff = (end - start) / mem::size_of::(); // Pass that to the `destroy` method. @@ -519,9 +518,9 @@ mod tests { #[allow(dead_code)] struct Point { - x: int, - y: int, - z: int, + x: i32, + y: i32, + z: i32, } #[test] @@ -576,7 +575,7 @@ mod tests { #[allow(dead_code)] struct Noncopy { string: String, - array: Vec, + array: Vec, } #[test] diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index 38d5c5eb27a..d95d0863ca8 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -15,7 +15,6 @@ #![cfg_attr(not(feature = "cargo-build"), feature(staged_api))] #![cfg_attr(not(feature = "cargo-build"), staged_api)] #![cfg_attr(not(feature = "cargo-build"), feature(core))] -#![feature(int_uint)] #![feature(no_std)] #![no_std] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", @@ -1905,7 +1904,7 @@ pub mod types { #[repr(C)] #[derive(Copy)] pub struct WSAPROTOCOLCHAIN { pub ChainLen: c_int, - pub ChainEntries: [DWORD; MAX_PROTOCOL_CHAIN as uint], + pub ChainEntries: [DWORD; MAX_PROTOCOL_CHAIN as usize], } pub type LPWSAPROTOCOLCHAIN = *mut WSAPROTOCOLCHAIN; @@ -1931,7 +1930,7 @@ pub mod types { pub iSecurityScheme: c_int, pub dwMessageSize: DWORD, pub dwProviderReserved: DWORD, - pub szProtocol: [u8; (WSAPROTOCOL_LEN as uint) + 1us], + pub szProtocol: [u8; WSAPROTOCOL_LEN as usize + 1], } pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO; From 97a9507232a714b8c9a4341901002f0b761210db Mon Sep 17 00:00:00 2001 From: Michael Budde Date: Mon, 9 Feb 2015 12:56:24 +0100 Subject: [PATCH 17/41] Fix links to module-level documentation in `std::cell` Replace links to `../index.html` with `index.html` as they are linking to the `std` module and not `std::cell` as intended. --- src/libcore/cell.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index c82d8c531d2..050b34508ff 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -151,7 +151,7 @@ use option::Option::{None, Some}; /// A mutable memory location that admits only `Copy` data. /// -/// See the [module-level documentation](../index.html) for more. +/// See the [module-level documentation](index.html) for more. #[stable(feature = "rust1", since = "1.0.0")] pub struct Cell { value: UnsafeCell, @@ -259,7 +259,7 @@ impl PartialEq for Cell { /// A mutable memory location with dynamically checked borrow rules /// -/// See the [module-level documentation](../index.html) for more. +/// See the [module-level documentation](index.html) for more. #[stable(feature = "rust1", since = "1.0.0")] pub struct RefCell { value: UnsafeCell, @@ -534,7 +534,7 @@ impl<'b> Clone for BorrowRef<'b> { /// Wraps a borrowed reference to a value in a `RefCell` box. /// A wrapper type for an immutably borrowed value from a `RefCell`. /// -/// See the [module-level documentation](../index.html) for more. +/// See the [module-level documentation](index.html) for more. #[stable(feature = "rust1", since = "1.0.0")] pub struct Ref<'b, T:'b> { // FIXME #12808: strange name to try to avoid interfering with @@ -595,7 +595,7 @@ impl<'b> BorrowRefMut<'b> { /// A wrapper type for a mutably borrowed value from a `RefCell`. /// -/// See the [module-level documentation](../index.html) for more. +/// See the [module-level documentation](index.html) for more. #[stable(feature = "rust1", since = "1.0.0")] pub struct RefMut<'b, T:'b> { // FIXME #12808: strange name to try to avoid interfering with From 0110f5e03c67d7a3590c7c86f50f5546d75f27b1 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Mon, 9 Feb 2015 09:01:15 -0800 Subject: [PATCH 18/41] syntax::fold: Allow removing attributes --- src/libsyntax/ext/expand.rs | 4 ++-- src/libsyntax/fold.rs | 32 ++++++++++++++++++-------------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index fd7593f2a3b..131bbc41005 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -844,7 +844,7 @@ fn expand_arm(arm: ast::Arm, fld: &mut MacroExpander) -> ast::Arm { arm.guard.map(|g| fld.fold_expr(rename_fld.fold_expr(g))); let rewritten_body = fld.fold_expr(rename_fld.fold_expr(arm.body)); ast::Arm { - attrs: arm.attrs.move_map(|x| fld.fold_attribute(x)), + attrs: fold::fold_attrs(arm.attrs, fld), pats: rewritten_pats, guard: rewritten_guard, body: rewritten_body, @@ -1273,7 +1273,7 @@ fn expand_method(m: P, fld: &mut MacroExpander) -> SmallVector Attribute { + fn fold_attribute(&mut self, at: Attribute) -> Option { noop_fold_attribute(at, self) } @@ -373,9 +373,13 @@ pub fn noop_fold_view_path(view_path: P, fld: &mut T) -> P< }) } +pub fn fold_attrs(attrs: Vec, fld: &mut T) -> Vec { + attrs.into_iter().flat_map(|x| fld.fold_attribute(x).into_iter()).collect() +} + pub fn noop_fold_arm(Arm {attrs, pats, guard, body}: Arm, fld: &mut T) -> Arm { Arm { - attrs: attrs.move_map(|x| fld.fold_attribute(x)), + attrs: fold_attrs(attrs, fld), pats: pats.move_map(|x| fld.fold_pat(x)), guard: guard.map(|x| fld.fold_expr(x)), body: fld.fold_expr(body), @@ -475,7 +479,7 @@ pub fn noop_fold_variant(v: P, fld: &mut T) -> P { node: Variant_ { id: fld.new_id(id), name: name, - attrs: attrs.move_map(|x| fld.fold_attribute(x)), + attrs: fold_attrs(attrs, fld), kind: match kind { TupleVariantKind(variant_args) => { TupleVariantKind(variant_args.move_map(|x| @@ -553,9 +557,9 @@ pub fn noop_fold_local(l: P, fld: &mut T) -> P { }) } -pub fn noop_fold_attribute(at: Attribute, fld: &mut T) -> Attribute { +pub fn noop_fold_attribute(at: Attribute, fld: &mut T) -> Option { let Spanned {node: Attribute_ {id, style, value, is_sugared_doc}, span} = at; - Spanned { + Some(Spanned { node: Attribute_ { id: id, style: style, @@ -563,7 +567,7 @@ pub fn noop_fold_attribute(at: Attribute, fld: &mut T) -> Attribute { is_sugared_doc: is_sugared_doc }, span: fld.new_span(span) - } + }) } pub fn noop_fold_explicit_self_underscore(es: ExplicitSelf_, fld: &mut T) @@ -843,8 +847,8 @@ pub fn noop_fold_typedef(t: Typedef, folder: &mut T) where T: Folder { let new_id = folder.new_id(t.id); let new_span = folder.new_span(t.span); - let new_attrs = t.attrs.iter().map(|attr| { - folder.fold_attribute((*attr).clone()) + let new_attrs = t.attrs.iter().flat_map(|attr| { + folder.fold_attribute((*attr).clone()).into_iter() }).collect(); let new_ident = folder.fold_ident(t.ident); let new_type = folder.fold_ty(t.typ); @@ -864,7 +868,7 @@ pub fn noop_fold_associated_type(at: AssociatedType, folder: &mut T) { let new_attrs = at.attrs .iter() - .map(|attr| folder.fold_attribute((*attr).clone())) + .flat_map(|attr| folder.fold_attribute((*attr).clone()).into_iter()) .collect(); let new_param = folder.fold_ty_param(at.ty_param); ast::AssociatedType { @@ -906,7 +910,7 @@ pub fn noop_fold_struct_field(f: StructField, fld: &mut T) -> StructF id: fld.new_id(id), kind: kind, ty: fld.fold_ty(ty), - attrs: attrs.move_map(|a| fld.fold_attribute(a)) + attrs: fold_attrs(attrs, fld), }, span: fld.new_span(span) } @@ -1069,7 +1073,7 @@ pub fn noop_fold_type_method(m: TypeMethod, fld: &mut T) -> TypeMetho TypeMethod { id: fld.new_id(id), ident: fld.fold_ident(ident), - attrs: attrs.move_map(|a| fld.fold_attribute(a)), + attrs: fold_attrs(attrs, fld), unsafety: unsafety, abi: abi, decl: fld.fold_fn_decl(decl), @@ -1151,7 +1155,7 @@ pub fn noop_fold_item_simple(Item {id, ident, attrs, node, vis, span} Item { id: id, ident: folder.fold_ident(ident), - attrs: attrs.move_map(|e| folder.fold_attribute(e)), + attrs: fold_attrs(attrs, folder), node: node, vis: vis, span: folder.new_span(span) @@ -1162,7 +1166,7 @@ pub fn noop_fold_foreign_item(ni: P, folder: &mut T) -> ni.map(|ForeignItem {id, ident, attrs, node, span, vis}| ForeignItem { id: folder.new_id(id), ident: folder.fold_ident(ident), - attrs: attrs.move_map(|x| folder.fold_attribute(x)), + attrs: fold_attrs(attrs, folder), node: match node { ForeignItemFn(fdec, generics) => { ForeignItemFn(folder.fold_fn_decl(fdec), folder.fold_generics(generics)) @@ -1181,7 +1185,7 @@ pub fn noop_fold_foreign_item(ni: P, folder: &mut T) -> pub fn noop_fold_method(m: P, folder: &mut T) -> SmallVector> { SmallVector::one(m.map(|Method {id, attrs, node, span}| Method { id: folder.new_id(id), - attrs: attrs.move_map(|a| folder.fold_attribute(a)), + attrs: fold_attrs(attrs, folder), node: match node { MethDecl(ident, generics, From a6e8496601767e59acce010531f8e4dfb40c7c0a Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Mon, 9 Feb 2015 19:30:22 +0200 Subject: [PATCH 19/41] Deduplicate --crate-type arguments Crate types from multiple sources appear to be deduplicated properly, but not deduplicated if they come from the command line arguments. At worst, this used to cause compiler failures when `--crate-type=lib,rlib` (the same as `--crate-type=rlib,rlib`, at least at the time of this commit) is provided and generate the output multiple times otherwise. --- src/librustc/session/config.rs | 4 +++- src/test/run-make/duplicate-output-flavors/Makefile | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index efd2392e453..6d09b8b09e7 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1061,7 +1061,9 @@ pub fn parse_crate_types_from_list(list_list: Vec) -> Result Date: Mon, 9 Feb 2015 09:29:21 -0800 Subject: [PATCH 20/41] Process cfg_attr right before stripping cfg Fixes #22070. Fixes #19372. --- src/libsyntax/config.rs | 49 ++++++++++++++++++++++- src/libsyntax/ext/base.rs | 2 - src/libsyntax/ext/cfg_attr.rs | 34 ---------------- src/libsyntax/lib.rs | 1 - src/test/compile-fail/cfg-attr-cfg-2.rs | 18 +++++++++ src/test/compile-fail/cfg-attr-crate-2.rs | 17 ++++++++ src/test/run-pass/cfg-attr-cfg.rs | 15 +++++++ src/test/run-pass/cfg-attr-crate.rs | 15 +++++++ 8 files changed, 113 insertions(+), 38 deletions(-) delete mode 100644 src/libsyntax/ext/cfg_attr.rs create mode 100644 src/test/compile-fail/cfg-attr-cfg-2.rs create mode 100644 src/test/compile-fail/cfg-attr-crate-2.rs create mode 100644 src/test/run-pass/cfg-attr-cfg.rs create mode 100644 src/test/run-pass/cfg-attr-crate.rs diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index eb845e463a0..7ca0591be50 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -12,7 +12,7 @@ use attr::AttrMetaMethods; use diagnostic::SpanHandler; use fold::Folder; use {ast, fold, attr}; -use codemap::Spanned; +use codemap::{Spanned, respan}; use ptr::P; use util::small_vector::SmallVector; @@ -26,6 +26,7 @@ struct Context where F: FnMut(&[ast::Attribute]) -> bool { // Support conditional compilation by transforming the AST, stripping out // any items that do not belong in the current configuration pub fn strip_unconfigured_items(diagnostic: &SpanHandler, krate: ast::Crate) -> ast::Crate { + let krate = process_cfg_attr(diagnostic, krate); let config = krate.config.clone(); strip_items(krate, |attrs| in_cfg(diagnostic, &config, attrs)) } @@ -281,3 +282,49 @@ fn in_cfg(diagnostic: &SpanHandler, cfg: &[P], attrs: &[ast::Attr attr::cfg_matches(diagnostic, cfg, &*mis[0]) }) } + +struct CfgAttrFolder<'a> { + diag: &'a SpanHandler, + config: ast::CrateConfig, +} + +// Process `#[cfg_attr]`. +fn process_cfg_attr(diagnostic: &SpanHandler, krate: ast::Crate) -> ast::Crate { + let mut fld = CfgAttrFolder { + diag: diagnostic, + config: krate.config.clone(), + }; + fld.fold_crate(krate) +} + +impl<'a> fold::Folder for CfgAttrFolder<'a> { + fn fold_attribute(&mut self, attr: ast::Attribute) -> Option { + if !attr.check_name("cfg_attr") { + return fold::noop_fold_attribute(attr, self); + } + + let (cfg, mi) = match attr.meta_item_list() { + Some([ref cfg, ref mi]) => (cfg, mi), + _ => { + self.diag.span_err(attr.span, "expected `#[cfg_attr(, )]`"); + return None; + } + }; + + if attr::cfg_matches(self.diag, &self.config[], &cfg) { + Some(respan(mi.span, ast::Attribute_ { + id: attr::mk_attr_id(), + style: attr.node.style, + value: mi.clone(), + is_sugared_doc: false, + })) + } else { + None + } + } + + // Need the ability to run pre-expansion. + fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { + fold::noop_fold_mac(mac, self) + } +} diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 778b2cabea6..64ae6162ef4 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -528,8 +528,6 @@ fn initial_syntax_expander_table(ecfg: &expand::ExpansionConfig) -> SyntaxEnv { syntax_expanders.insert(intern("cfg"), builtin_normal_expander( ext::cfg::expand_cfg)); - syntax_expanders.insert(intern("cfg_attr"), - Modifier(box ext::cfg_attr::expand)); syntax_expanders.insert(intern("trace_macros"), builtin_normal_expander( ext::trace_macros::expand_trace_macros)); diff --git a/src/libsyntax/ext/cfg_attr.rs b/src/libsyntax/ext/cfg_attr.rs deleted file mode 100644 index 72eaa3e47be..00000000000 --- a/src/libsyntax/ext/cfg_attr.rs +++ /dev/null @@ -1,34 +0,0 @@ -// 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. - -use ast; -use attr; -use codemap::Span; -use ext::base::ExtCtxt; -use ext::build::AstBuilder; -use ptr::P; - -pub fn expand(cx: &mut ExtCtxt, sp: Span, mi: &ast::MetaItem, it: P) -> P { - let (cfg, attr) = match mi.node { - ast::MetaList(_, ref mis) if mis.len() == 2 => (&mis[0], &mis[1]), - _ => { - cx.span_err(sp, "expected `#[cfg_attr(, )]`"); - return it; - } - }; - - let mut out = (*it).clone(); - if attr::cfg_matches(&cx.parse_sess.span_diagnostic, &cx.cfg, &**cfg) { - out.attrs.push(cx.attribute(attr.span, attr.clone())); - } - - P(out) -} - diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 08e795ef80d..41850ada3e6 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -96,7 +96,6 @@ pub mod ext { pub mod base; pub mod build; pub mod cfg; - pub mod cfg_attr; pub mod concat; pub mod concat_idents; pub mod deriving; diff --git a/src/test/compile-fail/cfg-attr-cfg-2.rs b/src/test/compile-fail/cfg-attr-cfg-2.rs new file mode 100644 index 00000000000..b71a3be5dce --- /dev/null +++ b/src/test/compile-fail/cfg-attr-cfg-2.rs @@ -0,0 +1,18 @@ +// 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: main function not found +// compile-flags: --cfg foo + +// main is conditionally compiled, but the conditional compilation +// is conditional too! + +#[cfg_attr(foo, cfg(bar))] +fn main() { } diff --git a/src/test/compile-fail/cfg-attr-crate-2.rs b/src/test/compile-fail/cfg-attr-crate-2.rs new file mode 100644 index 00000000000..4867dd8d0b4 --- /dev/null +++ b/src/test/compile-fail/cfg-attr-crate-2.rs @@ -0,0 +1,17 @@ +// 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: --cfg broken + +// https://github.com/rust-lang/rust/issues/21833#issuecomment-72353044 + +#![cfg_attr(broken, no_std)] //~ ERROR no_std is experimental + +fn main() { } diff --git a/src/test/run-pass/cfg-attr-cfg.rs b/src/test/run-pass/cfg-attr-cfg.rs new file mode 100644 index 00000000000..09ab7019486 --- /dev/null +++ b/src/test/run-pass/cfg-attr-cfg.rs @@ -0,0 +1,15 @@ +// 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. + +// main is conditionally compiled, but the conditional compilation +// is conditional too! + +#[cfg_attr(foo, cfg(bar))] +fn main() { } diff --git a/src/test/run-pass/cfg-attr-crate.rs b/src/test/run-pass/cfg-attr-crate.rs new file mode 100644 index 00000000000..e6bd8afad28 --- /dev/null +++ b/src/test/run-pass/cfg-attr-crate.rs @@ -0,0 +1,15 @@ +// 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. + +// https://github.com/rust-lang/rust/issues/21833#issuecomment-72353044 + +#![cfg_attr(not_used, no_std)] + +fn main() { } From d9393c21d788347a993108021e8395d0ff992d03 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 6 Feb 2015 17:59:56 +0100 Subject: [PATCH 21/41] Given ` as Box`, infer that `Box<_>` is expected type for ``. --- src/librustc_typeck/check/vtable.rs | 109 ++++++++++++---------------- 1 file changed, 47 insertions(+), 62 deletions(-) diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs index 19287f19d8d..00f6c6109fa 100644 --- a/src/librustc_typeck/check/vtable.rs +++ b/src/librustc_typeck/check/vtable.rs @@ -9,11 +9,11 @@ // except according to those terms. use check::{FnCtxt, structurally_resolved_type}; +use check::demand; use middle::traits::{self, ObjectSafetyViolation, MethodViolationCode}; use middle::traits::{Obligation, ObligationCause}; use middle::traits::report_fulfillment_errors; use middle::ty::{self, Ty, AsPredicate}; -use middle::infer; use syntax::ast; use syntax::codemap::Span; use util::nodemap::FnvHashSet; @@ -24,71 +24,63 @@ pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, source_expr: &ast::Expr, target_object_ty: Ty<'tcx>) { + let tcx = fcx.tcx(); debug!("check_object_cast(cast_expr={}, target_object_ty={})", - cast_expr.repr(fcx.tcx()), - target_object_ty.repr(fcx.tcx())); + cast_expr.repr(tcx), + target_object_ty.repr(tcx)); // Look up vtables for the type we're casting to, // passing in the source and target type. The source // must be a pointer type suitable to the object sigil, // e.g.: `&x as &Trait` or `box x as Box` - let source_ty = fcx.expr_ty(source_expr); - let source_ty = structurally_resolved_type(fcx, source_expr.span, source_ty); - debug!("source_ty={}", source_ty.repr(fcx.tcx())); - match (&source_ty.sty, &target_object_ty.sty) { - (&ty::ty_uniq(referent_ty), &ty::ty_uniq(object_trait_ty)) => { - let object_trait = object_trait(&object_trait_ty); - // Ensure that if ~T is cast to ~Trait, then T : Trait - push_cast_obligation(fcx, cast_expr, object_trait, referent_ty); - check_object_safety(fcx.tcx(), object_trait, source_expr.span); + // First, construct a fresh type that we can feed into `` + // within ` as ` to inform type inference (e.g. to + // tell it that we are expecting a `Box<_>` or an `&_`). + let fresh_ty = fcx.infcx().next_ty_var(); + let (object_trait_ty, source_expected_ty) = match target_object_ty.sty { + ty::ty_uniq(object_trait_ty) => { + (object_trait_ty, ty::mk_uniq(fcx.tcx(), fresh_ty)) } - - (&ty::ty_rptr(referent_region, ty::mt { ty: referent_ty, - mutbl: referent_mutbl }), - &ty::ty_rptr(target_region, ty::mt { ty: object_trait_ty, - mutbl: target_mutbl })) => - { - let object_trait = object_trait(&object_trait_ty); - if !mutability_allowed(referent_mutbl, target_mutbl) { - span_err!(fcx.tcx().sess, source_expr.span, E0188, - "types differ in mutability"); - } else { - // Ensure that if &'a T is cast to &'b Trait, then T : Trait - push_cast_obligation(fcx, cast_expr, - object_trait, - referent_ty); - - // Ensure that if &'a T is cast to &'b Trait, then 'b <= 'a - infer::mk_subr(fcx.infcx(), - infer::RelateObjectBound(source_expr.span), - *target_region, - *referent_region); - - check_object_safety(fcx.tcx(), object_trait, source_expr.span); - } + ty::ty_rptr(target_region, ty::mt { ty: object_trait_ty, + mutbl: target_mutbl }) => { + (object_trait_ty, + ty::mk_rptr(fcx.tcx(), + target_region, ty::mt { ty: fresh_ty, + mutbl: target_mutbl })) } - - (_, &ty::ty_uniq(..)) => { - span_err!(fcx.ccx.tcx.sess, source_expr.span, E0189, - "can only cast a boxed pointer \ - to a boxed object, not a {}", - ty::ty_sort_string(fcx.tcx(), source_ty)); - } - - (_, &ty::ty_rptr(..)) => { - span_err!(fcx.ccx.tcx.sess, source_expr.span, E0190, - "can only cast a &-pointer \ - to an &-object, not a {}", - ty::ty_sort_string(fcx.tcx(), source_ty)); - } - _ => { - fcx.tcx().sess.span_bug( - source_expr.span, - "expected object type"); + fcx.tcx().sess.span_bug(source_expr.span, "expected object type"); } - } + }; + + let source_ty = fcx.expr_ty(source_expr); + debug!("check_object_cast pre unify source_ty={}", source_ty.repr(tcx)); + + // This ensures that the source_ty <: source_expected_ty, which + // will ensure e.g. that &'a T <: &'b T when doing `&'a T as &'b Trait` + // + // FIXME (pnkfelix): do we need to use suptype_with_fn in order to + // override the error message emitted when the types do not work + // out in the manner desired? + demand::suptype(fcx, source_expr.span, source_expected_ty, source_ty); + + debug!("check_object_cast postunify source_ty={}", source_ty.repr(tcx)); + let source_ty = structurally_resolved_type(fcx, source_expr.span, source_ty); + debug!("check_object_cast resolveto source_ty={}", source_ty.repr(tcx)); + + let object_trait = object_trait(&object_trait_ty); + + let referent_ty = match source_ty.sty { + ty::ty_uniq(ty) => ty, + ty::ty_rptr(_, ty::mt { ty, mutbl: _ }) => ty, + _ => fcx.tcx().sess.span_bug(source_expr.span, + "expected appropriate reference type"), + }; + + // Ensure that if Ptr is cast to Ptr, then T : Trait. + push_cast_obligation(fcx, cast_expr, object_trait, referent_ty); + check_object_safety(tcx, object_trait, source_expr.span); fn object_trait<'a, 'tcx>(t: &'a Ty<'tcx>) -> &'a ty::TyTrait<'tcx> { match t.sty { @@ -97,13 +89,6 @@ pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } } - fn mutability_allowed(a_mutbl: ast::Mutability, - b_mutbl: ast::Mutability) - -> bool { - a_mutbl == b_mutbl || - (a_mutbl == ast::MutMutable && b_mutbl == ast::MutImmutable) - } - fn push_cast_obligation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, cast_expr: &ast::Expr, object_trait: &ty::TyTrait<'tcx>, From a1b3189f4864f1ada755e9ebc2e0ce1ac5bf2e06 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 6 Feb 2015 18:05:32 +0100 Subject: [PATCH 22/41] add test illustrating the feature. (with multiple impls to further exercise correct trait-matching.) --- .../infer-container-across-object-cast.rs | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/test/run-pass/infer-container-across-object-cast.rs diff --git a/src/test/run-pass/infer-container-across-object-cast.rs b/src/test/run-pass/infer-container-across-object-cast.rs new file mode 100644 index 00000000000..979e76b1ff9 --- /dev/null +++ b/src/test/run-pass/infer-container-across-object-cast.rs @@ -0,0 +1,59 @@ +// 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. + +// Given ` as Box`, we should be able to infer that a +// `Box<_>` is the expected type. + +trait Foo { fn foo(&self) -> u32; } +impl Foo for u32 { fn foo(&self) -> u32 { *self } } + +// (another impl to ensure trait-matching cannot just choose from a singleton set) +impl Foo for () { fn foo(&self) -> u32 { -176 } } + +trait Boxed { fn make() -> Self; } +impl Boxed for Box { fn make() -> Self { Box::new(7) } } + +// (another impl to ensure trait-matching cannot just choose from a singleton set) +impl Boxed for () { fn make() -> Self { () } } + +fn boxed_foo() { + let b7 = Boxed::make() as Box; + assert_eq!(b7.foo(), 7); +} + +trait Refed<'a,T> { fn make(&'a T) -> Self; } +impl<'a> Refed<'a, u32> for &'a u32 { fn make(x: &'a u32) -> Self { x } } + +// (another impl to ensure trait-matching cannot just choose from a singleton set) +impl<'a,'b> Refed<'a, ()> for &'b () { fn make(_: &'a ()) -> Self { static U: () = (); &U } } + +fn refed_foo() { + let a = 8; + let b7 = Refed::make(&a) as &Foo; + assert_eq!(b7.foo(), 8); +} + +fn check_subtyping_works() { + fn inner<'short, 'long:'short>(_s: &'short u32, + l: &'long u32) -> &'short (Foo+'short) { + Refed::make(l) as &Foo + } + + let a = 9; + let b = 10; + let r = inner(&b, &a); + assert_eq!(r.foo(), 9); +} + +pub fn main() { + boxed_foo(); + refed_foo(); + check_subtyping_works(); +} From 45f667286134c9d48008969c4e3f4b54d9c1dc22 Mon Sep 17 00:00:00 2001 From: Sean Collins Date: Mon, 9 Feb 2015 15:07:47 -0500 Subject: [PATCH 23/41] Make fallback font 'serif', rather than 'sans-serif' fonts --- src/doc/rust.css | 2 +- src/librustdoc/html/static/main.css | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rust.css b/src/doc/rust.css index 3f59f12e74c..c2a25cd7a58 100644 --- a/src/doc/rust.css +++ b/src/doc/rust.css @@ -58,7 +58,7 @@ body { margin: 0 auto; padding: 0 15px; - font-family: "Source Serif Pro", "Helvetica Neue", Helvetica, Arial, sans-serif; + font-family: "Source Serif Pro", Georgia, Times, "Times New Roman", serif; font-size: 18px; color: #333; line-height: 1.428571429; diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css index 46faa3efc34..7267f95b31f 100644 --- a/src/librustdoc/html/static/main.css +++ b/src/librustdoc/html/static/main.css @@ -64,7 +64,7 @@ body { color: #333; - font: 16px/1.4 "Source Serif Pro", "Helvetica Neue", Helvetica, Arial, sans-serif; + font: 16px/1.4 "Source Serif Pro", Georgia, Times, "Times New Roman", serif; margin: 0; position: relative; padding: 10px 15px 20px 15px; From 0479d90b77ab2b9abe9e242980ce8ec53fb7761d Mon Sep 17 00:00:00 2001 From: Pierre Baillet Date: Sat, 7 Feb 2015 15:11:25 +0100 Subject: [PATCH 24/41] Update deprecation notice. - add namespace - add function parens --- 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 1a617694456..526b5edd4cb 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -723,7 +723,7 @@ extern "system" { /// println!("{}", argument); /// } /// ``` -#[deprecated(since = "1.0.0", reason = "use env::args instead")] +#[deprecated(since = "1.0.0", reason = "use std::env::args() instead")] #[unstable(feature = "os")] pub fn args() -> Vec { real_args() From 1163cef1c43d421c54b97ee266bb4f2ddfe4595c Mon Sep 17 00:00:00 2001 From: Luke Steensen Date: Mon, 9 Feb 2015 15:10:33 -0600 Subject: [PATCH 25/41] remove obsolete closure syntax from the guide --- src/doc/trpl/closures.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/doc/trpl/closures.md b/src/doc/trpl/closures.md index bfb1494efc7..8cc6be7387c 100644 --- a/src/doc/trpl/closures.md +++ b/src/doc/trpl/closures.md @@ -9,7 +9,7 @@ arguments, really powerful things are possible. Let's make a closure: ```{rust} -let add_one = |&: x| { 1 + x }; +let add_one = |x| { 1 + x }; println!("The sum of 5 plus 1 is {}.", add_one(5)); ``` @@ -21,8 +21,8 @@ binding name and two parentheses, just like we would for a named function. Let's compare syntax. The two are pretty close: ```{rust} -let add_one = |&: x: i32| -> i32 { 1 + x }; -fn add_one (x: i32) -> i32 { 1 + x } +let add_one = |x: i32| -> i32 { 1 + x }; +fn add_one (x: i32) -> i32 { 1 + x } ``` As you may have noticed, closures infer their argument and return types, so you @@ -37,7 +37,7 @@ this: fn main() { let x: i32 = 5; - let printer = |&:| { println!("x is: {}", x); }; + let printer = || { println!("x is: {}", x); }; printer(); // prints "x is: 5" } @@ -53,7 +53,7 @@ defined. The closure borrows any variables it uses, so this will error: fn main() { let mut x: i32 = 5; - let printer = |&:| { println!("x is: {}", x); }; + let printer = || { println!("x is: {}", x); }; x = 6; // error: cannot assign to `x` because it is borrowed } @@ -80,7 +80,7 @@ fn twice i32>(x: i32, f: F) -> i32 { } fn main() { - let square = |&: x: i32| { x * x }; + let square = |x: i32| { x * x }; twice(5, square); // evaluates to 50 } @@ -89,7 +89,7 @@ fn main() { Let's break the example down, starting with `main`: ```{rust} -let square = |&: x: i32| { x * x }; +let square = |x: i32| { x * x }; ``` We've seen this before. We make a closure that takes an integer, and returns @@ -97,7 +97,7 @@ its square. ```{rust} # fn twice i32>(x: i32, f: F) -> i32 { f(x) + f(x) } -# let square = |&: x: i32| { x * x }; +# let square = |x: i32| { x * x }; twice(5, square); // evaluates to 50 ``` @@ -184,8 +184,8 @@ fn compose(x: i32, f: F, g: G) -> i32 fn main() { compose(5, - |&: n: i32| { n + 42 }, - |&: n: i32| { n * 2 }); // evaluates to 94 + |n: i32| { n + 42 }, + |n: i32| { n * 2 }); // evaluates to 94 } ``` From 64a4decec779ee0a30585a12352d20a54b722506 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 6 Feb 2015 14:47:09 -0800 Subject: [PATCH 26/41] std: Remove typarms from IteratorExt::cloned With associated types an where clauses none of the type parameters are necessary. [breaking-change] --- src/libcore/iter.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 5df64cfaada..fcf46b81a57 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -967,10 +967,9 @@ pub trait IteratorExt: Iterator + Sized { /// Creates an iterator that clones the elements it yields. Useful for converting an /// Iterator<&T> to an Iterator. #[unstable(feature = "core", reason = "recent addition")] - fn cloned(self) -> Cloned where - Self: Iterator, - D: Deref, - T: Clone, + fn cloned(self) -> Cloned where + Self::Item: Deref, + ::Output: Clone, { Cloned { it: self } } From 605225a366b62f29f5fd4b03cc298fff03bc3bdf Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 6 Feb 2015 14:47:55 -0800 Subject: [PATCH 27/41] std: Rename IntoIterator::Iter to IntoIter This is in preparation for stabilization of the `IntoIterator` trait. All implementations and references to `Iter` need to be renamed to `IntoIter`. [breaking-change] --- src/libcollections/binary_heap.rs | 4 ++-- src/libcollections/bit.rs | 4 ++-- src/libcollections/btree/map.rs | 6 +++--- src/libcollections/btree/set.rs | 4 ++-- src/libcollections/dlist.rs | 6 +++--- src/libcollections/enum_set.rs | 2 +- src/libcollections/ring_buf.rs | 6 +++--- src/libcollections/vec.rs | 6 +++--- src/libcollections/vec_map.rs | 6 +++--- src/libcore/array.rs | 4 ++-- src/libcore/iter.rs | 6 +++--- src/libcore/slice.rs | 4 ++-- src/libstd/collections/hash/map.rs | 6 +++--- src/libstd/collections/hash/set.rs | 4 ++-- 14 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index 275fc34f813..11576fbb00c 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -656,7 +656,7 @@ impl FromIterator for BinaryHeap { } impl IntoIterator for BinaryHeap { - type Iter = IntoIter; + type IntoIter = IntoIter; fn into_iter(self) -> IntoIter { self.into_iter() @@ -664,7 +664,7 @@ impl IntoIterator for BinaryHeap { } impl<'a, T> IntoIterator for &'a BinaryHeap where T: Ord { - type Iter = Iter<'a, T>; + type IntoIter = Iter<'a, T>; fn into_iter(self) -> Iter<'a, T> { self.iter() diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index 8ba0eb9b7ef..6d15a264172 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -1071,7 +1071,7 @@ impl<'a> RandomAccessIterator for Iter<'a> { } impl<'a> IntoIterator for &'a Bitv { - type Iter = Iter<'a>; + type IntoIter = Iter<'a>; fn into_iter(self) -> Iter<'a> { self.iter() @@ -1883,7 +1883,7 @@ impl<'a> Iterator for SymmetricDifference<'a> { } impl<'a> IntoIterator for &'a BitvSet { - type Iter = SetIter<'a>; + type IntoIter = SetIter<'a>; fn into_iter(self) -> SetIter<'a> { self.iter() diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index aec50d53808..2cef08725a2 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -463,7 +463,7 @@ impl BTreeMap { } impl IntoIterator for BTreeMap { - type Iter = IntoIter; + type IntoIter = IntoIter; fn into_iter(self) -> IntoIter { self.into_iter() @@ -471,7 +471,7 @@ impl IntoIterator for BTreeMap { } impl<'a, K, V> IntoIterator for &'a BTreeMap { - type Iter = Iter<'a, K, V>; + type IntoIter = Iter<'a, K, V>; fn into_iter(self) -> Iter<'a, K, V> { self.iter() @@ -479,7 +479,7 @@ impl<'a, K, V> IntoIterator for &'a BTreeMap { } impl<'a, K, V> IntoIterator for &'a mut BTreeMap { - type Iter = IterMut<'a, K, V>; + type IntoIter = IterMut<'a, K, V>; fn into_iter(mut self) -> IterMut<'a, K, V> { self.iter_mut() diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index c888a261f9d..7cb31ab1f6d 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -481,7 +481,7 @@ impl FromIterator for BTreeSet { } impl IntoIterator for BTreeSet { - type Iter = IntoIter; + type IntoIter = IntoIter; fn into_iter(self) -> IntoIter { self.into_iter() @@ -489,7 +489,7 @@ impl IntoIterator for BTreeSet { } impl<'a, T> IntoIterator for &'a BTreeSet { - type Iter = Iter<'a, T>; + type IntoIter = Iter<'a, T>; fn into_iter(self) -> Iter<'a, T> { self.iter() diff --git a/src/libcollections/dlist.rs b/src/libcollections/dlist.rs index 748230c5d24..a080146e0ec 100644 --- a/src/libcollections/dlist.rs +++ b/src/libcollections/dlist.rs @@ -831,7 +831,7 @@ impl FromIterator for DList { } impl IntoIterator for DList { - type Iter = IntoIter; + type IntoIter = IntoIter; fn into_iter(self) -> IntoIter { self.into_iter() @@ -839,7 +839,7 @@ impl IntoIterator for DList { } impl<'a, T> IntoIterator for &'a DList { - type Iter = Iter<'a, T>; + type IntoIter = Iter<'a, T>; fn into_iter(self) -> Iter<'a, T> { self.iter() @@ -847,7 +847,7 @@ impl<'a, T> IntoIterator for &'a DList { } impl<'a, T> IntoIterator for &'a mut DList { - type Iter = IterMut<'a, T>; + type IntoIter = IterMut<'a, T>; fn into_iter(mut self) -> IterMut<'a, T> { self.iter_mut() diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index da146506077..da533d34703 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -258,7 +258,7 @@ impl FromIterator for EnumSet { } impl<'a, E> IntoIterator for &'a EnumSet where E: CLike { - type Iter = Iter; + type IntoIter = Iter; fn into_iter(self) -> Iter { self.iter() diff --git a/src/libcollections/ring_buf.rs b/src/libcollections/ring_buf.rs index 76849e6ade8..5f1dc1d2ef4 100644 --- a/src/libcollections/ring_buf.rs +++ b/src/libcollections/ring_buf.rs @@ -1608,7 +1608,7 @@ impl FromIterator for RingBuf { } impl IntoIterator for RingBuf { - type Iter = IntoIter; + type IntoIter = IntoIter; fn into_iter(self) -> IntoIter { self.into_iter() @@ -1616,7 +1616,7 @@ impl IntoIterator for RingBuf { } impl<'a, T> IntoIterator for &'a RingBuf { - type Iter = Iter<'a, T>; + type IntoIter = Iter<'a, T>; fn into_iter(self) -> Iter<'a, T> { self.iter() @@ -1624,7 +1624,7 @@ impl<'a, T> IntoIterator for &'a RingBuf { } impl<'a, T> IntoIterator for &'a mut RingBuf { - type Iter = IterMut<'a, T>; + type IntoIter = IterMut<'a, T>; fn into_iter(mut self) -> IterMut<'a, T> { self.iter_mut() diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 70097c956cd..1cd2a89ad60 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1388,7 +1388,7 @@ impl FromIterator for Vec { } impl IntoIterator for Vec { - type Iter = IntoIter; + type IntoIter = IntoIter; fn into_iter(self) -> IntoIter { self.into_iter() @@ -1396,7 +1396,7 @@ impl IntoIterator for Vec { } impl<'a, T> IntoIterator for &'a Vec { - type Iter = slice::Iter<'a, T>; + type IntoIter = slice::Iter<'a, T>; fn into_iter(self) -> slice::Iter<'a, T> { self.iter() @@ -1404,7 +1404,7 @@ impl<'a, T> IntoIterator for &'a Vec { } impl<'a, T> IntoIterator for &'a mut Vec { - type Iter = slice::IterMut<'a, T>; + type IntoIter = slice::IterMut<'a, T>; fn into_iter(mut self) -> slice::IterMut<'a, T> { self.iter_mut() diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs index 739b8d8ce19..93d02de9b55 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -669,7 +669,7 @@ impl FromIterator<(usize, V)> for VecMap { } impl IntoIterator for VecMap { - type Iter = IntoIter; + type IntoIter = IntoIter; fn into_iter(self) -> IntoIter { self.into_iter() @@ -677,7 +677,7 @@ impl IntoIterator for VecMap { } impl<'a, T> IntoIterator for &'a VecMap { - type Iter = Iter<'a, T>; + type IntoIter = Iter<'a, T>; fn into_iter(self) -> Iter<'a, T> { self.iter() @@ -685,7 +685,7 @@ impl<'a, T> IntoIterator for &'a VecMap { } impl<'a, T> IntoIterator for &'a mut VecMap { - type Iter = IterMut<'a, T>; + type IntoIter = IterMut<'a, T>; fn into_iter(mut self) -> IterMut<'a, T> { self.iter_mut() diff --git a/src/libcore/array.rs b/src/libcore/array.rs index 5c4567e567b..a596fe4a588 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -49,7 +49,7 @@ macro_rules! array_impls { } impl<'a, T> IntoIterator for &'a [T; $N] { - type Iter = Iter<'a, T>; + type IntoIter = Iter<'a, T>; fn into_iter(self) -> Iter<'a, T> { self.iter() @@ -57,7 +57,7 @@ macro_rules! array_impls { } impl<'a, T> IntoIterator for &'a mut [T; $N] { - type Iter = IterMut<'a, T>; + type IntoIter = IterMut<'a, T>; fn into_iter(self) -> IterMut<'a, T> { self.iter_mut() diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index fcf46b81a57..2d240a53c4f 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -120,14 +120,14 @@ pub trait FromIterator { /// Conversion into an `Iterator` pub trait IntoIterator { - type Iter: Iterator; + type IntoIter: Iterator; /// Consumes `Self` and returns an iterator over it - fn into_iter(self) -> Self::Iter; + fn into_iter(self) -> Self::IntoIter; } impl IntoIterator for I where I: Iterator { - type Iter = I; + type IntoIter = I; fn into_iter(self) -> I { self diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index fc51920ec6b..459addb09fd 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -628,7 +628,7 @@ impl<'a, T> Default for &'a [T] { // impl<'a, T> IntoIterator for &'a [T] { - type Iter = Iter<'a, T>; + type IntoIter = Iter<'a, T>; fn into_iter(self) -> Iter<'a, T> { self.iter() @@ -636,7 +636,7 @@ impl<'a, T> IntoIterator for &'a [T] { } impl<'a, T> IntoIterator for &'a mut [T] { - type Iter = IterMut<'a, T>; + type IntoIter = IterMut<'a, T>; fn into_iter(self) -> IterMut<'a, T> { self.iter_mut() diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 710f021d912..18dd122891d 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1377,7 +1377,7 @@ impl<'a, K, V, S, H> IntoIterator for &'a HashMap S: HashState, H: hash::Hasher { - type Iter = Iter<'a, K, V>; + type IntoIter = Iter<'a, K, V>; fn into_iter(self) -> Iter<'a, K, V> { self.iter() @@ -1389,7 +1389,7 @@ impl<'a, K, V, S, H> IntoIterator for &'a mut HashMap S: HashState, H: hash::Hasher { - type Iter = IterMut<'a, K, V>; + type IntoIter = IterMut<'a, K, V>; fn into_iter(mut self) -> IterMut<'a, K, V> { self.iter_mut() @@ -1401,7 +1401,7 @@ impl IntoIterator for HashMap S: HashState, H: hash::Hasher { - type Iter = IntoIter; + type IntoIter = IntoIter; fn into_iter(self) -> IntoIter { self.into_iter() diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index e40f17f29e8..de3c0424c9a 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -840,7 +840,7 @@ impl<'a, T, S, H> IntoIterator for &'a HashSet S: HashState, H: hash::Hasher { - type Iter = Iter<'a, T>; + type IntoIter = Iter<'a, T>; fn into_iter(self) -> Iter<'a, T> { self.iter() @@ -852,7 +852,7 @@ impl IntoIterator for HashSet S: HashState, H: hash::Hasher { - type Iter = IntoIter; + type IntoIter = IntoIter; fn into_iter(self) -> IntoIter { self.into_iter() From 0ee95b917b30d7a48bcafa8b4642f3bcec4d50ff Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 9 Feb 2015 16:24:29 -0800 Subject: [PATCH 28/41] std: Mark IntoIterator::into_iter as #[stable Right now it is not possible to write a `for` loop without opting-in to the `core` feature due to the way they're expanding (calling `::std::iter::IntoIterator::into_iter`). There are some planned tweaks to the `IntoIterator` trait (adding an `Item` associated type) which will cause implementations of `IntoIterator` to break, but the *usage* of the trait is currently stable. This commit marks the method `into_iter` as stable as the name will not be changing, nor the fact that it takes no arguments and returns one type (which is determiend by the `Self` type). This means that usage of `for` loops is now stable but manual implementations of the `IntoIterator` trait will continue to be unstable. --- src/libcore/iter.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 2d240a53c4f..20cd1c30839 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -123,6 +123,7 @@ pub trait IntoIterator { type IntoIter: Iterator; /// Consumes `Self` and returns an iterator over it + #[stable(feature = "rust1", since = "1.0.0")] fn into_iter(self) -> Self::IntoIter; } From dbccd70a5736fd2e898b446e6c5f3da5d17538c6 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Sun, 8 Feb 2015 20:15:16 -0500 Subject: [PATCH 29/41] Add documentation on trait objects. Largely taken from @huonw's http://huonw.github.io/blog/2015/01/peeking-inside-trait-objects/ Fixes #21707 --- src/doc/trpl/SUMMARY.md | 1 + src/doc/trpl/static-and-dynamic-dispatch.md | 286 ++++++++++++++++++++ src/doc/trpl/traits.md | 47 +--- 3 files changed, 289 insertions(+), 45 deletions(-) create mode 100644 src/doc/trpl/static-and-dynamic-dispatch.md diff --git a/src/doc/trpl/SUMMARY.md b/src/doc/trpl/SUMMARY.md index 9d65f30e723..bfc1247dc3b 100644 --- a/src/doc/trpl/SUMMARY.md +++ b/src/doc/trpl/SUMMARY.md @@ -27,6 +27,7 @@ * [Iterators](iterators.md) * [Generics](generics.md) * [Traits](traits.md) + * [Static and Dynamic Dispatch](static-and-dynamic-dispatch.md) * [Concurrency](concurrency.md) * [Error Handling](error-handling.md) * [Documentation](documentation.md) diff --git a/src/doc/trpl/static-and-dynamic-dispatch.md b/src/doc/trpl/static-and-dynamic-dispatch.md new file mode 100644 index 00000000000..9421dac7bf6 --- /dev/null +++ b/src/doc/trpl/static-and-dynamic-dispatch.md @@ -0,0 +1,286 @@ +% Static and Dynamic Dispatch + +When code involves polymorphism, there needs to be a mechanism to determine +which specific version is actually run. This is called 'dispatch.' There are +two major forms of dispatch: static dispatch and dynamic dispatch. While Rust +favors static dispatch, it also supports dynamic dispatch through a mechanism +called 'trait objects.' + +## Background + +For the rest of this chapter, we'll need a trait and some implementations. +Let's make a simple one, `Foo`. It has one method that is expected to return a +`String`. + +```rust +trait Foo { + fn method(&self) -> String; +} +``` + +We'll also implement this trait for `u8` and `String`: + +```rust +# trait Foo { fn method(&self) -> String; } +impl Foo for u8 { + fn method(&self) -> String { format!("u8: {}", *self) } +} + +impl Foo for String { + fn method(&self) -> String { format!("string: {}", *self) } +} +``` + + +## Static dispatch + +We can use this trait to perform static dispatch with trait bounds: + +```rust +# trait Foo { fn method(&self) -> String; } +# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } } +# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } } +fn do_something(x: T) { + x.method(); +} + +fn main() { + let x = 5u8; + let y = "Hello".to_string(); + + do_something(x); + do_something(y); +} +``` + +Rust uses 'monomorphization' to perform static dispatch here. This means that +Rust will create a special version of `do_something()` for both `u8` and +`String`, and then replace the call sites with calls to these specialized +functions. In other words, Rust generates something like this: + +```rust +# trait Foo { fn method(&self) -> String; } +# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } } +# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } } +fn do_something_u8(x: u8) { + x.method(); +} + +fn do_something_string(x: String) { + x.method(); +} + +fn main() { + let x = 5u8; + let y = "Hello".to_string(); + + do_something_u8(x); + do_something_string(y); +} +``` + +This has some upsides: static dispatching of any method calls, allowing for +inlining and hence usually higher performance. It also has some downsides: +causing code bloat due to many copies of the same function existing in the +binary, one for each type. + +Furthermore, compilers aren’t perfect and may “optimise” code to become slower. +For example, functions inlined too eagerly will bloat the instruction cache +(cache rules everything around us). This is part of the reason that `#[inline]` +and `#[inline(always)]` should be used carefully, and one reason why using a +dynamic dispatch is sometimes more efficient. + +However, the common case is that it is more efficient to use static dispatch, +and one can always have a thin statically-dispatched wrapper function that does +a dynamic, but not vice versa, meaning static calls are more flexible. The +standard library tries to be statically dispatched where possible for this +reason. + +## Dynamic dispatch + +Rust provides dynamic dispatch through a feature called 'trait objects.' Trait +objects, like `&Foo` or `Box`, are normal values that store a value of +*any* type that implements the given trait, where the precise type can only be +known at runtime. The methods of the trait can be called on a trait object via +a special record of function pointers (created and managed by the compiler). + +A function that takes a trait object is not specialised to each of the types +that implements `Foo`: only one copy is generated, often (but not always) +resulting in less code bloat. However, this comes at the cost of requiring +slower virtual function calls, and effectively inhibiting any chance of +inlining and related optimisations from occurring. + +Trait objects are both simple and complicated: their core representation and +layout is quite straight-forward, but there are some curly error messages and +surprising behaviours to discover. + +### Obtaining a trait object + +There's two similar ways to get a trait object value: casts and coercions. If +`T` is a type that implements a trait `Foo` (e.g. `u8` for the `Foo` above), +then the two ways to get a `Foo` trait object out of a pointer to `T` look +like: + +```{rust,ignore} +let ref_to_t: &T = ...; + +// `as` keyword for casting +let cast = ref_to_t as &Foo; + +// using a `&T` in a place that has a known type of `&Foo` will implicitly coerce: +let coerce: &Foo = ref_to_t; + +fn also_coerce(_unused: &Foo) {} +also_coerce(ref_to_t); +``` + +These trait object coercions and casts also work for pointers like `&mut T` to +`&mut Foo` and `Box` to `Box`, but that's all at the moment. Coercions +and casts are identical. + +This operation can be seen as "erasing" the compiler's knowledge about the +specific type of the pointer, and hence trait objects are sometimes referred to +"type erasure". + +### Representation + +Let's start simple, with the runtime representation of a trait object. The +`std::raw` module contains structs with layouts that are the same as the +complicated build-in types, [including trait objects][stdraw]: + +```rust +# mod foo { +pub struct TraitObject { + pub data: *mut (), + pub vtable: *mut (), +} +# } +``` + +[stdraw]: ../std/raw/struct.TraitObject.html + +That is, a trait object like `&Foo` consists of a "data" pointer and a "vtable" +pointer. + +The data pointer addresses the data (of some unknown type `T`) that the trait +object is storing, and the vtable pointer points to the vtable ("virtual method +table") corresponding to the implementation of `Foo` for `T`. + + +A vtable is essentially a struct of function pointers, pointing to the concrete +piece of machine code for each method in the implementation. A method call like +`trait_object.method()` will retrieve the correct pointer out of the vtable and +then do a dynamic call of it. For example: + +```{rust,ignore} +struct FooVtable { + destructor: fn(*mut ()), + size: usize, + align: usize, + method: fn(*const ()) -> String, +} + +// u8: + +fn call_method_on_u8(x: *const ()) -> String { + // the compiler guarantees that this function is only called + // with `x` pointing to a u8 + let byte: &u8 = unsafe { &*(x as *const u8) }; + + byte.method() +} + +static Foo_for_u8_vtable: FooVtable = FooVtable { + destructor: /* compiler magic */, + size: 1, + align: 1, + + // cast to a function pointer + method: call_method_on_u8 as fn(*const ()) -> String, +}; + + +// String: + +fn call_method_on_String(x: *const ()) -> String { + // the compiler guarantees that this function is only called + // with `x` pointing to a String + let string: &String = unsafe { &*(x as *const String) }; + + string.method() +} + +static Foo_for_String_vtable: FooVtable = FooVtable { + destructor: /* compiler magic */, + // values for a 64-bit computer, halve them for 32-bit ones + size: 24, + align: 8, + + method: call_method_on_String as fn(*const ()) -> String, +}; +``` + +The `destructor` field in each vtable points to a function that will clean up +any resources of the vtable's type, for `u8` it is trivial, but for `String` it +will free the memory. This is necessary for owning trait objects like +`Box`, which need to clean-up both the `Box` allocation and as well as the +internal type when they go out of scope. The `size` and `align` fields store +the size of the erased type, and its alignment requirements; these are +essentially unused at the moment since the information is embedded in the +destructor, but will be used in future, as trait objects are progressively made +more flexible. + +Suppose we've got some values that implement `Foo`, the explicit form of +construction and use of `Foo` trait objects might look a bit like (ignoring the +type mismatches: they're all just pointers anyway): + +```{rust,ignore} +let a: String = "foo".to_string(); +let x: u8 = 1; + +// let b: &Foo = &a; +let b = TraitObject { + // store the data + data: &a, + // store the methods + vtable: &Foo_for_String_vtable +}; + +// let y: &Foo = x; +let y = TraitObject { + // store the data + data: &x, + // store the methods + vtable: &Foo_for_u8_vtable +}; + +// b.method(); +(b.vtable.method)(b.data); + +// y.method(); +(y.vtable.method)(y.data); +``` + +If `b` or `y` were owning trait objects (`Box`), there would be a +`(b.vtable.destructor)(b.data)` (respectively `y`) call when they went out of +scope. + +### Why pointers? + +The use of language like "fat pointer" implies that a trait object is +always a pointer of some form, but why? + +Rust does not put things behind a pointer by default, unlike many managed +languages, so types can have different sizes. Knowing the size of the value at +compile time is important for things like passing it as an argument to a +function, moving it about on the stack and allocating (and deallocating) space +on the heap to store it. + +For `Foo`, we would need to have a value that could be at least either a +`String` (24 bytes) or a `u8` (1 byte), as well as any other type for which +dependent crates may implement `Foo` (any number of bytes at all). There's no +way to guarantee that this last point can work if the values are stored without +a pointer, because those other types can be arbitrarily large. + +Putting the value behind a pointer means the size of the value is not relevant +when we are tossing a trait object around, only the size of the pointer itself. diff --git a/src/doc/trpl/traits.md b/src/doc/trpl/traits.md index d12480d7dd9..e091878cf86 100644 --- a/src/doc/trpl/traits.md +++ b/src/doc/trpl/traits.md @@ -270,51 +270,8 @@ not, because both the trait and the type aren't in our crate. One last thing about traits: generic functions with a trait bound use *monomorphization* (*mono*: one, *morph*: form), so they are statically -dispatched. What's that mean? Well, let's take a look at `print_area` again: - -```{rust,ignore} -fn print_area(shape: T) { - println!("This shape has an area of {}", shape.area()); -} - -fn main() { - let c = Circle { ... }; - - let s = Square { ... }; - - print_area(c); - print_area(s); -} -``` - -When we use this trait with `Circle` and `Square`, Rust ends up generating -two different functions with the concrete type, and replacing the call sites with -calls to the concrete implementations. In other words, you get something like -this: - -```{rust,ignore} -fn __print_area_circle(shape: Circle) { - println!("This shape has an area of {}", shape.area()); -} - -fn __print_area_square(shape: Square) { - println!("This shape has an area of {}", shape.area()); -} - -fn main() { - let c = Circle { ... }; - - let s = Square { ... }; - - __print_area_circle(c); - __print_area_square(s); -} -``` - -The names don't actually change to this, it's just for illustration. But -as you can see, there's no overhead of deciding which version to call here, -hence *statically dispatched*. The downside is that we have two copies of -the same function, so our binary is a little bit larger. +dispatched. What's that mean? Check out the chapter on [static and dynamic +dispatch](static-and-dynamic-dispatch.html) for more. ## Our `inverse` Example From e40d05800bd2f6c1e68548246a21f305447ae300 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Mon, 9 Feb 2015 21:51:30 -0500 Subject: [PATCH 30/41] Remove incorrect docs from mem::transmute Fixes #22032 --- src/libcore/intrinsics.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 125e8a0e814..5562845e11d 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -222,12 +222,11 @@ extern "rust-intrinsic" { /// Unsafely transforms a value of one type into a value of another type. /// - /// Both types must have the same size and alignment, and this guarantee - /// is enforced at compile-time. + /// Both types must have the same size. /// /// # Examples /// - /// ```rust + /// ``` /// use std::mem; /// /// let v: &[u8] = unsafe { mem::transmute("L") }; From b42c559e9f0162e9770631e86fb21995d60d0d09 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Mon, 9 Feb 2015 21:57:14 -0500 Subject: [PATCH 31/41] Remove bottom from the reference Fixes #20172 --- 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 9c8191a386d..c2b381fe5e4 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -1253,9 +1253,7 @@ fn my_err(s: &str) -> ! { We call such functions "diverging" because they never return a value to the caller. Every control path in a diverging function must end with a `panic!()` or a call to another diverging function on every control path. The `!` annotation -does *not* denote a type. Rather, the result type of a diverging function is a -special type called ⊥ ("bottom") that unifies with any type. Rust has no -syntax for ⊥. +does *not* denote a type. It might be necessary to declare a diverging function because as mentioned previously, the typechecker checks that every control path in a function ends From 17abb43248e5b8ce65ede45d7446fa7247eed5ae Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Mon, 9 Feb 2015 21:44:11 -0500 Subject: [PATCH 32/41] Set up docs for missing core types Fixes #22085 --- src/libcore/lib.rs | 4 ++++ src/libcore/tuple.rs | 1 + 2 files changed, 5 insertions(+) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index df4942b509b..a122bcb2c7a 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -141,6 +141,10 @@ pub mod hash; pub mod fmt; pub mod error; +#[doc(primitive = "bool")] +mod bool { +} + // note: does not need to be public mod tuple; mod array; diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index 64c2964eb7c..72b2d5dc188 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -34,6 +34,7 @@ //! * `Default` #![stable(feature = "rust1", since = "1.0.0")] +#![doc(primitive = "tuple")] use clone::Clone; use cmp::*; From 792dc8d067d1f11e08e859ccdd45d59436773fc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20L=C3=B6bel?= Date: Tue, 10 Feb 2015 14:37:44 +0100 Subject: [PATCH 33/41] Made the `ptr::Unique` type accept unsized types, to allow for use cases like sending a raw pointer slice across thread boundaries. --- src/libcore/ptr.rs | 6 +++--- src/libcoretest/ptr.rs | 9 +++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index ba1eae551ff..bf801a88ca5 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -522,21 +522,21 @@ impl PartialOrd for *mut T { /// Useful for building abstractions like `Vec` or `Box`, which /// internally use raw pointers to manage the memory that they own. #[unstable(feature = "core", reason = "recently added to this module")] -pub struct Unique(pub *mut T); +pub struct Unique(pub *mut T); /// `Unique` pointers are `Send` if `T` is `Send` because the data they /// reference is unaliased. Note that this aliasing invariant is /// unenforced by the type system; the abstraction using the /// `Unique` must enforce it. #[unstable(feature = "core", reason = "recently added to this module")] -unsafe impl Send for Unique { } +unsafe impl Send for Unique { } /// `Unique` pointers are `Sync` if `T` is `Sync` because the data they /// reference is unaliased. Note that this aliasing invariant is /// unenforced by the type system; the abstraction using the /// `Unique` must enforce it. #[unstable(feature = "core", reason = "recently added to this module")] -unsafe impl Sync for Unique { } +unsafe impl Sync for Unique { } impl Unique { /// Returns a null Unique. diff --git a/src/libcoretest/ptr.rs b/src/libcoretest/ptr.rs index 7f0b97c53d4..2365b907b3f 100644 --- a/src/libcoretest/ptr.rs +++ b/src/libcoretest/ptr.rs @@ -167,3 +167,12 @@ fn test_set_memory() { unsafe { set_memory(ptr, 5u8, xs.len()); } assert!(xs == [5u8; 20]); } + +#[test] +fn test_unsized_unique() { + let xs: &mut [_] = &mut [1, 2, 3]; + let ptr = Unique(xs as *mut [_]); + let ys = unsafe { &mut *ptr.0 }; + let zs: &mut [_] = &mut [1, 2, 3]; + assert!(ys == zs); +} From 3513c97302b72b6dd51136ce1e259ca0e67458f3 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 10 Feb 2015 15:01:31 +0100 Subject: [PATCH 34/41] Add error message (i.e. do not ICE) when moving out of unsafe pointers. Fix #20801. --- .../borrowck/gather_loans/move_error.rs | 1 + src/test/compile-fail/issue-20801.rs | 47 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 src/test/compile-fail/issue-20801.rs diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs index b00973c82bd..10ffb89e728 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs @@ -118,6 +118,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, match move_from.cat { mc::cat_deref(_, _, mc::BorrowedPtr(..)) | mc::cat_deref(_, _, mc::Implicit(..)) | + mc::cat_deref(_, _, mc::UnsafePtr(..)) | mc::cat_static_item => { bccx.span_err(move_from.span, &format!("cannot move out of {}", diff --git a/src/test/compile-fail/issue-20801.rs b/src/test/compile-fail/issue-20801.rs new file mode 100644 index 00000000000..a2565e88467 --- /dev/null +++ b/src/test/compile-fail/issue-20801.rs @@ -0,0 +1,47 @@ +// 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. + +// We used to ICE when moving out of a `*mut T` or `*const T`. + +struct T(u8); + +static mut GLOBAL_MUT_T: T = T(0); + +static GLOBAL_T: T = T(0); + +fn imm_ref() -> &'static T { + unsafe { &GLOBAL_T } +} + +fn mut_ref() -> &'static mut T { + unsafe { &mut GLOBAL_MUT_T } +} + +fn mut_ptr() -> *mut T { + unsafe { 0u8 as *mut T } +} + +fn const_ptr() -> *const T { + unsafe { 0u8 as *const T } +} + +pub fn main() { + let a = unsafe { *mut_ref() }; + //~^ ERROR cannot move out of dereference of borrowed content + + let b = unsafe { *imm_ref() }; + //~^ ERROR cannot move out of dereference of borrowed content + + let c = unsafe { *mut_ptr() }; + //~^ ERROR cannot move out of dereference of unsafe pointer + + let d = unsafe { *const_ptr() }; + //~^ ERROR cannot move out of dereference of unsafe pointer +} From 7d2404cb420591588684d4681cf81fe8cff1ace3 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Tue, 10 Feb 2015 15:06:45 +0100 Subject: [PATCH 35/41] Move native thread name setting from thread_info to Thread, fixes #21911 --- src/libstd/thread.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstd/thread.rs b/src/libstd/thread.rs index dda97bec925..cc9d7492441 100644 --- a/src/libstd/thread.rs +++ b/src/libstd/thread.rs @@ -156,6 +156,7 @@ use ops::{Drop, FnOnce}; use option::Option::{self, Some, None}; use result::Result::{Err, Ok}; use sync::{Mutex, Condvar, Arc}; +use str::Str; use string::String; use rt::{self, unwind}; use old_io::{Writer, stdio}; From 0b1d5f01828fdb21e31071d149618d2e983342c5 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 26 Jan 2015 14:27:22 +0100 Subject: [PATCH 36/41] Make FRU respect privacy of all struct fields, mentioned or unmentioned. This is RFC 736. Fix #21407. --- src/librustc_privacy/lib.rs | 29 ++++++------- ...nctional-struct-update-respects-privacy.rs | 42 +++++++++++++++++++ 2 files changed, 57 insertions(+), 14 deletions(-) create mode 100644 src/test/compile-fail/functional-struct-update-respects-privacy.rs diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index aa9b6c479bb..4afe8fe7878 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -390,8 +390,8 @@ enum PrivacyResult { enum FieldName { UnnamedField(uint), // index - // FIXME #6993: change type (and name) from Ident to Name - NamedField(ast::Ident), + // (Name, not Ident, because struct fields are not macro-hygienic) + NamedField(ast::Name), } impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { @@ -665,9 +665,9 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { name: FieldName) { let fields = ty::lookup_struct_fields(self.tcx, id); let field = match name { - NamedField(ident) => { - debug!("privacy - check named field {} in struct {:?}", ident.name, id); - fields.iter().find(|f| f.name == ident.name).unwrap() + NamedField(f_name) => { + debug!("privacy - check named field {} in struct {:?}", f_name, id); + fields.iter().find(|f| f.name == f_name).unwrap() } UnnamedField(idx) => &fields[idx] }; @@ -686,7 +686,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { }; let msg = match name { NamedField(name) => format!("field `{}` of {} is private", - token::get_ident(name), struct_desc), + token::get_name(name), struct_desc), UnnamedField(idx) => format!("field #{} of {} is private", idx + 1, struct_desc), }; @@ -873,7 +873,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { match expr.node { ast::ExprField(ref base, ident) => { if let ty::ty_struct(id, _) = ty::expr_ty_adjusted(self.tcx, &**base).sty { - self.check_field(expr.span, id, NamedField(ident.node)); + self.check_field(expr.span, id, NamedField(ident.node.name)); } } ast::ExprTupField(ref base, idx) => { @@ -897,10 +897,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { } ast::ExprStruct(_, ref fields, _) => { match ty::expr_ty(self.tcx, expr).sty { - ty::ty_struct(id, _) => { - for field in &(*fields) { - self.check_field(expr.span, id, - NamedField(field.ident.node)); + ty::ty_struct(ctor_id, _) => { + let all_fields = ty::lookup_struct_fields(self.tcx, ctor_id); + for field in all_fields { + self.check_field(expr.span, ctor_id, + NamedField(field.name)); } } ty::ty_enum(_, _) => { @@ -908,7 +909,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { def::DefVariant(_, variant_id, _) => { for field in fields { self.check_field(expr.span, variant_id, - NamedField(field.ident.node)); + NamedField(field.ident.node.name)); } } _ => self.tcx.sess.span_bug(expr.span, @@ -973,7 +974,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { ty::ty_struct(id, _) => { for field in fields { self.check_field(pattern.span, id, - NamedField(field.node.ident)); + NamedField(field.node.ident.name)); } } ty::ty_enum(_, _) => { @@ -981,7 +982,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { Some(&def::DefVariant(_, variant_id, _)) => { for field in fields { self.check_field(pattern.span, variant_id, - NamedField(field.node.ident)); + NamedField(field.node.ident.name)); } } _ => self.tcx.sess.span_bug(pattern.span, diff --git a/src/test/compile-fail/functional-struct-update-respects-privacy.rs b/src/test/compile-fail/functional-struct-update-respects-privacy.rs new file mode 100644 index 00000000000..c1619a38a29 --- /dev/null +++ b/src/test/compile-fail/functional-struct-update-respects-privacy.rs @@ -0,0 +1,42 @@ +// 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. + +// RFC 736 (and Issue 21407): functional struct update should respect privacy. + +// The `foo` module attempts to maintains an invariant that each `S` +// has a unique `u64` id. +use self::foo::S; +mod foo { + use std::cell::{UnsafeCell}; + + static mut count : UnsafeCell = UnsafeCell { value: 1 }; + + pub struct S { pub a: u8, pub b: String, secret_uid: u64 } + + pub fn make_secrets(a: u8, b: String) -> S { + let val = unsafe { let p = count.get(); let val = *p; *p = val + 1; val }; + println!("creating {}, uid {}", b, val); + S { a: a, b: b, secret_uid: val } + } + + impl Drop for S { + fn drop(&mut self) { + println!("dropping {}, uid {}", self.b, self.secret_uid); + } + } +} + +fn main() { + let s_1 = foo::make_secrets(3, format!("ess one")); + let s_2 = foo::S { b: format!("ess two"), ..s_1 }; // FRU ... + + println!("main forged an S named: {}", s_2.b); + // at end of scope, ... both s_1 *and* s_2 get dropped. Boom! +} From 0a0aa11bb1551ef3c0eda2a93d94077ba76b5150 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 10 Feb 2015 15:45:36 +0100 Subject: [PATCH 37/41] Add comment noting that this naive approach is not too naive. --- src/librustc_privacy/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 4afe8fe7878..96e146fc894 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -898,6 +898,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { ast::ExprStruct(_, ref fields, _) => { match ty::expr_ty(self.tcx, expr).sty { ty::ty_struct(ctor_id, _) => { + // RFC 736: ensure all unmentioned fields are visible. + // Rather than computing the set of unmentioned fields + // (i.e. `all_fields - fields`), just check them all. let all_fields = ty::lookup_struct_fields(self.tcx, ctor_id); for field in all_fields { self.check_field(expr.span, ctor_id, From ad3be9f23f9389c71f7f712ae5195d4190becf05 Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Mon, 9 Feb 2015 23:42:31 -0500 Subject: [PATCH 38/41] parse cfgspecs passed to rustdoc fixes #22131 --- src/librustdoc/test.rs | 10 ++-------- src/test/run-make/issue-22131/Makefile | 6 ++++++ src/test/run-make/issue-22131/foo.rs | 17 +++++++++++++++++ 3 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 src/test/run-make/issue-22131/Makefile create mode 100644 src/test/run-make/issue-22131/foo.rs diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index e43c3a6da3a..09df9fc8cbb 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -24,11 +24,8 @@ use rustc::session::{self, config}; use rustc::session::config::get_unstable_features_setting; use rustc::session::search_paths::{SearchPaths, PathKind}; use rustc_driver::{driver, Compilation}; -use syntax::ast; -use syntax::codemap::{CodeMap, dummy_spanned}; +use syntax::codemap::CodeMap; use syntax::diagnostic; -use syntax::parse::token; -use syntax::ptr::P; use core; use clean; @@ -67,10 +64,7 @@ pub fn run(input: &str, span_diagnostic_handler); let mut cfg = config::build_configuration(&sess); - cfg.extend(cfgs.into_iter().map(|cfg_| { - let cfg_ = token::intern_and_get_ident(&cfg_); - P(dummy_spanned(ast::MetaWord(cfg_))) - })); + cfg.extend(config::parse_cfgspecs(cfgs).into_iter()); let krate = driver::phase_1_parse_input(&sess, cfg, &input); let krate = driver::phase_2_configure_and_expand(&sess, krate, "rustdoc-test", None) diff --git a/src/test/run-make/issue-22131/Makefile b/src/test/run-make/issue-22131/Makefile new file mode 100644 index 00000000000..46d89f0e2a6 --- /dev/null +++ b/src/test/run-make/issue-22131/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: foo.rs + $(RUSTC) --cfg 'feature="bar"' --crate-type lib foo.rs + $(RUSTDOC) --test --cfg 'feature="bar"' -L $(TMPDIR) foo.rs |\ + grep --quiet 'test foo_0 ... ok' diff --git a/src/test/run-make/issue-22131/foo.rs b/src/test/run-make/issue-22131/foo.rs new file mode 100644 index 00000000000..0b1f1291df0 --- /dev/null +++ b/src/test/run-make/issue-22131/foo.rs @@ -0,0 +1,17 @@ +// 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. + +#![crate_name="foo"] + +/// ```rust +/// assert_eq!(foo::foo(), 1); +/// ``` +#[cfg(feature = "bar")] +pub fn foo() -> i32 { 1 } From 6e8b8733c98fb2333224c5cfc7ffcf57fa878d98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Tue, 10 Feb 2015 16:31:46 +0100 Subject: [PATCH 39/41] Add a flag to skip the LLVM version check in configure When trying to build against a newer, local LLVM version it might be preferable to have a flag to disable the LLVM version check instead of having to modify the configure script. Fixes #21998 --- configure | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configure b/configure index a80dafcf047..e6b8d235448 100755 --- a/configure +++ b/configure @@ -525,6 +525,7 @@ opt verify-install 1 "verify installed binaries work" opt dist-host-only 0 "only install bins for the host architecture" opt inject-std-version 1 "inject the current compiler version of libstd into programs" opt jemalloc 1 "build liballoc with jemalloc" +opt llvm-version-check 1 "don't check if the LLVM version is supported, build anyway" valopt localstatedir "/var/lib" "local state directory" valopt sysconfdir "/etc" "install system configuration files" @@ -796,7 +797,7 @@ then putvar CFG_ENABLE_CLANG fi -if [ ! -z "$CFG_LLVM_ROOT" -a -e "$CFG_LLVM_ROOT/bin/llvm-config" ] +if [ ! -z "$CFG_LLVM_ROOT" -a -z "$CFG_DISABLE_LLVM_VERSION_CHECK" -a -e "$CFG_LLVM_ROOT/bin/llvm-config" ] then step_msg "using custom LLVM at $CFG_LLVM_ROOT" From 3f5af9f34d282cde910c0a1dc6b9c595227701c3 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 10 Feb 2015 17:32:39 +0100 Subject: [PATCH 40/41] add `//~ ERROR` line to test for privacy respecting FRU (RFC 736). --- .../compile-fail/functional-struct-update-respects-privacy.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/compile-fail/functional-struct-update-respects-privacy.rs b/src/test/compile-fail/functional-struct-update-respects-privacy.rs index c1619a38a29..51e23a689a1 100644 --- a/src/test/compile-fail/functional-struct-update-respects-privacy.rs +++ b/src/test/compile-fail/functional-struct-update-respects-privacy.rs @@ -36,7 +36,7 @@ mod foo { fn main() { let s_1 = foo::make_secrets(3, format!("ess one")); let s_2 = foo::S { b: format!("ess two"), ..s_1 }; // FRU ... - + //~^ ERROR field `secret_uid` of struct `foo::S` is private println!("main forged an S named: {}", s_2.b); // at end of scope, ... both s_1 *and* s_2 get dropped. Boom! } From 3e10785e21b731d536cf9ad9b911e8261862bde7 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 10 Feb 2015 11:05:20 -0800 Subject: [PATCH 41/41] Test fixes and rebase conflicts --- src/compiletest/compiletest.rs | 1 - src/libgetopts/lib.rs | 1 - src/liblibc/lib.rs | 2 +- src/libterm/lib.rs | 1 - src/test/compile-fail/issue-17551.rs | 4 ++-- src/test/compile-fail/issue-17999.rs | 1 - src/test/compile-fail/issue-20801.rs | 4 ++-- src/test/compile-fail/issue-2150.rs | 1 - src/test/compile-fail/liveness-unused.rs | 1 - src/test/run-make/issue-22131/Makefile | 5 +++-- 10 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index e6d2a691cf5..3c92fa02f20 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -12,7 +12,6 @@ #![feature(box_syntax)] #![feature(collections)] -#![feature(core)] #![feature(int_uint)] #![feature(io)] #![feature(os)] diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index 72832cb9466..a3cae259fd3 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -90,7 +90,6 @@ #![deny(missing_docs)] #![feature(collections)] -#![feature(core)] #![feature(int_uint)] #![feature(slicing_syntax)] #![feature(staged_api)] diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index d95d0863ca8..94e4012c5ee 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -1930,7 +1930,7 @@ pub mod types { pub iSecurityScheme: c_int, pub dwMessageSize: DWORD, pub dwProviderReserved: DWORD, - pub szProtocol: [u8; WSAPROTOCOL_LEN as usize + 1], + pub szProtocol: [u8; WSAPROTOCOL_LEN as usize + 1us], } pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO; diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index 219c9baf4c8..084152f107c 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -52,7 +52,6 @@ #![feature(box_syntax)] #![feature(collections)] -#![feature(core)] #![feature(int_uint)] #![feature(io)] #![feature(path)] diff --git a/src/test/compile-fail/issue-17551.rs b/src/test/compile-fail/issue-17551.rs index b19a7703b85..e037ba92b4a 100644 --- a/src/test/compile-fail/issue-17551.rs +++ b/src/test/compile-fail/issue-17551.rs @@ -13,6 +13,6 @@ struct B; fn main() { - let foo = B; - let closure = || foo; //~ ERROR unable to infer enough type information + let foo = B; //~ ERROR: unable to infer enough type information + let closure = || foo; } diff --git a/src/test/compile-fail/issue-17999.rs b/src/test/compile-fail/issue-17999.rs index f4c0a9c38c3..88945f80eae 100644 --- a/src/test/compile-fail/issue-17999.rs +++ b/src/test/compile-fail/issue-17999.rs @@ -9,7 +9,6 @@ // except according to those terms. #![deny(unused_variables)] -#![feature(core)] fn main() { for _ in 1..101 { diff --git a/src/test/compile-fail/issue-20801.rs b/src/test/compile-fail/issue-20801.rs index a2565e88467..929c8ec0fd6 100644 --- a/src/test/compile-fail/issue-20801.rs +++ b/src/test/compile-fail/issue-20801.rs @@ -34,10 +34,10 @@ fn const_ptr() -> *const T { pub fn main() { let a = unsafe { *mut_ref() }; - //~^ ERROR cannot move out of dereference of borrowed content + //~^ ERROR cannot move out of borrowed content let b = unsafe { *imm_ref() }; - //~^ ERROR cannot move out of dereference of borrowed content + //~^ ERROR cannot move out of borrowed content let c = unsafe { *mut_ptr() }; //~^ ERROR cannot move out of dereference of unsafe pointer diff --git a/src/test/compile-fail/issue-2150.rs b/src/test/compile-fail/issue-2150.rs index a2711d532d2..79df16c8979 100644 --- a/src/test/compile-fail/issue-2150.rs +++ b/src/test/compile-fail/issue-2150.rs @@ -11,7 +11,6 @@ #![deny(unreachable_code)] #![allow(unused_variables)] #![allow(dead_code)] -#![feature(core)] fn fail_len(v: Vec ) -> usize { let mut i = 3; diff --git a/src/test/compile-fail/liveness-unused.rs b/src/test/compile-fail/liveness-unused.rs index d4238120d06..ac4b8a5f309 100644 --- a/src/test/compile-fail/liveness-unused.rs +++ b/src/test/compile-fail/liveness-unused.rs @@ -11,7 +11,6 @@ #![deny(unused_variables)] #![deny(unused_assignments)] #![allow(dead_code, non_camel_case_types)] -#![feature(core)] fn f1(x: isize) { //~^ ERROR unused variable: `x` diff --git a/src/test/run-make/issue-22131/Makefile b/src/test/run-make/issue-22131/Makefile index 46d89f0e2a6..0f927320c4e 100644 --- a/src/test/run-make/issue-22131/Makefile +++ b/src/test/run-make/issue-22131/Makefile @@ -2,5 +2,6 @@ all: foo.rs $(RUSTC) --cfg 'feature="bar"' --crate-type lib foo.rs - $(RUSTDOC) --test --cfg 'feature="bar"' -L $(TMPDIR) foo.rs |\ - grep --quiet 'test foo_0 ... ok' + $(HOST_RPATH_ENV) $(RUSTDOC) --test --cfg 'feature="bar"' \ + -L $(TMPDIR) foo.rs |\ + grep --quiet 'test foo_0 ... ok'