Skip to content

Commit

Permalink
Auto merge of #68423 - Centril:rollup-bdjykrv, r=Centril
Browse files Browse the repository at this point in the history
Rollup of 7 pull requests

Successful merges:

 - #67686 (Simplify NodeHeader by avoiding slices in BTreeMaps with shared roots)
 - #68140 (Implement `?const` opt-out for trait bounds)
 - #68313 (Options IP_MULTICAST_TTL and IP_MULTICAST_LOOP are 1 byte on BSD)
 - #68328 (Actually pass target LLVM args to LLVM)
 - #68399 (check_match: misc unifications and ICE fixes)
 - #68415 (tidy: fix most clippy warnings)
 - #68416 (lowering: cleanup some hofs)

Failed merges:

r? @ghost
  • Loading branch information
bors committed Jan 21, 2020
2 parents 2cf24ab + c1b20b1 commit 5e8897b
Show file tree
Hide file tree
Showing 95 changed files with 780 additions and 564 deletions.
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3763,6 +3763,7 @@ dependencies = [
"rustc_hir",
"rustc_index",
"rustc_macros",
"rustc_session",
"rustc_span",
"rustc_target",
"serialize",
Expand Down
6 changes: 3 additions & 3 deletions src/liballoc/collections/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1968,7 +1968,7 @@ where
(i, false) => i,
},
(_, Unbounded) => 0,
(true, Included(_)) => min_node.keys().len(),
(true, Included(_)) => min_node.len(),
(true, Excluded(_)) => 0,
};

Expand All @@ -1987,9 +1987,9 @@ where
}
(i, false) => i,
},
(_, Unbounded) => max_node.keys().len(),
(_, Unbounded) => max_node.len(),
(true, Included(_)) => 0,
(true, Excluded(_)) => max_node.keys().len(),
(true, Excluded(_)) => max_node.len(),
};

