Skip to content

Commit

Permalink
Auto merge of #66640 - Centril:rollup-862009l, r=Centril
Browse files Browse the repository at this point in the history
Rollup of 8 pull requests

Successful merges:

 - #66183 (*Syntactically* permit visibilities on trait items & enum variants)
 - #66566 (Document pitfall with `impl PartialEq<B> for A`)
 - #66575 (Remove pretty printing of specific nodes in AST)
 - #66587 (Handle statics in MIR as const pointers)
 - #66619 (follow the convention in this file to use third-person singular verbs)
 - #66633 (Error code's long explanation cleanup)
 - #66637 (fix reoccuring typo: dereferencable -> dereferenceable)
 - #66639 (resolve: more declarative `fresh_binding`)

Failed merges:

r? @ghost
  • Loading branch information
bors committed Nov 22, 2019
2 parents 5fa0af2 + 56512b9 commit a449535
Show file tree
Hide file tree
Showing 86 changed files with 779 additions and 778 deletions.
32 changes: 18 additions & 14 deletions src/libcore/cmp.rs
Expand Up @@ -135,17 +135,23 @@ use self::Ordering::*;
/// By changing `impl PartialEq for Book` to `impl PartialEq<BookFormat> for Book`,
/// we allow `BookFormat`s to be compared with `Book`s.
///
/// You can also combine these implementations to let the `==` operator work with
/// two different types:
///
/// ```
/// A comparison like the one above, which ignores some fields of the struct,
/// can be dangerous. It can easily lead to an unintended violation of the
/// requirements for a partial equivalence relation. For example, if we kept
/// the above implementation of `PartialEq<Book>` for `BookFormat` and added an
/// implementation of `PartialEq<Book>` for `Book` (either via a `#[derive]` or
/// via the manual implementation from the first example) then the result would
/// violate transitivity:
///
/// ```should_panic
/// #[derive(PartialEq)]
/// enum BookFormat {
/// Paperback,
/// Hardback,
/// Ebook,
/// }
///
/// #[derive(PartialEq)]
/// struct Book {
/// isbn: i32,
/// format: BookFormat,
Expand All @@ -163,18 +169,16 @@ use self::Ordering::*;
/// }
/// }
///
/// impl PartialEq for Book {
/// fn eq(&self, other: &Book) -> bool {
/// self.isbn == other.isbn
/// }
/// }
/// fn main() {
/// let b1 = Book { isbn: 1, format: BookFormat::Paperback };
/// let b2 = Book { isbn: 2, format: BookFormat::Paperback };
///
/// let b1 = Book { isbn: 3, format: BookFormat::Paperback };
/// let b2 = Book { isbn: 3, format: BookFormat::Ebook };
/// assert!(b1 == BookFormat::Paperback);
/// assert!(BookFormat::Paperback == b2);
///
/// assert!(b1 == BookFormat::Paperback);
/// assert!(BookFormat::Ebook != b1);
/// assert!(b1 == b2);
/// // The following should hold by transitivity but doesn't.
/// assert!(b1 == b2); // <-- PANICS
/// }
/// ```
///
/// # Examples
Expand Down
4 changes: 2 additions & 2 deletions src/libcore/iter/traits/iterator.rs
Expand Up @@ -1255,7 +1255,7 @@ pub trait Iterator {
Fuse::new(self)
}

/// Do something with each element of an iterator, passing the value on.
/// Does something with each element of an iterator, passing the value on.
///
/// When using iterators, you'll often chain several of them together.
/// While working on such code, you might want to check out what's
Expand Down Expand Up @@ -1548,7 +1548,7 @@ pub trait Iterator {
(left, right)
}

