rustc: move liberate_late_bound_regions to rustc_typeck.

This commit is contained in:
Eduard-Mihai Burtescu 2017-05-10 13:40:59 +03:00
parent 6d4c2141b5
commit 74c6788d9c
7 changed files with 24 additions and 74 deletions

View File

@ -96,9 +96,6 @@
//!
//! - `fallthrough_ln`: a live node that represents a fallthrough
//!
//! - `no_ret_var`: a synthetic variable that is only 'read' from, the
//! fallthrough node. This allows us to detect functions where we fail
//! to return explicitly.
//! - `clean_exit_var`: a synthetic variable that is only 'read' from the
//! fallthrough node. It is only live if the function could converge
//! via means other than an explicit `return` expression. That is, it is
@ -111,8 +108,6 @@ use self::VarKind::*;
use hir::def::*;
use ty::{self, TyCtxt};
use traits::{self, Reveal};
use ty::subst::Subst;
use lint;
use util::nodemap::NodeMap;
@ -256,7 +251,6 @@ struct LocalInfo {
enum VarKind {
Arg(NodeId, ast::Name),
Local(LocalInfo),
ImplicitRet,
CleanExit
}
@ -313,7 +307,7 @@ impl<'a, 'tcx> IrMaps<'a, 'tcx> {
Local(LocalInfo { id: node_id, .. }) | Arg(node_id, _) => {
self.variable_map.insert(node_id, v);
},
ImplicitRet | CleanExit => {}
CleanExit => {}
}
debug!("{:?} is {:?}", v, vk);
@ -335,7 +329,6 @@ impl<'a, 'tcx> IrMaps<'a, 'tcx> {
Local(LocalInfo { name, .. }) | Arg(_, name) => {
name.to_string()
},
ImplicitRet => "<implicit-ret>".to_string(),
CleanExit => "<clean-exit>".to_string()
}
}
@ -382,7 +375,6 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>,
// check for various error conditions
lsets.visit_body(body);
lsets.check_ret(id, sp, entry_ln);
lsets.warn_about_unused_args(body, entry_ln);
}
@ -500,7 +492,6 @@ fn invalid_users() -> Users {
struct Specials {
exit_ln: LiveNode,
fallthrough_ln: LiveNode,
no_ret_var: Variable,
clean_exit_var: Variable
}
@ -534,7 +525,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
let specials = Specials {
exit_ln: ir.add_live_node(ExitNode),
fallthrough_ln: ir.add_live_node(ExitNode),
no_ret_var: ir.add_variable(ImplicitRet),
clean_exit_var: ir.add_variable(CleanExit)
};
@ -1420,43 +1410,6 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) {
}
impl<'a, 'tcx> Liveness<'a, 'tcx> {
fn check_ret(&self,
id: NodeId,
sp: Span,
entry_ln: LiveNode)
{
let def_id = self.ir.tcx.hir.local_def_id(id);
let fn_ty = self.ir.tcx.type_of(def_id);
let fn_sig = match fn_ty.sty {
ty::TyClosure(closure_def_id, substs) => {
self.ir.tcx.closure_type(closure_def_id)
.subst(self.ir.tcx, substs.substs)
}
_ => fn_ty.fn_sig()
};
let fn_ret = fn_sig.output();
// within the fn body, late-bound regions are liberated
// and must outlive the *call-site* of the function.
let fn_ret =
self.ir.tcx.liberate_late_bound_regions(def_id, &fn_ret);
if !fn_ret.is_never() && self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() {
let param_env = self.ir.tcx.parameter_environment(def_id);
let t_ret_subst = fn_ret.subst(self.ir.tcx, &param_env.free_substs);
let is_nil = self.ir.tcx.infer_ctxt(param_env, Reveal::All).enter(|infcx| {
let cause = traits::ObligationCause::dummy();
traits::fully_normalize(&infcx, cause, &t_ret_subst).unwrap().is_nil()
});
// for nil return types, it is ok to not return a value expl.
if !is_nil {
span_bug!(sp, "not all control paths return a value");
}
}
}
fn check_lvalue(&mut self, expr: &'tcx Expr) {
match expr.node {
hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {

View File

@ -39,7 +39,6 @@
//! These methods return true to indicate that the visitor has found what it is looking for
//! and does not need to visit anything else.
use hir::def_id::DefId;
use ty::subst::Substs;
use ty::adjustment;
use ty::{self, Binder, Ty, TyCtxt, TypeFlags};
@ -326,23 +325,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
(result, replacer.map)
}
/// Replace any late-bound regions bound in `value` with free variants attached to scope-id
/// `scope_id`.
pub fn liberate_late_bound_regions<T>(self,
all_outlive_scope: DefId,
value: &Binder<T>)
-> T
where T : TypeFoldable<'tcx>
{
self.replace_late_bound_regions(value, |br| {
self.mk_region(ty::ReFree(ty::FreeRegion {
scope: all_outlive_scope,
bound_region: br
}))
}).0
}
/// Flattens two binding levels into one. So `for<'a> for<'b> Foo`
/// becomes `for<'a,'b> Foo`.
pub fn flatten_late_bound_regions<T>(self, bound2_value: &Binder<Binder<T>>)

View File

@ -2417,7 +2417,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
let tcx = self.global_tcx();
let generic_predicates = tcx.predicates_of(def_id);
let bounds = generic_predicates.instantiate(tcx, free_substs);
let bounds = tcx.liberate_late_bound_regions(def_id, &ty::Binder(bounds));
let predicates = bounds.predicates;
// Finally, we have to normalize the bounds in the environment, in

View File

@ -73,7 +73,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
debug!("check_closure: expr.id={:?} closure_type={:?}", expr.id, closure_type);
let fn_sig = self.tcx.liberate_late_bound_regions(expr_def_id, &sig);
let fn_sig = self.liberate_late_bound_regions(expr_def_id, &sig);
let fn_sig = self.inh.normalize_associated_types_in(body.value.span,
body.value.id, &fn_sig);

View File

@ -282,7 +282,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let impl_fty = tcx.mk_fn_ptr(ty::Binder(impl_sig));
debug!("compare_impl_method: impl_fty={:?}", impl_fty);
let trait_sig = tcx.liberate_late_bound_regions(
let trait_sig = inh.liberate_late_bound_regions(
impl_m.def_id,
&m_sig(trait_m));
let trait_sig =

View File

@ -628,6 +628,22 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
obligations);
InferOk { value, obligations }
}
/// Replace any late-bound regions bound in `value` with
/// free variants attached to `all_outlive_scope`.
fn liberate_late_bound_regions<T>(&self,
all_outlive_scope: DefId,
value: &ty::Binder<T>)
-> T
where T: TypeFoldable<'tcx>
{
self.tcx.replace_late_bound_regions(value, |br| {
self.tcx.mk_region(ty::ReFree(ty::FreeRegion {
scope: all_outlive_scope,
bound_region: br
}))
}).0
}
}
struct CheckItemTypesVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> }
@ -804,7 +820,7 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let fn_sig =
fn_sig.subst(inh.tcx, &inh.parameter_environment.free_substs);
let fn_sig =
inh.tcx.liberate_late_bound_regions(def_id, &fn_sig);
inh.liberate_late_bound_regions(def_id, &fn_sig);
let fn_sig =
inh.normalize_associated_types_in(body.value.span, body_id.node_id, &fn_sig);

