Skip to content

Commit

Permalink
Auto merge of #72010 - Dylan-DPC:rollup-prdj0pk, r=Dylan-DPC
Browse files Browse the repository at this point in the history
Rollup of 6 pull requests

Successful merges:

 - #71989 (Use a single enum for the kind of a const context)
 - #71993 (Remove old `util/liveness.rs` module)
 - #71999 (Add myself to mailmap.)
 - #72001 (Adjust cfg(version) to lang team decision)
 - #72007 (Fix some tests failing in `--pass check` mode)
 - #72008 (Add const-generics test)

Failed merges:

r? @ghost
  • Loading branch information
bors committed May 8, 2020
2 parents a51e004 + 6789540 commit 7b80539
Show file tree
Hide file tree
Showing 24 changed files with 235 additions and 476 deletions.
1 change: 1 addition & 0 deletions .mailmap
Expand Up @@ -49,6 +49,7 @@ Carol (Nichols || Goulding) <carol.nichols@gmail.com> <193874+carols10cents@user
Carol (Nichols || Goulding) <carol.nichols@gmail.com> <carol.nichols@gmail.com>
Carol (Nichols || Goulding) <carol.nichols@gmail.com> <cnichols@thinkthroughmath.com>
Carol Willing <carolcode@willingconsulting.com>
Charles Lew <crlf0710@gmail.com> CrLF0710 <crlf0710@gmail.com>
Chris C Cerami <chrisccerami@users.noreply.github.com> Chris C Cerami <chrisccerami@gmail.com>
Chris Pressey <cpressey@gmail.com>
Chris Thorn <chris@thorn.co> Chris Thorn <thorn@thoughtbot.com>
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_attr/build.rs
@@ -1,4 +1,5 @@
fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-env-changed=CFG_VERSION");
println!("cargo:rerun-if-env-changed=CFG_RELEASE");
println!("cargo:rerun-if-env-changed=CFG_RELEASE_CHANNEL");
}
7 changes: 5 additions & 2 deletions src/librustc_attr/builtin.rs
Expand Up @@ -652,9 +652,12 @@ pub fn eval_condition(
return false;
}
};
let version = Version::parse(env!("CFG_VERSION")).unwrap();
let channel = env!("CFG_RELEASE_CHANNEL");
let nightly = channel == "nightly" || channel == "dev";
let rustc_version = Version::parse(env!("CFG_RELEASE")).unwrap();

version >= min_version
// See https://github.com/rust-lang/rust/issues/64796#issuecomment-625474439 for details
if nightly { rustc_version > min_version } else { rustc_version >= min_version }
}
ast::MetaItemKind::List(ref mis) => {
for mi in mis.iter() {
Expand Down
47 changes: 47 additions & 0 deletions src/librustc_hir/hir.rs
Expand Up @@ -1291,6 +1291,53 @@ impl BodyOwnerKind {
}
}

/// The kind of an item that requires const-checking.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ConstContext {
/// A `const fn`.
ConstFn,

/// A `static` or `static mut`.
Static(Mutability),

/// A `const`, associated `const`, or other const context.
///
/// Other contexts include:
/// - Array length expressions
/// - Enum discriminants
/// - Const generics
///
/// For the most part, other contexts are treated just like a regular `const`, so they are
/// lumped into the same category.
Const,
}

impl ConstContext {
/// A description of this const context that can appear between backticks in an error message.
///
/// E.g. `const` or `static mut`.
pub fn keyword_name(self) -> &'static str {
match self {
Self::Const => "const",
Self::Static(Mutability::Not) => "static",
Self::Static(Mutability::Mut) => "static mut",
Self::ConstFn => "const fn",
}
}
}

/// A colloquial, trivially pluralizable description of this const context for use in error
/// messages.
impl fmt::Display for ConstContext {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Self::Const => write!(f, "constant"),
Self::Static(_) => write!(f, "static"),
Self::ConstFn => write!(f, "constant function"),
}
}
}

/// A literal.
pub type Lit = Spanned<LitKind>;

