Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit e3e5d27

Browse files
committed
Use member constraint for most opaque types in NLL
This ensures that NLL will infer suitable values for regions in opaque types when it's possible.
1 parent dd1687e commit e3e5d27

File tree

2 files changed

+43
-15
lines changed
  • src
    • librustc_mir/borrow_check/type_check
    • librustc/infer/opaque_types

2 files changed

+43
-15
lines changed

src/librustc/infer/opaque_types/mod.rs

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,18 @@ pub struct OpaqueTypeDecl<'tcx> {
9393
pub origin: hir::OpaqueTyOrigin,
9494
}
9595

96+
/// Whether member constraints should be generated for all opaque types
97+
pub enum GenerateMemberConstraints {
98+
/// The default, used by typeck
99+
WhenRequired,
100+
/// The borrow checker needs member constraints in any case where we don't
101+
/// have a `'static` bound. This is because the borrow checker has more
102+
/// flexibility in the values of regions. For example, given `f<'a, 'b>`
103+
/// the borrow checker can have an inference variable outlive `'a` and `'b`,
104+
/// but not be equal to `'static`.
105+
IfNoStaticBound,
106+
}
107+
96108
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
97109
/// Replaces all opaque types in `value` with fresh inference variables
98110
/// and creates appropriate obligations. For example, given the input:
@@ -315,7 +327,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
315327
debug!("constrain_opaque_types()");
316328

317329
for (&def_id, opaque_defn) in opaque_types {
318-
self.constrain_opaque_type(def_id, opaque_defn, free_region_relations);
330+
self.constrain_opaque_type(
331+
def_id,
332+
opaque_defn,
333+
GenerateMemberConstraints::WhenRequired,
334+
free_region_relations,
335+
);
319336
}
320337
}
321338

@@ -324,6 +341,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
324341
&self,
325342
def_id: DefId,
326343
opaque_defn: &OpaqueTypeDecl<'tcx>,
344+
mode: GenerateMemberConstraints,
327345
free_region_relations: &FRR,
328346
) {
329347
debug!("constrain_opaque_type()");
@@ -358,6 +376,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
358376
op: |r| self.sub_regions(infer::CallReturn(span), required_region, r),
359377
});
360378
}
379+
if let GenerateMemberConstraints::IfNoStaticBound = mode {
380+
self.generate_member_constraint(
381+
concrete_ty,
382+
opaque_type_generics,
383+
opaque_defn,
384+
def_id,
385+
);
386+
}
361387
return;
362388
}
363389

@@ -398,13 +424,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
398424
// we will create a "in bound" like `'r in
399425
// ['a, 'b, 'c]`, where `'a..'c` are the
400426
// regions that appear in the impl trait.
427+
428+
// For now, enforce a feature gate outside of async functions.
429+
self.member_constraint_feature_gate(opaque_defn, def_id, lr, subst_arg);
430+
401431
return self.generate_member_constraint(
402432
concrete_ty,
403433
opaque_type_generics,
404434
opaque_defn,
405435
def_id,
406-
lr,
407-
subst_arg,
408436
);
409437
}
410438
}
@@ -414,6 +442,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
414442
let least_region = least_region.unwrap_or(tcx.lifetimes.re_static);
415443
debug!("constrain_opaque_types: least_region={:?}", least_region);
416444

445+
if let GenerateMemberConstraints::IfNoStaticBound = mode {
446+
if least_region != tcx.lifetimes.re_static {
447+
self.generate_member_constraint(
448+
concrete_ty,
449+
opaque_type_generics,
450+
opaque_defn,
451+
def_id,
452+
);
453+
}
454+
}
417455
concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
418456
tcx: self.tcx,
419457
op: |r| self.sub_regions(infer::CallReturn(span), least_region, r),
@@ -434,19 +472,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
434472
opaque_type_generics: &ty::Generics,
435473
opaque_defn: &OpaqueTypeDecl<'tcx>,
436474
opaque_type_def_id: DefId,
437-
conflict1: ty::Region<'tcx>,
438-
conflict2: ty::Region<'tcx>,
439475
) {
440-
// For now, enforce a feature gate outside of async functions.
441-
if self.member_constraint_feature_gate(
442-
opaque_defn,
443-
opaque_type_def_id,
444-
conflict1,
445-
conflict2,
446-
) {
447-
return;
448-
}
449-
450476
// Create the set of choice regions: each region in the hidden
451477
// type can be equal to any of the region parameters of the
452478
// opaque type definition.

src/librustc_mir/borrow_check/type_check/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::{fmt, iter, mem};
66
use either::Either;
77

88
use rustc::infer::canonical::QueryRegionConstraints;
9+
use rustc::infer::opaque_types::GenerateMemberConstraints;
910
use rustc::infer::outlives::env::RegionBoundPairs;
1011
use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
1112
use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
@@ -1345,6 +1346,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
13451346
infcx.constrain_opaque_type(
13461347
opaque_def_id,
13471348
&opaque_decl,
1349+
GenerateMemberConstraints::IfNoStaticBound,
13481350
universal_region_relations,
13491351
);
13501352
Ok(InferOk { value: (), obligations: vec![] })

0 commit comments

Comments
 (0)