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