Auto merge of #39470 - GuillaumeGomez:rollup, r=GuillaumeGomez

Rollup of 9 pull requests

- Successful merges: #38823, #39196, #39299, #39319, #39373, #39383, #39416, #39420, #39427
- Failed merges:
This commit is contained in:
bors 2017-02-02 21:58:10 +00:00
commit eedaa94e33
17 changed files with 75 additions and 137 deletions

View File

@ -167,6 +167,7 @@ Ožbolt Menegatti <ozbolt.menegatti@gmail.com> gareins <ozbolt.menegatti@gmail.c
Paul Faria <paul_faria@ultimatesoftware.com> Paul Faria <Nashenas88@gmail.com> Paul Faria <paul_faria@ultimatesoftware.com> Paul Faria <Nashenas88@gmail.com>
Peer Aramillo Irizar <peer.aramillo.irizar@gmail.com> parir <peer.aramillo.irizar@gmail.com> Peer Aramillo Irizar <peer.aramillo.irizar@gmail.com> parir <peer.aramillo.irizar@gmail.com>
Peter Elmers <peter.elmers@yahoo.com> <peter.elmers@rice.edu> Peter Elmers <peter.elmers@yahoo.com> <peter.elmers@rice.edu>
Peter Liniker <peter.liniker+github@gmail.com>
Peter Zotov <whitequark@whitequark.org> Peter Zotov <whitequark@whitequark.org>
Phil Dawes <phil@phildawes.net> Phil Dawes <pdawes@drw.com> Phil Dawes <phil@phildawes.net> Phil Dawes <pdawes@drw.com>
Philipp Brüschweiler <blei42@gmail.com> <blei42@gmail.com> Philipp Brüschweiler <blei42@gmail.com> <blei42@gmail.com>

View File

@ -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 That's all there is to the `tests` directory. The `tests` module isn't needed
here, since the whole thing is focused on tests. 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. Let's finally check out that third section: documentation tests.
# Documentation tests # Documentation tests

View File

