From 74648b5d647526e421d5015417968b64c1900512 Mon Sep 17 00:00:00 2001 From: Theo Belaire Date: Sat, 25 Apr 2015 14:09:41 -0400 Subject: [PATCH 01/97] First attempt at fixing #20591 This isn't quite right, but it's interesting. --- src/librustc_resolve/resolve_imports.rs | 11 +++++++++++ src/test/compile-fail/double-import.rs | 25 +++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 src/test/compile-fail/double-import.rs diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 4b488981bfbc..c099123ad259 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -903,6 +903,17 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { }, &token::get_name(name)); span_err!(self.resolver.session, import_span, E0252, "{}", &msg[..]); + if let Some(sp) = target.bindings.span_for_namespace(namespace) { + span_note!(self.resolver.session, sp, + "first import of {} `{}` here", + match namespace { + TypeNS => "type", + ValueNS => "value", + }, + token::get_name(name)); + } else { + span_note!(self.resolver.session, import_span, "I can't find where it was previously imported"); + } } Some(_) | None => {} } diff --git a/src/test/compile-fail/double-import.rs b/src/test/compile-fail/double-import.rs new file mode 100644 index 000000000000..3d0158a0830d --- /dev/null +++ b/src/test/compile-fail/double-import.rs @@ -0,0 +1,25 @@ +// Copyright 2013 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. +#![feature(no_std)] +#![no_std] + + +mod sub1 { + fn foo() {} // Implementation 1 +} + +mod sub2 { + fn foo() {} // Implementation 2 +} + +use sub1::foo; //~ NOTE first imported here +use sub2::foo; //~ ERROR a value named `foo` has already been imported in this module [E0252] + +fn main() {} From 168615f869ea560aa95e12a3c043c19110368be6 Mon Sep 17 00:00:00 2001 From: Theo Belaire Date: Sat, 25 Apr 2015 14:35:47 -0400 Subject: [PATCH 02/97] Now passing in the ImportResolver to check_conflict... It compiles, yay. --- src/librustc_resolve/resolve_imports.rs | 31 +++++++++++-------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index c099123ad259..daffe08fe3a1 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -618,7 +618,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { namespace_name, name_bindings.def_for_namespace(namespace)); self.check_for_conflicting_import( - &import_resolution.target_for_namespace(namespace), + &import_resolution, directive.span, target, namespace); @@ -755,7 +755,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { // Continue. } Some(ref value_target) => { - self.check_for_conflicting_import(&dest_import_resolution.value_target, + self.check_for_conflicting_import(&dest_import_resolution, import_directive.span, *ident, ValueNS); @@ -767,7 +767,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { // Continue. } Some(ref type_target) => { - self.check_for_conflicting_import(&dest_import_resolution.type_target, + self.check_for_conflicting_import(&dest_import_resolution, import_directive.span, *ident, TypeNS); @@ -885,32 +885,29 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { /// Checks that imported names and items don't have the same name. fn check_for_conflicting_import(&mut self, - target: &Option, + import_resolution: &ImportResolution, import_span: Span, name: Name, namespace: Namespace) { + let target = import_resolution.target_for_namespace(namespace); debug!("check_for_conflicting_import: {}; target exists: {}", &token::get_name(name), target.is_some()); - match *target { + match target { Some(ref target) if target.shadowable != Shadowable::Always => { - let msg = format!("a {} named `{}` has already been imported \ - in this module", - match namespace { - TypeNS => "type", - ValueNS => "value", - }, + let ns_word = match namespace { + TypeNS => "type", + ValueNS => "value", + }; + span_err!(self.resolver.session, import_span, E0252, + "a {} named `{}` has already been imported \ + in this module", ns_word, &token::get_name(name)); - span_err!(self.resolver.session, import_span, E0252, "{}", &msg[..]); if let Some(sp) = target.bindings.span_for_namespace(namespace) { span_note!(self.resolver.session, sp, "first import of {} `{}` here", - match namespace { - TypeNS => "type", - ValueNS => "value", - }, - token::get_name(name)); + ns_word, token::get_name(name)); } else { span_note!(self.resolver.session, import_span, "I can't find where it was previously imported"); } From 69a5c379dfbfdb17319eab061bef554845eca407 Mon Sep 17 00:00:00 2001 From: Theo Belaire Date: Sat, 25 Apr 2015 15:11:56 -0400 Subject: [PATCH 03/97] Maybe it works Still compiling, but I think I have it! --- src/librustc_resolve/resolve_imports.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index daffe08fe3a1..10068cf373ec 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -896,6 +896,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { match target { Some(ref target) if target.shadowable != Shadowable::Always => { + use syntax::ast_map::NodeItem; let ns_word = match namespace { TypeNS => "type", ValueNS => "value", @@ -904,12 +905,21 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { "a {} named `{}` has already been imported \ in this module", ns_word, &token::get_name(name)); + let use_id = import_resolution.id(namespace); + if let NodeItem(item) = self.resolver.ast_map.get(use_id) { + // Assert item.node is ItemUse + // I feel like this should maybe mention the type, + // as it's otherwise a bit of work to look up... + // use syntax::ast::Item; + span_note!(self.resolver.session, item.span, + "Previously import of {} `{}` here", + ns_word, token::get_name(name)); + } + // Also showing the definition is reasonable? if let Some(sp) = target.bindings.span_for_namespace(namespace) { span_note!(self.resolver.session, sp, - "first import of {} `{}` here", + "definition of {} `{}` here", ns_word, token::get_name(name)); - } else { - span_note!(self.resolver.session, import_span, "I can't find where it was previously imported"); } } Some(_) | None => {} From 5c05278fecf9b7d4ff64fe374fb5b4598908d064 Mon Sep 17 00:00:00 2001 From: Theo Belaire Date: Sat, 25 Apr 2015 15:45:29 -0400 Subject: [PATCH 04/97] Fixed types, and slimmed down code I don't this we need to print the definition of the imported value too, though it's quite possible. --- src/librustc_resolve/resolve_imports.rs | 16 ++++------------ src/test/compile-fail/double-import.rs | 8 ++++---- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 10068cf373ec..e731e8a5ce21 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -897,6 +897,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { match target { Some(ref target) if target.shadowable != Shadowable::Always => { use syntax::ast_map::NodeItem; + let ns_word = match namespace { TypeNS => "type", ValueNS => "value", @@ -907,19 +908,10 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { &token::get_name(name)); let use_id = import_resolution.id(namespace); if let NodeItem(item) = self.resolver.ast_map.get(use_id) { - // Assert item.node is ItemUse - // I feel like this should maybe mention the type, - // as it's otherwise a bit of work to look up... - // use syntax::ast::Item; + // item is syntax::ast::Item; span_note!(self.resolver.session, item.span, - "Previously import of {} `{}` here", - ns_word, token::get_name(name)); - } - // Also showing the definition is reasonable? - if let Some(sp) = target.bindings.span_for_namespace(namespace) { - span_note!(self.resolver.session, sp, - "definition of {} `{}` here", - ns_word, token::get_name(name)); + "previous import of `{}` here", + token::get_name(name)); } } Some(_) | None => {} diff --git a/src/test/compile-fail/double-import.rs b/src/test/compile-fail/double-import.rs index 3d0158a0830d..d267efe8b25e 100644 --- a/src/test/compile-fail/double-import.rs +++ b/src/test/compile-fail/double-import.rs @@ -12,14 +12,14 @@ mod sub1 { - fn foo() {} // Implementation 1 + fn foo() {} // implementation 1 } mod sub2 { - fn foo() {} // Implementation 2 + fn foo() {} // implementation 2 } -use sub1::foo; //~ NOTE first imported here -use sub2::foo; //~ ERROR a value named `foo` has already been imported in this module [E0252] +use sub1::foo; //~ note previous import of `foo` here +use sub2::foo; //~ error a value named `foo` has already been imported in this module [e0252] fn main() {} From 372c69d8d293985ad3bffbe5c5e527dc37e90169 Mon Sep 17 00:00:00 2001 From: Theo Belaire Date: Mon, 27 Apr 2015 00:45:51 -0400 Subject: [PATCH 05/97] Fixed test text --- src/test/compile-fail/double-import.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/compile-fail/double-import.rs b/src/test/compile-fail/double-import.rs index d267efe8b25e..e564d39f80de 100644 --- a/src/test/compile-fail/double-import.rs +++ b/src/test/compile-fail/double-import.rs @@ -19,7 +19,7 @@ mod sub2 { fn foo() {} // implementation 2 } -use sub1::foo; //~ note previous import of `foo` here -use sub2::foo; //~ error a value named `foo` has already been imported in this module [e0252] +use sub1::foo; //~ NOTE previous import of `foo` here +use sub2::foo; //~ ERROR a value named `foo` has already been imported in this module [E0252] fn main() {} From a4c133777e33754137d8a097a0c932cfc45ec8a5 Mon Sep 17 00:00:00 2001 From: Jannis Redmann Date: Wed, 29 Apr 2015 17:55:14 +0200 Subject: [PATCH 06/97] link to .editorconfig for Rust files I've written a small [EditorConfig](http://editorconfig.org) file for Rust development. --- src/etc/CONFIGS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/etc/CONFIGS.md b/src/etc/CONFIGS.md index 036a2f7d4365..def5ab05fe2f 100644 --- a/src/etc/CONFIGS.md +++ b/src/etc/CONFIGS.md @@ -2,6 +2,7 @@ Here are some links to repos with configs which ease the use of rust: +* [.editorconfig](https://gist.github.com/derhuerst/c9d1b9309e308d9851fa) ([what is this?](http://editorconfig.org/)) * [rust.vim](https://github.com/rust-lang/rust.vim) * [emacs rust-mode](https://github.com/rust-lang/rust-mode) * [gedit-config](https://github.com/rust-lang/gedit-config) From 6f3641de83b2b3a5c52557b424489bc9fc350571 Mon Sep 17 00:00:00 2001 From: Jannis Redmann Date: Wed, 29 Apr 2015 18:53:36 +0200 Subject: [PATCH 07/97] distinction between official and community plugins --- src/etc/CONFIGS.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/etc/CONFIGS.md b/src/etc/CONFIGS.md index def5ab05fe2f..74837a06faec 100644 --- a/src/etc/CONFIGS.md +++ b/src/etc/CONFIGS.md @@ -1,11 +1,16 @@ # Configs -Here are some links to repos with configs which ease the use of rust: +These are some links to repos with configs which ease the use of rust. + +## Officially Maintained Configs -* [.editorconfig](https://gist.github.com/derhuerst/c9d1b9309e308d9851fa) ([what is this?](http://editorconfig.org/)) * [rust.vim](https://github.com/rust-lang/rust.vim) * [emacs rust-mode](https://github.com/rust-lang/rust-mode) * [gedit-config](https://github.com/rust-lang/gedit-config) * [kate-config](https://github.com/rust-lang/kate-config) * [nano-config](https://github.com/rust-lang/nano-config) * [zsh-config](https://github.com/rust-lang/zsh-config) + +## Community-maintained Configs + +* [.editorconfig](https://gist.github.com/derhuerst/c9d1b9309e308d9851fa) ([what is this?](http://editorconfig.org/)) From db9d01842450fe07f77ca97d9a68d105366f407e Mon Sep 17 00:00:00 2001 From: Theo Belaire Date: Thu, 30 Apr 2015 22:46:15 -0400 Subject: [PATCH 08/97] Fixed some nits --- src/librustc_resolve/resolve_imports.rs | 13 +++++-------- src/test/compile-fail/double-import.rs | 4 +++- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index e731e8a5ce21..91eb068e845a 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -896,8 +896,6 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { match target { Some(ref target) if target.shadowable != Shadowable::Always => { - use syntax::ast_map::NodeItem; - let ns_word = match namespace { TypeNS => "type", ValueNS => "value", @@ -907,12 +905,11 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { in this module", ns_word, &token::get_name(name)); let use_id = import_resolution.id(namespace); - if let NodeItem(item) = self.resolver.ast_map.get(use_id) { - // item is syntax::ast::Item; - span_note!(self.resolver.session, item.span, - "previous import of `{}` here", - token::get_name(name)); - } + let item = self.resolver.ast_map.expect_item(use_id); + // item is syntax::ast::Item; + span_note!(self.resolver.session, item.span, + "previous import of `{}` here", + token::get_name(name)); } Some(_) | None => {} } diff --git a/src/test/compile-fail/double-import.rs b/src/test/compile-fail/double-import.rs index e564d39f80de..cbf13c0a5590 100644 --- a/src/test/compile-fail/double-import.rs +++ b/src/test/compile-fail/double-import.rs @@ -1,4 +1,4 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -10,6 +10,8 @@ #![feature(no_std)] #![no_std] +// This tests that conflicting imports shows both `use` lines +// when reporting the error. mod sub1 { fn foo() {} // implementation 1 From 7ec81722250efc7798d9163574e01eec5cde85ca Mon Sep 17 00:00:00 2001 From: Carol Nichols Date: Sat, 2 May 2015 16:25:49 -0400 Subject: [PATCH 09/97] Update old uses of ~ in comments and debugging statements --- src/librustc/middle/expr_use_visitor.rs | 2 +- src/librustc/middle/traits/coherence.rs | 2 +- src/librustc/middle/traits/select.rs | 6 +++--- src/librustc/util/ppaux.rs | 2 +- src/librustc_borrowck/borrowck/check_loans.rs | 2 +- src/librustc_privacy/lib.rs | 2 +- src/librustc_trans/back/link.rs | 2 +- src/librustc_trans/save/span_utils.rs | 6 +++--- src/librustc_trans/trans/attributes.rs | 4 ++-- src/librustc_typeck/check/mod.rs | 2 +- src/librustc_typeck/variance.rs | 4 ++-- src/librustdoc/clean/mod.rs | 2 +- src/libsyntax/ext/deriving/generic/mod.rs | 4 ++-- src/libsyntax/ext/expand.rs | 2 +- src/libsyntax/print/pp.rs | 18 +++++++++--------- src/libtest/lib.rs | 4 ++-- src/test/compile-fail/kindck-copy.rs | 2 +- src/test/debuginfo/issue11600.rs | 2 +- src/test/run-pass/const-bound.rs | 2 +- src/test/run-pass/issue-3556.rs | 4 ---- 20 files changed, 35 insertions(+), 39 deletions(-) diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index d740d24e2367..359ea02c1d74 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -1125,7 +1125,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { // that case we can adjust the length of the // original vec accordingly, but we'd have to // make trans do the right thing, and it would - // only work for `~` vectors. It seems simpler + // only work for `Vec`s. It seems simpler // to just require that people call // `vec.pop()` or `vec.unshift()`. let slice_bk = ty::BorrowKind::from_mutbl(slice_mutbl); diff --git a/src/librustc/middle/traits/coherence.rs b/src/librustc/middle/traits/coherence.rs index d9f8a88fddca..222da6d7c3e5 100644 --- a/src/librustc/middle/traits/coherence.rs +++ b/src/librustc/middle/traits/coherence.rs @@ -323,7 +323,7 @@ fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>, def_id.krate == ast::LOCAL_CRATE } - ty::ty_uniq(_) => { // treat ~T like Box + ty::ty_uniq(_) => { // Box let krate = tcx.lang_items.owned_box().map(|d| d.krate); krate == Some(ast::LOCAL_CRATE) } diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 49371eae2652..9a5e7219aaa8 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -2441,10 +2441,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// `match_impl()`. For example, if `impl_def_id` is declared /// as: /// - /// impl Foo for ~T { ... } + /// impl Foo for Box { ... } /// - /// and `obligation_self_ty` is `int`, we'd back an `Err(_)` - /// result. But if `obligation_self_ty` were `~int`, we'd get + /// and `obligation_self_ty` is `int`, we'd get back an `Err(_)` + /// result. But if `obligation_self_ty` were `Box`, we'd get /// back `Ok(T=int)`. fn match_inherent_impl(&mut self, impl_def_id: ast::DefId, diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index aa89c1943a2e..32ec70c48788 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -637,7 +637,7 @@ impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for OwnedSlice { } } -// This is necessary to handle types like Option<~[T]>, for which +// This is necessary to handle types like Option>, for which // autoderef cannot convert the &[T] handler impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Vec { fn repr(&self, tcx: &ctxt<'tcx>) -> String { diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index 9776538de3fe..839b39a8ca00 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -732,7 +732,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { /// let p: Point; /// p.x = 22; // ok, even though `p` is uninitialized /// - /// let p: ~Point; + /// let p: Box; /// (*p).x = 22; // not ok, p is uninitialized, can't deref /// ``` fn check_if_assigned_path_is_moved(&self, diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 128e29ee76e7..9a8bbc5ea0bc 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1314,7 +1314,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { // `impl [... for] Private` is never visible. let self_contains_private; // impl [... for] Public<...>, but not `impl [... for] - // ~[Public]` or `(Public,)` etc. + // Vec` or `(Public,)` etc. let self_is_public_path; // check the properties of the Self type: diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 92c9549b3772..49e336c67007 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -288,7 +288,7 @@ pub fn mangle>(path: PI, // when using unix's linker. Perhaps one day when we just use a linker from LLVM // we won't need to do this name mangling. The problem with name mangling is // that it seriously limits the available characters. For example we can't - // have things like &T or ~[T] in symbol names when one would theoretically + // have things like &T or Vec in symbol names when one would theoretically // want them for things like impls of traits on that type. // // To be able to work on all platforms and get *some* reasonable output, we diff --git a/src/librustc_trans/save/span_utils.rs b/src/librustc_trans/save/span_utils.rs index 84a7678959d3..504663571f53 100644 --- a/src/librustc_trans/save/span_utils.rs +++ b/src/librustc_trans/save/span_utils.rs @@ -230,8 +230,8 @@ impl<'a> SpanUtils<'a> { // Reparse span and return an owned vector of sub spans of the first limit // identifier tokens in the given nesting level. // example with Foo, Bar> - // Nesting = 0: all idents outside of brackets: ~[Foo] - // Nesting = 1: idents within one level of brackets: ~[Bar, Bar] + // Nesting = 0: all idents outside of brackets: Vec + // Nesting = 1: idents within one level of brackets: Vec pub fn spans_with_brackets(&self, span: Span, nesting: isize, limit: isize) -> Vec { let mut result: Vec = vec!(); @@ -352,7 +352,7 @@ impl<'a> SpanUtils<'a> { return vec!(); } // Type params are nested within one level of brackets: - // i.e. we want ~[A, B] from Foo> + // i.e. we want Vec from Foo> self.spans_with_brackets(span, 1, number) } diff --git a/src/librustc_trans/trans/attributes.rs b/src/librustc_trans/trans/attributes.rs index b44ccec0127b..8086f88deeee 100644 --- a/src/librustc_trans/trans/attributes.rs +++ b/src/librustc_trans/trans/attributes.rs @@ -196,7 +196,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx // The `noalias` attribute on the return value is useful to a // function ptr caller. match ret_ty.sty { - // `~` pointer return values never alias because ownership + // `Box` pointer return values never alias because ownership // is transferred ty::ty_uniq(it) if common::type_is_sized(ccx.tcx(), it) => { attrs.ret(llvm::Attribute::NoAliasAttribute); @@ -239,7 +239,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx attrs.arg(idx, llvm::Attribute::ZExtAttribute); } - // `~` pointer parameters never alias because ownership is transferred + // `Box` pointer parameters never alias because ownership is transferred ty::ty_uniq(inner) => { let llsz = machine::llsize_of_real(ccx, type_of::type_of(ccx, inner)); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c05c1c6b0852..3769e9fa0f36 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2458,7 +2458,7 @@ fn check_expr_with_lvalue_pref<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast:: } // determine the `self` type, using fresh variables for all variables -// declared on the impl declaration e.g., `impl for ~[(A,B)]` +// declared on the impl declaration e.g., `impl for Vec<(A,B)>` // would return ($0, $1) where $0 and $1 are freshly instantiated type // variables. pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index 9e8c23734e3c..7c062d354d39 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -178,8 +178,8 @@ //! further that for whatever reason I specifically supply the value of //! `String` for the type parameter `T`: //! -//! let mut vector = ~["string", ...]; -//! convertAll::(v); +//! let mut vector = vec!["string", ...]; +//! convertAll::(vector); //! //! Is this legal? To put another way, can we apply the `impl` for //! `Object` to the type `String`? The answer is yes, but to see why diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1e6e9a7562a7..8f78841ef792 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -897,7 +897,7 @@ impl<'tcx> Clean for ty::ProjectionTy<'tcx> { } } -// maybe use a Generic enum and use ~[Generic]? +// maybe use a Generic enum and use Vec? #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] pub struct Generics { pub lifetimes: Vec, diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 339e535cdcd9..eb6d0c0285f7 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -896,8 +896,8 @@ impl<'a> MethodDef<'a> { nonself_args: &[P]) -> P { - let mut raw_fields = Vec::new(); // ~[[fields of self], - // [fields of next Self arg], [etc]] + let mut raw_fields = Vec::new(); // Vec<[fields of self], + // [fields of next Self arg], [etc]> let mut patterns = Vec::new(); for i in 0..self_args.len() { let struct_path= cx.path(DUMMY_SP, vec!( type_ident )); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 4ea2d4e5c686..b471e06492d4 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1691,7 +1691,7 @@ mod tests { // induced by visit. Each of these arrays contains a list of indexes, // interpreted as the varrefs in the varref traversal that this binding // should match. So, for instance, in a program with two bindings and - // three varrefs, the array ~[~[1,2],~[0]] would indicate that the first + // three varrefs, the array [[1, 2], [0]] would indicate that the first // binding should match the second two varrefs, and the second binding // should match the first varref. // diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index 15aaf9cf390f..ed9937c53f4a 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -312,7 +312,7 @@ impl<'a> Printer<'a> { self.token[self.right] = t; } pub fn pretty_print(&mut self, token: Token) -> io::Result<()> { - debug!("pp ~[{},{}]", self.left, self.right); + debug!("pp Vec<{},{}>", self.left, self.right); match token { Token::Eof => { if !self.scan_stack_empty { @@ -329,7 +329,7 @@ impl<'a> Printer<'a> { self.left = 0; self.right = 0; } else { self.advance_right(); } - debug!("pp Begin({})/buffer ~[{},{}]", + debug!("pp Begin({})/buffer Vec<{},{}>", b.offset, self.left, self.right); self.token[self.right] = token; self.size[self.right] = -self.right_total; @@ -339,10 +339,10 @@ impl<'a> Printer<'a> { } Token::End => { if self.scan_stack_empty { - debug!("pp End/print ~[{},{}]", self.left, self.right); + debug!("pp End/print Vec<{},{}>", self.left, self.right); self.print(token, 0) } else { - debug!("pp End/buffer ~[{},{}]", self.left, self.right); + debug!("pp End/buffer Vec<{},{}>", self.left, self.right); self.advance_right(); self.token[self.right] = token; self.size[self.right] = -1; @@ -358,7 +358,7 @@ impl<'a> Printer<'a> { self.left = 0; self.right = 0; } else { self.advance_right(); } - debug!("pp Break({})/buffer ~[{},{}]", + debug!("pp Break({})/buffer Vec<{},{}>", b.offset, self.left, self.right); self.check_stack(0); let right = self.right; @@ -370,11 +370,11 @@ impl<'a> Printer<'a> { } Token::String(s, len) => { if self.scan_stack_empty { - debug!("pp String('{}')/print ~[{},{}]", + debug!("pp String('{}')/print Vec<{},{}>", s, self.left, self.right); self.print(Token::String(s, len), len) } else { - debug!("pp String('{}')/buffer ~[{},{}]", + debug!("pp String('{}')/buffer Vec<{},{}>", s, self.left, self.right); self.advance_right(); self.token[self.right] = Token::String(s, len); @@ -386,7 +386,7 @@ impl<'a> Printer<'a> { } } pub fn check_stream(&mut self) -> io::Result<()> { - debug!("check_stream ~[{}, {}] with left_total={}, right_total={}", + debug!("check_stream Vec<{}, {}> with left_total={}, right_total={}", self.left, self.right, self.left_total, self.right_total); if self.right_total - self.left_total > self.space { debug!("scan window is {}, longer than space on line ({})", @@ -446,7 +446,7 @@ impl<'a> Printer<'a> { assert!((self.right != self.left)); } pub fn advance_left(&mut self) -> io::Result<()> { - debug!("advance_left ~[{},{}], sizeof({})={}", self.left, self.right, + debug!("advance_left Vec<{},{}>, sizeof({})={}", self.left, self.right, self.left, self.size[self.left]); let mut left_size = self.size[self.left]; diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 9cbfe283cbdd..31eb9b7fa276 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -259,8 +259,8 @@ pub fn test_main(args: &[String], tests: Vec ) { // This will panic (intentionally) when fed any dynamic tests, because // it is copying the static values out into a dynamic vector and cannot // copy dynamic values. It is doing this because from this point on -// a ~[TestDescAndFn] is used in order to effect ownership-transfer -// semantics into parallel test runners, which in turn requires a ~[] +// a Vec is used in order to effect ownership-transfer +// semantics into parallel test runners, which in turn requires a Vec<> // rather than a &[]. pub fn test_main_static(args: env::Args, tests: &[TestDescAndFn]) { let args = args.collect::>(); diff --git a/src/test/compile-fail/kindck-copy.rs b/src/test/compile-fail/kindck-copy.rs index d43ddff6b950..95ab2bbab14a 100644 --- a/src/test/compile-fail/kindck-copy.rs +++ b/src/test/compile-fail/kindck-copy.rs @@ -37,7 +37,7 @@ fn test<'a,T,U:Copy>(_: &'a isize) { assert_copy::<&'static mut isize>(); //~ ERROR `core::marker::Copy` is not implemented assert_copy::<&'a mut isize>(); //~ ERROR `core::marker::Copy` is not implemented - // ~ pointers are not ok + // owned pointers are not ok assert_copy::>(); //~ ERROR `core::marker::Copy` is not implemented assert_copy::(); //~ ERROR `core::marker::Copy` is not implemented assert_copy:: >(); //~ ERROR `core::marker::Copy` is not implemented diff --git a/src/test/debuginfo/issue11600.rs b/src/test/debuginfo/issue11600.rs index e93704cac34c..b79cba7aa697 100644 --- a/src/test/debuginfo/issue11600.rs +++ b/src/test/debuginfo/issue11600.rs @@ -25,6 +25,6 @@ fn main() { // compile-flags:-g // gdb-command:list // gdb-check:1[...]fn main() { -// gdb-check:2[...]let args : ~[String] = ::std::os::args(); +// gdb-check:2[...]let args : Vec = ::std::os::args(); // gdb-check:3[...]::std::io::println(args[0]); // gdb-check:4[...]} diff --git a/src/test/run-pass/const-bound.rs b/src/test/run-pass/const-bound.rs index 5c2985ffa777..72a23b998e5a 100644 --- a/src/test/run-pass/const-bound.rs +++ b/src/test/run-pass/const-bound.rs @@ -20,7 +20,7 @@ struct F { field: isize } pub fn main() { /*foo(1); foo("hi".to_string()); - foo(~[1, 2, 3]); + foo(vec![1, 2, 3]); foo(F{field: 42}); foo((1, 2)); foo(@1);*/ diff --git a/src/test/run-pass/issue-3556.rs b/src/test/run-pass/issue-3556.rs index 0efa85e232ba..e6b577ada0c8 100644 --- a/src/test/run-pass/issue-3556.rs +++ b/src/test/run-pass/issue-3556.rs @@ -32,10 +32,6 @@ fn check_strs(actual: &str, expected: &str) -> bool pub fn main() { -// assert!(check_strs(fmt!("%?", Text(@"foo".to_string())), "Text(@~\"foo\")")); -// assert!(check_strs(fmt!("%?", ETag(@~["foo".to_string()], @"bar".to_string())), -// "ETag(@~[ ~\"foo\" ], @~\"bar\")")); - let t = Token::Text("foo".to_string()); let u = Token::Section(vec!["alpha".to_string()], true, From 232b2022b515fdba7e06354c635998cbc0d76114 Mon Sep 17 00:00:00 2001 From: Carol Nichols Date: Sat, 2 May 2015 16:26:45 -0400 Subject: [PATCH 10/97] Update debuginfo metadata to use Box instead of ~ Also remove comments that reference the unique_type_id HEAP_VEC_BOX metadata, which was removed in 3e62637 and the unique_type_id GC_BOX metadata, which was removed in 8a91d33. --- .../trans/debuginfo/metadata.rs | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/src/librustc_trans/trans/debuginfo/metadata.rs b/src/librustc_trans/trans/debuginfo/metadata.rs index 9ff69e7f9dd2..29c22c8c9f71 100644 --- a/src/librustc_trans/trans/debuginfo/metadata.rs +++ b/src/librustc_trans/trans/debuginfo/metadata.rs @@ -142,26 +142,24 @@ impl<'tcx> TypeMap<'tcx> { fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>, type_: Ty<'tcx>) -> UniqueTypeId { - // basic type -> {:name of the type:} - // tuple -> {tuple_(:param-uid:)*} - // struct -> {struct_:svh: / :node-id:_<(:param-uid:),*> } - // enum -> {enum_:svh: / :node-id:_<(:param-uid:),*> } - // enum variant -> {variant_:variant-name:_:enum-uid:} - // reference (&) -> {& :pointee-uid:} - // mut reference (&mut) -> {&mut :pointee-uid:} - // ptr (*) -> {* :pointee-uid:} - // mut ptr (*mut) -> {*mut :pointee-uid:} - // unique ptr (~) -> {~ :pointee-uid:} - // @-ptr (@) -> {@ :pointee-uid:} - // sized vec ([T; x]) -> {[:size:] :element-uid:} - // unsized vec ([T]) -> {[] :element-uid:} - // trait (T) -> {trait_:svh: / :node-id:_<(:param-uid:),*> } - // closure -> { :store-sigil: |(:param-uid:),* <,_...>| -> \ + // basic type -> {:name of the type:} + // tuple -> {tuple_(:param-uid:)*} + // struct -> {struct_:svh: / :node-id:_<(:param-uid:),*> } + // enum -> {enum_:svh: / :node-id:_<(:param-uid:),*> } + // enum variant -> {variant_:variant-name:_:enum-uid:} + // reference (&) -> {& :pointee-uid:} + // mut reference (&mut) -> {&mut :pointee-uid:} + // ptr (*) -> {* :pointee-uid:} + // mut ptr (*mut) -> {*mut :pointee-uid:} + // unique ptr (Box) -> {Box :pointee-uid:} + // @-ptr (@) -> {@ :pointee-uid:} + // sized vec ([T; x]) -> {[:size:] :element-uid:} + // unsized vec ([T]) -> {[] :element-uid:} + // trait (T) -> {trait_:svh: / :node-id:_<(:param-uid:),*> } + // closure -> { :store-sigil: |(:param-uid:),* <,_...>| -> \ // :return-type-uid: : (:bounds:)*} - // function -> { fn( (:param-uid:)* <,_...> ) -> \ + // function -> { fn( (:param-uid:)* <,_...> ) -> \ // :return-type-uid:} - // unique vec box (~[]) -> {HEAP_VEC_BOX<:pointee-uid:>} - // gc box -> {GC_BOX<:pointee-uid:>} match self.type_to_unique_id.get(&type_).cloned() { Some(unique_type_id) => return unique_type_id, @@ -202,7 +200,7 @@ impl<'tcx> TypeMap<'tcx> { } }, ty::ty_uniq(inner_type) => { - unique_type_id.push('~'); + unique_type_id.push_str("Box "); let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type); let inner_type_id = self.get_unique_type_id_as_string(inner_type_id); unique_type_id.push_str(&inner_type_id[..]); From d3667746d417228f551a91886b7215c9e3038056 Mon Sep 17 00:00:00 2001 From: Carol Nichols Date: Sat, 2 May 2015 16:28:53 -0400 Subject: [PATCH 11/97] Update tests to not use old ~ syntax --- src/test/debuginfo/issue11600.rs | 2 +- src/test/run-pass/issue-4241.rs | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/test/debuginfo/issue11600.rs b/src/test/debuginfo/issue11600.rs index b79cba7aa697..dea2a0c5a23f 100644 --- a/src/test/debuginfo/issue11600.rs +++ b/src/test/debuginfo/issue11600.rs @@ -13,7 +13,7 @@ // ignore-test fn main() { - let args : ~[String] = ::std::os::args(); + let args : Vec = ::std::os::args(); ::std::io::println(args[0]); } diff --git a/src/test/run-pass/issue-4241.rs b/src/test/run-pass/issue-4241.rs index c9b684fd6569..ab75c2064a40 100644 --- a/src/test/run-pass/issue-4241.rs +++ b/src/test/run-pass/issue-4241.rs @@ -22,8 +22,8 @@ use std::io::{ReaderUtil,WriterUtil}; enum Result { Nil, Int(isize), - Data(~[u8]), - List(~[Result]), + Data(Vec), + List(Vec), Error(String), Status(String) } @@ -35,7 +35,7 @@ fn parse_data(len: usize, io: @io::Reader) -> Result { assert_eq!(bytes.len(), len); Data(bytes) } else { - Data(~[]) + Data(vec![]) }; assert_eq!(io.read_char(), '\r'); assert_eq!(io.read_char(), '\n'); @@ -43,7 +43,7 @@ fn parse_data(len: usize, io: @io::Reader) -> Result { } fn parse_list(len: usize, io: @io::Reader) -> Result { - let mut list: ~[Result] = ~[]; + let mut list: Vec = vec![]; for _ in 0..len { let v = match io.read_char() { '$' => parse_bulk(io), @@ -72,7 +72,7 @@ fn parse_multi(io: @io::Reader) -> Result { match from_str::(chop(io.read_line())) { None => panic!(), Some(-1) => Nil, - Some(0) => List(~[]), + Some(0) => List(vec![]), Some(len) if len >= 0 => parse_list(len as usize, io), Some(_) => panic!() } @@ -96,7 +96,7 @@ fn parse_response(io: @io::Reader) -> Result { } } -fn cmd_to_string(cmd: ~[String]) -> String { +fn cmd_to_string(cmd: Vec) -> String { let mut res = "*".to_string(); res.push_str(cmd.len().to_string()); res.push_str("\r\n"); @@ -107,7 +107,7 @@ fn cmd_to_string(cmd: ~[String]) -> String { res } -fn query(cmd: ~[String], sb: TcpSocketBuf) -> Result { +fn query(cmd: Vec, sb: TcpSocketBuf) -> Result { let cmd = cmd_to_string(cmd); //println!("{}", cmd); sb.write_str(cmd); @@ -115,7 +115,7 @@ fn query(cmd: ~[String], sb: TcpSocketBuf) -> Result { res } -fn query2(cmd: ~[String]) -> Result { +fn query2(cmd: Vec) -> Result { let _cmd = cmd_to_string(cmd); io::with_str_reader("$3\r\nXXX\r\n".to_string())(|sb| { let res = parse_response(@sb as @io::Reader); From 55e7f9b7d680d8085765c7c659351d3efe09ffb8 Mon Sep 17 00:00:00 2001 From: Carol Nichols Date: Mon, 4 May 2015 21:33:51 -0400 Subject: [PATCH 12/97] Changing Vec to Box<[T]> --- src/librustc/middle/expr_use_visitor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 359ea02c1d74..0458bd70346c 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -1125,7 +1125,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { // that case we can adjust the length of the // original vec accordingly, but we'd have to // make trans do the right thing, and it would - // only work for `Vec`s. It seems simpler + // only work for `Box<[T]>`s. It seems simpler // to just require that people call // `vec.pop()` or `vec.unshift()`. let slice_bk = ty::BorrowKind::from_mutbl(slice_mutbl); From 77acf7b4ee533bf0d84ee5097dfb6676e2f4360e Mon Sep 17 00:00:00 2001 From: Carol Nichols Date: Mon, 4 May 2015 21:43:11 -0400 Subject: [PATCH 13/97] Use the lowercase version of the box syntax --- src/librustc_trans/trans/debuginfo/metadata.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_trans/trans/debuginfo/metadata.rs b/src/librustc_trans/trans/debuginfo/metadata.rs index 29c22c8c9f71..bd04bd7a7546 100644 --- a/src/librustc_trans/trans/debuginfo/metadata.rs +++ b/src/librustc_trans/trans/debuginfo/metadata.rs @@ -151,7 +151,7 @@ impl<'tcx> TypeMap<'tcx> { // mut reference (&mut) -> {&mut :pointee-uid:} // ptr (*) -> {* :pointee-uid:} // mut ptr (*mut) -> {*mut :pointee-uid:} - // unique ptr (Box) -> {Box :pointee-uid:} + // unique ptr (box) -> {box :pointee-uid:} // @-ptr (@) -> {@ :pointee-uid:} // sized vec ([T; x]) -> {[:size:] :element-uid:} // unsized vec ([T]) -> {[] :element-uid:} @@ -200,7 +200,7 @@ impl<'tcx> TypeMap<'tcx> { } }, ty::ty_uniq(inner_type) => { - unique_type_id.push_str("Box "); + unique_type_id.push_str("box "); let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type); let inner_type_id = self.get_unique_type_id_as_string(inner_type_id); unique_type_id.push_str(&inner_type_id[..]); From abc0017f3b2308c3bff2a975d4e33b53c2f52bdb Mon Sep 17 00:00:00 2001 From: Carol Nichols Date: Mon, 4 May 2015 21:44:22 -0400 Subject: [PATCH 14/97] Remove an obsolete example in a comment --- src/librustc_trans/back/link.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 49e336c67007..e97f8d9be127 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -288,7 +288,7 @@ pub fn mangle>(path: PI, // when using unix's linker. Perhaps one day when we just use a linker from LLVM // we won't need to do this name mangling. The problem with name mangling is // that it seriously limits the available characters. For example we can't - // have things like &T or Vec in symbol names when one would theoretically + // have things like &T in symbol names when one would theoretically // want them for things like impls of traits on that type. // // To be able to work on all platforms and get *some* reasonable output, we From efb3872a49df2d4ffe5bdc948d1d12637fa3ebd1 Mon Sep 17 00:00:00 2001 From: Sean Patrick Santos Date: Thu, 7 May 2015 01:52:38 -0600 Subject: [PATCH 15/97] Fix use of UFCS syntax to call methods on associated types. --- src/librustc_resolve/lib.rs | 23 ++++---- src/libsyntax/parse/parser.rs | 50 +++++------------ .../run-pass/associated-item-long-paths.rs | 55 +++++++++++++++++++ 3 files changed, 83 insertions(+), 45 deletions(-) create mode 100644 src/test/run-pass/associated-item-long-paths.rs diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 7abe5a84c5ff..447230ada223 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2688,18 +2688,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { check_ribs: bool) -> AssocItemResolveResult { + let max_assoc_types; + match maybe_qself { - Some(&ast::QSelf { position: 0, .. }) => - return TypecheckRequired, - _ => {} + Some(qself) => { + if qself.position == 0 { + return TypecheckRequired; + } + max_assoc_types = path.segments.len() - qself.position; + // Make sure the trait is valid. + let _ = self.resolve_trait_reference(id, path, max_assoc_types); + } + None => { + max_assoc_types = path.segments.len(); + } } - let max_assoc_types = if let Some(qself) = maybe_qself { - // Make sure the trait is valid. - let _ = self.resolve_trait_reference(id, path, 1); - path.segments.len() - qself.position - } else { - path.segments.len() - }; let mut resolution = self.with_no_errors(|this| { this.resolve_path(id, path, 0, namespace, check_ribs) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a7b1beace51d..a5a667ae5ce6 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -110,15 +110,6 @@ pub enum PathParsingMode { LifetimeAndTypesWithColons, } -/// How to parse a qualified path, whether to allow trailing parameters. -#[derive(Copy, Clone, PartialEq)] -pub enum QPathParsingMode { - /// No trailing parameters, e.g. `::Item` - NoParameters, - /// Optional parameters, e.g. `::item::<'a, U>` - MaybeParameters, -} - /// How to parse a bound, whether to allow bound modifiers such as `?`. #[derive(Copy, Clone, PartialEq)] pub enum BoundParsingMode { @@ -1360,7 +1351,7 @@ impl<'a> Parser<'a> { } else if try!(self.eat_lt()) { let (qself, path) = - try!(self.parse_qualified_path(QPathParsingMode::NoParameters)); + try!(self.parse_qualified_path(NoTypesAllowed)); TyPath(Some(qself), path) } else if self.check(&token::ModSep) || @@ -1579,7 +1570,7 @@ impl<'a> Parser<'a> { // QUALIFIED PATH `::IDENT[::]` // Assumes that the leading `<` has been parsed already. - pub fn parse_qualified_path(&mut self, mode: QPathParsingMode) + pub fn parse_qualified_path(&mut self, mode: PathParsingMode) -> PResult<(QSelf, ast::Path)> { let self_type = try!(self.parse_ty_sum()); let mut path = if try!(self.eat_keyword(keywords::As)) { @@ -1600,29 +1591,18 @@ impl<'a> Parser<'a> { try!(self.expect(&token::Gt)); try!(self.expect(&token::ModSep)); - let item_name = try!(self.parse_ident()); - let parameters = match mode { - QPathParsingMode::NoParameters => ast::PathParameters::none(), - QPathParsingMode::MaybeParameters => { - if try!(self.eat(&token::ModSep)) { - try!(self.expect_lt()); - // Consumed `item::<`, go look for types - let (lifetimes, types, bindings) = - try!(self.parse_generic_values_after_lt()); - ast::AngleBracketedParameters(ast::AngleBracketedParameterData { - lifetimes: lifetimes, - types: OwnedSlice::from_vec(types), - bindings: OwnedSlice::from_vec(bindings), - }) - } else { - ast::PathParameters::none() - } + let segments = match mode { + LifetimeAndTypesWithoutColons => { + try!(self.parse_path_segments_without_colons()) + } + LifetimeAndTypesWithColons => { + try!(self.parse_path_segments_with_colons()) + } + NoTypesAllowed => { + try!(self.parse_path_segments_without_types()) } }; - path.segments.push(ast::PathSegment { - identifier: item_name, - parameters: parameters - }); + path.segments.extend(segments); if path.segments.len() == 1 { path.span.lo = self.last_span.lo; @@ -2097,7 +2077,7 @@ impl<'a> Parser<'a> { if try!(self.eat_lt()){ let (qself, path) = - try!(self.parse_qualified_path(QPathParsingMode::MaybeParameters)); + try!(self.parse_qualified_path(LifetimeAndTypesWithColons)); return Ok(self.mk_expr(lo, hi, ExprPath(Some(qself), path))); } @@ -3177,7 +3157,7 @@ impl<'a> Parser<'a> { let (qself, path) = if try!(self.eat_lt()) { // Parse a qualified path let (qself, path) = - try!(self.parse_qualified_path(QPathParsingMode::NoParameters)); + try!(self.parse_qualified_path(NoTypesAllowed)); (Some(qself), path) } else { // Parse an unqualified path @@ -3271,7 +3251,7 @@ impl<'a> Parser<'a> { let (qself, path) = if try!(self.eat_lt()) { // Parse a qualified path let (qself, path) = - try!(self.parse_qualified_path(QPathParsingMode::NoParameters)); + try!(self.parse_qualified_path(NoTypesAllowed)); (Some(qself), path) } else { // Parse an unqualified path diff --git a/src/test/run-pass/associated-item-long-paths.rs b/src/test/run-pass/associated-item-long-paths.rs new file mode 100644 index 000000000000..4ad0187df7a8 --- /dev/null +++ b/src/test/run-pass/associated-item-long-paths.rs @@ -0,0 +1,55 @@ +// 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. + +use std::mem::size_of; + +// The main point of this test is to ensure that we can parse and resolve +// associated items on associated types. + +trait Foo { + type U; +} + +trait Bar { + // Note 1: Chains of associated items in a path won't type-check. + // Note 2: Associated consts can't depend on type parameters or `Self`, + // which are the only types that an associated type can be referenced on for + // now, so we can only test methods. + fn method() -> u32; + fn generic_method() -> usize; +} + +struct MyFoo; +struct MyBar; + +impl Foo for MyFoo { + type U = MyBar; +} + +impl Bar for MyBar { + fn method() -> u32 { + 2u32 + } + fn generic_method() -> usize { + size_of::() + } +} + +fn foo() + where T: Foo, + T::U: Bar, +{ + assert_eq!(2u32, ::U::method()); + assert_eq!(8usize, ::U::generic_method::()); +} + +fn main() { + foo::(); +} From 4d1e48e37610f421f30e098f2ae9ef98b85b66eb Mon Sep 17 00:00:00 2001 From: Tincan Date: Thu, 7 May 2015 20:23:47 +0200 Subject: [PATCH 16/97] Typo in ownership.md --- src/doc/trpl/ownership.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/trpl/ownership.md b/src/doc/trpl/ownership.md index 3003156f875a..a70f03739f77 100644 --- a/src/doc/trpl/ownership.md +++ b/src/doc/trpl/ownership.md @@ -3,7 +3,7 @@ This guide is one of three presenting Rust’s ownership system. This is one of Rust’s most unique and compelling features, with which Rust developers should become quite acquainted. Ownership is how Rust achieves its largest goal, -memory safety. The there are a few distinct concepts, each with its own +memory safety. There are a few distinct concepts, each with its own chapter: * ownership, which you’re reading now. From 2a12e51dbd6949ae17925af9f3c4cc7402aa1b9b Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Thu, 7 May 2015 22:21:57 +0300 Subject: [PATCH 17/97] Select projections over impls in case of ambiguity. Fixes #23336. --- src/librustc/middle/traits/select.rs | 170 ++++++++++++++++----------- src/test/run-pass/issue-23336.rs | 20 ++++ 2 files changed, 123 insertions(+), 67 deletions(-) create mode 100644 src/test/run-pass/issue-23336.rs diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 49371eae2652..7bd2007d9419 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -117,23 +117,71 @@ pub enum MethodMatchedData { /// obligation is for `int`. In that case, we drop the impl out of the /// list. But the other cases are considered *candidates*. /// -/// Candidates can either be definitive or ambiguous. An ambiguous -/// candidate is one that might match or might not, depending on how -/// type variables wind up being resolved. This only occurs during inference. +/// For selection to succeed, there must be exactly one matching +/// candidate. If the obligation is fully known, this is guaranteed +/// by coherence. However, if the obligation contains type parameters +/// or variables, there may be multiple such impls. /// -/// For selection to succeed, there must be exactly one non-ambiguous -/// candidate. Usually, it is not possible to have more than one -/// definitive candidate, due to the coherence rules. However, there is -/// one case where it could occur: if there is a blanket impl for a -/// trait (that is, an impl applied to all T), and a type parameter -/// with a where clause. In that case, we can have a candidate from the -/// where clause and a second candidate from the impl. This is not a -/// problem because coherence guarantees us that the impl which would -/// be used to satisfy the where clause is the same one that we see -/// now. To resolve this issue, therefore, we ignore impls if we find a -/// matching where clause. Part of the reason for this is that where -/// clauses can give additional information (like, the types of output -/// parameters) that would have to be inferred from the impl. +/// It is not a real problem if multiple matching impls exist because +/// of type variables - it just means the obligation isn't sufficiently +/// elaborated. In that case we report an ambiguity, and the caller can +/// try again after more type information has been gathered or report a +/// "type annotations required" error. +/// +/// However, with type parameters, this can be a real problem - type +/// parameters don't unify with regular types, but they *can* unify +/// with variables from blanket impls, and (unless we know its bounds +/// will always be satisfied) picking the blanket impl will be wrong +/// for at least *some* substitutions. To make this concrete, if we have +/// +/// trait AsDebug { type Out : fmt::Debug; fn debug(self) -> Self::Out; } +/// impl AsDebug for T { +/// type Out = T; +/// fn debug(self) -> fmt::Debug { self } +/// } +/// fn foo(t: T) { println!("{:?}", ::debug(t)); } +/// +/// we can't just use the impl to resolve the obligation +/// - a type from another crate (that doesn't implement fmt::Debug) could +/// implement AsDebug. +/// +/// Because where-clauses match the type exactly, multiple clauses can +/// only match if there are unresolved variables, and we can mostly just +/// report this ambiguity in that case. This is still a problem - we can't +/// *do anything* with ambiguities that involve only regions. This is issue +/// #21974. +/// +/// If a single where-clause matches and there are no inference +/// variables left, then it definitely matches and we can just select +/// it. +/// +/// In fact, we even select the where-clause when the obligation contains +/// inference variables. The can lead to inference making "leaps of logic", +/// for example in this situation: +/// +/// pub trait Foo { fn foo(&self) -> T; } +/// impl Foo<()> for T { fn foo(&self) { } } +/// impl Foo for bool { fn foo(&self) -> bool { *self } } +/// +/// pub fn foo(t: T) where T: Foo { +/// println!("{:?}", >::foo(&t)); +/// } +/// fn main() { foo(false); } +/// +/// Here the obligation > can be matched by both the blanket +/// impl and the where-clause. We select the where-clause and unify $0=bool, +/// so the program prints "false". However, if the where-clause is omitted, +/// the blanket impl is selected, we unify $0=(), and the program prints +/// "()". +/// +/// Exactly the same issues apply to projection and object candidates, except +/// that we can have both a projection candidate and a where-clause candidate +/// for the same obligation. In that case either would do (except that +/// different "leaps of logic" would occur if inference variables are +/// present), and we just pick the projection. This is, for example, +/// required for associated types to work in default impls, as the bounds +/// are visible both as projection bounds and as where-clauses from the +/// parameter environment. #[derive(PartialEq,Eq,Debug,Clone)] enum SelectionCandidate<'tcx> { PhantomFnCandidate, @@ -1350,63 +1398,51 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Returns true if `candidate_i` should be dropped in favor of /// `candidate_j`. Generally speaking we will drop duplicate /// candidates and prefer where-clause candidates. + /// Returns true if `victim` should be dropped in favor of + /// `other`. Generally speaking we will drop duplicate + /// candidates and prefer where-clause candidates. + /// + /// See the comment for "SelectionCandidate" for more details. fn candidate_should_be_dropped_in_favor_of<'o>(&mut self, - candidate_i: &SelectionCandidate<'tcx>, - candidate_j: &SelectionCandidate<'tcx>) + victim: &SelectionCandidate<'tcx>, + other: &SelectionCandidate<'tcx>) -> bool { - if candidate_i == candidate_j { + if victim == other { return true; } - match (candidate_i, candidate_j) { - (&ImplCandidate(..), &ParamCandidate(..)) | - (&ClosureCandidate(..), &ParamCandidate(..)) | - (&FnPointerCandidate(..), &ParamCandidate(..)) | - (&BuiltinObjectCandidate(..), &ParamCandidate(_)) | - (&BuiltinCandidate(..), &ParamCandidate(..)) => { - // We basically prefer always prefer to use a - // where-clause over another option. Where clauses - // impose the burden of finding the exact match onto - // the caller. Using an impl in preference of a where - // clause can also lead us to "overspecialize", as in - // #18453. - true - } - (&ImplCandidate(..), &ObjectCandidate(..)) => { - // This means that we are matching an object of type - // `Trait` against the trait `Trait`. In that case, we - // always prefer to use the object vtable over the - // impl. Like a where clause, the impl may or may not - // be the one that is used by the object (because the - // impl may have additional where-clauses that the - // object's source might not meet) -- if it is, using - // the vtable is fine. If it is not, using the vtable - // is good. A win win! - true - } - (&DefaultImplCandidate(_), _) => { - // Prefer other candidates over default implementations. - self.tcx().sess.bug( - "default implementations shouldn't be recorded \ - when there are other valid candidates"); - } - (&ProjectionCandidate, &ParamCandidate(_)) => { - // FIXME(#20297) -- this gives where clauses precedent - // over projections. Really these are just two means - // of deducing information (one based on the where - // clauses on the trait definition; one based on those - // on the enclosing scope), and it'd be better to - // integrate them more intelligently. But for now this - // seems ok. If we DON'T give where clauses - // precedence, we run into trouble in default methods, - // where both the projection bounds for `Self::A` and - // the where clauses are in scope. - true - } - _ => { - false - } + match other { + &ObjectCandidate(..) | + &ParamCandidate(_) | &ProjectionCandidate => match victim { + &DefaultImplCandidate(..) => { + self.tcx().sess.bug( + "default implementations shouldn't be recorded \ + when there are other valid candidates"); + } + &PhantomFnCandidate => { + self.tcx().sess.bug("PhantomFn didn't short-circuit selection"); + } + &ImplCandidate(..) | + &ClosureCandidate(..) | + &FnPointerCandidate(..) | + &BuiltinObjectCandidate(..) | + &DefaultImplObjectCandidate(..) | + &BuiltinCandidate(..) => { + // We have a where-clause so don't go around looking + // for impls. + true + } + &ObjectCandidate(..) | + &ProjectionCandidate => { + // Arbitrarily give param candidates priority + // over projection and object candidates. + true + }, + &ParamCandidate(..) => false, + &ErrorCandidate => false // propagate errors + }, + _ => false } } diff --git a/src/test/run-pass/issue-23336.rs b/src/test/run-pass/issue-23336.rs new file mode 100644 index 000000000000..21e512984449 --- /dev/null +++ b/src/test/run-pass/issue-23336.rs @@ -0,0 +1,20 @@ +// 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. + +pub trait Data { fn doit(&self) {} } +impl Data for T {} +pub trait UnaryLogic { type D: Data; } +impl UnaryLogic for () { type D = i32; } + +pub fn crashes(t: T::D) { + t.doit(); +} + +fn main() { crashes::<()>(0); } From ae1b2f4bf3a5d9cee9227528b6df24decc20b977 Mon Sep 17 00:00:00 2001 From: Tincan Date: Thu, 7 May 2015 21:31:10 +0200 Subject: [PATCH 18/97] Another typo --- src/doc/trpl/ownership.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/trpl/ownership.md b/src/doc/trpl/ownership.md index a70f03739f77..d994c1772755 100644 --- a/src/doc/trpl/ownership.md +++ b/src/doc/trpl/ownership.md @@ -173,7 +173,7 @@ fn foo(v: Vec) -> Vec { } ``` -This would get very tedius. It gets worse the more things we want to take ownership of: +This would get very tedious. It gets worse the more things we want to take ownership of: ```rust fn foo(v1: Vec, v2: Vec) -> (Vec, Vec, i32) { From 51a1e83cb064484260110609834f8ecbc8f3f9a8 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 8 May 2015 13:18:04 -0700 Subject: [PATCH 19/97] doc: Remove mention of 30 minute intro --- src/doc/index.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/doc/index.md b/src/doc/index.md index 5a437e959b7f..355297685a16 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -5,15 +5,14 @@ to jump to any particular section. # Getting Started -If you haven't seen Rust at all yet, the first thing you should read is the [30 -minute intro](intro.html). It will give you an overview of the basic ideas of Rust -at a high level. +If you haven't seen Rust at all yet, the first thing you should read is the +introduction to [The Rust Programming Language](book/index.html). It'll give +you a good idea of what Rust is like. -Once you know you really want to learn Rust, the next step is reading [The -Rust Programming Language](book/index.html). It is a lengthy explanation of -Rust, its syntax, and its concepts. Upon completing the book, you'll be an -intermediate Rust developer, and will have a good grasp of the fundamental -ideas behind Rust. +The book provides a lengthy explanation of Rust, its syntax, and its +concepts. Upon completing the book, you'll be an intermediate Rust +developer, and will have a good grasp of the fundamental ideas behind +Rust. [Rust By Example][rbe] was originally a community resource, but was then donated to the Rust project. As the name implies, it teaches you Rust through a From 715f7c3cd2af3d54ef79d75fe7b1e820853f08ea Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 8 May 2015 23:54:24 +0200 Subject: [PATCH 20/97] Add a precision for references --- src/doc/trpl/references-and-borrowing.md | 32 ++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/doc/trpl/references-and-borrowing.md b/src/doc/trpl/references-and-borrowing.md index 21feff73342c..06ff9bfbc55d 100644 --- a/src/doc/trpl/references-and-borrowing.md +++ b/src/doc/trpl/references-and-borrowing.md @@ -334,3 +334,35 @@ In other words, `y` is only valid for the scope where `x` exists. As soon as `x` goes away, it becomes invalid to refer to it. As such, the error says that the borrow ‘doesn’t live long enough’ because it’s not valid for the right amount of time. + +The same problem occurs when the reference is declared _before_ the variable it refers to: + +```rust,ignore +let y: &i32; +let x = 5; +y = &x; + +println!("{}", y); +``` + +We get this error: + +error: `x` does not live long enough +y = &x; + ^ +note: reference must be valid for the block suffix following statement 0 at +2:16... + let y: &i32; + let x = 5; + y = &x; + + println!("{}", y); +} + +note: ...but borrowed value is only valid for the block suffix following +statement 1 at 3:14 + let x = 5; + y = &x; + + println!("{}", y); +} From ff4e06104903c8cb03600739fa51afb905188b18 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Sat, 9 May 2015 00:03:42 +0200 Subject: [PATCH 21/97] rustdoc: Link associated items in search index to trait This is related to isssue #22442 and solves it partly. This solves the links of associated types and constants, so that they link to the trait page. --- src/librustdoc/html/render.rs | 2 ++ src/librustdoc/html/static/main.js | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 5a828e8376e5..4074a6594427 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -905,6 +905,8 @@ impl DocFolder for Cache { // Index this method for searching later on if let Some(ref s) = item.name { let (parent, is_method) = match item.inner { + clean::AssociatedTypeItem(..) | + clean::AssociatedConstItem(..) | clean::TyMethodItem(..) | clean::StructFieldItem(..) | clean::VariantItem(..) => { diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index c2a59278a86d..02c6c8dca9d8 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -34,7 +34,8 @@ "macro", "primitive", "associatedtype", - "constant"]; + "constant", + "associatedconstant"]; $('.js-only').removeClass('js-only'); From c46f3ff12b0a0b9c55df89eeb92603e9e488b2a7 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Sat, 9 May 2015 00:16:20 +0200 Subject: [PATCH 22/97] rustdoc: Add Associated Constants section Section only visible if there are assoc. consts. present. --- src/librustdoc/html/render.rs | 11 +++++++++++ src/test/rustdoc/assoc-consts.rs | 1 + 2 files changed, 12 insertions(+) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 4074a6594427..55e16db596a3 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1862,6 +1862,17 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, try!(write!(w, "")); } + if !consts.is_empty() { + try!(write!(w, " +