/// Reorder the elements of this iterator *in-place* according to the given predicate,
/// Reorders the elements of this iterator *in-place* according to the given predicate,
/// such that all those that return `true` precede all those that return `false`.
/// Returns the number of `true` elements found.
///
Expand Down
105 changes: 82 additions & 23 deletions src/librustc/mir/mod.rs
Expand Up @@ -7,7 +7,7 @@
use crate::hir::def::{CtorKind, Namespace};
use crate::hir::def_id::DefId;
use crate::hir;
use crate::mir::interpret::{PanicInfo, Scalar};
use crate::mir::interpret::{GlobalAlloc, PanicInfo, Scalar};
use crate::mir::visit::MirVisitable;
use crate::ty::adjustment::PointerCast;
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
Expand Down Expand Up @@ -292,7 +292,7 @@ impl<'tcx> Body<'tcx> {
pub fn temps_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
(self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
let local = Local::new(index);
if self.local_decls[local].is_user_variable.is_some() {
if self.local_decls[local].is_user_variable() {
None
} else {
Some(local)
Expand All @@ -305,7 +305,7 @@ impl<'tcx> Body<'tcx> {
pub fn vars_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
(self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
let local = Local::new(index);
if self.local_decls[local].is_user_variable.is_some() {
if self.local_decls[local].is_user_variable() {
Some(local)
} else {
None
Expand All @@ -319,7 +319,7 @@ impl<'tcx> Body<'tcx> {
(self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
let local = Local::new(index);
let decl = &self.local_decls[local];
if decl.is_user_variable.is_some() && decl.mutability == Mutability::Mut {
if decl.is_user_variable() && decl.mutability == Mutability::Mut {
Some(local)
} else {
None
Expand All @@ -333,7 +333,7 @@ impl<'tcx> Body<'tcx> {
(1..self.local_decls.len()).filter_map(move |index| {
let local = Local::new(index);
let decl = &self.local_decls[local];
if (decl.is_user_variable.is_some() || index < self.arg_count + 1)
if (decl.is_user_variable() || index < self.arg_count + 1)
&& decl.mutability == Mutability::Mut
{
Some(local)
Expand Down Expand Up @@ -689,14 +689,8 @@ pub struct LocalDecl<'tcx> {
/// Temporaries and the return place are always mutable.
pub mutability: Mutability,

/// `Some(binding_mode)` if this corresponds to a user-declared local variable.
///
/// This is solely used for local diagnostics when generating
/// warnings/errors when compiling the current crate, and
/// therefore it need not be visible across crates. pnkfelix
/// currently hypothesized we *need* to wrap this in a
/// `ClearCrossCrate` as long as it carries as `HirId`.
pub is_user_variable: Option<ClearCrossCrate<BindingForm<'tcx>>>,
// FIXME(matthewjasper) Don't store in this in `Body`
pub local_info: LocalInfo<'tcx>,

/// `true` if this is an internal local.
///
Expand All @@ -721,6 +715,7 @@ pub struct LocalDecl<'tcx> {
/// then it is a temporary created for evaluation of some
/// subexpression of some block's tail expression (with no
/// intervening statement context).
// FIXME(matthewjasper) Don't store in this in `Body`
pub is_block_tail: Option<BlockTailInfo>,

/// The type of this local.
Expand All @@ -730,6 +725,7 @@ pub struct LocalDecl<'tcx> {
/// e.g., via `let x: T`, then we carry that type here. The MIR
/// borrow checker needs this information since it can affect
/// region inference.
// FIXME(matthewjasper) Don't store in this in `Body`
pub user_ty: UserTypeProjections,

/// The name of the local, used in debuginfo and pretty-printing.
Expand Down Expand Up @@ -824,6 +820,21 @@ pub struct LocalDecl<'tcx> {
pub visibility_scope: SourceScope,
}

/// Extra information about a local that's used for diagnostics.
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
pub enum LocalInfo<'tcx> {
/// A user-defined local variable or function parameter
///
/// The `BindingForm` is solely used for local diagnostics when generating
/// warnings/errors when compiling the current crate, and therefore it need
/// not be visible across crates.
User(ClearCrossCrate<BindingForm<'tcx>>),
/// A temporary created that references the static with the given `DefId`.
StaticRef { def_id: DefId, is_thread_local: bool },
/// Any other temporary, the return place, or an anonymous function parameter.
Other,
}

impl<'tcx> LocalDecl<'tcx> {
/// Returns `true` only if local is a binding that can itself be
/// made mutable via the addition of the `mut` keyword, namely
Expand All @@ -832,15 +843,17 @@ impl<'tcx> LocalDecl<'tcx> {
/// - `let x = ...`,
/// - or `match ... { C(x) => ... }`
pub fn can_be_made_mutable(&self) -> bool {
match self.is_user_variable {
Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
match self.local_info {
LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
binding_mode: ty::BindingMode::BindByValue(_),
opt_ty_info: _,
opt_match_place: _,
pat_span: _,
}))) => true,

Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf(ImplicitSelfKind::Imm))) => true,
LocalInfo::User(
ClearCrossCrate::Set(BindingForm::ImplicitSelf(ImplicitSelfKind::Imm)),
) => true,

_ => false,
}
Expand All @@ -850,26 +863,54 @@ impl<'tcx> LocalDecl<'tcx> {
/// `ref mut ident` binding. (Such bindings cannot be made into
/// mutable bindings, but the inverse does not necessarily hold).
pub fn is_nonref_binding(&self) -> bool {
match self.is_user_variable {
Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
match self.local_info {
LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
binding_mode: ty::BindingMode::BindByValue(_),
opt_ty_info: _,
opt_match_place: _,
pat_span: _,
}))) => true,

Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf(_))) => true,
LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(_))) => true,

_ => false,
}
}

/// Returns `true` if this variable is a named variable or function
/// parameter declared by the user.
#[inline]
pub fn is_user_variable(&self) -> bool {
match self.local_info {
LocalInfo::User(_) => true,
_ => false,
}
}

/// Returns `true` if this is a reference to a variable bound in a `match`
/// expression that is used to access said variable for the guard of the
/// match arm.
pub fn is_ref_for_guard(&self) -> bool {
match self.is_user_variable {
Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) => true,
match self.local_info {
LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard)) => true,
_ => false,
}
}

/// Returns `Some` if this is a reference to a static item that is used to
/// access that static
pub fn is_ref_to_static(&self) -> bool {
match self.local_info {
LocalInfo::StaticRef { .. } => true,
_ => false,
}
}

/// Returns `Some` if this is a reference to a static item that is used to
/// access that static
pub fn is_ref_to_thread_local(&self) -> bool {
match self.local_info {
LocalInfo::StaticRef { is_thread_local, .. } => is_thread_local,
_ => false,
}
}
Expand Down Expand Up @@ -918,7 +959,7 @@ impl<'tcx> LocalDecl<'tcx> {
source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE },
visibility_scope: OUTERMOST_SOURCE_SCOPE,
internal,
is_user_variable: None,
local_info: LocalInfo::Other,
is_block_tail: None,
}
}
Expand All @@ -937,7 +978,7 @@ impl<'tcx> LocalDecl<'tcx> {
internal: false,
is_block_tail: None,
name: None, // FIXME maybe we do want some name here?
is_user_variable: None,
local_info: LocalInfo::Other,
}
}
}
Expand Down Expand Up @@ -2341,6 +2382,24 @@ pub struct Constant<'tcx> {
pub literal: &'tcx ty::Const<'tcx>,
}

