Skip to content

[WIP] improve canonicalization by using a hashing scheme #51837

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

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
91 changes: 91 additions & 0 deletions src/librustc/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,14 @@ macro_rules! CloneTypeFoldableImpls {
{
false
}

fn super_hash_with<F: $crate::ty::fold::TypeHasher<$tcx>>(
&self,
_: &mut F)
-> u64
{
unimplemented!()
}
}
)+
};
Expand Down Expand Up @@ -320,6 +328,16 @@ macro_rules! BraceStructTypeFoldableImpl {
let $s { $($field,)* } = self;
false $(|| $crate::ty::fold::TypeFoldable::visit_with($field, visitor))*
}

fn super_hash_with<H: $crate::ty::fold::TypeHasher<$tcx>>(
&self,
hasher: &mut H)
-> u64
{
let $s { $($field,)* } = self;
$($crate::ty::fold::TypeFoldable::hash_with($field, hasher);)*
hasher.get_hash()
}
}
};
}
Expand Down Expand Up @@ -347,6 +365,16 @@ macro_rules! TupleStructTypeFoldableImpl {
let $s($($field,)*) = self;
false $(|| $crate::ty::fold::TypeFoldable::visit_with($field, visitor))*
}

fn super_hash_with<H: $crate::ty::fold::TypeHasher<$tcx>>(
&self,
hasher: &mut H)
-> u64
{
let $s($($field,)*) = self;
$($crate::ty::fold::TypeFoldable::hash_with($field, hasher);)*
hasher.get_hash()
}
}
};
}
Expand All @@ -372,6 +400,15 @@ macro_rules! EnumTypeFoldableImpl {
) -> bool {
EnumTypeFoldableImpl!(@VisitVariants(self, visitor) input($($variants)*) output())
}

fn super_hash_with<H: $crate::ty::fold::TypeHasher<$tcx>>(
&self,
hasher: &mut H)
-> u64
{
EnumTypeFoldableImpl!(@HashVariants(self, hasher) input($($variants)*) output());
hasher.get_hash()
}
}
};

Expand Down Expand Up @@ -481,5 +518,59 @@ macro_rules! EnumTypeFoldableImpl {
)
)
};

(@HashVariants($this:expr, $hasher:expr) input() output($($output:tt)*)) => {
::std::mem::discriminant($this).hash($hasher);
match $this {
$($output)*
}
};

(@HashVariants($this:expr, $hasher:expr)
input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
output( $($output:tt)*) ) => {
EnumTypeFoldableImpl!(
@HashVariants($this, $hasher)
input($($input)*)
output(
$variant ( $($variant_arg),* ) => {
$($crate::ty::fold::TypeFoldable::hash_with(
$variant_arg, $hasher
);)*
}
$($output)*
)
)
};

(@HashVariants($this:expr, $hasher:expr)
input( ($variant:path) { $($variant_arg:ident),* $(,)* } , $($input:tt)*)
output( $($output:tt)*) ) => {
EnumTypeFoldableImpl!(
@HashVariants($this, $hasher)
input($($input)*)
output(
$variant { $($variant_arg),* } => {
$($crate::ty::fold::TypeFoldable::hash_with(
$variant_arg, $hasher
);)*
}
$($output)*
)
)
};

(@HashVariants($this:expr, $hasher:expr)
input( ($variant:path), $($input:tt)*)
output( $($output:tt)*) ) => {
EnumTypeFoldableImpl!(
@HashVariants($this, $hasher)
input($($input)*)
output(
$variant => { }
$($output)*
)
)
};
}

4 changes: 4 additions & 0 deletions src/librustc/mir/interpret/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ impl<'tcx> ty::TypeFoldable<'tcx> for Value {
fn super_visit_with<V: ty::fold::TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
false
}

fn super_hash_with<H: ty::fold::TypeHasher<'tcx>>(&self, _hasher: &mut H) -> u64 {
unimplemented!()
}
}

impl<'tcx> Scalar {
Expand Down
52 changes: 31 additions & 21 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use std::{iter, mem, option, u32};
use syntax::ast::{self, Name};
use syntax::symbol::InternedString;
use syntax_pos::{Span, DUMMY_SP};
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use ty::fold::{TypeFoldable, TypeFolder, TypeHasher, TypeVisitor};
use ty::subst::{Subst, Substs};
use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt};
use util::ppaux;
Expand Down Expand Up @@ -2681,6 +2681,10 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
| FalseUnwind { .. } => false,
}
}

fn super_hash_with<H: TypeHasher<'tcx>>(&self, _hasher: &mut H) -> u64 {
unimplemented!()
}
}

impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
Expand All @@ -2698,6 +2702,10 @@ impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
false
}
}

fn super_hash_with<H: TypeHasher<'tcx>>(&self, _hasher: &mut H) -> u64 {
unimplemented!()
}
}

impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
Expand Down Expand Up @@ -2764,22 +2772,17 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
}
}
}
}

impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
match *self {
Operand::Copy(ref place) => Operand::Copy(place.fold_with(folder)),
Operand::Move(ref place) => Operand::Move(place.fold_with(folder)),
Operand::Constant(ref c) => Operand::Constant(c.fold_with(folder)),
}
fn super_hash_with<H: TypeHasher<'tcx>>(&self, _hasher: &mut H) -> u64 {
unimplemented!()
}
}

fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
match *self {
Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor),
Operand::Constant(ref c) => c.visit_with(visitor),
}
EnumTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
(Operand::Copy)(place),
(Operand::Move)(place),
(Operand::Constant)(c),
}
}

Expand Down Expand Up @@ -2812,17 +2815,16 @@ where
_ => false,
}
}
}