Associated Constants

+
+ ")); + for t in &consts { + try!(trait_item(w, *t)); + } + try!(write!(w, "
")); + } + // Output the documentation for each function individually if !required.is_empty() { try!(write!(w, " diff --git a/src/test/rustdoc/assoc-consts.rs b/src/test/rustdoc/assoc-consts.rs index cd8d7ec16dce..20d4c744414c 100644 --- a/src/test/rustdoc/assoc-consts.rs +++ b/src/test/rustdoc/assoc-consts.rs @@ -13,6 +13,7 @@ pub trait Foo { // @has assoc_consts/trait.Foo.html '//*[@class="rust trait"]' \ // 'const FOO: usize;' + // @has - '//*[@id="associatedconstant.FOO"]' 'const FOO' const FOO: usize; } From 7a91fe845c7ee6e78f6b9f5846541fdc1785687a Mon Sep 17 00:00:00 2001 From: Sindre Johansen Date: Sat, 9 May 2015 12:59:24 +0200 Subject: [PATCH 23/97] Fixed a typo. Removed an extra s --- src/doc/trpl/primitive-types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/trpl/primitive-types.md b/src/doc/trpl/primitive-types.md index e017e222c741..f0f57c3ab585 100644 --- a/src/doc/trpl/primitive-types.md +++ b/src/doc/trpl/primitive-types.md @@ -176,7 +176,7 @@ Slices have type `&[T]`. We’ll talk about that `T` when we cover [generics]: generics.html -You can find more documentation for `slices`s [in the standard library +You can find more documentation for `slices` [in the standard library documentation][slice]. [slice]: ../std/primitive.slice.html From 1e9ce0d50564b872d12457da59911838eb21b760 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Sat, 9 May 2015 13:27:23 +0200 Subject: [PATCH 24/97] std: Add example for HashMap::entry() --- src/libstd/collections/hash/map.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index eedda3cf4371..ae75de2086b7 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -916,6 +916,24 @@ impl HashMap } /// Gets the given key's corresponding entry in the map for in-place manipulation. + /// + /// # Examples + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let mut letters = HashMap::new(); + /// + /// for ch in "a short treatise on fungi".chars() { + /// let counter = letters.entry(ch).or_insert(0); + /// *counter += 1; + /// } + /// + /// assert_eq!(letters[&'s'], 2); + /// assert_eq!(letters[&'t'], 3); + /// assert_eq!(letters[&'u'], 1); + /// assert_eq!(letters.get(&'y'), None); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn entry(&mut self, key: K) -> Entry { // Gotta resize now. From 7a2ac0cd5ae44e84a15264888427f007f895946e Mon Sep 17 00:00:00 2001 From: Sindre Johansen Date: Sat, 9 May 2015 13:34:49 +0200 Subject: [PATCH 25/97] Added start of last text block The start of the last text block in references was missing, I added it. --- src/doc/trpl/references-and-borrowing.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/trpl/references-and-borrowing.md b/src/doc/trpl/references-and-borrowing.md index 8bb3f94760bc..f428107ffc0c 100644 --- a/src/doc/trpl/references-and-borrowing.md +++ b/src/doc/trpl/references-and-borrowing.md @@ -312,6 +312,7 @@ println!("{}", y); We get this error: +```text error: `x` does not live long enough y = &x; ^ From 101b25c10031b0230674f86712ce709e5e6f6023 Mon Sep 17 00:00:00 2001 From: Clark Gaebel Date: Sat, 7 Feb 2015 18:49:54 -0500 Subject: [PATCH 26/97] [liballoc] Adds checks for UB during allocation. They're only enabled in debug builds, but a panic is usually more welcome than UB in debug builds. --- src/liballoc/heap.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index 86a04a0687a5..b41ffcda3a5f 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -8,6 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::{isize, usize}; + +#[inline(always)] +fn check_size_and_alignment(size: usize, align: usize) { + debug_assert!(size != 0); + debug_assert!(size <= isize::MAX as usize, "Tried to allocate too much: {} bytes", size); + debug_assert!(usize::is_power_of_two(align), "Invalid alignment of allocation: {}", align); +} + // FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias` /// Return a pointer to `size` bytes of memory aligned to `align`. @@ -19,6 +28,7 @@ /// size on the platform. #[inline] pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { + check_size_and_alignment(size, align); imp::allocate(size, align) } @@ -38,6 +48,7 @@ pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { /// any value in range_inclusive(requested_size, usable_size). #[inline] pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 { + check_size_and_alignment(size, align); imp::reallocate(ptr, old_size, size, align) } @@ -56,6 +67,7 @@ pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usiz #[inline] pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> usize { + check_size_and_alignment(size, align); imp::reallocate_inplace(ptr, old_size, size, align) } From f8888af412b517c55deed84f851b3dc3c93d81d0 Mon Sep 17 00:00:00 2001 From: Don Petersen Date: Sat, 9 May 2015 20:25:09 -0700 Subject: [PATCH 27/97] Add omitted word to mutability docs. --- src/doc/trpl/mutability.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/trpl/mutability.md b/src/doc/trpl/mutability.md index 435407a8a967..9b386acdca21 100644 --- a/src/doc/trpl/mutability.md +++ b/src/doc/trpl/mutability.md @@ -78,8 +78,8 @@ When we call `clone()`, the `Arc` needs to update the reference count. Yet we’ve not used any `mut`s here, `x` is an immutable binding, and we didn’t take `&mut 5` or anything. So what gives? -To this, we have to go back to the core of Rust’s guiding philosophy, memory -safety, and the mechanism by which Rust guarantees it, the +To understand this, we have to go back to the core of Rust’s guiding +philosophy, memory safety, and the mechanism by which Rust guarantees it, the [ownership][ownership] system, and more specifically, [borrowing][borrowing]: > You may have one or the other of these two kinds of borrows, but not both at From ae1b64ff7376859b3582441cd41218b5445da148 Mon Sep 17 00:00:00 2001 From: Don Petersen Date: Sat, 9 May 2015 22:10:34 -0700 Subject: [PATCH 28/97] Fix typo in Match document. --- src/doc/trpl/match.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/trpl/match.md b/src/doc/trpl/match.md index 2c0c8ea73c03..86b944533896 100644 --- a/src/doc/trpl/match.md +++ b/src/doc/trpl/match.md @@ -50,7 +50,7 @@ side of a `let` binding or directly where an expression is used: ```rust let x = 5; -let numer = match x { +let number = match x { 1 => "one", 2 => "two", 3 => "three", From 2cc4d822dfada7395b67d83368a5bee44b50a5e2 Mon Sep 17 00:00:00 2001 From: Franziska Hinkelmann Date: Sun, 10 May 2015 08:02:06 +0200 Subject: [PATCH 29/97] Fix small typos in documentation --- src/doc/trpl/guessing-game.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/trpl/guessing-game.md b/src/doc/trpl/guessing-game.md index 57479a21e47a..fc3927380fad 100644 --- a/src/doc/trpl/guessing-game.md +++ b/src/doc/trpl/guessing-game.md @@ -711,7 +711,7 @@ variety of numbers, we need to give Rust a hint as to the exact type of number we want. Hence, `let guess: u32`. The colon (`:`) after `guess` tells Rust we’re going to annotate its type. `u32` is an unsigned, thirty-two bit integer. Rust has [a number of built-in number types][number], but we’ve -chosen `u32`. It’s a good default choice for a small positive numer. +chosen `u32`. It’s a good default choice for a small positive number. [parse]: ../std/primitive.str.html#method.parse [number]: primitive-types.html#numeric-types @@ -920,7 +920,7 @@ failure. Each contains more information: the successful parsed integer, or an error type. In this case, we `match` on `Ok(num)`, which sets the inner value of the `Ok` to the name `num`, and then we just return it on the right-hand side. In the `Err` case, we don’t care what kind of error it is, so we just -use `_` intead of a name. This ignores the error, and `continue` causes us +use `_` instead of a name. This ignores the error, and `continue` causes us to go to the next iteration of the `loop`. Now we should be good! Let’s try: From c4b72a88ef2e6f79bfbab0fc2784eb1c3c366487 Mon Sep 17 00:00:00 2001 From: Richo Healey Date: Sun, 10 May 2015 02:08:48 -0700 Subject: [PATCH 30/97] sancheck: import resource inside of the posix check This avoids a crash on windows --- src/etc/check-sanitycheck.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/etc/check-sanitycheck.py b/src/etc/check-sanitycheck.py index 0d9c430ec3ac..fc8ed7b383ec 100644 --- a/src/etc/check-sanitycheck.py +++ b/src/etc/check-sanitycheck.py @@ -13,7 +13,6 @@ import os import sys import functools -import resource STATUS = 0 @@ -37,6 +36,7 @@ def only_on(platforms): @only_on(('linux', 'darwin', 'freebsd', 'openbsd')) def check_rlimit_core(): + import resource soft, hard = resource.getrlimit(resource.RLIMIT_CORE) if soft > 0: error_unless_permitted('ALLOW_NONZERO_RLIMIT_CORE', """\ From 8ad1c90db0670c763fec0f1d5cfc0303bc28fb77 Mon Sep 17 00:00:00 2001 From: Sindre Johansen Date: Sun, 10 May 2015 11:16:32 +0200 Subject: [PATCH 31/97] Removed the backticks on slices --- src/doc/trpl/primitive-types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/trpl/primitive-types.md b/src/doc/trpl/primitive-types.md index f0f57c3ab585..bb2bf028700d 100644 --- a/src/doc/trpl/primitive-types.md +++ b/src/doc/trpl/primitive-types.md @@ -176,7 +176,7 @@ Slices have type `&[T]`. We’ll talk about that `T` when we cover [generics]: generics.html -You can find more documentation for `slices` [in the standard library +You can find more documentation for slices [in the standard library documentation][slice]. [slice]: ../std/primitive.slice.html From 7d9e605b93eb3ac359b3470dce829ed8432012d1 Mon Sep 17 00:00:00 2001 From: Ricardo Martins Date: Sun, 10 May 2015 10:43:30 +0100 Subject: [PATCH 32/97] Add error explanation for E0317. --- src/librustc_resolve/diagnostics.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index a896bd311698..3e7ee714ea9f 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -10,6 +10,24 @@ #![allow(non_snake_case)] +// Error messages for EXXXX errors. +// Each message should start and end with a new line, and be wrapped to 80 characters. +// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable. +register_long_diagnostics! { + +E0317: r##" +User-defined types or type parameters cannot shadow the primitive types. +This error indicates you tried to define a type, struct or enum with the same +name as an existing primitive type, and is therefore invalid. + +See the Types section of the reference for more information about the primitive +types: + +http://doc.rust-lang.org/nightly/reference.html#types +"## + +} + register_diagnostics! { E0154, E0157, @@ -24,7 +42,6 @@ register_diagnostics! { E0258, // import conflicts with existing submodule E0259, // an extern crate has already been imported into this module E0260, // name conflicts with an external crate that has been imported into this module - E0317, // user-defined types or type parameters cannot shadow the primitive types E0364, // item is private E0365 // item is private } From c0412bcad69d95e217211bf6be925802004e4b17 Mon Sep 17 00:00:00 2001 From: Ricardo Martins Date: Sun, 10 May 2015 12:16:33 +0100 Subject: [PATCH 33/97] Fix documentation URL in diagnostic message. --- src/librustc_resolve/diagnostics.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 3e7ee714ea9f..dd867d676ed2 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -23,7 +23,7 @@ name as an existing primitive type, and is therefore invalid. See the Types section of the reference for more information about the primitive types: -http://doc.rust-lang.org/nightly/reference.html#types +http://doc.rust-lang.org/reference.html#types "## } From f3a3684614c0baf01e2d22e662b67e6a1408b718 Mon Sep 17 00:00:00 2001 From: Ricardo Martins Date: Sun, 10 May 2015 11:40:43 +0100 Subject: [PATCH 34/97] Add error explanation for E0154. --- src/librustc_resolve/diagnostics.rs | 33 ++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index dd867d676ed2..4b754913bd9f 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -15,6 +15,38 @@ // In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable. register_long_diagnostics! { +E0154: r##" +Imports (`use` statements) are not allowed after non-item statements, such as +variable declarations and expression statements. + +Wrong example: +``` +fn f() { + // Variable declaration before import + let x = 0; + use std::io::Read; + ... +} +``` + +The solution is to declare the imports at the top of the block, function, or +file. + +Here is the previous example again, with the correct order: +``` +fn f() { + use std::io::Read; + let x = 0; + ... +} +``` + +See the Declaration Statements section of the reference for more information +about what constitutes an Item declaration and what does not: + +http://doc.rust-lang.org/reference.html#statements +"##, + E0317: r##" User-defined types or type parameters cannot shadow the primitive types. This error indicates you tried to define a type, struct or enum with the same @@ -29,7 +61,6 @@ http://doc.rust-lang.org/reference.html#types } register_diagnostics! { - E0154, E0157, E0153, E0251, // a named type or value has already been imported in this module From e7fa00a3e24f094012f878945bef8a62df1678c1 Mon Sep 17 00:00:00 2001 From: Ricardo Martins Date: Sun, 10 May 2015 12:09:41 +0100 Subject: [PATCH 35/97] Add error explanation for E0259. --- src/librustc_resolve/diagnostics.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 4b754913bd9f..47f9b024fd05 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -47,6 +47,26 @@ about what constitutes an Item declaration and what does not: http://doc.rust-lang.org/reference.html#statements "##, +E0259: r##" +The name chosen for an external crate conflicts with another external crate that +has been imported into the current module. + +Wrong example: +``` +extern a; +extern crate_a as a; +``` + +The solution is to choose a different name that doesn't conflict with any +external crate imported into the current module. + +Correct example: +``` +extern a; +extern crate_a as other_name; +``` +"##, + E0317: r##" User-defined types or type parameters cannot shadow the primitive types. This error indicates you tried to define a type, struct or enum with the same @@ -71,7 +91,6 @@ register_diagnostics! { E0256, // import conflicts with type in this module E0257, // inherent implementations are only allowed on types defined in the current module E0258, // import conflicts with existing submodule - E0259, // an extern crate has already been imported into this module E0260, // name conflicts with an external crate that has been imported into this module E0364, // item is private E0365 // item is private From 60ec4ab220385be1ad2aef237733d7f38c2196b3 Mon Sep 17 00:00:00 2001 From: Ricardo Martins Date: Sun, 10 May 2015 12:26:19 +0100 Subject: [PATCH 36/97] Add error explanation for E0260. --- src/librustc_resolve/diagnostics.rs | 35 ++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 47f9b024fd05..5f0b5af9a053 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -67,6 +67,40 @@ extern crate_a as other_name; ``` "##, +E0260: r##" +The name for an item declaration conflicts with an external crate's name. + +For instance, +``` +extern abc; + +struct abc; +``` + +There are two possible solutions: + +Solution #1: Rename the item. + +``` +extern abc; + +struct xyz; +``` + +Solution #2: Import the crate with a different name. + +``` +extern abc as xyz; + +struct abc; +``` + +See the Declaration Statements section of the reference for more information +about what constitutes an Item declaration and what does not: + +http://doc.rust-lang.org/reference.html#statements +"##, + E0317: r##" User-defined types or type parameters cannot shadow the primitive types. This error indicates you tried to define a type, struct or enum with the same @@ -91,7 +125,6 @@ register_diagnostics! { E0256, // import conflicts with type in this module E0257, // inherent implementations are only allowed on types defined in the current module E0258, // import conflicts with existing submodule - E0260, // name conflicts with an external crate that has been imported into this module E0364, // item is private E0365 // item is private } From a168dbad15e108fce02a996fc8f72803460b7a55 Mon Sep 17 00:00:00 2001 From: Jan Bujak Date: Sun, 10 May 2015 14:06:41 +0200 Subject: [PATCH 37/97] Add #[inline] to AsRef::as_ref for String and str. --- src/libcollections/string.rs | 1 + src/libcore/convert.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 3c668f7fe9bc..bb5345917e71 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -1052,6 +1052,7 @@ impl ToString for T { #[stable(feature = "rust1", since = "1.0.0")] impl AsRef for String { + #[inline] fn as_ref(&self) -> &str { self } diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index d3de77a9241e..da6ac6bd752b 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -173,6 +173,7 @@ impl AsMut<[T]> for [T] { #[stable(feature = "rust1", since = "1.0.0")] impl AsRef for str { + #[inline] fn as_ref(&self) -> &str { self } From 5613502a4f3476e5db2c68bdf203104556796630 Mon Sep 17 00:00:00 2001 From: Nick Platt Date: Sat, 9 May 2015 23:18:28 -0400 Subject: [PATCH 38/97] Add long diagnostic for E0067 --- src/librustc_typeck/diagnostics.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 0e6386618f17..2cc1b23e03ec 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -46,6 +46,23 @@ enum variant, one of the fields was not provided. Each field should be specified exactly once. "##, +E0067: r##" +The left-hand side of an assignment operator must be an lvalue expression. An +lvalue expression represents a memory location and includes item paths (ie, +namespaced variables), dereferences, indexing expressions, and field references. + +``` +use std::collections::LinkedList; + +// Good +let mut list = LinkedList::new(); + + +// Bad: assignment to non-lvalue expression +LinkedList::new() += 1; +``` +"##, + E0081: r##" Enum discriminants are used to differentiate enum variants stored in memory. This error indicates that the same value was used for two or more variants, @@ -149,7 +166,6 @@ register_diagnostics! { E0060, E0061, E0066, - E0067, E0068, E0069, E0070, From ffc0d0448917c1f225a3500bf3a1dc6fc40029d7 Mon Sep 17 00:00:00 2001 From: Nick Platt Date: Sat, 9 May 2015 23:20:14 -0400 Subject: [PATCH 39/97] Add long diagnostic for E0131, E0132 --- src/librustc_typeck/diagnostics.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 2cc1b23e03ec..026ba3d08b42 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -136,6 +136,20 @@ construct an instance of the following type using only safe code: ``` enum Empty {} ``` +"##, + +E0131: r##" +It is not possible to define `main` with type parameters, or even with function +parameters. When `main` is present, it must take no arguments and return `()`. +"##, + +E0132: r##" +It is not possible to declare type parameters on a function that has the `start` +attribute. Such a function must have the following type signature: + +``` +fn(isize, *const *const u8) -> isize +``` "## } @@ -205,8 +219,6 @@ register_diagnostics! { E0128, E0129, E0130, - E0131, - E0132, E0141, E0159, E0163, From 25543f38e437f959298238790a3737ff44ab5baf Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 10 May 2015 21:05:04 +0200 Subject: [PATCH 40/97] Add missing backticks --- src/doc/trpl/references-and-borrowing.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/doc/trpl/references-and-borrowing.md b/src/doc/trpl/references-and-borrowing.md index 06ff9bfbc55d..82533becef34 100644 --- a/src/doc/trpl/references-and-borrowing.md +++ b/src/doc/trpl/references-and-borrowing.md @@ -312,6 +312,7 @@ println!("{}", y); We get this error: +```text error: `x` does not live long enough y = &x; ^ @@ -347,6 +348,7 @@ println!("{}", y); We get this error: +```text error: `x` does not live long enough y = &x; ^ @@ -366,3 +368,4 @@ statement 1 at 3:14 println!("{}", y); } +``` \ No newline at end of file From 0c390d2f8e1cc2f29d9c1088387d375a929356a5 Mon Sep 17 00:00:00 2001 From: Alexander Polakov Date: Sun, 10 May 2015 22:37:06 +0300 Subject: [PATCH 41/97] point supposed to be immutable in this example --- src/doc/trpl/mutability.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/trpl/mutability.md b/src/doc/trpl/mutability.md index 435407a8a967..3e910aff9eaf 100644 --- a/src/doc/trpl/mutability.md +++ b/src/doc/trpl/mutability.md @@ -169,7 +169,7 @@ struct Point { y: Cell, } -let mut point = Point { x: 5, y: Cell::new(6) }; +let point = Point { x: 5, y: Cell::new(6) }; point.y.set(7); From 1276506f6832ad0376e0ecbfc8b82f80c4293b91 Mon Sep 17 00:00:00 2001 From: Cole Reynolds Date: Sun, 10 May 2015 15:42:29 -0400 Subject: [PATCH 42/97] Fix grammar in path::Path documentation Change from "must be used with behind a pointer" to "must be used behind a pointer" --- src/libstd/path.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 8ccc387c9027..c9c867615d22 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1199,7 +1199,7 @@ impl Into for PathBuf { /// absolute, and so on. More details about the overall approach can be found in /// the module documentation. /// -/// This is an *unsized* type, meaning that it must always be used with behind a +/// This is an *unsized* type, meaning that it must always be used behind a /// pointer like `&` or `Box`. /// /// # Examples From f95c8123112ee55d3be429fa839a270732ad0976 Mon Sep 17 00:00:00 2001 From: Johannes Oertel Date: Tue, 28 Apr 2015 18:01:23 +0200 Subject: [PATCH 43/97] Implement `append` and `split_off` for BitSet (RFC 509) --- src/libcollections/bit.rs | 83 +++++++++++++++++++++++++++++++ src/libcollectionstest/bit/set.rs | 61 +++++++++++++++++++++++ src/libcollectionstest/lib.rs | 1 + 3 files changed, 145 insertions(+) diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index 1271a6276aec..5ea5f566d108 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -1792,6 +1792,89 @@ impl BitSet { self.other_op(other, |w1, w2| w1 ^ w2); } + /// Moves all elements from `other` into `Self`, leaving `other` empty. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collections, bit_set_append_split_off)] + /// use std::collections::{BitVec, BitSet}; + /// + /// let mut a = BitSet::new(); + /// a.insert(2); + /// a.insert(6); + /// + /// let mut b = BitSet::new(); + /// b.insert(1); + /// b.insert(3); + /// b.insert(6); + /// + /// a.append(&mut b); + /// + /// assert_eq!(a.len(), 4); + /// assert_eq!(b.len(), 0); + /// assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b01110010]))); + /// ``` + #[unstable(feature = "bit_set_append_split_off", + reason = "recently added as part of collections reform 2")] + pub fn append(&mut self, other: &mut Self) { + self.union_with(other); + other.clear(); + } + + /// Splits the `BitSet` into two at the given key including the key. + /// Retains the first part in-place while returning the second part. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collections, bit_set_append_split_off)] + /// use std::collections::{BitSet, BitVec}; + /// let mut a = BitSet::new(); + /// a.insert(2); + /// a.insert(6); + /// a.insert(1); + /// a.insert(3); + /// + /// let b = a.split_off(3); + /// + /// assert_eq!(a.len(), 2); + /// assert_eq!(b.len(), 2); + /// assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100000]))); + /// assert_eq!(b, BitSet::from_bit_vec(BitVec::from_bytes(&[0b00010010]))); + /// ``` + #[unstable(feature = "bit_set_append_split_off", + reason = "recently added as part of collections reform 2")] + pub fn split_off(&mut self, at: usize) -> Self { + let mut other = BitSet::new(); + + if at == 0 { + swap(self, &mut other); + return other; + } else if at >= self.bit_vec.len() { + return other; + } + + // Calculate block and bit at which to split + let w = at / u32::BITS; + let b = at % u32::BITS; + + // Pad `other` with `w` zero blocks, + // append `self`'s blocks in the range from `w` to the end to `other` + other.bit_vec.storage.extend(repeat(0u32).take(w) + .chain(self.bit_vec.storage[w..].iter().cloned())); + other.bit_vec.nbits = self.bit_vec.nbits; + + if b > 0 { + other.bit_vec.storage[w] &= !0 << b; + } + + // Sets `bit_vec.len()` and fixes the last block as well + self.bit_vec.truncate(at); + + other + } + /// Returns the number of set bits in this set. #[inline] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcollectionstest/bit/set.rs b/src/libcollectionstest/bit/set.rs index d020f551dd55..e6aa15608f03 100644 --- a/src/libcollectionstest/bit/set.rs +++ b/src/libcollectionstest/bit/set.rs @@ -387,6 +387,67 @@ fn test_bit_vec_clone() { assert!(b.contains(&1000)); } +#[test] +fn test_bit_set_append() { + let mut a = BitSet::new(); + a.insert(2); + a.insert(6); + + let mut b = BitSet::new(); + b.insert(1); + b.insert(3); + b.insert(6); + + a.append(&mut b); + + assert_eq!(a.len(), 4); + assert_eq!(b.len(), 0); + assert!(b.capacity() >= 6); + + assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b01110010]))); +} + +#[test] +fn test_bit_set_split_off() { + // Split at 0 + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010, + 0b00110011, 0b01101011, 0b10101101])); + + let b = a.split_off(0); + + assert_eq!(a.len(), 0); + assert_eq!(b.len(), 21); + + assert_eq!(b, BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010, + 0b00110011, 0b01101011, 0b10101101]))); + + // Split behind last element + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010, + 0b00110011, 0b01101011, 0b10101101])); + + let b = a.split_off(50); + + assert_eq!(a.len(), 21); + assert_eq!(b.len(), 0); + + assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010, + 0b00110011, 0b01101011, 0b10101101]))); + + // Split at arbitrary element + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010, + 0b00110011, 0b01101011, 0b10101101])); + + let b = a.split_off(34); + + assert_eq!(a.len(), 12); + assert_eq!(b.len(), 9); + + assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010, + 0b00110011, 0b01000000]))); + assert_eq!(b, BitSet::from_bit_vec(BitVec::from_bytes(&[0, 0, 0, 0, + 0b00101011, 0b10101101]))); +} + mod bench { use std::collections::{BitSet, BitVec}; use std::__rand::{Rng, thread_rng, ThreadRng}; diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index 154bdd56c5a6..9b50478472fa 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(bit_set_append_split_off)] #![feature(bit_vec_append_split_off)] #![feature(box_syntax)] #![feature(collections)] From 685f557729e3bb2691a81ac10074bddf4f61a0b6 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sun, 10 May 2015 16:32:18 -0400 Subject: [PATCH 44/97] Update docs to stop referencing `BufReadExt` --- src/libstd/io/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 9089b417fcb9..e7b2b01d09f3 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -844,7 +844,7 @@ impl fmt::Display for CharsError { /// An iterator over the contents of an instance of `BufRead` split on a /// particular byte. /// -/// See `BufReadExt::split` for more information. +/// See `BufRead::split` for more information. #[stable(feature = "rust1", since = "1.0.0")] pub struct Split { buf: B, @@ -873,7 +873,7 @@ impl Iterator for Split { /// An iterator over the lines of an instance of `BufRead` split on a newline /// byte. /// -/// See `BufReadExt::lines` for more information. +/// See `BufRead::lines` for more information. #[stable(feature = "rust1", since = "1.0.0")] pub struct Lines { buf: B, From f11c4ba30c09016b07e763414c7295416283d853 Mon Sep 17 00:00:00 2001 From: Jan-Erik Rediger Date: Sun, 10 May 2015 23:12:45 +0200 Subject: [PATCH 45/97] Remove extra parentheses --- src/doc/reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 16fdcfa30139..29290acf6dc5 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -547,7 +547,7 @@ _name_ s that occur in its body. At the "current layer", they all must repeat the same number of times, so ` ( $( $i:ident ),* ; $( $j:ident ),* ) => ( $( ($i,$j) ),* )` is valid if given the argument `(a,b,c ; d,e,f)`, but not `(a,b,c ; d,e)`. The repetition walks through the choices at that layer in -lockstep, so the former input transcribes to `( (a,d), (b,e), (c,f) )`. +lockstep, so the former input transcribes to `(a,d), (b,e), (c,f)`. Nested repetitions are allowed. From 683da9c3840a622601818488941161dc7d53652e Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Sun, 10 May 2015 13:32:31 +0200 Subject: [PATCH 46/97] doc: unwrap is discouraged, so use Some --- src/libcore/iter.rs | 68 ++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index e4d2ab198630..cab79d938c37 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -137,7 +137,7 @@ pub trait Iterator { /// /// ``` /// let a = [1, 2, 3, 4, 5]; - /// assert_eq!(a.iter().last().unwrap(), &5); + /// assert_eq!(a.iter().last(), Some(&5)); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -155,7 +155,7 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter(); - /// assert_eq!(it.nth(2).unwrap(), &3); + /// assert_eq!(it.nth(2), Some(&3)); /// assert_eq!(it.nth(2), None); /// ``` #[inline] @@ -178,8 +178,8 @@ pub trait Iterator { /// let a = [0]; /// let b = [1]; /// let mut it = a.iter().chain(b.iter()); - /// assert_eq!(it.next().unwrap(), &0); - /// assert_eq!(it.next().unwrap(), &1); + /// assert_eq!(it.next(), Some(&0)); + /// assert_eq!(it.next(), Some(&1)); /// assert!(it.next().is_none()); /// ``` #[inline] @@ -201,7 +201,7 @@ pub trait Iterator { /// let a = [0]; /// let b = [1]; /// let mut it = a.iter().zip(b.iter()); - /// assert_eq!(it.next().unwrap(), (&0, &1)); + /// assert_eq!(it.next(), Some((&0, &1))); /// assert!(it.next().is_none()); /// ``` /// @@ -234,8 +234,8 @@ pub trait Iterator { /// ``` /// let a = [1, 2]; /// let mut it = a.iter().map(|&x| 2 * x); - /// assert_eq!(it.next().unwrap(), 2); - /// assert_eq!(it.next().unwrap(), 4); + /// assert_eq!(it.next(), Some(2)); + /// assert_eq!(it.next(), Some(4)); /// assert!(it.next().is_none()); /// ``` #[inline] @@ -255,7 +255,7 @@ pub trait Iterator { /// ``` /// let a = [1, 2]; /// let mut it = a.iter().filter(|&x| *x > 1); - /// assert_eq!(it.next().unwrap(), &2); + /// assert_eq!(it.next(), Some(&2)); /// assert!(it.next().is_none()); /// ``` #[inline] @@ -275,7 +275,7 @@ pub trait Iterator { /// ``` /// let a = [1, 2]; /// let mut it = a.iter().filter_map(|&x| if x > 1 {Some(2 * x)} else {None}); - /// assert_eq!(it.next().unwrap(), 4); + /// assert_eq!(it.next(), Some(4)); /// assert!(it.next().is_none()); /// ``` #[inline] @@ -310,8 +310,8 @@ pub trait Iterator { /// ``` /// let a = [100, 200]; /// let mut it = a.iter().enumerate(); - /// assert_eq!(it.next().unwrap(), (0, &100)); - /// assert_eq!(it.next().unwrap(), (1, &200)); + /// assert_eq!(it.next(), Some((0, &100))); + /// assert_eq!(it.next(), Some((1, &200))); /// assert!(it.next().is_none()); /// ``` #[inline] @@ -353,9 +353,9 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter().skip_while(|&a| *a < 3); - /// assert_eq!(it.next().unwrap(), &3); - /// assert_eq!(it.next().unwrap(), &4); - /// assert_eq!(it.next().unwrap(), &5); + /// assert_eq!(it.next(), Some(&3)); + /// assert_eq!(it.next(), Some(&4)); + /// assert_eq!(it.next(), Some(&5)); /// assert!(it.next().is_none()); /// ``` #[inline] @@ -375,8 +375,8 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter().take_while(|&a| *a < 3); - /// assert_eq!(it.next().unwrap(), &1); - /// assert_eq!(it.next().unwrap(), &2); + /// assert_eq!(it.next(), Some(&1)); + /// assert_eq!(it.next(), Some(&2)); /// assert!(it.next().is_none()); /// ``` #[inline] @@ -395,8 +395,8 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter().skip(3); - /// assert_eq!(it.next().unwrap(), &4); - /// assert_eq!(it.next().unwrap(), &5); + /// assert_eq!(it.next(), Some(&4)); + /// assert_eq!(it.next(), Some(&5)); /// assert!(it.next().is_none()); /// ``` #[inline] @@ -413,9 +413,9 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter().take(3); - /// assert_eq!(it.next().unwrap(), &1); - /// assert_eq!(it.next().unwrap(), &2); - /// assert_eq!(it.next().unwrap(), &3); + /// assert_eq!(it.next(), Some(&1)); + /// assert_eq!(it.next(), Some(&2)); + /// assert_eq!(it.next(), Some(&3)); /// assert!(it.next().is_none()); /// ``` #[inline] @@ -437,11 +437,11 @@ pub trait Iterator { /// *fac = *fac * x; /// Some(*fac) /// }); - /// assert_eq!(it.next().unwrap(), 1); - /// assert_eq!(it.next().unwrap(), 2); - /// assert_eq!(it.next().unwrap(), 6); - /// assert_eq!(it.next().unwrap(), 24); - /// assert_eq!(it.next().unwrap(), 120); + /// assert_eq!(it.next(), Some(1)); + /// assert_eq!(it.next(), Some(2)); + /// assert_eq!(it.next(), Some(6)); + /// assert_eq!(it.next(), Some(24)); + /// assert_eq!(it.next(), Some(120)); /// assert!(it.next().is_none()); /// ``` #[inline] @@ -680,7 +680,7 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter(); - /// assert_eq!(it.find(|&x| *x == 3).unwrap(), &3); + /// assert_eq!(it.find(|&x| *x == 3), Some(&3)); /// assert_eq!(it.collect::>(), [&4, &5]); #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -715,7 +715,7 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter(); - /// assert_eq!(it.position(|x| *x == 3).unwrap(), 2); + /// assert_eq!(it.position(|x| *x == 3), Some(2)); /// assert_eq!(it.collect::>(), [&4, &5]); #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -743,7 +743,7 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 2, 4, 5]; /// let mut it = a.iter(); - /// assert_eq!(it.rposition(|x| *x == 2).unwrap(), 2); + /// assert_eq!(it.rposition(|x| *x == 2), Some(2)); /// assert_eq!(it.collect::>(), [&1, &2]); #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -773,7 +773,7 @@ pub trait Iterator { /// /// ``` /// let a = [1, 2, 3, 4, 5]; - /// assert_eq!(a.iter().max().unwrap(), &5); + /// assert_eq!(a.iter().max(), Some(&5)); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -796,7 +796,7 @@ pub trait Iterator { /// /// ``` /// let a = [1, 2, 3, 4, 5]; - /// assert_eq!(a.iter().min().unwrap(), &1); + /// assert_eq!(a.iter().min(), Some(&1)); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -1025,9 +1025,9 @@ pub trait Iterator { /// ``` /// let a = [1, 2]; /// let mut it = a.iter().cycle(); - /// assert_eq!(it.next().unwrap(), &1); - /// assert_eq!(it.next().unwrap(), &2); - /// assert_eq!(it.next().unwrap(), &1); + /// assert_eq!(it.next(), Some(&1)); + /// assert_eq!(it.next(), Some(&2)); + /// assert_eq!(it.next(), Some(&1)); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] From 6d410132dcbe7a83f3276b6eac4c0baa0f6a3930 Mon Sep 17 00:00:00 2001 From: Pete Hunt Date: Sun, 10 May 2015 15:11:40 -0700 Subject: [PATCH 47/97] Fix typo in guessing-game docs --- src/doc/trpl/guessing-game.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/trpl/guessing-game.md b/src/doc/trpl/guessing-game.md index 50767b603c46..86158e716d2f 100644 --- a/src/doc/trpl/guessing-game.md +++ b/src/doc/trpl/guessing-game.md @@ -273,7 +273,7 @@ information’. Why throw it away? Well, for a basic program, we just want to print a generic error, as basically any issue means we can’t continue. The [`ok()` method][ok] returns a value which has another method defined on it: `expect()`. The [`expect()` method][expect] takes a value it’s called on, and -if it isn’t a successful one, [`panic!`][panic]s with a message you passed you +if it isn’t a successful one, [`panic!`][panic]s with a message you passed it. A `panic!` like this will cause our program to crash, displaying the message. From a6dc983a604ec3a0e89a08419c57c256ba1a0e4a Mon Sep 17 00:00:00 2001 From: Nick Hamann Date: Sat, 9 May 2015 20:38:10 -0500 Subject: [PATCH 48/97] Add some comments for error codes in librustc_typeck/diagnostics --- src/librustc_typeck/diagnostics.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 026ba3d08b42..904cd156f2a2 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -164,18 +164,18 @@ register_diagnostics! { E0030, E0031, E0033, - E0034, - E0035, - E0036, - E0038, + E0034, // multiple applicable methods in scope + E0035, // does not take type parameters + E0036, // incorrect number of type parameters given for this method + E0038, // cannot convert to a trait object because trait is not object-safe E0040, // explicit use of destructor method - E0044, - E0045, + E0044, // foreign items may not have type parameters + E0045, // variadic function must have C calling convention E0049, E0050, E0053, - E0055, - E0057, + E0055, // method has an incompatible type for trait + E0057, // method has an incompatible type for trait E0059, E0060, E0061, From d730750d24e74263e349b0d5f32a8922065829c0 Mon Sep 17 00:00:00 2001 From: Nick Hamann Date: Sun, 10 May 2015 03:48:15 -0500 Subject: [PATCH 49/97] Add long diagnostics for E0184, E0204, E0205, E0206, E0243, E0244. --- src/librustc_typeck/diagnostics.rs | 117 ++++++++++++++++++++++++++--- 1 file changed, 108 insertions(+), 9 deletions(-) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 904cd156f2a2..7428e5ada5f2 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -150,6 +150,114 @@ attribute. Such a function must have the following type signature: ``` fn(isize, *const *const u8) -> isize ``` +"##, + +E0184: r##" +Explicitly implementing both Drop and Copy for a type is currently disallowed. +This feature can make some sense in theory, but the current implementation is +incorrect and can lead to memory unsafety (see issue #20126), so it has been +disabled for now. +"##, + +E0204: r##" +An attempt to implement the `Copy` trait for a struct failed because one of the +fields does not implement `Copy`. To fix this, you must implement `Copy` for the +mentioned field. Note that this may not be possible, as in the example of + +``` +struct Foo { + foo : Vec, +} + +impl Copy for Foo { } +``` + +This fails because `Vec` does not implement `Copy` for any `T`. + +Here's another example that will fail: + +``` +#[derive(Copy)] +struct Foo<'a> { + ty: &'a mut bool, +} +``` + +This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (as opposed +to `&T`, which is). +"##, + +E0205: r##" +An attempt to implement the `Copy` trait for an enum failed because one of the +variants does not implement `Copy`. To fix this, you must implement `Copy` for +the mentioned variant. Note that this may not be possible, as in the example of + +``` +enum Foo { + Bar(Vec), + Baz, +} + +impl Copy for Foo { } +``` + +This fails because `Vec` does not implement `Copy` for any `T`. + +Here's another example that will fail: + +``` +#[derive(Copy)] +enum Foo<'a> { + Bar(&'a mut bool), + Baz +} +``` + +This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (as opposed +to `&T`, which is). +"##, + +E0206: r##" +You can only implement `Copy` for a struct or enum. For example, both of the +following examples will fail, because neither `i32` nor `&'static mut Bar` is +a struct or enum: + +``` +type Foo = i32; +impl Copy for Foo { } // error + +#[derive(Copy, Clone)] +struct Bar; +impl Copy for &'static mut Bar { } // error +``` +"##, + +E0243: r##" +This error indicates that not enough type parameters were found in a type or +trait. + +For example, the `Foo` struct below is defined to be generic in `T`, but the +type parameter is missing in the definition of `Bar`: + +``` +struct Foo { x: T } + +struct Bar { x: Foo } +``` +"##, + +E0244: r##" +This error indicates that too many type parameters were found in a type or +trait. + +For example, the `Foo` struct below has no type parameters, but is supplied +with two in the definition of `Bar`: + +``` +struct Foo { x: bool } + +struct Bar { x: Foo } +``` "## } @@ -232,7 +340,6 @@ register_diagnostics! { E0178, E0182, E0183, - E0184, E0185, E0186, E0187, // can't infer the kind of the closure @@ -254,12 +361,6 @@ register_diagnostics! { E0202, // associated items are not allowed in inherent impls E0203, // type parameter has more than one relaxed default bound, // and only one is supported - E0204, // trait `Copy` may not be implemented for this type; field - // does not implement `Copy` - E0205, // trait `Copy` may not be implemented for this type; variant - // does not implement `copy` - E0206, // trait `Copy` may not be implemented for this type; type is - // not a structure or enumeration E0207, // type parameter is not constrained by the impl trait, self type, or predicate E0208, E0209, // builtin traits can only be implemented on structs or enums @@ -296,8 +397,6 @@ register_diagnostics! { E0240, E0241, E0242, // internal error looking up a definition - E0243, // wrong number of type arguments - E0244, // wrong number of type arguments E0245, // not a trait E0246, // illegal recursive type E0247, // found module name used as a type From a40c49c6dba55c8074a79fa26fbf2bc0d9387371 Mon Sep 17 00:00:00 2001 From: Nick Hamann Date: Sun, 10 May 2015 12:55:12 -0500 Subject: [PATCH 50/97] Improve wording for E0204 and E0205 long diagnostic messages. --- src/librustc_typeck/diagnostics.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 7428e5ada5f2..887e15bd6b61 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -183,8 +183,8 @@ struct Foo<'a> { } ``` -This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (as opposed -to `&T`, which is). +This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (this +differs from the behavior for `&T`, which is `Copy` when `T` is `Copy`). "##, E0205: r##" @@ -213,8 +213,8 @@ enum Foo<'a> { } ``` -This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (as opposed -to `&T`, which is). +This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (this +differs from the behavior for `&T`, which is `Copy` when `T` is `Copy`). "##, E0206: r##" From 021b3f55d6a10e668a6fa7b51b4f8cd10a2493e5 Mon Sep 17 00:00:00 2001 From: Nick Hamann Date: Sun, 10 May 2015 13:01:40 -0500 Subject: [PATCH 51/97] Revise the E0206 long diagnostics message. --- src/librustc_typeck/diagnostics.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 887e15bd6b61..89b7e8c5747f 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -218,9 +218,9 @@ differs from the behavior for `&T`, which is `Copy` when `T` is `Copy`). "##, E0206: r##" -You can only implement `Copy` for a struct or enum. For example, both of the -following examples will fail, because neither `i32` nor `&'static mut Bar` is -a struct or enum: +You can only implement `Copy` for a struct or enum. Both of the following +examples will fail, because neither `i32` (primitive type) nor `&'static Bar` +(reference to `Bar`) is a struct or enum: ``` type Foo = i32; @@ -228,7 +228,7 @@ impl Copy for Foo { } // error #[derive(Copy, Clone)] struct Bar; -impl Copy for &'static mut Bar { } // error +impl Copy for &'static Bar { } // error ``` "##, From ed1bc684fc28d26635eed49a8a39e6c492782564 Mon Sep 17 00:00:00 2001 From: Nick Hamann Date: Sun, 10 May 2015 13:17:12 -0500 Subject: [PATCH 52/97] Add a link to the E0184 long diagnostic message. --- src/librustc_typeck/diagnostics.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 89b7e8c5747f..373be6207364 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -155,8 +155,10 @@ fn(isize, *const *const u8) -> isize E0184: r##" Explicitly implementing both Drop and Copy for a type is currently disallowed. This feature can make some sense in theory, but the current implementation is -incorrect and can lead to memory unsafety (see issue #20126), so it has been -disabled for now. +incorrect and can lead to memory unsafety (see [issue #20126][iss20126]), so +it has been disabled for now. + +[iss20126]: https://github.com/rust-lang/rust/issues/20126 "##, E0204: r##" From a168a15008e5a5ac50a3914e8d15c6ee8fbc92ce Mon Sep 17 00:00:00 2001 From: Pete Hunt Date: Sun, 10 May 2015 16:10:02 -0700 Subject: [PATCH 53/97] Fix typo in references-and-borrowing docs --- src/doc/trpl/references-and-borrowing.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/trpl/references-and-borrowing.md b/src/doc/trpl/references-and-borrowing.md index da416e994c4c..c434371ce59d 100644 --- a/src/doc/trpl/references-and-borrowing.md +++ b/src/doc/trpl/references-and-borrowing.md @@ -6,7 +6,7 @@ become quite acquainted. Ownership is how Rust achieves its largest goal, memory safety. There are a few distinct concepts, each with its own chapter: -* [ownership][ownership], ownership, the key concept +* [ownership][ownership], the key concept * borrowing, which you’re reading now * [lifetimes][lifetimes], an advanced concept of borrowing @@ -368,4 +368,4 @@ statement 1 at 3:14 println!("{}", y); } -``` \ No newline at end of file +``` From 295b62dfb9ae53cb14518664ddaaf71348b20f18 Mon Sep 17 00:00:00 2001 From: Johann Hofmann Date: Mon, 11 May 2015 00:53:24 +0200 Subject: [PATCH 54/97] Docs: Compile-time bounds check in index expression The reference was claiming all vectors all bounds-checked at run-time, when constant vectors are usually checked at compile-time. For the changed example see http://is.gd/28ak9E --- src/doc/reference.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 16fdcfa30139..fe5a6d9be49d 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -842,7 +842,7 @@ module declarations should be at the crate root if direct usage of the declared modules within `use` items is desired. It is also possible to use `self` and `super` at the beginning of a `use` item to refer to the current and direct parent modules respectively. All rules regarding accessing declared modules in -`use` declarations applies to both module declarations and `extern crate` +`use` declarations apply to both module declarations and `extern crate` declarations. An example of what will and will not work for `use` items: @@ -2564,12 +2564,19 @@ array is mutable, the resulting [lvalue](#lvalues,-rvalues-and-temporaries) can be assigned to. Indices are zero-based, and may be of any integral type. Vector access is -bounds-checked at run-time. When the check fails, it will put the thread in a -_panicked state_. +bounds-checked at compile-time for constant arrays being accessed with a constant index value. +Otherwise a check will be performed at run-time that will put the thread in a _panicked state_ if it fails. ```{should-fail} ([1, 2, 3, 4])[0]; -(["a", "b"])[10]; // panics + +let x = (["a", "b"])[10]; // compiler error: const index-expr is out of bounds + +let n = 10; +let y = (["a", "b"])[n]; // panics + +let arr = ["a", "b"]; +arr[10]; // panics ``` ### Range expressions From 770f0e95a189e84491845ab1378eb3bc3c896f62 Mon Sep 17 00:00:00 2001 From: Johann Hofmann Date: Mon, 11 May 2015 02:03:37 +0200 Subject: [PATCH 55/97] Add if let expressions example --- src/doc/reference.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/doc/reference.md b/src/doc/reference.md index 16fdcfa30139..89f74d8d87af 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -3064,6 +3064,17 @@ of a condition expression it expects a refutable let statement. If the value of expression on the right hand side of the let statement matches the pattern, the corresponding block will execute, otherwise flow proceeds to the first `else` block that follows. +``` +let dish = ("Ham", "Eggs"); +if let ("Bacon", b) = dish { // will not execute because let is refuted + println!("Bacon is served with {}", b); +} + +if let ("Ham", b) = dish { // will execute + println!("Ham is served with {}", b); +} +``` + ### While let loops A `while let` loop is semantically identical to a `while` loop but in place of a From c98df58593254374dac0ab941fe753e4fd6938e3 Mon Sep 17 00:00:00 2001 From: Paul Quint Date: Sun, 10 May 2015 18:08:44 -0500 Subject: [PATCH 56/97] Update BitSet docs to correct types Update BitSet docs to correct type in one more spot removed accidental file --- src/libcollections/bit.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index 17e937c5af25..fd53f9eee930 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -1537,7 +1537,7 @@ impl BitSet { bit_vec.nbits = trunc_len * u32::BITS; } - /// Iterator over each u32 stored in the `BitSet`. + /// Iterator over each usize stored in the `BitSet`. /// /// # Examples /// @@ -1558,7 +1558,7 @@ impl BitSet { SetIter {set: self, next_idx: 0} } - /// Iterator over each u32 stored in `self` union `other`. + /// Iterator over each usize stored in `self` union `other`. /// See [union_with](#method.union_with) for an efficient in-place version. /// /// # Examples @@ -1658,7 +1658,7 @@ impl BitSet { }) } - /// Iterator over each u32 stored in the symmetric difference of `self` and `other`. + /// Iterator over each usize stored in the symmetric difference of `self` and `other`. /// See [symmetric_difference_with](#method.symmetric_difference_with) for /// an efficient in-place version. /// From 6a19046423b49672bc71eb07149ae9ef32bc8af5 Mon Sep 17 00:00:00 2001 From: Johann Date: Mon, 11 May 2015 02:40:02 +0200 Subject: [PATCH 57/97] Four spaces indent, rephrasing --- src/doc/reference.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 89f74d8d87af..e6afa695b2c6 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -3066,12 +3066,15 @@ block will execute, otherwise flow proceeds to the first `else` block that follo ``` let dish = ("Ham", "Eggs"); -if let ("Bacon", b) = dish { // will not execute because let is refuted - println!("Bacon is served with {}", b); + +// this body will be skipped because the pattern is refuted +if let ("Bacon", b) = dish { + println!("Bacon is served with {}", b); } -if let ("Ham", b) = dish { // will execute - println!("Ham is served with {}", b); +// this body will execute +if let ("Ham", b) = dish { + println!("Ham is served with {}", b); } ``` From 3c4facbcfe16ea0919e7a8537cae219c14a2b1ca Mon Sep 17 00:00:00 2001 From: Nick Hamann Date: Sun, 10 May 2015 18:58:21 -0500 Subject: [PATCH 58/97] Add long diagnostics for E0249 and E0250 --- src/librustc_typeck/astconv.rs | 3 ++- src/librustc_typeck/diagnostics.rs | 34 ++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 677254238c03..54ec1aace921 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1603,7 +1603,8 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, Some(i as usize)), _ => { span_err!(tcx.sess, ast_ty.span, E0249, - "expected constant expr for array length"); + "expected constant integer expression \ + for array length"); this.tcx().types.err } } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 373be6207364..ea872d101442 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -260,6 +260,38 @@ struct Foo { x: bool } struct Bar { x: Foo } ``` +"##, + +E0249: r##" +This error indicates a constant expression for the array length was found, but +it was not an integer (signed or unsigned) expression. + +Some examples of code that produces this error are: + +``` +const A: [u32; "hello"] = []; // error +const B: [u32; true] = []; // error +const C: [u32; 0.0] = []; // error +"##, + +E0250: r##" +This means there was an error while evaluating the expression for the length of +a fixed-size array type. + +Some examples of code that produces this error are: + +``` +// divide by zero in the length expression +const A: [u32; 1/0] = []; + +// Rust currently will not evaluate the function `foo` at compile time +fn foo() -> usize { 12 } +const B: [u32; foo()] = []; + +// it is an error to try to add `u8` and `f64` +use std::{f64, u8}; +const C: [u32; u8::MAX + f64::EPSILON] = []; +``` "## } @@ -403,8 +435,6 @@ register_diagnostics! { E0246, // illegal recursive type E0247, // found module name used as a type E0248, // found value name used as a type - E0249, // expected constant expr for array length - E0250, // expected constant expr for array length E0318, // can't create default impls for traits outside their crates E0319, // trait impls for defaulted traits allowed just for structs/enums E0320, // recursive overflow during dropck From 4e8afd65f93f1c351365c71f4461a2c6728f8287 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Mon, 11 May 2015 00:22:04 +0200 Subject: [PATCH 59/97] docs: Update FromStr documentation Fixes #25250 --- src/libcore/str/mod.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 4d39607b16e9..11ca6e332b57 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -44,8 +44,11 @@ pub trait FromStr { #[stable(feature = "rust1", since = "1.0.0")] type Err; - /// Parses a string `s` to return an optional value of this type. If the - /// string is ill-formatted, the None is returned. + /// Parses a string `s` to return a value of this type. + /// + /// If parsing succeeds, return the value inside `Ok`, otherwise + /// when the string is ill-formatted return an error specific to the + /// inside `Err`. The error type is specific to implementation of the trait. #[stable(feature = "rust1", since = "1.0.0")] fn from_str(s: &str) -> Result; } From 02b8e4e6cf6f3fc3a7d31f348fc82bafa0165e3a Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Mon, 11 May 2015 00:29:50 +0200 Subject: [PATCH 60/97] docs: Clarify Path::starts_with (and ends_with) Fixes #24882 --- src/libstd/path.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 8ccc387c9027..21f873e68774 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1449,6 +1449,8 @@ impl Path { /// Determines whether `base` is a prefix of `self`. /// + /// Only considers whole path components to match. + /// /// # Examples /// /// ``` @@ -1457,6 +1459,8 @@ impl Path { /// let path = Path::new("/etc/passwd"); /// /// assert!(path.starts_with("/etc")); + /// + /// assert!(!path.starts_with("/e")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn starts_with>(&self, base: P) -> bool { @@ -1465,6 +1469,8 @@ impl Path { /// Determines whether `child` is a suffix of `self`. /// + /// Only considers whole path components to match. + /// /// # Examples /// /// ``` From 098040f8fc8a0928bec25382066b5318c63e2a31 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Mon, 11 May 2015 00:38:47 +0200 Subject: [PATCH 61/97] docs: Link from tls macros to relevant docs Fixes #25233 --- src/libstd/thread/local.rs | 2 ++ src/libstd/thread/scoped_tls.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 41bdf034705d..2e043c58a5da 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -85,6 +85,8 @@ pub struct LocalKey { } /// Declare a new thread local storage key of type `std::thread::LocalKey`. +/// +/// See [LocalKey documentation](thread/struct.LocalKey.html) for more information. #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable] diff --git a/src/libstd/thread/scoped_tls.rs b/src/libstd/thread/scoped_tls.rs index 35684a1f3909..e195c3aaa3f8 100644 --- a/src/libstd/thread/scoped_tls.rs +++ b/src/libstd/thread/scoped_tls.rs @@ -66,6 +66,8 @@ pub struct ScopedKey { #[doc(hidden)] pub inner: __impl::KeyInner } /// /// This macro declares a `static` item on which methods are used to get and /// set the value stored within. +/// +/// See [ScopedKey documentation](thread/struct.ScopedKey.html) for more information. #[macro_export] #[allow_internal_unstable] macro_rules! scoped_thread_local { From 12d50b2da02166582326833efa6ba59e55cd18cf Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Mon, 11 May 2015 01:25:10 +0200 Subject: [PATCH 62/97] docs: Fixes in Reference Chapter 6.1 --- src/doc/reference.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 16fdcfa30139..0c70f442231a 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -653,9 +653,10 @@ There are several kinds of item: * [`use` declarations](#use-declarations) * [modules](#modules) * [functions](#functions) -* [type definitions](#type-definitions) +* [type aliases](#type-aliases) * [structures](#structures) * [enumerations](#enumerations) +* [constant items](#constant-items) * [static items](#static-items) * [traits](#traits) * [implementations](#implementations) @@ -672,16 +673,16 @@ which sub-item declarations may appear. ### Type Parameters -All items except modules may be *parameterized* by type. Type parameters are -given as a comma-separated list of identifiers enclosed in angle brackets -(`<...>`), after the name of the item and before its definition. The type -parameters of an item are considered "part of the name", not part of the type -of the item. A referencing [path](#paths) must (in principle) provide type -arguments as a list of comma-separated types enclosed within angle brackets, in -order to refer to the type-parameterized item. In practice, the type-inference -system can usually infer such argument types from context. There are no -general type-parametric types, only type-parametric items. That is, Rust has -no notion of type abstraction: there are no first-class "forall" types. +All items except modules, constants and statics may be *parameterized* by type. +Type parameters are given as a comma-separated list of identifiers enclosed in +angle brackets (`<...>`), after the name of the item and before its definition. +The type parameters of an item are considered "part of the name", not part of +the type of the item. A referencing [path](#paths) must (in principle) provide +type arguments as a list of comma-separated types enclosed within angle +brackets, in order to refer to the type-parameterized item. In practice, the +type-inference system can usually infer such argument types from context. There +are no general type-parametric types, only type-parametric items. That is, Rust +has no notion of type abstraction: there are no first-class "forall" types. ### Modules @@ -743,7 +744,7 @@ mod thread { } ``` -##### Extern crate declarations +#### Extern crate declarations An _`extern crate` declaration_ specifies a dependency on an external crate. The external crate is then bound into the declaring scope as the `ident` @@ -767,7 +768,7 @@ extern crate std; // equivalent to: extern crate std as std; extern crate std as ruststd; // linking to 'std' under another name ``` -##### Use declarations +#### Use declarations A _use declaration_ creates one or more local name bindings synonymous with some other [path](#paths). Usually a `use` declaration is used to shorten the From aabdd8e0a607643915020c072923fdf135358921 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Mon, 11 May 2015 02:01:27 +0200 Subject: [PATCH 63/97] docs: Update SliceConcatExt docs for assoc types --- src/libcollections/slice.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index b9e9800f7a0e..d5a069b194a5 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -1002,7 +1002,7 @@ pub trait SliceConcatExt { /// The resulting type after concatenation type Output; - /// Flattens a slice of `T` into a single value `U`. + /// Flattens a slice of `T` into a single value `Self::Output`. /// /// # Examples /// @@ -1012,7 +1012,8 @@ pub trait SliceConcatExt { #[stable(feature = "rust1", since = "1.0.0")] fn concat(&self) -> Self::Output; - /// Flattens a slice of `T` into a single value `U`, placing a given separator between each. + /// Flattens a slice of `T` into a single value `Self::Output`, placing a given separator + /// between each. /// /// # Examples /// From 847c088ac503294d3d47d2dc5bc4d5671bfa162d Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 6 May 2015 13:23:33 -0700 Subject: [PATCH 64/97] Update AUTHORS.txt and RELEASES.md for 1.0 --- AUTHORS.txt | 107 ++++++++++++++----------- RELEASES.md | 194 ++++++++++++++++++++++++++++++--------------- src/rust-installer | 2 +- 3 files changed, 188 insertions(+), 115 deletions(-) diff --git a/AUTHORS.txt b/AUTHORS.txt index 0f20e510adcd..16346db4e1d9 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -8,6 +8,7 @@ Aaron Raimist Aaron Todd Aaron Turon Aaron Weiss +Abhishek Chanda Adam Bozanich Adam Jacob Adam Roben @@ -28,6 +29,7 @@ Aleksandr Koshlo Alex Crichton Alex Gaynor Alex Lyon +Alex Quach Alex Rønne Petersen Alex Whitney Alexander Bliskovsky @@ -41,7 +43,6 @@ Alexandros Tasos Alexei Sholik Alexis Beingessner Alfie John -Alfie John Ali Smesseim Alisdair Owens Aljaž "g5pw" Srebrnič @@ -64,10 +65,13 @@ Andrew Gallant Andrew Hobden Andrew Paseltiner Andrew Poelstra +Andrew Seidl Andrew Wagner Angus Lees Anthony Juckel Anton Löfgren +Aram Visser +Areski Belaid Arcterus Ariel Ben-Yehuda Arjan Topolovec @@ -78,6 +82,7 @@ Arpad Borsos Artem Arthur Liao Ashok Gautham +Augusto Hack Austin Bonander Austin King Austin Seipp @@ -85,13 +90,14 @@ Axel Viala Aydin Kim Barosl Lee Ben Alpert +Ben Ashford Ben Blum Ben Foppa Ben Gamari Ben Harris Ben Kelly Ben Noordhuis -Ben S +Ben Sago Ben Striegel Benjamin Adamson Benjamin Herr @@ -112,6 +118,7 @@ Brandon Waskiewicz Branimir Brendan Cully Brendan Eich +Brendan Graetz Brendan McLoughlin Brendan Zabarauskas Brett Cannon @@ -135,8 +142,8 @@ Camille TJHOA CarVac Carl Lerche Carl-Anton Ingmarsson -Carlos -Carol Nichols +Carlos Galarza +Carol (Nichols || Goulding) Carol Willing Carter Hinsley Carter Tazio Schonwald @@ -151,10 +158,11 @@ Chris Peterson Chris Pressey Chris Sainty Chris Shea -Chris Thorn +Chris Thorn Chris Wong Christoph Burgdorf Christopher Bergqvist +Christopher Chambers Christopher Kendell Chuck Ries Clark Gaebel @@ -172,13 +180,14 @@ Corey Richardson Cristi Burcă Cristian Kubis DJUrsus -Dabo Ross +David Ross Damian Gryski Damien Grassart Damien Radtke Damien Schoof Dan Albert Dan Burkert +Dan Callahan Dan Connolly Dan Luu Dan Schatzberg @@ -234,6 +243,8 @@ Dmitry Ermolov Dmitry Promsky Dmitry Vasiliev Do Nhat Minh +Dominic van Berkel +Dominick Allen Dominik Inführ Donovan Preston Douglas Young @@ -287,11 +298,10 @@ Felix S. Klock II Fenhl Filip Szczepański Flaper Fesp -Flavio Percoco Florian Gilcher Florian Hahn Florian Hartwig -Florian Wilkens +Florian Wilkens Florian Zeitz Francisco Souza Franklin Chen @@ -310,13 +320,12 @@ Georges Dubus Germano Gabbianelli Gil Cottle Gioele Barabucci -GlacJAY Gleb Kozyrev Glenn Willen Gonçalo Cabrita <_@gmcabrita.com> Graham Fawcett Grahame Bowland -Graydon Hoare +Graydon Hoare Greg Chapple Grigoriy Guillaume Gomez @@ -325,11 +334,12 @@ Gyorgy Andrasek Gábor Horváth Gábor Lehel Haitao Li +Hajime Morrita Hanno Braun Harry Marr Heather Henrik Schopmans -Herman J. Radtke III +Herman J. Radtke III HeroesGrave Hong Chulju Honza Strnad @@ -343,6 +353,7 @@ Ian D. Bollinger Ian Daniher Ignacio Corderi Igor Bukanov +Igor Strebezhev Ilya Dmitrichenko Ilyong Cho Ingo Blechschmidt @@ -390,7 +401,7 @@ Jashank Jeremy Jason Fager Jason Orendorff Jason Thompson -Jason Toffaletti +Jason Toffaletti Jauhien Piatlicki Jay Anderson Jay True @@ -421,8 +432,10 @@ Jimmie Elvenmark Jimmy Lu Jimmy Zelinskie Jiří Stránský +João Oliveira Joe Pletcher Joe Schafer +Johann Hofmann Johannes Hoff Johannes Löthberg Johannes Muenzel @@ -436,10 +449,10 @@ John Gallagher John Hodge John Kåre Alsaker John Kleint -John Kåre Alsaker John Louis Walker John Schmidt John Simon +John Talling John Zhang Jon Haddad Jon Morton @@ -462,6 +475,7 @@ Joseph Rushton Wakeling Josh Haberman Josh Matthews Josh Stone +Josh Triplett Joshua Clark Joshua Wise Joshua Yanovski @@ -515,6 +529,7 @@ Loïc Damien Luca Bruno Luis de Bethencourt Luke Francl +Luke Gallagher Luke Metz Luke Steensen Luqman Aden @@ -523,10 +538,12 @@ Magnus Auvinen Mahmut Bulut Makoto Nakashima Manish Goregaokar +Manuel Hoffmann Marcel Rodrigues Margaret Meyerhofer Marijn Haverbeke Mark Lacey <641@rudkx.com> +Mark Mossberg Mark Rowe Mark Sinclair Mark Vian @@ -563,6 +580,7 @@ Maximilian Haack Maya Nitu Meyer S. Jacobs Micah Chalmer +Michael Alexander Michael Arntzenius Michael Bebenita Michael Budde @@ -582,9 +600,12 @@ Michael Sullivan Michael Williams Michael Woerister Michael Zhou +Michał Czardybon Michał Krasnoborski Mick Koch Mickaël Delahaye +Mickaël Raybaud-Roig +Mickaël Salaün Mihnea Dobrescu-Balaur Mike Boutin Mike Dilger @@ -595,28 +616,28 @@ Mikhail Zabaluev Mikko Perttunen Ms2ger Mukilan Thiagarajan -Mukilan Thiyagarajan Murarth Mátyás Mustoha -NAKASHIMA, Makoto NODA, Kai Nafis Nathan Froyd Nathan Stoddard Nathan Typanski +Nathan Wilson Nathan Zadoks Nathaniel Herman Nathaniel Theis Neil Pankey Nelson Chen NiccosSystem -Nicholas Nicholas Bishop Nicholas Mazzuca Nick Cameron Nick Desaulniers +Nick Hamann Nick Howell Nick Sarten +Nick Platt Nicolas Silva Niels Egberts Niels langager Ellegaard @@ -626,9 +647,10 @@ Niklas Koep Niko Matsakis Noam Yorav-Raphael Noufal Ibrahim +Oak O S K Chaitanya OGINO Masanori -Oliver Schneider +Oliver Schneider Olivier Saut Olle Jonsson Or Brostovski @@ -650,6 +672,7 @@ Paul Collier Paul Collins Paul Crowley Paul Osborne +Paul Quint Paul Stansifer Paul Woolcock Pavel Panchekha @@ -657,7 +680,7 @@ Pawel Olzacki Pedro Larroy Peer Aramillo Irizar Peter Atashian -Peter Elmers +Peter Elmers Peter Hull Peter Marheine Peter Minten @@ -675,12 +698,11 @@ Piotr Czarnecki Piotr Jawniak Piotr Szotkowski Piotr Zolnierek +Poga Po Potpourri -Pradeep Kumar Prudhvi Krishna Surapaneni Pyfisch Pyry Kontio -Pythoner6 Q.P.Liu Rafael Ávila de Espíndola Rahul Horé @@ -694,9 +716,9 @@ Raphael Speyer Raul Gutierrez S Ray Clanan Reilly Watson +Remi Rampin Renato Alves Renato Riccieri Santos Zannon -Renato Zannon Reuben Morais Ricardo M. Correia Ricardo Martins @@ -714,6 +736,7 @@ Robert Irelan Robert Knight Robert Millar Robin Gloster +Robin Kruppe Robin Stocker Rohit Joshi Roland Tanglao @@ -722,14 +745,13 @@ Rolf van de Krol Ron Dahlgren Roy Crihfield Roy Frostig -Russell +Russell Johnston Ruud van Asseldonk Ryan Levick Ryan Mulligan Ryan Prichard Ryan Riginding Ryan Scheel -Ryman Rüdiger Sonderfeld S Pradeep Kumar Sae-bom Kim @@ -745,6 +767,7 @@ Saurabh Anand Scott Jenkins Scott Lawrence Scott Olson +Sean Bowe Sean Chalmers Sean Collins Sean Gillespie @@ -799,16 +822,18 @@ Taylor Hutchison Ted Horst Tero Hänninen Thad Guidry +Theo Belaire Thiago Carvalho Thiago Pontes Thomas Backman +Thomas Bracht Laumann Jespersen Thomas Daede Tiago Nobrega +Tibor Benke Till Hoeppner Tim Brooks Tim Chevalier Tim Cuthbertson -Tim Dumol Tim Joseph Dumol Tim Kuehn Tim Parenti @@ -836,7 +861,7 @@ Trinick Tristan Storch Tshepang Lekhonkhobe Tuncer Ayaz -TyOverby +Ty Overby Tycho Sci Tyler Bindon Tyler Thrailkill @@ -870,8 +895,10 @@ WebeWizard Wendell Smith Wesley Wiser Will +Will Hipschman William Ting Willson Mock +Xue Fuqiao Yasuhiro Fujii YawarRaza7349 Yazhong Liu @@ -889,27 +916,21 @@ Zack Slayton Zbigniew Siciarz Ziad Hatahet Zooko Wilcox-O'Hearn -adridu59 -aochagavia -areski arturo auREAX awlnx aydin.kim -b1nd bachm bcoopers -blackbeam +Anatoly Ikorsky blake2-ppc bluss -bombless bors -caipre chitra chromatic comex crhino -dan@daramos.com +Daniel Ramos darkf defuz dgoon @@ -917,6 +938,7 @@ donkopotamus eliovir elszben emanueLczirai +fenduru flo-l fort free-Runner @@ -924,17 +946,13 @@ g3xzh gamazeps gareth gentlefolk -gifnksm +github-monoculture hansjorg -iancormac84 -inrustwetrust jamesluke jatinn jbranchaud -jfager jmgrosen jmu303 -joaoxsouls jrincayc juxiliary jxv @@ -942,15 +960,12 @@ kgv kjpgit klutzy korenchkin -kud1ing kulakowski -kvark kwantam lpy lucy lummax lyuts -m-r-r madmalik maikklein masklinn @@ -962,21 +977,20 @@ mr.Shu mrec musitdev nathan dotz -nham -niftynif +Nils Winter noam novalis nsf -nwin -oli-obk olivren osa1 +pez posixphreak qwitwa ray glover reedlepee reus rjz +rundrop1 sevrak sheroze1123 smenardpw @@ -990,12 +1004,9 @@ tinaun tshakah ville-h visualfc -we whataloadofwhat wickerwaka wonyong kim xales zofrex -zslayton -zzmp 克雷 diff --git a/RELEASES.md b/RELEASES.md index 7da73afb4111..7c8a6d0e0cdb 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,79 +1,140 @@ -Version 1.0.0-beta (April 2015) -------------------------------------- +Version 1.0.0 (May 2015) +======================== -* ~1100 changes, numerous bugfixes +Highlights +---------- -* Highlights +* The vast majority of the standard library is now `#[stable]`. It is + no longer possible to use unstable features with a stable build of + the compiler. +* Many popular crates on [crates.io] now work on the stable release + channel. +* Arithmetic on basic integer types now [checks for overflow in debug + builds][overflow]. - * The big news is that the vast majority of the standard library - is now `#[stable]` -- 75% of the non-deprecated API surface at - last count. Numerous crates are now running on stable - Rust. Starting with this release, it is not possible to use - unstable features on a stable build. - * Arithmetic on basic integer types now - [checks for overflow in debug builds][overflow]. +Language +-------- -* Language +* Several [restrictions have been added to trait coherence][coh] in + order to make it easier for upstream authors to change traits + without breaking downsteam code. +* Digits of binary and octal literals are [lexed more eagerly][lex] to + improve error messages and macro behavior. For example, `0b1234` is + now lexed as `0b1234` instead of two tokens, `0b1` and `234`. +* Trait bounds [are always invariant][inv], eleminating the need for + the `PhantomFn` and `MarkerTrait` lang items, which have been + removed. +* ["-" is no longer a valid character in crate names][cr], the `extern crate + "foo" as bar` syntax has been replaced with `extern crate foo as + bar`, and Cargo now automatically translates "-" in *package* names + to underscore for the crate name. +* [Lifetime shadowing is an error][lt]. +* [`Send` no longer implies `'static`][send-rfc]. +* [UFCS now supports trait-less associated paths][moar-ufcs] like + `MyType::default()`. +* Primitive types [now have inherent methods][prim-inherent], + obviating the need for extension traits like `SliceExt`. +* Methods with `Self: Sized` in their `where` clause are [considered + object-safe][self-sized], allowing many extension traits like + `IteratorExt` to be merged into the traits they extended. +* You can now [refer to associated types][assoc-where] whose + corresponding trait bounds appear only in a `where` clause. +* The final bits of [OIBIT landed][oibit-final], meaning that traits + like `Send` and `Sync` are now library-defined. +* A [Reflect trait][reflect] was introduced, which means that + downcasting via the `Any` trait is effectively limited to concrete + types. This helps retain the potentially-important "parametricity" + property: generic code cannot behave differently for different type + arguments except in minor ways. +* The `unsafe_destructor` feature is now deprecated in favor of the + [new `dropck`][dropck]. This change is a major reduction in unsafe + code. - * [`Send` no longer implies `'static`][send-rfc], which made - possible the [`thread::scoped` API][scoped]. Scoped threads can - borrow data from their parent's stack frame -- safely! - * [UFCS now supports trait-less associated paths][moar-ufcs] like - `MyType::default()`. - * Primitive types [now have inherent methods][prim-inherent], - obviating the need for extension traits like `SliceExt`. - * Methods with `Self: Sized` in their `where` clause are - [considered object-safe][self-sized], allowing many extension - traits like `IteratorExt` to be merged into the traits they - extended. - * You can now [refer to associated types][assoc-where] whose - corresponding trait bounds appear only in a `where` clause. - * The final bits of [OIBIT landed][oibit-final], meaning that - traits like `Send` and `Sync` are now library-defined. - * A [Reflect trait][reflect] was introduced, which means that - downcasting via the `Any` trait is effectively limited to - concrete types. This helps retain the potentially-important - "parametricity" property: generic code cannot behave differently - for different type arguments except in minor ways. - * The `unsafe_destructor` feature is now deprecated in favor of - the [new `dropck`][dropck]. This change is a major reduction in - unsafe code. - * Trait coherence was [revised again][fundamental], this time with - an eye toward API evolution over time. +Libraries +--------- -* Libraries +* The `thread_local` module [has been renamed to `std::thread`][th]. +* The methods of `IteratorExt` [have been moved to the `Iterator` + trait itself][ie]. +* Several traits that implement Rust's conventions for type + conversions, `AsMut`, `AsRef`, `From`, and `Into` have been + [centralized in the `std::convert` module][con]. +* The `FromError` trait [was removed in favor of `From`][fe]. +* The basic sleep function [has moved to + `std::thread::sleep_ms`][slp]. +* The `splitn` function now takes an `n` parameter that represents the + number of items yielded by the returned iterator [instead of the + number of 'splits'][spl]. +* [On Unix, all file descriptors are `CLOEXEC` by default][clo]. +* [Derived implementations of `PartialOrd` now order enums according + to their explicitly-assigned discriminants][po]. +* [Methods for searching strings are generic over `Pattern`s][pat], + implemented presently by `&char`, `&str`, `FnMut(char) -> bool` and + some others. +* [In method resolution, object methods are resolved before inherent + methods][meth]. +* [`String::from_str` has been deprecated in favor of the `From` impl, + `String::from`][sf]. +* [`io::Error` implements `Sync`][ios]. +* [The `words` method on `&str` has been replaced with + `split_whitespace`][sw], to avoid answering the tricky question, 'what is + a word?' +* The new path and IO modules are complete and `#[stable]`. This + was the major library focus for this cycle. +* The path API was [revised][path-normalize] to normalize `.`, + adjusting the tradeoffs in favor of the most common usage. +* A large number of remaining APIs in `std` were also stabilized + during this cycle; about 75% of the non-deprecated API surface + is now stable. +* The new [string pattern API][string-pattern] landed, which makes + the string slice API much more internally consistent and flexible. +* A new set of [generic conversion traits][conversion] replaced + many existing ad hoc traits. +* Generic numeric traits were [completely removed][num-traits]. This + was made possible thanks to inherent methods for primitive types, + and the removal gives maximal flexibility for designing a numeric + hierarchy in the future. +* The `Fn` traits are now related via [inheritance][fn-inherit] + and provide ergonomic [blanket implementations][fn-blanket]. +* The `Index` and `IndexMut` traits were changed to + [take the index by value][index-value], enabling code like + `hash_map["string"]` to work. +* `Copy` now [inherits][copy-clone] from `Clone`, meaning that all + `Copy` data is known to be `Clone` as well. - * The new path and IO modules are complete and `#[stable]`. This - was the major library focus for this cycle. - * The path API was [revised][path-normalize] to normalize `.`, - adjusting the tradeoffs in favor of the most common usage. - * A large number of remaining APIs in `std` were also stabilized - during this cycle; about 75% of the non-deprecated API surface - is now stable. - * The new [string pattern API][string-pattern] landed, which makes - the string slice API much more internally consistent and flexible. - * A shiny [framework for Debug implementations][debug-builder] landed. - This makes it possible to opt in to "pretty-printed" debugging output. - * A new set of [generic conversion traits][conversion] replaced - many existing ad hoc traits. - * Generic numeric traits were - [completely removed][num-traits]. This was made possible thanks - to inherent methods for primitive types, and the removal gives - maximal flexibility for designing a numeric hierarchy in the future. - * The `Fn` traits are now related via [inheritance][fn-inherit] - and provide ergonomic [blanket implementations][fn-blanket]. - * The `Index` and `IndexMut` traits were changed to - [take the index by value][index-value], enabling code like - `hash_map["string"]` to work. - * `Copy` now [inherits][copy-clone] from `Clone`, meaning that all - `Copy` data is known to be `Clone` as well. +Misc +---- -* Infrastructure +* Many errors now have extended explanations that can be accessed with + the `--explain` flag to `rustc`. +* Many new examples have been added to the standard library + documentation. +* rustdoc has received a number of improvements focused on completion + and polish. +* Metadata was tuned, shrinking binaries [by 27%][metadata-shrink]. +* Much headway was made on ecosystem-wide CI, making it possible + to [compare builds for breakage][ci-compare]. - * Metadata was tuned, shrinking binaries [by 27%][metadata-shrink]. - * Much headway was made on ecosystem-wide CI, making it possible - to [compare builds for breakage][ci-compare]. +[crates.io]: http://crates.io +[clo]: https://github.com/rust-lang/rust/pull/24034 +[coh]: https://github.com/rust-lang/rfcs/blob/master/text/1023-rebalancing-coherence.md +[con]: https://github.com/rust-lang/rust/pull/23875 +[cr]: https://github.com/rust-lang/rust/pull/23419 +[fe]: https://github.com/rust-lang/rust/pull/23879 +[ie]: https://github.com/rust-lang/rust/pull/23300 +[inv]: https://github.com/rust-lang/rust/pull/23938 +[ios]: https://github.com/rust-lang/rust/pull/24133 +[lex]: https://github.com/rust-lang/rfcs/blob/master/text/0879-small-base-lexing.md +[lt]: https://github.com/rust-lang/rust/pull/24057 +[meth]: https://github.com/rust-lang/rust/pull/24056 +[pat]: https://github.com/rust-lang/rfcs/blob/master/text/0528-string-patterns.md +[po]: https://github.com/rust-lang/rust/pull/24270 +[sf]: https://github.com/rust-lang/rust/pull/24517 +[slp]: https://github.com/rust-lang/rust/pull/23949 +[spl]: https://github.com/rust-lang/rfcs/blob/master/text/0979-align-splitn-with-other-languages.md +[sw]: https://github.com/rust-lang/rfcs/blob/master/text/1054-str-words.md +[th]: https://github.com/rust-lang/rfcs/blob/master/text/0909-move-thread-local-to-std-thread.md [send-rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0458-send-improvements.md [scoped]: http://static.rust-lang.org/doc/master/std/thread/fn.scoped.html [moar-ufcs]: https://github.com/rust-lang/rust/pull/22172 @@ -97,6 +158,7 @@ Version 1.0.0-beta (April 2015) [copy-clone]: https://github.com/rust-lang/rust/pull/23860 [path-normalize]: https://github.com/rust-lang/rust/pull/23229 + Version 1.0.0-alpha.2 (February 2015) ------------------------------------- diff --git a/src/rust-installer b/src/rust-installer index e54d4823d26c..ebc6b04c2959 160000 --- a/src/rust-installer +++ b/src/rust-installer @@ -1 +1 @@ -Subproject commit e54d4823d26cdb3f98e5a1b17e1c257cd329aa61 +Subproject commit ebc6b04c29591108d3f28e724b4b9b74cd1232e6 From c9c8ff1762b6761b738380ba57c939d515eab50c Mon Sep 17 00:00:00 2001 From: Carol Nichols Date: Tue, 5 May 2015 20:52:34 -0400 Subject: [PATCH 65/97] Add visibility section of the grammar Namely an optional "pub" before any item. The "pub" in the Use declaration section should use this too. --- src/doc/grammar.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/doc/grammar.md b/src/doc/grammar.md index 4897b27dec35..e14300dcd5dd 100644 --- a/src/doc/grammar.md +++ b/src/doc/grammar.md @@ -304,7 +304,7 @@ transcriber : '(' transcriber * ')' | '[' transcriber * ']' ## Items ```antlr -item : mod_item | fn_item | type_item | struct_item | enum_item +item : vis ? mod_item | fn_item | type_item | struct_item | enum_item | const_item | static_item | trait_item | impl_item | extern_block ; ``` @@ -335,8 +335,8 @@ crate_name: ident | ( ident "as" ident ) ##### Use declarations ```antlr -use_decl : "pub" ? "use" [ path "as" ident - | path_glob ] ; +use_decl : vis ? "use" [ path "as" ident + | path_glob ] ; path_glob : ident [ "::" [ path_glob | '*' ] ] ? @@ -414,8 +414,9 @@ extern_block : [ foreign_fn ] * ; ## Visibility and Privacy -**FIXME:** grammar? - +```antlr +vis : "pub" ; +``` ### Re-exporting and Visibility **FIXME:** grammar? From a5c651cfdfe78d464653d63cc5b6496f50c2fab0 Mon Sep 17 00:00:00 2001 From: Carol Nichols Date: Tue, 5 May 2015 21:06:17 -0400 Subject: [PATCH 66/97] Point to the use declaration section from the re-exporting section The syntax for re-exporting privacy is covered in the use declaration item. --- src/doc/grammar.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/grammar.md b/src/doc/grammar.md index e14300dcd5dd..6a2ad874513f 100644 --- a/src/doc/grammar.md +++ b/src/doc/grammar.md @@ -419,7 +419,7 @@ vis : "pub" ; ``` ### Re-exporting and Visibility -**FIXME:** grammar? +See [Use declarations](#use-declarations). ## Attributes From ab913c881cfd559591fcde3ca1c82c784c5aab87 Mon Sep 17 00:00:00 2001 From: Carol Nichols Date: Tue, 5 May 2015 21:52:21 -0400 Subject: [PATCH 67/97] Fill in grammar for Statements Some of this text is duplicated in the reference (and belongs there) so remove it. It says item grammar is the same, so point to that grammar section. --- src/doc/grammar.md | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/doc/grammar.md b/src/doc/grammar.md index 6a2ad874513f..e606b282f5c2 100644 --- a/src/doc/grammar.md +++ b/src/doc/grammar.md @@ -434,26 +434,19 @@ meta_seq : meta_item [ ',' meta_seq ] ? ; ## Statements -**FIXME:** grammar? +```antlr +stmt : decl_stmt | expr_stmt ; +``` ### Declaration statements -**FIXME:** grammar? - -A _declaration statement_ is one that introduces one or more *names* into the -enclosing statement block. The declared names may denote new variables or new -items. +```antlr +decl_stmt : item | let_decl ; +``` #### Item declarations -**FIXME:** grammar? - -An _item declaration statement_ has a syntactic form identical to an -[item](#items) declaration within a module. Declaring an item — a -function, enumeration, structure, type, static, trait, implementation or module -— locally within a statement block is simply a way of restricting its -scope to a narrow region containing all of its uses; it is otherwise identical -in meaning to declaring the item outside the statement block. +See [Items](#items). #### Variable declarations @@ -464,7 +457,9 @@ init : [ '=' ] expr ; ### Expression statements -**FIXME:** grammar? +```antlr +expr_stmt : expr ';' ; +``` ## Expressions From e607d76564cf01247b247e0e83c7abdc4bb1fbee Mon Sep 17 00:00:00 2001 From: Carol Nichols Date: Tue, 5 May 2015 22:32:20 -0400 Subject: [PATCH 68/97] Fill in more parts of the grammar for Expressions --- src/doc/grammar.md | 59 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/src/doc/grammar.md b/src/doc/grammar.md index e606b282f5c2..a752ce47b1ba 100644 --- a/src/doc/grammar.md +++ b/src/doc/grammar.md @@ -463,7 +463,15 @@ expr_stmt : expr ';' ; ## Expressions -**FIXME:** grammar? +```antlr +expr : literal | path | tuple_expr | unit_expr | struct_expr + | block_expr | method_call_expr | field_expr | array_expr + | idx_expr | range_expr | unop_expr | binop_expr + | paren_expr | call_expr | lambda_expr | while_expr + | loop_expr | break_expr | continue_expr | for_expr + | if_expr | match_expr | if_let_expr | while_let_expr + | return_expr ; +``` #### Lvalues, rvalues and temporaries @@ -475,19 +483,23 @@ expr_stmt : expr ';' ; ### Literal expressions -**FIXME:** grammar? +See [Literals](#literals). ### Path expressions -**FIXME:** grammar? +See [Paths](#paths). ### Tuple expressions -**FIXME:** grammar? +```antlr +tuple_expr : '(' [ expr [ ',' expr ] * | expr ',' ] ? ')' ; +``` ### Unit expressions -**FIXME:** grammar? +```antlr +unit_expr : "()" ; +``` ### Structure expressions @@ -545,41 +557,60 @@ range_expr : expr ".." expr | ### Unary operator expressions -**FIXME:** grammar? +```antlr +unop_expr : unop expr ; +unop : '-' | '*' | '!' ; +``` ### Binary operator expressions ```antlr -binop_expr : expr binop expr ; +binop_expr : expr binop expr | type_cast_expr + | assignment_expr | compound_assignment_expr ; +binop : arith_op | bitwise_op | lazy_bool_op | comp_op ``` #### Arithmetic operators -**FIXME:** grammar? +```antlr +arith_op : '+' | '-' | '*' | '/' | '%' ; +``` #### Bitwise operators -**FIXME:** grammar? +```antlr +bitwise_op : '&' | '|' | '^' | "<<" | ">>" ; +``` #### Lazy boolean operators -**FIXME:** grammar? +```antlr +lazy_bool_op : "&&" | "||" ; +``` #### Comparison operators -**FIXME:** grammar? +```antlr +comp_op : "==" | "!=" | '<' | '>' | "<=" | ">=" ; +``` #### Type cast expressions -**FIXME:** grammar? +```antlr +type_cast_expr : value "as" type ; +``` #### Assignment expressions -**FIXME:** grammar? +```antlr +assignment_expr : expr '=' expr ; +``` #### Compound assignment expressions -**FIXME:** grammar? +```antlr +compound_assignment_expr : expr [ arith_op | bitwise_op ] '=' expr ; +``` #### Operator precedence From c3156a8ff434060403a1743cff780d8e80a53db2 Mon Sep 17 00:00:00 2001 From: Carol Nichols Date: Tue, 5 May 2015 22:32:38 -0400 Subject: [PATCH 69/97] Remove operator precedence section covered in the reference --- src/doc/grammar.md | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/src/doc/grammar.md b/src/doc/grammar.md index a752ce47b1ba..3cecc28b8036 100644 --- a/src/doc/grammar.md +++ b/src/doc/grammar.md @@ -612,30 +612,6 @@ assignment_expr : expr '=' expr ; compound_assignment_expr : expr [ arith_op | bitwise_op ] '=' expr ; ``` -#### Operator precedence - -The precedence of Rust binary operators is ordered as follows, going from -strong to weak: - -```text -* / % -as -+ - -<< >> -& -^ -| -< > <= >= -== != -&& -|| -= -``` - -Operators at the same precedence level are evaluated left-to-right. [Unary -operators](#unary-operator-expressions) have the same precedence level and it -is stronger than any of the binary operators'. - ### Grouped expressions ```antlr From 53cd0bc772c5b73d8059a02f828ceecf9ed2287c Mon Sep 17 00:00:00 2001 From: Carol Nichols Date: Sun, 10 May 2015 20:48:02 -0400 Subject: [PATCH 70/97] Add literal semicolon to the grammar of view_item Both external crate declarations and use declarations need to end with a semicolon. --- src/doc/grammar.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/grammar.md b/src/doc/grammar.md index 3cecc28b8036..a3325b82a9da 100644 --- a/src/doc/grammar.md +++ b/src/doc/grammar.md @@ -322,7 +322,7 @@ mod : [ view_item | item ] * ; #### View items ```antlr -view_item : extern_crate_decl | use_decl ; +view_item : extern_crate_decl | use_decl ';' ; ``` ##### Extern crate declarations From 218d38fb94379feca89eb858b309890d513c35da Mon Sep 17 00:00:00 2001 From: Carol Nichols Date: Sun, 10 May 2015 22:17:33 -0400 Subject: [PATCH 71/97] Overwrite grammar sections with what was removed from the reference Between ffc5f1c, when grammar.md was created by copying parts of the reference, and 8cf2552, when all EBNF was removed from reference.md, there were parts of the grammar that were updated in reference.md but not grammar.md, and then they weren't copied over because they existed already, but they were slightly out of date. Example: the `path_item : ident | "self" ;` rule in Use declarations was changed from "mod" to "self" in the reference in 195fd9a but wasn't updated in the grammar. --- src/doc/grammar.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/doc/grammar.md b/src/doc/grammar.md index a3325b82a9da..fb7562e7bdf8 100644 --- a/src/doc/grammar.md +++ b/src/doc/grammar.md @@ -253,7 +253,7 @@ The two values of the boolean type are written `true` and `false`. ### Symbols ```antlr -symbol : "::" "->" +symbol : "::" | "->" | '#' | '[' | ']' | '(' | ')' | '{' | '}' | ',' | ';' ; ``` @@ -342,7 +342,7 @@ path_glob : ident [ "::" [ path_glob | '*' ] ] ? | '{' path_item [ ',' path_item ] * '}' ; -path_item : ident | "mod" ; +path_item : ident | "self" ; ``` ### Functions @@ -424,7 +424,7 @@ See [Use declarations](#use-declarations). ## Attributes ```antlr -attribute : "#!" ? '[' meta_item ']' ; +attribute : '#' '!' ? '[' meta_item ']' ; meta_item : ident [ '=' literal | '(' meta_seq ')' ] ? ; meta_seq : meta_item [ ',' meta_seq ] ? ; @@ -515,8 +515,7 @@ struct_expr : expr_path '{' ident ':' expr ### Block expressions ```antlr -block_expr : '{' [ view_item ] * - [ stmt ';' | item ] * +block_expr : '{' [ stmt ';' | item ] * [ expr ] '}' ; ``` @@ -537,7 +536,7 @@ field_expr : expr '.' ident ; ```antlr array_expr : '[' "mut" ? array_elems? ']' ; -array_elems : [expr [',' expr]*] | [expr ',' ".." expr] ; +array_elems : [expr [',' expr]*] | [expr ';' expr] ; ``` ### Index expressions From bff170786cd99bfca7669430fdcc0889a01d2906 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Czardybon?= Date: Fri, 8 May 2015 22:15:14 +0200 Subject: [PATCH 72/97] Fixed one textual mistake and one casing error. Corrected "Ownership": - [`Variable bindings`] link was not processed properly. - Changed the paragraph about move semantics with two vectors, because it was confusing. - Removed "So it may not be as inefficient as it initially seems", because there is nothing that seems inefficient in copying pointers only. - Other text corrections. Fixed copied-and-pasted text mistakes. Revised the paragraph about moving a vector (taking into account suggestions by echochamber). Fixed markdown. Fixes requested by steveklabnik. Brought back a sentence about supposed inefficiency. --- src/doc/trpl/lifetimes.md | 2 +- src/doc/trpl/ownership.md | 28 ++++++++++++------------ src/doc/trpl/references-and-borrowing.md | 4 ++-- src/doc/trpl/while-loops.md | 2 +- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/doc/trpl/lifetimes.md b/src/doc/trpl/lifetimes.md index 86164a08a430..25d5122b4e49 100644 --- a/src/doc/trpl/lifetimes.md +++ b/src/doc/trpl/lifetimes.md @@ -5,7 +5,7 @@ Rust’s most unique and compelling features, with which Rust developers should become quite acquainted. Ownership is how Rust achieves its largest goal, memory safety. There are a few distinct concepts, each with its own chapter: -* [ownership][ownership], ownership, the key concept +* [ownership][ownership], the key concept * [borrowing][borrowing], and their associated feature ‘references’ * lifetimes, which you’re reading now diff --git a/src/doc/trpl/ownership.md b/src/doc/trpl/ownership.md index 971bb7cd700d..b210f1c643f4 100644 --- a/src/doc/trpl/ownership.md +++ b/src/doc/trpl/ownership.md @@ -6,7 +6,7 @@ become quite acquainted. Ownership is how Rust achieves its largest goal, memory safety. There are a few distinct concepts, each with its own chapter: -* ownership, which you’re reading now. +* ownership, which you’re reading now * [borrowing][borrowing], and their associated feature ‘references’ * [lifetimes][lifetimes], an advanced concept of borrowing @@ -23,7 +23,7 @@ Before we get to the details, two important notes about the ownership system. Rust has a focus on safety and speed. It accomplishes these goals through many ‘zero-cost abstractions’, which means that in Rust, abstractions cost as little as possible in order to make them work. The ownership system is a prime example -of a zero cost abstraction. All of the analysis we’ll talk about in this guide +of a zero-cost abstraction. All of the analysis we’ll talk about in this guide is _done at compile time_. You do not pay any run-time cost for any of these features. @@ -41,7 +41,7 @@ With that in mind, let’s learn about ownership. # Ownership -[`Variable bindings`][bindings] have a property in Rust: they ‘have ownership’ +[Variable bindings][bindings] have a property in Rust: they ‘have ownership’ of what they’re bound to. This means that when a binding goes out of scope, the resource that they’re bound to are freed. For example: @@ -106,8 +106,8 @@ take(v); println!("v[0] is: {}", v[0]); ``` -Same error: “use of moved value.” When we transfer ownership to something else, -we say that we’ve ‘moved’ the thing we refer to. You don’t need some sort of +Same error: ‘use of moved value’. When we transfer ownership to something else, +we say that we’ve ‘moved’ the thing we refer to. You don’t need any sort of special annotation here, it’s the default thing that Rust does. ## The details @@ -121,19 +121,19 @@ let v = vec![1, 2, 3]; let v2 = v; ``` -The first line creates some data for the vector on the [stack][sh], `v`. The -vector’s data, however, is stored on the [heap][sh], and so it contains a -pointer to that data. When we move `v` to `v2`, it creates a copy of that pointer, -for `v2`. Which would mean two pointers to the contents of the vector on the -heap. That would be a problem: it would violate Rust’s safety guarantees by -introducing a data race. Therefore, Rust forbids using `v` after we’ve done the -move. +The first line allocates memory for the vector object, `v`, and for the data it +contains. The vector object is stored on the [stack][sh] and contains a pointer +to the content (`[1, 2, 3]`) stored on the [heap][sh]. When we move `v` to `v2`, +it creates a copy of that pointer, for `v2`. Which means that there would be two +pointers to the content of the vector on the heap. It would violate Rust’s +safety guarantees by introducing a data race. Therefore, Rust forbids using `v` +after we’ve done the move. [sh]: the-stack-and-the-heap.html It’s also important to note that optimizations may remove the actual copy of -the bytes, depending on circumstances. So it may not be as inefficient as it -initially seems. +the bytes on the stack, depending on circumstances. So it may not be as +inefficient as it initially seems. ## `Copy` types diff --git a/src/doc/trpl/references-and-borrowing.md b/src/doc/trpl/references-and-borrowing.md index da416e994c4c..c434371ce59d 100644 --- a/src/doc/trpl/references-and-borrowing.md +++ b/src/doc/trpl/references-and-borrowing.md @@ -6,7 +6,7 @@ become quite acquainted. Ownership is how Rust achieves its largest goal, memory safety. There are a few distinct concepts, each with its own chapter: -* [ownership][ownership], ownership, the key concept +* [ownership][ownership], the key concept * borrowing, which you’re reading now * [lifetimes][lifetimes], an advanced concept of borrowing @@ -368,4 +368,4 @@ statement 1 at 3:14 println!("{}", y); } -``` \ No newline at end of file +``` diff --git a/src/doc/trpl/while-loops.md b/src/doc/trpl/while-loops.md index f2e2f6b6f49a..e71d2033f49e 100644 --- a/src/doc/trpl/while-loops.md +++ b/src/doc/trpl/while-loops.md @@ -1,4 +1,4 @@ -% while loops +% while Loops Rust also has a `while` loop. It looks like this: From ef030555c67988878e1a68743da25b5107bd2787 Mon Sep 17 00:00:00 2001 From: Ricardo Martins Date: Mon, 11 May 2015 09:10:19 +0100 Subject: [PATCH 73/97] Improve wording in error explanation. --- src/librustc_resolve/diagnostics.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 5f0b5af9a053..2ac6ffdea2d6 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -19,7 +19,7 @@ E0154: r##" Imports (`use` statements) are not allowed after non-item statements, such as variable declarations and expression statements. -Wrong example: +Here is an example that demonstrates the error: ``` fn f() { // Variable declaration before import @@ -104,7 +104,7 @@ http://doc.rust-lang.org/reference.html#statements E0317: r##" User-defined types or type parameters cannot shadow the primitive types. This error indicates you tried to define a type, struct or enum with the same -name as an existing primitive type, and is therefore invalid. +name as an existing primitive type. See the Types section of the reference for more information about the primitive types: From aa529ef52e54039fcfaa8aa7914be4c581179497 Mon Sep 17 00:00:00 2001 From: Ricardo Martins Date: Mon, 11 May 2015 09:10:49 +0100 Subject: [PATCH 74/97] Add missing keyword in `extern crate` declarations. --- src/librustc_resolve/diagnostics.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 2ac6ffdea2d6..7e7af8006805 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -53,8 +53,8 @@ has been imported into the current module. Wrong example: ``` -extern a; -extern crate_a as a; +extern crate a; +extern crate crate_a as a; ``` The solution is to choose a different name that doesn't conflict with any @@ -62,8 +62,8 @@ external crate imported into the current module. Correct example: ``` -extern a; -extern crate_a as other_name; +extern crate a; +extern crate crate_a as other_name; ``` "##, @@ -72,7 +72,7 @@ The name for an item declaration conflicts with an external crate's name. For instance, ``` -extern abc; +extern crate abc; struct abc; ``` @@ -82,7 +82,7 @@ There are two possible solutions: Solution #1: Rename the item. ``` -extern abc; +extern crate abc; struct xyz; ``` @@ -90,7 +90,7 @@ struct xyz; Solution #2: Import the crate with a different name. ``` -extern abc as xyz; +extern crate abc as xyz; struct abc; ``` From 52efe55d0425d963ee949be96e36d584a603a455 Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Mon, 11 May 2015 00:55:21 -0700 Subject: [PATCH 75/97] Handle overflow properly in core::slice core::slice was originally written to tolerate overflow (notably, with slices of zero-sized elements), but it was never updated to use wrapping arithmetic when overflow traps were added. Also correctly handle the case of calling .nth() on an Iter with a zero-sized element type. The iterator was assuming that the pointer value of the returned reference was meaningful, but that's not true for zero-sized elements. Fixes #25016. --- src/libcore/slice.rs | 51 +++++-------------- .../run-pass/slice-of-zero-size-elements.rs | 34 +++++++++++++ 2 files changed, 46 insertions(+), 39 deletions(-) create mode 100644 src/test/run-pass/slice-of-zero-size-elements.rs diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 56dee3034870..f9aa83d241a7 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -140,7 +140,7 @@ impl SliceExt for [T] { assume(!p.is_null()); if mem::size_of::() == 0 { Iter {ptr: p, - end: (p as usize + self.len()) as *const T, + end: ((p as usize).wrapping_add(self.len())) as *const T, _marker: marker::PhantomData} } else { Iter {ptr: p, @@ -277,7 +277,7 @@ impl SliceExt for [T] { assume(!p.is_null()); if mem::size_of::() == 0 { IterMut {ptr: p, - end: (p as usize + self.len()) as *mut T, + end: ((p as usize).wrapping_add(self.len())) as *mut T, _marker: marker::PhantomData} } else { IterMut {ptr: p, @@ -632,35 +632,17 @@ fn size_from_ptr(_: *const T) -> usize { // Use macros to be generic over const/mut -// -// They require non-negative `$by` because otherwise the expression -// `(ptr as usize + $by)` would interpret `-1` as `usize::MAX` (and -// thus trigger a panic when overflow checks are on). - -// Use this to do `$ptr + $by`, where `$by` is non-negative. -macro_rules! slice_add_offset { +macro_rules! slice_offset { ($ptr:expr, $by:expr) => {{ let ptr = $ptr; if size_from_ptr(ptr) == 0 { - transmute(ptr as usize + $by) + transmute((ptr as isize).wrapping_add($by)) } else { ptr.offset($by) } }}; } -// Use this to do `$ptr - $by`, where `$by` is non-negative. -macro_rules! slice_sub_offset { - ($ptr:expr, $by:expr) => {{ - let ptr = $ptr; - if size_from_ptr(ptr) == 0 { - transmute(ptr as usize - $by) - } else { - ptr.offset(-$by) - } - }}; -} - macro_rules! slice_ref { ($ptr:expr) => {{ let ptr = $ptr; @@ -684,13 +666,11 @@ macro_rules! iterator { fn next(&mut self) -> Option<$elem> { // could be implemented with slices, but this avoids bounds checks unsafe { - ::intrinsics::assume(!self.ptr.is_null()); - ::intrinsics::assume(!self.end.is_null()); if self.ptr == self.end { None } else { let old = self.ptr; - self.ptr = slice_add_offset!(self.ptr, 1); + self.ptr = slice_offset!(self.ptr, 1); Some(slice_ref!(old)) } } @@ -698,7 +678,7 @@ macro_rules! iterator { #[inline] fn size_hint(&self) -> (usize, Option) { - let diff = (self.end as usize) - (self.ptr as usize); + let diff = (self.end as usize).wrapping_sub(self.ptr as usize); let size = mem::size_of::(); let exact = diff / (if size == 0 {1} else {size}); (exact, Some(exact)) @@ -727,12 +707,10 @@ macro_rules! iterator { fn next_back(&mut self) -> Option<$elem> { // could be implemented with slices, but this avoids bounds checks unsafe { - ::intrinsics::assume(!self.ptr.is_null()); - ::intrinsics::assume(!self.end.is_null()); if self.end == self.ptr { None } else { - self.end = slice_sub_offset!(self.end, 1); + self.end = slice_offset!(self.end, -1); Some(slice_ref!(self.end)) } } @@ -743,7 +721,7 @@ macro_rules! iterator { macro_rules! make_slice { ($t: ty => $result: ty: $start: expr, $end: expr) => {{ - let diff = $end as usize - $start as usize; + let diff = ($end as usize).wrapping_sub($start as usize); let len = if mem::size_of::() == 0 { diff } else { @@ -757,7 +735,7 @@ macro_rules! make_slice { macro_rules! make_mut_slice { ($t: ty => $result: ty: $start: expr, $end: expr) => {{ - let diff = $end as usize - $start as usize; + let diff = ($end as usize).wrapping_sub($start as usize); let len = if mem::size_of::() == 0 { diff } else { @@ -794,7 +772,7 @@ impl<'a, T> Iter<'a, T> { fn iter_nth(&mut self, n: usize) -> Option<&'a T> { match self.as_slice().get(n) { Some(elem_ref) => unsafe { - self.ptr = slice_add_offset!(elem_ref as *const _, 1); + self.ptr = slice_offset!(self.ptr, (n as isize).wrapping_add(1)); Some(slice_ref!(elem_ref)) }, None => { @@ -827,12 +805,7 @@ impl<'a, T> RandomAccessIterator for Iter<'a, T> { fn idx(&mut self, index: usize) -> Option<&'a T> { unsafe { if index < self.indexable() { - if mem::size_of::() == 0 { - // Use a non-null pointer value - Some(&mut *(1 as *mut _)) - } else { - Some(transmute(self.ptr.offset(index as isize))) - } + Some(slice_ref!(self.ptr.offset(index as isize))) } else { None } @@ -867,7 +840,7 @@ impl<'a, T> IterMut<'a, T> { fn iter_nth(&mut self, n: usize) -> Option<&'a mut T> { match make_mut_slice!(T => &'a mut [T]: self.ptr, self.end).get_mut(n) { Some(elem_ref) => unsafe { - self.ptr = slice_add_offset!(elem_ref as *mut _, 1); + self.ptr = slice_offset!(self.ptr, (n as isize).wrapping_add(1)); Some(slice_ref!(elem_ref)) }, None => { diff --git a/src/test/run-pass/slice-of-zero-size-elements.rs b/src/test/run-pass/slice-of-zero-size-elements.rs new file mode 100644 index 000000000000..98b668031a89 --- /dev/null +++ b/src/test/run-pass/slice-of-zero-size-elements.rs @@ -0,0 +1,34 @@ +// 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: -C debug-assertions + +use std::slice; + +pub fn main() { + // In a slice of zero-size elements the pointer is meaningless. + // Ensure iteration still works even if the pointer is at the end of the address space. + let slice: &[()] = unsafe { slice::from_raw_parts(-5isize as *const (), 10) }; + assert_eq!(slice.len(), 10); + assert_eq!(slice.iter().count(), 10); + + // .nth() on the iterator should also behave correctly + let mut it = slice.iter(); + assert!(it.nth(5).is_some()); + assert_eq!(it.count(), 4); + + let slice: &mut [()] = unsafe { slice::from_raw_parts_mut(-5isize as *mut (), 10) }; + assert_eq!(slice.len(), 10); + assert_eq!(slice.iter_mut().count(), 10); + + let mut it = slice.iter_mut(); + assert!(it.nth(5).is_some()); + assert_eq!(it.count(), 4); +} From 5b0e19794efe6d2d7f225df57505205627103f32 Mon Sep 17 00:00:00 2001 From: Johannes Oertel Date: Mon, 11 May 2015 12:54:59 +0200 Subject: [PATCH 76/97] Minor optimization for `VecMap::split_off` We don't need to copy any elements if `at` is behind the last element in the map. The last element is at index `self.v.len() - 1`, so we should not copy if `at` is greater or equals `self.v.len()`. --- src/libcollections/vec_map.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs index 6ff819fc87cd..aa0ab41b7455 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -367,7 +367,7 @@ impl VecMap { // Move all elements to other swap(self, &mut other); return other - } else if at > self.v.len() { + } else if at >= self.v.len() { // No elements to copy return other; } From ce7ef32982541727cdbeda1960364cb09e7ca63c Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Mon, 11 May 2015 23:04:31 +1000 Subject: [PATCH 77/97] Markdown formatting for error explanations. --- src/librustc/diagnostics.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index aaf615ee4040..0f1e55544e1a 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -745,6 +745,7 @@ variable. For example: +``` let x: i32 = "I am not a number!"; // ~~~ ~~~~~~~~~~~~~~~~~~~~ // | | @@ -752,6 +753,7 @@ let x: i32 = "I am not a number!"; // | compiler infers type `&str` // | // type `i32` assigned to variable `x` +``` "##, E0309: r##" @@ -760,6 +762,7 @@ how long the data stored within them is guaranteed to be live. This lifetime must be as long as the data needs to be alive, and missing the constraint that denotes this will cause this error. +``` // This won't compile because T is not constrained, meaning the data // stored in it is not guaranteed to last as long as the reference struct Foo<'a, T> { @@ -770,6 +773,7 @@ struct Foo<'a, T> { struct Foo<'a, T: 'a> { foo: &'a T } +``` "##, E0310: r##" @@ -778,6 +782,7 @@ how long the data stored within them is guaranteed to be live. This lifetime must be as long as the data needs to be alive, and missing the constraint that denotes this will cause this error. +``` // This won't compile because T is not constrained to the static lifetime // the reference needs struct Foo { @@ -788,6 +793,7 @@ struct Foo { struct Foo { foo: &'static T } +``` "## } From 7dd7bea3ac8ebaa6059e885c24d1388d2c7d03ac Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 11 May 2015 16:46:24 +0200 Subject: [PATCH 78/97] trpl: item macros must be followed by a semicolon --- src/doc/trpl/compiler-plugins.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/trpl/compiler-plugins.md b/src/doc/trpl/compiler-plugins.md index 9eb22a7f6985..127e097c34f7 100644 --- a/src/doc/trpl/compiler-plugins.md +++ b/src/doc/trpl/compiler-plugins.md @@ -176,7 +176,7 @@ for a full example, the core of which is reproduced here: ```ignore declare_lint!(TEST_LINT, Warn, - "Warn about items named 'lintme'") + "Warn about items named 'lintme'"); struct Pass; From dd7d0f5e9cd3e76f9781bf1a2f0a45b02aabe9d6 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Sun, 10 May 2015 18:11:51 -0400 Subject: [PATCH 79/97] Fix links in the referece and remove references to the unit type, which no longer exists Fixes #24999 --- src/doc/reference.md | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 66a7f543ad95..10469bae8aa1 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -31,23 +31,27 @@ You may also be interested in the [grammar]. ## Unicode productions -A few productions in Rust's grammar permit Unicode code points outside the ASCII -range. We define these productions in terms of character properties specified -in the Unicode standard, rather than in terms of ASCII-range code points. The -section [Special Unicode Productions](#special-unicode-productions) lists these -productions. +A few productions in Rust's grammar permit Unicode code points outside the +ASCII range. We define these productions in terms of character properties +specified in the Unicode standard, rather than in terms of ASCII-range code +points. The grammar has a [Special Unicode Productions][unicodeproductions] +section that lists these productions. + +[unicodeproductions]: grammar.html#special-unicode-productions ## String table productions Some rules in the grammar — notably [unary operators](#unary-operator-expressions), [binary -operators](#binary-operator-expressions), and [keywords](#keywords) — are +operators](#binary-operator-expressions), and [keywords][keywords] — are given in a simplified form: as a listing of a table of unquoted, printable whitespace-separated strings. These cases form a subset of the rules regarding the [token](#tokens) rule, and are assumed to be the result of a lexical-analysis phase feeding the parser, driven by a DFA, operating over the disjunction of all such string table entries. +[keywords]: grammar.html#keywords + When such a string enclosed in double-quotes (`"`) occurs inside the grammar, it is an implicit reference to a single member of such a string table production. See [tokens](#tokens) for more information. @@ -75,7 +79,7 @@ An identifier is any nonempty Unicode[^non_ascii_idents] string of the following - The first character has property `XID_start` - The remaining characters have property `XID_continue` -that does _not_ occur in the set of [keywords](#keywords). +that does _not_ occur in the set of [keywords][keywords]. > **Note**: `XID_start` and `XID_continue` as character properties cover the > character ranges used to form the more familiar C and Java language-family @@ -401,7 +405,7 @@ Symbols are a general class of printable [token](#tokens) that play structural roles in a variety of grammar productions. They are catalogued here for completeness as the set of remaining miscellaneous printable tokens that do not otherwise appear as [unary operators](#unary-operator-expressions), [binary -operators](#binary-operator-expressions), or [keywords](#keywords). +operators](#binary-operator-expressions), or [keywords][keywords]. ## Paths @@ -611,7 +615,7 @@ module needs its own source file: [module definitions](#modules) can be nested within one file. Each source file contains a sequence of zero or more `item` definitions, and -may optionally begin with any number of [attributes](#Items and attributes) +may optionally begin with any number of [attributes](#items-and-attributes) that apply to the containing module, most of which influence the behavior of the compiler. The anonymous crate module can have additional attributes that apply to the crate as a whole. @@ -653,7 +657,7 @@ There are several kinds of item: * [`use` declarations](#use-declarations) * [modules](#modules) * [functions](#functions) -* [type aliases](#type-aliases) +* [type definitions](grammar.html#type-definitions) * [structures](#structures) * [enumerations](#enumerations) * [constant items](#constant-items) @@ -773,7 +777,7 @@ extern crate std as ruststd; // linking to 'std' under another name A _use declaration_ creates one or more local name bindings synonymous with some other [path](#paths). Usually a `use` declaration is used to shorten the path required to refer to a module item. These declarations may appear at the -top of [modules](#modules) and [blocks](#blocks). +top of [modules](#modules) and [blocks](grammar.html#block-expressions). > **Note**: Unlike in many languages, > `use` declarations in Rust do *not* declare linkage dependency with external crates. @@ -1144,9 +1148,7 @@ let px: i32 = match p { Point(x, _) => x }; ``` A _unit-like struct_ is a structure without any fields, defined by leaving off -the list of fields entirely. Such types will have a single value, just like -the [unit value `()`](#unit-and-boolean-literals) of the unit type. For -example: +the list of fields entirely. Such types will have a single value. For example: ``` struct Cookie; @@ -2436,11 +2438,6 @@ comma: (0); // zero in parentheses ``` -### Unit expressions - -The expression `()` denotes the _unit value_, the only value of the type with -the same name. - ### Structure expressions There are several forms of structure expressions. A _structure expression_ @@ -3281,7 +3278,7 @@ constructor or `struct` field may refer, directly or indirectly, to the enclosing `enum` or `struct` type itself. Such recursion has restrictions: * Recursive types must include a nominal type in the recursion - (not mere [type definitions](#type-definitions), + (not mere [type definitions](grammar.html#type-definitions), or other structural types such as [arrays](#array,-and-slice-types) or [tuples](#tuple-types)). * A recursive `enum` item must have at least one non-recursive constructor (in order to give the recursion a basis case). From 94caeb326c45bd0a108abe92ae50f9deda0aeb4c Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 11 May 2015 10:59:23 -0700 Subject: [PATCH 80/97] More authors updates --- AUTHORS.txt | 6 +++++- RELEASES.md | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/AUTHORS.txt b/AUTHORS.txt index 16346db4e1d9..e342a3de55a9 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -338,6 +338,7 @@ Hajime Morrita Hanno Braun Harry Marr Heather +Heejong Ahn Herman J. Radtke III HeroesGrave @@ -506,6 +507,7 @@ Kevin Walter Kevin Yap Kiet Tran Kim Røen +KokaKiwi Kostas Karachalios Kyeongwoon Lee Lai Jiangshan @@ -625,7 +627,7 @@ Nathan Stoddard Nathan Typanski Nathan Wilson Nathan Zadoks -Nathaniel Herman +Nathaniel Herman Nathaniel Theis Neil Pankey Nelson Chen @@ -658,6 +660,7 @@ Or Neeman Oren Hazi Orpheus Lummis Orphée Lafond-Lummis +Ožbolt Menegatti P1start Pablo Brasero Palmer Cox @@ -701,6 +704,7 @@ Piotr Zolnierek Poga Po Potpourri Prudhvi Krishna Surapaneni +Przemek Wesołek Pyfisch Pyry Kontio Q.P.Liu diff --git a/RELEASES.md b/RELEASES.md index 7c8a6d0e0cdb..3219449edd8a 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,6 +1,8 @@ Version 1.0.0 (May 2015) ======================== +* ~1500 changes, numerous bugfixes + Highlights ---------- From e1e34e9275918679336210874f8dd770323daa81 Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Mon, 11 May 2015 09:34:59 -0700 Subject: [PATCH 81/97] Reintroduce non-null assumptions in core::slice iterators The previous assumptions were not valid for slices of zero-sized elements. --- src/libcore/slice.rs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index f9aa83d241a7..3abba3145582 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -665,10 +665,14 @@ macro_rules! iterator { #[inline] fn next(&mut self) -> Option<$elem> { // could be implemented with slices, but this avoids bounds checks - unsafe { - if self.ptr == self.end { - None - } else { + if self.ptr == self.end { + None + } else { + unsafe { + if mem::size_of::() != 0 { + ::intrinsics::assume(!self.ptr.is_null()); + ::intrinsics::assume(!self.end.is_null()); + } let old = self.ptr; self.ptr = slice_offset!(self.ptr, 1); Some(slice_ref!(old)) @@ -706,11 +710,15 @@ macro_rules! iterator { #[inline] fn next_back(&mut self) -> Option<$elem> { // could be implemented with slices, but this avoids bounds checks - unsafe { - if self.end == self.ptr { - None - } else { + if self.end == self.ptr { + None + } else { + unsafe { self.end = slice_offset!(self.end, -1); + if mem::size_of::() != 0 { + ::intrinsics::assume(!self.ptr.is_null()); + ::intrinsics::assume(!self.end.is_null()); + } Some(slice_ref!(self.end)) } } From f2614f5858fed10e180102def32c60f180e46496 Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Mon, 11 May 2015 12:37:31 -0700 Subject: [PATCH 82/97] Avoid returning a slice with a null pointer from Iter.as_slice() core::slice::Iter.ptr can be null when iterating a slice of zero-sized elements, but the pointer value used for the slice itself cannot. Handle this case by always returning a dummy pointer for slices of zero-sized elements. --- src/libcore/slice.rs | 38 +++++++++---------- .../run-pass/slice-of-zero-size-elements.rs | 32 ++++++++++++++-- 2 files changed, 48 insertions(+), 22 deletions(-) diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 3abba3145582..9db1ceddf0d7 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -728,29 +728,29 @@ macro_rules! iterator { } macro_rules! make_slice { - ($t: ty => $result: ty: $start: expr, $end: expr) => {{ - let diff = ($end as usize).wrapping_sub($start as usize); - let len = if mem::size_of::() == 0 { - diff + ($start: expr, $end: expr) => {{ + let start = $start; + let diff = ($end as usize).wrapping_sub(start as usize); + if size_from_ptr(start) == 0 { + // use a non-null pointer value + unsafe { from_raw_parts(1 as *const _, diff) } } else { - diff / mem::size_of::<$t>() - }; - unsafe { - from_raw_parts($start, len) + let len = diff / size_from_ptr(start); + unsafe { from_raw_parts(start, len) } } }} } macro_rules! make_mut_slice { - ($t: ty => $result: ty: $start: expr, $end: expr) => {{ - let diff = ($end as usize).wrapping_sub($start as usize); - let len = if mem::size_of::() == 0 { - diff + ($start: expr, $end: expr) => {{ + let start = $start; + let diff = ($end as usize).wrapping_sub(start as usize); + if size_from_ptr(start) == 0 { + // use a non-null pointer value + unsafe { from_raw_parts_mut(1 as *mut _, diff) } } else { - diff / mem::size_of::<$t>() - }; - unsafe { - from_raw_parts_mut($start, len) + let len = diff / size_from_ptr(start); + unsafe { from_raw_parts_mut(start, len) } } }} } @@ -773,7 +773,7 @@ impl<'a, T> Iter<'a, T> { /// iterator can continue to be used while this exists. #[unstable(feature = "core")] pub fn as_slice(&self) -> &'a [T] { - make_slice!(T => &'a [T]: self.ptr, self.end) + make_slice!(self.ptr, self.end) } // Helper function for Iter::nth @@ -841,12 +841,12 @@ impl<'a, T> IterMut<'a, T> { /// restricted lifetimes that do not consume the iterator. #[unstable(feature = "core")] pub fn into_slice(self) -> &'a mut [T] { - make_mut_slice!(T => &'a mut [T]: self.ptr, self.end) + make_mut_slice!(self.ptr, self.end) } // Helper function for IterMut::nth fn iter_nth(&mut self, n: usize) -> Option<&'a mut T> { - match make_mut_slice!(T => &'a mut [T]: self.ptr, self.end).get_mut(n) { + match make_mut_slice!(self.ptr, self.end).get_mut(n) { Some(elem_ref) => unsafe { self.ptr = slice_offset!(self.ptr, (n as isize).wrapping_add(1)); Some(slice_ref!(elem_ref)) diff --git a/src/test/run-pass/slice-of-zero-size-elements.rs b/src/test/run-pass/slice-of-zero-size-elements.rs index 98b668031a89..6fe510586c74 100644 --- a/src/test/run-pass/slice-of-zero-size-elements.rs +++ b/src/test/run-pass/slice-of-zero-size-elements.rs @@ -10,8 +10,26 @@ // compile-flags: -C debug-assertions +#![feature(core)] + use std::slice; +fn foo(v: &[T]) -> Option<&[T]> { + let mut it = v.iter(); + for _ in 0..5 { + let _ = it.next(); + } + Some(it.as_slice()) +} + +fn foo_mut(v: &mut [T]) -> Option<&mut [T]> { + let mut it = v.iter_mut(); + for _ in 0..5 { + let _ = it.next(); + } + Some(it.into_slice()) +} + pub fn main() { // In a slice of zero-size elements the pointer is meaningless. // Ensure iteration still works even if the pointer is at the end of the address space. @@ -24,11 +42,19 @@ pub fn main() { assert!(it.nth(5).is_some()); assert_eq!(it.count(), 4); + // Converting Iter to a slice should never have a null pointer + assert!(foo(slice).is_some()); + + // Test mutable iterators as well let slice: &mut [()] = unsafe { slice::from_raw_parts_mut(-5isize as *mut (), 10) }; assert_eq!(slice.len(), 10); assert_eq!(slice.iter_mut().count(), 10); - let mut it = slice.iter_mut(); - assert!(it.nth(5).is_some()); - assert_eq!(it.count(), 4); + { + let mut it = slice.iter_mut(); + assert!(it.nth(5).is_some()); + assert_eq!(it.count(), 4); + } + + assert!(foo_mut(slice).is_some()) } From e66653bee52b87ada8d591b13b915e5ed2c86d5a Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Sun, 10 May 2015 20:22:06 -0400 Subject: [PATCH 83/97] TRPL: the stack and the heap --- src/doc/trpl/the-stack-and-the-heap.md | 569 ++++++++++++++++++++++++- 1 file changed, 568 insertions(+), 1 deletion(-) diff --git a/src/doc/trpl/the-stack-and-the-heap.md b/src/doc/trpl/the-stack-and-the-heap.md index cc0941bc025a..7b1cd7dc8093 100644 --- a/src/doc/trpl/the-stack-and-the-heap.md +++ b/src/doc/trpl/the-stack-and-the-heap.md @@ -1,3 +1,570 @@ % The Stack and the Heap -Coming Soon +As a systems language, Rust operates at a low level. If you’re coming from a +high-level language, there are some aspects of systems programming that you may +not be familiar with. The most important one is how memory works, with a stack +and a heap. If you’re familiar with how C-like languages use stack allocation, +this chapter will be a refresher. If you’re not, you’ll learn about this more +general concept, but with a Rust-y focus. + +# Memory management + +These two terms are about memory management. The stack and the heap are +abstractions that help you determine when to allocate and deallocate memory. + +Here’s a high-level comparison: + +The stack is very fast, and is where memory is allocated in Rust by default. +But the allocation is local to a function call, and is limited in size. The +heap, on the other hand, is slower, and is explicitly allocated by your +program. But it’s effectively unlimited in size, and is globally accessible. + +# The Stack + +Let’s talk about this Rust program: + +```rust +fn main() { + let x = 42; +} +``` + +This program has one variable binding, `x`. This memory needs to be allocated +from somewhere. Rust ‘stack allocates’ by default, which means that basic +values ‘go on the stack’. What does that mean? + +Well, when a function gets called, some memory gets allocated for all of its +local variables and some other information. This is called a ‘stack frame’, and +for the purpose of this tutorial, we’re going to ignore the extra information +and just consider the local variables we’re allocating. So in this case, when +`main()` is run, we’ll allocate a single 32-bit integer for our stack frame. +This is automatically handled for you, as you can see, we didn’t have to write +any special Rust code or anything. + +When the function is over, its stack frame gets deallocated. This happens +automatically, we didn’t have to do anything special here. + +That’s all there is for this simple program. The key thing to understand here +is that stack allocation is very, very fast. Since we know all the local +variables we have ahead of time, we can grab the memory all at once. And since +we’ll throw them all away at the same time as well, we can get rid of it very +fast too. + +The downside is that we can’t keep values around if we need them for longer +than a single function. We also haven’t talked about what that name, ‘stack’ +means. To do that, we need a slightly more complicated example: + +```rust +fn foo() { + let y = 5; + let z = 100; +} + +fn main() { + let x = 42; + + foo(); +} +``` + +This program has three variables total: two in `foo()`, one in `main()`. Just +as before, when `main()` is called, a single integer is allocated for its stack +frame. But before we can show what happens when `foo()` is called, we need to +visualize what’s going on with memory. Your operating system presents a view of +memory to your program that’s pretty simple: a huge list of addresses, from 0 +to a large number, representing how much RAM your computer has. For example, if +you have a gigabyte of RAM, your addresses go from `0` to `1,073,741,824`. That +number comes from 230, the number of bytes in a gigabyte. + +This memory is kind of like a giant array: addresses start at zero and go +up to the final number. So here’s a diagram of our first stack frame: + +| Address | Name | Value | ++---------+------+-------+ +| 0 | x | 42 | + +We’ve got `x` located at address `0`, with the value `42`. + +When `foo()` is called, a new stack frame is allocated: + +| Address | Name | Value | ++---------+------+-------+ +| 2 | z | 100 | +| 1 | y | 5 | +| 0 | x | 42 | + +Because `0` was taken by the first frame, `1` and `2` are used for `foo()`’s +stack frame. It grows upward, the more functions we call. + + +There’s some important things we have to take note of here. The numbers 0, 1, +and 2 are all solely for illustrative purposes, and bear no relationship to the +actual numbers the computer will actually use. In particular, the series of +addresses are in reality going to be separated by some number of bytes that +separate each address, and that separation may even exceed the size of the +value being stored. + +After `foo()` is over, its frame is deallocated: + +| Address | Name | Value | ++---------+------+-------+ +| 0 | x | 42 | + +And then, after `main()`, even this last value goes away. Easy! + +It’s called a ‘stack’ because it works like a stack of dinner plates: the first +plate you put down is the last plate to pick back up. Stacks are sometimes +called ‘last in, first out queues’ for this reason, as the last value you put +on the stack is the first one you retrieve from it. + +Let’s try a three-deep example: + +```rust +fn bar() { + let i = 6; +} + +fn foo() { + let a = 5; + let b = 100; + let c = 1; + + bar(); +} + +fn main() { + let x = 42; + + foo(); +} +``` + +Okay, first, we call `main()`: + +| Address | Name | Value | ++---------+------+-------+ +| 0 | x | 42 | + +Next up, `main()` calls `foo()`: + +| Address | Name | Value | ++---------+------+-------+ +| 3 | c | 1 | +| 2 | b | 100 | +| 1 | a | 5 | +| 0 | x | 42 | + +And then `foo()` calls `bar()`: + +| Address | Name | Value | ++---------+------+-------+ +| 4 | i | 6 | +| 3 | c | 1 | +| 2 | b | 100 | +| 1 | a | 5 | +| 0 | x | 42 | + +Whew! Our stack is growing tall. + +After `bar()` is over, its frame is deallocated, leaving just `foo()` and +`main()`: + +| Address | Name | Value | ++---------+------+-------+ +| 3 | c | 1 | +| 2 | b | 100 | +| 1 | a | 5 | +| 0 | x | 42 | + +And then `foo()` ends, leaving just `main()` + +| Address | Name | Value | ++---------+------+-------+ +| 0 | x | 42 | + +And then we’re done. Getting the hang of it? It’s like piling up dishes: you +add to the top, you take away from the top. + +# The Heap + +Now, this works pretty well, but not everything can work like this. Sometimes, +you need to pass some memory between different functions, or keep it alive for +longer than a single function’s execution. For this, we can use the heap. + +In Rust, you can allocate memory on the heap with the [`Box` type][box]. +Here’s an example: + +```rust +fn main() { + let x = Box::new(5); + let y = 42; +} +``` + +[box]: ../std/boxed/index.html + +Here’s what happens in memory when `main()` is called: + +| Address | Name | Value | ++---------+------+--------+ +| 1 | y | 42 | +| 0 | x | ?????? | + +We allocate space for two variables on the stack. `y` is `42`, as it always has +been, but what about `x`? Well, `x` is a `Box`, and boxes allocate memory +on the heap. The actual value of the box is a structure which has a pointer to +‘the heap’. When we start executing the function, and `Box::new()` is called, +it allocates some memory for the heap, and puts `5` there. The memory now looks +like this: + +| Address | Name | Value | ++-----------------+------+----------------+ +| 230 | | 5 | +| ... | ... | ... | +| 1 | y | 42 | +| 0 | x | 230 | + +We have 230 in our hypothetical computer with 1GB of RAM. And since +our stack grows from zero, the easiest place to allocate memory is from the +other end. So our first value is at the highest place in memory. And the value +of the struct at `x` has a [raw pointer][rawpointer] to the place we’ve +allocated on the heap, so the value of `x` is 230, the memory +location we’ve asked for. + +[rawpointer]: raw-pointers.html + +We haven’t really talked too much about what it actually means to allocate and +deallocate memory in these contexts. Getting into very deep detail is out of +the scope of this tutorial, but what’s important to point out here is that +the heap isn’t just a stack that grows from the opposite end. We’ll have an +example of this later in the book, but because the heap can be allocated and +freed in any order, it can end up with ‘holes’. Here’s a diagram of the memory +layout of a program which has been running for a while now: + + +| Address | Name | Value | ++----------------------+------+----------------------+ +| 230 | | 5 | +| (230) - 1 | | | +| (230) - 2 | | | +| (230) - 3 | | 42 | +| ... | ... | ... | +| 3 | y | (230) - 3 | +| 2 | y | 42 | +| 1 | y | 42 | +| 0 | x | 230 | + +In this case, we’ve allocated four things on the heap, but deallocated two of +them. There’s a gap between 230 and (230) - 3 which isn’t +currently being used. The specific details of how and why this happens depends +on what kind of strategy you use to manage the heap. Different programs can use +different ‘memory allocators’, which are libraries that manage this for you. +Rust programs use [jemalloc][jemalloc] for this purpose. + +[jemalloc]: http://www.canonware.com/jemalloc/ + +Anyway, back to our example. Since this memory is on the heap, it can stay +alive longer than the function which allocates the box. In this case, however, +it doesn’t.[^moving] When the function is over, we need to free the stack frame +for `main()`. `Box`, though, has a trick up its sleve: [Drop][drop]. The +implementation of `Drop` for `Box` deallocates the memory that was allocated +when it was created. Great! So when `x` goes away, it first frees the memory +allocated on the heap: + +| Address | Name | Value | ++---------+------+--------+ +| 1 | y | 42 | +| 0 | x | ?????? | + +[drop]: drop.html +[moving]: We can make the memory live longer by transferring ownership, + sometimes called ‘moving out of the box’. More complex examples will + be covered later. + + +And then the stack frame goes away, freeing all of our memory. + +# Arguments and borrowing + +We’ve got some basic examples with the stack and the heap going, but what about +function arguments and borrowing? Here’s a small Rust program: + +```rust +fn foo(i: &i32) { + let z = 42; +} + +fn main() { + let x = 5; + let y = &x; + + foo(y); +} +``` + +When we enter `main()`, memory looks like this: + +| Address | Name | Value | ++---------+------+-------+ +| 1 | y | 0 | +| 0 | x | 5 | + +`x` is a plain old `5`, and `y` is a reference to `x`. So its value is the +memory location that `x` lives at, which in this case is `0`. + +What about when we call `foo()`, passing `y` as an argument? + +| Address | Name | Value | ++---------+------+-------+ +| 3 | z | 42 | +| 2 | i | 0 | +| 1 | y | 0 | +| 0 | x | 5 | + +Stack frames aren’t just for local bindings, they’re for arguments too. So in +this case, we need to have both `i`, our argument, and `z`, our local variable +binding. `i` is a copy of the argument, `y`. Since `y`’s value is `0`, so is +`i`’s. + +This is one reason why borrowing a variable doesn’t deallocate any memory: the +value of a reference is just a pointer to a memory location. If we got rid of +the underlying memory, things wouldn’t work very well. + +# A complex example + +Okay, let’s go through this complex program step-by-step: + +```rust +fn foo(x: &i32) { + let y = 10; + let z = &y; + + baz(z); + bar(x, z); +} + +fn bar(a: &i32, b: &i32) { + let c = 5; + let d = Box::new(5); + let e = &d; + + baz(e); +} + +fn baz(f: &i32) { + let g = 100; +} + +fn main() { + let h = 3; + let i = Box::new(20); + let j = &h; + + foo(j); +} +``` + +First, we call `main()`: + +| Address | Name | Value | ++-----------------+------+----------------+ +| 230 | | 20 | +| ... | ... | ... | +| 2 | j | 0 | +| 1 | i | 230 | +| 0 | h | 3 | + +We allocate memory for `j`, `i`, and `h`. `i` is on the heap, and so has a +value pointing there. + +Next, at the end of `main()`, `foo()` gets called: + +| Address | Name | Value | ++-----------------+------+----------------+ +| 230 | | 20 | +| ... | ... | ... | +| 5 | z | 4 | +| 4 | y | 10 | +| 3 | x | 0 | +| 2 | j | 0 | +| 1 | i | 230 | +| 0 | h | 3 | + +Space gets allocated for `x`, `y`, and `z`. The argument `x` has the same value +as `j`, since that’s what we passed it in. It’s a pointer to the `0` address, +since `j` points at `h`. + +Next, `foo()` calls `baz()`, passing `z`: + +| Address | Name | Value | ++-----------------+------+----------------+ +| 230 | | 20 | +| ... | ... | ... | +| 7 | g | 100 | +| 6 | f | 4 | +| 5 | z | 4 | +| 4 | y | 10 | +| 3 | x | 0 | +| 2 | j | 0 | +| 1 | i | 230 | +| 0 | h | 3 | + +We’ve allocated memory for `f` and `g`. `baz()` is very short, so when it’s +over, we get rid of its stack frame: + +| Address | Name | Value | ++-----------------+------+----------------+ +| 230 | | 20 | +| ... | ... | ... | +| 5 | z | 4 | +| 4 | y | 10 | +| 3 | x | 0 | +| 2 | j | 0 | +| 1 | i | 230 | +| 0 | h | 3 | + +Next, `foo()` calls `bar()` with `x` and `z`: + +| Address | Name | Value | ++----------------------+------+----------------------+ +| 230 | | 20 | +| (230) - 1 | | 5 | +| ... | ... | ... | +| 10 | e | 4 | +| 9 | d | (230) - 1 | +| 8 | c | 5 | +| 7 | b | 4 | +| 6 | a | 0 | +| 5 | z | 4 | +| 4 | y | 10 | +| 3 | x | 0 | +| 2 | j | 0 | +| 1 | i | 230 | +| 0 | h | 3 | + +We end up allocating another value on the heap, and so we have to subtract one +from 230. It’s easier to just write that than `1,073,741,823`. In any +case, we set up the variables as usual. + +At the end of `bar()`, it calls `baz()`: + +| Address | Name | Value | ++----------------------+------+----------------------+ +| 230 | | 20 | +| (230) - 1 | | 5 | +| ... | ... | ... | +| 12 | g | 100 | +| 11 | f | 4 | +| 10 | e | 4 | +| 9 | d | (230) - 1 | +| 8 | c | 5 | +| 7 | b | 4 | +| 6 | a | 0 | +| 5 | z | 4 | +| 4 | y | 10 | +| 3 | x | 0 | +| 2 | j | 0 | +| 1 | i | 230 | +| 0 | h | 3 | + +With this, we’re at our deepest point! Whew! Congrats for following along this +far. + +After `baz()` is over, we get rid of `f` and `g`: + +| Address | Name | Value | ++----------------------+------+----------------------+ +| 230 | | 20 | +| (230) - 1 | | 5 | +| ... | ... | ... | +| 10 | e | 4 | +| 9 | d | (230) - 1 | +| 8 | c | 5 | +| 7 | b | 4 | +| 6 | a | 0 | +| 5 | z | 4 | +| 4 | y | 10 | +| 3 | x | 0 | +| 2 | j | 0 | +| 1 | i | 230 | +| 0 | h | 3 | + +Next, we return from `bar()`. `d` in this case is a `Box`, so it also frees +what it points to: (230) - 1. + +| Address | Name | Value | ++-----------------+------+----------------+ +| 230 | | 20 | +| ... | ... | ... | +| 5 | z | 4 | +| 4 | y | 10 | +| 3 | x | 0 | +| 2 | j | 0 | +| 1 | i | 230 | +| 0 | h | 3 | + +And after that, `foo()` returns: + +| Address | Name | Value | ++-----------------+------+----------------+ +| 230 | | 20 | +| ... | ... | ... | +| 2 | j | 0 | +| 1 | i | 230 | +| 0 | h | 3 | + +And then, finally, `main()`, which cleans the rest up. When `i` is `Drop`ped, +it will clean up the last of the heap too. + +# What do other languages do? + +Most languages with a garbage collector heap-allocate by default. This means +that every value is boxed. There are a number of reasons why this is done, but +they’re out of scope for this tutorial. There are some possible optimizations +that don’t make it true 100% of the time, too. Rather than relying on the stack +and `Drop` to clean up memory, the garbage collector deals with the heap +instead. + +# Which to use? + +So if the stack is faster and easier to manage, why do we need the heap? A big +reason is that Stack-allocation alone means you only have LIFO semantics for +reclaiming storage. Heap-allocation is strictly more general, allowing storage +to be taken from and returned to the pool in arbitrary order, but at a +complexity cost. + +Generally, you should prefer stack allocation, and so, Rust stack-allocates by +default. The LIFO model of the stack is simpler, at a fundamental level. This +has two big impacts: runtime efficiency and semantic impact. + +## Runtime Efficiency. + +Managing the memory for the stack is trivial: The machine just +increments or decrements a single value, the so-called “stack pointer”. +Managing memory for the heap is non-trivial: heap-allocated memory is freed at +arbitrary points, and each block of heap-allocated memory can be of arbitrary +size, the memory manager must generally work much harder to identify memory for +reuse. + +If you’d like to dive into this topic in greater detail, [this paper][wilson] +is a great introduction. + +[wilson]: http://www.cs.northwestern.edu/~pdinda/icsclass/doc/dsa.pdf + +## Semantic impact + +Stack-allocation impacts the Rust language itself, and thus the developer’s +mental model. The LIFO semantics is what drives how the Rust language handles +automatic memory management. Even the deallocation of a uniquely-owned +heap-allocated box can be driven by the stack-based LIFO semantics, as +discussed throughout this chapter. The flexibility (i.e. expressiveness) of non +LIFO-semantics means that in general the compiler cannot automatically infer at +compile-time where memory should be freed; it has to rely on dynamic protocols, +potentially from outside the language itself, to drive deallocation (reference +counting, as used by `Rc` and `Arc`, is one example of this). + +When taken to the extreme, the increased expressive power of heap allocation +comes at the cost of either significant runtime support (e.g. in the form of a +garbage collector) or significant programmer effort (in the form of explicit +memory management calls that require verification not provided by the Rust +compiler). From f6119f18d29cefab2e7e36daab033bf40f5c0fda Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 11 May 2015 15:05:57 -0700 Subject: [PATCH 84/97] Update rust-installer --- src/rust-installer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rust-installer b/src/rust-installer index ebc6b04c2959..e54d4823d26c 160000 --- a/src/rust-installer +++ b/src/rust-installer @@ -1 +1 @@ -Subproject commit ebc6b04c29591108d3f28e724b4b9b74cd1232e6 +Subproject commit e54d4823d26cdb3f98e5a1b17e1c257cd329aa61 From 42240dccb600548b222992583402eafb3f47f364 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Mon, 11 May 2015 18:22:49 -0400 Subject: [PATCH 85/97] static method -> associated function --- src/doc/trpl/method-syntax.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/trpl/method-syntax.md b/src/doc/trpl/method-syntax.md index c5dd25516f31..1527d9cf978d 100644 --- a/src/doc/trpl/method-syntax.md +++ b/src/doc/trpl/method-syntax.md @@ -127,12 +127,12 @@ fn grow(&self) -> Circle { We just say we’re returning a `Circle`. With this method, we can grow a new circle to any arbitrary size. -# Static methods +# Associated functions -You can also define static methods that do not take a `self` parameter. Here’s a -pattern that’s very common in Rust code: +You can also define associated functions that do not take a `self` parameter. +Here’s a pattern that’s very common in Rust code: -``` +```rust struct Circle { x: f64, y: f64, From d13f765be8d202450bf106057e19d6bd57f51f6c Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Tue, 12 May 2015 00:33:22 -0400 Subject: [PATCH 86/97] Make mention of `if` more generic `if` can be a statement or also an expression. --- src/doc/trpl/primitive-types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/trpl/primitive-types.md b/src/doc/trpl/primitive-types.md index bb2bf028700d..22483816769c 100644 --- a/src/doc/trpl/primitive-types.md +++ b/src/doc/trpl/primitive-types.md @@ -15,7 +15,7 @@ let x = true; let y: bool = false; ``` -A common use of booleans is in [`if` statements][if]. +A common use of booleans is in [`if` conditionals][if]. [if]: if.html From 8bcb3cb475f0e5223ac63274d229fcbd866f7fe6 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 12 May 2015 07:49:15 +0300 Subject: [PATCH 87/97] rustc::metadata: use u64 for DefId's instead of strings. --- src/librustc/metadata/decoder.rs | 96 +++++++++++++------------------- src/librustc/metadata/encoder.rs | 60 ++++++++++---------- 2 files changed, 71 insertions(+), 85 deletions(-) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 00fc42341c38..f7fb5d495a45 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -21,7 +21,8 @@ use metadata::common::*; use metadata::csearch::MethodInfo; use metadata::csearch; use metadata::cstore; -use metadata::tydecode::{parse_ty_data, parse_region_data, parse_def_id, +use metadata::encoder::def_to_u64; +use metadata::tydecode::{parse_ty_data, parse_region_data, parse_type_param_def_data, parse_bare_fn_ty_data, parse_trait_ref_data, parse_predicate_data}; use middle::def; @@ -190,29 +191,32 @@ fn item_symbol(item: rbml::Doc) -> String { reader::get_doc(item, tag_items_data_item_symbol).as_str().to_string() } -fn item_parent_item(d: rbml::Doc) -> Option { +fn translated_def_id(cdata: Cmd, d: rbml::Doc) -> ast::DefId { + let id = reader::doc_as_u64(d); + let def_id = ast::DefId { krate: (id >> 32) as u32, node: id as u32 }; + translate_def_id(cdata, def_id) +} + +fn item_parent_item(cdata: Cmd, d: rbml::Doc) -> Option { let mut ret = None; reader::tagged_docs(d, tag_items_data_parent_item, |did| { - ret = Some(reader::with_doc_data(did, parse_def_id)); + ret = Some(translated_def_id(cdata, did)); false }); ret } -fn item_reqd_and_translated_parent_item(cnum: ast::CrateNum, - d: rbml::Doc) -> ast::DefId { - let trait_did = item_parent_item(d).expect("item without parent"); - ast::DefId { krate: cnum, node: trait_did.node } +fn item_require_parent_item(cdata: Cmd, d: rbml::Doc) -> ast::DefId { + translated_def_id(cdata, reader::get_doc(d, tag_items_data_parent_item)) } fn item_def_id(d: rbml::Doc, cdata: Cmd) -> ast::DefId { - let tagdoc = reader::get_doc(d, tag_def_id); - return translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id)); + translated_def_id(cdata, reader::get_doc(d, tag_def_id)) } fn get_provided_source(d: rbml::Doc, cdata: Cmd) -> Option { reader::maybe_get_doc(d, tag_item_method_provided_source).map(|doc| { - translate_def_id(cdata, reader::with_doc_data(doc, parse_def_id)) + translated_def_id(cdata, doc) }) } @@ -261,14 +265,12 @@ fn item_trait_ref<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd) } fn enum_variant_ids(item: rbml::Doc, cdata: Cmd) -> Vec { - let mut ids: Vec = Vec::new(); - let v = tag_items_data_item_variant; - reader::tagged_docs(item, v, |p| { - let ext = reader::with_doc_data(p, parse_def_id); - ids.push(ast::DefId { krate: cdata.cnum, node: ext.node }); + let mut ids = vec![]; + reader::tagged_docs(item, tag_items_data_item_variant, |p| { + ids.push(translated_def_id(cdata, p)); true }); - return ids; + ids } fn item_path(item_doc: rbml::Doc) -> Vec { @@ -303,8 +305,7 @@ fn item_name(intr: &IdentInterner, item: rbml::Doc) -> ast::Name { } } -fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum) - -> DefLike { +fn item_to_def_like(cdata: Cmd, item: rbml::Doc, did: ast::DefId) -> DefLike { let fam = item_family(item); match fam { Constant => { @@ -314,11 +315,9 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum) // See the comment for methods below. let provenance = if reader::maybe_get_doc( item, tag_item_trait_parent_sort).is_some() { - def::FromTrait(item_reqd_and_translated_parent_item(cnum, - item)) + def::FromTrait(item_require_parent_item(cdata, item)) } else { - def::FromImpl(item_reqd_and_translated_parent_item(cnum, - item)) + def::FromImpl(item_require_parent_item(cdata, item)) }; DlDef(def::DefAssociatedConst(did, provenance)) } else { @@ -339,17 +338,15 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum) // a trait_parent_sort. let provenance = if reader::maybe_get_doc( item, tag_item_trait_parent_sort).is_some() { - def::FromTrait(item_reqd_and_translated_parent_item(cnum, - item)) + def::FromTrait(item_require_parent_item(cdata, item)) } else { - def::FromImpl(item_reqd_and_translated_parent_item(cnum, - item)) + def::FromImpl(item_require_parent_item(cdata, item)) }; DlDef(def::DefMethod(did, provenance)) } Type => { if item_sort(item) == Some('t') { - let trait_did = item_reqd_and_translated_parent_item(cnum, item); + let trait_did = item_require_parent_item(cdata, item); DlDef(def::DefAssociatedTy(trait_did, did)) } else { DlDef(def::DefTy(did, false)) @@ -358,11 +355,11 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum) Mod => DlDef(def::DefMod(did)), ForeignMod => DlDef(def::DefForeignMod(did)), StructVariant => { - let enum_did = item_reqd_and_translated_parent_item(cnum, item); + let enum_did = item_require_parent_item(cdata, item); DlDef(def::DefVariant(enum_did, did, true)) } TupleVariant => { - let enum_did = item_reqd_and_translated_parent_item(cnum, item); + let enum_did = item_require_parent_item(cdata, item); DlDef(def::DefVariant(enum_did, did, false)) } Trait => DlDef(def::DefTrait(did)), @@ -560,9 +557,7 @@ fn each_child_of_item_or_crate(intr: Rc, { // Iterate over all children. let _ = reader::tagged_docs(item_doc, tag_mod_child, |child_info_doc| { - let child_def_id = reader::with_doc_data(child_info_doc, - parse_def_id); - let child_def_id = translate_def_id(cdata, child_def_id); + let child_def_id = translated_def_id(cdata, child_info_doc); // This item may be in yet another crate if it was the child of a // reexport. @@ -584,9 +579,7 @@ fn each_child_of_item_or_crate(intr: Rc, Some(child_item_doc) => { // Hand off the item to the callback. let child_name = item_name(&*intr, child_item_doc); - let def_like = item_to_def_like(child_item_doc, - child_def_id, - cdata.cnum); + let def_like = item_to_def_like(crate_data, child_item_doc, child_def_id); let visibility = item_visibility(child_item_doc); callback(def_like, child_name, visibility); @@ -615,9 +608,8 @@ fn each_child_of_item_or_crate(intr: Rc, if let StaticMethod = item_family(impl_method_doc) { // Hand off the static method to the callback. let static_method_name = item_name(&*intr, impl_method_doc); - let static_method_def_like = item_to_def_like(impl_method_doc, - impl_item_def_id, - cdata.cnum); + let static_method_def_like = item_to_def_like(cdata, impl_method_doc, + impl_item_def_id); callback(static_method_def_like, static_method_name, item_visibility(impl_method_doc)); @@ -633,9 +625,7 @@ fn each_child_of_item_or_crate(intr: Rc, let _ = each_reexport(item_doc, |reexport_doc| { let def_id_doc = reader::get_doc(reexport_doc, tag_items_data_item_reexport_def_id); - let child_def_id = reader::with_doc_data(def_id_doc, - parse_def_id); - let child_def_id = translate_def_id(cdata, child_def_id); + let child_def_id = translated_def_id(cdata, def_id_doc); let name_doc = reader::get_doc(reexport_doc, tag_items_data_item_reexport_name); @@ -657,9 +647,7 @@ fn each_child_of_item_or_crate(intr: Rc, // Get the item. if let Some(child_item_doc) = maybe_find_item(child_def_id.node, other_crates_items) { // Hand off the item to the callback. - let def_like = item_to_def_like(child_item_doc, - child_def_id, - child_def_id.krate); + let def_like = item_to_def_like(crate_data, child_item_doc, child_def_id); // These items have a public visibility because they're part of // a public re-export. callback(def_like, token::intern(name), ast::Public); @@ -733,9 +721,8 @@ pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &ty::ctxt<'tcx>, id: ast::NodeI match decode_inlined_item(cdata, tcx, path, item_doc) { Ok(ii) => csearch::FoundAst::Found(ii), Err(path) => { - match item_parent_item(item_doc) { + match item_parent_item(cdata, item_doc) { Some(did) => { - let did = translate_def_id(cdata, did); let parent_item = lookup_item(did.node, cdata.data()); match decode_inlined_item(cdata, tcx, path, parent_item) { Ok(ii) => csearch::FoundAst::FoundParent(did, ii), @@ -759,7 +746,7 @@ pub fn get_enum_variant_defs(intr: &IdentInterner, let item = find_item(did.node, items); let name = item_name(intr, item); let visibility = item_visibility(item); - match item_to_def_like(item, *did, cdata.cnum) { + match item_to_def_like(cdata, item, *did) { DlDef(def @ def::DefVariant(..)) => (def, name, visibility), _ => unreachable!() } @@ -889,8 +876,7 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc, let def_id = item_def_id(method_doc, cdata); - let container_id = item_reqd_and_translated_parent_item(cdata.cnum, - method_doc); + let container_id = item_require_parent_item(cdata, method_doc); let container_doc = lookup_item(container_id.node, cdata.data()); let container = match item_family(container_doc) { Trait => TraitContainer(container_id), @@ -1094,7 +1080,7 @@ pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd, let item = lookup_item(node_id, cdata.data()); let mut ret = None; reader::tagged_docs(item, tag_items_data_item_is_tuple_struct_ctor, |_| { - ret = Some(item_reqd_and_translated_parent_item(cdata.cnum, item)); + ret = Some(item_require_parent_item(cdata, item)); false }); ret @@ -1144,7 +1130,7 @@ pub fn get_struct_fields(intr: Rc, cdata: Cmd, id: ast::NodeId) let name = item_name(&*intr, an_item); let did = item_def_id(an_item, cdata); let tagdoc = reader::get_doc(an_item, tag_item_field_origin); - let origin_id = translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id)); + let origin_id = translated_def_id(cdata, tagdoc); result.push(ty::field_ty { name: name, id: did, @@ -1158,7 +1144,7 @@ pub fn get_struct_fields(intr: Rc, cdata: Cmd, id: ast::NodeId) let did = item_def_id(an_item, cdata); let tagdoc = reader::get_doc(an_item, tag_item_field_origin); let f = item_family(an_item); - let origin_id = translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id)); + let origin_id = translated_def_id(cdata, tagdoc); result.push(ty::field_ty { name: special_idents::unnamed_field.name, id: did, @@ -1386,11 +1372,10 @@ pub fn each_implementation_for_trait(cdata: Cmd, pub fn get_trait_of_item(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt) -> Option { let item_doc = lookup_item(id, cdata.data()); - let parent_item_id = match item_parent_item(item_doc) { + let parent_item_id = match item_parent_item(cdata, item_doc) { None => return None, Some(item_id) => item_id, }; - let parent_item_id = translate_def_id(cdata, parent_item_id); let parent_item_doc = lookup_item(parent_item_id.node, cdata.data()); match item_family(parent_item_doc) { Trait => Some(item_def_id(parent_item_doc, cdata)), @@ -1538,8 +1523,7 @@ fn doc_generics<'tcx>(base_doc: rbml::Doc, let name = item_name(&*token::get_ident_interner(), ident_str_doc); let def_id_doc = reader::get_doc(rp_doc, tag_region_param_def_def_id); - let def_id = reader::with_doc_data(def_id_doc, parse_def_id); - let def_id = translate_def_id(cdata, def_id); + let def_id = translated_def_id(cdata, def_id_doc); let doc = reader::get_doc(rp_doc, tag_region_param_def_space); let space = subst::ParamSpace::from_uint(reader::doc_as_u64(doc) as usize); diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 90dd452e06b5..d7d30cada81b 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -91,8 +91,8 @@ fn encode_impl_type_basename(rbml_w: &mut Encoder, name: ast::Name) { rbml_w.wr_tagged_str(tag_item_impl_type_basename, &token::get_name(name)); } -pub fn encode_def_id(rbml_w: &mut Encoder, id: DefId) { - rbml_w.wr_tagged_str(tag_def_id, &def_to_string(id)); +fn encode_def_id(rbml_w: &mut Encoder, id: DefId) { + rbml_w.wr_tagged_u64(tag_def_id, def_to_u64(id)); } #[derive(Clone)] @@ -122,6 +122,10 @@ fn encode_family(rbml_w: &mut Encoder, c: char) { rbml_w.wr_tagged_u8(tag_items_data_item_family, c as u8); } +pub fn def_to_u64(did: DefId) -> u64 { + (did.krate as u64) << 32 | (did.node as u64) +} + pub fn def_to_string(did: DefId) -> String { format!("{}:{}", did.krate, did.node) } @@ -153,9 +157,9 @@ fn encode_bounds_and_type<'a, 'tcx>(rbml_w: &mut Encoder, } fn encode_variant_id(rbml_w: &mut Encoder, vid: DefId) { - let s = def_to_string(vid); - rbml_w.wr_tagged_str(tag_items_data_item_variant, &s[..]); - rbml_w.wr_tagged_str(tag_mod_child, &s[..]); + let id = def_to_u64(vid); + rbml_w.wr_tagged_u64(tag_items_data_item_variant, id); + rbml_w.wr_tagged_u64(tag_mod_child, id); } pub fn write_closure_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, @@ -260,7 +264,7 @@ fn encode_disr_val(_: &EncodeContext, } fn encode_parent_item(rbml_w: &mut Encoder, id: DefId) { - rbml_w.wr_tagged_str(tag_items_data_parent_item, &def_to_string(id)); + rbml_w.wr_tagged_u64(tag_items_data_parent_item, def_to_u64(id)); } fn encode_struct_fields(rbml_w: &mut Encoder, @@ -275,7 +279,7 @@ fn encode_struct_fields(rbml_w: &mut Encoder, } encode_struct_field_family(rbml_w, f.vis); encode_def_id(rbml_w, f.id); - rbml_w.wr_tagged_str(tag_item_field_origin, &def_to_string(origin)); + rbml_w.wr_tagged_u64(tag_item_field_origin, def_to_u64(origin)); rbml_w.end_tag(); } } @@ -358,8 +362,8 @@ fn encode_reexported_static_method(rbml_w: &mut Encoder, debug!("(encode reexported static method) {}::{}", exp.name, token::get_name(method_name)); rbml_w.start_tag(tag_items_data_item_reexport); - rbml_w.wr_tagged_str(tag_items_data_item_reexport_def_id, - &def_to_string(method_def_id)); + rbml_w.wr_tagged_u64(tag_items_data_item_reexport_def_id, + def_to_u64(method_def_id)); rbml_w.wr_tagged_str(tag_items_data_item_reexport_name, &format!("{}::{}", exp.name, token::get_name(method_name))); @@ -495,8 +499,8 @@ fn encode_reexports(ecx: &EncodeContext, exp.def_id.node, id); rbml_w.start_tag(tag_items_data_item_reexport); - rbml_w.wr_tagged_str(tag_items_data_item_reexport_def_id, - &def_to_string(exp.def_id)); + rbml_w.wr_tagged_u64(tag_items_data_item_reexport_def_id, + def_to_u64(exp.def_id)); rbml_w.wr_tagged_str(tag_items_data_item_reexport_name, exp.name.as_str()); rbml_w.end_tag(); @@ -526,12 +530,12 @@ fn encode_info_for_mod(ecx: &EncodeContext, // Encode info about all the module children. for item in &md.items { - rbml_w.wr_tagged_str(tag_mod_child, - &def_to_string(local_def(item.id))); + rbml_w.wr_tagged_u64(tag_mod_child, + def_to_u64(local_def(item.id))); each_auxiliary_node_id(&**item, |auxiliary_node_id| { - rbml_w.wr_tagged_str(tag_mod_child, - &def_to_string(local_def(auxiliary_node_id))); + rbml_w.wr_tagged_u64(tag_mod_child, + def_to_u64(local_def(auxiliary_node_id))); true }); @@ -541,8 +545,7 @@ fn encode_info_for_mod(ecx: &EncodeContext, token::get_ident(ident), did, ecx.tcx.map.node_to_string(did)); - rbml_w.wr_tagged_str(tag_mod_impl, - &def_to_string(local_def(did))); + rbml_w.wr_tagged_u64(tag_mod_impl, def_to_u64(local_def(did))); } } @@ -619,8 +622,7 @@ fn encode_parent_sort(rbml_w: &mut Encoder, sort: char) { fn encode_provided_source(rbml_w: &mut Encoder, source_opt: Option) { if let Some(source) = source_opt { - rbml_w.wr_tagged_str(tag_item_method_provided_source, - &def_to_string(source)); + rbml_w.wr_tagged_u64(tag_item_method_provided_source, def_to_u64(source)); } } @@ -725,8 +727,8 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder, encode_name(rbml_w, param.name); rbml_w.end_tag(); - rbml_w.wr_tagged_str(tag_region_param_def_def_id, - &def_to_string(param.def_id)); + rbml_w.wr_tagged_u64(tag_region_param_def_def_id, + def_to_u64(param.def_id)); rbml_w.wr_tagged_u64(tag_region_param_def_space, param.space.to_uint() as u64); @@ -1089,8 +1091,8 @@ fn encode_info_for_item(ecx: &EncodeContext, // Encode all the items in this module. for foreign_item in &fm.items { - rbml_w.wr_tagged_str(tag_mod_child, - &def_to_string(local_def(foreign_item.id))); + rbml_w.wr_tagged_u64(tag_mod_child, + def_to_u64(local_def(foreign_item.id))); } encode_visibility(rbml_w, vis); encode_stability(rbml_w, stab); @@ -1335,8 +1337,8 @@ fn encode_info_for_item(ecx: &EncodeContext, } rbml_w.end_tag(); - rbml_w.wr_tagged_str(tag_mod_child, - &def_to_string(method_def_id.def_id())); + rbml_w.wr_tagged_u64(tag_mod_child, + def_to_u64(method_def_id.def_id())); } encode_path(rbml_w, path.clone()); @@ -1932,12 +1934,12 @@ fn encode_misc_info(ecx: &EncodeContext, rbml_w.start_tag(tag_misc_info); rbml_w.start_tag(tag_misc_info_crate_items); for item in &krate.module.items { - rbml_w.wr_tagged_str(tag_mod_child, - &def_to_string(local_def(item.id))); + rbml_w.wr_tagged_u64(tag_mod_child, + def_to_u64(local_def(item.id))); each_auxiliary_node_id(&**item, |auxiliary_node_id| { - rbml_w.wr_tagged_str(tag_mod_child, - &def_to_string(local_def(auxiliary_node_id))); + rbml_w.wr_tagged_u64(tag_mod_child, + def_to_u64(local_def(auxiliary_node_id))); true }); } From aeb92bab5d63313455e4bfd079ce84712a1a4bac Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 12 May 2015 07:51:15 +0300 Subject: [PATCH 88/97] rustc: rename ty::populate_implementations_for_type_if_necessary to make it clear that it only populates inherent impls. --- src/librustc/metadata/csearch.rs | 8 ++--- src/librustc/metadata/decoder.rs | 11 ++++--- src/librustc/middle/ty.rs | 40 +++++------------------ src/librustc_typeck/check/method/probe.rs | 2 +- src/librustdoc/clean/inline.rs | 2 +- 5 files changed, 21 insertions(+), 42 deletions(-) diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index 7132ac4895aa..4d59bf5d96ab 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -313,13 +313,13 @@ pub fn each_impl(cstore: &cstore::CStore, decoder::each_impl(&*cdata, callback) } -pub fn each_implementation_for_type(cstore: &cstore::CStore, - def_id: ast::DefId, - callback: F) where +pub fn each_inherent_implementation_for_type(cstore: &cstore::CStore, + def_id: ast::DefId, + callback: F) where F: FnMut(ast::DefId), { let cdata = cstore.get_crate_data(def_id.krate); - decoder::each_implementation_for_type(&*cdata, def_id.node, callback) + decoder::each_inherent_implementation_for_type(&*cdata, def_id.node, callback) } pub fn each_implementation_for_trait(cstore: &cstore::CStore, diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index f7fb5d495a45..c5ef97c75f87 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -1338,17 +1338,18 @@ pub fn each_impl(cdata: Cmd, mut callback: F) where }); } -pub fn each_implementation_for_type(cdata: Cmd, - id: ast::NodeId, - mut callback: F) +pub fn each_inherent_implementation_for_type(cdata: Cmd, + id: ast::NodeId, + mut callback: F) where F: FnMut(ast::DefId), { let item_doc = lookup_item(id, cdata.data()); reader::tagged_docs(item_doc, tag_items_data_item_inherent_impl, |impl_doc| { - let implementation_def_id = item_def_id(impl_doc, cdata); - callback(implementation_def_id); + if reader::maybe_get_doc(impl_doc, tag_item_trait_ref).is_none() { + callback(item_def_id(impl_doc, cdata)); + } true }); } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 5298c9682b48..38cd6d91a31e 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -6336,10 +6336,10 @@ pub fn populate_implementations_for_primitive_if_necessary(tcx: &ctxt, tcx.populated_external_primitive_impls.borrow_mut().insert(primitive_def_id); } -/// Populates the type context with all the implementations for the given type -/// if necessary. -pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt, - type_id: ast::DefId) { +/// Populates the type context with all the inherent implementations for +/// the given type if necessary. +pub fn populate_inherent_implementations_for_type_if_necessary(tcx: &ctxt, + type_id: ast::DefId) { if type_id.krate == LOCAL_CRATE { return } @@ -6348,37 +6348,15 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt, return } - debug!("populate_implementations_for_type_if_necessary: searching for {:?}", type_id); + debug!("populate_inherent_implementations_for_type_if_necessary: searching for {:?}", type_id); let mut inherent_impls = Vec::new(); - csearch::each_implementation_for_type(&tcx.sess.cstore, type_id, |impl_def_id| { - let impl_items = csearch::get_impl_items(&tcx.sess.cstore, impl_def_id); - - // Record the implementation, if needed - if let Some(trait_ref) = csearch::get_impl_trait(tcx, impl_def_id) { - let trait_def = lookup_trait_def(tcx, trait_ref.def_id); - trait_def.record_impl(tcx, impl_def_id, trait_ref); - } else { - inherent_impls.push(impl_def_id); - } - - // For any methods that use a default implementation, add them to - // the map. This is a bit unfortunate. - for impl_item_def_id in &impl_items { - let method_def_id = impl_item_def_id.def_id(); - match impl_or_trait_item(tcx, method_def_id) { - MethodTraitItem(method) => { - if let Some(source) = method.provided_source { - tcx.provided_method_sources - .borrow_mut() - .insert(method_def_id, source); - } - } - _ => {} - } - } + csearch::each_inherent_implementation_for_type(&tcx.sess.cstore, type_id, |impl_def_id| { + // Record the implementation. + inherent_impls.push(impl_def_id); // Store the implementation info. + let impl_items = csearch::get_impl_items(&tcx.sess.cstore, impl_def_id); tcx.impl_items.borrow_mut().insert(impl_def_id, impl_items); }); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index c94fa0370268..6171df218bb6 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -371,7 +371,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: ast::DefId) { // Read the inherent implementation candidates for this type from the // metadata if necessary. - ty::populate_implementations_for_type_if_necessary(self.tcx(), def_id); + ty::populate_inherent_implementations_for_type_if_necessary(self.tcx(), def_id); if let Some(impl_infos) = self.tcx().inherent_impls.borrow().get(&def_id) { for &impl_def_id in &***impl_infos { diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 0d59577a6d80..3ce8835b1a8d 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -221,7 +221,7 @@ fn build_type(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEn pub fn build_impls(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> Vec { - ty::populate_implementations_for_type_if_necessary(tcx, did); + ty::populate_inherent_implementations_for_type_if_necessary(tcx, did); let mut impls = Vec::new(); match tcx.inherent_impls.borrow().get(&did) { From 592165fb17fb78e7aa1cfd054ddfdfe9401e92d7 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 12 May 2015 07:56:37 +0300 Subject: [PATCH 89/97] Fix ty::populate_implementations_for_trait_if_necessary to load the trait's impls from all the crates. --- src/librustc/metadata/common.rs | 1 + src/librustc/metadata/csearch.rs | 7 +++-- src/librustc/metadata/decoder.rs | 50 ++++++++++++++++++++++++++------ src/librustc/metadata/encoder.rs | 1 + src/librustc/middle/ty.rs | 12 ++++---- 5 files changed, 54 insertions(+), 17 deletions(-) diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index 06a40f1dd277..b6202084296b 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -189,6 +189,7 @@ pub const tag_item_impl_vtables: usize = 0x7e; pub const tag_impls: usize = 0x109; // top-level only pub const tag_impls_impl: usize = 0x7f; +pub const tag_impls_impl_trait_def_id: usize = 0x8d; pub const tag_items_data_item_inherent_impl: usize = 0x80; pub const tag_items_data_item_extension_impl: usize = 0x81; diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index 4d59bf5d96ab..369d1aeabd41 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -324,11 +324,12 @@ pub fn each_inherent_implementation_for_type(cstore: &cstore::CStore, pub fn each_implementation_for_trait(cstore: &cstore::CStore, def_id: ast::DefId, - callback: F) where + mut callback: F) where F: FnMut(ast::DefId), { - let cdata = cstore.get_crate_data(def_id.krate); - decoder::each_implementation_for_trait(&*cdata, def_id.node, callback) + cstore.iter_crate_data(|_, cdata| { + decoder::each_implementation_for_trait(cdata, def_id, &mut callback) + }) } /// If the given def ID describes an item belonging to a trait (either a diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index c5ef97c75f87..4cb6e7481902 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -1328,6 +1328,22 @@ pub fn translate_def_id(cdata: Cmd, did: ast::DefId) -> ast::DefId { } } +// Translate a DefId from the current compilation environment to a DefId +// for an external crate. +fn reverse_translate_def_id(cdata: Cmd, did: ast::DefId) -> Option { + if did.krate == cdata.cnum { + return Some(ast::DefId { krate: ast::LOCAL_CRATE, node: did.node }); + } + + for (&local, &global) in &cdata.cnum_map { + if global == did.krate { + return Some(ast::DefId { krate: local, node: did.node }); + } + } + + None +} + pub fn each_impl(cdata: Cmd, mut callback: F) where F: FnMut(ast::DefId), { @@ -1355,19 +1371,35 @@ pub fn each_inherent_implementation_for_type(cdata: Cmd, } pub fn each_implementation_for_trait(cdata: Cmd, - id: ast::NodeId, + def_id: ast::DefId, mut callback: F) where F: FnMut(ast::DefId), { - let item_doc = lookup_item(id, cdata.data()); + if cdata.cnum == def_id.krate { + let item_doc = lookup_item(def_id.node, cdata.data()); + let _ = reader::tagged_docs(item_doc, + tag_items_data_item_extension_impl, + |impl_doc| { + callback(item_def_id(impl_doc, cdata)); + true + }); + return; + } - let _ = reader::tagged_docs(item_doc, - tag_items_data_item_extension_impl, - |impl_doc| { - let implementation_def_id = item_def_id(impl_doc, cdata); - callback(implementation_def_id); - true - }); + // Do a reverse lookup beforehand to avoid touching the crate_num + // hash map in the loop below. + if let Some(crate_local_did) = reverse_translate_def_id(cdata, def_id) { + let def_id_u64 = def_to_u64(crate_local_did); + + let impls_doc = reader::get_doc(rbml::Doc::new(cdata.data()), tag_impls); + let _ = reader::tagged_docs(impls_doc, tag_impls_impl, |impl_doc| { + let impl_trait = reader::get_doc(impl_doc, tag_impls_impl_trait_def_id); + if reader::doc_as_u64(impl_trait) == def_id_u64 { + callback(item_def_id(impl_doc, cdata)); + } + true + }); + } } pub fn get_trait_of_item(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt) diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index d7d30cada81b..afc71f83975c 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1895,6 +1895,7 @@ impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> { def_id.krate != ast::LOCAL_CRATE { self.rbml_w.start_tag(tag_impls_impl); encode_def_id(self.rbml_w, local_def(item.id)); + self.rbml_w.wr_tagged_u64(tag_impls_impl_trait_def_id, def_to_u64(def_id)); self.rbml_w.end_tag(); } } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 38cd6d91a31e..3ec400b35c95 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -2564,9 +2564,11 @@ impl<'tcx> TraitDef<'tcx> { tcx: &ctxt<'tcx>, impl_def_id: DefId, impl_trait_ref: TraitRef<'tcx>) { + debug!("TraitDef::record_impl for {}, from {}", + self.repr(tcx), impl_trait_ref.repr(tcx)); + // We don't want to borrow_mut after we already populated all impls, // so check if an impl is present with an immutable borrow first. - if let Some(sty) = fast_reject::simplify_type(tcx, impl_trait_ref.self_ty(), false) { if let Some(is) = self.nonblanket_impls.borrow().get(&sty) { @@ -6366,18 +6368,18 @@ pub fn populate_inherent_implementations_for_type_if_necessary(tcx: &ctxt, /// Populates the type context with all the implementations for the given /// trait if necessary. -pub fn populate_implementations_for_trait_if_necessary( - tcx: &ctxt, - trait_id: ast::DefId) { +pub fn populate_implementations_for_trait_if_necessary(tcx: &ctxt, trait_id: ast::DefId) { if trait_id.krate == LOCAL_CRATE { return } let def = lookup_trait_def(tcx, trait_id); if def.flags.get().intersects(TraitFlags::IMPLS_VALID) { - return + return; } + debug!("populate_implementations_for_trait_if_necessary: searching for {}", def.repr(tcx)); + if csearch::is_defaulted_trait(&tcx.sess.cstore, trait_id) { record_trait_has_default_impl(tcx, trait_id); } From 75cd8f94e1f6319f92f837f9ef6884fafca8fb6f Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 12 May 2015 07:58:01 +0300 Subject: [PATCH 90/97] rustc_typeck: remove the "preload all impls ever" workaround in coherence. --- src/librustc/metadata/csearch.rs | 9 --- src/librustc/metadata/decoder.rs | 10 --- src/librustc_typeck/coherence/mod.rs | 80 +----------------------- src/librustc_typeck/coherence/overlap.rs | 7 +-- 4 files changed, 4 insertions(+), 102 deletions(-) diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index 369d1aeabd41..6caefec48783 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -304,15 +304,6 @@ pub fn get_native_libraries(cstore: &cstore::CStore, crate_num: ast::CrateNum) decoder::get_native_libraries(&*cdata) } -pub fn each_impl(cstore: &cstore::CStore, - crate_num: ast::CrateNum, - callback: F) where - F: FnMut(ast::DefId), -{ - let cdata = cstore.get_crate_data(crate_num); - decoder::each_impl(&*cdata, callback) -} - pub fn each_inherent_implementation_for_type(cstore: &cstore::CStore, def_id: ast::DefId, callback: F) where diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 4cb6e7481902..382dc437bdc4 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -1344,16 +1344,6 @@ fn reverse_translate_def_id(cdata: Cmd, did: ast::DefId) -> Option { None } -pub fn each_impl(cdata: Cmd, mut callback: F) where - F: FnMut(ast::DefId), -{ - let impls_doc = reader::get_doc(rbml::Doc::new(cdata.data()), tag_impls); - let _ = reader::tagged_docs(impls_doc, tag_impls_impl, |impl_doc| { - callback(item_def_id(impl_doc, cdata)); - true - }); -} - pub fn each_inherent_implementation_for_type(cdata: Cmd, id: ast::NodeId, mut callback: F) diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 05b74a5cc226..4dc1596b1ff7 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -16,13 +16,10 @@ // mappings. That mapping code resides here. -use metadata::csearch::{each_impl, get_impl_trait}; -use metadata::csearch; use middle::subst::{self, Subst}; use middle::ty::RegionEscape; use middle::ty::{ImplContainer, ImplOrTraitItemId, ConstTraitItemId}; -use middle::ty::{MethodTraitItemId, TypeTraitItemId}; -use middle::ty::{ParameterEnvironment, lookup_item_type}; +use middle::ty::{MethodTraitItemId, TypeTraitItemId, ParameterEnvironment}; use middle::ty::{Ty, ty_bool, ty_char, ty_enum, ty_err}; use middle::ty::{ty_param, TypeScheme, ty_ptr}; use middle::ty::{ty_rptr, ty_struct, ty_trait, ty_tup}; @@ -33,7 +30,6 @@ use middle::ty; use CrateCtxt; use middle::infer::InferCtxt; use middle::infer::new_infer_ctxt; -use std::collections::HashSet; use std::cell::RefCell; use std::rc::Rc; use syntax::ast::{Crate, DefId}; @@ -130,11 +126,6 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { Rc::new((*v.borrow()).clone())); } - // Bring in external crates. It's fine for this to happen after the - // coherence checks, because we ensure by construction that no errors - // can happen at link time. - self.add_external_crates(); - // Populate the table of destructors. It might seem a bit strange to // do this here, but it's actually the most convenient place, since // the coherence tables contain the trait -> type mappings. @@ -267,11 +258,6 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { trait_def.record_impl(self.crate_context.tcx, impl_def_id, impl_trait_ref); } - fn get_self_type_for_implementation(&self, impl_did: DefId) - -> TypeScheme<'tcx> { - self.crate_context.tcx.tcache.borrow().get(&impl_did).unwrap().clone() - } - // Converts an implementation in the AST to a vector of items. fn create_impl_from_item(&self, item: &Item) -> Vec { match item.node { @@ -313,66 +299,6 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { } } - // External crate handling - - fn add_external_impl(&self, - impls_seen: &mut HashSet, - impl_def_id: DefId) { - let tcx = self.crate_context.tcx; - let impl_items = csearch::get_impl_items(&tcx.sess.cstore, - impl_def_id); - - // Make sure we don't visit the same implementation multiple times. - if !impls_seen.insert(impl_def_id) { - // Skip this one. - return - } - // Good. Continue. - - let _ = lookup_item_type(tcx, impl_def_id); - let associated_traits = get_impl_trait(tcx, impl_def_id); - - // Do a sanity check. - assert!(associated_traits.is_some()); - - // Record all the trait items. - if let Some(trait_ref) = associated_traits { - self.add_trait_impl(trait_ref, impl_def_id); - } - - // For any methods that use a default implementation, add them to - // the map. This is a bit unfortunate. - for item_def_id in &impl_items { - let impl_item = ty::impl_or_trait_item(tcx, item_def_id.def_id()); - match impl_item { - ty::MethodTraitItem(ref method) => { - if let Some(source) = method.provided_source { - tcx.provided_method_sources - .borrow_mut() - .insert(item_def_id.def_id(), source); - } - } - _ => {} - } - } - - tcx.impl_items.borrow_mut().insert(impl_def_id, impl_items); - } - - // Adds implementations and traits from external crates to the coherence - // info. - fn add_external_crates(&self) { - let mut impls_seen = HashSet::new(); - - let crate_store = &self.crate_context.tcx.sess.cstore; - crate_store.iter_crate_data(|crate_number, _crate_metadata| { - each_impl(crate_store, crate_number, |def_id| { - assert_eq!(crate_number, def_id.krate); - self.add_external_impl(&mut impls_seen, def_id) - }) - }) - } - // // Destructors // @@ -395,7 +321,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { } let method_def_id = items[0]; - let self_type = self.get_self_type_for_implementation(impl_did); + let self_type = ty::lookup_item_type(tcx, impl_did); match self_type.ty.sty { ty::ty_enum(type_def_id, _) | ty::ty_struct(type_def_id, _) | @@ -451,7 +377,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { return } - let self_type = self.get_self_type_for_implementation(impl_did); + let self_type = ty::lookup_item_type(tcx, impl_did); debug!("check_implementations_of_copy: self_type={} (bound)", self_type.repr(tcx)); diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index 46cce5430116..e9c69c84630e 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -48,14 +48,9 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { // check_for_overlapping_impls_of_trait() check, since that // check can populate this table further with impls from other // crates. - let trait_defs : Vec<&ty::TraitDef> = { - let d = self.tcx.trait_defs.borrow(); - d.values().map(|&v|v).collect() - }; + let trait_defs: Vec<_> = self.tcx.trait_defs.borrow().values().cloned().collect(); for trait_def in trait_defs { - // FIXME -- it seems like this method actually pushes - // duplicate impls onto the list ty::populate_implementations_for_trait_if_necessary( self.tcx, trait_def.trait_ref.def_id); From 93c21c7bcad447fb4834d9013815ef44827328c9 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 12 May 2015 10:52:36 +0200 Subject: [PATCH 91/97] Correct claims about &T's Copyness. --- src/librustc_typeck/diagnostics.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index ea872d101442..f9565d528e89 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -186,7 +186,7 @@ struct Foo<'a> { ``` This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (this -differs from the behavior for `&T`, which is `Copy` when `T` is `Copy`). +differs from the behavior for `&T`, which is always `Copy`). "##, E0205: r##" @@ -216,7 +216,7 @@ enum Foo<'a> { ``` This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (this -differs from the behavior for `&T`, which is `Copy` when `T` is `Copy`). +differs from the behavior for `&T`, which is always `Copy`). "##, E0206: r##" From a5cac55be451a32a5956339009c49ac4fcaaef5c Mon Sep 17 00:00:00 2001 From: Mike Sampson Date: Tue, 12 May 2015 19:57:09 +1000 Subject: [PATCH 92/97] Add wait and waitpid to libc. --- src/liblibc/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index 55934da00a37..69ab34fee5a1 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -5722,6 +5722,9 @@ pub mod funcs { pub fn tcgetpgrp(fd: c_int) -> pid_t; pub fn ttyname(fd: c_int) -> *mut c_char; pub fn unlink(c: *const c_char) -> c_int; + pub fn wait(status: *const c_int) -> pid_t; + pub fn waitpid(pid: pid_t, status: *const c_int, options: c_int) + -> pid_t; pub fn write(fd: c_int, buf: *const c_void, count: size_t) -> ssize_t; pub fn pread(fd: c_int, buf: *mut c_void, count: size_t, @@ -5773,6 +5776,9 @@ pub mod funcs { pub fn sysconf(name: c_int) -> c_long; pub fn ttyname(fd: c_int) -> *mut c_char; pub fn unlink(c: *const c_char) -> c_int; + pub fn wait(status: *const c_int) -> pid_t; + pub fn waitpid(pid: pid_t, status: *const c_int, options: c_int) + -> pid_t; pub fn write(fd: c_int, buf: *const c_void, count: size_t) -> ssize_t; pub fn pread(fd: c_int, buf: *mut c_void, count: size_t, From 1d1570acc9ac9d76394da05f63fa7881b6492ab9 Mon Sep 17 00:00:00 2001 From: Johannes Oertel Date: Mon, 11 May 2015 22:51:31 +0200 Subject: [PATCH 93/97] Add regression test for #18075 Closes #18075. --- src/test/run-pass/issue-18075.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/test/run-pass/issue-18075.rs diff --git a/src/test/run-pass/issue-18075.rs b/src/test/run-pass/issue-18075.rs new file mode 100644 index 000000000000..5f07ba2235fd --- /dev/null +++ b/src/test/run-pass/issue-18075.rs @@ -0,0 +1,16 @@ +// 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. + +// exec-env:RUST_LOG=rustc::middle=debug + +fn main() { + let b = 1isize; + println!("{}", b); +} From 23300a39a1ceffdba4c4695fc2e527e47ea2c95d Mon Sep 17 00:00:00 2001 From: Johannes Oertel Date: Tue, 12 May 2015 11:02:47 +0200 Subject: [PATCH 94/97] Add regression test for #20413 Closes #20413. --- src/test/compile-fail/issue-20413.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/test/compile-fail/issue-20413.rs diff --git a/src/test/compile-fail/issue-20413.rs b/src/test/compile-fail/issue-20413.rs new file mode 100644 index 000000000000..a48c03aa178c --- /dev/null +++ b/src/test/compile-fail/issue-20413.rs @@ -0,0 +1,25 @@ +// 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. + +trait Foo { + fn answer(self); +} + +struct NoData; +//~^ ERROR: parameter `T` is never used + +impl Foo for T where NoData: Foo { +//~^ ERROR: overflow evaluating the requirement + fn answer(self) { + let val: NoData = NoData; + } +} + +fn main() {} From 6faa8d6793e9136cbc2d852504f499144ddd1097 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Tue, 12 May 2015 21:21:26 +1000 Subject: [PATCH 95/97] Add a link to the error index to the main doc page. I also capitalised "The Standard Library" and neatened a few bits of grammar. Also fixed: `#[main]` inside one of the error descriptions. --- src/doc/index.md | 13 +++++++++---- src/librustc/diagnostics.rs | 4 ++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/doc/index.md b/src/doc/index.md index 5a437e959b7f..85ee56180168 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -24,7 +24,7 @@ series of small examples. # Community & Getting Help If you need help with something, or just want to talk about Rust with others, -there's a few places you can do that: +there are a few places you can do that: The Rust IRC channels on [irc.mozilla.org](http://irc.mozilla.org/) are the fastest way to get help. @@ -59,7 +59,7 @@ the language in as much detail as possible is in [the reference](reference.html) # Tools -Rust's still a young language, so there isn't a ton of tooling yet, but the +Rust is still a young language, so there isn't a ton of tooling yet, but the tools we have are really nice. [Cargo](http://crates.io) is Rust's package manager, and its website contains @@ -69,16 +69,21 @@ lots of good documentation. # FAQs -There are questions that are asked quite often, and so we've made FAQs for them: +There are questions that are asked quite often, so we've made FAQs for them: * [Language Design FAQ](complement-design-faq.html) * [Language FAQ](complement-lang-faq.html) * [Project FAQ](complement-project-faq.html) * [How to submit a bug report](https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports) -# The standard library +# The Standard Library We have [API documentation for the entire standard library](std/index.html). There's a list of crates on the left with more specific sections, or you can use the search bar at the top to search for something if you know its name. + +# The Error Index + +If you encounter an error while compiling your code you may be able to look it +up in the [Rust Compiler Error Index](error-index.html). diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 0f1e55544e1a..6690e6831afe 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -273,8 +273,8 @@ See also http://doc.rust-lang.org/book/unsafe.html E0137: r##" This error indicates that the compiler found multiple functions with the -#[main] attribute. This is an error because there must be a unique entry point -into a Rust program. +`#[main]` attribute. This is an error because there must be a unique entry +point into a Rust program. "##, E0152: r##" From e780fb270c5296a87ff9dc1442fc141f69e77fcd Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Thu, 30 Apr 2015 14:40:38 -0400 Subject: [PATCH 96/97] TRPL: Borrow and AsRef These two traits are commonly confused. As such, explain the difference. Fixes #24163 --- src/doc/trpl/SUMMARY.md | 1 + src/doc/trpl/borrow-and-asref.md | 93 ++++++++++++++++++++++++++++++++ src/libcollections/borrow.rs | 5 ++ src/libcore/convert.rs | 5 ++ 4 files changed, 104 insertions(+) create mode 100644 src/doc/trpl/borrow-and-asref.md diff --git a/src/doc/trpl/SUMMARY.md b/src/doc/trpl/SUMMARY.md index de7ded76280f..3f97928a56e3 100644 --- a/src/doc/trpl/SUMMARY.md +++ b/src/doc/trpl/SUMMARY.md @@ -15,6 +15,7 @@ * [Concurrency](concurrency.md) * [Error Handling](error-handling.md) * [FFI](ffi.md) + * [Borrow and AsRef](borrow-and-asref.md) * [Syntax and Semantics](syntax-and-semantics.md) * [Variable Bindings](variable-bindings.md) * [Functions](functions.md) diff --git a/src/doc/trpl/borrow-and-asref.md b/src/doc/trpl/borrow-and-asref.md new file mode 100644 index 000000000000..f5f314f1c21d --- /dev/null +++ b/src/doc/trpl/borrow-and-asref.md @@ -0,0 +1,93 @@ +% Borrow and AsRef + +The [`Borrow`][borrow] and [`AsRef`][asref] traits are very similar, but +different. Here’s a quick refresher on what these two traits mean. + +[borrow]: ../std/borrow/trait.Borrow.html +[asref]: ../std/convert/trait.AsRef.html + +# Borrow + +The `Borrow` trait is used when you’re writing a datastructure, and you want to +use either an owned or borrowed type as synonymous for some purpose. + +For example, [`HashMap`][hashmap] has a [`get` method][get] which uses `Borrow`: + +```rust,ignore +fn get(&self, k: &Q) -> Option<&V> + where K: Borrow, + Q: Hash + Eq +``` + +[hashmap]: ../std/collections/struct.HashMap.html +[get]: ../std/collections/struct.HashMap.html#method.get + +This signature is pretty complicated. The `K` parameter is what we’re interested +in here. It refers to a parameter of the `HashMap` itself: + +```rust,ignore +struct HashMap { +``` + +The `K` parameter is the type of _key_ the `HashMap` uses. So, looking at +the signature of `get()` again, we can use `get()` when the key implements +`Borrow`. That way, we can make a `HashMap` which uses `String` keys, +but use `&str`s when we’re searching: + +```rust +use std::collections::HashMap; + +let mut map = HashMap::new(); +map.insert("Foo".to_string(), 42); + +assert_eq!(map.get("Foo"), Some(&42)); +``` + +This is because the standard library has `impl Borrow for String`. + +For most types, when you want to take an owned or borrowed type, a `&T` is +enough. But one area where `Borrow` is effective is when there’s more than one +kind of borrowed value. Slices are an area where this is especially true: you +can have both an `&[T]` or a `&mut [T]`. If we wanted to accept both of these +types, `Borrow` is up for it: + +``` +use std::borrow::Borrow; +use std::fmt::Display; + +fn foo + Display>(a: T) { + println!("a is borrowed: {}", a); +} + +let mut i = 5; + +foo(&i); +foo(&mut i); +``` + +This will print out `a is borrowed: 5` twice. + +# AsRef + +The `AsRef` trait is a conversion trait. It’s used for converting some value to +a reference in generic code. Like this: + +```rust +let s = "Hello".to_string(); + +fn foo>(s: T) { + let slice = s.as_ref(); +} +``` + +# Which should I use? + +We can see how they’re kind of the same: they both deal with owned and borrowed +versions of some type. However, they’re a bit different. + +Choose `Borrow` when you want to abstract over different kinds of borrowing, or +when you’re building a datastructure that treats owned and borrowed values in +equivalent ways, such as hashing and comparison. + +Choose `AsRef` when you want to convert something to a reference directly, and +you’re writing generic code. diff --git a/src/libcollections/borrow.rs b/src/libcollections/borrow.rs index 7332bf4670ae..a86a4b4215f2 100644 --- a/src/libcollections/borrow.rs +++ b/src/libcollections/borrow.rs @@ -37,6 +37,11 @@ use self::Cow::*; /// trait: if `T: Borrow`, then `&U` can be borrowed from `&T`. A given /// type can be borrowed as multiple different types. In particular, `Vec: /// Borrow>` and `Vec: Borrow<[T]>`. +/// +/// `Borrow` is very similar to, but different than, `AsRef`. See +/// [the book][book] for more. +/// +/// [book]: ../../book/borrow-and-asref.html #[stable(feature = "rust1", since = "1.0.0")] pub trait Borrow { /// Immutably borrows from an owned value. diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index da6ac6bd752b..f6987c196649 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -24,6 +24,11 @@ use marker::Sized; /// A cheap, reference-to-reference conversion. /// +/// `AsRef` is very similar to, but different than, `Borrow`. See +/// [the book][book] for more. +/// +/// [book]: ../../book/borrow-and-asref.html +/// /// # Examples /// /// Both `String` and `&str` implement `AsRef`: From 393a37ecbd5fbeda49246dc7f3885af69130151a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 12 May 2015 12:02:39 -0400 Subject: [PATCH 97/97] Correct various small points, expand some sections, while avoiding too much detail. --- src/doc/reference.md | 203 ++++++++++++++++++++++++++++++++----------- 1 file changed, 151 insertions(+), 52 deletions(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 750179622746..2ddec9ba424f 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -426,12 +426,12 @@ x; x::y::z; ``` -Path components are usually [identifiers](#identifiers), but the trailing -component of a path may be an angle-bracket-enclosed list of type arguments. In -[expression](#expressions) context, the type argument list is given after a -final (`::`) namespace qualifier in order to disambiguate it from a relational -expression involving the less-than symbol (`<`). In type expression context, -the final namespace qualifier is omitted. +Path components are usually [identifiers](#identifiers), but they may +also include angle-bracket-enclosed lists of type arguments. In +[expression](#expressions) context, the type argument list is given +after a `::` namespace qualifier in order to disambiguate it from a +relational expression involving the less-than symbol (`<`). In type +expression context, the final namespace qualifier is omitted. Two examples of paths with type arguments: @@ -497,8 +497,9 @@ names, and invoked through a consistent syntax: `some_extension!(...)`. Users of `rustc` can define new syntax extensions in two ways: -* [Compiler plugins][plugin] can include arbitrary - Rust code that manipulates syntax trees at compile time. +* [Compiler plugins][plugin] can include arbitrary Rust code that + manipulates syntax trees at compile time. Note that the interface + for compiler plugins is considered highly unstable. * [Macros](book/macros.html) define new syntax in a higher-level, declarative way. @@ -560,14 +561,18 @@ Nested repetitions are allowed. The parser used by the macro system is reasonably powerful, but the parsing of Rust syntax is restricted in two ways: -1. The parser will always parse as much as possible. If it attempts to match - `$i:expr [ , ]` against `8 [ , ]`, it will attempt to parse `i` as an array - index operation and fail. Adding a separator can solve this problem. +1. Macro definitions are required to include suitable separators after parsing + expressions and other bits of the Rust grammar. This implies that + a macro definition like `$i:expr [ , ]` is not legal, because `[` could be part + of an expression. A macro definition like `$i:expr,` or `$i:expr;` would be legal, + however, because `,` and `;` are legal separators. See [RFC 550] for more information. 2. The parser must have eliminated all ambiguity by the time it reaches a `$` _name_ `:` _designator_. This requirement most often affects name-designator pairs when they occur at the beginning of, or immediately after, a `$(...)*`; requiring a distinctive token in front can solve the problem. +[RFC 550]: https://github.com/rust-lang/rfcs/blob/master/text/0550-macro-future-proofing.md + # Crates and source files Although Rust, like any other language, can be implemented by an interpreter as @@ -686,7 +691,8 @@ type arguments as a list of comma-separated types enclosed within angle brackets, in order to refer to the type-parameterized item. In practice, the type-inference system can usually infer such argument types from context. There are no general type-parametric types, only type-parametric items. That is, Rust -has no notion of type abstraction: there are no first-class "forall" types. +has no notion of type abstraction: there are no higher-ranked (or "forall") types +abstracted over other types, though higher-ranked types do exist for lifetimes. ### Modules @@ -732,6 +738,7 @@ mod vec; mod thread { // Load the `local_data` module from `thread/local_data.rs` + // or `thread/local_data/mod.rs`. mod local_data; } ``` @@ -1004,7 +1011,8 @@ the guarantee that these issues are never caused by safe code. * `&mut` and `&` follow LLVM’s scoped [noalias] model, except if the `&T` contains an `UnsafeCell`. Unsafe code must not violate these aliasing guarantees. -* Mutating an immutable value/reference without `UnsafeCell` +* Mutating non-mutable data (that is, data reached through a shared reference or + data owned by a `let` binding), unless that data is contained within an `UnsafeCell`. * Invoking undefined behavior via compiler intrinsics: * Indexing outside of the bounds of an object with `std::ptr::offset` (`offset` intrinsic), with @@ -1034,9 +1042,13 @@ be undesired. * Exiting without calling destructors * Sending signals * Accessing/modifying the file system -* Unsigned integer overflow (well-defined as wrapping) -* Signed integer overflow (well-defined as two’s complement representation - wrapping) +* Integer overflow + - Overflow is considered "unexpected" behavior and is always user-error, + unless the `wrapping` primitives are used. In non-optimized builds, the compiler + will insert debug checks that panic on overflow, but in optimized builds overflow + instead results in wrapped values. See [RFC 560] for the rationale and more details. + +[RFC 560]: https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md #### Diverging functions @@ -1310,11 +1322,26 @@ type of the value is not required to ascribe to `Sync`. ### Traits -A _trait_ describes a set of method types. +A _trait_ describes an abstract interface that types can +implement. This interface consists of associated items, which come in +three varieties: -Traits can include default implementations of methods, written in terms of some -unknown [`self` type](#self-types); the `self` type may either be completely -unspecified, or constrained by some other trait. +- functions +- constants +- types + +Associated functions whose first parameter is named `self` are called +methods and may be invoked using `.` notation (e.g., `x.foo()`). + +All traits define an implicit type parameter `Self` that refers to +"the type that is implementing this interface". Traits may also +contain additional type parameters. These type parameters (including +`Self`) may be constrained by other traits and so forth as usual. + +Trait bounds on `Self` are considered "supertraits". These are +required to be acyclic. Supertraits are somewhat different from other +constraints in that they affect what methods are available in the +vtable when the trait is used as a [trait object](#trait-objects). Traits are implemented for specific types through separate [implementations](#implementations). @@ -1359,15 +1386,18 @@ fn draw_twice(surface: Surface, sh: T) { } ``` -Traits also define an [trait object](#trait-objects) with the same name as the -trait. Values of this type are created by [casting](#type-cast-expressions) -pointer values (pointing to a type for which an implementation of the given -trait is in scope) to pointers to the trait name, used as a type. +Traits also define an [trait object](#trait-objects) with the same +name as the trait. Values of this type are created by coercing from a +pointer of some specific type to a pointer of trait type. For example, +`&T` could be coerced to `&Shape` if `T: Shape` holds (and similarly +for `Box`). This coercion can either be implicit or +[explicit](#type-cast-expressions). Here is an example of an explicit +coercion: ``` -# trait Shape { fn dummy(&self) { } } -# impl Shape for i32 { } -# let mycircle = 0i32; +trait Shape { } +impl Shape for i32 { } +let mycircle = 0i32; let myshape: Box = Box::new(mycircle) as Box; ``` @@ -2041,7 +2071,8 @@ The name `str_eq` has a special meaning to the Rust compiler, and the presence of this definition means that it will use this definition when generating calls to the string equality function. -A complete list of the built-in language items will be added in the future. +The set of language items is currently considered unstable. A complete +list of the built-in language items will be added in the future. ### Inline attributes @@ -2053,11 +2084,6 @@ The compiler automatically inlines functions based on internal heuristics. Incorrectly inlining functions can actually make the program slower, so it should be used with care. -Immutable statics are always considered inlineable unless marked with -`#[inline(never)]`. It is undefined whether two different inlineable statics -have the same memory address. In other words, the compiler is free to collapse -duplicate inlineable statics together. - `#[inline]` and `#[inline(always)]` always cause the function to be serialized into the crate metadata to allow cross-crate inlining. @@ -2259,10 +2285,6 @@ The currently implemented features of the reference compiler are: * `unboxed_closures` - Rust's new closure design, which is currently a work in progress feature with many known bugs. -* `unsafe_destructor` - Allows use of the `#[unsafe_destructor]` attribute, - which is considered wildly unsafe and will be - obsoleted by language improvements. - * `unsafe_no_drop_flag` - Allows use of the `#[unsafe_no_drop_flag]` attribute, which removes hidden flag added to a type that implements the `Drop` trait. The design for the @@ -2382,18 +2404,54 @@ expressions](#index-expressions) (`expr[expr]`), and [field references](#field-expressions) (`expr.f`). All other expressions are rvalues. The left operand of an [assignment](#assignment-expressions) or -[compound-assignment](#compound-assignment-expressions) expression is an lvalue -context, as is the single operand of a unary -[borrow](#unary-operator-expressions). All other expression contexts are -rvalue contexts. +[compound-assignment](#compound-assignment-expressions) expression is +an lvalue context, as is the single operand of a unary +[borrow](#unary-operator-expressions). The discriminant or subject of +a [match expression](#match-expressions) may be an lvalue context, if +ref bindings are made, but is otherwise an rvalue context. All other +expression contexts are rvalue contexts. When an lvalue is evaluated in an _lvalue context_, it denotes a memory location; when evaluated in an _rvalue context_, it denotes the value held _in_ that memory location. -When an rvalue is used in an lvalue context, a temporary un-named lvalue is -created and used instead. A temporary's lifetime equals the largest lifetime -of any reference that points to it. +##### Temporary lifetimes + +When an rvalue is used in an lvalue context, a temporary un-named +lvalue is created and used instead. The lifetime of temporary values +is typically the innermost enclosing statement; the tail expression of +a block is considered part of the statement that encloses the block. + +When a temporary rvalue is being created that is assigned into a `let` +declaration, however, the temporary is created with the lifetime of +the enclosing block instead, as using the enclosing statement (the +`let` declaration) would be a guaranteed error (since a pointer to the +temporary would be stored into a variable, but the temporary would be +freed before the variable could be used). The compiler uses simple +syntactic rules to decide which values are being assigned into a `let` +binding, and therefore deserve a longer temporary lifetime. + +Here are some examples: + +- `let x = foo(&temp())`. The expression `temp()` is an rvalue. As it + is being borrowed, a temporary is created which will be freed after + the innermost enclosing statement (the `let` declaration, in this case). +- `let x = temp().foo()`. This is the same as the previous example, + except that the value of `temp()` is being borrowed via autoref on a + method-call. Here we are assuming that `foo()` is an `&self` method + defined in some trait, say `Foo`. In other words, the expression + `temp().foo()` is equivalent to `Foo::foo(&temp())`. +- `let x = &temp()`. Here, the same temporary is being assigned into + `x`, rather than being passed as a parameter, and hence the + temporary's lifetime is considered to be the enclosing block. +- `let x = SomeStruct { foo: &temp() }`. As in the previous case, the + temporary is assigned into a struct which is then assigned into a + binding, and hence it is given the lifetime of the enclosing block. +- `let x = [ &temp() ]`. As in the previous case, the + temporary is assigned into an array which is then assigned into a + binding, and hence it is given the lifetime of the enclosing block. +- `let ref x = temp()`. In this case, the temporary is created using a ref binding, + but the result is the same: the lifetime is extended to the enclosing block. #### Moved and copied types @@ -2535,8 +2593,10 @@ A field access is an [lvalue](#lvalues,-rvalues-and-temporaries) referring to the value of that field. When the type providing the field inherits mutability, it can be [assigned](#assignment-expressions) to. -Also, if the type of the expression to the left of the dot is a pointer, it is -automatically dereferenced to make the field access possible. +Also, if the type of the expression to the left of the dot is a +pointer, it is automatically dereferenced as many times as necessary +to make the field access possible. In cases of ambiguity, we prefer +fewer autoderefs to more. ### Array expressions @@ -2577,6 +2637,11 @@ let arr = ["a", "b"]; arr[10]; // panics ``` +Also, if the type of the expression to the left of the brackets is a +pointer, it is automatically dereferenced as many times as necessary +to make the indexing possible. In cases of ambiguity, we prefer fewer +autoderefs to more. + ### Range expressions The `..` operator will construct an object of one of the `std::ops::Range` variants. @@ -2599,7 +2664,7 @@ assert_eq!(x,y); ### Unary operator expressions -Rust defines three unary operators. They are all written as prefix operators, +Rust defines the following unary operators. They are all written as prefix operators, before the expression they apply to. * `-` @@ -2613,11 +2678,20 @@ before the expression they apply to. implemented by the type and required for an outer expression that will or could mutate the dereference), and produces the result of dereferencing the `&` or `&mut` borrowed pointer returned from the overload method. - * `!` : Logical negation. On the boolean type, this flips between `true` and `false`. On integer types, this inverts the individual bits in the two's complement representation of the value. +* `&` and `&mut` + : Borrowing. When applied to an lvalue, these operators produce a + reference (pointer) to the lvalue. The lvalue is also placed into + a borrowed state for the duration of the reference. For a shared + borrow (`&`), this implies that the lvalue may not be mutated, but + it may be read or shared again. For a mutable borrow (`&mut`), the + lvalue may not be accessed in any way until the borrow expires. + If the `&` or `&mut` operators are applied to an rvalue, a + temporary value is created; the lifetime of this temporary value + is defined by [syntactic rules](#temporary-lifetimes). ### Binary operator expressions @@ -2727,6 +2801,13 @@ fn avg(v: &[f64]) -> f64 { } ``` +Some of the conversions which can be done through the `as` operator +can also be done implicitly at various points in the program, such as +argument passing and assignment to a `let` binding with an explicit +type. Implicit conversions are limited to "harmless" conversions that +do not lose information and which have minimal or no risk of +surprising side-effects on the dynamic execution semantics. + #### Assignment expressions An _assignment expression_ consists of an @@ -3348,6 +3429,22 @@ let bo: Binop = add; x = bo(5,7); ``` +#### Function types for specific items + +Internally to the compiler, there are also function types that are specific to a particular +function item. In the following snippet, for example, the internal types of the functions +`foo` and `bar` are different, despite the fact that they have the same signature: + +``` +fn foo() { } +fn bar() { } +``` + +The types of `foo` and `bar` can both be implicitly coerced to the fn +pointer type `fn()`. There is currently no syntax for unique fn types, +though the compiler will emit a type like `fn() {foo}` in error +messages to indicate "the unique fn type for the function `foo`". + ### Closure types A [lambda expression](#lambda-expressions) produces a closure value with @@ -3432,8 +3529,9 @@ has type `Vec`, a vector with element type `A`. ### Self types -The special type `self` has a meaning within methods inside an impl item. It -refers to the type of the implicit `self` argument. For example, in: +The special type `Self` has a meaning within traits and impls. In a trait definition, it refers +to an implicit type parameter representing the "implementing" type. In an impl, +it is an alias for the implementing type. For example, in: ``` trait Printable { @@ -3447,8 +3545,9 @@ impl Printable for String { } ``` -`self` refers to the value of type `String` that is the receiver for a call to -the method `make_string`. +The notation `&self` is a shorthand for `self: &Self`. In this case, +in the impl, `Self` refers to the value of type `String` that is the +receiver for a call to the method `make_string`. # Special traits