Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 8 pull requests #63465

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
f84967f
Use sharded maps for queries
Zoxc Jun 12, 2019
740f8db
Add FIXME-s that some types should be transparent
MikailBag Jun 19, 2019
03e95ae
Miri shouldn't look at types
RalfJung Aug 10, 2019
62f1e8a
fix test
RalfJung Aug 10, 2019
440a5c8
rename RUST_CTFE_BACKTRACE to RUSTC_CTFE_BACKTRACE
RalfJung Aug 10, 2019
93839c3
Add an example to show how to insert item to a sorted vec
tesuji Aug 10, 2019
30ba4bd
Use Result::unwrap_or_else instead of matching
tesuji Aug 10, 2019
6b11a63
syntax: account for CVarArgs being in the argument list.
eddyb Aug 11, 2019
a8017d6
resolve: Populate external modules in more automatic and lazy way
petrochenkov Jul 29, 2019
aee4313
resolve: Populate external traits lazily as well
petrochenkov Jul 30, 2019
da6fbb1
add basic lint testing for misuse of mem::zeroed and mem::uninitialized
RalfJung Aug 6, 2019
ca1e94b
warn for more cases
RalfJung Aug 7, 2019
fbd5613
fix a comment
RalfJung Aug 7, 2019
8e6fbbe
add tuple_fields convenience method and use it in a few places
RalfJung Aug 7, 2019
4b062a1
note a FIXME
RalfJung Aug 7, 2019
3972d05
proper doc comment for 'recovered' field of variant
RalfJung Aug 7, 2019
c5a6356
allow the lint if a few UB-demonstrating doc tests
RalfJung Aug 7, 2019
5c77a17
note down some more future plans
RalfJung Aug 7, 2019
0930747
update clippy
RalfJung Aug 11, 2019
a087df6
resolve: Move some code around
petrochenkov Jul 30, 2019
83b0104
Rollup merge of #61969 - MikailBag:master, r=Centril
Mark-Simulacrum Aug 11, 2019
6381937
Rollup merge of #62108 - Zoxc:sharded-queries, r=oli-obk
Mark-Simulacrum Aug 11, 2019
9b835f3
Rollup merge of #63149 - petrochenkov:lazypop2, r=eddyb
Mark-Simulacrum Aug 11, 2019
d941f97
Rollup merge of #63346 - RalfJung:zeroed-lint, r=eddyb
Mark-Simulacrum Aug 11, 2019
63b4709
Rollup merge of #63433 - RalfJung:miri-call, r=oli-obk
Mark-Simulacrum Aug 11, 2019
9fbfab8
Rollup merge of #63440 - RalfJung:ctfe-backtrace, r=oli-obk
Mark-Simulacrum Aug 11, 2019
93bd9ff
Rollup merge of #63442 - lzutao:vec-bin-search-insert, r=Mark-Simulacrum
Mark-Simulacrum Aug 11, 2019
262394e
Rollup merge of #63459 - eddyb:issue-63430, r=petrochenkov
Mark-Simulacrum Aug 11, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/libcore/mem/maybe_uninit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::mem::ManuallyDrop;
/// ever gets used to access memory:
///
/// ```rust,no_run
/// # #![allow(invalid_value)]
/// use std::mem::{self, MaybeUninit};
///
/// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior!
Expand All @@ -27,6 +28,7 @@ use crate::mem::ManuallyDrop;
/// always be `true` or `false`. Hence, creating an uninitialized `bool` is undefined behavior:
///
/// ```rust,no_run
/// # #![allow(invalid_value)]
/// use std::mem::{self, MaybeUninit};
///
/// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior!
Expand All @@ -40,6 +42,7 @@ use crate::mem::ManuallyDrop;
/// which otherwise can hold any *fixed* bit pattern:
///
/// ```rust,no_run
/// # #![allow(invalid_value)]
/// use std::mem::{self, MaybeUninit};
///
/// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior!
Expand Down
3 changes: 2 additions & 1 deletion src/libcore/mem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,8 @@ pub const fn needs_drop<T>() -> bool {
///
/// *Incorrect* usage of this function: initializing a reference with zero.
///
/// ```no_run
/// ```rust,no_run
/// # #![allow(invalid_value)]
/// use std::mem;
///
/// let _x: &i32 = unsafe { mem::zeroed() }; // Undefined behavior!
Expand Down
11 changes: 11 additions & 0 deletions src/libcore/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1364,6 +1364,17 @@ impl<T> [T] {
/// let r = s.binary_search(&1);
/// assert!(match r { Ok(1..=4) => true, _ => false, });
/// ```
///
/// If you want to insert an item to a sorted vector, while maintaining
/// sort order:
///
/// ```
/// let mut s = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
/// let num = 42;
/// let idx = s.binary_search(&num).unwrap_or_else(|x| x);
/// s.insert(idx, num);
/// assert_eq!(s, [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn binary_search(&self, x: &T) -> Result<usize, usize>
where T: Ord
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ fn print_backtrace(backtrace: &mut Backtrace) {

impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
fn from(kind: InterpError<'tcx>) -> Self {
let backtrace = match env::var("RUST_CTFE_BACKTRACE") {
let backtrace = match env::var("RUSTC_CTFE_BACKTRACE") {
// Matching `RUST_BACKTRACE` -- we treat "0" the same as "not present".
Ok(ref val) if val != "0" => {
let mut backtrace = Backtrace::new_unresolved();
Expand Down
7 changes: 5 additions & 2 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1842,7 +1842,8 @@ pub struct VariantDef {
pub ctor_kind: CtorKind,
/// Flags of the variant (e.g. is field list non-exhaustive)?
flags: VariantFlags,
/// Recovered?
/// Variant is obtained as part of recovering from a syntactic error.
/// May be incomplete or bogus.
pub recovered: bool,
}

Expand Down Expand Up @@ -1949,7 +1950,7 @@ pub struct FieldDef {
pub struct AdtDef {
/// `DefId` of the struct, enum or union item.
pub did: DefId,
/// Variants of the ADT. If this is a struct or enum, then there will be a single variant.
/// Variants of the ADT. If this is a struct or union, then there will be a single variant.
pub variants: IndexVec<self::layout::VariantIdx, VariantDef>,
/// Flags of the ADT (e.g. is this a struct? is this non-exhaustive?)
flags: AdtFlags,
Expand Down Expand Up @@ -2565,6 +2566,8 @@ impl<'tcx> AdtDef {
}

impl<'tcx> FieldDef {
/// Returns the type of this field. The `subst` is typically obtained
/// via the second field of `TyKind::AdtDef`.
pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> {
tcx.type_of(self.did).subst(tcx, subst)
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/ty/query/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::util::profiling::ProfileCategory;
use std::borrow::Cow;
use std::hash::Hash;
use std::fmt::Debug;
use rustc_data_structures::sync::Lock;
use rustc_data_structures::sharded::Sharded;
use rustc_data_structures::fingerprint::Fingerprint;
use crate::ich::StableHashingContext;

Expand All @@ -34,7 +34,7 @@ pub(crate) trait QueryAccessors<'tcx>: QueryConfig<'tcx> {
fn query(key: Self::Key) -> Query<'tcx>;

// Don't use this method to access query results, instead use the methods on TyCtxt
fn query_cache<'a>(tcx: TyCtxt<'tcx>) -> &'a Lock<QueryCache<'tcx, Self>>;
fn query_cache<'a>(tcx: TyCtxt<'tcx>) -> &'a Sharded<QueryCache<'tcx, Self>>;

fn to_dep_node(tcx: TyCtxt<'tcx>, key: &Self::Key) -> DepNode;

Expand Down
6 changes: 3 additions & 3 deletions src/librustc/ty/query/on_disk_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1062,9 +1062,9 @@ where
::std::any::type_name::<Q>());

time_ext(tcx.sess.time_extended(), Some(tcx.sess), desc, || {
let map = Q::query_cache(tcx).borrow();
assert!(map.active.is_empty());
for (key, entry) in map.results.iter() {
let shards = Q::query_cache(tcx).lock_shards();
assert!(shards.iter().all(|shard| shard.active.is_empty()));
for (key, entry) in shards.iter().flat_map(|shard| shard.results.iter()) {
if Q::cache_on_disk(tcx, key.clone(), Some(&entry.value)) {
let dep_node = SerializedDepNodeIndex::new(entry.index.index());

Expand Down
44 changes: 23 additions & 21 deletions src/librustc/ty/query/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use errors::Diagnostic;
use errors::FatalError;
use rustc_data_structures::fx::{FxHashMap};
use rustc_data_structures::sync::{Lrc, Lock};
use rustc_data_structures::sharded::Sharded;
use rustc_data_structures::thin_vec::ThinVec;
#[cfg(not(parallel_compiler))]
use rustc_data_structures::cold_path;
Expand Down Expand Up @@ -90,7 +91,7 @@ macro_rules! profq_query_msg {
/// A type representing the responsibility to execute the job in the `job` field.
/// This will poison the relevant query if dropped.
pub(super) struct JobOwner<'a, 'tcx, Q: QueryDescription<'tcx>> {
cache: &'a Lock<QueryCache<'tcx, Q>>,
cache: &'a Sharded<QueryCache<'tcx, Q>>,
key: Q::Key,
job: Lrc<QueryJob<'tcx>>,
}
Expand All @@ -107,7 +108,7 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
pub(super) fn try_get(tcx: TyCtxt<'tcx>, span: Span, key: &Q::Key) -> TryGetJob<'a, 'tcx, Q> {
let cache = Q::query_cache(tcx);
loop {
let mut lock = cache.borrow_mut();
let mut lock = cache.get_shard_by_value(key).lock();
if let Some(value) = lock.results.get(key) {
profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
tcx.sess.profiler(|p| p.record_query_hit(Q::NAME));
Expand Down Expand Up @@ -191,7 +192,7 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {

let value = QueryValue::new(result.clone(), dep_node_index);
{
let mut lock = cache.borrow_mut();
let mut lock = cache.get_shard_by_value(&key).lock();
lock.active.remove(&key);
lock.results.insert(key, value);
}
Expand All @@ -215,7 +216,8 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> Drop for JobOwner<'a, 'tcx, Q> {
#[cold]
fn drop(&mut self) {
// Poison the query so jobs waiting on it panic
self.cache.borrow_mut().active.insert(self.key.clone(), QueryResult::Poisoned);
let shard = self.cache.get_shard_by_value(&self.key);
shard.lock().active.insert(self.key.clone(), QueryResult::Poisoned);
// Also signal the completion of the job, so waiters
// will continue execution
self.job.signal_complete();
Expand Down Expand Up @@ -708,7 +710,7 @@ macro_rules! define_queries_inner {
use std::mem;
#[cfg(parallel_compiler)]
use ty::query::job::QueryResult;
use rustc_data_structures::sync::Lock;
use rustc_data_structures::sharded::Sharded;
use crate::{
rustc_data_structures::stable_hasher::HashStable,
rustc_data_structures::stable_hasher::StableHasherResult,
Expand Down Expand Up @@ -740,18 +742,17 @@ macro_rules! define_queries_inner {
pub fn collect_active_jobs(&self) -> Vec<Lrc<QueryJob<$tcx>>> {
let mut jobs = Vec::new();

// We use try_lock here since we are only called from the
// We use try_lock_shards here since we are only called from the
// deadlock handler, and this shouldn't be locked.
$(
jobs.extend(
self.$name.try_lock().unwrap().active.values().filter_map(|v|
if let QueryResult::Started(ref job) = *v {
Some(job.clone())
} else {
None
}
)
);
let shards = self.$name.try_lock_shards().unwrap();
jobs.extend(shards.iter().flat_map(|shard| shard.active.values().filter_map(|v|
if let QueryResult::Started(ref job) = *v {
Some(job.clone())
} else {
None
}
)));
)*

jobs
Expand All @@ -773,26 +774,27 @@ macro_rules! define_queries_inner {

fn stats<'tcx, Q: QueryConfig<'tcx>>(
name: &'static str,
map: &QueryCache<'tcx, Q>
map: &Sharded<QueryCache<'tcx, Q>>,
) -> QueryStats {
let map = map.lock_shards();
QueryStats {
name,
#[cfg(debug_assertions)]
cache_hits: map.cache_hits,
cache_hits: map.iter().map(|shard| shard.cache_hits).sum(),
#[cfg(not(debug_assertions))]
cache_hits: 0,
key_size: mem::size_of::<Q::Key>(),
key_type: type_name::<Q::Key>(),
value_size: mem::size_of::<Q::Value>(),
value_type: type_name::<Q::Value>(),
entry_count: map.results.len(),
entry_count: map.iter().map(|shard| shard.results.len()).sum(),
}
}

$(
queries.push(stats::<queries::$name<'_>>(
stringify!($name),
&*self.$name.lock()
&self.$name,
));
)*

Expand Down Expand Up @@ -967,7 +969,7 @@ macro_rules! define_queries_inner {
}

#[inline(always)]
fn query_cache<'a>(tcx: TyCtxt<$tcx>) -> &'a Lock<QueryCache<$tcx, Self>> {
fn query_cache<'a>(tcx: TyCtxt<$tcx>) -> &'a Sharded<QueryCache<$tcx, Self>> {
&tcx.queries.$name
}

Expand Down Expand Up @@ -1099,7 +1101,7 @@ macro_rules! define_queries_struct {
providers: IndexVec<CrateNum, Providers<$tcx>>,
fallback_extern_providers: Box<Providers<$tcx>>,

$($(#[$attr])* $name: Lock<QueryCache<$tcx, queries::$name<$tcx>>>,)*
$($(#[$attr])* $name: Sharded<QueryCache<$tcx, queries::$name<$tcx>>>,)*
}
};
}
Expand Down
14 changes: 12 additions & 2 deletions src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ pub enum TyKind<'tcx> {
Never,

/// A tuple type. For example, `(i32, bool)`.
/// Use `TyS::tuple_fields` to iterate over the field types.
Tuple(SubstsRef<'tcx>),

/// The projection of an associated type. For example,
Expand Down Expand Up @@ -1723,8 +1724,8 @@ impl<'tcx> TyS<'tcx> {
})
})
}
ty::Tuple(tys) => tys.iter().any(|ty| {
ty.expect_ty().conservative_is_privately_uninhabited(tcx)
ty::Tuple(..) => self.tuple_fields().any(|ty| {
ty.conservative_is_privately_uninhabited(tcx)
}),
ty::Array(ty, len) => {
match len.try_eval_usize(tcx, ParamEnv::empty()) {
Expand Down Expand Up @@ -2103,6 +2104,15 @@ impl<'tcx> TyS<'tcx> {
}
}

/// Iterates over tuple fields.
/// Panics when called on anything but a tuple.
pub fn tuple_fields(&self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> {
match self.sty {
Tuple(substs) => substs.iter().map(|field| field.expect_ty()),
_ => bug!("tuple_fields called on non-tuple"),
}
}

/// If the type contains variants, returns the valid range of variant indices.
/// FIXME This requires the optimized MIR in the case of generators.
#[inline]
Expand Down
8 changes: 4 additions & 4 deletions src/librustc/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -845,15 +845,15 @@ impl<'tcx> ty::TyS<'tcx> {
ty: Ty<'tcx>,
) -> Representability {
match ty.sty {
Tuple(ref ts) => {
Tuple(..) => {
// Find non representable
fold_repr(ts.iter().map(|ty| {
fold_repr(ty.tuple_fields().map(|ty| {
is_type_structurally_recursive(
tcx,
sp,
seen,
representable_cache,
ty.expect_ty(),
ty,
)
}))
}
Expand Down Expand Up @@ -1095,7 +1095,7 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>
// state transformation pass
ty::Generator(..) => true,

ty::Tuple(ref tys) => tys.iter().map(|k| k.expect_ty()).any(needs_drop),
ty::Tuple(..) => ty.tuple_fields().any(needs_drop),

// unions don't have destructors because of the child types,
// only if they manually implement `Drop` (handled above).
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/ty/walk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
ty::GeneratorWitness(ts) => {
stack.extend(ts.skip_binder().iter().cloned().rev());
}
ty::Tuple(ts) => {
stack.extend(ts.iter().map(|k| k.expect_ty()).rev());
ty::Tuple(..) => {
stack.extend(parent_ty.tuple_fields().rev());
}
ty::FnDef(_, substs) => {
stack.extend(substs.types().rev());
Expand Down
Loading