Auto merge of #61044 - Centril:rollup-ztsgb9p, r=Centril

Rollup of 8 pull requests

Successful merges:

 - #60300 (Allow null-pointer-optimized enums in FFI if their underlying representation is FFI safe)
 - #60773 (Always try to project predicates when finding auto traits in rustdoc)
 - #60809 (Add FAQ for NLL migration)
 - #61023 (Migrate from recursion to iterate on qualify consts visitor impl)
 - #61029 (Simplify RefCell minimum_spanning_tree example)
 - #61030 (Make maybe_codegen_consume_direct iterate instead of doing recursion)
 - #61034 (rustc_metadata: parametrize schema::CrateRoot by 'tcx and rip out old unused incremental infra.)
 - #61037 (Update clippy submodule)

Failed merges:

r? @ghost
This commit is contained in:
bors 2019-05-22 22:57:48 +00:00
commit 11f01bfb9f
45 changed files with 592 additions and 848 deletions

View File

@ -67,16 +67,26 @@
//! mutability:
//!
//! ```
//! use std::cell::{RefCell, RefMut};
//! use std::collections::HashMap;
//! use std::cell::RefCell;
//! use std::rc::Rc;
//!
//! fn main() {
//! let shared_map: Rc<RefCell<_>> = Rc::new(RefCell::new(HashMap::new()));
//! shared_map.borrow_mut().insert("africa", 92388);
//! shared_map.borrow_mut().insert("kyoto", 11837);
//! shared_map.borrow_mut().insert("piccadilly", 11826);
//! shared_map.borrow_mut().insert("marbles", 38);
//! // Create a new block to limit the scope of the dynamic borrow
//! {
//! let mut map: RefMut<_> = shared_map.borrow_mut();
//! map.insert("africa", 92388);
//! map.insert("kyoto", 11837);
//! map.insert("piccadilly", 11826);
//! map.insert("marbles", 38);
//! }
//!
//! // Note that if we had not let the previous borrow of the cache fall out
//! // of scope then the subsequent borrow would cause a dynamic thread panic.
//! // This is the major hazard of using `RefCell`.
//! let total: i32 = shared_map.borrow().values().sum();
//! println!("{}", total);
//! }
//! ```
//!
@ -102,27 +112,15 @@
//!
//! impl Graph {
//! fn minimum_spanning_tree(&self) -> Vec<(i32, i32)> {
//! // Create a new scope to contain the lifetime of the
//! // dynamic borrow
//! {
//! // Take a reference to the inside of cache cell
//! let mut cache = self.span_tree_cache.borrow_mut();
//! if cache.is_some() {
//! return cache.as_ref().unwrap().clone();
//! }
//!
//! let span_tree = self.calc_span_tree();
//! *cache = Some(span_tree);
//! }
//!
//! // Recursive call to return the just-cached value.
//! // Note that if we had not let the previous borrow
//! // of the cache fall out of scope then the subsequent
//! // recursive borrow would cause a dynamic thread panic.
//! // This is the major hazard of using `RefCell`.
//! self.minimum_spanning_tree()
//! self.span_tree_cache.borrow_mut()
//! .get_or_insert_with(|| self.calc_span_tree())
//! .clone()
//! }
//!
//! fn calc_span_tree(&self) -> Vec<(i32, i32)> {
//! // Expensive computation goes here
//! vec![]
//! }
//! # fn calc_span_tree(&self) -> Vec<(i32, i32)> { vec![] }
//! }
//! ```
//!

View File

@ -50,6 +50,7 @@ assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", s
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
#[cfg_attr(not(stage0), rustc_nonnull_optimization_guaranteed)]
pub struct $Ty($Int);
}

View File

@ -2938,6 +2938,7 @@ impl<'a, T: ?Sized> From<NonNull<T>> for Unique<T> {
#[stable(feature = "nonnull", since = "1.25.0")]
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
#[cfg_attr(not(stage0), rustc_nonnull_optimization_guaranteed)]
pub struct NonNull<T: ?Sized> {
pointer: *const T,
}

View File

