Skip to content

Commit

Permalink
assert previously implicit invariants in stable_cmp
Browse files Browse the repository at this point in the history
  • Loading branch information
lcnr committed Sep 18, 2020
1 parent 7d12e5f commit 9818bda
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 11 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2420,7 +2420,7 @@ impl<'tcx> TyCtxt<'tcx> {
) -> &'tcx List<ExistentialPredicate<'tcx>> {
assert!(!eps.is_empty());
// Do not allow duplicate existential predicates.
assert!(eps.windows(2).all(|w| w[0].stable_cmp(self, &w[1]) == Ordering::Less));
assert!(eps.windows(2).all(|w| w[0].stable_cmp(self, w[1]) == Ordering::Less));
self._intern_existential_predicates(eps)
}

Expand Down
29 changes: 21 additions & 8 deletions compiler/rustc_middle/src/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use rustc_hir::def_id::DefId;
use rustc_index::vec::Idx;
use rustc_macros::HashStable;
use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::DUMMY_SP;
use rustc_target::abi::VariantIdx;
use rustc_target::spec::abi;
use std::borrow::Cow;
Expand Down Expand Up @@ -672,22 +673,34 @@ pub enum ExistentialPredicate<'tcx> {
impl<'tcx> ExistentialPredicate<'tcx> {
/// Compares via an ordering that will not change if modules are reordered or other changes are
/// made to the tree. In particular, this ordering is preserved across incremental compilations.
pub fn stable_cmp(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Ordering {
pub fn stable_cmp(self, tcx: TyCtxt<'tcx>, other: Self) -> Ordering {
use self::ExistentialPredicate::*;
// Note that we only call this method after checking that the
// given predicates represent a valid trait object.
//
// This means that we have at most one `ExistentialPredicate::Trait`
// and at most one `ExistentialPredicate::Projection` for each associated item.
// We therefore do not have to worry about the ordering for cases which
// are not well formed.
match (*self, *other) {
(Trait(_), Trait(_)) => Ordering::Equal,
(Projection(ref a), Projection(ref b)) => {
match (self, other) {
(Trait(a), Trait(b)) => {
if a != b {
tcx.sess.delay_span_bug(
DUMMY_SP,
&format!("unexpected existential predicates: {:?}, {:?}", a, b),
);
}
Ordering::Equal
}
(Projection(a), Projection(b)) => {
if a.item_def_id == b.item_def_id && a != b {
tcx.sess.delay_span_bug(
DUMMY_SP,
&format!("unexpected existential predicates: {:?}, {:?}", a, b),
);
}
tcx.def_path_hash(a.item_def_id).cmp(&tcx.def_path_hash(b.item_def_id))
}
(AutoTrait(ref a), AutoTrait(ref b)) => {
tcx.trait_def(*a).def_path_hash.cmp(&tcx.trait_def(*b).def_path_hash)
(AutoTrait(a), AutoTrait(b)) => {
tcx.trait_def(a).def_path_hash.cmp(&tcx.trait_def(b).def_path_hash)
}
(Trait(_), _) => Ordering::Less,
(Projection(_), Trait(_)) => Ordering::Greater,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_typeck/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1192,8 +1192,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.map(|x| ty::ExistentialPredicate::Projection(x.skip_binder())),
)
.collect::<SmallVec<[_; 8]>>();
v.sort_by(|a, b| a.stable_cmp(tcx, b));
v.dedup_by(|a, b| a.stable_cmp(tcx, b) == Ordering::Equal);
v.sort_by(|&a, &b| a.stable_cmp(tcx, b));
v.dedup_by(|&mut a, &mut b| a.stable_cmp(tcx, b) == Ordering::Equal);
let existential_predicates = ty::Binder::bind(tcx.mk_existential_predicates(v.into_iter()));

// Use explicitly-specified region bound.
Expand Down

0 comments on commit 9818bda

Please sign in to comment.