View File

@ -427,7 +427,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
{
let free_substs = &fcx.parameter_environment.free_substs;
let sig = fcx.instantiate_type_scheme(span, free_substs, &sig);
let sig = fcx.tcx.liberate_late_bound_regions(def_id, &sig);
let sig = fcx.liberate_late_bound_regions(def_id, &sig);
for input_ty in sig.inputs() {
fcx.register_wf_obligation(&input_ty, span, self.code.clone());
@ -462,7 +462,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
let free_substs = &fcx.parameter_environment.free_substs;
let method_ty = fcx.tcx.type_of(method.def_id);
let fty = fcx.instantiate_type_scheme(span, free_substs, &method_ty);
let sig = fcx.tcx.liberate_late_bound_regions(method.def_id, &fty.fn_sig());
let sig = fcx.liberate_late_bound_regions(method.def_id, &fty.fn_sig());
debug!("check_method_receiver: sig={:?}", sig);
@ -478,8 +478,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
ExplicitSelf::ByBox => fcx.tcx.mk_box(self_ty)
};
let rcvr_ty = fcx.instantiate_type_scheme(span, free_substs, &rcvr_ty);
let rcvr_ty = fcx.tcx.liberate_late_bound_regions(method.def_id,
&ty::Binder(rcvr_ty));
let rcvr_ty = fcx.liberate_late_bound_regions(method.def_id,
&ty::Binder(rcvr_ty));
debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty);