Skip to content

Commit fb295a6

Browse files
committed
Remove NormalizingClosureTyper
1 parent 0f13a3f commit fb295a6

File tree

9 files changed

+204
-94
lines changed

9 files changed

+204
-94
lines changed

src/librustc/middle/infer/mod.rs

Lines changed: 160 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub use self::TypeOrigin::*;
1919
pub use self::ValuePairs::*;
2020
pub use self::fixup_err::*;
2121
pub use middle::ty::IntVarValue;
22+
use middle::ty::ClosureTyper;
2223
pub use self::freshen::TypeFreshener;
2324
pub use self::region_inference::GenericKind;
2425

@@ -29,7 +30,8 @@ use middle::region::CodeExtent;
2930
use middle::subst;
3031
use middle::subst::Substs;
3132
use middle::subst::Subst;
32-
use middle::traits;
33+
use middle::traits::{self, FulfillmentContext, Normalized, MiscObligation,
34+
SelectionContext, ObligationCause};
3335
use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, UnconstrainedNumeric};
3436
use middle::ty::{self, Ty, HasTypeFlags};
3537
use middle::ty_fold::{self, TypeFolder, TypeFoldable};
@@ -39,7 +41,7 @@ use std::cell::{RefCell, Ref};
3941
use std::fmt;
4042
use syntax::ast;
4143
use syntax::codemap;
42-
use syntax::codemap::Span;
44+
use syntax::codemap::{Span, DUMMY_SP};
4345
use util::nodemap::{FnvHashMap, NodeMap};
4446

4547
use self::combine::CombineFields;
@@ -354,6 +356,14 @@ pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>,
354356
}
355357
}
356358

359+
pub fn normalizing_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>,
360+
tables: &'a RefCell<ty::Tables<'tcx>>)
361+
-> InferCtxt<'a, 'tcx> {
362+
let mut infcx = new_infer_ctxt(tcx, tables, None, false);
363+
infcx.normalize = true;
364+
infcx
365+
}
366+
357367
/// Computes the least upper-bound of `a` and `b`. If this is not possible, reports an error and
358368
/// returns ty::err.
359369
pub fn common_supertype<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
@@ -557,7 +567,8 @@ impl<'a, 'tcx> ty::ClosureTyper<'tcx> for InferCtxt<'a, 'tcx> {
557567
// the substitutions in `substs` are already monomorphized,
558568
// but we still must normalize associated types
559569
// normalize_associated_type(self.param_env.tcx, &closure_ty)
560-
panic!("see issue 26597: fufillment context refactor must occur")
570+
normalize_associated_type(&self.tcx, &closure_ty)
571+
// panic!("see issue 26597: fufillment context refactor must occur")
561572
} else {
562573
closure_ty
563574
}
@@ -579,13 +590,158 @@ impl<'a, 'tcx> ty::ClosureTyper<'tcx> for InferCtxt<'a, 'tcx> {
579590
// the substitutions in `substs` are already monomorphized,
580591
// but we still must normalize associated types
581592
// monomorphize::normalize_associated_type(self.param_env.tcx, &result)
582-
panic!("see issue 26597: fufillment context refactor must occur")
593+
// panic!("see issue 26597: fufillment context refactor must occur")
594+
normalize_associated_type(&self.tcx, &result)
583595
} else {
584596
result
585597
}
586598
}
587599
}
588600

