]> git.lizzy.rs Git - rust.git/commitdiff
Give precendence to regions from member constaints when inferring concrete types.
authorCamille GILLOT <gillot.camille@gmail.com>
Mon, 14 Nov 2022 21:24:18 +0000 (21:24 +0000)
committerCamille GILLOT <gillot.camille@gmail.com>
Mon, 14 Nov 2022 21:24:18 +0000 (21:24 +0000)
compiler/rustc_borrowck/src/member_constraints.rs
compiler/rustc_borrowck/src/region_infer/mod.rs
compiler/rustc_borrowck/src/region_infer/opaque_types.rs
compiler/rustc_middle/src/ty/mod.rs

index b48f9f97daad8d76dc07b541f445206f55fa7e8c..b5e00f471d26a0d266e021e330cfeb78f56fef1f 100644 (file)
@@ -11,6 +11,7 @@
 
 /// Compactly stores a set of `R0 member of [R1...Rn]` constraints,
 /// indexed by the region `R0`.
+#[derive(Debug)]
 pub(crate) struct MemberConstraintSet<'tcx, R>
 where
     R: Copy + Eq,
@@ -31,6 +32,7 @@ pub(crate) struct MemberConstraintSet<'tcx, R>
 }
 
 /// Represents a `R0 member of [R1..Rn]` constraint
+#[derive(Debug)]
 pub(crate) struct NllMemberConstraint<'tcx> {
     next_constraint: Option<NllMemberConstraintIndex>,
 
index 94e9e05e5d640936be66ffb5bec23018b3d0a82f..b35abbd107b9ce7e148603f91207a64c513e1f84 100644 (file)
@@ -128,6 +128,7 @@ pub struct RegionInferenceContext<'tcx> {
 /// adds a new lower bound to the SCC it is analyzing: so you wind up
 /// with `'R: 'O` where `'R` is the pick-region and `'O` is the
 /// minimal viable option.
+#[derive(Debug)]
 pub(crate) struct AppliedMemberConstraint {
     /// The SCC that was affected. (The "member region".)
     ///
index dd222485daf2c01b3188ff5abaa564065fa69246..fe49e3a4ba9c8366f496c4520d493a6529326ff4 100644 (file)
@@ -1,4 +1,4 @@
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
 use rustc_data_structures::vec_map::VecMap;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::OpaqueTyOrigin;
@@ -63,17 +63,21 @@ pub(crate) fn infer_opaque_types(
         opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>,
     ) -> VecMap<LocalDefId, OpaqueHiddenType<'tcx>> {
         let mut result: VecMap<LocalDefId, OpaqueHiddenType<'tcx>> = VecMap::new();
+
+        let member_constraints: FxHashMap<_, _> = self
+            .member_constraints
+            .all_indices()
+            .map(|ci| (self.member_constraints[ci].key, ci))
+            .collect();
+        debug!(?member_constraints);
+
         for (opaque_type_key, (concrete_type, origin)) in opaque_ty_decls {
             let substs = opaque_type_key.substs;
             debug!(?concrete_type, ?substs);
 
             let mut subst_regions = vec![self.universal_regions.fr_static];
-            let universal_substs = infcx.tcx.fold_regions(substs, |region, _| {
-                if let ty::RePlaceholder(..) = region.kind() {
-                    // Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs.
-                    return region;
-                }
-                let vid = self.to_region_vid(region);
+
+            let to_universal_region = |vid, subst_regions: &mut Vec<_>| {
                 trace!(?vid);
                 let scc = self.constraint_sccs.scc(vid);
                 trace!(?scc);
@@ -94,10 +98,33 @@ pub(crate) fn infer_opaque_types(
                         infcx.tcx.lifetimes.re_static
                     }
                 }
+            };
+
+            // Start by inserting universal regions from the member_constraint choice regions.
+            // This will ensure they get precedence when folding the regions in the concrete type.
+            if let Some(&ci) = member_constraints.get(&opaque_type_key) {
+                for &vid in self.member_constraints.choice_regions(ci) {
+                    to_universal_region(vid, &mut subst_regions);
+                }
+            }
+            debug!(?subst_regions);
+
+            // Next, insert universal regions from substs, so we can translate regions that appear
+            // in them but are not subject to member constraints, for instance closure substs.
+            let universal_substs = infcx.tcx.fold_regions(substs, |region, _| {
+                if let ty::RePlaceholder(..) = region.kind() {
+                    // Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs.
+                    return region;
+                }
+                let vid = self.to_region_vid(region);
+                to_universal_region(vid, &mut subst_regions)
             });
+            debug!(?universal_substs);
+            debug!(?subst_regions);
 
-            subst_regions.sort();
-            subst_regions.dedup();
+            // Deduplicate the set of regions while keeping the chosen order.
+            let subst_regions = subst_regions.into_iter().collect::<FxIndexSet<_>>();
+            debug!(?subst_regions);
 
             let universal_concrete_type =
                 infcx.tcx.fold_regions(concrete_type, |region, _| match *region {
@@ -108,8 +135,7 @@ pub(crate) fn infer_opaque_types(
                         .unwrap_or(infcx.tcx.lifetimes.re_erased),
                     _ => region,
                 });
-
-            debug!(?universal_concrete_type, ?universal_substs);
+            debug!(?universal_concrete_type);
 
             let opaque_type_key =
                 OpaqueTypeKey { def_id: opaque_type_key.def_id, substs: universal_substs };
index ce1b1d6973e180a74be1d137234ed6b7d6e9661f..31bdb049e76a5c5b76071fa324da8893022c8a68 100644 (file)
@@ -1257,7 +1257,7 @@ pub fn is_empty(&self) -> bool {
     }
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable, Lift)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable, Lift)]
 #[derive(TypeFoldable, TypeVisitable)]
 pub struct OpaqueTypeKey<'tcx> {
     pub def_id: LocalDefId,
@@ -1333,17 +1333,16 @@ pub fn remap_generic_params_to_declaration_params(
         debug!(?id_substs);
 
         // This zip may have several times the same lifetime in `substs` paired with a different
-        // lifetime from `id_substs`.  In that case, we actually want to pick the last one, as it
-        // is the one we introduced in the impl-trait desugaring to be meaningful.  The other ones
-        // are redundant.
+        // lifetime from `id_substs`.  Simply `collect`ing the iterator is the correct behaviour:
+        // it will pick the last one, which is the one we introduced in the impl-trait desugaring.
         let map = substs.iter().zip(id_substs);
 
         let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> = match origin {
             // HACK: The HIR lowering for async fn does not generate
             // any `+ Captures<'x>` bounds for the `impl Future<...>`, so all async fns with lifetimes
             // would now fail to compile. We should probably just make hir lowering fill this in properly.
-            OpaqueTyOrigin::FnReturn(_) | OpaqueTyOrigin::AsyncFn(_) => map.collect(),
-            OpaqueTyOrigin::TyAlias => {
+            OpaqueTyOrigin::AsyncFn(_) => map.collect(),
+            OpaqueTyOrigin::FnReturn(_) | OpaqueTyOrigin::TyAlias => {
                 // Opaque types may only use regions that are bound. So for
                 // ```rust
                 // type Foo<'a, 'b, 'c> = impl Trait<'a> + 'b;