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:
@@ -67,16 +67,26 @@
|
|||||||
//! mutability:
|
//! mutability:
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
|
//! use std::cell::{RefCell, RefMut};
|
||||||
//! use std::collections::HashMap;
|
//! use std::collections::HashMap;
|
||||||
//! use std::cell::RefCell;
|
|
||||||
//! use std::rc::Rc;
|
//! use std::rc::Rc;
|
||||||
//!
|
//!
|
||||||
//! fn main() {
|
//! fn main() {
|
||||||
//! let shared_map: Rc<RefCell<_>> = Rc::new(RefCell::new(HashMap::new()));
|
//! let shared_map: Rc<RefCell<_>> = Rc::new(RefCell::new(HashMap::new()));
|
||||||
//! shared_map.borrow_mut().insert("africa", 92388);
|
//! // Create a new block to limit the scope of the dynamic borrow
|
||||||
//! shared_map.borrow_mut().insert("kyoto", 11837);
|
//! {
|
||||||
//! shared_map.borrow_mut().insert("piccadilly", 11826);
|
//! let mut map: RefMut<_> = shared_map.borrow_mut();
|
||||||
//! shared_map.borrow_mut().insert("marbles", 38);
|
//! 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 {
|
//! impl Graph {
|
||||||
//! fn minimum_spanning_tree(&self) -> Vec<(i32, i32)> {
|
//! fn minimum_spanning_tree(&self) -> Vec<(i32, i32)> {
|
||||||
//! // Create a new scope to contain the lifetime of the
|
//! self.span_tree_cache.borrow_mut()
|
||||||
//! // dynamic borrow
|
//! .get_or_insert_with(|| self.calc_span_tree())
|
||||||
//! {
|
//! .clone()
|
||||||
//! // Take a reference to the inside of cache cell
|
//! }
|
||||||
//! let mut cache = self.span_tree_cache.borrow_mut();
|
//!
|
||||||
//! if cache.is_some() {
|
//! fn calc_span_tree(&self) -> Vec<(i32, i32)> {
|
||||||
//! return cache.as_ref().unwrap().clone();
|
//! // Expensive computation goes here
|
||||||
//! }
|
//! vec![]
|
||||||
//!
|
|
||||||
//! 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()
|
|
||||||
//! }
|
//! }
|
||||||
//! # fn calc_span_tree(&self) -> Vec<(i32, i32)> { vec![] }
|
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", s
|
|||||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[rustc_layout_scalar_valid_range_start(1)]
|
#[rustc_layout_scalar_valid_range_start(1)]
|
||||||
|
#[cfg_attr(not(stage0), rustc_nonnull_optimization_guaranteed)]
|
||||||
pub struct $Ty($Int);
|
pub struct $Ty($Int);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2938,6 +2938,7 @@ impl<'a, T: ?Sized> From<NonNull<T>> for Unique<T> {
|
|||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[rustc_layout_scalar_valid_range_start(1)]
|
#[rustc_layout_scalar_valid_range_start(1)]
|
||||||
|
#[cfg_attr(not(stage0), rustc_nonnull_optimization_guaranteed)]
|
||||||
pub struct NonNull<T: ?Sized> {
|
pub struct NonNull<T: ?Sized> {
|
||||||
pointer: *const T,
|
pointer: *const T,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -700,22 +700,64 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can only call poly_project_and_unify_type when our predicate's
|
// There are three possible cases when we project a predicate:
|
||||||
// Ty contains an inference variable - otherwise, there won't be anything to
|
//
|
||||||
// unify
|
// 1. We encounter an error. This means that it's impossible for
|
||||||
if p.ty().skip_binder().has_infer_types() {
|
// our current type to implement the auto trait - there's bound
|
||||||
debug!("Projecting and unifying projection predicate {:?}",
|
// that we could add to our ParamEnv that would 'fix' this kind
|
||||||
predicate);
|
// of error, as it's not caused by an unimplemented type.
|
||||||
match poly_project_and_unify_type(select, &obligation.with(p)) {
|
//
|
||||||
Err(e) => {
|
// 2. We succesfully project the predicate (Ok(Some(_))), generating
|
||||||
debug!(
|
// some subobligations. We then process these subobligations
|
||||||
"evaluate_nested_obligations: Unable to unify predicate \
|
// like any other generated sub-obligations.
|
||||||
'{:?}' '{:?}', bailing out",
|
//
|
||||||
ty, e
|
// 3. We receieve an 'ambiguous' result (Ok(None))
|
||||||
);
|
// If we were actually trying to compile a crate,
|
||||||
return false;
|
// we would need to re-process this obligation later.
|
||||||
}
|
// However, all we care about is finding out what bounds
|
||||||
Ok(Some(v)) => {
|
// 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(
|
if !self.evaluate_nested_obligations(
|
||||||
ty,
|
ty,
|
||||||
v.clone().iter().cloned(),
|
v.clone().iter().cloned(),
|
||||||
@@ -728,7 +770,16 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
|||||||
return false;
|
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)
|
panic!("Unexpected result when selecting {:?} {:?}", ty, obligation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -380,45 +380,47 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
) -> Option<OperandRef<'tcx, Bx::Value>> {
|
) -> Option<OperandRef<'tcx, Bx::Value>> {
|
||||||
debug!("maybe_codegen_consume_direct(place={:?})", place);
|
debug!("maybe_codegen_consume_direct(place={:?})", place);
|
||||||
|
|
||||||
// watch out for locals that do not have an
|
place.iterate(|place_base, place_projection| {
|
||||||
// alloca; they are handled somewhat differently
|
if let mir::PlaceBase::Local(index) = place_base {
|
||||||
if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
|
match self.locals[*index] {
|
||||||
match self.locals[index] {
|
LocalRef::Operand(Some(mut o)) => {
|
||||||
LocalRef::Operand(Some(o)) => {
|
// Moves out of scalar and scalar pair fields are trivial.
|
||||||
return Some(o);
|
for proj in place_projection {
|
||||||
}
|
match proj.elem {
|
||||||
LocalRef::Operand(None) => {
|
mir::ProjectionElem::Field(ref f, _) => {
|
||||||
bug!("use of {:?} before def", place);
|
o = o.extract_field(bx, f.index());
|
||||||
}
|
}
|
||||||
LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
|
mir::ProjectionElem::Index(_) |
|
||||||
// use path below
|
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);
|
||||||
// Moves out of scalar and scalar pair fields are trivial.
|
if elem.is_zst() {
|
||||||
if let &mir::Place::Projection(ref proj) = place {
|
o = OperandRef::new_zst(bx, elem);
|
||||||
if let Some(o) = self.maybe_codegen_consume_direct(bx, &proj.base) {
|
} else {
|
||||||
match proj.elem {
|
return None;
|
||||||
mir::ProjectionElem::Field(ref f, _) => {
|
}
|
||||||
return Some(o.extract_field(bx, f.index()));
|
}
|
||||||
}
|
_ => return None,
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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(
|
pub fn codegen_consume(
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use rustc::hir::{ExprKind, Node};
|
use rustc::hir::{ExprKind, Node};
|
||||||
|
use crate::hir::def_id::DefId;
|
||||||
use rustc::hir::lowering::is_range_literal;
|
use rustc::hir::lowering::is_range_literal;
|
||||||
use rustc::ty::subst::SubstsRef;
|
use rustc::ty::subst::SubstsRef;
|
||||||
use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
|
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::{lint, util};
|
||||||
use rustc_data_structures::indexed_vec::Idx;
|
use rustc_data_structures::indexed_vec::Idx;
|
||||||
use util::nodemap::FxHashSet;
|
use util::nodemap::FxHashSet;
|
||||||
@@ -14,11 +15,11 @@ use lint::{LintPass, LateLintPass};
|
|||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
|
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::errors::Applicability;
|
||||||
|
use syntax::symbol::sym;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
use syntax::source_map;
|
|
||||||
|
|
||||||
use rustc::hir;
|
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
|
/// Check if this enum can be safely exported based on the
|
||||||
/// "nullable pointer optimization". Currently restricted
|
/// "nullable pointer optimization". Currently restricted
|
||||||
/// to function pointers and references, but could be
|
/// to function pointers, references, core::num::NonZero*,
|
||||||
/// expanded to cover NonZero raw pointers and newtypes.
|
/// core::ptr::NonNull, and #[repr(transparent)] newtypes.
|
||||||
/// FIXME: This duplicates code in codegen.
|
/// FIXME: This duplicates code in codegen.
|
||||||
fn is_repr_nullable_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
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>)
|
substs: SubstsRef<'tcx>)
|
||||||
-> bool {
|
-> bool {
|
||||||
if def.variants.len() == 2 {
|
if ty_def.variants.len() != 2 {
|
||||||
let data_idx;
|
return false;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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> {
|
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
|
// repr(transparent) types are allowed to have arbitrary ZSTs, not just
|
||||||
// PhantomData -- skip checking all ZST fields
|
// PhantomData -- skip checking all ZST fields
|
||||||
if def.repr.transparent() {
|
if def.repr.transparent() && is_zst(cx, field.did, field_ty) {
|
||||||
let is_zst = cx
|
continue;
|
||||||
.layout_of(cx.param_env(field.did).and(field_ty))
|
|
||||||
.map(|layout| layout.is_zst())
|
|
||||||
.unwrap_or(false);
|
|
||||||
if is_zst {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let r = self.check_type_for_ffi(cache, field_ty);
|
let r = self.check_type_for_ffi(cache, field_ty);
|
||||||
match r {
|
match r {
|
||||||
@@ -682,7 +714,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||||||
// discriminant.
|
// discriminant.
|
||||||
if !def.repr.c() && def.repr.int.is_none() {
|
if !def.repr.c() && def.repr.int.is_none() {
|
||||||
// Special-case types like `Option<extern fn()>`.
|
// 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 {
|
return FfiUnsafe {
|
||||||
ty: ty,
|
ty: ty,
|
||||||
reason: "enum has no representation hint",
|
reason: "enum has no representation hint",
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ impl<'a> CrateLoader<'a> {
|
|||||||
|
|
||||||
fn verify_no_symbol_conflicts(&self,
|
fn verify_no_symbol_conflicts(&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
root: &CrateRoot) {
|
root: &CrateRoot<'_>) {
|
||||||
// Check for (potential) conflicts with the local crate
|
// Check for (potential) conflicts with the local crate
|
||||||
if self.local_crate_name == root.name &&
|
if self.local_crate_name == root.name &&
|
||||||
self.sess.local_crate_disambiguator() == root.disambiguator {
|
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
|
// Go through the crate metadata and load any crates that it references
|
||||||
fn resolve_crate_deps(&mut self,
|
fn resolve_crate_deps(&mut self,
|
||||||
root: &Option<CratePaths>,
|
root: &Option<CratePaths>,
|
||||||
crate_root: &CrateRoot,
|
crate_root: &CrateRoot<'_>,
|
||||||
metadata: &MetadataBlob,
|
metadata: &MetadataBlob,
|
||||||
krate: CrateNum,
|
krate: CrateNum,
|
||||||
span: Span,
|
span: Span,
|
||||||
@@ -582,7 +582,7 @@ impl<'a> CrateLoader<'a> {
|
|||||||
/// implemented as dynamic libraries, but we have a possible future where
|
/// implemented as dynamic libraries, but we have a possible future where
|
||||||
/// custom derive (and other macro-1.1 style features) are implemented via
|
/// custom derive (and other macro-1.1 style features) are implemented via
|
||||||
/// executables and custom IPC.
|
/// 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>)> {
|
-> Vec<(ast::Name, Lrc<SyntaxExtension>)> {
|
||||||
use std::{env, mem};
|
use std::{env, mem};
|
||||||
use crate::dynamic_lib::DynamicLibrary;
|
use crate::dynamic_lib::DynamicLibrary;
|
||||||
|
|||||||
@@ -64,7 +64,11 @@ pub struct CrateMetadata {
|
|||||||
/// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
|
/// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
|
||||||
pub alloc_decoding_state: AllocDecodingState,
|
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
|
/// 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
|
/// crate is loaded, we read all the keys and put them in this
|
||||||
|
|||||||
@@ -246,12 +246,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
|
|||||||
|
|
||||||
used_crate_source => { Lrc::new(cdata.source.clone()) }
|
used_crate_source => { Lrc::new(cdata.source.clone()) }
|
||||||
|
|
||||||
exported_symbols => {
|
exported_symbols => { Arc::new(cdata.exported_symbols(tcx)) }
|
||||||
let cnum = cdata.cnum;
|
|
||||||
assert!(cnum != LOCAL_CRATE);
|
|
||||||
|
|
||||||
Arc::new(cdata.exported_symbols(tcx))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
|
pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
|
||||||
|
|||||||
@@ -365,7 +365,7 @@ for DecodeContext<'a, 'tcx> {
|
|||||||
|
|
||||||
implement_ty_decoder!( DecodeContext<'a, 'tcx> );
|
implement_ty_decoder!( DecodeContext<'a, 'tcx> );
|
||||||
|
|
||||||
impl<'a, 'tcx> MetadataBlob {
|
impl<'tcx> MetadataBlob {
|
||||||
pub fn is_compatible(&self) -> bool {
|
pub fn is_compatible(&self) -> bool {
|
||||||
self.raw_bytes().starts_with(METADATA_HEADER)
|
self.raw_bytes().starts_with(METADATA_HEADER)
|
||||||
}
|
}
|
||||||
@@ -374,7 +374,7 @@ impl<'a, 'tcx> MetadataBlob {
|
|||||||
Lazy::with_position(METADATA_HEADER.len() + 4).decode(self)
|
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 slice = self.raw_bytes();
|
||||||
let offset = METADATA_HEADER.len();
|
let offset = METADATA_HEADER.len();
|
||||||
let pos = (((slice[offset + 0] as u32) << 24) | ((slice[offset + 1] as u32) << 16) |
|
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 #0 (DefIndex 1:N)
|
||||||
/// |- proc macro #1 (DefIndex 1:N+1)
|
/// |- 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>)])
|
proc_macros: &[(ast::Name, Lrc<SyntaxExtension>)])
|
||||||
-> DefPathTable
|
-> DefPathTable
|
||||||
{
|
{
|
||||||
@@ -475,7 +475,7 @@ impl<'a, 'tcx> CrateMetadata {
|
|||||||
|
|
||||||
fn maybe_entry(&self, item_id: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
|
fn maybe_entry(&self, item_id: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
|
||||||
assert!(!self.is_proc_macro(item_id));
|
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> {
|
fn entry(&self, item_id: DefIndex) -> Entry<'tcx> {
|
||||||
@@ -1126,10 +1126,7 @@ impl<'a, 'tcx> CrateMetadata {
|
|||||||
// link those in so we skip those crates.
|
// link those in so we skip those crates.
|
||||||
vec![]
|
vec![]
|
||||||
} else {
|
} else {
|
||||||
let lazy_seq: LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)> =
|
self.root.exported_symbols.decode((self, tcx)).collect()
|
||||||
LazySeq::with_position_and_length(self.root.exported_symbols.position,
|
|
||||||
self.root.exported_symbols.len);
|
|
||||||
lazy_seq.decode((self, tcx)).collect()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
use crate::index::Index;
|
use crate::index::Index;
|
||||||
use crate::index_builder::{FromId, IndexBuilder, Untracked};
|
|
||||||
use crate::isolated_encoder::IsolatedEncoder;
|
|
||||||
use crate::schema::*;
|
use crate::schema::*;
|
||||||
|
|
||||||
use rustc::middle::cstore::{LinkagePreference, NativeLibrary,
|
use rustc::middle::cstore::{LinkagePreference, NativeLibrary,
|
||||||
@@ -46,6 +44,8 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
|
|||||||
opaque: opaque::Encoder,
|
opaque: opaque::Encoder,
|
||||||
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
|
||||||
|
entries_index: Index<'tcx>,
|
||||||
|
|
||||||
lazy_state: LazyState,
|
lazy_state: LazyState,
|
||||||
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
|
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
|
||||||
predicate_shorthands: FxHashMap<ty::Predicate<'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
|
/// Emit the data for a `DefId` to the metadata. The function to
|
||||||
// and registers the Fingerprint in the `metadata_hashes` map.
|
/// emit the data is `op`, and it will be given `data` as
|
||||||
pub fn tracked<'x, DATA, R>(&'x mut self,
|
/// arguments. This `record` function will call `op` to generate
|
||||||
op: fn(&mut IsolatedEncoder<'x, 'a, 'tcx>, DATA) -> R,
|
/// the `Entry` (which may point to other encoded information)
|
||||||
data: DATA)
|
/// and will then record the `Lazy<Entry>` for use in the index.
|
||||||
-> R {
|
// FIXME(eddyb) remove this.
|
||||||
op(&mut IsolatedEncoder::new(self), data)
|
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 krate = self.tcx.hir().krate();
|
||||||
let mut index = IndexBuilder::new(self);
|
|
||||||
let vis = Spanned { span: syntax_pos::DUMMY_SP, node: hir::VisibilityKind::Public };
|
let vis = Spanned { span: syntax_pos::DUMMY_SP, node: hir::VisibilityKind::Public };
|
||||||
index.record(DefId::local(CRATE_DEF_INDEX),
|
self.record(DefId::local(CRATE_DEF_INDEX),
|
||||||
IsolatedEncoder::encode_info_for_mod,
|
EncodeContext::encode_info_for_mod,
|
||||||
FromId(hir::CRATE_HIR_ID, (&krate.module, &krate.attrs, &vis)));
|
(hir::CRATE_HIR_ID, &krate.module, &krate.attrs, &vis));
|
||||||
let mut visitor = EncodeVisitor { index };
|
krate.visit_all_item_likes(&mut self.as_deep_visitor());
|
||||||
krate.visit_all_item_likes(&mut visitor.as_deep_visitor());
|
|
||||||
for macro_def in &krate.exported_macros {
|
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> {
|
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))
|
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 mut i = self.position();
|
||||||
|
|
||||||
let crate_deps = self.tracked(IsolatedEncoder::encode_crate_deps, ());
|
let crate_deps = self.encode_crate_deps();
|
||||||
let dylib_dependency_formats = self.tracked(
|
let dylib_dependency_formats = self.encode_dylib_dependency_formats();
|
||||||
IsolatedEncoder::encode_dylib_dependency_formats,
|
|
||||||
());
|
|
||||||
let dep_bytes = self.position() - i;
|
let dep_bytes = self.position() - i;
|
||||||
|
|
||||||
// Encode the lib features.
|
// Encode the lib features.
|
||||||
i = self.position();
|
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;
|
let lib_feature_bytes = self.position() - i;
|
||||||
|
|
||||||
// Encode the language items.
|
// Encode the language items.
|
||||||
i = self.position();
|
i = self.position();
|
||||||
let lang_items = self.tracked(IsolatedEncoder::encode_lang_items, ());
|
let lang_items = self.encode_lang_items();
|
||||||
let lang_items_missing = self.tracked(
|
let lang_items_missing = self.encode_lang_items_missing();
|
||||||
IsolatedEncoder::encode_lang_items_missing,
|
|
||||||
());
|
|
||||||
let lang_item_bytes = self.position() - i;
|
let lang_item_bytes = self.position() - i;
|
||||||
|
|
||||||
// Encode the native libraries used
|
// Encode the native libraries used
|
||||||
i = self.position();
|
i = self.position();
|
||||||
let native_libraries = self.tracked(
|
let native_libraries = self.encode_native_libraries();
|
||||||
IsolatedEncoder::encode_native_libraries,
|
|
||||||
());
|
|
||||||
let native_lib_bytes = self.position() - i;
|
let native_lib_bytes = self.position() - i;
|
||||||
|
|
||||||
let foreign_modules = self.tracked(
|
let foreign_modules = self.encode_foreign_modules();
|
||||||
IsolatedEncoder::encode_foreign_modules,
|
|
||||||
());
|
|
||||||
|
|
||||||
// Encode source_map
|
// Encode source_map
|
||||||
i = self.position();
|
i = self.position();
|
||||||
@@ -416,22 +414,20 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||||||
|
|
||||||
// Encode the def IDs of impls, for coherence checking.
|
// Encode the def IDs of impls, for coherence checking.
|
||||||
i = self.position();
|
i = self.position();
|
||||||
let impls = self.tracked(IsolatedEncoder::encode_impls, ());
|
let impls = self.encode_impls();
|
||||||
let impl_bytes = self.position() - i;
|
let impl_bytes = self.position() - i;
|
||||||
|
|
||||||
// Encode exported symbols info.
|
// Encode exported symbols info.
|
||||||
i = self.position();
|
i = self.position();
|
||||||
let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE);
|
let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE);
|
||||||
let exported_symbols = self.tracked(
|
let exported_symbols = self.encode_exported_symbols(&exported_symbols);
|
||||||
IsolatedEncoder::encode_exported_symbols,
|
|
||||||
&exported_symbols);
|
|
||||||
let exported_symbols_bytes = self.position() - i;
|
let exported_symbols_bytes = self.position() - i;
|
||||||
|
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
|
|
||||||
// Encode the items.
|
// Encode the items.
|
||||||
i = self.position();
|
i = self.position();
|
||||||
let items = self.encode_info_for_items();
|
self.encode_info_for_items();
|
||||||
let item_bytes = self.position() - i;
|
let item_bytes = self.position() - i;
|
||||||
|
|
||||||
// Encode the allocation index
|
// Encode the allocation index
|
||||||
@@ -462,10 +458,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||||||
self.lazy_seq(interpret_alloc_index)
|
self.lazy_seq(interpret_alloc_index)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Index the items
|
|
||||||
i = self.position();
|
i = self.position();
|
||||||
let index = items.write_index(&mut self.opaque);
|
let entries_index = self.entries_index.write_index(&mut self.opaque);
|
||||||
let index_bytes = self.position() - i;
|
let entries_index_bytes = self.position() - i;
|
||||||
|
|
||||||
let attrs = tcx.hir().krate_attrs();
|
let attrs = tcx.hir().krate_attrs();
|
||||||
let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro);
|
let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro);
|
||||||
@@ -516,7 +511,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||||||
impls,
|
impls,
|
||||||
exported_symbols,
|
exported_symbols,
|
||||||
interpret_alloc_index,
|
interpret_alloc_index,
|
||||||
index,
|
entries_index,
|
||||||
});
|
});
|
||||||
|
|
||||||
let total_bytes = self.position();
|
let total_bytes = self.position();
|
||||||
@@ -539,7 +534,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||||||
println!(" exp. symbols bytes: {}", exported_symbols_bytes);
|
println!(" exp. symbols bytes: {}", exported_symbols_bytes);
|
||||||
println!(" def-path table bytes: {}", def_path_table_bytes);
|
println!(" def-path table bytes: {}", def_path_table_bytes);
|
||||||
println!(" item bytes: {}", item_bytes);
|
println!(" item bytes: {}", item_bytes);
|
||||||
println!(" index bytes: {}", index_bytes);
|
println!(" entries index bytes: {}", entries_index_bytes);
|
||||||
println!(" zero bytes: {}", zero_bytes);
|
println!(" zero bytes: {}", zero_bytes);
|
||||||
println!(" total bytes: {}", total_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
|
impl EncodeContext<'_, 'tcx> {
|
||||||
// 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> {
|
|
||||||
fn encode_variances_of(&mut self, def_id: DefId) -> LazySeq<ty::Variance> {
|
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;
|
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>> {
|
fn encode_item_type(&mut self, def_id: DefId) -> Lazy<Ty<'tcx>> {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let ty = tcx.type_of(def_id);
|
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)
|
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(
|
fn encode_enum_variant_info(
|
||||||
&mut self,
|
&mut self,
|
||||||
(enum_did, Untracked(index)): (DefId, Untracked<VariantIdx>),
|
(enum_did, index): (DefId, VariantIdx),
|
||||||
) -> Entry<'tcx> {
|
) -> Entry<'tcx> {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let def = tcx.adt_def(enum_did);
|
let def = tcx.adt_def(enum_did);
|
||||||
let variant = &def.variants[index];
|
let variant = &def.variants[index];
|
||||||
let def_id = variant.def_id;
|
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 {
|
let data = VariantData {
|
||||||
ctor_kind: variant.ctor_kind,
|
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(
|
fn encode_enum_variant_ctor(
|
||||||
&mut self,
|
&mut self,
|
||||||
(enum_did, Untracked(index)): (DefId, Untracked<VariantIdx>),
|
(enum_did, index): (DefId, VariantIdx),
|
||||||
) -> Entry<'tcx> {
|
) -> Entry<'tcx> {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let def = tcx.adt_def(enum_did);
|
let def = tcx.adt_def(enum_did);
|
||||||
let variant = &def.variants[index];
|
let variant = &def.variants[index];
|
||||||
let def_id = variant.ctor_def_id.unwrap();
|
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 {
|
let data = VariantData {
|
||||||
ctor_kind: variant.ctor_kind,
|
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,
|
fn encode_info_for_mod(
|
||||||
FromId(id, (md, attrs, vis)): FromId<(&hir::Mod,
|
&mut self,
|
||||||
&[ast::Attribute],
|
(id, md, attrs, vis): (hir::HirId, &hir::Mod, &[ast::Attribute], &hir::Visibility),
|
||||||
&hir::Visibility)>)
|
) -> Entry<'tcx> {
|
||||||
-> Entry<'tcx> {
|
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let def_id = tcx.hir().local_def_id_from_hir_id(id);
|
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 {
|
let data = ModData {
|
||||||
reexports: match tcx.module_exports(def_id) {
|
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(),
|
_ => 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
|
fn encode_field(
|
||||||
/// given ADT. The indices of the variant/field are untracked:
|
&mut self,
|
||||||
/// this is ok because we will have to lookup the adt-def by its
|
(adt_def_id, variant_index, field_index): (DefId, VariantIdx, usize),
|
||||||
/// id, and that gives us the right to access any information in
|
) -> Entry<'tcx> {
|
||||||
/// 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> {
|
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let variant = &tcx.adt_def(adt_def_id).variants[variant_index];
|
let variant = &tcx.adt_def(adt_def_id).variants[variant_index];
|
||||||
let field = &variant.fields[field_index];
|
let field = &variant.fields[field_index];
|
||||||
|
|
||||||
let def_id = field.did;
|
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_id = tcx.hir().as_local_hir_id(variant.def_id).unwrap();
|
||||||
let variant_data = tcx.hir().expect_variant_data(variant_id);
|
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> {
|
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 tcx = self.tcx;
|
||||||
let adt_def = tcx.adt_def(adt_def_id);
|
let adt_def = tcx.adt_def(adt_def_id);
|
||||||
let variant = adt_def.non_enum_variant();
|
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> {
|
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;
|
let tcx = self.tcx;
|
||||||
self.lazy(tcx.generics_of(def_id))
|
self.lazy(tcx.generics_of(def_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_predicates(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> {
|
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;
|
let tcx = self.tcx;
|
||||||
self.lazy(&tcx.predicates_of(def_id))
|
self.lazy(&tcx.predicates_of(def_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_predicates_defined_on(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> {
|
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;
|
let tcx = self.tcx;
|
||||||
self.lazy(&tcx.predicates_defined_on(def_id))
|
self.lazy(&tcx.predicates_defined_on(def_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
|
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 tcx = self.tcx;
|
||||||
|
|
||||||
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
|
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> {
|
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 tcx = self.tcx;
|
||||||
|
|
||||||
let hir_id = self.tcx.hir().as_local_hir_id(def_id).unwrap();
|
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.
|
// Encodes the inherent implementations of a structure, enumeration, or trait.
|
||||||
fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq<DefIndex> {
|
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);
|
let implementations = self.tcx.inherent_impls(def_id);
|
||||||
if implementations.is_empty() {
|
if implementations.is_empty() {
|
||||||
LazySeq::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>> {
|
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))
|
self.tcx.lookup_stability(def_id).map(|stab| self.lazy(stab))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_deprecation(&mut self, def_id: DefId) -> Option<Lazy<attr::Deprecation>> {
|
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))
|
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> {
|
fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> Entry<'tcx> {
|
||||||
let tcx = self.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 {
|
let kind = match item.node {
|
||||||
hir::ItemKind::Static(_, hir::MutMutable, _) => EntryKind::MutStatic,
|
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))
|
EntryKind::Fn(self.lazy(&data))
|
||||||
}
|
}
|
||||||
hir::ItemKind::Mod(ref m) => {
|
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::ForeignMod(_) => EntryKind::ForeignMod,
|
||||||
hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm,
|
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(
|
fn encode_info_for_ty_param(
|
||||||
&mut self,
|
&mut self,
|
||||||
(def_id, Untracked(encode_type)): (DefId, Untracked<bool>),
|
(def_id, encode_type): (DefId, bool),
|
||||||
) -> Entry<'tcx> {
|
) -> 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)
|
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,
|
&mut self,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
) -> Entry<'tcx> {
|
) -> 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)
|
self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
|
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 tcx = self.tcx;
|
||||||
|
|
||||||
let tables = self.tcx.typeck_tables_of(def_id);
|
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> {
|
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 tcx = self.tcx;
|
||||||
let id = tcx.hir().as_local_hir_id(def_id).unwrap();
|
let id = tcx.hir().as_local_hir_id(def_id).unwrap();
|
||||||
let body_id = tcx.hir().body_owned_by(id);
|
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> {
|
fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq<ast::Attribute> {
|
||||||
// NOTE: This must use lazy_seq_from_slice(), not lazy_seq() because
|
self.lazy_seq_ref(attrs)
|
||||||
// we rely on the HashStable specialization for [Attribute]
|
|
||||||
// to properly filter things out.
|
|
||||||
self.lazy_seq_from_slice(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);
|
let used_libraries = self.tcx.native_libraries(LOCAL_CRATE);
|
||||||
self.lazy_seq(used_libraries.iter().cloned())
|
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);
|
let foreign_modules = self.tcx.foreign_modules(LOCAL_CRATE);
|
||||||
self.lazy_seq(foreign_modules.iter().cloned())
|
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 crates = self.tcx.crates();
|
||||||
|
|
||||||
let mut deps = 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))
|
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 tcx = self.tcx;
|
||||||
let lib_features = tcx.lib_features();
|
let lib_features = tcx.lib_features();
|
||||||
self.lazy_seq(lib_features.to_vec())
|
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 tcx = self.tcx;
|
||||||
let lang_items = tcx.lang_items();
|
let lang_items = tcx.lang_items();
|
||||||
let lang_items = lang_items.items().iter();
|
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;
|
let tcx = self.tcx;
|
||||||
self.lazy_seq_ref(&tcx.lang_items().missing)
|
self.lazy_seq_ref(&tcx.lang_items().missing)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encodes an index, mapping each trait to its (local) implementations.
|
/// Encodes an index, mapping each trait to its (local) implementations.
|
||||||
fn encode_impls(&mut self, _: ()) -> LazySeq<TraitImpls> {
|
fn encode_impls(&mut self) -> LazySeq<TraitImpls> {
|
||||||
debug!("IsolatedEncoder::encode_impls()");
|
debug!("EncodeContext::encode_impls()");
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let mut visitor = ImplVisitor {
|
let mut visitor = ImplVisitor {
|
||||||
tcx,
|
tcx,
|
||||||
@@ -1580,12 +1551,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
|||||||
|
|
||||||
TraitImpls {
|
TraitImpls {
|
||||||
trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index),
|
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();
|
.collect();
|
||||||
|
|
||||||
self.lazy_seq_from_slice(&all_impls[..])
|
self.lazy_seq_ref(&all_impls)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encodes all symbols exported from this crate into the metadata.
|
// 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
|
// symbol associated with them (they weren't translated) or if they're an FFI
|
||||||
// definition (as that's not defined in this crate).
|
// definition (as that's not defined in this crate).
|
||||||
fn encode_exported_symbols(&mut self,
|
fn encode_exported_symbols(&mut self,
|
||||||
exported_symbols: &[(ExportedSymbol<'_>, SymbolExportLevel)])
|
exported_symbols: &[(ExportedSymbol<'tcx>, SymbolExportLevel)])
|
||||||
-> EncodedExportedSymbols {
|
-> LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)> {
|
||||||
// The metadata symbol name is special. It should not show up in
|
// The metadata symbol name is special. It should not show up in
|
||||||
// downstream crates.
|
// downstream crates.
|
||||||
let metadata_symbol_name = SymbolName::new(&metadata_symbol_name(self.tcx));
|
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()
|
.iter()
|
||||||
.filter(|&&(ref exported_symbol, _)| {
|
.filter(|&&(ref exported_symbol, _)| {
|
||||||
match *exported_symbol {
|
match *exported_symbol {
|
||||||
@@ -1611,15 +1582,10 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
|||||||
_ => true,
|
_ => true,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.cloned());
|
.cloned())
|
||||||
|
|
||||||
EncodedExportedSymbols {
|
|
||||||
len: lazy_seq.len,
|
|
||||||
position: lazy_seq.position,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
match self.tcx.sess.dependency_formats.borrow().get(&config::CrateType::Dylib) {
|
||||||
Some(arr) => {
|
Some(arr) => {
|
||||||
self.lazy_seq(arr.iter().map(|slot| {
|
self.lazy_seq(arr.iter().map(|slot| {
|
||||||
@@ -1641,7 +1607,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
|||||||
-> Entry<'tcx> {
|
-> Entry<'tcx> {
|
||||||
let tcx = self.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 {
|
let kind = match nitem.node {
|
||||||
hir::ForeignItemKind::Fn(_, ref names, _) => {
|
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> {
|
impl Visitor<'tcx> for EncodeContext<'_, 'tcx> {
|
||||||
index: IndexBuilder<'a, 'b, 'tcx>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> {
|
|
||||||
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, '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) {
|
fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
|
||||||
intravisit::walk_expr(self, ex);
|
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) {
|
fn visit_item(&mut self, item: &'tcx hir::Item) {
|
||||||
intravisit::walk_item(self, 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 {
|
match item.node {
|
||||||
hir::ItemKind::ExternCrate(_) |
|
hir::ItemKind::ExternCrate(_) |
|
||||||
hir::ItemKind::Use(..) => (), // ignore these
|
hir::ItemKind::Use(..) => {} // ignore these
|
||||||
_ => self.index.record(def_id, IsolatedEncoder::encode_info_for_item, (def_id, item)),
|
_ => 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) {
|
fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) {
|
||||||
intravisit::walk_foreign_item(self, ni);
|
intravisit::walk_foreign_item(self, ni);
|
||||||
let def_id = self.index.tcx.hir().local_def_id_from_hir_id(ni.hir_id);
|
let def_id = self.tcx.hir().local_def_id_from_hir_id(ni.hir_id);
|
||||||
self.index.record(def_id,
|
self.record(def_id,
|
||||||
IsolatedEncoder::encode_info_for_foreign_item,
|
EncodeContext::encode_info_for_foreign_item,
|
||||||
(def_id, ni));
|
(def_id, ni));
|
||||||
}
|
}
|
||||||
fn visit_variant(&mut self,
|
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);
|
intravisit::walk_variant(self, v, g, id);
|
||||||
|
|
||||||
if let Some(ref discr) = v.node.disr_expr {
|
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);
|
let def_id = self.tcx.hir().local_def_id_from_hir_id(discr.hir_id);
|
||||||
self.index.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id);
|
self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
|
fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
|
||||||
intravisit::walk_generics(self, 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) {
|
fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
|
||||||
intravisit::walk_ty(self, 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) {
|
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);
|
let def_id = self.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);
|
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) {
|
fn encode_fields(&mut self, adt_def_id: DefId) {
|
||||||
let def = self.tcx.adt_def(adt_def_id);
|
let def = self.tcx.adt_def(adt_def_id);
|
||||||
for (variant_index, variant) in def.variants.iter_enumerated() {
|
for (variant_index, variant) in def.variants.iter_enumerated() {
|
||||||
for (field_index, field) in variant.fields.iter().enumerate() {
|
for (field_index, field) in variant.fields.iter().enumerate() {
|
||||||
self.record(field.did,
|
self.record(field.did,
|
||||||
IsolatedEncoder::encode_field,
|
EncodeContext::encode_field,
|
||||||
(adt_def_id, Untracked((variant_index, field_index))));
|
(adt_def_id, variant_index, field_index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1755,12 +1717,12 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
|
|||||||
GenericParamKind::Type { ref default, .. } => {
|
GenericParamKind::Type { ref default, .. } => {
|
||||||
self.record(
|
self.record(
|
||||||
def_id,
|
def_id,
|
||||||
IsolatedEncoder::encode_info_for_ty_param,
|
EncodeContext::encode_info_for_ty_param,
|
||||||
(def_id, Untracked(default.is_some())),
|
(def_id, default.is_some()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
GenericParamKind::Const { .. } => {
|
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 {
|
match ty.node {
|
||||||
hir::TyKind::Array(_, ref length) => {
|
hir::TyKind::Array(_, ref length) => {
|
||||||
let def_id = self.tcx.hir().local_def_id_from_hir_id(length.hir_id);
|
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 {
|
match expr.node {
|
||||||
hir::ExprKind::Closure(..) => {
|
hir::ExprKind::Closure(..) => {
|
||||||
let def_id = self.tcx.hir().local_def_id_from_hir_id(expr.hir_id);
|
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);
|
let def = self.tcx.adt_def(def_id);
|
||||||
for (i, variant) in def.variants.iter_enumerated() {
|
for (i, variant) in def.variants.iter_enumerated() {
|
||||||
self.record(variant.def_id,
|
self.record(variant.def_id,
|
||||||
IsolatedEncoder::encode_enum_variant_info,
|
EncodeContext::encode_enum_variant_info,
|
||||||
(def_id, Untracked(i)));
|
(def_id, i));
|
||||||
|
|
||||||
if let Some(ctor_def_id) = variant.ctor_def_id {
|
if let Some(ctor_def_id) = variant.ctor_def_id {
|
||||||
self.record(ctor_def_id,
|
self.record(ctor_def_id,
|
||||||
IsolatedEncoder::encode_enum_variant_ctor,
|
EncodeContext::encode_enum_variant_ctor,
|
||||||
(def_id, Untracked(i)));
|
(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() {
|
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);
|
let ctor_def_id = self.tcx.hir().local_def_id_from_hir_id(ctor_hir_id);
|
||||||
self.record(ctor_def_id,
|
self.record(ctor_def_id,
|
||||||
IsolatedEncoder::encode_struct_ctor,
|
EncodeContext::encode_struct_ctor,
|
||||||
(def_id, ctor_def_id));
|
(def_id, ctor_def_id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1839,14 +1801,14 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
|
|||||||
hir::ItemKind::Impl(..) => {
|
hir::ItemKind::Impl(..) => {
|
||||||
for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
|
for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
|
||||||
self.record(trait_item_def_id,
|
self.record(trait_item_def_id,
|
||||||
IsolatedEncoder::encode_info_for_impl_item,
|
EncodeContext::encode_info_for_impl_item,
|
||||||
trait_item_def_id);
|
trait_item_def_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ItemKind::Trait(..) => {
|
hir::ItemKind::Trait(..) => {
|
||||||
for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
|
for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
|
||||||
self.record(item_def_id,
|
self.record(item_def_id,
|
||||||
IsolatedEncoder::encode_info_for_trait_item,
|
EncodeContext::encode_info_for_trait_item,
|
||||||
item_def_id);
|
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.
|
// Will be filled with the root position after encoding everything.
|
||||||
encoder.emit_raw_bytes(&[0, 0, 0, 0]);
|
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 {
|
let mut ecx = EncodeContext {
|
||||||
opaque: encoder,
|
opaque: encoder,
|
||||||
tcx,
|
tcx,
|
||||||
|
entries_index: Index::new(tcx.hir().definitions().def_index_count()),
|
||||||
lazy_state: LazyState::NoNode,
|
lazy_state: LazyState::NoNode,
|
||||||
type_shorthands: Default::default(),
|
type_shorthands: Default::default(),
|
||||||
predicate_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.
|
// culminating in the `CrateRoot` which points to all of it.
|
||||||
let root = ecx.encode_crate_root();
|
let root = ecx.encode_crate_root();
|
||||||
(root, ecx.opaque.into_inner())
|
(root, ecx.opaque.into_inner())
|
||||||
};
|
});
|
||||||
|
|
||||||
// Encode the root position.
|
// Encode the root position.
|
||||||
let header = METADATA_HEADER.len();
|
let header = METADATA_HEADER.len();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use crate::schema::*;
|
|||||||
|
|
||||||
use rustc::hir::def_id::{DefId, DefIndex};
|
use rustc::hir::def_id::{DefId, DefIndex};
|
||||||
use rustc_serialize::opaque::Encoder;
|
use rustc_serialize::opaque::Encoder;
|
||||||
|
use std::marker::PhantomData;
|
||||||
use std::u32;
|
use std::u32;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
|
||||||
@@ -74,23 +75,25 @@ impl FixedSizeEncoding for u32 {
|
|||||||
/// `u32::MAX`. Whenever an index is visited, we fill in the
|
/// `u32::MAX`. Whenever an index is visited, we fill in the
|
||||||
/// appropriate spot by calling `record_position`. We should never
|
/// appropriate spot by calling `record_position`. We should never
|
||||||
/// visit the same index twice.
|
/// visit the same index twice.
|
||||||
pub struct Index {
|
pub struct Index<'tcx> {
|
||||||
positions: Vec<u8>,
|
positions: Vec<u8>,
|
||||||
|
_marker: PhantomData<&'tcx ()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Index {
|
impl Index<'tcx> {
|
||||||
pub fn new(max_index: usize) -> Index {
|
pub fn new(max_index: usize) -> Self {
|
||||||
Index {
|
Index {
|
||||||
positions: vec![0xff; max_index * 4],
|
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());
|
assert!(def_id.is_local());
|
||||||
self.record_index(def_id.index, entry);
|
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));
|
assert!(entry.position < (u32::MAX as usize));
|
||||||
let position = entry.position as u32;
|
let position = entry.position as u32;
|
||||||
let array_index = item.index();
|
let array_index = item.index();
|
||||||
@@ -105,7 +108,7 @@ impl Index {
|
|||||||
position.write_to_bytes_at(positions, array_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();
|
let pos = buf.position();
|
||||||
|
|
||||||
// First we write the length of the lower range ...
|
// 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
|
/// Given the metadata, extract out the offset of a particular
|
||||||
/// DefIndex (if any).
|
/// DefIndex (if any).
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(drain_filter)]
|
#![feature(drain_filter)]
|
||||||
|
#![feature(in_band_lifetimes)]
|
||||||
#![feature(libc)]
|
#![feature(libc)]
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
#![feature(proc_macro_internals)]
|
#![feature(proc_macro_internals)]
|
||||||
@@ -28,12 +29,10 @@ extern crate rustc_data_structures;
|
|||||||
|
|
||||||
mod error_codes;
|
mod error_codes;
|
||||||
|
|
||||||
mod index_builder;
|
|
||||||
mod index;
|
mod index;
|
||||||
mod encoder;
|
mod encoder;
|
||||||
mod decoder;
|
mod decoder;
|
||||||
mod cstore_impl;
|
mod cstore_impl;
|
||||||
mod isolated_encoder;
|
|
||||||
mod schema;
|
mod schema;
|
||||||
mod native_libs;
|
mod native_libs;
|
||||||
mod link_args;
|
mod link_args;
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ use crate::index;
|
|||||||
|
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::hir::def::{self, CtorKind};
|
use rustc::hir::def::{self, CtorKind};
|
||||||
use rustc::hir::def_id::{DefIndex, DefId, CrateNum};
|
use rustc::hir::def_id::{DefIndex, DefId};
|
||||||
use rustc::ich::StableHashingContext;
|
use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
|
||||||
use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary, ForeignModule};
|
use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary, ForeignModule};
|
||||||
use rustc::middle::lang_items;
|
use rustc::middle::lang_items;
|
||||||
use rustc::mir;
|
use rustc::mir;
|
||||||
@@ -19,10 +19,6 @@ use syntax::symbol::Symbol;
|
|||||||
use syntax_pos::{self, Span};
|
use syntax_pos::{self, Span};
|
||||||
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::mem;
|
|
||||||
|
|
||||||
use rustc_data_structures::stable_hasher::{StableHasher, HashStable,
|
|
||||||
StableHasherResult};
|
|
||||||
|
|
||||||
pub fn rustc_version() -> String {
|
pub fn rustc_version() -> String {
|
||||||
format!("rustc {}",
|
format!("rustc {}",
|
||||||
@@ -91,15 +87,6 @@ impl<T> Clone for Lazy<T> {
|
|||||||
impl<T> serialize::UseSpecializedEncodable for Lazy<T> {}
|
impl<T> serialize::UseSpecializedEncodable for Lazy<T> {}
|
||||||
impl<T> serialize::UseSpecializedDecodable 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
|
/// A sequence of type T referred to by its absolute position
|
||||||
/// in the metadata and length, and which can be decoded lazily.
|
/// in the metadata and length, and which can be decoded lazily.
|
||||||
/// The sequence is a single node for the purposes of `Lazy`.
|
/// 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::UseSpecializedEncodable for LazySeq<T> {}
|
||||||
impl<T> serialize::UseSpecializedDecodable 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`.
|
/// Encoding / decoding state for `Lazy` and `LazySeq`.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum LazyState {
|
pub enum LazyState {
|
||||||
@@ -174,7 +152,7 @@ pub enum LazyState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct CrateRoot {
|
pub struct CrateRoot<'tcx> {
|
||||||
pub name: Symbol,
|
pub name: Symbol,
|
||||||
pub triple: TargetTriple,
|
pub triple: TargetTriple,
|
||||||
pub extra_filename: String,
|
pub extra_filename: String,
|
||||||
@@ -199,10 +177,10 @@ pub struct CrateRoot {
|
|||||||
pub source_map: LazySeq<syntax_pos::SourceFile>,
|
pub source_map: LazySeq<syntax_pos::SourceFile>,
|
||||||
pub def_path_table: Lazy<hir::map::definitions::DefPathTable>,
|
pub def_path_table: Lazy<hir::map::definitions::DefPathTable>,
|
||||||
pub impls: LazySeq<TraitImpls>,
|
pub impls: LazySeq<TraitImpls>,
|
||||||
pub exported_symbols: EncodedExportedSymbols,
|
pub exported_symbols: LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)>,
|
||||||
pub interpret_alloc_index: LazySeq<u32>,
|
pub interpret_alloc_index: LazySeq<u32>,
|
||||||
|
|
||||||
pub index: LazySeq<index::Index>,
|
pub entries_index: LazySeq<index::Index<'tcx>>,
|
||||||
|
|
||||||
pub compiler_builtins: bool,
|
pub compiler_builtins: bool,
|
||||||
pub needs_allocator: bool,
|
pub needs_allocator: bool,
|
||||||
@@ -221,36 +199,12 @@ pub struct CrateDep {
|
|||||||
pub extra_filename: String,
|
pub extra_filename: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_stable_hash_for!(struct CrateDep {
|
|
||||||
name,
|
|
||||||
hash,
|
|
||||||
kind,
|
|
||||||
extra_filename
|
|
||||||
});
|
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct TraitImpls {
|
pub struct TraitImpls {
|
||||||
pub trait_id: (u32, DefIndex),
|
pub trait_id: (u32, DefIndex),
|
||||||
pub impls: LazySeq<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)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct Entry<'tcx> {
|
pub struct Entry<'tcx> {
|
||||||
pub kind: EntryKind<'tcx>,
|
pub kind: EntryKind<'tcx>,
|
||||||
@@ -271,23 +225,6 @@ pub struct Entry<'tcx> {
|
|||||||
pub mir: Option<Lazy<mir::Mir<'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)]
|
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
|
||||||
pub enum EntryKind<'tcx> {
|
pub enum EntryKind<'tcx> {
|
||||||
Const(ConstQualif, Lazy<RenderedConst>),
|
Const(ConstQualif, Lazy<RenderedConst>),
|
||||||
@@ -322,82 +259,6 @@ pub enum EntryKind<'tcx> {
|
|||||||
TraitAlias(Lazy<TraitAliasData<'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
|
/// Additional data for EntryKind::Const and EntryKind::AssociatedConst
|
||||||
#[derive(Clone, Copy, RustcEncodable, RustcDecodable)]
|
#[derive(Clone, Copy, RustcEncodable, RustcDecodable)]
|
||||||
pub struct ConstQualif {
|
pub struct ConstQualif {
|
||||||
@@ -405,37 +266,22 @@ pub struct ConstQualif {
|
|||||||
pub ast_promotable: bool,
|
pub ast_promotable: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_stable_hash_for!(struct ConstQualif { mir, ast_promotable });
|
|
||||||
|
|
||||||
/// Contains a constant which has been rendered to a String.
|
/// Contains a constant which has been rendered to a String.
|
||||||
/// Used by rustdoc.
|
/// Used by rustdoc.
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct RenderedConst(pub String);
|
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)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct ModData {
|
pub struct ModData {
|
||||||
pub reexports: LazySeq<def::Export<hir::HirId>>,
|
pub reexports: LazySeq<def::Export<hir::HirId>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_stable_hash_for!(struct ModData { reexports });
|
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct MacroDef {
|
pub struct MacroDef {
|
||||||
pub body: String,
|
pub body: String,
|
||||||
pub legacy: bool,
|
pub legacy: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_stable_hash_for!(struct MacroDef { body, legacy });
|
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct FnData<'tcx> {
|
pub struct FnData<'tcx> {
|
||||||
pub constness: hir::Constness,
|
pub constness: hir::Constness,
|
||||||
@@ -443,8 +289,6 @@ pub struct FnData<'tcx> {
|
|||||||
pub sig: Lazy<ty::PolyFnSig<'tcx>>,
|
pub sig: Lazy<ty::PolyFnSig<'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig });
|
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct VariantData<'tcx> {
|
pub struct VariantData<'tcx> {
|
||||||
pub ctor_kind: CtorKind,
|
pub ctor_kind: CtorKind,
|
||||||
@@ -456,13 +300,6 @@ pub struct VariantData<'tcx> {
|
|||||||
pub ctor_sig: Option<Lazy<ty::PolyFnSig<'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)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct TraitData<'tcx> {
|
pub struct TraitData<'tcx> {
|
||||||
pub unsafety: hir::Unsafety,
|
pub unsafety: hir::Unsafety,
|
||||||
@@ -472,23 +309,11 @@ pub struct TraitData<'tcx> {
|
|||||||
pub super_predicates: Lazy<ty::GenericPredicates<'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)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct TraitAliasData<'tcx> {
|
pub struct TraitAliasData<'tcx> {
|
||||||
pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
|
pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_stable_hash_for!(struct TraitAliasData<'tcx> {
|
|
||||||
super_predicates
|
|
||||||
});
|
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct ImplData<'tcx> {
|
pub struct ImplData<'tcx> {
|
||||||
pub polarity: hir::ImplPolarity,
|
pub polarity: hir::ImplPolarity,
|
||||||
@@ -500,14 +325,6 @@ pub struct ImplData<'tcx> {
|
|||||||
pub trait_ref: Option<Lazy<ty::TraitRef<'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
|
/// Describes whether the container of an associated item
|
||||||
/// is a trait or an impl and whether, in a trait, it has
|
/// is a trait or an impl and whether, in a trait, it has
|
||||||
@@ -520,13 +337,6 @@ pub enum AssociatedContainer {
|
|||||||
ImplFinal,
|
ImplFinal,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_stable_hash_for!(enum crate::schema::AssociatedContainer {
|
|
||||||
TraitRequired,
|
|
||||||
TraitWithDefault,
|
|
||||||
ImplDefault,
|
|
||||||
ImplFinal
|
|
||||||
});
|
|
||||||
|
|
||||||
impl AssociatedContainer {
|
impl AssociatedContainer {
|
||||||
pub fn with_def_id(&self, def_id: DefId) -> ty::AssociatedItemContainer {
|
pub fn with_def_id(&self, def_id: DefId) -> ty::AssociatedItemContainer {
|
||||||
match *self {
|
match *self {
|
||||||
@@ -560,26 +370,17 @@ pub struct MethodData<'tcx> {
|
|||||||
pub container: AssociatedContainer,
|
pub container: AssociatedContainer,
|
||||||
pub has_self: bool,
|
pub has_self: bool,
|
||||||
}
|
}
|
||||||
impl_stable_hash_for!(struct MethodData<'tcx> { fn_data, container, has_self });
|
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct ClosureData<'tcx> {
|
pub struct ClosureData<'tcx> {
|
||||||
pub sig: Lazy<ty::PolyFnSig<'tcx>>,
|
pub sig: Lazy<ty::PolyFnSig<'tcx>>,
|
||||||
}
|
}
|
||||||
impl_stable_hash_for!(struct ClosureData<'tcx> { sig });
|
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct GeneratorData<'tcx> {
|
pub struct GeneratorData<'tcx> {
|
||||||
pub layout: mir::GeneratorLayout<'tcx>,
|
pub layout: mir::GeneratorLayout<'tcx>,
|
||||||
}
|
}
|
||||||
impl_stable_hash_for!(struct GeneratorData<'tcx> { layout });
|
|
||||||
|
|
||||||
// Tags used for encoding Spans:
|
// Tags used for encoding Spans:
|
||||||
pub const TAG_VALID_SPAN: u8 = 0;
|
pub const TAG_VALID_SPAN: u8 = 0;
|
||||||
pub const TAG_INVALID_SPAN: u8 = 1;
|
pub const TAG_INVALID_SPAN: u8 = 1;
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
|
||||||
pub struct EncodedExportedSymbols {
|
|
||||||
pub position: usize,
|
|
||||||
pub len: usize,
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -439,10 +439,11 @@ fn downgrade_if_error(diag: &mut Diagnostic) {
|
|||||||
diag.warn(
|
diag.warn(
|
||||||
"this error has been downgraded to a warning for backwards \
|
"this error has been downgraded to a warning for backwards \
|
||||||
compatibility with previous releases",
|
compatibility with previous releases",
|
||||||
);
|
).warn(
|
||||||
diag.warn(
|
|
||||||
"this represents potential undefined behavior in your code and \
|
"this represents potential undefined behavior in your code and \
|
||||||
this warning will become a hard error in the future",
|
this warning will become a hard error in the future",
|
||||||
|
).note(
|
||||||
|
"for more information, try `rustc --explain E0729`"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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! {
|
register_diagnostics! {
|
||||||
|
|||||||
@@ -930,58 +930,60 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
|
|||||||
context: PlaceContext,
|
context: PlaceContext,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
debug!("visit_place: place={:?} context={:?} location={:?}", place, context, location);
|
debug!("visit_place: place={:?} context={:?} location={:?}", place, context, location);
|
||||||
self.super_place(place, context, location);
|
place.iterate(|place_base, place_projections| {
|
||||||
match *place {
|
match place_base {
|
||||||
Place::Base(PlaceBase::Local(_)) => {}
|
PlaceBase::Local(_) => {}
|
||||||
Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) => {
|
PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. }) => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })) => {
|
PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. }) => {
|
||||||
if self.tcx
|
if self.tcx
|
||||||
.get_attrs(def_id)
|
.get_attrs(*def_id)
|
||||||
.iter()
|
.iter()
|
||||||
.any(|attr| attr.check_name(sym::thread_local)) {
|
.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 {
|
if self.mode != Mode::Fn {
|
||||||
span_err!(self.tcx.sess, self.span, E0625,
|
let mut err = struct_span_err!(self.tcx.sess, self.span, E0013,
|
||||||
"thread-local statics cannot be \
|
"{}s cannot refer to statics, use \
|
||||||
accessed at compile-time");
|
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 {
|
match proj.elem {
|
||||||
ProjectionElem::Deref => {
|
ProjectionElem::Deref => {
|
||||||
if context.is_mutating_use() {
|
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) {
|
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
|
||||||
|
|||||||
@@ -1134,6 +1134,13 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||||||
is just used to enable niche optimizations in libcore \
|
is just used to enable niche optimizations in libcore \
|
||||||
and will never be stable",
|
and will never be stable",
|
||||||
cfg_fn!(rustc_attrs))),
|
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_regions, Normal, template!(Word), Gated(Stability::Unstable,
|
||||||
sym::rustc_attrs,
|
sym::rustc_attrs,
|
||||||
"the `#[rustc_regions]` attribute \
|
"the `#[rustc_regions]` attribute \
|
||||||
|
|||||||
@@ -491,6 +491,7 @@ symbols! {
|
|||||||
rustc_layout_scalar_valid_range_end,
|
rustc_layout_scalar_valid_range_end,
|
||||||
rustc_layout_scalar_valid_range_start,
|
rustc_layout_scalar_valid_range_start,
|
||||||
rustc_mir,
|
rustc_mir,
|
||||||
|
rustc_nonnull_optimization_guaranteed,
|
||||||
rustc_object_lifetime_default,
|
rustc_object_lifetime_default,
|
||||||
rustc_on_unimplemented,
|
rustc_on_unimplemented,
|
||||||
rustc_outlives,
|
rustc_outlives,
|
||||||
|
|||||||
35
src/test/rustdoc/issue-60726.rs
Normal file
35
src/test/rustdoc/issue-60726.rs
Normal 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>>,
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@ LL | *a += 1;
|
|||||||
|
|
|
|
||||||
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
|
= 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
|
= 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
|
error[E0503]: cannot use `y` because it was mutably borrowed
|
||||||
--> $DIR/borrowck-anon-fields-variant.rs:37:7
|
--> $DIR/borrowck-anon-fields-variant.rs:37:7
|
||||||
|
|||||||
@@ -341,6 +341,7 @@ LL | drop(x);
|
|||||||
|
|
|
|
||||||
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
|
= 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
|
= 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
|
warning[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
|
||||||
--> $DIR/borrowck-describe-lvalue.rs:227:33
|
--> $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 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
|
= 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`
|
error[E0382]: use of moved value: `x`
|
||||||
--> $DIR/borrowck-describe-lvalue.rs:282:22
|
--> $DIR/borrowck-describe-lvalue.rs:282:22
|
||||||
|
|||||||
@@ -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 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
|
= 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`
|
||||||
|
|
||||||
|
|||||||
@@ -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 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
|
= 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`
|
||||||
|
|
||||||
|
|||||||
@@ -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 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
|
= 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
|
warning[E0510]: cannot mutably borrow `x` in match guard
|
||||||
--> $DIR/borrowck-mutate-in-guard.rs:15:33
|
--> $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 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
|
= 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
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ LL | a + b
|
|||||||
|
|
|
|
||||||
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
|
= 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
|
= 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`
|
warning[E0381]: use of possibly uninitialized variable: `b`
|
||||||
--> $DIR/const_let_refutable.rs:4:9
|
--> $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 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
|
= 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
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|||||||
@@ -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 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
|
= 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
|
error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
|
||||||
--> $DIR/min_const_fn.rs:144:41
|
--> $DIR/min_const_fn.rs:144:41
|
||||||
|
|||||||
@@ -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 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
|
= 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
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ LL | u
|
|||||||
|
|
|
|
||||||
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
|
= 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
|
= 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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ LL | m;
|
|||||||
|
|
|
|
||||||
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
|
= 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
|
= 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
|
error: compilation successful
|
||||||
--> $DIR/feature-gate-nll.rs:10:1
|
--> $DIR/feature-gate-nll.rs:10:1
|
||||||
|
|||||||
@@ -4,5 +4,6 @@
|
|||||||
|
|
||||||
#[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
|
#[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_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() {}
|
fn main() {}
|
||||||
|
|||||||
@@ -16,6 +16,15 @@ LL | #[rustc_error]
|
|||||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||||
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
|
= 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`.
|
For more information about this error, try `rustc --explain E0658`.
|
||||||
|
|||||||
@@ -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 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
|
= 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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ LL | &mut x
|
|||||||
= note: ...therefore, they cannot allow references to captured variables to escape
|
= 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 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
|
= 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
|
error: compilation successful
|
||||||
--> $DIR/issue-40510-1.rs:20:1
|
--> $DIR/issue-40510-1.rs:20:1
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ LL | | }
|
|||||||
= note: ...therefore, they cannot allow references to captured variables to escape
|
= 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 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
|
= 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
|
error: compilation successful
|
||||||
--> $DIR/issue-40510-3.rs:22:1
|
--> $DIR/issue-40510-3.rs:22:1
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ LL | }
|
|||||||
|
|
|
|
||||||
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
|
= 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
|
= 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
|
warning[E0713]: borrow may still be in use when destructor runs
|
||||||
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:62:5
|
--> $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 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
|
= 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
|
warning[E0713]: borrow may still be in use when destructor runs
|
||||||
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:73:5
|
--> $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 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
|
= 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
|
error: compilation successful
|
||||||
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:80:1
|
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:80:1
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ LL | | }
|
|||||||
= note: ...therefore, they cannot allow references to captured variables to escape
|
= 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 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
|
= 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
|
error: compilation successful
|
||||||
--> $DIR/issue-49824.rs:6:1
|
--> $DIR/issue-49824.rs:6:1
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#![deny(improper_ctypes)]
|
#![deny(improper_ctypes)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
use std::num;
|
||||||
|
|
||||||
enum Z { }
|
enum Z { }
|
||||||
enum U { A }
|
enum U { A }
|
||||||
enum B { C, D }
|
enum B { C, D }
|
||||||
@@ -15,14 +17,39 @@ enum U8 { A, B, C }
|
|||||||
#[repr(isize)]
|
#[repr(isize)]
|
||||||
enum Isize { A, B, C }
|
enum Isize { A, B, C }
|
||||||
|
|
||||||
|
#[repr(transparent)]
|
||||||
|
struct Transparent<T>(T, std::marker::PhantomData<Z>);
|
||||||
|
|
||||||
|
struct Rust<T>(T);
|
||||||
|
|
||||||
extern {
|
extern {
|
||||||
fn zf(x: Z);
|
fn zf(x: Z);
|
||||||
fn uf(x: U); //~ ERROR enum has no representation hint
|
fn uf(x: U); //~ ERROR enum has no representation hint
|
||||||
fn bf(x: B); //~ 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 tf(x: T); //~ ERROR enum has no representation hint
|
||||||
fn reprc(x: ReprC);
|
fn repr_c(x: ReprC);
|
||||||
fn u8(x: U8);
|
fn repr_u8(x: U8);
|
||||||
fn isize(x: Isize);
|
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() { }
|
pub fn main() { }
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
error: `extern` block uses type `U` which is not FFI-safe: enum has no representation hint
|
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);
|
LL | fn uf(x: U);
|
||||||
| ^
|
| ^
|
||||||
@@ -11,36 +11,64 @@ LL | #![deny(improper_ctypes)]
|
|||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
= help: consider adding a #[repr(...)] attribute to this enum
|
= help: consider adding a #[repr(...)] attribute to this enum
|
||||||
note: type defined here
|
note: type defined here
|
||||||
--> $DIR/lint-ctypes-enum.rs:5:1
|
--> $DIR/lint-ctypes-enum.rs:7:1
|
||||||
|
|
|
|
||||||
LL | enum U { A }
|
LL | enum U { A }
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `extern` block uses type `B` which is not FFI-safe: enum has no representation hint
|
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);
|
LL | fn bf(x: B);
|
||||||
| ^
|
| ^
|
||||||
|
|
|
|
||||||
= help: consider adding a #[repr(...)] attribute to this enum
|
= help: consider adding a #[repr(...)] attribute to this enum
|
||||||
note: type defined here
|
note: type defined here
|
||||||
--> $DIR/lint-ctypes-enum.rs:6:1
|
--> $DIR/lint-ctypes-enum.rs:8:1
|
||||||
|
|
|
|
||||||
LL | enum B { C, D }
|
LL | enum B { C, D }
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `extern` block uses type `T` which is not FFI-safe: enum has no representation hint
|
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);
|
LL | fn tf(x: T);
|
||||||
| ^
|
| ^
|
||||||
|
|
|
|
||||||
= help: consider adding a #[repr(...)] attribute to this enum
|
= help: consider adding a #[repr(...)] attribute to this enum
|
||||||
note: type defined here
|
note: type defined here
|
||||||
--> $DIR/lint-ctypes-enum.rs:7:1
|
--> $DIR/lint-ctypes-enum.rs:9:1
|
||||||
|
|
|
|
||||||
LL | enum T { E, F, G }
|
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
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ LL | **z = None;
|
|||||||
|
|
|
|
||||||
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
|
= 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
|
= 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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ LL | x
|
|||||||
|
|
|
|
||||||
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
|
= 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
|
= 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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|||||||
@@ -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 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
|
= 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
|
error[E0625]: thread-local statics cannot be accessed at compile-time
|
||||||
--> $DIR/thread-local-in-ctfe.rs:15:16
|
--> $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 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
|
= 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
|
error[E0625]: thread-local statics cannot be accessed at compile-time
|
||||||
--> $DIR/thread-local-in-ctfe.rs:25:5
|
--> $DIR/thread-local-in-ctfe.rs:25:5
|
||||||
|
|||||||
Submodule src/tools/clippy updated: 60a609acae...a8eeb7cdb1
Reference in New Issue
Block a user