Expand Down
20 changes: 20 additions & 0 deletions src/librustc_middle/hir/map/mod.rs
Expand Up @@ -408,6 +408,9 @@ impl<'hir> Map<'hir> {
})
}

/// Returns the `BodyOwnerKind` of this `LocalDefId`.
///
/// Panics if `LocalDefId` does not have an associated body.
pub fn body_owner_kind(&self, id: HirId) -> BodyOwnerKind {
match self.get(id) {
Node::Item(&Item { kind: ItemKind::Const(..), .. })
Expand All @@ -424,6 +427,23 @@ impl<'hir> Map<'hir> {
}
}

/// Returns the `ConstContext` of the body associated with this `LocalDefId`.
///
/// Panics if `LocalDefId` does not have an associated body.
pub fn body_const_context(&self, did: LocalDefId) -> Option<ConstContext> {
let hir_id = self.local_def_id_to_hir_id(did);
let ccx = match self.body_owner_kind(hir_id) {
BodyOwnerKind::Const => ConstContext::Const,
BodyOwnerKind::Static(mt) => ConstContext::Static(mt),

BodyOwnerKind::Fn if self.tcx.is_constructor(did.to_def_id()) => return None,
BodyOwnerKind::Fn if self.tcx.is_const_fn_raw(did.to_def_id()) => ConstContext::ConstFn,
BodyOwnerKind::Fn | BodyOwnerKind::Closure => return None,
};

Some(ccx)
}

pub fn ty_param_owner(&self, id: HirId) -> HirId {
match self.get(id) {
Node::Item(&Item { kind: ItemKind::Trait(..) | ItemKind::TraitAlias(..), .. }) => id,
Expand Down
78 changes: 78 additions & 0 deletions src/librustc_mir/borrow_check/def_use.rs
@@ -0,0 +1,78 @@
use rustc_middle::mir::visit::{
MutatingUseContext, NonMutatingUseContext, NonUseContext, PlaceContext,
};

#[derive(Eq, PartialEq, Clone)]
pub enum DefUse {
Def,
Use,
Drop,
}

pub fn categorize(context: PlaceContext) -> Option<DefUse> {
match context {
///////////////////////////////////////////////////////////////////////////
// DEFS

PlaceContext::MutatingUse(MutatingUseContext::Store) |

// This is potentially both a def and a use...
PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) |

// We let Call define the result in both the success and
// unwind cases. This is not really correct, however it
// does not seem to be observable due to the way that we
// generate MIR. To do things properly, we would apply
// the def in call only to the input from the success
// path and not the unwind path. -nmatsakis
PlaceContext::MutatingUse(MutatingUseContext::Call) |
PlaceContext::MutatingUse(MutatingUseContext::Yield) |

// Storage live and storage dead aren't proper defines, but we can ignore
// values that come before them.
PlaceContext::NonUse(NonUseContext::StorageLive) |
PlaceContext::NonUse(NonUseContext::StorageDead) => Some(DefUse::Def),

///////////////////////////////////////////////////////////////////////////
// REGULAR USES
//
// These are uses that occur *outside* of a drop. For the
// purposes of NLL, these are special in that **all** the
// lifetimes appearing in the variable must be live for each regular use.

PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) |
PlaceContext::MutatingUse(MutatingUseContext::Projection) |

// Borrows only consider their local used at the point of the borrow.
// This won't affect the results since we use this analysis for generators
// and we only care about the result at suspension points. Borrows cannot
// cross suspension points so this behavior is unproblematic.
PlaceContext::MutatingUse(MutatingUseContext::Borrow) |
PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) |
PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) |
PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow) |

PlaceContext::MutatingUse(MutatingUseContext::AddressOf) |
PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) |
PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect) |
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) |
PlaceContext::NonUse(NonUseContext::AscribeUserTy) |
PlaceContext::MutatingUse(MutatingUseContext::Retag) =>
Some(DefUse::Use),

///////////////////////////////////////////////////////////////////////////
// DROP USES
//
// These are uses that occur in a DROP (a MIR drop, not a
// call to `std::mem::drop()`). For the purposes of NLL,
// uses in drop are special because `#[may_dangle]`
// attributes can affect whether lifetimes must be live.

