@@ -93,6 +93,18 @@ pub struct OpaqueTypeDecl<'tcx> {
93
93
pub origin : hir:: OpaqueTyOrigin ,
94
94
}
95
95
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
+
96
108
impl < ' a , ' tcx > InferCtxt < ' a , ' tcx > {
97
109
/// Replaces all opaque types in `value` with fresh inference variables
98
110
/// and creates appropriate obligations. For example, given the input:
@@ -315,7 +327,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
315
327
debug ! ( "constrain_opaque_types()" ) ;
316
328
317
329
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
+ ) ;
319
336
}
320
337
}
321
338
@@ -324,6 +341,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
324
341
& self ,
325
342
def_id : DefId ,
326
343
opaque_defn : & OpaqueTypeDecl < ' tcx > ,
344
+ mode : GenerateMemberConstraints ,
327
345
free_region_relations : & FRR ,
328
346
) {
329
347
debug ! ( "constrain_opaque_type()" ) ;
@@ -358,6 +376,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
358
376
op : |r| self . sub_regions ( infer:: CallReturn ( span) , required_region, r) ,
359
377
} ) ;
360
378
}
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
+ }
361
387
return ;
362
388
}
363
389
@@ -398,13 +424,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
398
424
// we will create a "in bound" like `'r in
399
425
// ['a, 'b, 'c]`, where `'a..'c` are the
400
426
// 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
+
401
431
return self . generate_member_constraint (
402
432
concrete_ty,
403
433
opaque_type_generics,
404
434
opaque_defn,
405
435
def_id,
406
- lr,
407
- subst_arg,
408
436
) ;
409
437
}
410
438
}
@@ -414,6 +442,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
414
442
let least_region = least_region. unwrap_or ( tcx. lifetimes . re_static ) ;
415
443
debug ! ( "constrain_opaque_types: least_region={:?}" , least_region) ;
416
444
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
+ }
417
455
concrete_ty. visit_with ( & mut ConstrainOpaqueTypeRegionVisitor {
418
456
tcx : self . tcx ,
419
457
op : |r| self . sub_regions ( infer:: CallReturn ( span) , least_region, r) ,
@@ -434,19 +472,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
434
472
opaque_type_generics : & ty:: Generics ,
435
473
opaque_defn : & OpaqueTypeDecl < ' tcx > ,
436
474
opaque_type_def_id : DefId ,
437
- conflict1 : ty:: Region < ' tcx > ,
438
- conflict2 : ty:: Region < ' tcx > ,
439
475
) {
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
-
450
476
// Create the set of choice regions: each region in the hidden
451
477
// type can be equal to any of the region parameters of the
452
478
// opaque type definition.
@@ -500,8 +526,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
500
526
hir:: OpaqueTyOrigin :: AsyncFn => return false ,
501
527
502
528
// Otherwise, generate the label we'll use in the error message.
503
- hir:: OpaqueTyOrigin :: TypeAlias => "impl Trait" ,
504
- hir:: OpaqueTyOrigin :: FnReturn => "impl Trait" ,
529
+ hir:: OpaqueTyOrigin :: TypeAlias
530
+ | hir:: OpaqueTyOrigin :: FnReturn
531
+ | hir:: OpaqueTyOrigin :: Misc => "impl Trait" ,
505
532
} ;
506
533
let msg = format ! ( "ambiguous lifetime bound in `{}`" , context_name) ;
507
534
let mut err = self . tcx . sess . struct_span_err ( span, & msg) ;
@@ -549,13 +576,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
549
576
/// # Parameters
550
577
///
551
578
/// - `def_id`, the `impl Trait` type
552
- /// - `opaque_defn `, the opaque definition created in `instantiate_opaque_types`
579
+ /// - `substs `, the substs used to instantiate this opaque type
553
580
/// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of
554
581
/// `opaque_defn.concrete_ty`
555
582
pub fn infer_opaque_definition_from_instantiation (
556
583
& self ,
557
584
def_id : DefId ,
558
- opaque_defn : & OpaqueTypeDecl < ' tcx > ,
585
+ substs : SubstsRef < ' tcx > ,
559
586
instantiated_ty : Ty < ' tcx > ,
560
587
span : Span ,
561
588
) -> Ty < ' tcx > {
@@ -571,12 +598,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
571
598
// `impl Trait` return type, resulting in the parameters
572
599
// shifting.
573
600
let id_substs = InternalSubsts :: identity_for_item ( self . tcx , def_id) ;
574
- let map: FxHashMap < GenericArg < ' tcx > , GenericArg < ' tcx > > = opaque_defn
575
- . substs
576
- . iter ( )
577
- . enumerate ( )
578
- . map ( |( index, subst) | ( * subst, id_substs[ index] ) )
579
- . collect ( ) ;
601
+ let map: FxHashMap < GenericArg < ' tcx > , GenericArg < ' tcx > > =
602
+ substs. iter ( ) . enumerate ( ) . map ( |( index, subst) | ( * subst, id_substs[ index] ) ) . collect ( ) ;
580
603
581
604
// Convert the type from the function into a type valid outside
582
605
// the function, by replacing invalid regions with 'static,
@@ -598,11 +621,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
598
621
pub fn unexpected_hidden_region_diagnostic (
599
622
tcx : TyCtxt < ' tcx > ,
600
623
region_scope_tree : Option < & region:: ScopeTree > ,
601
- opaque_type_def_id : DefId ,
624
+ span : Span ,
602
625
hidden_ty : Ty < ' tcx > ,
603
626
hidden_region : ty:: Region < ' tcx > ,
604
627
) -> DiagnosticBuilder < ' tcx > {
605
- let span = tcx. def_span ( opaque_type_def_id) ;
606
628
let mut err = struct_span_err ! (
607
629
tcx. sess,
608
630
span,
@@ -817,32 +839,48 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
817
839
818
840
fn fold_region ( & mut self , r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
819
841
match r {
820
- // ignore bound regions that appear in the type (e.g., this
821
- // would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
822
- ty:: ReLateBound ( ..) |
823
-
824
- // ignore `'static`, as that can appear anywhere
825
- ty:: ReStatic => return r,
826
-
827
- _ => { }
842
+ // Ignore bound regions and `'static` regions that appear in the
843
+ // type, we only need to remap regions that reference lifetimes
844
+ // from the function declaraion.
845
+ // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
846
+ ty:: ReLateBound ( ..) | ty:: ReStatic => return r,
847
+
848
+ // If regions have been erased (by writeback), don't try to unerase
849
+ // them.
850
+ ty:: ReErased => return r,
851
+
852
+ // The regions that we expect from borrow checking.
853
+ ty:: ReEarlyBound ( _) | ty:: ReFree ( _) | ty:: ReEmpty ( ty:: UniverseIndex :: ROOT ) => { }
854
+
855
+ ty:: ReEmpty ( _)
856
+ | ty:: RePlaceholder ( _)
857
+ | ty:: ReVar ( _)
858
+ | ty:: ReScope ( _)
859
+ | ty:: ReClosureBound ( _) => {
860
+ // All of the regions in the type should either have been
861
+ // erased by writeback, or mapped back to named regions by
862
+ // borrow checking.
863
+ bug ! ( "unexpected region kind in opaque type: {:?}" , r) ;
864
+ }
828
865
}
829
866
830
867
let generics = self . tcx ( ) . generics_of ( self . opaque_type_def_id ) ;
831
868
match self . map . get ( & r. into ( ) ) . map ( |k| k. unpack ( ) ) {
832
869
Some ( GenericArgKind :: Lifetime ( r1) ) => r1,
833
870
Some ( u) => panic ! ( "region mapped to unexpected kind: {:?}" , u) ,
871
+ None if self . map_missing_regions_to_empty || self . tainted_by_errors => {
872
+ self . tcx . lifetimes . re_root_empty
873
+ }
834
874
None if generics. parent . is_some ( ) => {
835
- if !self . map_missing_regions_to_empty && !self . tainted_by_errors {
836
- if let Some ( hidden_ty) = self . hidden_ty . take ( ) {
837
- unexpected_hidden_region_diagnostic (
838
- self . tcx ,
839
- None ,
840
- self . opaque_type_def_id ,
841
- hidden_ty,
842
- r,
843
- )
844
- . emit ( ) ;
845
- }
875
+ if let Some ( hidden_ty) = self . hidden_ty . take ( ) {
876
+ unexpected_hidden_region_diagnostic (
877
+ self . tcx ,
878
+ None ,
879
+ self . tcx . def_span ( self . opaque_type_def_id ) ,
880
+ hidden_ty,
881
+ r,
882
+ )
883
+ . emit ( ) ;
846
884
}
847
885
self . tcx . lifetimes . re_root_empty
848
886
}
@@ -860,7 +898,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
860
898
)
861
899
. emit ( ) ;
862
900
863
- self . tcx ( ) . mk_region ( ty :: ReStatic )
901
+ self . tcx ( ) . lifetimes . re_static
864
902
}
865
903
}
866
904
}
0 commit comments