@ -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 not access any expired data, even if its type gives it the capability
to do so. 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: To deploy it on the Inspector example from above, we would write:
```rust,ignore ```rust,ignore
struct Inspector<'a>(&'a u8, &'static str); struct Inspector<'a>(&'a u8, &'static str);
impl<'a> Drop for Inspector<'a> { unsafe impl<#[may_dangle] 'a> Drop for Inspector<'a> {
#[unsafe_destructor_blind_to_params]
fn drop(&mut self) { fn drop(&mut self) {
println!("Inspector(_, {}) knows when *not* to inspect.", self.1); println!("Inspector(_, {}) knows when *not* to inspect.", self.1);
} }
} }
``` ```
This attribute has the word `unsafe` in it because the compiler is not Use of this attribute requires the `Drop` impl to be marked `unsafe` because the
checking the implicit assertion that no potentially expired data compiler is not checking the implicit assertion that no potentially expired data
(e.g. `self.0` above) is accessed. (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. 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 However, when dealing with a generic type parameter, such access can
occur indirectly. Examples of such indirect access are: 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. directly within it.
In all of the above cases where the `&'a u8` is accessed in the 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 attribute makes the type vulnerable to misuse that the borrower
checker will not catch, inviting havoc. It is better to avoid adding checker will not catch, inviting havoc. It is better to avoid adding
the attribute. the attribute.

View File

@ -17,9 +17,11 @@
//! pointer to the same value in the heap. When the last [`Rc`] pointer to a //! 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. //! given value is destroyed, the pointed-to value is also destroyed.
//! //!
//! Shared references in Rust disallow mutation by default, and `Rc` is no //! Shared references in Rust disallow mutation by default, and [`Rc`]
//! exception. If you need to mutate through an [`Rc`], use [`Cell`] or //! is no exception: you cannot obtain a mutable reference to
//! [`RefCell`]. //! 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 //! [`Rc`] uses non-atomic reference counting. This means that overhead is very
//! low, but an [`Rc`] cannot be sent between threads, and consequently [`Rc`] //! low, but an [`Rc`] cannot be sent between threads, and consequently [`Rc`]
@ -214,6 +216,7 @@
//! [upgrade]: struct.Weak.html#method.upgrade //! [upgrade]: struct.Weak.html#method.upgrade
//! [`None`]: ../../std/option/enum.Option.html#variant.None //! [`None`]: ../../std/option/enum.Option.html#variant.None
//! [assoc]: ../../book/method-syntax.html#associated-functions //! [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")] #![stable(feature = "rust1", since = "1.0.0")]

View File

@ -109,7 +109,6 @@ pub mod util {
pub mod common; pub mod common;
pub mod ppaux; pub mod ppaux;
pub mod nodemap; pub mod nodemap;
pub mod num;
pub mod fs; pub mod fs;
} }

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<i8>;
fn to_i16(&self) -> Option<i16>;
fn to_i32(&self) -> Option<i32>;
fn to_i64(&self) -> Option<i64>;
fn to_u8(&self) -> Option<u8>;
fn to_u16(&self) -> Option<u16>;
fn to_u32(&self) -> Option<u32>;
fn to_u64(&self) -> Option<u64>;
}
impl ToPrimitive for i64 {
fn to_i8(&self) -> Option<i8> {
if *self < i8::min_value() as i64 || *self > i8::max_value() as i64 {
None
} else {
Some(*self as i8)
}
}
fn to_i16(&self) -> Option<i16> {
if *self < i16::min_value() as i64 || *self > i16::max_value() as i64 {
None
} else {
Some(*self as i16)
}
}
fn to_i32(&self) -> Option<i32> {
if *self < i32::min_value() as i64 || *self > i32::max_value() as i64 {
None
} else {
Some(*self as i32)
}
}
fn to_i64(&self) -> Option<i64> {
Some(*self)
}
fn to_u8(&self) -> Option<u8> {
if *self < 0 || *self > u8::max_value() as i64 {
None
} else {
Some(*self as u8)
}
}
fn to_u16(&self) -> Option<u16> {
if *self < 0 || *self > u16::max_value() as i64 {
None
} else {
Some(*self as u16)
}
}
fn to_u32(&self) -> Option<u32> {
if *self < 0 || *self > u32::max_value() as i64 {
None
} else {
Some(*self as u32)
}
}
fn to_u64(&self) -> Option<u64> {
if *self < 0 {None} else {Some(*self as u64)}
}
}
impl ToPrimitive for u64 {
fn to_i8(&self) -> Option<i8> {
if *self > i8::max_value() as u64 {None} else {Some(*self as i8)}
}
fn to_i16(&self) -> Option<i16> {
if *self > i16::max_value() as u64 {None} else {Some(*self as i16)}
}
fn to_i32(&self) -> Option<i32> {
if *self > i32::max_value() as u64 {None} else {Some(*self as i32)}
}
fn to_i64(&self) -> Option<i64> {
if *self > i64::max_value() as u64 {None} else {Some(*self as i64)}
}
fn to_u8(&self) -> Option<u8> {
if *self > u8::max_value() as u64 {None} else {Some(*self as u8)}
}
fn to_u16(&self) -> Option<u16> {
if *self > u16::max_value() as u64 {None} else {Some(*self as u16)}
}
fn to_u32(&self) -> Option<u32> {
if *self > u32::max_value() as u64 {None} else {Some(*self as u32)}
}
fn to_u64(&self) -> Option<u64> {
Some(*self)
}
}

View File

@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
//#![allow(non_camel_case_types)]
use rustc::middle::const_val::ConstVal::*; use rustc::middle::const_val::ConstVal::*;
use rustc::middle::const_val::ConstVal; use rustc::middle::const_val::ConstVal;
use self::ErrKind::*; use self::ErrKind::*;

View File

@ -804,7 +804,7 @@ extern "C" {
Name: *const c_char) Name: *const c_char)
-> ValueRef; -> ValueRef;
pub fn LLVMRustAddHandler(CatchSwitch: ValueRef, Handler: BasicBlockRef); 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 // Add a case to the switch instruction
pub fn LLVMAddCase(Switch: ValueRef, OnVal: ValueRef, Dest: BasicBlockRef); pub fn LLVMAddCase(Switch: ValueRef, OnVal: ValueRef, Dest: BasicBlockRef);

View File

