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

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

Closed
wants to merge 6 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
36 changes: 19 additions & 17 deletions src/librustc/infer/canonical/canonicalizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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")
Expand Down Expand Up @@ -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);
Expand All @@ -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)
}
}

Expand Down Expand Up @@ -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)
}
}
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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()))
Expand Down
89 changes: 41 additions & 48 deletions src/librustc/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand All @@ -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 {
Expand All @@ -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);
Expand All @@ -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 {
Expand Down
20 changes: 11 additions & 9 deletions src/librustc/infer/freshen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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
Expand All @@ -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(
Expand Down Expand Up @@ -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