Introduce a "liberated fn sigs" map so that we have easy access to this
information when constructing MIR.
This commit is contained in:
parent
fffe075708
commit
6d7c66e6e8
@ -121,6 +121,13 @@ pub struct Tables<'tcx> {
|
||||
/// Records the type of each closure. The def ID is the ID of the
|
||||
/// expression defining the closure.
|
||||
pub closure_kinds: DefIdMap<ty::ClosureKind>,
|
||||
|
||||
/// For each fn, records the "liberated" types of its arguments
|
||||
/// and return type. Liberated means that all bound regions
|
||||
/// (including late-bound regions) are replaced with free
|
||||
/// equivalents. This table is not used in trans (since regions
|
||||
/// are erased there) and hence is not serialized to metadata.
|
||||
pub liberated_fn_sigs: NodeMap<ty::FnSig<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> Tables<'tcx> {
|
||||
@ -133,6 +140,7 @@ impl<'tcx> Tables<'tcx> {
|
||||
upvar_capture_map: FnvHashMap(),
|
||||
closure_tys: DefIdMap(),
|
||||
closure_kinds: DefIdMap(),
|
||||
liberated_fn_sigs: NodeMap(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,11 +164,6 @@ pub struct Inherited<'a, 'tcx: 'a> {
|
||||
|
||||
tables: &'a RefCell<ty::Tables<'tcx>>,
|
||||
|
||||
// A mapping from each fn's id to its signature, with all bound
|
||||
// regions replaced with free ones. Unlike the other tables, this
|
||||
// one is never copied into the tcx: it is only used by regionck.
|
||||
fn_sig_map: RefCell<NodeMap<Vec<Ty<'tcx>>>>,
|
||||
|
||||
// When we process a call like `c()` where `c` is a closure type,
|
||||
// we may not have decided yet whether `c` is a `Fn`, `FnMut`, or
|
||||
// `FnOnce` closure. In that case, we defer full resolution of the
|
||||
@ -314,7 +309,6 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
|
||||
infcx: infer::new_infer_ctxt(tcx, tables, Some(param_env), true),
|
||||
locals: RefCell::new(NodeMap()),
|
||||
tables: tables,
|
||||
fn_sig_map: RefCell::new(NodeMap()),
|
||||
deferred_call_resolutions: RefCell::new(DefIdMap()),
|
||||
deferred_cast_checks: RefCell::new(Vec::new()),
|
||||
}
|
||||
@ -620,22 +614,13 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
|
||||
ccx: ccx
|
||||
};
|
||||
|
||||
// Remember return type so that regionck can access it later.
|
||||
let mut fn_sig_tys: Vec<Ty> =
|
||||
arg_tys.iter()
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
if let ty::FnConverging(ret_ty) = ret_ty {
|
||||
fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
|
||||
fn_sig_tys.push(ret_ty); // FIXME(#25759) just take implied bounds from the arguments
|
||||
}
|
||||
|
||||
debug!("fn-sig-map: fn_id={} fn_sig_tys={:?}",
|
||||
fn_id,
|
||||
fn_sig_tys);
|
||||
debug!("fn-sig-map: fn_id={} fn_sig={:?}", fn_id, fn_sig);
|
||||
|
||||
inherited.fn_sig_map.borrow_mut().insert(fn_id, fn_sig_tys);
|
||||
inherited.tables.borrow_mut().liberated_fn_sigs.insert(fn_id, fn_sig.clone());
|
||||
|
||||
{
|
||||
let mut visit = GatherLocalsVisitor { fcx: &fcx, };
|
||||
|
@ -284,19 +284,32 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> {
|
||||
// When we enter a function, we can derive
|
||||
debug!("visit_fn_body(id={})", id);
|
||||
|
||||
let fn_sig_map = self.fcx.inh.fn_sig_map.borrow();
|
||||
let fn_sig = match fn_sig_map.get(&id) {
|
||||
Some(f) => f,
|
||||
None => {
|
||||
self.tcx().sess.bug(
|
||||
&format!("No fn-sig entry for id={}", id));
|
||||
let fn_sig = {
|
||||
let fn_sig_map = &self.infcx().tables.borrow().liberated_fn_sigs;
|
||||
match fn_sig_map.get(&id) {
|
||||
Some(f) => f.clone(),
|
||||
None => {
|
||||
self.tcx().sess.bug(
|
||||
&format!("No fn-sig entry for id={}", id));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let old_region_bounds_pairs_len = self.region_bound_pairs.len();
|
||||
|
||||
// Collect the types from which we create inferred bounds.
|
||||
// For the return type, if diverging, substitute `bool` just
|
||||
// because it will have no effect.
|
||||
//
|
||||
// FIXME(#25759) return types should not be implied bounds
|
||||
let fn_sig_tys: Vec<_> =
|
||||
fn_sig.inputs.iter()
|
||||
.cloned()
|
||||
.chain(Some(fn_sig.output.unwrap_or(self.tcx().types.bool)))
|
||||
.collect();
|
||||
|
||||
let old_body_id = self.set_body_id(body.id);
|
||||
self.relate_free_regions(&fn_sig[..], body.id, span);
|
||||
self.relate_free_regions(&fn_sig_tys[..], body.id, span);
|
||||
link_fn_args(self,
|
||||
self.tcx().region_maps.node_extent(body.id),
|
||||
&fn_decl.inputs[..]);
|
||||
|
@ -43,6 +43,7 @@ pub fn resolve_type_vars_in_expr(fcx: &FnCtxt, e: &hir::Expr) {
|
||||
wbcx.visit_expr(e);
|
||||
wbcx.visit_upvar_borrow_map();
|
||||
wbcx.visit_closures();
|
||||
wbcx.visit_liberated_fn_sigs();
|
||||
}
|
||||
|
||||
pub fn resolve_type_vars_in_fn(fcx: &FnCtxt,
|
||||
@ -63,6 +64,7 @@ pub fn resolve_type_vars_in_fn(fcx: &FnCtxt,
|
||||
}
|
||||
wbcx.visit_upvar_borrow_map();
|
||||
wbcx.visit_closures();
|
||||
wbcx.visit_liberated_fn_sigs();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -361,6 +363,13 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_liberated_fn_sigs(&self) {
|
||||
for (&node_id, fn_sig) in self.fcx.inh.tables.borrow().liberated_fn_sigs.iter() {
|
||||
let fn_sig = self.resolve(fn_sig, ResolvingFnSig(node_id));
|
||||
self.tcx().tables.borrow_mut().liberated_fn_sigs.insert(node_id, fn_sig.clone());
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve<T:TypeFoldable<'tcx>>(&self, t: &T, reason: ResolveReason) -> T {
|
||||
t.fold_with(&mut Resolver::new(self.fcx, reason))
|
||||
}
|
||||
@ -376,6 +385,7 @@ enum ResolveReason {
|
||||
ResolvingPattern(Span),
|
||||
ResolvingUpvar(ty::UpvarId),
|
||||
ResolvingClosure(DefId),
|
||||
ResolvingFnSig(ast::NodeId),
|
||||
}
|
||||
|
||||
impl ResolveReason {
|
||||
@ -387,6 +397,9 @@ impl ResolveReason {
|
||||
ResolvingUpvar(upvar_id) => {
|
||||
tcx.expr_span(upvar_id.closure_expr_id)
|
||||
}
|
||||
ResolvingFnSig(id) => {
|
||||
tcx.map.span(id)
|
||||
}
|
||||
ResolvingClosure(did) => {
|
||||
if let Some(node_id) = tcx.map.as_local_node_id(did) {
|
||||
tcx.expr_span(node_id)
|
||||
@ -463,6 +476,16 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
|
||||
span_err!(self.tcx.sess, span, E0196,
|
||||
"cannot determine a type for this closure")
|
||||
}
|
||||
|
||||
ResolvingFnSig(id) => {
|
||||
// any failures here should also fail when
|
||||
// resolving the patterns, closure types, or
|
||||
// something else.
|
||||
let span = self.reason.span(self.tcx);
|
||||
self.tcx.sess.delay_span_bug(
|
||||
span,
|
||||
&format!("cannot resolve some aspect of fn sig for {:?}", id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user