Infer opaque type regions in borrow checking

We want type checking for function bodies to ignore/erase regions. As
such, we need to infer the regions in opaque types in borrow check
instead.
This commit is contained in:
Matthew Jasper 2019-12-26 21:16:28 +00:00
parent 75ac0cca36
commit d9b9f00109
4 changed files with 83 additions and 3 deletions

View File

@ -282,9 +282,11 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
let (closure_region_requirements, nll_errors) =
regioncx.solve(infcx, &body, def_id, polonius_output.clone());
let remapped_opaque_tys = regioncx.infer_opaque_types(&infcx, opaque_type_values, body.span);
NllOutput {
regioncx,
opaque_type_values,
opaque_type_values: remapped_opaque_tys,
polonius_output,
opt_closure_req: closure_region_requirements,
nll_errors,

View File

@ -36,6 +36,7 @@ use crate::borrow_check::{
mod dump_mir;
mod graphviz;
mod opaque_types;
pub mod values;

View File

@ -0,0 +1,72 @@
use rustc::hir::def_id::DefId;
use rustc::infer::InferCtxt;
use rustc::ty;
use rustc_data_structures::fx::FxHashMap;
use rustc_span::Span;
use super::RegionInferenceContext;
impl<'tcx> RegionInferenceContext<'tcx> {
/// Resolve any opaque types that were encountered while borrow checking
/// this item. This is then used to get the type in the `type_of` query.
pub(in crate::borrow_check) fn infer_opaque_types(
&self,
infcx: &InferCtxt<'_, 'tcx>,
opaque_ty_decls: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
span: Span,
) -> FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>> {
opaque_ty_decls
.into_iter()
.map(|(opaque_def_id, ty::ResolvedOpaqueTy { concrete_type, substs })| {
debug!(
"infer_opaque_types(concrete_type = {:?}, substs = {:?})",
concrete_type, substs
);
// Map back to "concrete" regions so that errors in
// `infer_opaque_definition_from_instantiation` can show
// sensible region names.
let universal_concrete_type =
infcx.tcx.fold_regions(&concrete_type, &mut false, |region, _| match region {
&ty::ReVar(vid) => {
let universal_bound = self.universal_upper_bound(vid);
self.definitions[universal_bound]
.external_name
.filter(|_| self.eval_equal(universal_bound, vid))
.unwrap_or(infcx.tcx.lifetimes.re_empty)
}
concrete => concrete,
});
let universal_substs =
infcx.tcx.fold_regions(&substs, &mut false, |region, _| match region {
ty::ReVar(vid) => {
self.definitions[*vid].external_name.unwrap_or_else(|| {
infcx.tcx.sess.delay_span_bug(
span,
"opaque type with non-universal region substs",
);
infcx.tcx.lifetimes.re_static
})
}
concrete => concrete,
});
debug!(
"infer_opaque_types(universal_concrete_type = {:?}, universal_substs = {:?})",
universal_concrete_type, universal_substs
);
let remapped_type = infcx.infer_opaque_definition_from_instantiation(
opaque_def_id,
universal_substs,
universal_concrete_type,
span,
);
(
opaque_def_id,
ty::ResolvedOpaqueTy { concrete_type: remapped_type, substs: universal_substs },
)
})
.collect()
}
}

View File

@ -1267,8 +1267,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
.at(&ObligationCause::dummy(), param_env)
.eq(opaque_decl.concrete_ty, renumbered_opaque_defn_ty)?,
);
opaque_type_values
.push((opaque_def_id, ty::ResolvedOpaqueTy { ..*opaque_defn_ty }));
opaque_type_values.push((
opaque_def_id,
ty::ResolvedOpaqueTy {
concrete_type: renumbered_opaque_defn_ty,
substs: opaque_decl.substs,
},
));
} else {
// We're using an opaque `impl Trait` type without
// 'revealing' it. For example, code like this: