Skip to content

Commit

Permalink
Infer opaque type regions in borrow checking
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
matthewjasper committed Feb 14, 2020
1 parent 75ac0cc commit d9b9f00
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 3 deletions.
4 changes: 3 additions & 1 deletion src/librustc_mir/borrow_check/nll.rs
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/borrow_check/region_infer/mod.rs
Expand Up @@ -36,6 +36,7 @@ use crate::borrow_check::{

mod dump_mir;
mod graphviz;
mod opaque_types;

pub mod values;

Expand Down
72 changes: 72 additions & 0 deletions src/librustc_mir/borrow_check/region_infer/opaque_types.rs
@@ -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()
}
}
9 changes: 7 additions & 2 deletions src/librustc_mir/borrow_check/type_check/mod.rs
Expand Up @@ -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:
Expand Down

0 comments on commit d9b9f00

Please sign in to comment.