1
+ use rustc_data_structures:: fx:: FxHashMap ;
1
2
use rustc_data_structures:: vec_map:: VecMap ;
3
+ use rustc_hir:: OpaqueTyOrigin ;
4
+ use rustc_infer:: infer:: opaque_types:: OpaqueTypeDecl ;
2
5
use rustc_infer:: infer:: InferCtxt ;
6
+ use rustc_middle:: ty:: subst:: GenericArgKind ;
3
7
use rustc_middle:: ty:: { self , OpaqueTypeKey , Ty , TyCtxt , TypeFoldable } ;
4
8
use rustc_span:: Span ;
5
9
use rustc_trait_selection:: opaque_types:: InferCtxtExt ;
@@ -50,13 +54,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
50
54
pub ( crate ) fn infer_opaque_types (
51
55
& self ,
52
56
infcx : & InferCtxt < ' _ , ' tcx > ,
53
- opaque_ty_decls : VecMap < OpaqueTypeKey < ' tcx > , Ty < ' tcx > > ,
57
+ opaque_ty_decls : VecMap < OpaqueTypeKey < ' tcx > , OpaqueTypeDecl < ' tcx > > ,
54
58
span : Span ,
55
59
) -> VecMap < OpaqueTypeKey < ' tcx > , Ty < ' tcx > > {
56
60
opaque_ty_decls
57
61
. into_iter ( )
58
- . map ( |( opaque_type_key, concrete_type ) | {
62
+ . filter_map ( |( opaque_type_key, decl ) | {
59
63
let substs = opaque_type_key. substs ;
64
+ let concrete_type = decl. concrete_ty ;
60
65
debug ! ( ?concrete_type, ?substs) ;
61
66
62
67
let mut subst_regions = vec ! [ self . universal_regions. fr_static] ;
@@ -94,7 +99,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
94
99
universal_concrete_type,
95
100
span,
96
101
) ;
97
- ( opaque_type_key, remapped_type)
102
+
103
+ check_opaque_type_parameter_valid (
104
+ infcx. tcx ,
105
+ opaque_type_key,
106
+ OpaqueTypeDecl { concrete_ty : remapped_type, ..decl } ,
107
+ )
108
+ . then_some ( ( opaque_type_key, remapped_type) )
98
109
} )
99
110
. collect ( )
100
111
}
@@ -119,3 +130,95 @@ impl<'tcx> RegionInferenceContext<'tcx> {
119
130
} )
120
131
}
121
132
}
133
+
134
+ fn check_opaque_type_parameter_valid (
135
+ tcx : TyCtxt < ' _ > ,
136
+ opaque_type_key : OpaqueTypeKey < ' _ > ,
137
+ decl : OpaqueTypeDecl < ' _ > ,
138
+ ) -> bool {
139
+ match decl. origin {
140
+ // No need to check return position impl trait (RPIT)
141
+ // because for type and const parameters they are correct
142
+ // by construction: we convert
143
+ //
144
+ // fn foo<P0..Pn>() -> impl Trait
145
+ //
146
+ // into
147
+ //
148
+ // type Foo<P0...Pn>
149
+ // fn foo<P0..Pn>() -> Foo<P0...Pn>.
150
+ //
151
+ // For lifetime parameters we convert
152
+ //
153
+ // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
154
+ //
155
+ // into
156
+ //
157
+ // type foo::<'p0..'pn>::Foo<'q0..'qm>
158
+ // fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
159
+ //
160
+ // which would error here on all of the `'static` args.
161
+ OpaqueTyOrigin :: FnReturn | OpaqueTyOrigin :: AsyncFn => return true ,
162
+ // Check these
163
+ OpaqueTyOrigin :: TyAlias => { }
164
+ }
165
+ let span = decl. definition_span ;
166
+ let opaque_generics = tcx. generics_of ( opaque_type_key. def_id ) ;
167
+ let mut seen_params: FxHashMap < _ , Vec < _ > > = FxHashMap :: default ( ) ;
168
+ for ( i, arg) in opaque_type_key. substs . iter ( ) . enumerate ( ) {
169
+ let arg_is_param = match arg. unpack ( ) {
170
+ GenericArgKind :: Type ( ty) => matches ! ( ty. kind( ) , ty:: Param ( _) ) ,
171
+ GenericArgKind :: Lifetime ( ty:: ReStatic ) => {
172
+ tcx. sess
173
+ . struct_span_err ( span, "non-defining opaque type use in defining scope" )
174
+ . span_label (
175
+ tcx. def_span ( opaque_generics. param_at ( i, tcx) . def_id ) ,
176
+ "cannot use static lifetime; use a bound lifetime \
177
+ instead or remove the lifetime parameter from the \
178
+ opaque type",
179
+ )
180
+ . emit ( ) ;
181
+ return false ;
182
+ }
183
+ GenericArgKind :: Lifetime ( lt) => {
184
+ matches ! ( lt, ty:: ReEarlyBound ( _) | ty:: ReFree ( _) )
185
+ }
186
+ GenericArgKind :: Const ( ct) => matches ! ( ct. val, ty:: ConstKind :: Param ( _) ) ,
187
+ } ;
188
+
189
+ if arg_is_param {
190
+ seen_params. entry ( arg) . or_default ( ) . push ( i) ;
191
+ } else {
192
+ // Prevent `fn foo() -> Foo<u32>` from being defining.
193
+ let opaque_param = opaque_generics. param_at ( i, tcx) ;
194
+ tcx. sess
195
+ . struct_span_err ( span, "non-defining opaque type use in defining scope" )
196
+ . span_note (
197
+ tcx. def_span ( opaque_param. def_id ) ,
198
+ & format ! (
199
+ "used non-generic {} `{}` for generic parameter" ,
200
+ opaque_param. kind. descr( ) ,
201
+ arg,
202
+ ) ,
203
+ )
204
+ . emit ( ) ;
205
+ return false ;
206
+ }
207
+ }
208
+
209
+ for ( _, indices) in seen_params {
210
+ if indices. len ( ) > 1 {
211
+ let descr = opaque_generics. param_at ( indices[ 0 ] , tcx) . kind . descr ( ) ;
212
+ let spans: Vec < _ > = indices
213
+ . into_iter ( )
214
+ . map ( |i| tcx. def_span ( opaque_generics. param_at ( i, tcx) . def_id ) )
215
+ . collect ( ) ;
216
+ tcx. sess
217
+ . struct_span_err ( span, "non-defining opaque type use in defining scope" )
218
+ . span_note ( spans, & format ! ( "{} used multiple times" , descr) )
219
+ . emit ( ) ;
220
+ return false ;
221
+ }
222
+ }
223
+ true
224
+ }
0 commit comments