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.
This commit is contained in:
parent
dd1687ef41
commit
e3e5d27f23
@ -93,6 +93,18 @@ pub struct OpaqueTypeDecl<'tcx> {
|
||||
pub origin: hir::OpaqueTyOrigin,
|
||||
}
|
||||
|
||||
/// Whether member constraints should be generated for all opaque types
|
||||
pub enum GenerateMemberConstraints {
|
||||
/// The default, used by typeck
|
||||
WhenRequired,
|
||||
/// The borrow checker needs member constraints in any case where we don't
|
||||
/// have a `'static` bound. This is because the borrow checker has more
|
||||
/// flexibility in the values of regions. For example, given `f<'a, 'b>`
|
||||
/// the borrow checker can have an inference variable outlive `'a` and `'b`,
|
||||
/// but not be equal to `'static`.
|
||||
IfNoStaticBound,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
/// Replaces all opaque types in `value` with fresh inference variables
|
||||
/// and creates appropriate obligations. For example, given the input:
|
||||
@ -315,7 +327,12 @@ pub fn constrain_opaque_types<FRR: FreeRegionRelations<'tcx>>(
|
||||
debug!("constrain_opaque_types()");
|
||||
|
||||
for (&def_id, opaque_defn) in opaque_types {
|
||||
self.constrain_opaque_type(def_id, opaque_defn, free_region_relations);
|
||||
self.constrain_opaque_type(
|
||||
def_id,
|
||||
opaque_defn,
|
||||
GenerateMemberConstraints::WhenRequired,
|
||||
free_region_relations,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -324,6 +341,7 @@ pub fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
opaque_defn: &OpaqueTypeDecl<'tcx>,
|
||||
mode: GenerateMemberConstraints,
|
||||
free_region_relations: &FRR,
|
||||
) {
|
||||
debug!("constrain_opaque_type()");
|
||||
@ -358,6 +376,14 @@ pub fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
|
||||
op: |r| self.sub_regions(infer::CallReturn(span), required_region, r),
|
||||
});
|
||||
}
|
||||
if let GenerateMemberConstraints::IfNoStaticBound = mode {
|
||||
self.generate_member_constraint(
|
||||
concrete_ty,
|
||||
opaque_type_generics,
|
||||
opaque_defn,
|
||||
def_id,
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -398,13 +424,15 @@ pub fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
|
||||
// we will create a "in bound" like `'r in
|
||||
// ['a, 'b, 'c]`, where `'a..'c` are the
|
||||
// regions that appear in the impl trait.
|
||||
|
||||
// For now, enforce a feature gate outside of async functions.
|
||||
self.member_constraint_feature_gate(opaque_defn, def_id, lr, subst_arg);
|
||||
|
||||
return self.generate_member_constraint(
|
||||
concrete_ty,
|
||||
opaque_type_generics,
|
||||
opaque_defn,
|
||||
def_id,
|
||||
lr,
|
||||
subst_arg,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -414,6 +442,16 @@ pub fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
|
||||
let least_region = least_region.unwrap_or(tcx.lifetimes.re_static);
|
||||
debug!("constrain_opaque_types: least_region={:?}", least_region);
|
||||
|
||||
if let GenerateMemberConstraints::IfNoStaticBound = mode {
|
||||
if least_region != tcx.lifetimes.re_static {
|
||||
self.generate_member_constraint(
|
||||
concrete_ty,
|
||||
opaque_type_generics,
|
||||
opaque_defn,
|
||||
def_id,
|
||||
);
|
||||
}
|
||||
}
|
||||
concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
|
||||
tcx: self.tcx,
|
||||
op: |r| self.sub_regions(infer::CallReturn(span), least_region, r),
|
||||
@ -434,19 +472,7 @@ fn generate_member_constraint(
|
||||
opaque_type_generics: &ty::Generics,
|
||||
opaque_defn: &OpaqueTypeDecl<'tcx>,
|
||||
opaque_type_def_id: DefId,
|
||||
conflict1: ty::Region<'tcx>,
|
||||
conflict2: ty::Region<'tcx>,
|
||||
) {
|
||||
// For now, enforce a feature gate outside of async functions.
|
||||
if self.member_constraint_feature_gate(
|
||||
opaque_defn,
|
||||
opaque_type_def_id,
|
||||
conflict1,
|
||||
conflict2,
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the set of choice regions: each region in the hidden
|
||||
// type can be equal to any of the region parameters of the
|
||||
// opaque type definition.
|
||||
|
@ -6,6 +6,7 @@
|
||||
use either::Either;
|
||||
|
||||
use rustc::infer::canonical::QueryRegionConstraints;
|
||||
use rustc::infer::opaque_types::GenerateMemberConstraints;
|
||||
use rustc::infer::outlives::env::RegionBoundPairs;
|
||||
use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
|
||||
@ -1345,6 +1346,7 @@ fn eq_opaque_type_and_type(
|
||||
infcx.constrain_opaque_type(
|
||||
opaque_def_id,
|
||||
&opaque_decl,
|
||||
GenerateMemberConstraints::IfNoStaticBound,
|
||||
universal_region_relations,
|
||||
);
|
||||
Ok(InferOk { value: (), obligations: vec![] })
|
||||
|
Loading…
Reference in New Issue
Block a user