diff options
| author | Matthew Jasper <mjjasper1@gmail.com> | 2019-12-26 21:16:28 +0000 |
|---|---|---|
| committer | Matthew Jasper <mjjasper1@gmail.com> | 2020-02-14 22:40:02 +0000 |
| commit | d9b9f00109aefcaf565c9da3c6fdf9e446f4876c (patch) | |
| tree | d49a7dc86e527252b1bdca172585c148a39340ba | |
| parent | 75ac0cca3678d5d309c737f1bd8ef237628a278b (diff) | |
| download | rust-d9b9f00109aefcaf565c9da3c6fdf9e446f4876c.tar.gz rust-d9b9f00109aefcaf565c9da3c6fdf9e446f4876c.zip | |
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.
| -rw-r--r-- | src/librustc_mir/borrow_check/nll.rs | 4 | ||||
| -rw-r--r-- | src/librustc_mir/borrow_check/region_infer/mod.rs | 1 | ||||
| -rw-r--r-- | src/librustc_mir/borrow_check/region_infer/opaque_types.rs | 72 | ||||
| -rw-r--r-- | src/librustc_mir/borrow_check/type_check/mod.rs | 9 |
4 files changed, 83 insertions, 3 deletions
diff --git a/src/librustc_mir/borrow_check/nll.rs b/src/librustc_mir/borrow_check/nll.rs index 4acf1cf7c2b..e4e5fe35d7f 100644 --- a/src/librustc_mir/borrow_check/nll.rs +++ b/src/librustc_mir/borrow_check/nll.rs @@ -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, diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs index 6abca481eac..4a2f398c6d5 100644 --- a/src/librustc_mir/borrow_check/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/region_infer/mod.rs @@ -36,6 +36,7 @@ use crate::borrow_check::{ mod dump_mir; mod graphviz; +mod opaque_types; pub mod values; diff --git a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs new file mode 100644 index 00000000000..e16a2c838eb --- /dev/null +++ b/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() + } +} diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index c6809f9e37e..5c6f3a0ffa9 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -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: |
