@@ -68,10 +68,11 @@ use crate::infer::{
6868} ;
6969use crate :: traits:: { ObligationCause , ObligationCauseCode } ;
7070use rustc_data_structures:: undo_log:: UndoLogs ;
71+ use rustc_hir:: def_id:: DefId ;
7172use rustc_hir:: def_id:: LocalDefId ;
7273use rustc_middle:: mir:: ConstraintCategory ;
7374use rustc_middle:: ty:: subst:: GenericArgKind ;
74- use rustc_middle:: ty:: { self , Region , Ty , TyCtxt , TypeVisitable } ;
75+ use rustc_middle:: ty:: { self , Region , SubstsRef , Ty , TyCtxt , TypeVisitable } ;
7576use smallvec:: smallvec;
7677
7778impl < ' cx , ' tcx > InferCtxt < ' cx , ' tcx > {
@@ -283,6 +284,9 @@ where
283284 Component :: Param ( param_ty) => {
284285 self . param_ty_must_outlive ( origin, region, * param_ty) ;
285286 }
287+ Component :: Opaque ( def_id, substs) => {
288+ self . opaque_must_outlive ( * def_id, substs, origin, region)
289+ }
286290 Component :: Projection ( projection_ty) => {
287291 self . projection_must_outlive ( origin, region, * projection_ty) ;
288292 }
@@ -314,17 +318,69 @@ where
314318 ) ;
315319
316320 let generic = GenericKind :: Param ( param_ty) ;
317- let verify_bound = self . verify_bound . generic_bound ( generic ) ;
321+ let verify_bound = self . verify_bound . param_bound ( param_ty ) ;
318322 self . delegate . push_verify ( origin, generic, region, verify_bound) ;
319323 }
320324
325+ #[ instrument( level = "debug" , skip( self ) ) ]
326+ fn opaque_must_outlive (
327+ & mut self ,
328+ def_id : DefId ,
329+ substs : SubstsRef < ' tcx > ,
330+ origin : infer:: SubregionOrigin < ' tcx > ,
331+ region : ty:: Region < ' tcx > ,
332+ ) {
333+ self . generic_must_outlive (
334+ origin,
335+ region,
336+ GenericKind :: Opaque ( def_id, substs) ,
337+ def_id,
338+ substs,
339+ true ,
340+ |ty| match * ty. kind ( ) {
341+ ty:: Opaque ( def_id, substs) => ( def_id, substs) ,
342+ _ => bug ! ( "expected only projection types from env, not {:?}" , ty) ,
343+ } ,
344+ ) ;
345+ }
346+
321347 #[ instrument( level = "debug" , skip( self ) ) ]
322348 fn projection_must_outlive (
323349 & mut self ,
324350 origin : infer:: SubregionOrigin < ' tcx > ,
325351 region : ty:: Region < ' tcx > ,
326352 projection_ty : ty:: ProjectionTy < ' tcx > ,
327353 ) {
354+ self . generic_must_outlive (
355+ origin,
356+ region,
357+ GenericKind :: Projection ( projection_ty) ,
358+ projection_ty. item_def_id ,
359+ projection_ty. substs ,
360+ false ,
361+ |ty| match ty. kind ( ) {
362+ ty:: Projection ( projection_ty) => ( projection_ty. item_def_id , projection_ty. substs ) ,
363+ _ => bug ! ( "expected only projection types from env, not {:?}" , ty) ,
364+ } ,
365+ ) ;
366+ }
367+
368+ #[ instrument( level = "debug" , skip( self , filter) ) ]
369+ fn generic_must_outlive (
370+ & mut self ,
371+ origin : infer:: SubregionOrigin < ' tcx > ,
372+ region : ty:: Region < ' tcx > ,
373+ generic : GenericKind < ' tcx > ,
374+ def_id : DefId ,
375+ substs : SubstsRef < ' tcx > ,
376+ is_opaque : bool ,
377+ filter : impl Fn ( Ty < ' tcx > ) -> ( DefId , SubstsRef < ' tcx > ) ,
378+ ) {
379+ // An optimization for a common case with opaque types.
380+ if substs. is_empty ( ) {
381+ return ;
382+ }
383+
328384 // This case is thorny for inference. The fundamental problem is
329385 // that there are many cases where we have choice, and inference
330386 // doesn't like choice (the current region inference in
@@ -343,16 +399,15 @@ where
343399 // These are guaranteed to apply, no matter the inference
344400 // results.
345401 let trait_bounds: Vec < _ > =
346- self . verify_bound . projection_declared_bounds_from_trait ( projection_ty ) . collect ( ) ;
402+ self . verify_bound . declared_region_bounds ( def_id , substs ) . collect ( ) ;
347403
348404 debug ! ( ?trait_bounds) ;
349405
350406 // Compute the bounds we can derive from the environment. This
351407 // is an "approximate" match -- in some cases, these bounds
352408 // may not apply.
353- let mut approx_env_bounds =
354- self . verify_bound . projection_approx_declared_bounds_from_env ( projection_ty) ;
355- debug ! ( "projection_must_outlive: approx_env_bounds={:?}" , approx_env_bounds) ;
409+ let mut approx_env_bounds = self . verify_bound . approx_declared_bounds_from_env ( generic) ;
410+ debug ! ( ?approx_env_bounds) ;
356411
357412 // Remove outlives bounds that we get from the environment but
358413 // which are also deducible from the trait. This arises (cc
@@ -366,14 +421,8 @@ where
366421 // If the declaration is `trait Trait<'b> { type Item: 'b; }`, then `projection_declared_bounds_from_trait`
367422 // will be invoked with `['b => ^1]` and so we will get `^1` returned.
368423 let bound = bound_outlives. skip_binder ( ) ;
369- match * bound. 0 . kind ( ) {
370- ty:: Projection ( projection_ty) => self
371- . verify_bound
372- . projection_declared_bounds_from_trait ( projection_ty)
373- . all ( |r| r != bound. 1 ) ,
374-
375- _ => panic ! ( "expected only projection types from env, not {:?}" , bound. 0 ) ,
376- }
424+ let ( def_id, substs) = filter ( bound. 0 ) ;
425+ self . verify_bound . declared_region_bounds ( def_id, substs) . all ( |r| r != bound. 1 )
377426 } ) ;
378427
379428 // If declared bounds list is empty, the only applicable rule is
@@ -390,29 +439,11 @@ where
390439 // the problem is to add `T: 'r`, which isn't true. So, if there are no
391440 // inference variables, we use a verify constraint instead of adding
392441 // edges, which winds up enforcing the same condition.
393- let needs_infer = projection_ty. needs_infer ( ) ;
394- if approx_env_bounds. is_empty ( ) && trait_bounds. is_empty ( ) && needs_infer {
395- debug ! ( "projection_must_outlive: no declared bounds" ) ;
396-
397- let constraint = origin. to_constraint_category ( ) ;
398- for k in projection_ty. substs {
399- match k. unpack ( ) {
400- GenericArgKind :: Lifetime ( lt) => {
401- self . delegate . push_sub_region_constraint (
402- origin. clone ( ) ,
403- region,
404- lt,
405- constraint,
406- ) ;
407- }
408- GenericArgKind :: Type ( ty) => {
409- self . type_must_outlive ( origin. clone ( ) , ty, region, constraint) ;
410- }
411- GenericArgKind :: Const ( _) => {
412- // Const parameters don't impose constraints.
413- }
414- }
415- }
442+ let needs_infer = substs. needs_infer ( ) ;
443+ if approx_env_bounds. is_empty ( ) && trait_bounds. is_empty ( ) && ( needs_infer || is_opaque) {
444+ debug ! ( "no declared bounds" ) ;
445+
446+ self . substs_must_outlive ( substs, origin, region) ;
416447
417448 return ;
418449 }
@@ -442,8 +473,8 @@ where
442473 . all ( |b| b == Some ( trait_bounds[ 0 ] ) )
443474 {
444475 let unique_bound = trait_bounds[ 0 ] ;
445- debug ! ( "projection_must_outlive: unique trait bound = {:?}" , unique_bound) ;
446- debug ! ( "projection_must_outlive: unique declared bound appears in trait ref" ) ;
476+ debug ! ( ? unique_bound) ;
477+ debug ! ( "unique declared bound appears in trait ref" ) ;
447478 let category = origin. to_constraint_category ( ) ;
448479 self . delegate . push_sub_region_constraint ( origin, region, unique_bound, category) ;
449480 return ;
@@ -454,11 +485,42 @@ where
454485 // projection outlive; in some cases, this may add insufficient
455486 // edges into the inference graph, leading to inference failures
456487 // even though a satisfactory solution exists.
457- let generic = GenericKind :: Projection ( projection_ty) ;
458- let verify_bound = self . verify_bound . generic_bound ( generic) ;
488+ let verify_bound = self . verify_bound . projection_opaque_bounds (
489+ generic,
490+ def_id,
491+ substs,
492+ & mut Default :: default ( ) ,
493+ ) ;
459494 debug ! ( "projection_must_outlive: pushing {:?}" , verify_bound) ;
460495 self . delegate . push_verify ( origin, generic, region, verify_bound) ;
461496 }
497+
498+ fn substs_must_outlive (
499+ & mut self ,
500+ substs : SubstsRef < ' tcx > ,
501+ origin : infer:: SubregionOrigin < ' tcx > ,
502+ region : ty:: Region < ' tcx > ,
503+ ) {
504+ let constraint = origin. to_constraint_category ( ) ;
505+ for k in substs {
506+ match k. unpack ( ) {
507+ GenericArgKind :: Lifetime ( lt) => {
508+ self . delegate . push_sub_region_constraint (
509+ origin. clone ( ) ,
510+ region,
511+ lt,
512+ constraint,
513+ ) ;
514+ }
515+ GenericArgKind :: Type ( ty) => {
516+ self . type_must_outlive ( origin. clone ( ) , ty, region, constraint) ;
517+ }
518+ GenericArgKind :: Const ( _) => {
519+ // Const parameters don't impose constraints.
520+ }
521+ }
522+ }
523+ }
462524}
463525
464526impl < ' cx , ' tcx > TypeOutlivesDelegate < ' tcx > for & ' cx InferCtxt < ' cx , ' tcx > {
0 commit comments