if !diverged {
Expand Down
65 changes: 11 additions & 54 deletions src/liballoc/collections/btree/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,8 @@ pub const CAPACITY: usize = 2 * B - 1;
/// `NodeHeader` because we do not want unnecessary padding between `len` and the keys.
/// Crucially, `NodeHeader` can be safely transmuted to different K and V. (This is exploited
/// by `as_header`.)
/// See `into_key_slice` for an explanation of K2. K2 cannot be safely transmuted around
/// because the size of `NodeHeader` depends on its alignment!
#[repr(C)]
struct NodeHeader<K, V, K2 = ()> {
struct NodeHeader<K, V> {
/// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`.
/// This either points to an actual node or is null.
parent: *const InternalNode<K, V>,
Expand All @@ -72,9 +70,6 @@ struct NodeHeader<K, V, K2 = ()> {
/// This next to `parent_idx` to encourage the compiler to join `len` and
/// `parent_idx` into the same 32-bit word, reducing space overhead.
len: u16,

/// See `into_key_slice`.
keys_start: [K2; 0],
}
#[repr(C)]
struct LeafNode<K, V> {
Expand Down Expand Up @@ -128,7 +123,7 @@ unsafe impl Sync for NodeHeader<(), ()> {}
// We use just a header in order to save space, since no operation on an empty tree will
// ever take a pointer past the first key.
static EMPTY_ROOT_NODE: NodeHeader<(), ()> =
NodeHeader { parent: ptr::null(), parent_idx: MaybeUninit::uninit(), len: 0, keys_start: [] };
NodeHeader { parent: ptr::null(), parent_idx: MaybeUninit::uninit(), len: 0 };

/// The underlying representation of internal nodes. As with `LeafNode`s, these should be hidden
/// behind `BoxedNode`s to prevent dropping uninitialized keys and values. Any pointer to an
Expand Down Expand Up @@ -390,14 +385,13 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
}

/// Borrows a view into the keys stored in the node.
/// Works on all possible nodes, including the shared root.
pub fn keys(&self) -> &[K] {
/// The caller must ensure that the node is not the shared root.
pub unsafe fn keys(&self) -> &[K] {
self.reborrow().into_key_slice()
}

/// Borrows a view into the values stored in the node.
/// The caller must ensure that the node is not the shared root.
/// This function is not public, so doesn't have to support shared roots like `keys` does.
fn vals(&self) -> &[V] {
self.reborrow().into_val_slice()
}
Expand Down Expand Up @@ -515,7 +509,6 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
}

/// The caller must ensure that the node is not the shared root.
/// This function is not public, so doesn't have to support shared roots like `keys` does.
fn keys_mut(&mut self) -> &mut [K] {
unsafe { self.reborrow_mut().into_key_slice_mut() }
}
Expand All @@ -527,48 +520,11 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
}

impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
fn into_key_slice(self) -> &'a [K] {
// We have to be careful here because we might be pointing to the shared root.
// In that case, we must not create an `&LeafNode`. We could just return
// an empty slice whenever the length is 0 (this includes the shared root),
// but we want to avoid that run-time check.
// Instead, we create a slice pointing into the node whenever possible.
// We can sometimes do this even for the shared root, as the slice will be
// empty and `NodeHeader` contains an empty `keys_start` array.
// We cannot *always* do this because:
// - `keys_start` is not correctly typed because we want `NodeHeader`'s size to
// not depend on the alignment of `K` (needed because `as_header` should be safe).
// For this reason, `NodeHeader` has this `K2` parameter (that's usually `()`
// and hence just adds a size-0-align-1 field, not affecting layout).
// If the correctly typed header is more highly aligned than the allocated header,
// we cannot transmute safely.
// - Even if we can transmute, the offset of a correctly typed `keys_start` might
// be different and outside the bounds of the allocated header!
// So we do an alignment check and a size check first, that will be evaluated
// at compile-time, and only do any run-time check in the rare case that
// the compile-time checks signal danger.
if (mem::align_of::<NodeHeader<K, V, K>>() > mem::align_of::<NodeHeader<K, V>>()
|| mem::size_of::<NodeHeader<K, V, K>>() != mem::size_of::<NodeHeader<K, V>>())
&& self.is_shared_root()
{
&[]
} else {
// If we are a `LeafNode<K, V>`, we can always transmute to
// `NodeHeader<K, V, K>` and `keys_start` always has the same offset
// as the actual `keys`.
// Thanks to the checks above, we know that we can transmute to
// `NodeHeader<K, V, K>` and that `keys_start` will be
// in-bounds of some allocation even if this is the shared root!
// (We might be one-past-the-end, but that is allowed by LLVM.)
// Thus we can use `NodeHeader<K, V, K>`
// to compute the pointer where the keys start.
// This entire hack will become unnecessary once
// <https://github.com/rust-lang/rfcs/pull/2582> lands, then we can just take a raw
// pointer to the `keys` field of `*const InternalNode<K, V>`.
let header = self.as_header() as *const _ as *const NodeHeader<K, V, K>;
let keys = unsafe { &(*header).keys_start as *const _ as *const K };
unsafe { slice::from_raw_parts(keys, self.len()) }
}
/// The caller must ensure that the node is not the shared root.
unsafe fn into_key_slice(self) -> &'a [K] {
debug_assert!(!self.is_shared_root());
// We cannot be the shared root, so `as_leaf` is okay.
slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().keys), self.len())
}

/// The caller must ensure that the node is not the shared root.
Expand All @@ -578,9 +534,10 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
unsafe { slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().vals), self.len()) }
}

/// The caller must ensure that the node is not the shared root.
fn into_slices(self) -> (&'a [K], &'a [V]) {
let k = unsafe { ptr::read(&self) };
(k.into_key_slice(), self.into_val_slice())
(unsafe { k.into_key_slice() }, self.into_val_slice())
}
}