@ -700,22 +700,64 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
}
}
// We can only call poly_project_and_unify_type when our predicate's
// Ty contains an inference variable - otherwise, there won't be anything to
// unify
if p.ty().skip_binder().has_infer_types() {
debug!("Projecting and unifying projection predicate {:?}",
predicate);
match poly_project_and_unify_type(select, &obligation.with(p)) {
Err(e) => {
debug!(
"evaluate_nested_obligations: Unable to unify predicate \
'{:?}' '{:?}', bailing out",
ty, e
);
return false;
}
Ok(Some(v)) => {
// There are three possible cases when we project a predicate:
//
// 1. We encounter an error. This means that it's impossible for
// our current type to implement the auto trait - there's bound
// that we could add to our ParamEnv that would 'fix' this kind
// of error, as it's not caused by an unimplemented type.
//
// 2. We succesfully project the predicate (Ok(Some(_))), generating
// some subobligations. We then process these subobligations
// like any other generated sub-obligations.
//
// 3. We receieve an 'ambiguous' result (Ok(None))
// If we were actually trying to compile a crate,
// we would need to re-process this obligation later.
// However, all we care about is finding out what bounds
// are needed for our type to implement a particular auto trait.
// We've already added this obligation to our computed ParamEnv
// above (if it was necessary). Therefore, we don't need
// to do any further processing of the obligation.
//
// Note that we *must* try to project *all* projection predicates
// we encounter, even ones without inference variable.
// This ensures that we detect any projection errors,
// which indicate that our type can *never* implement the given
// auto trait. In that case, we will generate an explicit negative
// impl (e.g. 'impl !Send for MyType'). However, we don't
// try to process any of the generated subobligations -
// they contain no new information, since we already know
// that our type implements the projected-through trait,
// and can lead to weird region issues.
//
// Normally, we'll generate a negative impl as a result of encountering
// a type with an explicit negative impl of an auto trait
// (for example, raw pointers have !Send and !Sync impls)
// However, through some **interesting** manipulations of the type
// system, it's actually possible to write a type that never
// implements an auto trait due to a projection error, not a normal
// negative impl error. To properly handle this case, we need
// to ensure that we catch any potential projection errors,
// and turn them into an explicit negative impl for our type.
debug!("Projecting and unifying projection predicate {:?}",
predicate);
match poly_project_and_unify_type(select, &obligation.with(p)) {
Err(e) => {
debug!(
"evaluate_nested_obligations: Unable to unify predicate \
'{:?}' '{:?}', bailing out",
ty, e
);
return false;
}
Ok(Some(v)) => {
// We only care about sub-obligations
// when we started out trying to unify
// some inference variables. See the comment above
// for more infomration
if p.ty().skip_binder().has_infer_types() {
if !self.evaluate_nested_obligations(
ty,
v.clone().iter().cloned(),
@ -728,7 +770,16 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
return false;
}
}
Ok(None) => {
}
Ok(None) => {
// It's ok not to make progress when hvave no inference variables -
// in that case, we were only performing unifcation to check if an
// error occured (which would indicate that it's impossible for our
// type to implement the auto trait).
// However, we should always make progress (either by generating
// subobligations or getting an error) when we started off with
// inference variables
if p.ty().skip_binder().has_infer_types() {
panic!("Unexpected result when selecting {:?} {:?}", ty, obligation)
}
}

View File

@ -380,45 +380,47 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
) -> Option<OperandRef<'tcx, Bx::Value>> {
debug!("maybe_codegen_consume_direct(place={:?})", place);
// watch out for locals that do not have an
// alloca; they are handled somewhat differently
if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
match self.locals[index] {
LocalRef::Operand(Some(o)) => {
return Some(o);
}
LocalRef::Operand(None) => {
bug!("use of {:?} before def", place);
}
LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
// use path below
}
}
}
// Moves out of scalar and scalar pair fields are trivial.
if let &mir::Place::Projection(ref proj) = place {
if let Some(o) = self.maybe_codegen_consume_direct(bx, &proj.base) {
match proj.elem {
mir::ProjectionElem::Field(ref f, _) => {
return Some(o.extract_field(bx, f.index()));
}
mir::ProjectionElem::Index(_) |
mir::ProjectionElem::ConstantIndex { .. } => {
// ZSTs don't require any actual memory access.
// FIXME(eddyb) deduplicate this with the identical
// checks in `codegen_consume` and `extract_field`.
let elem = o.layout.field(bx.cx(), 0);
if elem.is_zst() {
return Some(OperandRef::new_zst(bx, elem));
place.iterate(|place_base, place_projection| {
if let mir::PlaceBase::Local(index) = place_base {
match self.locals[*index] {
LocalRef::Operand(Some(mut o)) => {
// Moves out of scalar and scalar pair fields are trivial.
for proj in place_projection {
match proj.elem {
mir::ProjectionElem::Field(ref f, _) => {
o = o.extract_field(bx, f.index());
}
mir::ProjectionElem::Index(_) |
mir::ProjectionElem::ConstantIndex { .. } => {
// ZSTs don't require any actual memory access.
// FIXME(eddyb) deduplicate this with the identical
// checks in `codegen_consume` and `extract_field`.
let elem = o.layout.field(bx.cx(), 0);
if elem.is_zst() {
o = OperandRef::new_zst(bx, elem);
} else {
return None;
}
}
_ => return None,
}
}
}
_ => {}
}
}
}
None
Some(o)
}
LocalRef::Operand(None) => {
bug!("use of {:?} before def", place);
}
LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
// watch out for locals that do not have an
// alloca; they are handled somewhat differently
None
}
}
} else {
None
}
})
}
pub fn codegen_consume(

View File

@ -1,10 +1,11 @@
#![allow(non_snake_case)]
use rustc::hir::{ExprKind, Node};
use crate::hir::def_id::DefId;
use rustc::hir::lowering::is_range_literal;
use rustc::ty::subst::SubstsRef;
use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
use rustc::ty::layout::{self, IntegerExt, LayoutOf, VariantIdx};
use rustc::ty::layout::{self, IntegerExt, LayoutOf, VariantIdx, SizeSkeleton};
use rustc::{lint, util};
use rustc_data_structures::indexed_vec::Idx;
use util::nodemap::FxHashSet;
@ -14,11 +15,11 @@ use lint::{LintPass, LateLintPass};
use std::cmp;
use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
use syntax::{ast, attr};
use syntax::{ast, attr, source_map};
use syntax::errors::Applicability;
use syntax::symbol::sym;
use rustc_target::spec::abi::Abi;
use syntax_pos::Span;
use syntax::source_map;
use rustc::hir;
@ -522,42 +523,79 @@ enum FfiResult<'tcx> {
},
}
fn is_zst<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId, ty: Ty<'tcx>) -> bool {
tcx.layout_of(tcx.param_env(did).and(ty)).map(|layout| layout.is_zst()).unwrap_or(false)
}
fn ty_is_known_nonnull<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
match ty.sty {
ty::FnPtr(_) => true,
ty::Ref(..) => true,
ty::Adt(field_def, substs) if field_def.repr.transparent() && field_def.is_struct() => {
for field in &field_def.non_enum_variant().fields {
let field_ty = tcx.normalize_erasing_regions(
ParamEnv::reveal_all(),
field.ty(tcx, substs),
);
if is_zst(tcx, field.did, field_ty) {
continue;
}
let attrs = tcx.get_attrs(field_def.did);
if attrs.iter().any(|a| a.check_name(sym::rustc_nonnull_optimization_guaranteed)) ||
ty_is_known_nonnull(tcx, field_ty) {
return true;
}
}
false
}
_ => false,
}
}
/// Check if this enum can be safely exported based on the
/// "nullable pointer optimization". Currently restricted
/// to function pointers and references, but could be
/// expanded to cover NonZero raw pointers and newtypes.
/// to function pointers, references, core::num::NonZero*,
/// core::ptr::NonNull, and #[repr(transparent)] newtypes.
/// FIXME: This duplicates code in codegen.
fn is_repr_nullable_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def: &'tcx ty::AdtDef,
ty: Ty<'tcx>,
ty_def: &'tcx ty::AdtDef,
substs: SubstsRef<'tcx>)
-> bool {
if def.variants.len() == 2 {
let data_idx;
let zero = VariantIdx::new(0);
let one = VariantIdx::new(1);
if def.variants[zero].fields.is_empty() {
data_idx = one;
} else if def.variants[one].fields.is_empty() {
data_idx = zero;
} else {
return false;
}
if def.variants[data_idx].fields.len() == 1 {
match def.variants[data_idx].fields[0].ty(tcx, substs).sty {
ty::FnPtr(_) => {
return true;
}
ty::Ref(..) => {
return true;
}
_ => {}
}
}
if ty_def.variants.len() != 2 {
return false;
}
false
let get_variant_fields = |index| &ty_def.variants[VariantIdx::new(index)].fields;
let variant_fields = [get_variant_fields(0), get_variant_fields(1)];
let fields = if variant_fields[0].is_empty() {
&variant_fields[1]
} else if variant_fields[1].is_empty() {
&variant_fields[0]
} else {
return false;
};
if fields.len() != 1 {
return false;
}
let field_ty = fields[0].ty(tcx, substs);
if !ty_is_known_nonnull(tcx, field_ty) {
return false;
}
// At this point, the field's type is known to be nonnull and the parent enum is Option-like.
// If the computed size for the field and the enum are different, the nonnull optimization isn't
// being applied (and we've got a problem somewhere).
let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, ParamEnv::reveal_all()).unwrap();
if !compute_size_skeleton(ty).same_size(compute_size_skeleton(field_ty)) {
bug!("improper_ctypes: Option nonnull optimization not applied?");
}
true
}
impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
@ -612,14 +650,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
);
// repr(transparent) types are allowed to have arbitrary ZSTs, not just
// PhantomData -- skip checking all ZST fields
if def.repr.transparent() {
let is_zst = cx
.layout_of(cx.param_env(field.did).and(field_ty))
.map(|layout| layout.is_zst())
.unwrap_or(false);
if is_zst {
continue;
}
if def.repr.transparent() && is_zst(cx, field.did, field_ty) {
continue;
}
let r = self.check_type_for_ffi(cache, field_ty);
match r {
@ -682,7 +714,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
// discriminant.
if !def.repr.c() && def.repr.int.is_none() {
// Special-case types like `Option<extern fn()>`.
if !is_repr_nullable_ptr(cx, def, substs) {
if !is_repr_nullable_ptr(cx, ty, def, substs) {
return FfiUnsafe {
ty: ty,
reason: "enum has no representation hint",

View File

@ -162,7 +162,7 @@ impl<'a> CrateLoader<'a> {
fn verify_no_symbol_conflicts(&self,
span: Span,
root: &CrateRoot) {
root: &CrateRoot<'_>) {
// Check for (potential) conflicts with the local crate
if self.local_crate_name == root.name &&
self.sess.local_crate_disambiguator() == root.disambiguator {
@ -476,7 +476,7 @@ impl<'a> CrateLoader<'a> {
// Go through the crate metadata and load any crates that it references
fn resolve_crate_deps(&mut self,
root: &Option<CratePaths>,
crate_root: &CrateRoot,
crate_root: &CrateRoot<'_>,
metadata: &MetadataBlob,
krate: CrateNum,
span: Span,
@ -582,7 +582,7 @@ impl<'a> CrateLoader<'a> {
/// implemented as dynamic libraries, but we have a possible future where
/// custom derive (and other macro-1.1 style features) are implemented via
/// executables and custom IPC.
fn load_derive_macros(&mut self, root: &CrateRoot, dylib: Option<PathBuf>, span: Span)
fn load_derive_macros(&mut self, root: &CrateRoot<'_>, dylib: Option<PathBuf>, span: Span)
-> Vec<(ast::Name, Lrc<SyntaxExtension>)> {
use std::{env, mem};
use crate::dynamic_lib::DynamicLibrary;

View File

@ -64,7 +64,11 @@ pub struct CrateMetadata {
/// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
pub alloc_decoding_state: AllocDecodingState,
pub root: schema::CrateRoot,
// NOTE(eddyb) we pass `'static` to a `'tcx` parameter because this
// lifetime is only used behind `Lazy` / `LazySeq`, and therefore
// acts like an universal (`for<'tcx>`), that is paired up with
// whichever `TyCtxt` is being used to decode those values.
pub root: schema::CrateRoot<'static>,
/// For each public item in this crate, we encode a key. When the
/// crate is loaded, we read all the keys and put them in this

View File

@ -246,12 +246,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
used_crate_source => { Lrc::new(cdata.source.clone()) }
exported_symbols => {
let cnum = cdata.cnum;
assert!(cnum != LOCAL_CRATE);
Arc::new(cdata.exported_symbols(tcx))
}
exported_symbols => { Arc::new(cdata.exported_symbols(tcx)) }
}
pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {

View File

@ -365,7 +365,7 @@ for DecodeContext<'a, 'tcx> {
implement_ty_decoder!( DecodeContext<'a, 'tcx> );
impl<'a, 'tcx> MetadataBlob {
impl<'tcx> MetadataBlob {
pub fn is_compatible(&self) -> bool {
self.raw_bytes().starts_with(METADATA_HEADER)
}
@ -374,7 +374,7 @@ impl<'a, 'tcx> MetadataBlob {
Lazy::with_position(METADATA_HEADER.len() + 4).decode(self)
}
pub fn get_root(&self) -> CrateRoot {
pub fn get_root(&self) -> CrateRoot<'tcx> {
let slice = self.raw_bytes();
let offset = METADATA_HEADER.len();
let pos = (((slice[offset + 0] as u32) << 24) | ((slice[offset + 1] as u32) << 16) |
@ -444,7 +444,7 @@ impl<'tcx> EntryKind<'tcx> {
/// |- proc macro #0 (DefIndex 1:N)
/// |- proc macro #1 (DefIndex 1:N+1)
/// \- ...
crate fn proc_macro_def_path_table(crate_root: &CrateRoot,
crate fn proc_macro_def_path_table(crate_root: &CrateRoot<'_>,
proc_macros: &[(ast::Name, Lrc<SyntaxExtension>)])
-> DefPathTable
{
@ -475,7 +475,7 @@ impl<'a, 'tcx> CrateMetadata {
fn maybe_entry(&self, item_id: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
assert!(!self.is_proc_macro(item_id));
self.root.index.lookup(self.blob.raw_bytes(), item_id)
self.root.entries_index.lookup(self.blob.raw_bytes(), item_id)
}
fn entry(&self, item_id: DefIndex) -> Entry<'tcx> {
@ -1126,10 +1126,7 @@ impl<'a, 'tcx> CrateMetadata {
// link those in so we skip those crates.
vec![]
} else {
let lazy_seq: LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)> =
LazySeq::with_position_and_length(self.root.exported_symbols.position,
self.root.exported_symbols.len);
lazy_seq.decode((self, tcx)).collect()
self.root.exported_symbols.decode((self, tcx)).collect()
}
}

View File

@ -1,6 +1,4 @@
use crate::index::Index;
use crate::index_builder::{FromId, IndexBuilder, Untracked};
use crate::isolated_encoder::IsolatedEncoder;
use crate::schema::*;
use rustc::middle::cstore::{LinkagePreference, NativeLibrary,
@ -46,6 +44,8 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
opaque: opaque::Encoder,
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
entries_index: Index<'tcx>,
lazy_state: LazyState,
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
@ -300,28 +300,34 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
})
}
// Encodes something that corresponds to a single DepNode::GlobalMetaData
// and registers the Fingerprint in the `metadata_hashes` map.
pub fn tracked<'x, DATA, R>(&'x mut self,
op: fn(&mut IsolatedEncoder<'x, 'a, 'tcx>, DATA) -> R,
data: DATA)
-> R {
op(&mut IsolatedEncoder::new(self), data)
/// Emit the data for a `DefId` to the metadata. The function to
/// emit the data is `op`, and it will be given `data` as
/// arguments. This `record` function will call `op` to generate
/// the `Entry` (which may point to other encoded information)
/// and will then record the `Lazy<Entry>` for use in the index.
// FIXME(eddyb) remove this.
pub fn record<DATA>(&mut self,
id: DefId,
op: impl FnOnce(&mut Self, DATA) -> Entry<'tcx>,
data: DATA)
{
assert!(id.is_local());
let entry = op(self, data);
let entry = self.lazy(&entry);
self.entries_index.record(id, entry);
}
fn encode_info_for_items(&mut self) -> Index {
fn encode_info_for_items(&mut self) {
let krate = self.tcx.hir().krate();
let mut index = IndexBuilder::new(self);
let vis = Spanned { span: syntax_pos::DUMMY_SP, node: hir::VisibilityKind::Public };
index.record(DefId::local(CRATE_DEF_INDEX),
IsolatedEncoder::encode_info_for_mod,
FromId(hir::CRATE_HIR_ID, (&krate.module, &krate.attrs, &vis)));
let mut visitor = EncodeVisitor { index };
krate.visit_all_item_likes(&mut visitor.as_deep_visitor());
self.record(DefId::local(CRATE_DEF_INDEX),
EncodeContext::encode_info_for_mod,
(hir::CRATE_HIR_ID, &krate.module, &krate.attrs, &vis));
krate.visit_all_item_likes(&mut self.as_deep_visitor());
for macro_def in &krate.exported_macros {
visitor.visit_macro_def(macro_def);
self.visit_macro_def(macro_def);
}
visitor.index.into_items()
}
fn encode_def_path_table(&mut self) -> Lazy<DefPathTable> {
@ -371,38 +377,30 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
self.lazy_seq_ref(adapted.iter().map(|rc| &**rc))
}
fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
let mut i = self.position();
let crate_deps = self.tracked(IsolatedEncoder::encode_crate_deps, ());
let dylib_dependency_formats = self.tracked(
IsolatedEncoder::encode_dylib_dependency_formats,
());
let crate_deps = self.encode_crate_deps();
let dylib_dependency_formats = self.encode_dylib_dependency_formats();
let dep_bytes = self.position() - i;
// Encode the lib features.
i = self.position();
let lib_features = self.tracked(IsolatedEncoder::encode_lib_features, ());
let lib_features = self.encode_lib_features();
let lib_feature_bytes = self.position() - i;
// Encode the language items.
i = self.position();
let lang_items = self.tracked(IsolatedEncoder::encode_lang_items, ());
let lang_items_missing = self.tracked(
IsolatedEncoder::encode_lang_items_missing,
());
let lang_items = self.encode_lang_items();
let lang_items_missing = self.encode_lang_items_missing();
let lang_item_bytes = self.position() - i;
// Encode the native libraries used
i = self.position();
let native_libraries = self.tracked(
IsolatedEncoder::encode_native_libraries,
());
let native_libraries = self.encode_native_libraries();
let native_lib_bytes = self.position() - i;
let foreign_modules = self.tracked(
IsolatedEncoder::encode_foreign_modules,
());
let foreign_modules = self.encode_foreign_modules();
// Encode source_map
i = self.position();
@ -416,22 +414,20 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
// Encode the def IDs of impls, for coherence checking.
i = self.position();
let impls = self.tracked(IsolatedEncoder::encode_impls, ());
let impls = self.encode_impls();
let impl_bytes = self.position() - i;
// Encode exported symbols info.
i = self.position();
let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE);
let exported_symbols = self.tracked(
IsolatedEncoder::encode_exported_symbols,
&exported_symbols);
let exported_symbols = self.encode_exported_symbols(&exported_symbols);
let exported_symbols_bytes = self.position() - i;
let tcx = self.tcx;
// Encode the items.
i = self.position();
let items = self.encode_info_for_items();
self.encode_info_for_items();
let item_bytes = self.position() - i;
// Encode the allocation index
@ -462,10 +458,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
self.lazy_seq(interpret_alloc_index)
};
// Index the items
i = self.position();
let index = items.write_index(&mut self.opaque);
let index_bytes = self.position() - i;
let entries_index = self.entries_index.write_index(&mut self.opaque);
let entries_index_bytes = self.position() - i;
let attrs = tcx.hir().krate_attrs();
let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro);
@ -516,7 +511,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
impls,
exported_symbols,
interpret_alloc_index,
index,
entries_index,
});
let total_bytes = self.position();
@ -539,7 +534,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
println!(" exp. symbols bytes: {}", exported_symbols_bytes);
println!(" def-path table bytes: {}", def_path_table_bytes);
println!(" item bytes: {}", item_bytes);
println!(" index bytes: {}", index_bytes);
println!(" entries index bytes: {}", entries_index_bytes);
println!(" zero bytes: {}", zero_bytes);
println!(" total bytes: {}", total_bytes);
}
@ -548,40 +543,29 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
}
// These are methods for encoding various things. They are meant to be used with
// IndexBuilder::record() and EncodeContext::tracked(). They actually
// would not have to be methods of IsolatedEncoder (free standing functions
// taking IsolatedEncoder as first argument would be just fine) but by making
// them methods we don't have to repeat the lengthy `<'a, 'b: 'a, 'tcx: 'b>`
// clause again and again.
impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
impl EncodeContext<'_, 'tcx> {
fn encode_variances_of(&mut self, def_id: DefId) -> LazySeq<ty::Variance> {
debug!("IsolatedEncoder::encode_variances_of({:?})", def_id);
debug!("EncodeContext::encode_variances_of({:?})", def_id);
let tcx = self.tcx;
self.lazy_seq_from_slice(&tcx.variances_of(def_id))
self.lazy_seq_ref(&tcx.variances_of(def_id)[..])
}
fn encode_item_type(&mut self, def_id: DefId) -> Lazy<Ty<'tcx>> {
let tcx = self.tcx;
let ty = tcx.type_of(def_id);
debug!("IsolatedEncoder::encode_item_type({:?}) => {:?}", def_id, ty);
debug!("EncodeContext::encode_item_type({:?}) => {:?}", def_id, ty);
self.lazy(&ty)
}
/// Encode data for the given variant of the given ADT. The
/// index of the variant is untracked: this is ok because we
/// will have to lookup the adt-def by its id, and that gives us
/// the right to access any information in the adt-def (including,
/// e.g., the length of the various vectors).
fn encode_enum_variant_info(
&mut self,
(enum_did, Untracked(index)): (DefId, Untracked<VariantIdx>),
(enum_did, index): (DefId, VariantIdx),
) -> Entry<'tcx> {
let tcx = self.tcx;
let def = tcx.adt_def(enum_did);
let variant = &def.variants[index];
let def_id = variant.def_id;
debug!("IsolatedEncoder::encode_enum_variant_info({:?})", def_id);
debug!("EncodeContext::encode_enum_variant_info({:?})", def_id);
let data = VariantData {
ctor_kind: variant.ctor_kind,
@ -625,17 +609,15 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
}
}
/// Encode the constructor for the given variant of the given ADT. See
/// `encode_enum_variant_info` for an explanation about why the index is untracked.
fn encode_enum_variant_ctor(
&mut self,
(enum_did, Untracked(index)): (DefId, Untracked<VariantIdx>),
(enum_did, index): (DefId, VariantIdx),
) -> Entry<'tcx> {
let tcx = self.tcx;
let def = tcx.adt_def(enum_did);
let variant = &def.variants[index];
let def_id = variant.ctor_def_id.unwrap();
debug!("IsolatedEncoder::encode_enum_variant_ctor({:?})", def_id);
debug!("EncodeContext::encode_enum_variant_ctor({:?})", def_id);
let data = VariantData {
ctor_kind: variant.ctor_kind,
@ -681,18 +663,17 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
}
}
fn encode_info_for_mod(&mut self,
FromId(id, (md, attrs, vis)): FromId<(&hir::Mod,
&[ast::Attribute],
&hir::Visibility)>)
-> Entry<'tcx> {
fn encode_info_for_mod(
&mut self,
(id, md, attrs, vis): (hir::HirId, &hir::Mod, &[ast::Attribute], &hir::Visibility),
) -> Entry<'tcx> {
let tcx = self.tcx;
let def_id = tcx.hir().local_def_id_from_hir_id(id);
debug!("IsolatedEncoder::encode_info_for_mod({:?})", def_id);
debug!("EncodeContext::encode_info_for_mod({:?})", def_id);
let data = ModData {
reexports: match tcx.module_exports(def_id) {
Some(ref exports) => self.lazy_seq_from_slice(exports.as_slice()),
Some(ref exports) => self.lazy_seq_ref(&exports[..]),
_ => LazySeq::empty(),
},
};
@ -719,23 +700,16 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
}
}
/// Encode data for the given field of the given variant of the
/// given ADT. The indices of the variant/field are untracked:
/// this is ok because we will have to lookup the adt-def by its
/// id, and that gives us the right to access any information in
/// the adt-def (including, e.g., the length of the various
/// vectors).
fn encode_field(&mut self,
(adt_def_id, Untracked((variant_index, field_index))): (DefId,
Untracked<(VariantIdx,
usize)>))
-> Entry<'tcx> {
fn encode_field(
&mut self,
(adt_def_id, variant_index, field_index): (DefId, VariantIdx, usize),
) -> Entry<'tcx> {
let tcx = self.tcx;
let variant = &tcx.adt_def(adt_def_id).variants[variant_index];
let field = &variant.fields[field_index];
let def_id = field.did;
debug!("IsolatedEncoder::encode_field({:?})", def_id);
debug!("EncodeContext::encode_field({:?})", def_id);
let variant_id = tcx.hir().as_local_hir_id(variant.def_id).unwrap();
let variant_data = tcx.hir().expect_variant_data(variant_id);
@ -761,7 +735,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
}
fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<'tcx> {
debug!("IsolatedEncoder::encode_struct_ctor({:?})", def_id);
debug!("EncodeContext::encode_struct_ctor({:?})", def_id);
let tcx = self.tcx;
let adt_def = tcx.adt_def(adt_def_id);
let variant = adt_def.non_enum_variant();
@ -821,25 +795,25 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
}
fn encode_generics(&mut self, def_id: DefId) -> Lazy<ty::Generics> {
debug!("IsolatedEncoder::encode_generics({:?})", def_id);
debug!("EncodeContext::encode_generics({:?})", def_id);
let tcx = self.tcx;
self.lazy(tcx.generics_of(def_id))
}
fn encode_predicates(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> {
debug!("IsolatedEncoder::encode_predicates({:?})", def_id);
debug!("EncodeContext::encode_predicates({:?})", def_id);
let tcx = self.tcx;
self.lazy(&tcx.predicates_of(def_id))
}
fn encode_predicates_defined_on(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> {
debug!("IsolatedEncoder::encode_predicates_defined_on({:?})", def_id);
debug!("EncodeContext::encode_predicates_defined_on({:?})", def_id);
let tcx = self.tcx;
self.lazy(&tcx.predicates_defined_on(def_id))
}
fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
debug!("IsolatedEncoder::encode_info_for_trait_item({:?})", def_id);
debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id);
let tcx = self.tcx;
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
@ -949,7 +923,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
}
fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
debug!("IsolatedEncoder::encode_info_for_impl_item({:?})", def_id);
debug!("EncodeContext::encode_info_for_impl_item({:?})", def_id);
let tcx = self.tcx;
let hir_id = self.tcx.hir().as_local_hir_id(def_id).unwrap();
@ -1064,7 +1038,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
// Encodes the inherent implementations of a structure, enumeration, or trait.
fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq<DefIndex> {
debug!("IsolatedEncoder::encode_inherent_implementations({:?})", def_id);
debug!("EncodeContext::encode_inherent_implementations({:?})", def_id);
let implementations = self.tcx.inherent_impls(def_id);
if implementations.is_empty() {
LazySeq::empty()
@ -1077,12 +1051,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
}
fn encode_stability(&mut self, def_id: DefId) -> Option<Lazy<attr::Stability>> {
debug!("IsolatedEncoder::encode_stability({:?})", def_id);
debug!("EncodeContext::encode_stability({:?})", def_id);
self.tcx.lookup_stability(def_id).map(|stab| self.lazy(stab))
}
fn encode_deprecation(&mut self, def_id: DefId) -> Option<Lazy<attr::Deprecation>> {
debug!("IsolatedEncoder::encode_deprecation({:?})", def_id);
debug!("EncodeContext::encode_deprecation({:?})", def_id);
self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(&depr))
}
@ -1096,7 +1070,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> Entry<'tcx> {
let tcx = self.tcx;
debug!("IsolatedEncoder::encode_info_for_item({:?})", def_id);
debug!("EncodeContext::encode_info_for_item({:?})", def_id);
let kind = match item.node {
hir::ItemKind::Static(_, hir::MutMutable, _) => EntryKind::MutStatic,
@ -1118,7 +1092,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
EntryKind::Fn(self.lazy(&data))
}
hir::ItemKind::Mod(ref m) => {
return self.encode_info_for_mod(FromId(item.hir_id, (m, &item.attrs, &item.vis)));
return self.encode_info_for_mod((item.hir_id, m, &item.attrs, &item.vis));
}
hir::ItemKind::ForeignMod(_) => EntryKind::ForeignMod,
hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm,
@ -1391,9 +1365,9 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
fn encode_info_for_ty_param(
&mut self,
(def_id, Untracked(encode_type)): (DefId, Untracked<bool>),
(def_id, encode_type): (DefId, bool),
) -> Entry<'tcx> {
debug!("IsolatedEncoder::encode_info_for_ty_param({:?})", def_id);
debug!("EncodeContext::encode_info_for_ty_param({:?})", def_id);
self.encode_info_for_generic_param(def_id, EntryKind::TypeParam, encode_type)
}
@ -1401,12 +1375,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
&mut self,
def_id: DefId,
) -> Entry<'tcx> {
debug!("IsolatedEncoder::encode_info_for_const_param({:?})", def_id);
debug!("EncodeContext::encode_info_for_const_param({:?})", def_id);
self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true)
}
fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
debug!("IsolatedEncoder::encode_info_for_closure({:?})", def_id);
debug!("EncodeContext::encode_info_for_closure({:?})", def_id);
let tcx = self.tcx;
let tables = self.tcx.typeck_tables_of(def_id);
@ -1450,7 +1424,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
}
fn encode_info_for_anon_const(&mut self, def_id: DefId) -> Entry<'tcx> {
debug!("IsolatedEncoder::encode_info_for_anon_const({:?})", def_id);
debug!("EncodeContext::encode_info_for_anon_const({:?})", def_id);
let tcx = self.tcx;
let id = tcx.hir().as_local_hir_id(def_id).unwrap();
let body_id = tcx.hir().body_owned_by(id);
@ -1478,23 +1452,20 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
}
fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq<ast::Attribute> {
// NOTE: This must use lazy_seq_from_slice(), not lazy_seq() because
// we rely on the HashStable specialization for [Attribute]
// to properly filter things out.
self.lazy_seq_from_slice(attrs)
self.lazy_seq_ref(attrs)
}
fn encode_native_libraries(&mut self, _: ()) -> LazySeq<NativeLibrary> {
fn encode_native_libraries(&mut self) -> LazySeq<NativeLibrary> {
let used_libraries = self.tcx.native_libraries(LOCAL_CRATE);
self.lazy_seq(used_libraries.iter().cloned())
}
fn encode_foreign_modules(&mut self, _: ()) -> LazySeq<ForeignModule> {
fn encode_foreign_modules(&mut self) -> LazySeq<ForeignModule> {
let foreign_modules = self.tcx.foreign_modules(LOCAL_CRATE);
self.lazy_seq(foreign_modules.iter().cloned())
}
fn encode_crate_deps(&mut self, _: ()) -> LazySeq<CrateDep> {
fn encode_crate_deps(&mut self) -> LazySeq<CrateDep> {
let crates = self.tcx.crates();
let mut deps = crates
@ -1528,13 +1499,13 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
self.lazy_seq_ref(deps.iter().map(|&(_, ref dep)| dep))
}
fn encode_lib_features(&mut self, _: ()) -> LazySeq<(ast::Name, Option<ast::Name>)> {
fn encode_lib_features(&mut self) -> LazySeq<(ast::Name, Option<ast::Name>)> {
let tcx = self.tcx;
let lib_features = tcx.lib_features();
self.lazy_seq(lib_features.to_vec())
}
fn encode_lang_items(&mut self, _: ()) -> LazySeq<(DefIndex, usize)> {
fn encode_lang_items(&mut self) -> LazySeq<(DefIndex, usize)> {
let tcx = self.tcx;
let lang_items = tcx.lang_items();
let lang_items = lang_items.items().iter();
@ -1548,14 +1519,14 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
}))
}
fn encode_lang_items_missing(&mut self, _: ()) -> LazySeq<lang_items::LangItem> {
fn encode_lang_items_missing(&mut self) -> LazySeq<lang_items::LangItem> {
let tcx = self.tcx;
self.lazy_seq_ref(&tcx.lang_items().missing)
}
/// Encodes an index, mapping each trait to its (local) implementations.
fn encode_impls(&mut self, _: ()) -> LazySeq<TraitImpls> {
debug!("IsolatedEncoder::encode_impls()");
fn encode_impls(&mut self) -> LazySeq<TraitImpls> {
debug!("EncodeContext::encode_impls()");
let tcx = self.tcx;
let mut visitor = ImplVisitor {
tcx,
@ -1580,12 +1551,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
TraitImpls {
trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index),
impls: self.lazy_seq_from_slice(&impls[..]),
impls: self.lazy_seq_ref(&impls),
}
})
.collect();
self.lazy_seq_from_slice(&all_impls[..])
self.lazy_seq_ref(&all_impls)
}
// Encodes all symbols exported from this crate into the metadata.
@ -1595,13 +1566,13 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
// symbol associated with them (they weren't translated) or if they're an FFI
// definition (as that's not defined in this crate).
fn encode_exported_symbols(&mut self,
exported_symbols: &[(ExportedSymbol<'_>, SymbolExportLevel)])
-> EncodedExportedSymbols {
exported_symbols: &[(ExportedSymbol<'tcx>, SymbolExportLevel)])
-> LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)> {
// The metadata symbol name is special. It should not show up in
// downstream crates.
let metadata_symbol_name = SymbolName::new(&metadata_symbol_name(self.tcx));
let lazy_seq = self.lazy_seq(exported_symbols
self.lazy_seq(exported_symbols
.iter()
.filter(|&&(ref exported_symbol, _)| {
match *exported_symbol {
@ -1611,15 +1582,10 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
_ => true,
}
})
.cloned());
EncodedExportedSymbols {
len: lazy_seq.len,
position: lazy_seq.position,
}
.cloned())
}
fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq<Option<LinkagePreference>> {
fn encode_dylib_dependency_formats(&mut self) -> LazySeq<Option<LinkagePreference>> {
match self.tcx.sess.dependency_formats.borrow().get(&config::CrateType::Dylib) {
Some(arr) => {
self.lazy_seq(arr.iter().map(|slot| {
@ -1641,7 +1607,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
-> Entry<'tcx> {
let tcx = self.tcx;
debug!("IsolatedEncoder::encode_info_for_foreign_item({:?})", def_id);
debug!("EncodeContext::encode_info_for_foreign_item({:?})", def_id);
let kind = match nitem.node {
hir::ForeignItemKind::Fn(_, ref names, _) => {
@ -1681,33 +1647,29 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
}
}
struct EncodeVisitor<'a, 'b: 'a, 'tcx: 'b> {
index: IndexBuilder<'a, 'b, 'tcx>,
}
impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> {
impl Visitor<'tcx> for EncodeContext<'_, 'tcx> {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
NestedVisitorMap::OnlyBodies(&self.index.tcx.hir())
NestedVisitorMap::OnlyBodies(&self.tcx.hir())
}
fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
intravisit::walk_expr(self, ex);
self.index.encode_info_for_expr(ex);
self.encode_info_for_expr(ex);
}
fn visit_item(&mut self, item: &'tcx hir::Item) {
intravisit::walk_item(self, item);
let def_id = self.index.tcx.hir().local_def_id_from_hir_id(item.hir_id);
let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
match item.node {
hir::ItemKind::ExternCrate(_) |
hir::ItemKind::Use(..) => (), // ignore these
_ => self.index.record(def_id, IsolatedEncoder::encode_info_for_item, (def_id, item)),
hir::ItemKind::Use(..) => {} // ignore these
_ => self.record(def_id, EncodeContext::encode_info_for_item, (def_id, item)),
}
self.index.encode_addl_info_for_item(item);
self.encode_addl_info_for_item(item);
}
fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) {
intravisit::walk_foreign_item(self, ni);
let def_id = self.index.tcx.hir().local_def_id_from_hir_id(ni.hir_id);
self.index.record(def_id,
IsolatedEncoder::encode_info_for_foreign_item,
let def_id = self.tcx.hir().local_def_id_from_hir_id(ni.hir_id);
self.record(def_id,
EncodeContext::encode_info_for_foreign_item,
(def_id, ni));
}
fn visit_variant(&mut self,
@ -1717,32 +1679,32 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> {
intravisit::walk_variant(self, v, g, id);
if let Some(ref discr) = v.node.disr_expr {
let def_id = self.index.tcx.hir().local_def_id_from_hir_id(discr.hir_id);
self.index.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id);
let def_id = self.tcx.hir().local_def_id_from_hir_id(discr.hir_id);
self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id);
}
}
fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
intravisit::walk_generics(self, generics);
self.index.encode_info_for_generics(generics);
self.encode_info_for_generics(generics);
}
fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
intravisit::walk_ty(self, ty);
self.index.encode_info_for_ty(ty);
self.encode_info_for_ty(ty);
}
fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) {
let def_id = self.index.tcx.hir().local_def_id_from_hir_id(macro_def.hir_id);
self.index.record(def_id, IsolatedEncoder::encode_info_for_macro_def, macro_def);
let def_id = self.tcx.hir().local_def_id_from_hir_id(macro_def.hir_id);
self.record(def_id, EncodeContext::encode_info_for_macro_def, macro_def);
}
}
impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
impl EncodeContext<'_, 'tcx> {
fn encode_fields(&mut self, adt_def_id: DefId) {
let def = self.tcx.adt_def(adt_def_id);
for (variant_index, variant) in def.variants.iter_enumerated() {
for (field_index, field) in variant.fields.iter().enumerate() {
self.record(field.did,
IsolatedEncoder::encode_field,
(adt_def_id, Untracked((variant_index, field_index))));
EncodeContext::encode_field,
(adt_def_id, variant_index, field_index));
}
}
}
@ -1755,12 +1717,12 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
GenericParamKind::Type { ref default, .. } => {
self.record(
def_id,
IsolatedEncoder::encode_info_for_ty_param,
(def_id, Untracked(default.is_some())),
EncodeContext::encode_info_for_ty_param,
(def_id, default.is_some()),
);
}
GenericParamKind::Const { .. } => {
self.record(def_id, IsolatedEncoder::encode_info_for_const_param, def_id);
self.record(def_id, EncodeContext::encode_info_for_const_param, def_id);
}
}
}
@ -1770,7 +1732,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
match ty.node {
hir::TyKind::Array(_, ref length) => {
let def_id = self.tcx.hir().local_def_id_from_hir_id(length.hir_id);
self.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id);
self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id);
}
_ => {}
}
@ -1780,7 +1742,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
match expr.node {
hir::ExprKind::Closure(..) => {
let def_id = self.tcx.hir().local_def_id_from_hir_id(expr.hir_id);
self.record(def_id, IsolatedEncoder::encode_info_for_closure, def_id);
self.record(def_id, EncodeContext::encode_info_for_closure, def_id);
}
_ => {}
}
@ -1812,13 +1774,13 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
let def = self.tcx.adt_def(def_id);
for (i, variant) in def.variants.iter_enumerated() {
self.record(variant.def_id,
IsolatedEncoder::encode_enum_variant_info,
(def_id, Untracked(i)));
EncodeContext::encode_enum_variant_info,
(def_id, i));
if let Some(ctor_def_id) = variant.ctor_def_id {
self.record(ctor_def_id,
IsolatedEncoder::encode_enum_variant_ctor,
(def_id, Untracked(i)));
EncodeContext::encode_enum_variant_ctor,
(def_id, i));
}
}
}
@ -1829,7 +1791,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
let ctor_def_id = self.tcx.hir().local_def_id_from_hir_id(ctor_hir_id);
self.record(ctor_def_id,
IsolatedEncoder::encode_struct_ctor,
EncodeContext::encode_struct_ctor,
(def_id, ctor_def_id));
}
}
@ -1839,14 +1801,14 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
hir::ItemKind::Impl(..) => {
for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
self.record(trait_item_def_id,
IsolatedEncoder::encode_info_for_impl_item,
EncodeContext::encode_info_for_impl_item,
trait_item_def_id);
}
}
hir::ItemKind::Trait(..) => {
for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
self.record(item_def_id,
IsolatedEncoder::encode_info_for_trait_item,
EncodeContext::encode_info_for_trait_item,
item_def_id);
}
}
@ -1911,10 +1873,13 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
// Will be filled with the root position after encoding everything.
encoder.emit_raw_bytes(&[0, 0, 0, 0]);
let (root, mut result) = {
// Since encoding metadata is not in a query, and nothing is cached,
// there's no need to do dep-graph tracking for any of it.
let (root, mut result) = tcx.dep_graph.with_ignore(move || {
let mut ecx = EncodeContext {
opaque: encoder,
tcx,
entries_index: Index::new(tcx.hir().definitions().def_index_count()),
lazy_state: LazyState::NoNode,
type_shorthands: Default::default(),
predicate_shorthands: Default::default(),
@ -1930,7 +1895,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
// culminating in the `CrateRoot` which points to all of it.
let root = ecx.encode_crate_root();
(root, ecx.opaque.into_inner())
};
});
// Encode the root position.
let header = METADATA_HEADER.len();

View File

@ -2,6 +2,7 @@ use crate::schema::*;
use rustc::hir::def_id::{DefId, DefIndex};
use rustc_serialize::opaque::Encoder;
use std::marker::PhantomData;
use std::u32;
use log::debug;
@ -74,23 +75,25 @@ impl FixedSizeEncoding for u32 {
/// `u32::MAX`. Whenever an index is visited, we fill in the
/// appropriate spot by calling `record_position`. We should never
/// visit the same index twice.
pub struct Index {
pub struct Index<'tcx> {
positions: Vec<u8>,
_marker: PhantomData<&'tcx ()>,
}
impl Index {
pub fn new(max_index: usize) -> Index {
impl Index<'tcx> {
pub fn new(max_index: usize) -> Self {
Index {
positions: vec![0xff; max_index * 4],
_marker: PhantomData,
}
}
pub fn record(&mut self, def_id: DefId, entry: Lazy<Entry<'_>>) {
pub fn record(&mut self, def_id: DefId, entry: Lazy<Entry<'tcx>>) {
assert!(def_id.is_local());
self.record_index(def_id.index, entry);
}
pub fn record_index(&mut self, item: DefIndex, entry: Lazy<Entry<'_>>) {
pub fn record_index(&mut self, item: DefIndex, entry: Lazy<Entry<'tcx>>) {
assert!(entry.position < (u32::MAX as usize));
let position = entry.position as u32;
let array_index = item.index();
@ -105,7 +108,7 @@ impl Index {
position.write_to_bytes_at(positions, array_index)
}
pub fn write_index(&self, buf: &mut Encoder) -> LazySeq<Index> {
pub fn write_index(&self, buf: &mut Encoder) -> LazySeq<Self> {
let pos = buf.position();
// First we write the length of the lower range ...
@ -116,7 +119,7 @@ impl Index {
}
}
impl<'tcx> LazySeq<Index> {
impl LazySeq<Index<'tcx>> {
/// Given the metadata, extract out the offset of a particular
/// DefIndex (if any).
#[inline(never)]

View File

@ -1,224 +0,0 @@
//! Builder types for generating the "item data" section of the
//! metadata. This section winds up looking like this:
//!
//! ```
//! <common::data> // big list of item-like things...
//! <common::data_item> // ...for most `DefId`s, there is an entry.
//! </common::data_item>
//! </common::data>
//! ```
//!
//! As we generate this listing, we collect the offset of each
//! `data_item` entry and store it in an index. Then, when we load the
//! metadata, we can skip right to the metadata for a particular item.
//!
//! In addition to the offset, we need to track the data that was used
//! to generate the contents of each `data_item`. This is so that we
//! can figure out which HIR nodes contributed to that data for
//! incremental compilation purposes.
//!
//! The `IndexBuilder` facilitates both of these. It is created
//! with an `EncodingContext` (`ecx`), which it encapsulates.
//! It has one main method, `record()`. You invoke `record`
//! like so to create a new `data_item` element in the list:
//!
//! ```
//! index.record(some_def_id, callback_fn, data)
//! ```
//!
//! What record will do is to (a) record the current offset, (b) emit
//! the `common::data_item` tag, and then call `callback_fn` with the
//! given data as well as the `EncodingContext`. Once `callback_fn`
//! returns, the `common::data_item` tag will be closed.
//!
//! `EncodingContext` does not offer the `record` method, so that we
//! can ensure that `common::data_item` elements are never nested.
//!
//! In addition, while the `callback_fn` is executing, we will push a
//! task `MetaData(some_def_id)`, which can then observe the
//! reads/writes that occur in the task. For this reason, the `data`
//! argument that is given to the `callback_fn` must implement the
//! trait `DepGraphRead`, which indicates how to register reads on the
//! data in this new task (note that many types of data, such as
//! `DefId`, do not currently require any reads to be registered,
//! since they are not derived from a HIR node). This is also why we
//! give a callback fn, rather than taking a closure: it allows us to
//! easily control precisely what data is given to that fn.
use crate::encoder::EncodeContext;
use crate::index::Index;
use crate::schema::*;
use crate::isolated_encoder::IsolatedEncoder;
use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::ty::TyCtxt;
use syntax::ast;
use std::ops::{Deref, DerefMut};
/// Builder that can encode new items, adding them into the index.
/// Item encoding cannot be nested.
pub struct IndexBuilder<'a, 'b: 'a, 'tcx: 'b> {
items: Index,
pub ecx: &'a mut EncodeContext<'b, 'tcx>,
}
impl<'a, 'b, 'tcx> Deref for IndexBuilder<'a, 'b, 'tcx> {
type Target = EncodeContext<'b, 'tcx>;
fn deref(&self) -> &Self::Target {
self.ecx
}
}
impl<'a, 'b, 'tcx> DerefMut for IndexBuilder<'a, 'b, 'tcx> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.ecx
}
}
impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self {
IndexBuilder {
items: Index::new(ecx.tcx.hir().definitions().def_index_count()),
ecx,
}
}
/// Emit the data for a `DefId` to the metadata. The function to
/// emit the data is `op`, and it will be given `data` as
/// arguments. This `record` function will call `op` to generate
/// the `Entry` (which may point to other encoded information)
/// and will then record the `Lazy<Entry>` for use in the index.
///
/// In addition, it will setup a dep-graph task to track what data
/// `op` accesses to generate the metadata, which is later used by
/// incremental compilation to compute a hash for the metadata and
/// track changes.
///
/// The reason that `op` is a function pointer, and not a closure,
/// is that we want to be able to completely track all data it has
/// access to, so that we can be sure that `DATA: DepGraphRead`
/// holds, and that it is therefore not gaining "secret" access to
/// bits of HIR or other state that would not be trackd by the
/// content system.
pub fn record<'x, DATA>(&'x mut self,
id: DefId,
op: fn(&mut IsolatedEncoder<'x, 'b, 'tcx>, DATA) -> Entry<'tcx>,
data: DATA)
where DATA: DepGraphRead
{
assert!(id.is_local());
// We don't track this since we are explicitly computing the incr. comp.
// hashes anyway. In theory we could do some tracking here and use it to
// avoid rehashing things (and instead cache the hashes) but it's
// unclear whether that would be a win since hashing is cheap enough.
self.ecx.tcx.dep_graph.with_ignore(move || {
let mut entry_builder = IsolatedEncoder::new(self.ecx);
let entry = op(&mut entry_builder, data);
let entry = entry_builder.lazy(&entry);
self.items.record(id, entry);
})
}
pub fn into_items(self) -> Index {
self.items
}
}
/// Trait used for data that can be passed from outside a dep-graph
/// task. The data must either be of some safe type, such as a
/// `DefId` index, or implement the `read` method so that it can add
/// a read of whatever dep-graph nodes are appropriate.
pub trait DepGraphRead {
fn read(&self, tcx: TyCtxt<'_, '_, '_>);
}
impl DepGraphRead for DefId {
fn read(&self, _tcx: TyCtxt<'_, '_, '_>) {}
}
impl DepGraphRead for ast::NodeId {
fn read(&self, _tcx: TyCtxt<'_, '_, '_>) {}
}
impl<T> DepGraphRead for Option<T>
where T: DepGraphRead
{
fn read(&self, tcx: TyCtxt<'_, '_, '_>) {
match *self {
Some(ref v) => v.read(tcx),
None => (),
}
}
}
impl<T> DepGraphRead for [T]
where T: DepGraphRead
{
fn read(&self, tcx: TyCtxt<'_, '_, '_>) {
for i in self {
i.read(tcx);
}
}
}
macro_rules! read_tuple {
($($name:ident),*) => {
impl<$($name),*> DepGraphRead for ($($name),*)
where $($name: DepGraphRead),*
{
#[allow(non_snake_case)]
fn read(&self, tcx: TyCtxt<'_, '_, '_>) {
let &($(ref $name),*) = self;
$($name.read(tcx);)*
}
}
}
}
read_tuple!(A, B);
read_tuple!(A, B, C);
macro_rules! read_hir {
($t:ty) => {
impl<'tcx> DepGraphRead for &'tcx $t {
fn read(&self, tcx: TyCtxt<'_, '_, '_>) {
tcx.hir().read(self.hir_id);
}
}
}
}
read_hir!(hir::Item);
read_hir!(hir::ImplItem);
read_hir!(hir::TraitItem);
read_hir!(hir::ForeignItem);
read_hir!(hir::MacroDef);
/// Leaks access to a value of type T without any tracking. This is
/// suitable for ambiguous types like `usize`, which *could* represent
/// tracked data (e.g., if you read it out of a HIR node) or might not
/// (e.g., if it's an index). Adding in an `Untracked` is an
/// assertion, essentially, that the data does not need to be tracked
/// (or that read edges will be added by some other way).
///
/// A good idea is to add to each use of `Untracked` an explanation of
/// why this value is ok.
pub struct Untracked<T>(pub T);
impl<T> DepGraphRead for Untracked<T> {
fn read(&self, _tcx: TyCtxt<'_, '_, '_>) {}
}
/// Newtype that can be used to package up misc data extracted from a
/// HIR node that doesn't carry its own ID. This will allow an
/// arbitrary `T` to be passed in, but register a read on the given
/// `NodeId`.
pub struct FromId<T>(pub hir::HirId, pub T);
impl<T> DepGraphRead for FromId<T> {
fn read(&self, tcx: TyCtxt<'_, '_, '_>) {
tcx.hir().read(self.0);
}
}

View File

@ -1,48 +0,0 @@
use crate::encoder::EncodeContext;
use crate::schema::{Lazy, LazySeq};
use rustc::ty::TyCtxt;
use rustc_serialize::Encodable;
/// The IsolatedEncoder provides facilities to write to crate metadata while
/// making sure that anything going through it is also feed into an ICH hasher.
pub struct IsolatedEncoder<'a, 'b: 'a, 'tcx: 'b> {
pub tcx: TyCtxt<'b, 'tcx, 'tcx>,
ecx: &'a mut EncodeContext<'b, 'tcx>,
}
impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self {
let tcx = ecx.tcx;
IsolatedEncoder {
tcx,
ecx,
}
}
pub fn lazy<T>(&mut self, value: &T) -> Lazy<T>
where T: Encodable
{
self.ecx.lazy(value)
}
pub fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T>
where I: IntoIterator<Item = T>,
T: Encodable
{
self.ecx.lazy_seq(iter)
}
pub fn lazy_seq_ref<'x, I, T>(&mut self, iter: I) -> LazySeq<T>
where I: IntoIterator<Item = &'x T>,
T: 'x + Encodable
{
self.ecx.lazy_seq_ref(iter)
}
pub fn lazy_seq_from_slice<T>(&mut self, slice: &[T]) -> LazySeq<T>
where T: Encodable
{
self.ecx.lazy_seq_ref(slice.iter())
}
}

View File

@ -2,6 +2,7 @@
#![feature(box_patterns)]
#![feature(drain_filter)]
#![feature(in_band_lifetimes)]
#![feature(libc)]
#![feature(nll)]
#![feature(proc_macro_internals)]
@ -28,12 +29,10 @@ extern crate rustc_data_structures;
mod error_codes;
mod index_builder;
mod index;
mod encoder;
mod decoder;
mod cstore_impl;
mod isolated_encoder;
mod schema;
mod native_libs;
mod link_args;

View File

@ -2,8 +2,8 @@ use crate::index;
use rustc::hir;
use rustc::hir::def::{self, CtorKind};
use rustc::hir::def_id::{DefIndex, DefId, CrateNum};
use rustc::ich::StableHashingContext;
use rustc::hir::def_id::{DefIndex, DefId};
use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary, ForeignModule};
use rustc::middle::lang_items;
use rustc::mir;
@ -19,10 +19,6 @@ use syntax::symbol::Symbol;
use syntax_pos::{self, Span};
use std::marker::PhantomData;
use std::mem;
use rustc_data_structures::stable_hasher::{StableHasher, HashStable,
StableHasherResult};
pub fn rustc_version() -> String {
format!("rustc {}",
@ -91,15 +87,6 @@ impl<T> Clone for Lazy<T> {
impl<T> serialize::UseSpecializedEncodable for Lazy<T> {}
impl<T> serialize::UseSpecializedDecodable for Lazy<T> {}
impl<CTX, T> HashStable<CTX> for Lazy<T> {
fn hash_stable<W: StableHasherResult>(&self,
_: &mut CTX,
_: &mut StableHasher<W>) {
// There's nothing to do. Whatever got encoded within this Lazy<>
// wrapper has already been hashed.
}
}
/// A sequence of type T referred to by its absolute position
/// in the metadata and length, and which can be decoded lazily.
/// The sequence is a single node for the purposes of `Lazy`.
@ -148,15 +135,6 @@ impl<T> Clone for LazySeq<T> {
impl<T> serialize::UseSpecializedEncodable for LazySeq<T> {}
impl<T> serialize::UseSpecializedDecodable for LazySeq<T> {}
impl<CTX, T> HashStable<CTX> for LazySeq<T> {
fn hash_stable<W: StableHasherResult>(&self,
_: &mut CTX,
_: &mut StableHasher<W>) {
// There's nothing to do. Whatever got encoded within this Lazy<>
// wrapper has already been hashed.
}
}
/// Encoding / decoding state for `Lazy` and `LazySeq`.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum LazyState {
@ -174,7 +152,7 @@ pub enum LazyState {
}
#[derive(RustcEncodable, RustcDecodable)]
pub struct CrateRoot {
pub struct CrateRoot<'tcx> {
pub name: Symbol,
pub triple: TargetTriple,
pub extra_filename: String,
@ -199,10 +177,10 @@ pub struct CrateRoot {
pub source_map: LazySeq<syntax_pos::SourceFile>,
pub def_path_table: Lazy<hir::map::definitions::DefPathTable>,
pub impls: LazySeq<TraitImpls>,
pub exported_symbols: EncodedExportedSymbols,
pub exported_symbols: LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)>,
pub interpret_alloc_index: LazySeq<u32>,
pub index: LazySeq<index::Index>,
pub entries_index: LazySeq<index::Index<'tcx>>,
pub compiler_builtins: bool,
pub needs_allocator: bool,
@ -221,36 +199,12 @@ pub struct CrateDep {
pub extra_filename: String,
}
impl_stable_hash_for!(struct CrateDep {
name,
hash,
kind,
extra_filename
});
#[derive(RustcEncodable, RustcDecodable)]
pub struct TraitImpls {
pub trait_id: (u32, DefIndex),
pub impls: LazySeq<DefIndex>,
}
impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TraitImpls {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
let TraitImpls {
trait_id: (krate, def_index),
ref impls,
} = *self;
DefId {
krate: CrateNum::from_u32(krate),
index: def_index
}.hash_stable(hcx, hasher);
impls.hash_stable(hcx, hasher);
}
}
#[derive(RustcEncodable, RustcDecodable)]
pub struct Entry<'tcx> {
pub kind: EntryKind<'tcx>,
@ -271,23 +225,6 @@ pub struct Entry<'tcx> {
pub mir: Option<Lazy<mir::Mir<'tcx>>>,
}
impl_stable_hash_for!(struct Entry<'tcx> {
kind,
visibility,
span,
attributes,
children,
stability,
deprecation,
ty,
inherent_impls,
variances,
generics,
predicates,
predicates_defined_on,
mir
});
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
pub enum EntryKind<'tcx> {
Const(ConstQualif, Lazy<RenderedConst>),
@ -322,82 +259,6 @@ pub enum EntryKind<'tcx> {
TraitAlias(Lazy<TraitAliasData<'tcx>>),
}
impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for EntryKind<'gcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
EntryKind::ImmStatic |
EntryKind::MutStatic |
EntryKind::ForeignImmStatic |
EntryKind::ForeignMutStatic |
EntryKind::ForeignMod |
EntryKind::GlobalAsm |
EntryKind::ForeignType |
EntryKind::Field |
EntryKind::Existential |
EntryKind::Type |
EntryKind::TypeParam |
EntryKind::ConstParam => {
// Nothing else to hash here.
}
EntryKind::Const(qualif, ref const_data) => {
qualif.hash_stable(hcx, hasher);
const_data.hash_stable(hcx, hasher);
}
EntryKind::Enum(ref repr_options) => {
repr_options.hash_stable(hcx, hasher);
}
EntryKind::Variant(ref variant_data) => {
variant_data.hash_stable(hcx, hasher);
}
EntryKind::Struct(ref variant_data, ref repr_options) |
EntryKind::Union(ref variant_data, ref repr_options) => {
variant_data.hash_stable(hcx, hasher);
repr_options.hash_stable(hcx, hasher);
}
EntryKind::Fn(ref fn_data) |
EntryKind::ForeignFn(ref fn_data) => {
fn_data.hash_stable(hcx, hasher);
}
EntryKind::Mod(ref mod_data) => {
mod_data.hash_stable(hcx, hasher);
}
EntryKind::MacroDef(ref macro_def) => {
macro_def.hash_stable(hcx, hasher);
}
EntryKind::Generator(data) => {
data.hash_stable(hcx, hasher);
}
EntryKind::Closure(closure_data) => {
closure_data.hash_stable(hcx, hasher);
}
EntryKind::Trait(ref trait_data) => {
trait_data.hash_stable(hcx, hasher);
}
EntryKind::TraitAlias(ref trait_alias_data) => {
trait_alias_data.hash_stable(hcx, hasher);
}
EntryKind::Impl(ref impl_data) => {
impl_data.hash_stable(hcx, hasher);
}
EntryKind::Method(ref method_data) => {
method_data.hash_stable(hcx, hasher);
}
EntryKind::AssociatedExistential(associated_container) |
EntryKind::AssociatedType(associated_container) => {
associated_container.hash_stable(hcx, hasher);
}
EntryKind::AssociatedConst(associated_container, qualif, 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 {
@ -405,37 +266,22 @@ pub struct ConstQualif {
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)]
pub struct RenderedConst(pub String);
impl<'a> HashStable<StableHashingContext<'a>> for RenderedConst {
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
self.0.hash_stable(hcx, hasher);
}
}
#[derive(RustcEncodable, RustcDecodable)]
pub struct ModData {
pub reexports: LazySeq<def::Export<hir::HirId>>,
}
impl_stable_hash_for!(struct ModData { reexports });
#[derive(RustcEncodable, RustcDecodable)]
pub struct MacroDef {
pub body: String,
pub legacy: bool,
}
impl_stable_hash_for!(struct MacroDef { body, legacy });
#[derive(RustcEncodable, RustcDecodable)]
pub struct FnData<'tcx> {
pub constness: hir::Constness,
@ -443,8 +289,6 @@ pub struct FnData<'tcx> {
pub sig: Lazy<ty::PolyFnSig<'tcx>>,
}
impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig });
#[derive(RustcEncodable, RustcDecodable)]
pub struct VariantData<'tcx> {
pub ctor_kind: CtorKind,
@ -456,13 +300,6 @@ pub struct VariantData<'tcx> {
pub ctor_sig: Option<Lazy<ty::PolyFnSig<'tcx>>>,
}
impl_stable_hash_for!(struct VariantData<'tcx> {
ctor_kind,
discr,
ctor,
ctor_sig
});
#[derive(RustcEncodable, RustcDecodable)]
pub struct TraitData<'tcx> {
pub unsafety: hir::Unsafety,
@ -472,23 +309,11 @@ pub struct TraitData<'tcx> {
pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
}
impl_stable_hash_for!(struct TraitData<'tcx> {
unsafety,
paren_sugar,
has_auto_impl,
is_marker,
super_predicates
});
#[derive(RustcEncodable, RustcDecodable)]
pub struct TraitAliasData<'tcx> {
pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
}
impl_stable_hash_for!(struct TraitAliasData<'tcx> {
super_predicates
});
#[derive(RustcEncodable, RustcDecodable)]
pub struct ImplData<'tcx> {
pub polarity: hir::ImplPolarity,
@ -500,14 +325,6 @@ pub struct ImplData<'tcx> {
pub trait_ref: Option<Lazy<ty::TraitRef<'tcx>>>,
}
impl_stable_hash_for!(struct ImplData<'tcx> {
polarity,
defaultness,
parent_impl,
coerce_unsized_info,
trait_ref
});
/// Describes whether the container of an associated item
/// is a trait or an impl and whether, in a trait, it has
@ -520,13 +337,6 @@ pub enum AssociatedContainer {
ImplFinal,
}
impl_stable_hash_for!(enum crate::schema::AssociatedContainer {
TraitRequired,
TraitWithDefault,
ImplDefault,
ImplFinal
});
impl AssociatedContainer {
pub fn with_def_id(&self, def_id: DefId) -> ty::AssociatedItemContainer {
match *self {
@ -560,26 +370,17 @@ pub struct MethodData<'tcx> {
pub container: AssociatedContainer,
pub has_self: bool,
}
impl_stable_hash_for!(struct MethodData<'tcx> { fn_data, container, has_self });
#[derive(RustcEncodable, RustcDecodable)]
pub struct ClosureData<'tcx> {
pub sig: Lazy<ty::PolyFnSig<'tcx>>,
}
impl_stable_hash_for!(struct ClosureData<'tcx> { sig });
#[derive(RustcEncodable, RustcDecodable)]
pub struct GeneratorData<'tcx> {
pub layout: mir::GeneratorLayout<'tcx>,
}
impl_stable_hash_for!(struct GeneratorData<'tcx> { layout });
// Tags used for encoding Spans:
pub const TAG_VALID_SPAN: u8 = 0;
pub const TAG_INVALID_SPAN: u8 = 1;
#[derive(RustcEncodable, RustcDecodable)]
pub struct EncodedExportedSymbols {
pub position: usize,
pub len: usize,
}

View File

@ -439,10 +439,11 @@ fn downgrade_if_error(diag: &mut Diagnostic) {
diag.warn(
"this error has been downgraded to a warning for backwards \
compatibility with previous releases",
);
diag.warn(
).warn(
"this represents potential undefined behavior in your code and \
this warning will become a hard error in the future",
).note(
"for more information, try `rustc --explain E0729`"
);
}
}

View File

@ -2424,6 +2424,38 @@ const fn foo() -> impl T {
```
"##,
E0729: r##"
Support for Non-Lexical Lifetimes (NLL) has been included in the Rust compiler
since 1.31, and has been enabled on the 2015 edition since 1.36. The new borrow
checker for NLL uncovered some bugs in the old borrow checker, which in some
cases allowed unsound code to compile, resulting in memory safety issues.
### What do I do?
Change your code so the warning does no longer trigger. For backwards
compatibility, this unsound code may still compile (with a warning) right now.
However, at some point in the future, the compiler will no longer accept this
code and will throw a hard error.
### Shouldn't you fix the old borrow checker?
The old borrow checker has known soundness issues that are basically impossible
to fix. The new NLL-based borrow checker is the fix.
### Can I turn these warnings into errors by denying a lint?
No.
### When are these warnings going to turn into errors?
No formal timeline for turning the warnings into errors has been set. See
[GitHub issue 58781](https://github.com/rust-lang/rust/issues/58781) for more
information.
### Why do I get this message with code that doesn't involve borrowing?
There are some known bugs that trigger this message.
"##,
}
register_diagnostics! {

View File

@ -930,58 +930,60 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
context: PlaceContext,
location: Location) {
debug!("visit_place: place={:?} context={:?} location={:?}", place, context, location);
self.super_place(place, context, location);
match *place {
Place::Base(PlaceBase::Local(_)) => {}
Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) => {
unreachable!()
}
Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })) => {
if self.tcx
.get_attrs(def_id)
.iter()
.any(|attr| attr.check_name(sym::thread_local)) {
place.iterate(|place_base, place_projections| {
match place_base {
PlaceBase::Local(_) => {}
PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. }) => {
unreachable!()
}
PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. }) => {
if self.tcx
.get_attrs(*def_id)
.iter()
.any(|attr| attr.check_name(sym::thread_local)) {
if self.mode != Mode::Fn {
span_err!(self.tcx.sess, self.span, E0625,
"thread-local statics cannot be \
accessed at compile-time");
}
return;
}
// Only allow statics (not consts) to refer to other statics.
if self.mode == Mode::Static || self.mode == Mode::StaticMut {
if self.mode == Mode::Static && context.is_mutating_use() {
// this is not strictly necessary as miri will also bail out
// For interior mutability we can't really catch this statically as that
// goes through raw pointers and intermediate temporaries, so miri has
// to catch this anyway
self.tcx.sess.span_err(
self.span,
"cannot mutate statics in the initializer of another static",
);
}
return;
}
unleash_miri!(self);
if self.mode != Mode::Fn {
span_err!(self.tcx.sess, self.span, E0625,
"thread-local statics cannot be \
accessed at compile-time");
let mut err = struct_span_err!(self.tcx.sess, self.span, E0013,
"{}s cannot refer to statics, use \
a constant instead", self.mode);
if self.tcx.sess.teach(&err.get_code().unwrap()) {
err.note(
"Static and const variables can refer to other const variables. \
But a const variable cannot refer to a static variable."
);
err.help(
"To fix this, the value can be extracted as a const and then used."
);
}
err.emit()
}
return;
}
// Only allow statics (not consts) to refer to other statics.
if self.mode == Mode::Static || self.mode == Mode::StaticMut {
if self.mode == Mode::Static && context.is_mutating_use() {
// this is not strictly necessary as miri will also bail out
// For interior mutability we can't really catch this statically as that
// goes through raw pointers and intermediate temporaries, so miri has
// to catch this anyway
self.tcx.sess.span_err(
self.span,
"cannot mutate statics in the initializer of another static",
);
}
return;
}
unleash_miri!(self);
if self.mode != Mode::Fn {
let mut err = struct_span_err!(self.tcx.sess, self.span, E0013,
"{}s cannot refer to statics, use \
a constant instead", self.mode);
if self.tcx.sess.teach(&err.get_code().unwrap()) {
err.note(
"Static and const variables can refer to other const variables. But a \
const variable cannot refer to a static variable."
);
err.help(
"To fix this, the value can be extracted as a const and then used."
);
}
err.emit()
}
}
Place::Projection(ref proj) => {
for proj in place_projections {
match proj.elem {
ProjectionElem::Deref => {
if context.is_mutating_use() {
@ -1041,7 +1043,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
}
}
}
}
});
}
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {

View File

@ -1134,6 +1134,13 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
is just used to enable niche optimizations in libcore \
and will never be stable",
cfg_fn!(rustc_attrs))),
(sym::rustc_nonnull_optimization_guaranteed, Whitelisted, template!(Word),
Gated(Stability::Unstable,
sym::rustc_attrs,
"the `#[rustc_nonnull_optimization_guaranteed]` attribute \
is just used to enable niche optimizations in libcore \
and will never be stable",
cfg_fn!(rustc_attrs))),
(sym::rustc_regions, Normal, template!(Word), Gated(Stability::Unstable,
sym::rustc_attrs,
"the `#[rustc_regions]` attribute \

View File

@ -491,6 +491,7 @@ symbols! {
rustc_layout_scalar_valid_range_end,
rustc_layout_scalar_valid_range_start,
rustc_mir,
rustc_nonnull_optimization_guaranteed,
rustc_object_lifetime_default,
rustc_on_unimplemented,
rustc_outlives,

View File

@ -0,0 +1,35 @@
use std::marker::PhantomData;
pub struct True;
pub struct False;
pub trait InterfaceType{
type Send;
}
pub struct FooInterface<T>(PhantomData<fn()->T>);
impl<T> InterfaceType for FooInterface<T> {
type Send=False;
}
pub struct DynTrait<I>{
_interface:PhantomData<fn()->I>,
_unsync_unsend:PhantomData<::std::rc::Rc<()>>,
}
unsafe impl<I> Send for DynTrait<I>
where
I:InterfaceType<Send=True>
{}
// @has issue_60726/struct.IntoIter.html
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<T> !Send for \
// IntoIter<T>"
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<T> !Sync for \
// IntoIter<T>"
pub struct IntoIter<T>{
hello:DynTrait<FooInterface<T>>,
}

View File

@ -12,6 +12,7 @@ LL | *a += 1;
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`
error[E0503]: cannot use `y` because it was mutably borrowed
--> $DIR/borrowck-anon-fields-variant.rs:37:7

View File

@ -341,6 +341,7 @@ LL | drop(x);
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`
warning[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
--> $DIR/borrowck-describe-lvalue.rs:227:33
@ -355,6 +356,7 @@ LL | drop(x);
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`
error[E0382]: use of moved value: `x`
--> $DIR/borrowck-describe-lvalue.rs:282:22

View File

@ -6,4 +6,5 @@ LL | (|| { let bar = foo; bar.take() })();
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`

View File

@ -6,4 +6,5 @@ LL | (|| { let bar = foo; bar.take() })();
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`

View File

@ -28,6 +28,7 @@ LL | Enum::A(_) if { x = Enum::B(false); false } => 1,
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`
warning[E0510]: cannot mutably borrow `x` in match guard
--> $DIR/borrowck-mutate-in-guard.rs:15:33
@ -40,6 +41,7 @@ LL | Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`
error: aborting due to 3 previous errors

View File

@ -21,6 +21,7 @@ LL | a + b
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`
warning[E0381]: use of possibly uninitialized variable: `b`
--> $DIR/const_let_refutable.rs:4:9
@ -30,6 +31,7 @@ LL | a + b
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`
error: aborting due to 2 previous errors

View File

@ -297,6 +297,7 @@ LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`
error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
--> $DIR/min_const_fn.rs:144:41

View File

@ -27,6 +27,7 @@ LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`
error: aborting due to 2 previous errors

View File

@ -19,6 +19,7 @@ LL | u
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`
error: aborting due to previous error

View File

@ -11,6 +11,7 @@ LL | m;
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`
error: compilation successful
--> $DIR/feature-gate-nll.rs:10:1

View File

@ -4,5 +4,6 @@
#[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
#[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
#[rustc_nonnull_optimization_guaranteed] //~ ERROR the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable niche optimizations in libcore and will never be stable
fn main() {}

View File

@ -16,6 +16,15 @@ LL | #[rustc_error]
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
error: aborting due to 2 previous errors
error[E0658]: the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable niche optimizations in libcore and will never be stable
--> $DIR/feature-gate-rustc-attrs-1.rs:7:1
|
LL | #[rustc_nonnull_optimization_guaranteed]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -12,6 +12,7 @@ LL | println!("y={}", y);
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`
error: aborting due to previous error

View File

@ -10,6 +10,7 @@ LL | &mut x
= note: ...therefore, they cannot allow references to captured variables to escape
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`
error: compilation successful
--> $DIR/issue-40510-1.rs:20:1

View File

@ -12,6 +12,7 @@ LL | | }
= note: ...therefore, they cannot allow references to captured variables to escape
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`
error: compilation successful
--> $DIR/issue-40510-3.rs:22:1

View File

@ -11,6 +11,7 @@ LL | }
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`
warning[E0713]: borrow may still be in use when destructor runs
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:62:5
@ -25,6 +26,7 @@ LL | }
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`
warning[E0713]: borrow may still be in use when destructor runs
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:73:5
@ -39,6 +41,7 @@ LL | }
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`
error: compilation successful
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:80:1

View File

@ -15,6 +15,7 @@ LL | | }
= note: ...therefore, they cannot allow references to captured variables to escape
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`
error: compilation successful
--> $DIR/issue-49824.rs:6:1

View File

@ -1,6 +1,8 @@
#![deny(improper_ctypes)]
#![allow(dead_code)]
use std::num;
enum Z { }
enum U { A }
enum B { C, D }
@ -15,14 +17,39 @@ enum U8 { A, B, C }
#[repr(isize)]
enum Isize { A, B, C }
#[repr(transparent)]
struct Transparent<T>(T, std::marker::PhantomData<Z>);
struct Rust<T>(T);
extern {
fn zf(x: Z);
fn uf(x: U); //~ ERROR enum has no representation hint
fn bf(x: B); //~ ERROR enum has no representation hint
fn tf(x: T); //~ ERROR enum has no representation hint
fn reprc(x: ReprC);
fn u8(x: U8);
fn isize(x: Isize);
fn repr_c(x: ReprC);
fn repr_u8(x: U8);
fn repr_isize(x: Isize);
fn option_ref(x: Option<&'static u8>);
fn option_fn(x: Option<extern "C" fn()>);
fn nonnull(x: Option<std::ptr::NonNull<u8>>);
fn nonzero_u8(x: Option<num::NonZeroU8>);
fn nonzero_u16(x: Option<num::NonZeroU16>);
fn nonzero_u32(x: Option<num::NonZeroU32>);
fn nonzero_u64(x: Option<num::NonZeroU64>);
fn nonzero_u128(x: Option<num::NonZeroU128>);
//~^ ERROR 128-bit integers don't currently have a known stable ABI
fn nonzero_usize(x: Option<num::NonZeroUsize>);
fn nonzero_i8(x: Option<num::NonZeroI8>);
fn nonzero_i16(x: Option<num::NonZeroI16>);
fn nonzero_i32(x: Option<num::NonZeroI32>);
fn nonzero_i64(x: Option<num::NonZeroI64>);
fn nonzero_i128(x: Option<num::NonZeroI128>);
//~^ ERROR 128-bit integers don't currently have a known stable ABI
fn nonzero_isize(x: Option<num::NonZeroIsize>);
fn repr_transparent(x: Option<Transparent<num::NonZeroU8>>);
fn repr_rust(x: Option<Rust<num::NonZeroU8>>); //~ ERROR enum has no representation hint
fn no_result(x: Result<(), num::NonZeroI32>); //~ ERROR enum has no representation hint
}
pub fn main() { }

View File

@ -1,5 +1,5 @@
error: `extern` block uses type `U` which is not FFI-safe: enum has no representation hint
--> $DIR/lint-ctypes-enum.rs:20:13
--> $DIR/lint-ctypes-enum.rs:27:13
|
LL | fn uf(x: U);
| ^
@ -11,36 +11,64 @@ LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
= help: consider adding a #[repr(...)] attribute to this enum
note: type defined here
--> $DIR/lint-ctypes-enum.rs:5:1
--> $DIR/lint-ctypes-enum.rs:7:1
|
LL | enum U { A }
| ^^^^^^^^^^^^
error: `extern` block uses type `B` which is not FFI-safe: enum has no representation hint
--> $DIR/lint-ctypes-enum.rs:21:13
--> $DIR/lint-ctypes-enum.rs:28:13
|
LL | fn bf(x: B);
| ^
|
= help: consider adding a #[repr(...)] attribute to this enum
note: type defined here
--> $DIR/lint-ctypes-enum.rs:6:1
--> $DIR/lint-ctypes-enum.rs:8:1
|
LL | enum B { C, D }
| ^^^^^^^^^^^^^^^
error: `extern` block uses type `T` which is not FFI-safe: enum has no representation hint
--> $DIR/lint-ctypes-enum.rs:22:13
--> $DIR/lint-ctypes-enum.rs:29:13
|
LL | fn tf(x: T);
| ^
|
= help: consider adding a #[repr(...)] attribute to this enum
note: type defined here
--> $DIR/lint-ctypes-enum.rs:7:1
--> $DIR/lint-ctypes-enum.rs:9:1
|
LL | enum T { E, F, G }
| ^^^^^^^^^^^^^^^^^^
error: aborting due to 3 previous errors
error: `extern` block uses type `u128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
--> $DIR/lint-ctypes-enum.rs:40:23
|
LL | fn nonzero_u128(x: Option<num::NonZeroU128>);
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: `extern` block uses type `i128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
--> $DIR/lint-ctypes-enum.rs:47:23
|
LL | fn nonzero_i128(x: Option<num::NonZeroI128>);
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: `extern` block uses type `std::option::Option<Rust<std::num::NonZeroU8>>` which is not FFI-safe: enum has no representation hint
--> $DIR/lint-ctypes-enum.rs:51:20
|
LL | fn repr_rust(x: Option<Rust<num::NonZeroU8>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding a #[repr(...)] attribute to this enum
error: `extern` block uses type `std::result::Result<(), std::num::NonZeroI32>` which is not FFI-safe: enum has no representation hint
--> $DIR/lint-ctypes-enum.rs:52:20
|
LL | fn no_result(x: Result<(), num::NonZeroI32>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding a #[repr(...)] attribute to this enum
error: aborting due to 7 previous errors

View File

@ -18,6 +18,7 @@ LL | **z = None;
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`
error: aborting due to previous error

View File

@ -12,6 +12,7 @@ LL | x
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`
error: aborting due to previous error

View File

@ -20,6 +20,7 @@ LL | static C: &u32 = &A;
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`
error[E0625]: thread-local statics cannot be accessed at compile-time
--> $DIR/thread-local-in-ctfe.rs:15:16
@ -43,6 +44,7 @@ LL | const E: &u32 = &A;
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
= note: for more information, try `rustc --explain E0729`
error[E0625]: thread-local statics cannot be accessed at compile-time
--> $DIR/thread-local-in-ctfe.rs:25:5

@ -1 +1 @@
Subproject commit 60a609acaed3bf2b3ec6ab995bccf0f03bc26060
Subproject commit a8eeb7cdb135da1cd582c6093c1739732727a4a2