@@ -8,17 +8,75 @@ use rustc_infer::infer::TyCtxtInferExt as _;
8
8
use rustc_infer:: traits:: { Obligation , ObligationCause } ;
9
9
use rustc_middle:: traits:: DefiningAnchor ;
10
10
use rustc_middle:: ty:: visit:: TypeVisitableExt ;
11
+ use rustc_middle:: ty:: RegionVid ;
11
12
use rustc_middle:: ty:: { self , OpaqueHiddenType , OpaqueTypeKey , Ty , TyCtxt , TypeFoldable } ;
12
13
use rustc_middle:: ty:: { GenericArgKind , GenericArgs } ;
13
14
use rustc_span:: Span ;
14
15
use rustc_trait_selection:: traits:: error_reporting:: TypeErrCtxtExt as _;
15
16
use rustc_trait_selection:: traits:: ObligationCtxt ;
16
17
18
+ use crate :: session_diagnostics:: LifetimeMismatchOpaqueParam ;
17
19
use crate :: session_diagnostics:: NonGenericOpaqueTypeParam ;
18
20
19
21
use super :: RegionInferenceContext ;
20
22
21
23
impl < ' tcx > RegionInferenceContext < ' tcx > {
24
+ fn universal_name ( & self , vid : ty:: RegionVid ) -> Option < ty:: Region < ' tcx > > {
25
+ let scc = self . constraint_sccs . scc ( vid) ;
26
+ self . scc_values
27
+ . universal_regions_outlived_by ( scc)
28
+ . find_map ( |lb| self . eval_equal ( vid, lb) . then_some ( self . definitions [ lb] . external_name ?) )
29
+ }
30
+
31
+ fn generic_arg_to_region ( & self , arg : ty:: GenericArg < ' tcx > ) -> Option < RegionVid > {
32
+ let region = arg. as_region ( ) ?;
33
+
34
+ if let ty:: RePlaceholder ( ..) = region. kind ( ) {
35
+ None
36
+ } else {
37
+ Some ( self . to_region_vid ( region) )
38
+ }
39
+ }
40
+
41
+ /// Check that all opaque types have the same region parameters if they have the same
42
+ /// non-region parameters. This is necessary because within the new solver we perform various query operations
43
+ /// modulo regions, and thus could unsoundly select some impls that don't hold.
44
+ fn check_unique (
45
+ & self ,
46
+ infcx : & InferCtxt < ' tcx > ,
47
+ opaque_ty_decls : & FxIndexMap < OpaqueTypeKey < ' tcx > , OpaqueHiddenType < ' tcx > > ,
48
+ ) {
49
+ for ( i, ( a, a_ty) ) in opaque_ty_decls. iter ( ) . enumerate ( ) {
50
+ for ( b, b_ty) in opaque_ty_decls. iter ( ) . skip ( i + 1 ) {
51
+ if a. def_id != b. def_id {
52
+ continue ;
53
+ }
54
+ // Non-lifetime params differ -> ok
55
+ if infcx. tcx . erase_regions ( a. args ) != infcx. tcx . erase_regions ( b. args ) {
56
+ continue ;
57
+ }
58
+ trace ! ( ?a, ?b) ;
59
+ for ( a, b) in a. args . iter ( ) . zip ( b. args ) {
60
+ trace ! ( ?a, ?b) ;
61
+ let Some ( r1) = self . generic_arg_to_region ( a) else {
62
+ continue ;
63
+ } ;
64
+ let r2 = self . generic_arg_to_region ( b) . unwrap ( ) ;
65
+ if self . eval_equal ( r1, r2) {
66
+ continue ;
67
+ }
68
+
69
+ infcx. tcx . sess . emit_err ( LifetimeMismatchOpaqueParam {
70
+ arg : self . universal_name ( r1) . unwrap ( ) . into ( ) ,
71
+ prev : self . universal_name ( r2) . unwrap ( ) . into ( ) ,
72
+ span : a_ty. span ,
73
+ prev_span : b_ty. span ,
74
+ } ) ;
75
+ }
76
+ }
77
+ }
78
+ }
79
+
22
80
/// Resolve any opaque types that were encountered while borrow checking
23
81
/// this item. This is then used to get the type in the `type_of` query.
24
82
///
@@ -64,6 +122,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
64
122
infcx : & InferCtxt < ' tcx > ,
65
123
opaque_ty_decls : FxIndexMap < OpaqueTypeKey < ' tcx > , OpaqueHiddenType < ' tcx > > ,
66
124
) -> FxIndexMap < LocalDefId , OpaqueHiddenType < ' tcx > > {
125
+ self . check_unique ( infcx, & opaque_ty_decls) ;
126
+
67
127
let mut result: FxIndexMap < LocalDefId , OpaqueHiddenType < ' tcx > > = FxIndexMap :: default ( ) ;
68
128
69
129
let member_constraints: FxIndexMap < _ , _ > = self
@@ -79,13 +139,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
79
139
80
140
let mut subst_regions = vec ! [ self . universal_regions. fr_static] ;
81
141
82
- let to_universal_region = |vid, subst_regions : & mut Vec < _ > | {
83
- trace ! ( ?vid) ;
84
- let scc = self . constraint_sccs . scc ( vid) ;
85
- trace ! ( ?scc) ;
86
- match self . scc_values . universal_regions_outlived_by ( scc) . find_map ( |lb| {
87
- self . eval_equal ( vid, lb) . then_some ( self . definitions [ lb] . external_name ?)
88
- } ) {
142
+ let to_universal_region =
143
+ |vid, subst_regions : & mut Vec < _ > | match self . universal_name ( vid) {
89
144
Some ( region) => {
90
145
let vid = self . universal_regions . to_region_vid ( region) ;
91
146
subst_regions. push ( vid) ;
@@ -99,8 +154,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
99
154
"opaque type with non-universal region args" ,
100
155
)
101
156
}
102
- }
103
- } ;
157
+ } ;
104
158
105
159
// Start by inserting universal regions from the member_constraint choice regions.
106
160
// This will ensure they get precedence when folding the regions in the concrete type.
0 commit comments