Expand Down
18 changes: 10 additions & 8 deletions src/liballoc/collections/btree/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,18 @@ where
{
// This function is defined over all borrow types (immutable, mutable, owned),
// and may be called on the shared root in each case.
// Crucially, we use `keys()` here, i.e., we work with immutable data.
// `keys_mut()` does not support the shared root, so we cannot use it.
// Using `keys()` is fine here even if BorrowType is mutable, as all we return
// is an index -- not a reference.
for (i, k) in node.keys().iter().enumerate() {
match key.cmp(k.borrow()) {
Ordering::Greater => {}
Ordering::Equal => return (i, true),
Ordering::Less => return (i, false),
let len = node.len();
if len > 0 {
let keys = unsafe { node.keys() }; // safe because a non-empty node cannot be the shared root
for (i, k) in keys.iter().enumerate() {
match key.cmp(k.borrow()) {
Ordering::Greater => {}
Ordering::Equal => return (i, true),
Ordering::Less => return (i, false),
}
}
}
(node.keys().len(), false)
(len, false)
}
9 changes: 6 additions & 3 deletions src/librustc/traits/auto_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,10 @@ impl AutoTraitFinder<'tcx> {
&Err(SelectionError::Unimplemented) => {
if self.is_param_no_infer(pred.skip_binder().trait_ref.substs) {
already_visited.remove(&pred);
self.add_user_pred(&mut user_computed_preds, ty::Predicate::Trait(pred));
self.add_user_pred(
&mut user_computed_preds,
ty::Predicate::Trait(pred, ast::Constness::NotConst),
);
predicates.push_back(pred);
} else {
debug!(
Expand Down Expand Up @@ -405,7 +408,7 @@ impl AutoTraitFinder<'tcx> {
let mut should_add_new = true;
user_computed_preds.retain(|&old_pred| {
match (&new_pred, old_pred) {
(&ty::Predicate::Trait(new_trait), ty::Predicate::Trait(old_trait)) => {
(&ty::Predicate::Trait(new_trait, _), ty::Predicate::Trait(old_trait, _)) => {
if new_trait.def_id() == old_trait.def_id() {
let new_substs = new_trait.skip_binder().trait_ref.substs;
let old_substs = old_trait.skip_binder().trait_ref.substs;
Expand Down Expand Up @@ -627,7 +630,7 @@ impl AutoTraitFinder<'tcx> {
// We check this by calling is_of_param on the relevant types
// from the various possible predicates
match &predicate {
&ty::Predicate::Trait(p) => {
&ty::Predicate::Trait(p, _) => {
if self.is_param_no_infer(p.skip_binder().trait_ref.substs)
&& !only_projections
&& is_new_pred
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/traits/engine.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::infer::InferCtxt;
use crate::traits::Obligation;
use crate::ty::{self, ToPredicate, Ty, TyCtxt};
use crate::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
use rustc_hir::def_id::DefId;

use super::{ChalkFulfillmentContext, FulfillmentContext, FulfillmentError};
Expand Down Expand Up @@ -33,7 +33,7 @@ pub trait TraitEngine<'tcx>: 'tcx {
cause,
recursion_depth: 0,
param_env,
predicate: trait_ref.to_predicate(),
predicate: trait_ref.without_const().to_predicate(),
},
);
}
Expand Down
28 changes: 18 additions & 10 deletions src/librustc/traits/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ use crate::ty::error::ExpectedFound;
use crate::ty::fast_reject;
use crate::ty::fold::TypeFolder;
use crate::ty::SubtypePredicate;
use crate::ty::{self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
use crate::ty::{
self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
};

use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
Expand Down Expand Up @@ -128,15 +130,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}

let (cond, error) = match (cond, error) {
(&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error)) => (cond, error),
(&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error, _)) => (cond, error),
_ => {
// FIXME: make this work in other cases too.
return false;
}
};

for implication in super::elaborate_predicates(self.tcx, vec![cond.clone()]) {
if let ty::Predicate::Trait(implication) = implication {
if let ty::Predicate::Trait(implication, _) = implication {
let error = error.to_poly_trait_ref();
let implication = implication.to_poly_trait_ref();
// FIXME: I'm just not taking associated types at all here.
Expand Down Expand Up @@ -528,7 +530,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
return;
}
match obligation.predicate {
ty::Predicate::Trait(ref trait_predicate) => {
ty::Predicate::Trait(ref trait_predicate, _) => {
let trait_predicate = self.resolve_vars_if_possible(trait_predicate);

if self.tcx.sess.has_errors() && trait_predicate.references_error() {
Expand Down Expand Up @@ -581,7 +583,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"{}",
message.unwrap_or_else(|| format!(
"the trait bound `{}` is not satisfied{}",
trait_ref.to_predicate(),
trait_ref.without_const().to_predicate(),
post_message,
))
);
Expand Down Expand Up @@ -693,7 +695,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
trait_pred
});
let unit_obligation = Obligation {
predicate: ty::Predicate::Trait(predicate),
predicate: ty::Predicate::Trait(
predicate,
ast::Constness::NotConst,
),
..obligation.clone()
};
if self.predicate_may_hold(&unit_obligation) {
Expand Down Expand Up @@ -986,7 +991,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
) -> PredicateObligation<'tcx> {
let new_trait_ref =
ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
Obligation::new(cause, param_env, new_trait_ref.to_predicate())
Obligation::new(cause, param_env, new_trait_ref.without_const().to_predicate())
}
}

Expand Down Expand Up @@ -1074,7 +1079,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}

let mut err = match predicate {
ty::Predicate::Trait(ref data) => {
ty::Predicate::Trait(ref data, _) => {
let trait_ref = data.to_poly_trait_ref();
let self_ty = trait_ref.self_ty();
debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind, trait_ref);
Expand Down Expand Up @@ -1267,8 +1272,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
)
.value;

let obligation =
Obligation::new(ObligationCause::dummy(), param_env, cleaned_pred.to_predicate());
let obligation = Obligation::new(
ObligationCause::dummy(),
param_env,
cleaned_pred.without_const().to_predicate(),
);

self.predicate_may_hold(&obligation)
})
Expand Down
17 changes: 10 additions & 7 deletions src/librustc/traits/error_reporting/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use super::{
use crate::infer::InferCtxt;
use crate::traits::object_safety::object_safety_violations;
use crate::ty::TypeckTables;
use crate::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable};
use crate::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};

use rustc_errors::{
error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style,
Expand Down Expand Up @@ -48,7 +48,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
} else {
" where"
},
trait_ref.to_predicate(),
trait_ref.without_const().to_predicate(),
),
Applicability::MachineApplicable,
);
Expand Down Expand Up @@ -338,8 +338,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let new_self_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, self_ty);
let substs = self.tcx.mk_substs_trait(new_self_ty, &[]);
let new_trait_ref = ty::TraitRef::new(obligation.parent_trait_ref.def_id(), substs);
let new_obligation =
Obligation::new(ObligationCause::dummy(), param_env, new_trait_ref.to_predicate());
let new_obligation = Obligation::new(
ObligationCause::dummy(),
param_env,
new_trait_ref.without_const().to_predicate(),
);
if self.predicate_must_hold_modulo_regions(&new_obligation) {
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
// We have a very specific type of error, where just borrowing this argument
Expand Down Expand Up @@ -1120,7 +1123,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// the type. The last generator has information about where the bound was introduced. At
// least one generator should be present for this diagnostic to be modified.
let (mut trait_ref, mut target_ty) = match obligation.predicate {
ty::Predicate::Trait(p) => {
ty::Predicate::Trait(p, _) => {
(Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty()))
}
_ => (None, None),
Expand Down Expand Up @@ -1543,7 +1546,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
err.note(&format!("required because it appears within the type `{}`", ty));
obligated_types.push(ty);

let parent_predicate = parent_trait_ref.to_predicate();
let parent_predicate = parent_trait_ref.without_const().to_predicate();
if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
self.note_obligation_cause_code(
err,
Expand All @@ -1560,7 +1563,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
parent_trait_ref.print_only_trait_path(),
parent_trait_ref.skip_binder().self_ty()
));
let parent_predicate = parent_trait_ref.to_predicate();
let parent_predicate = parent_trait_ref.without_const().to_predicate();
self.note_obligation_cause_code(
err,
&parent_predicate,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
}

match obligation.predicate {
ty::Predicate::Trait(ref data) => {
ty::Predicate::Trait(ref data, _) => {
let trait_obligation = obligation.with(data.clone());

if data.is_global() {
Expand Down
Loading

0 comments on commit 5e8897b

Please sign in to comment.