impl<'tcx> TypeFoldable<'tcx> for Field {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _: &mut F) -> Self {
*self
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
false
fn super_hash_with<H: TypeHasher<'tcx>>(&self, _hasher: &mut H) -> u64 {
unimplemented!()
}
}

TupleStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for Field {}
}

impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
Constant {
Expand All @@ -2834,6 +2836,10 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.ty.visit_with(visitor) || self.literal.visit_with(visitor)
}

fn super_hash_with<H: TypeHasher<'tcx>>(&self, _hasher: &mut H) -> u64 {
unimplemented!()
}
}

impl<'tcx> TypeFoldable<'tcx> for Literal<'tcx> {
Expand All @@ -2851,4 +2857,8 @@ impl<'tcx> TypeFoldable<'tcx> for Literal<'tcx> {
Literal::Promoted { .. } => false,
}
}

fn super_hash_with<H: TypeHasher<'tcx>>(&self, _hasher: &mut H) -> u64 {
unimplemented!()
}
}
7 changes: 6 additions & 1 deletion src/librustc/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use mir::interpret::ConstEvalErr;
use ty::subst::Substs;
use ty::{self, AdtKind, Slice, Ty, TyCtxt, GenericParamDefKind, ToPredicate};
use ty::error::{ExpectedFound, TypeError};
use ty::fold::{TypeFolder, TypeFoldable, TypeVisitor};
use ty::fold::{TypeFolder, TypeFoldable, TypeHasher, TypeVisitor};
use infer::{InferCtxt};

use rustc_data_structures::sync::Lrc;
Expand Down Expand Up @@ -1027,6 +1027,11 @@ where
ex_clause: &chalk_engine::ExClause<Self>,
visitor: &mut V,
) -> bool;

fn hash_ex_clause_with<'gcx: 'tcx, H: TypeHasher<'tcx>>(
ex_clause: &chalk_engine::ExClause<Self>,
hasher: &mut H,
) -> u64;
}

pub trait ExClauseLift<'tcx>
Expand Down
25 changes: 24 additions & 1 deletion src/librustc/traits/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use chalk_engine;
use rustc_data_structures::accumulate_vec::AccumulateVec;
use traits;
use traits::project::Normalized;
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use ty::fold::{TypeFoldable, TypeFolder, TypeHasher, TypeVisitor};
use ty::{self, Lift, TyCtxt};

use std::fmt;
Expand Down Expand Up @@ -342,6 +342,10 @@ impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.predicate.visit_with(visitor)
}

fn super_hash_with<H: TypeHasher<'tcx>>(&self, hasher: &mut H) -> u64 {
self.predicate.hash_with(hasher)
}
}

BraceStructTypeFoldableImpl! {
Expand Down Expand Up @@ -630,6 +634,10 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice<traits::Goal<'tcx>> {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.iter().any(|t| t.visit_with(visitor))
}

fn super_hash_with<H: TypeHasher<'tcx>>(&self, _hasher: &mut H) -> u64 {
unimplemented!()
}
}

impl<'tcx> TypeFoldable<'tcx> for &'tcx traits::Goal<'tcx> {
Expand All @@ -641,6 +649,10 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx traits::Goal<'tcx> {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
(**self).visit_with(visitor)
}

fn super_hash_with<H: TypeHasher<'tcx>>(&self, _hasher: &mut H) -> u64 {
unimplemented!()
}
}

BraceStructTypeFoldableImpl! {
Expand Down Expand Up @@ -668,6 +680,10 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice<traits::Clause<'tcx>> {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.iter().any(|t| t.visit_with(visitor))
}

fn super_hash_with<H: TypeHasher<'tcx>>(&self, _hasher: &mut H) -> u64 {
unimplemented!()
}
}

impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::ExClause<C>
Expand All @@ -689,6 +705,13 @@ where
visitor,
)
}

fn super_hash_with<H: TypeHasher<'tcx>>(&self, hasher: &mut H) -> u64 {
<C as traits::ExClauseFold>::hash_ex_clause_with(
self,
hasher,
)
}
}

impl<'tcx, C> Lift<'tcx> for chalk_engine::ExClause<C>
Expand Down
34 changes: 28 additions & 6 deletions src/librustc/ty/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,9 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
self.super_visit_with(visitor)
}

/// True if `self` has any late-bound regions that are either
/// bound by `binder` or bound by some binder outside of `binder`.
/// If `binder` is `ty::INNERMOST`, this indicates whether
/// there are any late-bound regions that appear free.
fn has_regions_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool {
self.visit_with(&mut HasEscapingRegionsVisitor { outer_index: binder })
fn super_hash_with<H: TypeHasher<'tcx>>(&self, hasher: &mut H) -> u64;
fn hash_with<H: TypeHasher<'tcx>>(&self, hasher: &mut H) -> u64 {
self.super_hash_with(hasher)
}

/// True if this `self` has any regions that escape `binder` (and
Expand Down Expand Up @@ -197,6 +194,31 @@ pub trait TypeVisitor<'tcx> : Sized {
}
}

pub trait TypeHasher<'tcx> : Sized + ::std::hash::Hasher {
fn hash_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> u64 {
t.super_hash_with(self)
}

fn hash_ty(&mut self, t: Ty<'tcx>) -> u64 {
t.super_hash_with(self)
}

fn hash_region(&mut self, r: ty::Region<'tcx>) -> u64 {
r.super_hash_with(self)
}

fn hash_const(&mut self, c: &'tcx ty::Const<'tcx>) -> u64 {
c.super_hash_with(self)
}

fn hash_hashable<H: ::std::hash::Hash>(&mut self, h: H) -> u64 {
h.hash(self);
self.get_hash()
}

fn get_hash(&self) -> u64;
}

///////////////////////////////////////////////////////////////////////////
// Some sample folders

Expand Down
Loading