601+
pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
602+
where T : TypeFoldable<'tcx> + HasTypeFlags
603+
{
604+
debug!("normalize_associated_type(t={:?})", value);
605+
606+
let value = erase_regions(tcx, value);
607+
608+
if !value.has_projection_types() {
609+
return value;
610+
}
611+
612+
let infcx = new_infer_ctxt(tcx, &tcx.tables, None, true);
613+
let mut selcx = traits::SelectionContext::new(&infcx, &infcx);
614+
let cause = traits::ObligationCause::dummy();
615+
let traits::Normalized { value: result, obligations } =
616+
traits::normalize(&mut selcx, cause, &value);
617+
618+
debug!("normalize_associated_type: result={:?} obligations={:?}",
619+
result,
620+
obligations);
621+
622+
let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
623+
624+
for obligation in obligations {
625+
fulfill_cx.register_predicate_obligation(&infcx, obligation);
626+
}
627+
628+
let result = drain_fulfillment_cx_or_panic(DUMMY_SP, &infcx, &mut fulfill_cx, &result);
629+
630+
result
631+
}
632+
633+
pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span,
634+
infcx: &InferCtxt<'a,'tcx>,
635+
fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
636+
result: &T)
637+
-> T
638+
where T : TypeFoldable<'tcx>
639+
{
640+
match drain_fulfillment_cx(infcx, fulfill_cx, result) {
641+
Ok(v) => v,
642+
Err(errors) => {
643+
infcx.tcx.sess.span_bug(
644+
span,
645+
&format!("Encountered errors `{:?}` fulfilling during trans",
646+
errors));
647+
}
648+
}
649+
}
650+
651+
/// Finishes processes any obligations that remain in the fulfillment
652+
/// context, and then "freshens" and returns `result`. This is
653+
/// primarily used during normalization and other cases where
654+
/// processing the obligations in `fulfill_cx` may cause type
655+
/// inference variables that appear in `result` to be unified, and
656+
/// hence we need to process those obligations to get the complete
657+
/// picture of the type.
658+
pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
659+
fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
660+
result: &T)
661+
-> Result<T,Vec<traits::FulfillmentError<'tcx>>>
662+
where T : TypeFoldable<'tcx>
663+
{
664+
debug!("drain_fulfillment_cx(result={:?})",
665+
result);
666+
// this is stupid but temporary
667+
let typer: &ClosureTyper<'tcx> = infcx;
668+
// In principle, we only need to do this so long as `result`
669+
// contains unbound type parameters. It could be a slight
670+
// optimization to stop iterating early.
671+
match fulfill_cx.select_all_or_error(infcx, typer) {
672+
Ok(()) => { }
673+
Err(errors) => {
674+
return Err(errors);
675+
}
676+
}
677+
678+
// Use freshen to simultaneously replace all type variables with
679+
// their bindings and replace all regions with 'static. This is
680+
// sort of overkill because we do not expect there to be any
681+
// unbound type variables, hence no `TyFresh` types should ever be
682+
// inserted.
683+
Ok(result.fold_with(&mut infcx.freshener()))
684+
}
685+
686+
/// Returns an equivalent value with all free regions removed (note
687+
/// that late-bound regions remain, because they are important for
688+
/// subtyping, but they are anonymized and normalized as well). This
689+
/// is a stronger, caching version of `ty_fold::erase_regions`.
690+
pub fn erase_regions<'tcx,T>(cx: &ty::ctxt<'tcx>, value: &T) -> T
691+
where T : TypeFoldable<'tcx>
692+
{
693+
let value1 = value.fold_with(&mut RegionEraser(cx));
694+
debug!("erase_regions({:?}) = {:?}",
695+
value, value1);
696+
return value1;
697+
698+
struct RegionEraser<'a, 'tcx: 'a>(&'a ty::ctxt<'tcx>);
699+
700+
impl<'a, 'tcx> TypeFolder<'tcx> for RegionEraser<'a, 'tcx> {
701+
fn tcx(&self) -> &ty::ctxt<'tcx> { self.0 }
702+
703+
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
704+
match self.tcx().normalized_cache.borrow().get(&ty).cloned() {
705+
None => {}
706+
Some(u) => return u
707+
}
708+
709+
let t_norm = ty_fold::super_fold_ty(self, ty);
710+
self.tcx().normalized_cache.borrow_mut().insert(ty, t_norm);
711+
return t_norm;
712+
}
713+
714+
fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
715+
where T : TypeFoldable<'tcx>
716+
{
717+
let u = self.tcx().anonymize_late_bound_regions(t);
718+
ty_fold::super_fold_binder(self, &u)
719+
}
720+
721+
fn fold_region(&mut self, r: ty::Region) -> ty::Region {
722+
// because late-bound regions affect subtyping, we can't
723+
// erase the bound/free distinction, but we can replace
724+
// all free regions with 'static.
725+
//
726+
// Note that we *CAN* replace early-bound regions -- the
727+
// type system never "sees" those, they get substituted
728+
// away. In trans, they will always be erased to 'static
729+
// whenever a substitution occurs.
730+
match r {
731+
ty::ReLateBound(..) => r,
732+
_ => ty::ReStatic
733+
}
734+
}
735+
736+
fn fold_substs(&mut self,
737+
substs: &subst::Substs<'tcx>)
738+
-> subst::Substs<'tcx> {
739+
subst::Substs { regions: subst::ErasedRegions,
740+
types: substs.types.fold_with(self) }
741+
}
742+
}
743+
}
744+
589745
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
590746
pub fn freshen<T:TypeFoldable<'tcx>>(&self, t: T) -> T {
591747
t.fold_with(&mut self.freshener())