PlaceContext::MutatingUse(MutatingUseContext::Drop) =>
Some(DefUse::Drop),

// Debug info is neither def nor use.
PlaceContext::NonUse(NonUseContext::VarDebugInfo) => None,
}
}
4 changes: 2 additions & 2 deletions src/librustc_mir/borrow_check/diagnostics/find_use.rs
Expand Up @@ -2,10 +2,10 @@ use std::collections::VecDeque;
use std::rc::Rc;

use crate::borrow_check::{
def_use::{self, DefUse},
nll::ToRegionVid,
region_infer::{Cause, RegionInferenceContext},
};
use crate::util::liveness::{self, DefUse};
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::mir::visit::{MirVisitable, PlaceContext, Visitor};
use rustc_middle::mir::{Body, Local, Location};
Expand Down Expand Up @@ -117,7 +117,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for DefUseVisitor<'cx, 'tcx> {
});

if found_it {
self.def_use_result = match liveness::categorize(context) {
self.def_use_result = match def_use::categorize(context) {
Some(DefUse::Def) => Some(DefUseResult::Def),
Some(DefUse::Use) => Some(DefUseResult::UseLive { local }),
Some(DefUse::Drop) => Some(DefUseResult::UseDrop { local }),
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/borrow_check/mod.rs
Expand Up @@ -51,6 +51,7 @@ use self::path_utils::*;
mod borrow_set;
mod constraint_generation;
mod constraints;
mod def_use;
mod diagnostics;
mod facts;
mod invalidation;
Expand Down
Expand Up @@ -3,8 +3,7 @@ use rustc_index::vec::IndexVec;
use rustc_middle::mir::visit::{PlaceContext, Visitor};
use rustc_middle::mir::{Body, Local, Location};

use crate::util::liveness::{categorize, DefUse};

use crate::borrow_check::def_use::{self, DefUse};
use crate::borrow_check::region_infer::values::{PointIndex, RegionValueElements};

/// A map that cross references each local with the locations where it
Expand Down Expand Up @@ -160,7 +159,7 @@ impl LocalUseMapBuild<'_> {
impl Visitor<'tcx> for LocalUseMapBuild<'_> {
fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) {
if self.locals_with_use_data[local] {
match categorize(context) {
match def_use::categorize(context) {
Some(DefUse::Def) => self.insert_def(local, location),
Some(DefUse::Use) => self.insert_use(local, location),
Some(DefUse::Drop) => self.insert_drop(local, location),
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_mir/borrow_check/type_check/liveness/polonius.rs
@@ -1,7 +1,7 @@
use crate::borrow_check::def_use::{self, DefUse};
use crate::borrow_check::location::{LocationIndex, LocationTable};
use crate::dataflow::indexes::MovePathIndex;
use crate::dataflow::move_paths::{LookupResult, MoveData};
use crate::util::liveness::{categorize, DefUse};
use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::{Body, Local, Location, Place};
use rustc_middle::ty::subst::GenericArg;
Expand Down Expand Up @@ -56,7 +56,7 @@ impl UseFactsExtractor<'_> {

impl Visitor<'tcx> for UseFactsExtractor<'_> {
fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) {
match categorize(context) {
match def_use::categorize(context) {
Some(DefUse::Def) => self.insert_def(local, location),
Some(DefUse::Use) => self.insert_use(local, location),
Some(DefUse::Drop) => self.insert_drop_use(local, location),
Expand Down
7 changes: 7 additions & 0 deletions src/librustc_mir/dataflow/impls/liveness.rs
Expand Up @@ -6,6 +6,13 @@ use crate::dataflow::{AnalysisDomain, Backward, BottomValue, GenKill, GenKillAna

/// A [live-variable dataflow analysis][liveness].
///
/// This analysis considers references as being used only at the point of the
/// borrow. In other words, this analysis does not track uses because of references that already
/// exist. See [this `mir-datalow` test][flow-test] for an example. You almost never want to use
/// this analysis without also looking at the results of [`MaybeBorrowedLocals`].
///
/// [`MaybeBorrowedLocals`]: ../struct.MaybeBorrowedLocals.html
/// [flow-test]: https://github.com/rust-lang/rust/blob/a08c47310c7d49cbdc5d7afb38408ba519967ecd/src/test/ui/mir-dataflow/liveness-ptr.rs
/// [liveness]: https://en.wikipedia.org/wiki/Live_variable_analysis
pub struct MaybeLiveLocals;

Expand Down
68 changes: 3 additions & 65 deletions src/librustc_mir/transform/check_consts/mod.rs
Expand Up @@ -9,8 +9,6 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::mir;
use rustc_middle::ty::{self, TyCtxt};

use std::fmt;

pub use self::qualifs::Qualif;

mod ops;
Expand All @@ -25,7 +23,7 @@ pub struct ConstCx<'mir, 'tcx> {
pub tcx: TyCtxt<'tcx>,
pub def_id: DefId,
pub param_env: ty::ParamEnv<'tcx>,
pub const_kind: Option<ConstKind>,
pub const_kind: Option<hir::ConstContext>,
}

impl ConstCx<'mir, 'tcx> {
Expand All @@ -40,78 +38,18 @@ impl ConstCx<'mir, 'tcx> {
body: &'mir mir::Body<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> Self {
let const_kind = ConstKind::for_item(tcx, def_id);

let const_kind = tcx.hir().body_const_context(def_id);
ConstCx { body, tcx, def_id: def_id.to_def_id(), param_env, const_kind }
}

/// Returns the kind of const context this `Item` represents (`const`, `static`, etc.).
///
/// Panics if this `Item` is not const.
pub fn const_kind(&self) -> ConstKind {
pub fn const_kind(&self) -> hir::ConstContext {
self.const_kind.expect("`const_kind` must not be called on a non-const fn")
}
}

/// The kinds of items which require compile-time evaluation.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ConstKind {
/// A `static` item.
Static,
/// A `static mut` item.
StaticMut,
/// A `const fn` item.
ConstFn,
/// A `const` item or an anonymous constant (e.g. in array lengths).
Const,
}

impl ConstKind {
/// Returns the validation mode for the item with the given `DefId`, or `None` if this item
/// does not require validation (e.g. a non-const `fn`).
pub fn for_item(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Option<Self> {
use hir::BodyOwnerKind as HirKind;

let hir_id = tcx.hir().as_local_hir_id(def_id);

let mode = match tcx.hir().body_owner_kind(hir_id) {
HirKind::Closure => return None,

// Note: this is deliberately checking for `is_const_fn_raw`, as the `is_const_fn`
// checks take into account the `rustc_const_unstable` attribute combined with enabled
// feature gates. Otherwise, const qualification would _not check_ whether this
// function body follows the `const fn` rules, as an unstable `const fn` would
// be considered "not const". More details are available in issue #67053.
HirKind::Fn if tcx.is_const_fn_raw(def_id) => ConstKind::ConstFn,
HirKind::Fn => return None,

HirKind::Const => ConstKind::Const,

HirKind::Static(hir::Mutability::Not) => ConstKind::Static,
HirKind::Static(hir::Mutability::Mut) => ConstKind::StaticMut,
};

Some(mode)
}

pub fn is_static(self) -> bool {
match self {
ConstKind::Static | ConstKind::StaticMut => true,
ConstKind::ConstFn | ConstKind::Const => false,
}
}
}

impl fmt::Display for ConstKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
ConstKind::Const => write!(f, "constant"),
ConstKind::Static | ConstKind::StaticMut => write!(f, "static"),
ConstKind::ConstFn => write!(f, "constant function"),
}
}
}

/// Returns `true` if this `DefId` points to one of the official `panic` lang items.
pub fn is_lang_panic_fn(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
Some(def_id) == tcx.lang_items().panic_fn() || Some(def_id) == tcx.lang_items().begin_panic_fn()
Expand Down

0 comments on commit 7b80539

Please sign in to comment.