2017-10-30 04:51:10 -04:00
|
|
|
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
|
|
|
//! Code to extract the free regions declared on a function and the
|
|
|
|
//! relationships between them. For example:
|
|
|
|
//!
|
|
|
|
//! ```
|
|
|
|
//! fn foo<'a, 'b, 'c: 'b>() { }
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! here we would be returning a map assigning each of `{'a, 'b, 'c}`
|
|
|
|
//! to an index, as well as the `FreeRegionMap` which can compute
|
|
|
|
//! relationships between them.
|
|
|
|
//!
|
|
|
|
//! The code in this file doesn't *do anything* with those results; it
|
|
|
|
//! just returns them for other code to use.
|
|
|
|
|
2017-11-10 19:20:35 +02:00
|
|
|
use rustc::hir::def_id::DefId;
|
2017-10-30 04:51:10 -04:00
|
|
|
use rustc::infer::InferCtxt;
|
|
|
|
use rustc::middle::free_region::FreeRegionMap;
|
2017-11-06 04:15:38 -05:00
|
|
|
use rustc::ty::{self, RegionVid};
|
2017-10-30 04:51:10 -04:00
|
|
|
use rustc::ty::subst::Substs;
|
|
|
|
use rustc::util::nodemap::FxHashMap;
|
2017-11-06 04:04:45 -05:00
|
|
|
use rustc_data_structures::indexed_vec::Idx;
|
|
|
|
|
2017-10-30 04:51:10 -04:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct FreeRegions<'tcx> {
|
|
|
|
/// Given a free region defined on this function (either early- or
|
2017-11-06 04:04:45 -05:00
|
|
|
/// late-bound), this maps it to its internal region index. When
|
|
|
|
/// the region context is created, the first N variables will be
|
|
|
|
/// created based on these indices.
|
2017-11-06 04:15:38 -05:00
|
|
|
pub indices: FxHashMap<ty::Region<'tcx>, RegionVid>,
|
2017-10-30 04:51:10 -04:00
|
|
|
|
|
|
|
/// The map from the typeck tables telling us how to relate free regions.
|
|
|
|
pub free_region_map: &'tcx FreeRegionMap<'tcx>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn free_regions<'a, 'gcx, 'tcx>(
|
|
|
|
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
2017-11-10 19:20:35 +02:00
|
|
|
item_def_id: DefId,
|
2017-10-30 04:51:10 -04:00
|
|
|
) -> FreeRegions<'tcx> {
|
2017-11-10 19:20:35 +02:00
|
|
|
debug!("free_regions(item_def_id={:?})", item_def_id);
|
2017-10-30 04:51:10 -04:00
|
|
|
|
|
|
|
let mut indices = FxHashMap();
|
|
|
|
|
2017-11-06 07:26:34 -05:00
|
|
|
// `'static` is always free.
|
|
|
|
insert_free_region(&mut indices, infcx.tcx.types.re_static);
|
|
|
|
|
2017-10-30 04:51:10 -04:00
|
|
|
// Extract the early regions.
|
|
|
|
let item_substs = Substs::identity_for_item(infcx.tcx, item_def_id);
|
|
|
|
for item_subst in item_substs {
|
|
|
|
if let Some(region) = item_subst.as_region() {
|
|
|
|
insert_free_region(&mut indices, region);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Extract the late-bound regions. Use the liberated fn sigs,
|
|
|
|
// where the late-bound regions will have been converted into free
|
|
|
|
// regions, and add them to the map.
|
2017-11-10 19:20:35 +02:00
|
|
|
let item_id = infcx.tcx.hir.as_local_node_id(item_def_id).unwrap();
|
2017-10-30 04:51:10 -04:00
|
|
|
let fn_hir_id = infcx.tcx.hir.node_to_hir_id(item_id);
|
|
|
|
let tables = infcx.tcx.typeck_tables_of(item_def_id);
|
|
|
|
let fn_sig = tables.liberated_fn_sigs()[fn_hir_id].clone();
|
|
|
|
infcx
|
|
|
|
.tcx
|
|
|
|
.for_each_free_region(&fn_sig.inputs_and_output, |region| {
|
|
|
|
if let ty::ReFree(_) = *region {
|
|
|
|
insert_free_region(&mut indices, region);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
debug!("free_regions: indices={:#?}", indices);
|
|
|
|
|
|
|
|
FreeRegions { indices, free_region_map: &tables.free_region_map }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn insert_free_region<'tcx>(
|
2017-11-06 04:15:38 -05:00
|
|
|
free_regions: &mut FxHashMap<ty::Region<'tcx>, RegionVid>,
|
2017-10-30 04:51:10 -04:00
|
|
|
region: ty::Region<'tcx>,
|
|
|
|
) {
|
2017-11-06 04:15:38 -05:00
|
|
|
let next = RegionVid::new(free_regions.len());
|
2017-11-06 04:04:45 -05:00
|
|
|
free_regions.entry(region).or_insert(next);
|
2017-10-30 04:51:10 -04:00
|
|
|
}
|