src/librustc_trans/trans/adt.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ use std::rc::Rc;
5050
use llvm::{ValueRef, True, IntEQ, IntNE};
5151
use back::abi::FAT_PTR_ADDR;
5252
use middle::subst;
53+
use middle::infer;
5354
use middle::ty::{self, Ty, ClosureTyper};
5455
use middle::ty::Disr;
5556
use syntax::ast;
@@ -223,8 +224,8 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
223224
Univariant(mk_struct(cx, &ftys[..], packed, t), dtor_to_init_u8(dtor))
224225
}
225226
ty::TyClosure(def_id, substs) => {
226-
let typer = NormalizingClosureTyper::new(cx.tcx());
227-
let upvars = typer.closure_upvars(def_id, substs).unwrap();
227+
let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables);
228+
let upvars = infcx.closure_upvars(def_id, substs).unwrap();
228229
let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
229230
Univariant(mk_struct(cx, &upvar_types[..], false, t), 0)
230231
}
@@ -443,8 +444,8 @@ fn find_discr_field_candidate<'tcx>(tcx: &ty::ctxt<'tcx>,
443444
// Perhaps one of the upvars of this struct is non-zero
444445
// Let's recurse and find out!
445446
ty::TyClosure(def_id, substs) => {
446-
let typer = NormalizingClosureTyper::new(tcx);
447-
let upvars = typer.closure_upvars(def_id, substs).unwrap();
447+
let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables);
448+
let upvars = infcx.closure_upvars(def_id, substs).unwrap();
448449
let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
449450

450451
for (j, &ty) in upvar_types.iter().enumerate() {

src/librustc_trans/trans/attributes.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use libc::{c_uint, c_ulonglong};
1313
use llvm::{self, ValueRef, AttrHelper};
1414
use middle::ty::{self, ClosureTyper};
15+
use middle::infer;
1516
use session::config::NoDebugInfo;
1617
use syntax::abi;
1718
use syntax::ast;
@@ -145,8 +146,8 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
145146
let (fn_sig, abi, env_ty) = match fn_type.sty {
146147
ty::TyBareFn(_, ref f) => (&f.sig, f.abi, None),
147148
ty::TyClosure(closure_did, substs) => {
148-
let typer = common::NormalizingClosureTyper::new(ccx.tcx());
149-
function_type = typer.closure_type(closure_did, substs);
149+
let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
150+
function_type = infcx.closure_type(closure_did, substs);
150151
let self_type = base::self_type_for_closure(ccx, closure_did, fn_type);
151152
(&function_type.sig, abi::RustCall, Some(self_type))
152153
}

src/librustc_trans/trans/base.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ use llvm;
3737
use metadata::{csearch, encoder, loader};
3838
use middle::astencode;
3939
use middle::cfg;
40+
use middle::infer;
4041
use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
4142
use middle::weak_lang_items;
4243
use middle::subst::Substs;
@@ -434,8 +435,8 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
434435
}
435436
ty::TyClosure(def_id, substs) => {
436437
let repr = adt::represent_type(cx.ccx(), t);
437-
let typer = common::NormalizingClosureTyper::new(cx.tcx());
438-
let upvars = typer.closure_upvars(def_id, substs).unwrap();
438+
let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables);
439+
let upvars = infcx.closure_upvars(def_id, substs).unwrap();
439440
for (i, upvar) in upvars.iter().enumerate() {
440441
let llupvar = adt::trans_field_ptr(cx, &*repr, data_ptr, 0, i);
441442
cx = f(cx, llupvar, upvar.ty);

src/librustc_trans/trans/closure.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use arena::TypedArena;
1212
use back::link::{self, mangle_internal_name_by_path_and_seq};
1313
use llvm::{ValueRef, get_params};
1414
use middle::mem_categorization::Typer;
15+
use middle::infer;
1516
use trans::adt;
1617
use trans::attributes;
1718
use trans::base::*;
@@ -214,8 +215,9 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
214215
// takes the same set of type arguments as the enclosing fn, and
215216
// this function (`trans_closure`) is invoked at the point
216217
// of the closure expression.
217-
let typer = NormalizingClosureTyper::new(tcx);
218-
let function_type = typer.closure_type(closure_id, param_substs);
218+
219+
let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
220+
let function_type = infcx.closure_type(closure_id, param_substs);
219221

220222
let freevars: Vec<ty::Freevar> =
221223
tcx.with_freevars(id, |fv| fv.iter().cloned().collect());
@@ -358,7 +360,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
358360
ccx.tn().val_to_string(llreffn));
359361

360362
let tcx = ccx.tcx();
361-
let typer = NormalizingClosureTyper::new(tcx);
363+
let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
362364

363365
// Find a version of the closure type. Substitute static for the
364366
// region since it doesn't really matter.
@@ -367,7 +369,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
367369
let ref_closure_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic), closure_ty);
368370

369371
// Make a version with the type of by-ref closure.
370-
let ty::ClosureTy { unsafety, abi, mut sig } = typer.closure_type(closure_def_id, substs);
372+
let ty::ClosureTy { unsafety, abi, mut sig } = infcx.closure_type(closure_def_id, substs);
371373
sig.0.inputs.insert(0, ref_closure_ty); // sig has no self type as of yet
372374
let llref_bare_fn_ty = tcx.mk_bare_fn(ty::BareFnTy { unsafety: unsafety,
373375
abi: abi,

0 commit comments

Comments
 (0)