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

Do not promote constants that contain unpromotable code #51570

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 0 additions & 2 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,6 @@ define_dep_nodes!( <'tcx>

// Represents the MIR for a fn; also used as the task node for
// things read/modify that MIR.
[] MirConstQualif(DefId),
[] MirBuilt(DefId),
[] MirConst(DefId),
[] MirValidated(DefId),
Expand Down Expand Up @@ -562,7 +561,6 @@ define_dep_nodes!( <'tcx>
[input] DefSpan(DefId),
[] LookupStability(DefId),
[] LookupDeprecationEntry(DefId),
[] ConstIsRvaluePromotableToStatic(DefId),
[] RvaluePromotableMap(DefId),
[] ImplParent(DefId),
[] TraitOfItem(DefId),
Expand Down
1 change: 1 addition & 0 deletions src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
#![feature(in_band_lifetimes)]
#![feature(macro_at_most_once_rep)]
#![feature(inclusive_range_methods)]
#![feature(extern_prelude)]

#![recursion_limit="512"]

Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use std::rc::Rc;
use syntax::ast;
use syntax::ptr::P;
use syntax_pos::Span;
use util::nodemap::ItemLocalSet;
use util::nodemap::ItemLocalMap;

///////////////////////////////////////////////////////////////////////////
// The Delegate trait
Expand Down Expand Up @@ -280,7 +280,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> {
param_env: ty::ParamEnv<'tcx>,
region_scope_tree: &'a region::ScopeTree,
tables: &'a ty::TypeckTables<'tcx>,
rvalue_promotable_map: Option<Lrc<ItemLocalSet>>)
rvalue_promotable_map: Option<Lrc<ItemLocalMap<ty::Promotability>>>)
-> Self
{
ExprUseVisitor {
Expand Down
31 changes: 17 additions & 14 deletions src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ use std::fmt;
use std::hash::{Hash, Hasher};
use rustc_data_structures::sync::Lrc;
use std::rc::Rc;
use util::nodemap::ItemLocalSet;
use util::nodemap::ItemLocalMap;

#[derive(Clone, Debug, PartialEq)]
pub enum Categorization<'tcx> {
Expand Down Expand Up @@ -295,7 +295,7 @@ pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
pub region_scope_tree: &'a region::ScopeTree,
pub tables: &'a ty::TypeckTables<'tcx>,
rvalue_promotable_map: Option<Lrc<ItemLocalSet>>,
rvalue_promotable_map: Option<Lrc<ItemLocalMap<ty::Promotability>>>,
infcx: Option<&'a InferCtxt<'a, 'gcx, 'tcx>>,
}

Expand Down Expand Up @@ -404,7 +404,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx, 'tcx> {
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
region_scope_tree: &'a region::ScopeTree,
tables: &'a ty::TypeckTables<'tcx>,
rvalue_promotable_map: Option<Lrc<ItemLocalSet>>)
rvalue_promotable_map: Option<Lrc<ItemLocalMap<ty::Promotability>>>)
-> MemCategorizationContext<'a, 'tcx, 'tcx> {
MemCategorizationContext {
tcx,
Expand Down Expand Up @@ -946,32 +946,35 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
span,
expr_ty,
);
let promotable = self.rvalue_promotable_map.as_ref().map(|m| m.contains(&hir_id.local_id))
.unwrap_or(false);
use ty::Promotability::*;
let promotability = self
.rvalue_promotable_map
.as_ref()
.and_then(|m| m.get(&hir_id.local_id).cloned())
.unwrap_or(NotPromotable);

debug!(
"cat_rvalue_node: promotable = {:?}",
promotable,
promotability,
);