impl Constant<'tcx> {
pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
match self.literal.val.try_to_scalar() {
Some(Scalar::Ptr(ptr)) => match tcx.alloc_map.lock().get(ptr.alloc_id) {
Some(GlobalAlloc::Static(def_id)) => Some(def_id),
Some(_) => None,
None => {
tcx.sess.delay_span_bug(
DUMMY_SP, "MIR cannot contain dangling const pointers",
);
None
},
},
_ => None,
}
}
}

/// A collection of projections into user types.
///
/// They are projections because a binding can occur a part of a
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/mir/tcx.rs
Expand Up @@ -81,7 +81,7 @@ impl<'tcx> PlaceTy<'tcx> {
let ty = self.ty
.builtin_deref(true)
.unwrap_or_else(|| {
bug!("deref projection of non-dereferencable ty {:?}", self)
bug!("deref projection of non-dereferenceable ty {:?}", self)
})
.ty;
PlaceTy::from_ty(ty)
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/mir/visit.rs
Expand Up @@ -691,7 +691,7 @@ macro_rules! make_mir_visitor {
source_info,
visibility_scope,
internal: _,
is_user_variable: _,
local_info: _,
is_block_tail: _,
} = local_decl;

Expand Down

0 comments on commit a449535

Please sign in to comment.