11use rustc_data_structures:: fx:: FxHashSet ;
2+ use rustc_hir:: intravisit:: Visitor ;
23use rustc_hir:: { def:: DefKind , def_id:: LocalDefId } ;
4+ use rustc_hir:: { intravisit, CRATE_HIR_ID } ;
35use rustc_middle:: query:: Providers ;
46use rustc_middle:: ty:: util:: { CheckRegions , NotUniqueParam } ;
57use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
@@ -51,7 +53,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
5153
5254 fn parent ( & self ) -> Option < LocalDefId > {
5355 match self . tcx . def_kind ( self . item ) {
54- DefKind :: Fn => None ,
56+ DefKind :: AnonConst | DefKind :: InlineConst | DefKind :: Fn | DefKind :: TyAlias => None ,
5557 DefKind :: AssocFn | DefKind :: AssocTy | DefKind :: AssocConst => {
5658 Some ( self . tcx . local_parent ( self . item ) )
5759 }
@@ -61,6 +63,73 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
6163 ) ,
6264 }
6365 }
66+
67+ /// Returns `true` if `opaque_hir_id` is a sibling or a child of a sibling of `self.item`.
68+ ///
69+ /// Example:
70+ /// ```ignore UNSOLVED (is this a bug?)
71+ /// # #![feature(type_alias_impl_trait)]
72+ /// pub mod foo {
73+ /// pub mod bar {
74+ /// pub trait Bar { /* ... */ }
75+ /// pub type Baz = impl Bar;
76+ ///
77+ /// # impl Bar for () {}
78+ /// fn f1() -> Baz { /* ... */ }
79+ /// }
80+ /// fn f2() -> bar::Baz { /* ... */ }
81+ /// }
82+ /// ```
83+ ///
84+ /// and `opaque_def_id` is the `DefId` of the definition of the opaque type `Baz`.
85+ /// For the above example, this function returns `true` for `f1` and `false` for `f2`.
86+ #[ instrument( level = "trace" , skip( self ) , ret) ]
87+ fn check_tait_defining_scope ( & self , opaque_def_id : LocalDefId ) -> bool {
88+ let mut hir_id = self . tcx . hir ( ) . local_def_id_to_hir_id ( self . item ) ;
89+ let opaque_hir_id = self . tcx . hir ( ) . local_def_id_to_hir_id ( opaque_def_id) ;
90+
91+ // Named opaque types can be defined by any siblings or children of siblings.
92+ let scope = self . tcx . hir ( ) . get_defining_scope ( opaque_hir_id) ;
93+ // We walk up the node tree until we hit the root or the scope of the opaque type.
94+ while hir_id != scope && hir_id != CRATE_HIR_ID {
95+ hir_id = self . tcx . hir ( ) . get_parent_item ( hir_id) . into ( ) ;
96+ }
97+ // Syntactically, we are allowed to define the concrete type if:
98+ hir_id == scope
99+ }
100+
101+ fn collect_body_and_predicate_taits ( & mut self ) {
102+ // Look at all where bounds.
103+ self . tcx . predicates_of ( self . item ) . instantiate_identity ( self . tcx ) . visit_with ( self ) ;
104+ // An item is allowed to constrain opaques declared within its own body (but not nested within
105+ // nested functions).
106+ self . collect_taits_declared_in_body ( ) ;
107+ }
108+
109+ #[ instrument( level = "trace" , skip( self ) ) ]
110+ fn collect_taits_declared_in_body ( & mut self ) {
111+ let body = self . tcx . hir ( ) . body ( self . tcx . hir ( ) . body_owned_by ( self . item ) ) . value ;
112+ struct TaitInBodyFinder < ' a , ' tcx > {
113+ collector : & ' a mut OpaqueTypeCollector < ' tcx > ,
114+ }
115+ impl < ' v > intravisit:: Visitor < ' v > for TaitInBodyFinder < ' _ , ' _ > {
116+ #[ instrument( level = "trace" , skip( self ) ) ]
117+ fn visit_nested_item ( & mut self , id : rustc_hir:: ItemId ) {
118+ let id = id. owner_id . def_id ;
119+ if let DefKind :: TyAlias = self . collector . tcx . def_kind ( id) {
120+ let items = self . collector . tcx . opaque_types_defined_by ( id) ;
121+ self . collector . opaques . extend ( items) ;
122+ }
123+ }
124+ #[ instrument( level = "trace" , skip( self ) ) ]
125+ // Recurse into these, as they are type checked with their parent
126+ fn visit_nested_body ( & mut self , id : rustc_hir:: BodyId ) {
127+ let body = self . collector . tcx . hir ( ) . body ( id) ;
128+ self . visit_body ( body) ;
129+ }
130+ }
131+ TaitInBodyFinder { collector : self } . visit_expr ( body) ;
132+ }
64133}
65134
66135impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for OpaqueTypeCollector < ' tcx > {
@@ -73,6 +142,21 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
73142 return ControlFlow :: Continue ( ( ) ) ;
74143 }
75144
145+ // TAITs outside their defining scopes are ignored.
146+ let origin = self . tcx . opaque_type_origin ( alias_ty. def_id . expect_local ( ) ) ;
147+ trace ! ( ?origin) ;
148+ match origin {
149+ rustc_hir:: OpaqueTyOrigin :: FnReturn ( _)
150+ | rustc_hir:: OpaqueTyOrigin :: AsyncFn ( _) => { }
151+ rustc_hir:: OpaqueTyOrigin :: TyAlias { in_assoc_ty } => {
152+ if !in_assoc_ty {
153+ if !self . check_tait_defining_scope ( alias_ty. def_id . expect_local ( ) ) {
154+ return ControlFlow :: Continue ( ( ) ) ;
155+ }
156+ }
157+ }
158+ }
159+
76160 self . opaques . push ( alias_ty. def_id . expect_local ( ) ) ;
77161
78162 match self . tcx . uses_unique_generic_params ( alias_ty. substs , CheckRegions :: Bound ) {
@@ -188,65 +272,63 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
188272fn opaque_types_defined_by < ' tcx > ( tcx : TyCtxt < ' tcx > , item : LocalDefId ) -> & ' tcx [ LocalDefId ] {
189273 let kind = tcx. def_kind ( item) ;
190274 trace ! ( ?kind) ;
191- // FIXME(type_alias_impl_trait): This is definitely still wrong except for RPIT and impl trait in assoc types.
275+ let mut collector = OpaqueTypeCollector :: new ( tcx , item ) ;
192276 match kind {
277+ // Walk over the signature of the function-like to find the opaques.
278+ DefKind :: AssocFn | DefKind :: Fn => {
279+ let ty_sig = tcx. fn_sig ( item) . subst_identity ( ) ;
280+ let hir_sig = tcx. hir ( ) . get_by_def_id ( item) . fn_sig ( ) . unwrap ( ) ;
281+ // Walk over the inputs and outputs manually in order to get good spans for them.
282+ collector. visit_spanned ( hir_sig. decl . output . span ( ) , ty_sig. output ( ) ) ;
283+ for ( hir, ty) in hir_sig. decl . inputs . iter ( ) . zip ( ty_sig. inputs ( ) . iter ( ) ) {
284+ collector. visit_spanned ( hir. span , ty. map_bound ( |x| * x) ) ;
285+ }
286+ collector. collect_body_and_predicate_taits ( ) ;
287+ }
288+ // Walk over the type of the item to find opaques.
289+ DefKind :: Static ( _) | DefKind :: Const | DefKind :: AssocConst | DefKind :: AnonConst => {
290+ let span = match tcx. hir ( ) . get_by_def_id ( item) . ty ( ) {
291+ Some ( ty) => ty. span ,
292+ _ => tcx. def_span ( item) ,
293+ } ;
294+ collector. visit_spanned ( span, tcx. type_of ( item) . subst_identity ( ) ) ;
295+ collector. collect_body_and_predicate_taits ( ) ;
296+ }
193297 // We're also doing this for `AssocTy` for the wf checks in `check_opaque_meets_bounds`
194- DefKind :: Fn | DefKind :: AssocFn | DefKind :: AssocTy | DefKind :: AssocConst => {
195- let mut collector = OpaqueTypeCollector :: new ( tcx, item) ;
196- match kind {
197- // Walk over the signature of the function-like to find the opaques.
198- DefKind :: AssocFn | DefKind :: Fn => {
199- let ty_sig = tcx. fn_sig ( item) . subst_identity ( ) ;
200- let hir_sig = tcx. hir ( ) . get_by_def_id ( item) . fn_sig ( ) . unwrap ( ) ;
201- // Walk over the inputs and outputs manually in order to get good spans for them.
202- collector. visit_spanned ( hir_sig. decl . output . span ( ) , ty_sig. output ( ) ) ;
203- for ( hir, ty) in hir_sig. decl . inputs . iter ( ) . zip ( ty_sig. inputs ( ) . iter ( ) ) {
204- collector. visit_spanned ( hir. span , ty. map_bound ( |x| * x) ) ;
205- }
206- }
207- // Walk over the type of the item to find opaques.
208- DefKind :: AssocTy | DefKind :: AssocConst => {
209- let span = match tcx. hir ( ) . get_by_def_id ( item) . ty ( ) {
210- Some ( ty) => ty. span ,
211- _ => tcx. def_span ( item) ,
212- } ;
213- collector. visit_spanned ( span, tcx. type_of ( item) . subst_identity ( ) ) ;
214- }
215- _ => unreachable ! ( ) ,
298+ DefKind :: TyAlias | DefKind :: AssocTy => {
299+ tcx. type_of ( item) . subst_identity ( ) . visit_with ( & mut collector) ;
300+ }
301+ DefKind :: OpaqueTy => {
302+ for ( pred, span) in tcx. explicit_item_bounds ( item) . subst_identity_iter_copied ( ) {
303+ collector. visit_spanned ( span, pred) ;
216304 }
217- tcx. arena . alloc_from_iter ( collector. opaques )
218305 }
219306 DefKind :: Mod
220307 | DefKind :: Struct
221308 | DefKind :: Union
222309 | DefKind :: Enum
223310 | DefKind :: Variant
224311 | DefKind :: Trait
225- | DefKind :: TyAlias
226312 | DefKind :: ForeignTy
227313 | DefKind :: TraitAlias
228314 | DefKind :: TyParam
229- | DefKind :: Const
230315 | DefKind :: ConstParam
231- | DefKind :: Static ( _)
232316 | DefKind :: Ctor ( _, _)
233317 | DefKind :: Macro ( _)
234318 | DefKind :: ExternCrate
235319 | DefKind :: Use
236320 | DefKind :: ForeignMod
237- | DefKind :: AnonConst
238- | DefKind :: InlineConst
239- | DefKind :: OpaqueTy
240321 | DefKind :: ImplTraitPlaceholder
241322 | DefKind :: Field
242323 | DefKind :: LifetimeParam
243324 | DefKind :: GlobalAsm
244- | DefKind :: Impl { .. }
245- | DefKind :: Closure
246- | DefKind :: Generator => {
247- span_bug ! ( tcx. def_span ( item) , "{kind:?} is type checked as part of its parent" )
325+ | DefKind :: Impl { .. } => { }
326+ // Closures and generators are type checked with their parent, so there is no difference here.
327+ DefKind :: Closure | DefKind :: Generator | DefKind :: InlineConst => {
328+ return tcx . opaque_types_defined_by ( tcx. local_parent ( item) ) ;
248329 }
249330 }
331+ tcx. arena . alloc_from_iter ( collector. opaques )
250332}
251333
252334pub ( super ) fn provide ( providers : & mut Providers ) {
0 commit comments