@ -16,8 +16,6 @@ use rustc::hir;
impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
pub fn ast_block(&mut self, pub fn ast_block(&mut self,
destination: &Lvalue<'tcx>, destination: &Lvalue<'tcx>,
// FIXME(#32959): temporary measure for the issue
dest_is_unit: bool,
mut block: BasicBlock, mut block: BasicBlock,
ast_block: &'tcx hir::Block) ast_block: &'tcx hir::Block)
-> BlockAnd<()> { -> BlockAnd<()> {
@ -83,8 +81,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
// of the block. // of the block.
if let Some(expr) = expr { if let Some(expr) = expr {
unpack!(block = this.into(destination, block, expr)); unpack!(block = this.into(destination, block, expr));
} else if dest_is_unit { } else {
// FIXME(#31472)
let source_info = this.source_info(span); let source_info = this.source_info(span);
this.cfg.push_assign_unit(block, source_info, destination); this.cfg.push_assign_unit(block, source_info, destination);
} }

View File

@ -40,7 +40,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
this.in_scope(extent, block, |this| this.into(destination, block, value)) this.in_scope(extent, block, |this| this.into(destination, block, value))
} }
ExprKind::Block { body: ast_block } => { 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 } => { ExprKind::Match { discriminant, arms } => {
this.match_expr(destination, expr_span, block, discriminant, arms) this.match_expr(destination, expr_span, block, discriminant, arms)

View File

@ -1107,7 +1107,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
pub fn set_personality_fn(&self, personality: ValueRef) { pub fn set_personality_fn(&self, personality: ValueRef) {
unsafe { unsafe {
llvm::LLVMRustSetPersonalityFn(self.llbuilder, personality); llvm::LLVMSetPersonalityFn(self.llfn(), personality);
} }
} }

View File

@ -319,7 +319,9 @@ pub fn trans_mir<'a, 'tcx: 'a>(
mircx.cleanup_kinds.iter_enumerated().map(|(bb, cleanup_kind)| { mircx.cleanup_kinds.iter_enumerated().map(|(bb, cleanup_kind)| {
if let CleanupKind::Funclet = *cleanup_kind { if let CleanupKind::Funclet = *cleanup_kind {
let bcx = mircx.get_builder(bb); 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()) { if base::wants_msvc_seh(ccx.sess()) {
return Some(Funclet::new(bcx.cleanup_pad(None, &[]))); return Some(Funclet::new(bcx.cleanup_pad(None, &[])));
} }

View File

@ -1806,12 +1806,13 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
String::new() String::new()
}; };
let mut unsafety_flag = ""; let unsafety_flag = match myitem.inner {
if let clean::FunctionItem(ref func) = myitem.inner { clean::FunctionItem(ref func) | clean::ForeignFunctionItem(ref func)
if func.unsafety == hir::Unsafety::Unsafe { if func.unsafety == hir::Unsafety::Unsafe => {
unsafety_flag = "<a title='unsafe function' href='#'><sup>⚠</sup></a>"; "<a title='unsafe function' href='#'><sup>⚠</sup></a>"
} }
} _ => "",
};
let doc_value = myitem.doc_value().unwrap_or(""); let doc_value = myitem.doc_value().unwrap_or("");
write!(w, " write!(w, "

View File

@ -2456,9 +2456,21 @@ impl<'a> Parser<'a> {
Some(f) => f, Some(f) => f,
None => continue, None => continue,
}; };
err.help(&format!("try parenthesizing the first index; e.g., `(foo.{}){}`", let sugg = pprust::to_string(|s| {
float.trunc() as usize, use print::pprust::PrintState;
format!(".{}", fstr.splitn(2, ".").last().unwrap()))); 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); return Err(err);
@ -3900,7 +3912,14 @@ impl<'a> Parser<'a> {
if self.eat(&token::Semi) { if self.eat(&token::Semi) {
stmt_span.hi = self.prev_span.hi; 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) => { Err(mut e) => {
self.recover_stmt_(SemiColonMode::Break); self.recover_stmt_(SemiColonMode::Break);

View File

@ -1082,14 +1082,6 @@ extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
#endif #endif
} }
extern "C" void LLVMRustSetPersonalityFn(LLVMBuilderRef B,
LLVMValueRef Personality) {
#if LLVM_VERSION_GE(3, 8)
unwrap(B)->GetInsertBlock()->getParent()->setPersonalityFn(
cast<Function>(unwrap(Personality)));
#endif
}
#if LLVM_VERSION_GE(3, 8) #if LLVM_VERSION_GE(3, 8)
extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name, extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
LLVMValueRef *Inputs, LLVMValueRef *Inputs,

View File

@ -15,6 +15,7 @@ fn main() {
{ {
if (foo) if (foo)
bar; //~ ERROR expected `{`, found `bar` bar; //~ ERROR expected `{`, found `bar`
//^ HELP try placing this code inside a block //~^ HELP try placing this code inside a block
//~| SUGGESTION { bar; }
} }
} }

View File

@ -12,5 +12,6 @@
fn main () { fn main () {
(1, (2, 3)).1.1; //~ ERROR unexpected token (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
} }