Skip to content

Lift TypeFoldable over Result and remove the Relate hack in combine/nll #58333

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 6 commits into from
Closed
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
36 changes: 19 additions & 17 deletions src/librustc/infer/canonical/canonicalizer.rs
Original file line number Diff line number Diff line change
@@ -284,11 +284,13 @@ struct Canonicalizer<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
}

impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> {
type Error = !;

fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
self.tcx
}

fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> Result<ty::Binder<T>, !>
where T: TypeFoldable<'tcx>
{
self.binder_index.shift_in(1);
@@ -297,8 +299,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
t
}

fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match *r {
fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, !> {
Ok(match *r {
ty::ReLateBound(index, ..) => {
if index >= self.binder_index {
bug!("escaping late bound region during canonicalization")
@@ -333,10 +335,10 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
ty::ReClosureBound(..) => {
bug!("closure bound region encountered during canonicalization")
}
}
})
}

fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, !> {
match t.sty {
ty::Infer(ty::TyVar(vid)) => {
debug!("canonical: type var found with vid {:?}", vid);
@@ -354,48 +356,48 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
// FIXME: perf problem described in #55921.
ui = ty::UniverseIndex::ROOT;
}
self.canonicalize_ty_var(
Ok(self.canonicalize_ty_var(
CanonicalVarInfo {
kind: CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
},
t
)
))
}
}
}

ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var(
ty::Infer(ty::IntVar(_)) => Ok(self.canonicalize_ty_var(
CanonicalVarInfo {
kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
},
t
),
)),

ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var(
ty::Infer(ty::FloatVar(_)) => Ok(self.canonicalize_ty_var(
CanonicalVarInfo {
kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float)
},
t
),
)),

ty::Infer(ty::FreshTy(_))
| ty::Infer(ty::FreshIntTy(_))
| ty::Infer(ty::FreshFloatTy(_)) => {
bug!("encountered a fresh type during canonicalization")
}

ty::Placeholder(placeholder) => self.canonicalize_ty_var(
ty::Placeholder(placeholder) => Ok(self.canonicalize_ty_var(
CanonicalVarInfo {
kind: CanonicalVarKind::PlaceholderTy(placeholder)
},
t
),
)),

ty::Bound(debruijn, _) => {
if debruijn >= self.binder_index {
bug!("escaping bound type during canonicalization")
} else {
t
Ok(t)
}
}

@@ -427,7 +429,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
if t.flags.intersects(self.needs_canonical_flags) {
t.super_fold_with(self)
} else {
t
Ok(t)
}
}
}
@@ -485,7 +487,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
indices: FxHashMap::default(),
binder_index: ty::INNERMOST,
};
let out_value = value.fold_with(&mut canonicalizer);
let Ok(out_value) = value.fold_with(&mut canonicalizer);

