1+ use rustc_data_structures:: fx:: FxHashMap ;
12use rustc_data_structures:: vec_map:: VecMap ;
3+ use rustc_hir:: OpaqueTyOrigin ;
4+ use rustc_infer:: infer:: opaque_types:: OpaqueTypeDecl ;
25use rustc_infer:: infer:: InferCtxt ;
6+ use rustc_middle:: ty:: subst:: GenericArgKind ;
37use rustc_middle:: ty:: { self , OpaqueTypeKey , Ty , TyCtxt , TypeFoldable } ;
48use rustc_span:: Span ;
59use rustc_trait_selection:: opaque_types:: InferCtxtExt ;
@@ -50,13 +54,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
5054 pub ( crate ) fn infer_opaque_types (
5155 & self ,
5256 infcx : & InferCtxt < ' _ , ' tcx > ,
53- opaque_ty_decls : VecMap < OpaqueTypeKey < ' tcx > , Ty < ' tcx > > ,
57+ opaque_ty_decls : VecMap < OpaqueTypeKey < ' tcx > , OpaqueTypeDecl < ' tcx > > ,
5458 span : Span ,
5559 ) -> VecMap < OpaqueTypeKey < ' tcx > , Ty < ' tcx > > {
5660 opaque_ty_decls
5761 . into_iter ( )
58- . map ( |( opaque_type_key, concrete_type ) | {
62+ . filter_map ( |( opaque_type_key, decl ) | {
5963 let substs = opaque_type_key. substs ;
64+ let concrete_type = decl. concrete_ty ;
6065 debug ! ( ?concrete_type, ?substs) ;
6166
6267 let mut subst_regions = vec ! [ self . universal_regions. fr_static] ;
@@ -94,7 +99,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
9499 universal_concrete_type,
95100 span,
96101 ) ;
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) )
98109 } )
99110 . collect ( )
100111 }
@@ -119,3 +130,95 @@ impl<'tcx> RegionInferenceContext<'tcx> {
119130 } )
120131 }
121132}
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