// Always promote `[T; 0]` (even when e.g. borrowed mutably).
let promotable = match expr_ty.sty {
ty::TyArray(_, len) if len.assert_usize(self.tcx) == Some(0) => true,
_ => promotable,
let promotability = match expr_ty.sty {
ty::TyArray(_, len) if len.assert_usize(self.tcx) == Some(0) => Promotable,
_ => promotability,
};

debug!(
"cat_rvalue_node: promotable = {:?} (2)",
promotable,
promotability,
);

// Compute maximum lifetime of this rvalue. This is 'static if
// we can promote to a constant, otherwise equal to enclosing temp
// lifetime.
let re = if promotable {
self.tcx.types.re_static
} else {
self.temporary_scope(hir_id.local_id)
let re = match promotability {
Promotable | NotInspectable => self.tcx.types.re_static,
NotPromotable => self.temporary_scope(hir_id.local_id),
};
let ret = self.cat_rvalue(hir_id, span, re, expr_ty);
debug!("cat_rvalue_node ret {:?}", ret);
Expand Down
43 changes: 43 additions & 0 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2998,3 +2998,46 @@ impl fmt::Debug for SymbolName {
fmt::Display::fmt(&self.name, fmt)
}
}

impl_stable_hash_for!(enum self::Promotability {
Promotable,
NotInspectable,
NotPromotable
});

#[must_use]
#[derive(Debug, PartialEq, Clone, RustcEncodable, RustcDecodable)]
/// A fancy `bool` for making it less fragile to compute the promotability of something
pub enum Promotability {
Promotable,
/// The value is promotable as long as that promotion will not cause parts of it to be inspected
/// at compile-time. So it can't be used in a BinOp or UnOp, or dereferenced, or...
NotInspectable,
NotPromotable
}

impl Promotability {
pub fn inspect(self) -> Self {
match self {
// We are allowed to promote operations inspecting the value on these
Promotability::Promotable => Promotability::Promotable,
// We are *not* allowed to inspect values of this
Promotability::NotInspectable => Promotability::NotPromotable,
// This isn't promoted anyway
Promotability::NotPromotable => Promotability::NotPromotable,
}
}
}

impl std::ops::BitAnd for Promotability {
type Output = Self;

fn bitand(self, rhs: Self) -> Self {
use self::Promotability::*;
match (self, rhs) {
(NotPromotable, _) | (_, NotPromotable) => NotPromotable,
(NotInspectable, _) | (_, NotInspectable) => NotInspectable,
(Promotable, Promotable) => Promotable,
}
}
}
20 changes: 0 additions & 20 deletions src/librustc/ty/query/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,25 +375,6 @@ impl<'tcx> QueryDescription<'tcx> for queries::trait_of_item<'tcx> {
}
}

impl<'tcx> QueryDescription<'tcx> for queries::const_is_rvalue_promotable_to_static<'tcx> {
fn describe(tcx: TyCtxt, def_id: DefId) -> String {
format!("const checking if rvalue is promotable to static `{}`",
tcx.item_path_str(def_id))
}

#[inline]
fn cache_on_disk(_: Self::Key) -> bool {
true
}

#[inline]
fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
id: SerializedDepNodeIndex)
-> Option<Self::Value> {
tcx.queries.on_disk_cache.try_load_query_result(tcx, id)
}
}

