From 65147b673bcf8cc740d40209321f0716864a0ab3 Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Thu, 19 Jan 2017 18:09:23 -0500 Subject: [PATCH 1/9] Update nomicon to describe `#[may_dangle]` --- src/doc/nomicon/dropck.md | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/doc/nomicon/dropck.md b/src/doc/nomicon/dropck.md index f54933827b330..6114006cbb341 100644 --- a/src/doc/nomicon/dropck.md +++ b/src/doc/nomicon/dropck.md @@ -199,24 +199,42 @@ assert (unsafely) that a generic type's destructor is *guaranteed* to not access any expired data, even if its type gives it the capability to do so. -That attribute is called `unsafe_destructor_blind_to_params`. +That attribute is called `may_dangle` and was introduced in [RFC 1327] +(https://github.com/rust-lang/rfcs/blob/master/text/1327-dropck-param-eyepatch.md). To deploy it on the Inspector example from above, we would write: ```rust,ignore struct Inspector<'a>(&'a u8, &'static str); -impl<'a> Drop for Inspector<'a> { - #[unsafe_destructor_blind_to_params] +unsafe impl<#[may_dangle] 'a> Drop for Inspector<'a> { fn drop(&mut self) { println!("Inspector(_, {}) knows when *not* to inspect.", self.1); } } ``` -This attribute has the word `unsafe` in it because the compiler is not -checking the implicit assertion that no potentially expired data +Use of this attribute requires the `Drop` impl to be marked `unsafe` because the +compiler is not checking the implicit assertion that no potentially expired data (e.g. `self.0` above) is accessed. +The attribute can be applied to any number of lifetime and type parameters. In +the following example, we assert that we access no data behind a reference of +lifetime `'b` and that the only uses of `T` will be moves or drops, but omit +the attribute from `'a` and `U`, because we do access data with that lifetime +and that type: + +```rust,ignore +use std::fmt::Display; + +struct Inspector<'a, 'b, T, U: Display>(&'a u8, &'b u8, T, U); + +unsafe impl<'a, #[may_dangle] 'b, #[may_dangle] T, U: Display> Drop for Inspector<'a, 'b, T, U> { + fn drop(&mut self) { + println!("Inspector({}, _, _, {})", self.0, self.3); + } +} +``` + It is sometimes obvious that no such access can occur, like the case above. However, when dealing with a generic type parameter, such access can occur indirectly. Examples of such indirect access are: @@ -263,7 +281,7 @@ some other method invoked by the destructor, rather than being written directly within it. In all of the above cases where the `&'a u8` is accessed in the -destructor, adding the `#[unsafe_destructor_blind_to_params]` +destructor, adding the `#[may_dangle]` attribute makes the type vulnerable to misuse that the borrower checker will not catch, inviting havoc. It is better to avoid adding the attribute. From b996a7ecec4bb22a28bce3b86f68fe51b4409287 Mon Sep 17 00:00:00 2001 From: Freyskeyd Date: Wed, 4 Jan 2017 16:02:34 +0100 Subject: [PATCH 2/9] Fix doc cfg(test) and tests directory Signed-off-by: Freyskeyd --- src/doc/book/testing.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/doc/book/testing.md b/src/doc/book/testing.md index 96cec7295aa9d..6fefa1c9f1e1c 100644 --- a/src/doc/book/testing.md +++ b/src/doc/book/testing.md @@ -499,6 +499,10 @@ be imported in every test with `mod common;` That's all there is to the `tests` directory. The `tests` module isn't needed here, since the whole thing is focused on tests. +Note, when building integration tests, cargo will not pass the `test` attribute +to the compiler. It means that all parts in `cfg(test)` won't be included in +the build used in your integration tests. + Let's finally check out that third section: documentation tests. # Documentation tests From 1363cdaec9984269fc421cbc910f1f520b669f21 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Thu, 26 Jan 2017 17:51:10 +0200 Subject: [PATCH 3/9] Remove unnecessary LLVMRustPersonalityFn binding LLVM Core C bindings provide this function for all the versions back to what we support (3.7), and helps to avoid this unnecessary builder->function transition every time. Also a negative diff. --- src/librustc_llvm/ffi.rs | 2 +- src/librustc_trans/builder.rs | 2 +- src/librustc_trans/mir/mod.rs | 4 +++- src/rustllvm/RustWrapper.cpp | 8 -------- 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index caa27404086b9..58b2017ceb66e 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -804,7 +804,7 @@ extern "C" { Name: *const c_char) -> ValueRef; pub fn LLVMRustAddHandler(CatchSwitch: ValueRef, Handler: BasicBlockRef); - pub fn LLVMRustSetPersonalityFn(B: BuilderRef, Pers: ValueRef); + pub fn LLVMSetPersonalityFn(Func: ValueRef, Pers: ValueRef); // Add a case to the switch instruction pub fn LLVMAddCase(Switch: ValueRef, OnVal: ValueRef, Dest: BasicBlockRef); diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs index cf7f3e9501d1a..c113716ca5c74 100644 --- a/src/librustc_trans/builder.rs +++ b/src/librustc_trans/builder.rs @@ -1107,7 +1107,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub fn set_personality_fn(&self, personality: ValueRef) { unsafe { - llvm::LLVMRustSetPersonalityFn(self.llbuilder, personality); + llvm::LLVMSetPersonalityFn(self.llfn(), personality); } } diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index eedd7956805b6..30c138310da9c 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -319,7 +319,9 @@ pub fn trans_mir<'a, 'tcx: 'a>( mircx.cleanup_kinds.iter_enumerated().map(|(bb, cleanup_kind)| { if let CleanupKind::Funclet = *cleanup_kind { let bcx = mircx.get_builder(bb); - bcx.set_personality_fn(mircx.ccx.eh_personality()); + unsafe { + llvm::LLVMSetPersonalityFn(mircx.llfn, mircx.ccx.eh_personality()); + } if base::wants_msvc_seh(ccx.sess()) { return Some(Funclet::new(bcx.cleanup_pad(None, &[]))); } diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index bd0ff9e8d83cc..34ee7d552f346 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -1082,14 +1082,6 @@ extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef, #endif } -extern "C" void LLVMRustSetPersonalityFn(LLVMBuilderRef B, - LLVMValueRef Personality) { -#if LLVM_VERSION_GE(3, 8) - unwrap(B)->GetInsertBlock()->getParent()->setPersonalityFn( - cast(unwrap(Personality))); -#endif -} - #if LLVM_VERSION_GE(3, 8) extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name, LLVMValueRef *Inputs, From 95227a4dc16b90994e6b39271a75363ff0f05bb3 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Sat, 28 Jan 2017 14:37:50 -0700 Subject: [PATCH 4/9] Remove ToPrimitive trait. It is no longer used. --- src/librustc/lib.rs | 1 - src/librustc/util/num.rs | 98 ---------------------------------------- 2 files changed, 99 deletions(-) delete mode 100644 src/librustc/util/num.rs diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 0ff9626ae11a8..855f4a8197e35 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -109,7 +109,6 @@ pub mod util { pub mod common; pub mod ppaux; pub mod nodemap; - pub mod num; pub mod fs; } diff --git a/src/librustc/util/num.rs b/src/librustc/util/num.rs deleted file mode 100644 index da04976a96a37..0000000000000 --- a/src/librustc/util/num.rs +++ /dev/null @@ -1,98 +0,0 @@ -// 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 ToPrimitive { - fn to_i8(&self) -> Option; - fn to_i16(&self) -> Option; - fn to_i32(&self) -> Option; - fn to_i64(&self) -> Option; - fn to_u8(&self) -> Option; - fn to_u16(&self) -> Option; - fn to_u32(&self) -> Option; - fn to_u64(&self) -> Option; -} - -impl ToPrimitive for i64 { - fn to_i8(&self) -> Option { - if *self < i8::min_value() as i64 || *self > i8::max_value() as i64 { - None - } else { - Some(*self as i8) - } - } - fn to_i16(&self) -> Option { - if *self < i16::min_value() as i64 || *self > i16::max_value() as i64 { - None - } else { - Some(*self as i16) - } - } - fn to_i32(&self) -> Option { - if *self < i32::min_value() as i64 || *self > i32::max_value() as i64 { - None - } else { - Some(*self as i32) - } - } - fn to_i64(&self) -> Option { - Some(*self) - } - fn to_u8(&self) -> Option { - if *self < 0 || *self > u8::max_value() as i64 { - None - } else { - Some(*self as u8) - } - } - fn to_u16(&self) -> Option { - if *self < 0 || *self > u16::max_value() as i64 { - None - } else { - Some(*self as u16) - } - } - fn to_u32(&self) -> Option { - if *self < 0 || *self > u32::max_value() as i64 { - None - } else { - Some(*self as u32) - } - } - fn to_u64(&self) -> Option { - if *self < 0 {None} else {Some(*self as u64)} - } -} - -impl ToPrimitive for u64 { - fn to_i8(&self) -> Option { - if *self > i8::max_value() as u64 {None} else {Some(*self as i8)} - } - fn to_i16(&self) -> Option { - if *self > i16::max_value() as u64 {None} else {Some(*self as i16)} - } - fn to_i32(&self) -> Option { - if *self > i32::max_value() as u64 {None} else {Some(*self as i32)} - } - fn to_i64(&self) -> Option { - if *self > i64::max_value() as u64 {None} else {Some(*self as i64)} - } - fn to_u8(&self) -> Option { - if *self > u8::max_value() as u64 {None} else {Some(*self as u8)} - } - fn to_u16(&self) -> Option { - if *self > u16::max_value() as u64 {None} else {Some(*self as u16)} - } - fn to_u32(&self) -> Option { - if *self > u32::max_value() as u64 {None} else {Some(*self as u32)} - } - fn to_u64(&self) -> Option { - Some(*self) - } -} From d880bbb35ff19a6e7c257eae6ef7c48df5eda9e6 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Sun, 29 Jan 2017 08:17:34 +0200 Subject: [PATCH 5/9] Remove the workaround for gh32959 This workaround is no longer necessary as Rust, and by extension MIR, now support uninhabited type properly. This removes the workaround for the gh32959 that was introduced in gh33267. Fixes #32959 --- src/librustc_mir/build/block.rs | 5 +---- src/librustc_mir/build/expr/into.rs | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index 73d3875ba2384..121d592da0316 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -16,8 +16,6 @@ use rustc::hir; impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn ast_block(&mut self, destination: &Lvalue<'tcx>, - // FIXME(#32959): temporary measure for the issue - dest_is_unit: bool, mut block: BasicBlock, ast_block: &'tcx hir::Block) -> BlockAnd<()> { @@ -83,8 +81,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // of the block. if let Some(expr) = expr { unpack!(block = this.into(destination, block, expr)); - } else if dest_is_unit { - // FIXME(#31472) + } else { let source_info = this.source_info(span); this.cfg.push_assign_unit(block, source_info, destination); } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 24b9c955658fd..3d4af259ec9f7 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -40,7 +40,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { this.in_scope(extent, block, |this| this.into(destination, block, value)) } ExprKind::Block { body: ast_block } => { - this.ast_block(destination, expr.ty.is_nil(), block, ast_block) + this.ast_block(destination, block, ast_block) } ExprKind::Match { discriminant, arms } => { this.match_expr(destination, expr_span, block, discriminant, arms) From fe324cea6490fc6e7ce16fb5209fde57cfa1b94f Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Tue, 31 Jan 2017 00:57:52 +0100 Subject: [PATCH 6/9] rustdoc: mark ffi functions with unsafety icon --- src/librustdoc/html/render.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 52257653405e0..40eb7e5ab78c3 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1806,12 +1806,13 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, String::new() }; - let mut unsafety_flag = ""; - if let clean::FunctionItem(ref func) = myitem.inner { - if func.unsafety == hir::Unsafety::Unsafe { - unsafety_flag = ""; + let unsafety_flag = match myitem.inner { + clean::FunctionItem(ref func) | clean::ForeignFunctionItem(ref func) + if func.unsafety == hir::Unsafety::Unsafe => { + "" } - } + _ => "", + }; let doc_value = myitem.doc_value().unwrap_or(""); write!(w, " From d73e84d2e7a7733d507ed7a3a44af4ab7941ce88 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 31 Jan 2017 14:45:08 +0100 Subject: [PATCH 7/9] use suggestions instead of helps with code in them --- src/librustc_const_eval/eval.rs | 2 -- src/libsyntax/parse/parser.rs | 27 ++++++++++++++++++--- src/test/compile-fail/missing-block-hint.rs | 3 ++- src/test/parse-fail/tuple-float-index.rs | 3 ++- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index a9dcb1ed89613..47a98155fc4b0 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//#![allow(non_camel_case_types)] - use rustc::middle::const_val::ConstVal::*; use rustc::middle::const_val::ConstVal; use self::ErrKind::*; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 3480db8ec3b7d..2532a1def7dda 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2456,9 +2456,21 @@ impl<'a> Parser<'a> { Some(f) => f, None => continue, }; - err.help(&format!("try parenthesizing the first index; e.g., `(foo.{}){}`", - float.trunc() as usize, - format!(".{}", fstr.splitn(2, ".").last().unwrap()))); + let sugg = pprust::to_string(|s| { + use print::pprust::PrintState; + use print::pp::word; + s.popen()?; + s.print_expr(&e)?; + word(&mut s.s, ".")?; + s.print_usize(float.trunc() as usize)?; + s.pclose()?; + word(&mut s.s, ".")?; + word(&mut s.s, fstr.splitn(2, ".").last().unwrap()) + }); + err.span_suggestion( + prev_span, + "try parenthesizing the first index", + sugg); } return Err(err); @@ -3900,7 +3912,14 @@ impl<'a> Parser<'a> { if self.eat(&token::Semi) { stmt_span.hi = self.prev_span.hi; } - e.span_help(stmt_span, "try placing this code inside a block"); + let sugg = pprust::to_string(|s| { + use print::pprust::{PrintState, INDENT_UNIT}; + s.ibox(INDENT_UNIT)?; + s.bopen()?; + s.print_stmt(&stmt)?; + s.bclose_maybe_open(stmt.span, INDENT_UNIT, false) + }); + e.span_suggestion(stmt_span, "try placing this code inside a block", sugg); } Err(mut e) => { self.recover_stmt_(SemiColonMode::Break); diff --git a/src/test/compile-fail/missing-block-hint.rs b/src/test/compile-fail/missing-block-hint.rs index 1f29ff4e05c09..6a140e6f21c19 100644 --- a/src/test/compile-fail/missing-block-hint.rs +++ b/src/test/compile-fail/missing-block-hint.rs @@ -15,6 +15,7 @@ fn main() { { if (foo) bar; //~ ERROR expected `{`, found `bar` - //^ HELP try placing this code inside a block + //~^ HELP try placing this code inside a block + //~| SUGGESTION { bar; } } } diff --git a/src/test/parse-fail/tuple-float-index.rs b/src/test/parse-fail/tuple-float-index.rs index f3f5e35634682..57ad89ad37404 100644 --- a/src/test/parse-fail/tuple-float-index.rs +++ b/src/test/parse-fail/tuple-float-index.rs @@ -12,5 +12,6 @@ fn main () { (1, (2, 3)).1.1; //~ ERROR unexpected token - //~^ HELP try parenthesizing the first index; e.g., `(foo.1).1` + //~^ HELP try parenthesizing the first index + //~| SUGGESTION ((1, (2, 3)).1).1 } From 4b52600b152a2220dca847046962a6f37a773378 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Tue, 31 Jan 2017 13:19:03 -0500 Subject: [PATCH 8/9] update mailmap for @pliniker --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index c44c486831acc..1ae0aae2d01ba 100644 --- a/.mailmap +++ b/.mailmap @@ -167,6 +167,7 @@ Ožbolt Menegatti gareins Paul Faria Peer Aramillo Irizar parir Peter Elmers +Peter Liniker Peter Zotov Phil Dawes Phil Dawes Philipp Brüschweiler From 4a07e722c01962aa814f2ae0915dfa84cd4d732a Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Wed, 25 Jan 2017 13:11:15 -0600 Subject: [PATCH 9/9] In std:rc, clarify the lack of mutability inside an Rc Also, point to the example in Cell's docs for how to do it. --- src/liballoc/rc.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 010e378ef2f48..6108a06634bb8 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -17,9 +17,11 @@ //! pointer to the same value in the heap. When the last [`Rc`] pointer to a //! given value is destroyed, the pointed-to value is also destroyed. //! -//! Shared references in Rust disallow mutation by default, and `Rc` is no -//! exception. If you need to mutate through an [`Rc`], use [`Cell`] or -//! [`RefCell`]. +//! Shared references in Rust disallow mutation by default, and [`Rc`] +//! is no exception: you cannot obtain a mutable reference to +//! something inside an [`Rc`]. If you need mutability, put a [`Cell`] +//! or [`RefCell`] inside the [`Rc`]; see [an example of mutability +//! inside an Rc][mutability]. //! //! [`Rc`] uses non-atomic reference counting. This means that overhead is very //! low, but an [`Rc`] cannot be sent between threads, and consequently [`Rc`] @@ -214,6 +216,7 @@ //! [upgrade]: struct.Weak.html#method.upgrade //! [`None`]: ../../std/option/enum.Option.html#variant.None //! [assoc]: ../../book/method-syntax.html#associated-functions +//! [mutability]: ../../std/cell/index.html#introducing-mutability-inside-of-something-immutable #![stable(feature = "rust1", since = "1.0.0")]