Skip to content

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/infer/opaque_types
    • librustc_mir/borrow_check/type_check

2 files changed

+43
-15
lines changed

src/librustc/infer/opaque_types/mod.rs

+41-15
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

+2
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)