Skip to content

Commit

Permalink
Auto merge of #58333 - arielb1:fold-result, r=<try>
Browse files Browse the repository at this point in the history
Lift TypeFoldable over Result and remove the Relate hack in combine/nll

No functional changes intended - just a cleanup.

r? @nikomatsakis
  • Loading branch information
bors committed Feb 16, 2019
2 parents eac0908 + 090f21e commit c5e0b61
Show file tree
Hide file tree
Showing 33 changed files with 1,021 additions and 693 deletions.
36 changes: 19 additions & 17 deletions src/librustc/infer/canonical/canonicalizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,11 +275,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 @@ -288,8 +290,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 @@ -324,10 +326,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 @@ -345,48 +347,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 @@ -418,7 +420,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 @@ -476,7 +478,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 @@ -618,7 +620,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::Substs;
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 @@ -264,7 +264,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 @@ -332,60 +332,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: &'tcx Substs<'tcx>,
b_subst: &'tcx Substs<'tcx>)
-> RelateResult<'tcx, &'tcx Substs<'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);
// Check to see whether the type we are genealizing references
// any other type variable related to `vid` via
// subtyping. This is basically our "occurs check", preventing
Expand All @@ -403,7 +384,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
match variables.probe(vid) {
TypeVariableValue::Known { value: u } => {
drop(variables);
self.relate(&u, &u)
u.fold_with(self)
}
TypeVariableValue::Unknown { universe } => {
match self.ambient_variance {
Expand All @@ -423,7 +404,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(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 @@ -433,21 +414,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);
match *r {
// Never make variables for regions bound within the type itself,
// nor for erased regions.
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

0 comments on commit c5e0b61

Please sign in to comment.