Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 8 pull requests #66640

Merged
merged 27 commits into from
Nov 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9a88364
syntactically allow visibility on trait item & enum variant
Centril Nov 7, 2019
7ec20dd
Remove pretty printing of specific nodes in AST
Mark-Simulacrum Nov 20, 2019
a1d04cc
Remove statics from HAIR by lowering them to a pointer constant
oli-obk Oct 24, 2019
ae9677c
Readjust const qualification to detect statics again
spastorino Nov 11, 2019
3600695
Simplify pattern
spastorino Nov 11, 2019
47a3294
Readjust constant evaluation for operands
spastorino Nov 11, 2019
c6d97df
Fix rebase
matthewjasper Nov 18, 2019
9abc34e
Track pointers to statics in MIR
matthewjasper Nov 18, 2019
025630d
Bless remaining test output
matthewjasper Nov 19, 2019
bccc59a
Address review comments
matthewjasper Nov 21, 2019
5028fd8
Document pitfall with `impl PartialEq<B> for A`
robamler Nov 20, 2019
da5539c
follow the convention in this file to use third-person singular verbs
Nov 22, 2019
9ff91ab
fix reoccuring typo: dereferencable -> dereferenceable
RalfJung Nov 22, 2019
ea62c2e
Improve E0015 long error explanation
GuillaumeGomez Nov 22, 2019
60d9c2c
Improve E0023 long error explanation
GuillaumeGomez Nov 22, 2019
f798804
Improve E0057 long error explanation
GuillaumeGomez Nov 22, 2019
9bb2e3c
Improve E0061 long error explanation
GuillaumeGomez Nov 22, 2019
a8de11c
small error code explanations improvements
GuillaumeGomez Nov 22, 2019
94b7ea9
resolve: more declarative fresh_binding
Centril Nov 22, 2019
8cba0a9
Rollup merge of #66183 - Centril:empty-vis-trait-decl, r=petrochenkov
Centril Nov 22, 2019
afc78e1
Rollup merge of #66566 - robamler:issue-66476, r=rkruppe
Centril Nov 22, 2019
c66b508
Rollup merge of #66575 - Mark-Simulacrum:no-uii, r=petrochenkov
Centril Nov 22, 2019
3031720
Rollup merge of #66587 - matthewjasper:handle-static-as-const, r=oli-obk
Centril Nov 22, 2019
a699945
Rollup merge of #66619 - guanqun:use-third-person-singular-verb, r=Ce…
Centril Nov 22, 2019
8be9e90
Rollup merge of #66633 - GuillaumeGomez:err-codes-cleanup, r=Dylan-DPC
Centril Nov 22, 2019
fd3bd29
Rollup merge of #66637 - RalfJung:typo, r=Centril
Centril Nov 22, 2019
56512b9
Rollup merge of #66639 - Centril:simplify-fresh-binding, r=petrochenkov
Centril Nov 22, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 18 additions & 14 deletions src/libcore/cmp.rs
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Loading