diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 78e57c6a5d78f..a331702007c37 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -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), @@ -562,7 +561,6 @@ define_dep_nodes!( <'tcx> [input] DefSpan(DefId), [] LookupStability(DefId), [] LookupDeprecationEntry(DefId), - [] ConstIsRvaluePromotableToStatic(DefId), [] RvaluePromotableMap(DefId), [] ImplParent(DefId), [] TraitOfItem(DefId), diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index c72952efc6144..f91a124b56572 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -74,6 +74,7 @@ #![feature(in_band_lifetimes)] #![feature(macro_at_most_once_rep)] #![feature(inclusive_range_methods)] +#![feature(extern_prelude)] #![recursion_limit="512"] diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 5beafe2b601bf..56d74b53c37e6 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -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 @@ -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>) + rvalue_promotable_map: Option>>) -> Self { ExprUseVisitor { diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 0602dc55c43d6..107ef64cf9354 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -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> { @@ -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>, + rvalue_promotable_map: Option>>, infcx: Option<&'a InferCtxt<'a, 'gcx, 'tcx>>, } @@ -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>) + rvalue_promotable_map: Option>>) -> MemCategorizationContext<'a, 'tcx, 'tcx> { MemCategorizationContext { tcx, @@ -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); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index c2795bae01029..0896a95f62e47 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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, + } + } +} diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index 8db33032625b2..3ccd2ffa4cbfb 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -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 { - 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", @@ -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()); diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 1b1020c9bd86d..eee457ed3210f 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -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}; @@ -203,11 +202,6 @@ define_queries! { <'tcx> /// constructors. [] fn mir_keys: mir_keys(CrateNum) -> Lrc, - /// 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>), - /// Fetch the MIR for a given def-id right after it's built - this includes /// unreachable code. [] fn mir_built: MirBuilt(DefId) -> &'tcx Steal>, @@ -332,8 +326,8 @@ define_queries! { <'tcx> TypeChecking { [] fn trait_of_item: TraitOfItem(DefId) -> Option, - [] fn const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool, - [] fn rvalue_promotable_map: RvaluePromotableMap(DefId) -> Lrc, + [] fn rvalue_promotable_map: RvaluePromotableMap(DefId) + -> Lrc>, }, Codegen { diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index aa42b4072bd8a..6d82eb8b5e305 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -223,9 +223,7 @@ impl<'sess> OnDiskCache<'sess> { encode_query_results::(tcx, enc, qri)?; encode_query_results::(tcx, enc, qri)?; encode_query_results::(tcx, enc, qri)?; - encode_query_results::(tcx, enc, qri)?; encode_query_results::(tcx, enc, qri)?; - encode_query_results::(tcx, enc, qri)?; encode_query_results::(tcx, enc, qri)?; encode_query_results::(tcx, enc, qri)?; encode_query_results::(tcx, enc, qri)?; diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 7a9827b50a176..ca3842ac78aae 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -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!()); } @@ -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!()); } @@ -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, diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index e3a7918f8c589..c4b5c193b8653 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -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 { @@ -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) } @@ -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()) } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index ab566654c389c..bbfee501b3d4f 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -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() @@ -793,17 +785,6 @@ 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); @@ -811,7 +792,7 @@ impl<'a, 'tcx> CrateMetadata { 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) => { @@ -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!(), } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 7ed991e0de3a1..5ff9e049643b8 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -802,18 +802,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let kind = match trait_item.kind { ty::AssociatedKind::Const => { - let const_qualif = - if let hir::TraitItemKind::Const(_, Some(body)) = ast_item.node { - self.const_qualif(0, body) - } else { - ConstQualif { mir: 0, ast_promotable: false } - }; - let rendered = hir::print::to_string(&self.tcx.hir, |s| s.print_trait_item(ast_item)); let rendered_const = self.lazy(&RenderedConst(rendered)); - EntryKind::AssociatedConst(container, const_qualif, rendered_const) + EntryKind::AssociatedConst(container, rendered_const) } ty::AssociatedKind::Method => { let fn_data = if let hir::TraitItemKind::Method(_, ref m) = ast_item.node { @@ -886,13 +879,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { !self.tcx.sess.opts.output_types.should_codegen() } - fn const_qualif(&self, mir: u8, body_id: hir::BodyId) -> ConstQualif { - let body_owner_def_id = self.tcx.hir.body_owner_def_id(body_id); - let ast_promotable = self.tcx.const_is_rvalue_promotable_to_static(body_owner_def_id); - - ConstQualif { mir, ast_promotable } - } - fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> { debug!("IsolatedEncoder::encode_info_for_impl_item({:?})", def_id); let tcx = self.tcx; @@ -911,20 +897,17 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let kind = match impl_item.kind { ty::AssociatedKind::Const => { if let hir::ImplItemKind::Const(_, body_id) = ast_item.node { - let mir = self.tcx.at(ast_item.span).mir_const_qualif(def_id).0; - EntryKind::AssociatedConst(container, - self.const_qualif(mir, body_id), self.encode_rendered_const_for_body(body_id)) } else { bug!() } } ty::AssociatedKind::Method => { - let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node { + let fn_data = if let hir::ImplItemKind::Method(ref sig, body_id) = ast_item.node { FnData { constness: sig.header.constness, - arg_names: self.encode_fn_arg_names_for_body(body), + arg_names: self.encode_fn_arg_names_for_body(body_id), sig: self.lazy(&tcx.fn_sig(def_id)), } } else { @@ -1047,19 +1030,14 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { hir::ItemKind::Static(_, hir::MutMutable, _) => EntryKind::MutStatic, hir::ItemKind::Static(_, hir::MutImmutable, _) => EntryKind::ImmStatic, hir::ItemKind::Const(_, body_id) => { - let mir = tcx.at(item.span).mir_const_qualif(def_id).0; - EntryKind::Const( - self.const_qualif(mir, body_id), - self.encode_rendered_const_for_body(body_id) - ) + EntryKind::Const(self.encode_rendered_const_for_body(body_id)) } - hir::ItemKind::Fn(_, header, .., body) => { + hir::ItemKind::Fn(_, header, .., body_id) => { let data = FnData { constness: header.constness, - arg_names: self.encode_fn_arg_names_for_body(body), + arg_names: self.encode_fn_arg_names_for_body(body_id), sig: self.lazy(&tcx.fn_sig(def_id)), }; - EntryKind::Fn(self.lazy(&data)) } hir::ItemKind::Mod(ref m) => { @@ -1383,10 +1361,9 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let id = tcx.hir.as_local_node_id(def_id).unwrap(); let body_id = tcx.hir.body_owned_by(id); let const_data = self.encode_rendered_const_for_body(body_id); - let mir = tcx.mir_const_qualif(def_id).0; Entry { - kind: EntryKind::Const(self.const_qualif(mir, body_id), const_data), + kind: EntryKind::Const(const_data), visibility: self.lazy(&ty::Visibility::Public), span: self.lazy(&tcx.def_span(def_id)), attributes: LazySeq::empty(), diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index d7c54cbc81d94..31eb2f4b92c7a 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -296,7 +296,7 @@ impl_stable_hash_for!(struct Entry<'tcx> { #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] pub enum EntryKind<'tcx> { - Const(ConstQualif, Lazy), + Const(Lazy), ImmStatic, MutStatic, ForeignImmStatic, @@ -322,7 +322,7 @@ pub enum EntryKind<'tcx> { Method(Lazy>), AssociatedType(AssociatedContainer), AssociatedExistential(AssociatedContainer), - AssociatedConst(AssociatedContainer, ConstQualif, Lazy), + AssociatedConst(AssociatedContainer, Lazy), } impl<'a, 'gcx> HashStable> for EntryKind<'gcx> { @@ -343,8 +343,7 @@ impl<'a, 'gcx> HashStable> for EntryKind<'gcx> { EntryKind::Type => { // Nothing else to hash here. } - EntryKind::Const(qualif, ref const_data) => { - qualif.hash_stable(hcx, hasher); + EntryKind::Const(ref const_data) => { const_data.hash_stable(hcx, hasher); } EntryKind::Enum(ref repr_options) => { @@ -387,24 +386,14 @@ impl<'a, 'gcx> HashStable> for EntryKind<'gcx> { EntryKind::AssociatedType(associated_container) => { associated_container.hash_stable(hcx, hasher); } - EntryKind::AssociatedConst(associated_container, qualif, ref const_data) => { + EntryKind::AssociatedConst(associated_container, ref const_data) => { associated_container.hash_stable(hcx, hasher); - qualif.hash_stable(hcx, hasher); const_data.hash_stable(hcx, hasher); } } } } -/// Additional data for EntryKind::Const and EntryKind::AssociatedConst -#[derive(Clone, Copy, RustcEncodable, RustcDecodable)] -pub struct ConstQualif { - pub mir: u8, - pub ast_promotable: bool, -} - -impl_stable_hash_for!(struct ConstQualif { mir, ast_promotable }); - /// Contains a constant which has been rendered to a String. /// Used by rustdoc. #[derive(RustcEncodable, RustcDecodable)] diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 24228389fbfbb..8e7787bd5caac 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -36,7 +36,7 @@ use util as mir_util; /// Construct the MIR for a given def-id. pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'tcx> { - let id = tcx.hir.as_local_node_id(def_id).unwrap(); + let id = tcx.hir.as_local_node_id(def_id).expect("can't build non-local MIR"); let unsupported = || { span_bug!(tcx.hir.span(id), "can't build MIR for {:?}", def_id); }; diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs index 3c92f3f623581..126b33c32b871 100644 --- a/src/librustc_mir/interpret/const_eval.rs +++ b/src/librustc_mir/interpret/const_eval.rs @@ -532,7 +532,7 @@ pub fn const_eval_provider<'a, 'tcx>( let cid = key.value; let def_id = cid.instance.def.def_id(); - if let Some(id) = tcx.hir.as_local_node_id(def_id) { + if def_id.is_local() { let tables = tcx.typeck_tables_of(def_id); let span = tcx.def_span(def_id); @@ -545,10 +545,6 @@ pub fn const_eval_provider<'a, 'tcx>( }.into()); } - if let hir::BodyOwnerKind::Const = tcx.hir.body_owner_kind(id) { - tcx.mir_const_qualif(def_id); - } - // Do not continue into miri if typeck errors occurred; it will fail horribly if tables.tainted_by_errors { return Err(ConstEvalErr { diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 90dfebeef1b0c..3deb88874fc0a 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -48,7 +48,6 @@ pub mod lower_128bit; pub mod uniform_array_move_out; pub(crate) fn provide(providers: &mut Providers) { - self::qualify_consts::provide(providers); self::check_unsafety::provide(providers); *providers = Providers { mir_keys, @@ -205,13 +204,6 @@ fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Stea } fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal> { - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - if let hir::BodyOwnerKind::Const = tcx.hir.body_owner_kind(node_id) { - // Ensure that we compute the `mir_const_qualif` for constants at - // this point, before we steal the mir-const result. - let _ = tcx.mir_const_qualif(def_id); - } - let mut mir = tcx.mir_const(def_id).steal(); run_passes![tcx, mir, def_id, 1; // What we need to run borrowck etc. diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 4e1129ea7e945..79ddefe4cbfa3 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -20,11 +20,9 @@ use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc_data_structures::fx::FxHashSet; use rustc::hir; use rustc::hir::def_id::DefId; -use rustc::mir::interpret::ConstValue; use rustc::traits::{self, TraitEngine}; use rustc::ty::{self, TyCtxt, Ty, TypeFoldable}; use rustc::ty::cast::CastTy; -use rustc::ty::query::Providers; use rustc::mir::*; use rustc::mir::traversal::ReversePostorder; use rustc::mir::visit::{PlaceContext, Visitor}; @@ -279,7 +277,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { } /// Qualify a whole const, static initializer or const fn. - fn qualify_const(&mut self) -> (Qualif, Lrc>) { + fn qualify_const(&mut self) -> Lrc> { debug!("qualifying {} {:?}", self.mode, self.def_id); let mir = self.mir; @@ -398,7 +396,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { } } - (self.qualif, Lrc::new(promoted_temps)) + Lrc::new(promoted_temps) } } @@ -558,24 +556,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { ); } } - Operand::Constant(ref constant) => { - if let ConstValue::Unevaluated(def_id, _) = constant.literal.val { - // Don't peek inside trait associated constants. - if self.tcx.trait_of_item(def_id).is_some() { - self.add_type(constant.literal.ty); - } else { - let (bits, _) = self.tcx.at(constant.span).mir_const_qualif(def_id); - - let qualif = Qualif::from_bits(bits).expect("invalid mir_const_qualif"); - self.add(qualif); - - // Just in case the type is more specific than - // the definition, e.g. impl associated const - // with type parameters, take it into account. - self.qualif.restrict(constant.literal.ty, self.tcx, self.param_env); - } - } - } + Operand::Constant(ref constant) => self.add_type(constant.literal.ty), } } @@ -838,15 +819,29 @@ This does not pose a problem by itself because they can't be accessed directly." Abi::PlatformIntrinsic => { assert!(!self.tcx.is_const_fn(def_id)); match &self.tcx.item_name(def_id).as_str()[..] { + // DANGER_ZONE + // Do not add anything to this list without consulting + // @eddyb, @nikomatsakis and @oli-obk + // + // Any intrinsic which has arguments can potentially cause + // a mismatch between what becomes promoted to `'static` and + // what can be evaluated at compile-time | "size_of" | "min_align_of" - | "type_id" + | "type_id" => is_const_fn = Some(def_id), + // END(DANGER_ZONE) + + // If you add anything to this list, make sure to also implement it + // in `rustc_mir::interpret::const_eval` | "bswap" | "ctpop" | "cttz" | "cttz_nonzero" | "ctlz" - | "ctlz_nonzero" => is_const_fn = Some(def_id), + | "ctlz_nonzero" => { + self.add(Qualif::NOT_PROMOTABLE); + is_const_fn = Some(def_id) + }, name if name.starts_with("simd_shuffle") => { is_shuffle = true; @@ -858,6 +853,10 @@ This does not pose a problem by itself because they can't be accessed directly." _ => { if self.tcx.is_const_fn(def_id) { is_const_fn = Some(def_id); + // do not promote unsafe function calls + if fn_ty.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe { + self.add(Qualif::NOT_PROMOTABLE); + } } } } @@ -1095,30 +1094,18 @@ This does not pose a problem by itself because they can't be accessed directly." } } -pub fn provide(providers: &mut Providers) { - *providers = Providers { - mir_const_qualif, - ..*providers - }; -} - -fn mir_const_qualif<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> (u8, Lrc>) { - // NB: This `borrow()` is guaranteed to be valid (i.e., the value - // cannot yet be stolen), because `mir_validated()`, which steals - // from `mir_const(), forces this query to execute before - // performing the steal. - let mir = &tcx.mir_const(def_id).borrow(); - +fn mir_const_qualif<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, + mir: &mut Mir<'tcx>, +) -> Lrc> { if mir.return_ty().references_error() { tcx.sess.delay_span_bug(mir.span, "mir_const_qualif: Mir had errors"); - return (Qualif::NOT_CONST.bits(), Lrc::new(IdxSetBuf::new_empty(0))); + return Lrc::new(IdxSetBuf::new_empty(0)); } let mut qualifier = Qualifier::new(tcx, def_id, mir, Mode::Const); - let (qualif, promoted_temps) = qualifier.qualify_const(); - (qualif.bits(), promoted_temps) + qualifier.qualify_const() } pub struct QualifyAndPromoteConstants; @@ -1150,7 +1137,7 @@ impl MirPass for QualifyAndPromoteConstants { } } hir::BodyOwnerKind::Const => { - const_promoted_temps = Some(tcx.mir_const_qualif(def_id).1); + const_promoted_temps = Some(mir_const_qualif(tcx, def_id, mir)); Mode::Const } hir::BodyOwnerKind::Static(hir::MutImmutable) => Mode::Static, @@ -1181,7 +1168,7 @@ impl MirPass for QualifyAndPromoteConstants { // Already computed by `mir_const_qualif`. const_promoted_temps.unwrap() } else { - Qualifier::new(tcx, def_id, mir, mode).qualify_const().1 + Qualifier::new(tcx, def_id, mir, mode).qualify_const() }; // In `const` and `static` everything without `StorageDead` diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index d223dc2a35335..7851eb92e2ba8 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -27,27 +27,24 @@ use rustc::ty::cast::CastKind; use rustc::hir::def::{Def, CtorKind}; use rustc::hir::def_id::DefId; -use rustc::hir::map::blocks::FnLikeNode; use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization as mc; use rustc::middle::mem_categorization::Categorization; -use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::{self, Ty, TyCtxt, Promotability}; use rustc::ty::query::Providers; use rustc::ty::subst::Substs; -use rustc::util::nodemap::{ItemLocalSet, NodeSet}; +use rustc::util::nodemap::{ItemLocalMap, NodeSet, FxHashSet}; use rustc::hir; use rustc_data_structures::sync::Lrc; use syntax::ast; use syntax::attr; use syntax_pos::{Span, DUMMY_SP}; use self::Promotability::*; -use std::ops::{BitAnd, BitOr}; pub fn provide(providers: &mut Providers) { *providers = Providers { rvalue_promotable_map, - const_is_rvalue_promotable_to_static, ..*providers }; } @@ -55,28 +52,23 @@ pub fn provide(providers: &mut Providers) { pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { for &body_id in &tcx.hir.krate().body_ids { let def_id = tcx.hir.body_owner_def_id(body_id); - tcx.const_is_rvalue_promotable_to_static(def_id); + tcx.rvalue_promotable_map(def_id); } tcx.sess.abort_if_errors(); } -fn const_is_rvalue_promotable_to_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> bool -{ - assert!(def_id.is_local()); - - let node_id = tcx.hir.as_local_node_id(def_id) - .expect("rvalue_promotable_map invoked with non-local def-id"); - let body_id = tcx.hir.body_owned_by(node_id); - let body_hir_id = tcx.hir.node_to_hir_id(body_id.node_id); - tcx.rvalue_promotable_map(def_id).contains(&body_hir_id.local_id) -} - fn rvalue_promotable_map<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Lrc + -> Lrc> { + rvalue_promotable_map_inner(tcx, def_id, &mut FxHashSet()) +} + +fn rvalue_promotable_map_inner<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, + seen: &mut FxHashSet, +) -> Lrc> { let outer_def_id = tcx.closure_base_def_id(def_id); if outer_def_id != def_id { return tcx.rvalue_promotable_map(outer_def_id); @@ -90,9 +82,12 @@ fn rvalue_promotable_map<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mut_rvalue_borrows: NodeSet(), param_env: ty::ParamEnv::empty(), identity_substs: Substs::empty(), - result: ItemLocalSet(), + result: ItemLocalMap(), + seen, }; + visitor.seen.insert(def_id); + // `def_id` should be a `Body` owner let node_id = tcx.hir.as_local_node_id(def_id) .expect("rvalue_promotable_map invoked with non-local def-id"); @@ -110,40 +105,8 @@ struct CheckCrateVisitor<'a, 'tcx: 'a> { param_env: ty::ParamEnv<'tcx>, identity_substs: &'tcx Substs<'tcx>, tables: &'a ty::TypeckTables<'tcx>, - result: ItemLocalSet, -} - -#[must_use] -#[derive(Debug, PartialEq)] -enum Promotability { - Promotable, - NotPromotable -} - -impl BitAnd for Promotability { - type Output = Self; - - fn bitand(self, rhs: Self) -> Self { - match (self, rhs) { - (Promotable, NotPromotable) => NotPromotable, - (NotPromotable, Promotable) => NotPromotable, - (NotPromotable, NotPromotable) => NotPromotable, - (Promotable, Promotable) => Promotable, - } - } -} - -impl BitOr for Promotability { - type Output = Self; - - fn bitor(self, rhs: Self) -> Self { - match (self, rhs) { - (Promotable, NotPromotable) => Promotable, - (NotPromotable, Promotable) => Promotable, - (NotPromotable, NotPromotable) => NotPromotable, - (Promotable, Promotable) => Promotable, - } - } + result: ItemLocalMap, + seen: &'a mut FxHashSet, } impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { @@ -159,24 +122,12 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { } } - fn handle_const_fn_call(&mut self, def_id: DefId, - ret_ty: Ty<'gcx>, span: Span) -> Promotability { - if let NotPromotable = self.type_promotability(ret_ty) { - return NotPromotable; - } - - let node_check = if let Some(fn_id) = self.tcx.hir.as_local_node_id(def_id) { - FnLikeNode::from_node(self.tcx.hir.get(fn_id)).map_or(false, |fn_like| { - fn_like.constness() == hir::Constness::Const - }) - } else { - self.tcx.is_const_fn(def_id) - }; - - if !node_check { - return NotPromotable - } - + fn handle_const_fn_call( + &mut self, + def_id: DefId, + ret_ty: Ty<'gcx>, + span: Span, + ) -> Promotability { if let Some(&attr::Stability { rustc_const_unstable: Some(attr::RustcConstUnstable { feature: ref feature_name @@ -197,8 +148,22 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { if !stable_check { return NotPromotable } - }; - Promotable + } + + if !self.tcx.is_const_fn(def_id) { + return NotPromotable; + } + + // do not promote unsafe function calls + let fn_ty = self.tcx.type_of(def_id); + if fn_ty.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe { + return NotPromotable; + } + + // At this point the user needed to do something not-const inside a const fn to make this + // not promotable. We will just error when actually computing the promoted's value in that + // case. + self.type_promotability(ret_ty) } /// While the `ExprUseVisitor` walks, we will identify which @@ -298,8 +263,9 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> { outer = NotPromotable } - if outer == Promotable { - self.result.insert(ex.hir_id.local_id); + // No need to add entries for nonpromotable nodes + if outer != NotPromotable { + assert!(self.result.insert(ex.hir_id.local_id, outer.clone()).is_none()); } outer } @@ -339,7 +305,7 @@ fn check_expr_kind<'a, 'tcx>( NotPromotable } hir::ExprKind::Unary(op, ref expr) => { - let expr_promotability = v.check_expr(expr); + let expr_promotability = v.check_expr(expr).inspect(); if v.tables.is_method_call(e) { return NotPromotable; } @@ -349,8 +315,8 @@ fn check_expr_kind<'a, 'tcx>( expr_promotability } hir::ExprKind::Binary(op, ref lhs, ref rhs) => { - let lefty = v.check_expr(lhs); - let righty = v.check_expr(rhs); + let lefty = v.check_expr(lhs).inspect(); + let righty = v.check_expr(rhs).inspect(); if v.tables.is_method_call(e) { return NotPromotable; } @@ -366,7 +332,7 @@ fn check_expr_kind<'a, 'tcx>( } } hir::ExprKind::Cast(ref from, _) => { - let expr_promotability = v.check_expr(from); + let expr_promotability = v.check_expr(from).inspect(); debug!("Checking const cast(id={})", from.id); match v.tables.cast_kinds().get(from.hir_id) { None => { @@ -410,18 +376,8 @@ fn check_expr_kind<'a, 'tcx>( Def::Const(did) | Def::AssociatedConst(did) => { - let promotable = if v.tcx.trait_of_item(did).is_some() { - // Don't peek inside trait associated constants. - NotPromotable - } else if v.tcx.at(e.span).const_is_rvalue_promotable_to_static(did) { - Promotable - } else { - NotPromotable - }; - // Just in case the type is more specific than the definition, - // e.g. impl associated const with type parameters, check it. - // Also, trait associated consts are relaxed by this. - promotable | v.type_promotability(node_ty) + let ty = v.tcx.type_of(did); + v.type_promotability(ty) } _ => NotPromotable } @@ -522,10 +478,10 @@ fn check_expr_kind<'a, 'tcx>( } hir::ExprKind::Field(ref expr, _ident) => { - let expr_promotability = v.check_expr(&expr); + let expr_promotability = v.check_expr(&expr).inspect(); if let Some(def) = v.tables.expr_ty(expr).ty_adt_def() { if def.is_union() { - return NotPromotable; + return expr_promotability & NotInspectable; } } expr_promotability @@ -536,8 +492,8 @@ fn check_expr_kind<'a, 'tcx>( } hir::ExprKind::Index(ref lhs, ref rhs) => { - let lefty = v.check_expr(lhs); - let righty = v.check_expr(rhs); + let lefty = v.check_expr(lhs).inspect(); + let righty = v.check_expr(rhs).inspect(); if v.tables.is_method_call(e) { return NotPromotable; } @@ -553,7 +509,7 @@ fn check_expr_kind<'a, 'tcx>( } hir::ExprKind::Type(ref expr, ref _ty) => { - v.check_expr(&expr) + v.check_expr(&expr).inspect() } hir::ExprKind::Tup(ref hirvec) => { @@ -659,6 +615,7 @@ fn check_adjustments<'a, 'tcx>( let mut adjustments = v.tables.expr_adjustments(e).iter().peekable(); while let Some(adjustment) = adjustments.next() { + // FIXME: do some of these make the value not inspectable? match adjustment.kind { Adjust::NeverToAny | Adjust::ReifyFnPointer | diff --git a/src/test/compile-fail/static-drop-scope.rs b/src/test/compile-fail/static-drop-scope.rs index e22eb7e4484d6..08de5e90a59ab 100644 --- a/src/test/compile-fail/static-drop-scope.rs +++ b/src/test/compile-fail/static-drop-scope.rs @@ -24,12 +24,6 @@ const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); //~^ ERROR destructors cannot be evaluated at compile-time //~| ERROR borrowed value does not live long enoug -static EARLY_DROP_S: i32 = (WithDtor, 0).1; -//~^ ERROR destructors cannot be evaluated at compile-time - -const EARLY_DROP_C: i32 = (WithDtor, 0).1; -//~^ ERROR destructors cannot be evaluated at compile-time - const fn const_drop(_: T) {} //~^ ERROR destructors cannot be evaluated at compile-time diff --git a/src/test/compile-fail/static-drop-scope2.rs b/src/test/compile-fail/static-drop-scope2.rs new file mode 100644 index 0000000000000..dc3694594f39a --- /dev/null +++ b/src/test/compile-fail/static-drop-scope2.rs @@ -0,0 +1,22 @@ +// Copyright 2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(const_fn)] + +struct WithDtor; + +impl Drop for WithDtor { + fn drop(&mut self) {} +} + +const EARLY_DROP_C: i32 = (WithDtor, 0).1; +//~^ ERROR this constant cannot be used + +fn main () {} diff --git a/src/test/compile-fail/static-drop-scope3.rs b/src/test/compile-fail/static-drop-scope3.rs new file mode 100644 index 0000000000000..416de0107f786 --- /dev/null +++ b/src/test/compile-fail/static-drop-scope3.rs @@ -0,0 +1,22 @@ +// Copyright 2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(const_fn)] + +struct WithDtor; + +impl Drop for WithDtor { + fn drop(&mut self) {} +} + +static EARLY_DROP_S: i32 = (WithDtor, 0).1; +//~^ ERROR could not evaluate static initializer + +fn main () {} diff --git a/src/test/run-pass/ctfe/promotion.rs b/src/test/run-pass/ctfe/promotion.rs index 2d228408254aa..761249651621f 100644 --- a/src/test/run-pass/ctfe/promotion.rs +++ b/src/test/run-pass/ctfe/promotion.rs @@ -11,7 +11,24 @@ fn foo(_: &'static [&'static str]) {} fn bar(_: &'static [&'static str; 3]) {} +struct Foo { + a: usize, + b: u32, +} + fn main() { foo(&["a", "b", "c"]); bar(&["d", "e", "f"]); } + +trait Trait { + const INT: usize; +} + +fn generic() -> &'static Foo { + &(Foo {a: T::INT, b: 42}) +} + +fn generic2() -> &'static usize { + &T::INT +} diff --git a/src/test/ui/const-eval/issue-44578.rs b/src/test/ui/const-eval/issue-44578.rs index 59ac4ab311c6c..eb1ab96777194 100644 --- a/src/test/ui/const-eval/issue-44578.rs +++ b/src/test/ui/const-eval/issue-44578.rs @@ -33,6 +33,6 @@ impl Foo for u16 { fn main() { println!("{}", as Foo>::AMT); - //~^ ERROR erroneous constant used + //~^ ERROR E0080 //~| ERROR E0080 } diff --git a/src/test/ui/const-eval/issue-50814-2.rs b/src/test/ui/const-eval/issue-50814-2.rs index af627ee5fbe70..678820b57d279 100644 --- a/src/test/ui/const-eval/issue-50814-2.rs +++ b/src/test/ui/const-eval/issue-50814-2.rs @@ -23,8 +23,8 @@ impl Foo for A { } fn foo() -> &'static usize { - & as Foo>::BAR //~ ERROR erroneous constant used -//~| ERROR E0080 + & as Foo>::BAR //~ ERROR referenced constant + //~^ ERROR erroneous constant } impl C for () { diff --git a/src/test/ui/const-eval/issue-50814-2.stderr b/src/test/ui/const-eval/issue-50814-2.stderr index 1e37e9498120f..9eaea817b38a5 100644 --- a/src/test/ui/const-eval/issue-50814-2.stderr +++ b/src/test/ui/const-eval/issue-50814-2.stderr @@ -4,13 +4,13 @@ error[E0080]: referenced constant has errors LL | const BAR: usize = [5, 6, 7][T::BOO]; | ----------------- index out of bounds: the len is 3 but the index is 42 ... -LL | & as Foo>::BAR //~ ERROR erroneous constant used +LL | & as Foo>::BAR //~ ERROR referenced constant | ^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: erroneous constant used --> $DIR/issue-50814-2.rs:26:5 | -LL | & as Foo>::BAR //~ ERROR erroneous constant used +LL | & as Foo>::BAR //~ ERROR referenced constant | ^--------------------- | | | referenced constant has errors diff --git a/src/test/ui/const-eval/issue-50814.rs b/src/test/ui/const-eval/issue-50814.rs index 8f2752453b52e..26794834f6f11 100644 --- a/src/test/ui/const-eval/issue-50814.rs +++ b/src/test/ui/const-eval/issue-50814.rs @@ -24,8 +24,8 @@ impl Unsigned for Sum { } fn foo(_: T) -> &'static u8 { - &Sum::::MAX //~ ERROR erroneous constant used -//~| ERROR E0080 + &Sum::::MAX //~ ERROR erroneous constant + //~^ ERROR referenced constant } fn main() { diff --git a/src/test/ui/const-eval/issue-50814.stderr b/src/test/ui/const-eval/issue-50814.stderr index 16160207c573b..4b415a6aa8797 100644 --- a/src/test/ui/const-eval/issue-50814.stderr +++ b/src/test/ui/const-eval/issue-50814.stderr @@ -4,13 +4,13 @@ error[E0080]: referenced constant has errors LL | const MAX: u8 = A::MAX + B::MAX; | --------------- attempt to add with overflow ... -LL | &Sum::::MAX //~ ERROR erroneous constant used +LL | &Sum::::MAX //~ ERROR erroneous constant | ^^^^^^^^^^^^^^^^^^ error[E0080]: erroneous constant used --> $DIR/issue-50814.rs:27:5 | -LL | &Sum::::MAX //~ ERROR erroneous constant used +LL | &Sum::::MAX //~ ERROR erroneous constant | ^----------------- | | | referenced constant has errors diff --git a/src/test/ui/const-eval/promote_const_fn_call.rs b/src/test/ui/const-eval/promote_const_fn_call.rs new file mode 100644 index 0000000000000..be8a0f83006bc --- /dev/null +++ b/src/test/ui/const-eval/promote_const_fn_call.rs @@ -0,0 +1,29 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass + +#![feature(const_fn)] + +const fn max() -> usize { !0 } + +trait Foo { + const BAR: usize; +} + +impl Foo for u32 { + const BAR: usize = 42; +} + +fn main() { + let x: &'static usize = &max(); + let y: &'static usize = &std::usize::MAX; + let z: &'static usize = &u32::BAR; +} diff --git a/src/test/ui/const-eval/unpromotable_constant.rs b/src/test/ui/const-eval/unpromotable_constant.rs new file mode 100644 index 0000000000000..08774f451aabc --- /dev/null +++ b/src/test/ui/const-eval/unpromotable_constant.rs @@ -0,0 +1,29 @@ +// Copyright 2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(const_err)] + +// compile-pass + +union Bad { + usize: usize, + ptr: &'static u32, +} + +// the constant does something "unconst", so promotion is allowed to fail +const FOO: usize = unsafe { + Bad { ptr: &1 }.usize +}; + + +fn main() { + let x: &'static usize = &FOO; + let y: &'static usize = &(FOO % 42); +} diff --git a/src/test/ui/issue-17252.stderr b/src/test/ui/issue-17252.stderr index 8f97a841666ec..71c23ca8bac74 100644 --- a/src/test/ui/issue-17252.stderr +++ b/src/test/ui/issue-17252.stderr @@ -1,10 +1,10 @@ -error[E0391]: cycle detected when processing `FOO` +error[E0391]: cycle detected when const-evaluating `FOO` --> $DIR/issue-17252.rs:11:20 | LL | const FOO: usize = FOO; //~ ERROR E0391 | ^^^ | - = note: ...which again requires processing `FOO`, completing the cycle + = note: ...which again requires const-evaluating `FOO`, completing the cycle note: cycle used when processing `main::{{constant}}` --> $DIR/issue-17252.rs:14:18 | diff --git a/src/test/ui/issue-23302-1.stderr b/src/test/ui/issue-23302-1.stderr index dcf021de57e56..e5d07dc2ab4c7 100644 --- a/src/test/ui/issue-23302-1.stderr +++ b/src/test/ui/issue-23302-1.stderr @@ -1,15 +1,15 @@ -error[E0391]: cycle detected when processing `X::A::{{constant}}` +error[E0391]: cycle detected when const-evaluating `X::A::{{constant}}` --> $DIR/issue-23302-1.rs:14:9 | LL | A = X::A as isize, //~ ERROR E0391 | ^^^^^^^^^^^^^ | - = note: ...which again requires processing `X::A::{{constant}}`, completing the cycle -note: cycle used when const-evaluating `X::A::{{constant}}` +note: ...which requires processing `X::A::{{constant}}`... --> $DIR/issue-23302-1.rs:14:9 | LL | A = X::A as isize, //~ ERROR E0391 | ^^^^^^^^^^^^^ + = note: ...which again requires const-evaluating `X::A::{{constant}}`, completing the cycle error: aborting due to previous error diff --git a/src/test/ui/issue-23302-2.stderr b/src/test/ui/issue-23302-2.stderr index 146f86127c5e4..ee51c3ac7e335 100644 --- a/src/test/ui/issue-23302-2.stderr +++ b/src/test/ui/issue-23302-2.stderr @@ -1,15 +1,15 @@ -error[E0391]: cycle detected when processing `Y::A::{{constant}}` +error[E0391]: cycle detected when const-evaluating `Y::A::{{constant}}` --> $DIR/issue-23302-2.rs:14:9 | LL | A = Y::B as isize, //~ ERROR E0391 | ^^^^^^^^^^^^^ | - = note: ...which again requires processing `Y::A::{{constant}}`, completing the cycle -note: cycle used when const-evaluating `Y::A::{{constant}}` +note: ...which requires processing `Y::A::{{constant}}`... --> $DIR/issue-23302-2.rs:14:9 | LL | A = Y::B as isize, //~ ERROR E0391 | ^^^^^^^^^^^^^ + = note: ...which again requires const-evaluating `Y::A::{{constant}}`, completing the cycle error: aborting due to previous error diff --git a/src/test/ui/issue-23302-3.stderr b/src/test/ui/issue-23302-3.stderr index 54edf42679aef..ef5b0c79c6456 100644 --- a/src/test/ui/issue-23302-3.stderr +++ b/src/test/ui/issue-23302-3.stderr @@ -1,25 +1,15 @@ -error[E0391]: cycle detected when const checking if rvalue is promotable to static `A` - --> $DIR/issue-23302-3.rs:11:1 - | -LL | const A: i32 = B; //~ ERROR cycle detected - | ^^^^^^^^^^^^^^^^^ - | -note: ...which requires checking which parts of `A` are promotable to static... +error[E0391]: cycle detected when const-evaluating `A` --> $DIR/issue-23302-3.rs:11:16 | LL | const A: i32 = B; //~ ERROR cycle detected | ^ -note: ...which requires const checking if rvalue is promotable to static `B`... - --> $DIR/issue-23302-3.rs:13:1 | -LL | const B: i32 = A; - | ^^^^^^^^^^^^^^^^^ -note: ...which requires checking which parts of `B` are promotable to static... +note: ...which requires const-evaluating `B`... --> $DIR/issue-23302-3.rs:13:16 | LL | const B: i32 = A; | ^ - = note: ...which again requires const checking if rvalue is promotable to static `A`, completing the cycle + = note: ...which again requires const-evaluating `A`, completing the cycle error: aborting due to previous error diff --git a/src/test/ui/issue-36163.stderr b/src/test/ui/issue-36163.stderr index 5623437669f06..793f4689af521 100644 --- a/src/test/ui/issue-36163.stderr +++ b/src/test/ui/issue-36163.stderr @@ -1,20 +1,20 @@ -error[E0391]: cycle detected when processing `Foo::B::{{constant}}` +error[E0391]: cycle detected when const-evaluating `Foo::B::{{constant}}` --> $DIR/issue-36163.rs:14:9 | LL | B = A, //~ ERROR E0391 | ^ | -note: ...which requires processing `A`... - --> $DIR/issue-36163.rs:11:18 - | -LL | const A: isize = Foo::B as isize; - | ^^^^^^^^^^^^^^^ - = note: ...which again requires processing `Foo::B::{{constant}}`, completing the cycle -note: cycle used when const-evaluating `Foo::B::{{constant}}` +note: ...which requires processing `Foo::B::{{constant}}`... --> $DIR/issue-36163.rs:14:9 | LL | B = A, //~ ERROR E0391 | ^ +note: ...which requires const-evaluating `A`... + --> $DIR/issue-36163.rs:11:18 + | +LL | const A: isize = Foo::B as isize; + | ^^^^^^^^^^^^^^^ + = note: ...which again requires const-evaluating `Foo::B::{{constant}}`, completing the cycle error: aborting due to previous error diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index ad86844cec323..cb38605c75362 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2978,7 +2978,7 @@ impl<'test> TestCx<'test> { fn delete_file(&self, file: &PathBuf) { if let Err(e) = ::std::fs::remove_file(file) { - self.fatal(&format!( + self.error(&format!( "failed to delete `{}`: {}", file.display(), e,