impl<'tcx> QueryDescription<'tcx> for queries::rvalue_promotable_map<'tcx> {
fn describe(tcx: TyCtxt, def_id: DefId) -> String {
format!("checking which parts of `{}` are promotable to static",
Expand Down Expand Up @@ -842,7 +823,6 @@ macro_rules! impl_disk_cacheable_query(
impl_disk_cacheable_query!(unsafety_check_result, |def_id| def_id.is_local());
impl_disk_cacheable_query!(borrowck, |def_id| def_id.is_local());
impl_disk_cacheable_query!(mir_borrowck, |def_id| def_id.is_local());
impl_disk_cacheable_query!(mir_const_qualif, |def_id| def_id.is_local());
impl_disk_cacheable_query!(check_match, |def_id| def_id.is_local());
impl_disk_cacheable_query!(def_symbol_name, |_| true);
impl_disk_cacheable_query!(type_of, |def_id| def_id.is_local());
Expand Down
12 changes: 3 additions & 9 deletions src/librustc/ty/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,9 @@ use traits::Clauses;
use ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
use ty::steal::Steal;
use ty::subst::Substs;
use util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet};
use util::nodemap::{DefIdSet, DefIdMap, ItemLocalMap};
use util::common::{ErrorReported};

use rustc_data_structures::indexed_set::IdxSetBuf;
use rustc_target::spec::PanicStrategy;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
Expand Down Expand Up @@ -203,11 +202,6 @@ define_queries! { <'tcx>
/// constructors.
[] fn mir_keys: mir_keys(CrateNum) -> Lrc<DefIdSet>,

/// Maps DefId's that have an associated Mir to the result
/// of the MIR qualify_consts pass. The actual meaning of
/// the value isn't known except to the pass itself.
[] fn mir_const_qualif: MirConstQualif(DefId) -> (u8, Lrc<IdxSetBuf<mir::Local>>),

/// Fetch the MIR for a given def-id right after it's built - this includes
/// unreachable code.
[] fn mir_built: MirBuilt(DefId) -> &'tcx Steal<mir::Mir<'tcx>>,
Expand Down Expand Up @@ -332,8 +326,8 @@ define_queries! { <'tcx>

TypeChecking {
[] fn trait_of_item: TraitOfItem(DefId) -> Option<DefId>,
[] fn const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool,
[] fn rvalue_promotable_map: RvaluePromotableMap(DefId) -> Lrc<ItemLocalSet>,
[] fn rvalue_promotable_map: RvaluePromotableMap(DefId)
-> Lrc<ItemLocalMap<ty::Promotability>>,
},

Codegen {
Expand Down
2 changes: 0 additions & 2 deletions src/librustc/ty/query/on_disk_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,7 @@ impl<'sess> OnDiskCache<'sess> {
encode_query_results::<unsafety_check_result, _>(tcx, enc, qri)?;
encode_query_results::<borrowck, _>(tcx, enc, qri)?;
encode_query_results::<mir_borrowck, _>(tcx, enc, qri)?;
encode_query_results::<mir_const_qualif, _>(tcx, enc, qri)?;
encode_query_results::<def_symbol_name, _>(tcx, enc, qri)?;
encode_query_results::<const_is_rvalue_promotable_to_static, _>(tcx, enc, qri)?;
encode_query_results::<symbol_name, _>(tcx, enc, qri)?;
encode_query_results::<check_match, _>(tcx, enc, qri)?;
encode_query_results::<codegen_fn_attrs, _>(tcx, enc, qri)?;
Expand Down
6 changes: 0 additions & 6 deletions src/librustc/ty/query/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1069,7 +1069,6 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
},
DepKind::PrivacyAccessLevels => { force!(privacy_access_levels, LOCAL_CRATE); }
DepKind::MirBuilt => { force!(mir_built, def_id!()); }
DepKind::MirConstQualif => { force!(mir_const_qualif, def_id!()); }
DepKind::MirConst => { force!(mir_const, def_id!()); }
DepKind::MirValidated => { force!(mir_validated, def_id!()); }
DepKind::MirOptimized => { force!(optimized_mir, def_id!()); }
Expand Down Expand Up @@ -1121,9 +1120,6 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
DepKind::LookupDeprecationEntry => {
force!(lookup_deprecation_entry, def_id!());
}
DepKind::ConstIsRvaluePromotableToStatic => {
force!(const_is_rvalue_promotable_to_static, def_id!());
}
DepKind::RvaluePromotableMap => { force!(rvalue_promotable_map, def_id!()); }
DepKind::ImplParent => { force!(impl_parent, def_id!()); }
DepKind::TraitOfItem => { force!(trait_of_item, def_id!()); }
Expand Down Expand Up @@ -1285,9 +1281,7 @@ impl_load_from_cache!(
UnsafetyCheckResult => unsafety_check_result,
BorrowCheck => borrowck,
MirBorrowCheck => mir_borrowck,
MirConstQualif => mir_const_qualif,
SymbolName => def_symbol_name,
ConstIsRvaluePromotableToStatic => const_is_rvalue_promotable_to_static,
CheckMatch => check_match,
TypeOfItem => type_of,
GenericsOfItem => generics_of,
Expand Down
7 changes: 0 additions & 7 deletions src/librustc_metadata/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ use syntax::edition::Edition;
use syntax::parse::filemap_to_stream;
use syntax::symbol::Symbol;
use syntax_pos::{Span, NO_EXPANSION, FileName};
use rustc_data_structures::indexed_set::IdxSetBuf;
use rustc::hir;

macro_rules! provide {
Expand Down Expand Up @@ -140,9 +139,6 @@ provide! { <'tcx> tcx, def_id, other, cdata,

mir
}
mir_const_qualif => {
(cdata.mir_const_qualif(def_id.index), Lrc::new(IdxSetBuf::new_empty(0)))
}
fn_sig => { cdata.fn_sig(def_id.index, tcx) }
inherent_impls => { Lrc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
is_const_fn => { cdata.is_const_fn(def_id.index) }
Expand All @@ -164,9 +160,6 @@ provide! { <'tcx> tcx, def_id, other, cdata,
rendered_const => { cdata.get_rendered_const(def_id.index) }
impl_parent => { cdata.get_parent_impl(def_id.index) }
trait_of_item => { cdata.get_trait_of_item(def_id.index) }
const_is_rvalue_promotable_to_static => {
cdata.const_is_rvalue_promotable_to_static(def_id.index)
}
is_mir_available => { cdata.is_item_mir_available(def_id.index) }

dylib_dependency_formats => { Lrc::new(cdata.get_dylib_dependency_formats()) }
Expand Down
25 changes: 3 additions & 22 deletions src/librustc_metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -770,14 +770,6 @@ impl<'a, 'tcx> CrateMetadata {
}
}

pub fn const_is_rvalue_promotable_to_static(&self, id: DefIndex) -> bool {
match self.entry(id).kind {
EntryKind::AssociatedConst(_, data, _) |
EntryKind::Const(data, _) => data.ast_promotable,
_ => bug!(),
}
}

pub fn is_item_mir_available(&self, id: DefIndex) -> bool {
!self.is_proc_macro(id) &&
self.maybe_entry(id).and_then(|item| item.decode(self).mir).is_some()
Expand All @@ -793,25 +785,14 @@ impl<'a, 'tcx> CrateMetadata {
}
}

pub fn mir_const_qualif(&self, id: DefIndex) -> u8 {
match self.entry(id).kind {
EntryKind::Const(qualif, _) |
EntryKind::AssociatedConst(AssociatedContainer::ImplDefault, qualif, _) |
EntryKind::AssociatedConst(AssociatedContainer::ImplFinal, qualif, _) => {
qualif.mir
}
_ => bug!(),
}
}

pub fn get_associated_item(&self, id: DefIndex) -> ty::AssociatedItem {
let item = self.entry(id);
let def_key = self.def_key(id);
let parent = self.local_def_id(def_key.parent.unwrap());
let name = def_key.disambiguated_data.data.get_opt_name().unwrap();

let (kind, container, has_self) = match item.kind {
EntryKind::AssociatedConst(container, _, _) => {
EntryKind::AssociatedConst(container, _) => {
(ty::AssociatedKind::Const, container, false)
}
EntryKind::Method(data) => {
Expand Down Expand Up @@ -1006,8 +987,8 @@ impl<'a, 'tcx> CrateMetadata {

pub fn get_rendered_const(&self, id: DefIndex) -> String {
match self.entry(id).kind {
EntryKind::Const(_, data) |
EntryKind::AssociatedConst(_, _, data) => data.decode(self).0,
EntryKind::Const(data) |
EntryKind::AssociatedConst(_, data) => data.decode(self).0,
_ => bug!(),
}
}
Expand Down
Loading