// Once we have canonicalized `out_value`, it should not
// contain anything that ties it to this inference context
@@ -627,7 +629,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
let infcx = self.infcx.expect("encountered ty-var without infcx");
let bound_to = infcx.shallow_resolve(ty_var);
if bound_to != ty_var {
self.fold_ty(bound_to)
self.fold_ty(bound_to).unwrap_or_else(|e: !| e)
} else {
let var = self.canonical_var(info, ty_var.into());
self.tcx().mk_ty(ty::Bound(self.binder_index, var.into()))
89 changes: 41 additions & 48 deletions src/librustc/infer/combine.rs
Original file line number Diff line number Diff line change
@@ -29,13 +29,13 @@ use super::lub::Lub;
use super::sub::Sub;
use super::type_variable::TypeVariableValue;

use crate::hir::def_id::DefId;
use crate::ty::{IntType, UintType};
use crate::ty::{self, Ty, TyCtxt};
use crate::ty::fold::{TypeFoldable, TypeFolder};
use crate::ty::error::TypeError;
use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
use crate::ty::subst::SubstsRef;
use crate::ty::relate::{RelateResult, TypeRelation};
use crate::traits::{Obligation, PredicateObligations};
use crate::util::common::ErrorReported;

use syntax::ast;
use syntax_pos::Span;
@@ -278,7 +278,7 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> {
root_ty: ty,
};

let ty = match generalize.relate(&ty, &ty) {
let ty = match ty.fold_with(&mut generalize) {
Ok(ty) => ty,
Err(e) => {
debug!("generalize: failure {:?}", e);
@@ -351,60 +351,41 @@ struct Generalization<'tcx> {
needs_wf: bool,
}

impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, 'tcx> {
fn tcx(&self) -> TyCtxt<'cx, 'gcx, 'tcx> {
self.infcx.tcx
}

fn tag(&self) -> &'static str {
"Generalizer"
}
impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Generalizer<'cx, 'gcx, 'tcx> {
type Error = TypeError<'tcx>;

fn a_is_expected(&self) -> bool {
true
}

fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
-> RelateResult<'tcx, ty::Binder<T>>
where T: Relate<'tcx>
{
Ok(ty::Binder::bind(self.relate(a.skip_binder(), b.skip_binder())?))
fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> {
self.infcx.tcx
}

fn relate_item_substs(&mut self,
item_def_id: DefId,
a_subst: SubstsRef<'tcx>,
b_subst: SubstsRef<'tcx>)
-> RelateResult<'tcx, SubstsRef<'tcx>>
{
fn use_variances(&self) -> bool {
if self.ambient_variance == ty::Variance::Invariant {
// Avoid fetching the variance if we are in an invariant
// context; no need, and it can induce dependency cycles
// (e.g., #41849).
relate::relate_substs(self, None, a_subst, b_subst)
false
} else {
let opt_variances = self.tcx().variances_of(item_def_id);
relate::relate_substs(self, Some(&opt_variances), a_subst, b_subst)
true
}
}

fn relate_with_variance<T: Relate<'tcx>>(&mut self,
variance: ty::Variance,
a: &T,
b: &T)
-> RelateResult<'tcx, T>
fn fold_with_variance<T: TypeFoldable<'tcx>>(&mut self,
variance: ty::Variance,
a: &T)
-> RelateResult<'tcx, T>
{
let old_ambient_variance = self.ambient_variance;
debug!("Generalize: fold_with_variance({:?}, {:?}, old_variance={:?})",
variance, a, old_ambient_variance);
self.ambient_variance = self.ambient_variance.xform(variance);

let result = self.relate(a, b);
let result = a.fold_with(self);
self.ambient_variance = old_ambient_variance;
result
}

fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
assert_eq!(t, t2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==

fn fold_ty(&mut self, t: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
debug!("Generalize: fold_ty({:?}, variance={:?})", t, self.ambient_variance);
debug!("generalize: t={:?}", t);

// Check to see whether the type we are genealizing references
@@ -425,7 +406,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
TypeVariableValue::Known { value: u } => {
drop(variables);
debug!("generalize: known value {:?}", u);
self.relate(&u, &u)
u.fold_with(self)
}
TypeVariableValue::Unknown { universe } => {
match self.ambient_variance {
@@ -449,7 +430,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '

let origin = *variables.var_origin(vid);
let new_var_id = variables.new_var(self.for_universe, false, origin);
let u = self.tcx().mk_var(new_var_id);
let u = self.infcx.tcx.mk_var(new_var_id);
debug!("generalize: replacing original vid={:?} with new={:?}",
vid, u);
return Ok(u);
@@ -459,21 +440,33 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
}
ty::Infer(ty::IntVar(_)) |
ty::Infer(ty::FloatVar(_)) => {
// No matter what mode we are in,
// integer/floating-point types must be equal to be
// relatable.
Ok(t)
}
ty::Array(_, sz) => {
// HACK, not sure how desirable this is: propagate errors from
// array lengths to the array type itself. This makes error
// messages a bit nicer, and used to be the case before because
// we used `ty::relate` instead of `TypeFoldable`, so I'll keep
// it here.
//
// This does not serve any functional purpose, but it does
// avoid some "duplicate" errors.
match self.infcx.tcx.force_eval_array_length(*sz) {
Ok(_) => t.super_fold_with(self),
Err(ErrorReported) => {
Ok(self.infcx.tcx.types.err)
}
}
}
_ => {
relate::super_relate_tys(self, t, t)
t.super_fold_with(self)
}
}
}

fn regions(&mut self, r: ty::Region<'tcx>, r2: ty::Region<'tcx>)
fn fold_region(&mut self, r: ty::Region<'tcx>)
-> RelateResult<'tcx, ty::Region<'tcx>> {
assert_eq!(r, r2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==

debug!("Generalize: fold_region({:?}, variance={:?})", r, self.ambient_variance);
debug!("generalize: regions r={:?}", r);

match *r {
20 changes: 11 additions & 9 deletions src/librustc/infer/freshen.rs
Original file line number Diff line number Diff line change
@@ -64,7 +64,7 @@ impl<'a, 'gcx, 'tcx> TypeFreshener<'a, 'gcx, 'tcx> {
F: FnOnce(u32) -> ty::InferTy,
{
if let Some(ty) = opt_ty {
return ty.fold_with(self);
return ty.fold_with(self).unwrap_or_else(|e: !| e);
}

match self.freshen_map.entry(key) {
@@ -81,12 +81,14 @@ impl<'a, 'gcx, 'tcx> TypeFreshener<'a, 'gcx, 'tcx> {
}

impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
type Error = !;

fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
self.infcx.tcx
}

fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match *r {
fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, !> {
Ok(match *r {
ty::ReLateBound(..) => {
// leave bound regions alone
r
@@ -110,18 +112,18 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
r,
);
}
}
})
}

fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, !> {
if !t.needs_infer() && !t.has_erasable_regions() &&
!(t.has_closure_types() && self.infcx.in_progress_tables.is_some()) {
return t;
return Ok(t);
}

let tcx = self.infcx.tcx;

match t.sty {
Ok(match t.sty {
ty::Infer(ty::TyVar(v)) => {
let opt_ty = self.infcx.type_variables.borrow_mut().probe(v).known();
self.freshen(
@@ -185,11 +187,11 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
ty::Closure(..) |
ty::GeneratorWitness(..) |
ty::Opaque(..) => {
t.super_fold_with(self)
t.super_fold_with(self)?
}

ty::Placeholder(..) |
ty::Bound(..) => bug!("unexpected type {:?}", t),
}
})
}
}
Loading