Skip to content

Commit a2a6d23

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 38755e6 commit a2a6d23

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
@@ -95,6 +95,18 @@ pub struct OpaqueTypeDecl<'tcx> {
9595
pub origin: hir::OpaqueTyOrigin,
9696
}
9797

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

319331
for (&def_id, opaque_defn) in opaque_types {
320-
self.constrain_opaque_type(def_id, opaque_defn, free_region_relations);
332+
self.constrain_opaque_type(
333+
def_id,
334+
opaque_defn,
335+
GenerateMemberConstraints::WhenRequired,
336+
free_region_relations,
337+
);
321338
}
322339
}
323340

@@ -326,6 +343,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
326343
&self,
327344
def_id: DefId,
328345
opaque_defn: &OpaqueTypeDecl<'tcx>,
346+
mode: GenerateMemberConstraints,
329347
free_region_relations: &FRR,
330348
) {
331349
debug!("constrain_opaque_type()");
@@ -360,6 +378,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
360378
op: |r| self.sub_regions(infer::CallReturn(span), required_region, r),
361379
});
362380
}
381+
if let GenerateMemberConstraints::IfNoStaticBound = mode {
382+
self.generate_member_constraint(
383+
concrete_ty,
384+
opaque_type_generics,
385+
opaque_defn,
386+
def_id,
387+
);
388+
}
363389
return;
364390
}
365391

@@ -400,13 +426,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
400426
// we will create a "in bound" like `'r in
401427
// ['a, 'b, 'c]`, where `'a..'c` are the
402428
// regions that appear in the impl trait.
429+
430+
// For now, enforce a feature gate outside of async functions.
431+
self.member_constraint_feature_gate(opaque_defn, def_id, lr, subst_arg);
432+
403433
return self.generate_member_constraint(
404434
concrete_ty,
405435
opaque_type_generics,
406436
opaque_defn,
407437
def_id,
408-
lr,
409-
subst_arg,
410438
);
411439
}
412440
}
@@ -416,6 +444,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
416444
let least_region = least_region.unwrap_or(tcx.lifetimes.re_static);
417445
debug!("constrain_opaque_types: least_region={:?}", least_region);
418446

447+
if let GenerateMemberConstraints::IfNoStaticBound = mode {
448+
if least_region != tcx.lifetimes.re_static {
449+
self.generate_member_constraint(
450+
concrete_ty,
451+
opaque_type_generics,
452+
opaque_defn,
453+
def_id,
454+
);
455+
}
456+
}
419457
concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
420458
tcx: self.tcx,
421459
op: |r| self.sub_regions(infer::CallReturn(span), least_region, r),
@@ -436,19 +474,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
436474
opaque_type_generics: &ty::Generics,
437475
opaque_defn: &OpaqueTypeDecl<'tcx>,
438476
opaque_type_def_id: DefId,
439-
conflict1: ty::Region<'tcx>,
440-
conflict2: ty::Region<'tcx>,
441477
) {
442-
// For now, enforce a feature gate outside of async functions.
443-
if self.member_constraint_feature_gate(
444-
opaque_defn,
445-
opaque_type_def_id,
446-
conflict1,
447-
conflict2,
448-
) {
449-
return;
450-
}
451-
452478
// Create the set of choice regions: each region in the hidden
453479
// type can be equal to any of the region parameters of the
454480
// 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};
@@ -1346,6 +1347,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
13461347
infcx.constrain_opaque_type(
13471348
opaque_def_id,
13481349
&opaque_decl,
1350+
GenerateMemberConstraints::IfNoStaticBound,
13491351
universal_region_relations,
13501352
);
13511353
Ok(InferOk { value: (), obligations: vec![] })

0 commit comments

Comments
 (0)