diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 4edacd4731c..5ecd03e4123 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -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>( 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>( &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>( 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>( // 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>( 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. diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 85bc032606f..2a2d8642760 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -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![] })