@@ -900,6 +900,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
900
900
self . tcx . parent ( def_id) ,
901
901
& path. segments [ ..path. segments . len ( ) - 1 ] ,
902
902
) ) ,
903
+ // FIXME(mgca): @fmease thinks we also need to handle AssocConsts here.
903
904
_ => None ,
904
905
} ;
905
906
let object_lifetime_defaults =
@@ -914,17 +915,27 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
914
915
}
915
916
}
916
917
}
917
- hir:: QPath :: TypeRelative ( qself, segment) => {
918
- // Resolving object lifetime defaults for type-relative paths requires full
919
- // type-dependent resolution as performed by HIR ty lowering whose results
920
- // we don't have access to (and we'd results for both FnCtxts and ItemCtxts).
921
- // FIXME: Figure out if there's a feasible way to obtain the map of
922
- // type-dependent definitions.
918
+ & hir:: QPath :: TypeRelative ( qself, segment) => {
919
+ if let Some ( args) = segment. args {
920
+ // FIXME(mgca): @fmease thinks we also need to handle AssocConsts here.
921
+ let container = self
922
+ . limited_resolve_type_relative_path (
923
+ ty:: AssocTag :: Type ,
924
+ qself,
925
+ segment,
926
+ true ,
927
+ )
928
+ . map ( |( _, assoc_item) | ( assoc_item. def_id , std:: slice:: from_ref ( segment) ) ) ;
929
+ self . visit_segment_args ( container, args) ;
930
+ }
931
+
932
+ // For forward compatibility we reject elided object lifetimes in the self type as
933
+ // "indeterminate" by passing `None`. `limited_resolve_type_relative_path` is not
934
+ // complete compared to HIR ty lowering's `lower_assoc_path_shared`, so we need to
935
+ // be conservative. Consider paths like `<dyn Trait>::X` which may resolve in the
936
+ // future (under IATs or mGCA (IACs)).
923
937
let scope = Scope :: ObjectLifetimeDefault { lifetime : None , s : self . scope } ;
924
- self . with ( scope, |this| {
925
- this. visit_ty_unambig ( qself) ;
926
- this. visit_path_segment ( segment)
927
- } ) ;
938
+ self . with ( scope, |this| this. visit_ty_unambig ( qself) ) ;
928
939
}
929
940
hir:: QPath :: LangItem ( ..) => { }
930
941
}
@@ -933,7 +944,38 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
933
944
fn visit_path ( & mut self , path : & hir:: Path < ' tcx > , hir_id : HirId ) {
934
945
for ( index, segment) in path. segments . iter ( ) . enumerate ( ) {
935
946
if let Some ( args) = segment. args {
936
- self . visit_segment_args ( path, index, args) ;
947
+ // Figure out if this is an "eligible generic container" that brings along ambient object
948
+ // lifetime defaults for trait object types contained in any of the type arguments passed to
949
+ // it (any inner generic containers will of course end up shadowing that the default).
950
+ let depth = path. segments . len ( ) - index - 1 ;
951
+ let container = match ( path. res , depth) {
952
+ ( Res :: Def ( DefKind :: AssocTy , def_id) , 1 ) => {
953
+ Some ( ( self . tcx . parent ( def_id) , & path. segments [ ..=index] ) )
954
+ }
955
+ ( Res :: Def ( DefKind :: Variant , def_id) , 0 ) => {
956
+ Some ( ( self . tcx . parent ( def_id) , path. segments ) )
957
+ }
958
+ // FIXME(trait_alias): Arguably, trait aliases are eligible generic containers.
959
+ (
960
+ Res :: Def (
961
+ DefKind :: Struct
962
+ | DefKind :: Union
963
+ | DefKind :: Enum
964
+ | DefKind :: TyAlias
965
+ | DefKind :: Trait
966
+ | DefKind :: AssocTy ,
967
+ def_id,
968
+ ) ,
969
+ 0 ,
970
+ ) => Some ( ( def_id, path. segments ) ) ,
971
+ // Note: We don't need to care about definition kinds that may have generics if they
972
+ // can only ever appear in positions where we can perform type inference (i.e., bodies).
973
+ // FIXME(mgca): @fmease thinks that under (m)GCA we now also need to care about e.g.,
974
+ // type-level Consts (GCI) and AssocConsts (maybe also Fns, AssocFns) here
975
+ // since they appear outside of bodies (once the feature is more complete).
976
+ _ => None ,
977
+ } ;
978
+ self . visit_segment_args ( container, args) ;
937
979
}
938
980
}
939
981
if let Res :: Def ( DefKind :: TyParam | DefKind :: ConstParam , param_def_id) = path. res {
@@ -1652,8 +1694,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
1652
1694
#[ instrument( level = "debug" , skip( self ) ) ]
1653
1695
fn visit_segment_args (
1654
1696
& mut self ,
1655
- path : & hir:: Path < ' tcx > ,
1656
- index : usize ,
1697
+ container : Option < ( DefId , & [ hir:: PathSegment < ' tcx > ] ) > ,
1657
1698
generic_args : & ' tcx hir:: GenericArgs < ' tcx > ,
1658
1699
) {
1659
1700
if let Some ( ( inputs, output) ) = generic_args. paren_sugar_inputs_output ( ) {
@@ -1669,40 +1710,6 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
1669
1710
}
1670
1711
}
1671
1712
1672
- // Figure out if this is an "eligible generic container" that brings along ambient object
1673
- // lifetime defaults for trait object types contained in any of the type arguments passed to
1674
- // it (any inner generic containers will of course end up shadowing that the default).
1675
- let depth = path. segments . len ( ) - index - 1 ;
1676
- let container = match ( path. res , depth) {
1677
- ( Res :: Def ( DefKind :: AssocTy , def_id) , 1 ) => {
1678
- Some ( ( self . tcx . parent ( def_id) , & path. segments [ ..=index] ) )
1679
- }
1680
- ( Res :: Def ( DefKind :: Variant , def_id) , 0 ) => {
1681
- Some ( ( self . tcx . parent ( def_id) , path. segments ) )
1682
- }
1683
- // FIXME(trait_alias): Arguably, trait aliases are eligible generic containers.
1684
- (
1685
- Res :: Def (
1686
- DefKind :: Struct
1687
- | DefKind :: Union
1688
- | DefKind :: Enum
1689
- | DefKind :: TyAlias
1690
- | DefKind :: Trait
1691
- | DefKind :: AssocTy ,
1692
- def_id,
1693
- ) ,
1694
- 0 ,
1695
- ) => Some ( ( def_id, path. segments ) ) ,
1696
- // Note: We don't need to care about definition kinds that may have generics if they
1697
- // can only ever appear in positions where we can perform type inference (i.e., bodies).
1698
- // FIXME(mgca): @fmease thinks that under (m)GCA we now also need to care about e.g.,
1699
- // type-level Consts (GCI) and AssocConsts (maybe also Fns, AssocFns) here
1700
- // since they appear outside of bodies (once the feature is more complete).
1701
- _ => None ,
1702
- } ;
1703
-
1704
- debug ! ( ?container) ;
1705
-
1706
1713
let object_lifetime_defaults = container. map_or_else ( Vec :: new, |( def_id, segs) | {
1707
1714
self . compute_ambient_object_lifetime_defaults ( def_id, segs)
1708
1715
} ) ;
@@ -2143,72 +2150,15 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
2143
2150
matches ! ( args. parenthesized, hir:: GenericArgsParentheses :: ReturnTypeNotation )
2144
2151
} ) =>
2145
2152
{
2146
- // First, ignore a qself that isn't a type or `Self` param. Those are the
2147
- // only ones that support `T::Assoc` anyways in HIR lowering.
2148
- let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , path) ) = qself. kind else {
2153
+ let Some ( ( bound_vars, assoc_item) ) = self . limited_resolve_type_relative_path (
2154
+ ty:: AssocTag :: Fn ,
2155
+ qself,
2156
+ item_segment,
2157
+ false ,
2158
+ ) else {
2149
2159
return ;
2150
2160
} ;
2151
- match path. res {
2152
- Res :: Def ( DefKind :: TyParam , _) | Res :: SelfTyParam { trait_ : _ } => {
2153
- let mut bounds =
2154
- self . for_each_trait_bound_on_res ( path. res ) . filter_map ( |trait_def_id| {
2155
- BoundVarContext :: supertrait_hrtb_vars (
2156
- self . tcx ,
2157
- trait_def_id,
2158
- item_segment. ident ,
2159
- ty:: AssocTag :: Fn ,
2160
- )
2161
- } ) ;
2162
-
2163
- let Some ( ( bound_vars, assoc_item) ) = bounds. next ( ) else {
2164
- // This will error in HIR lowering.
2165
- self . tcx
2166
- . dcx ( )
2167
- . span_delayed_bug ( path. span , "no resolution for RTN path" ) ;
2168
- return ;
2169
- } ;
2170
-
2171
- // Don't bail if we have identical bounds, which may be collected from
2172
- // something like `T: Bound + Bound`, or via elaborating supertraits.
2173
- for ( second_vars, second_assoc_item) in bounds {
2174
- if second_vars != bound_vars || second_assoc_item != assoc_item {
2175
- // This will error in HIR lowering.
2176
- self . tcx . dcx ( ) . span_delayed_bug (
2177
- path. span ,
2178
- "ambiguous resolution for RTN path" ,
2179
- ) ;
2180
- return ;
2181
- }
2182
- }
2183
-
2184
- ( bound_vars, assoc_item. def_id , item_segment)
2185
- }
2186
- // If we have a self type alias (in an impl), try to resolve an
2187
- // associated item from one of the supertraits of the impl's trait.
2188
- Res :: SelfTyAlias { alias_to : impl_def_id, is_trait_impl : true , .. } => {
2189
- let hir:: ItemKind :: Impl ( hir:: Impl { of_trait : Some ( trait_ref) , .. } ) = self
2190
- . tcx
2191
- . hir_node_by_def_id ( impl_def_id. expect_local ( ) )
2192
- . expect_item ( )
2193
- . kind
2194
- else {
2195
- return ;
2196
- } ;
2197
- let Some ( trait_def_id) = trait_ref. trait_def_id ( ) else {
2198
- return ;
2199
- } ;
2200
- let Some ( ( bound_vars, assoc_item) ) = BoundVarContext :: supertrait_hrtb_vars (
2201
- self . tcx ,
2202
- trait_def_id,
2203
- item_segment. ident ,
2204
- ty:: AssocTag :: Fn ,
2205
- ) else {
2206
- return ;
2207
- } ;
2208
- ( bound_vars, assoc_item. def_id , item_segment)
2209
- }
2210
- _ => return ,
2211
- }
2161
+ ( bound_vars, assoc_item. def_id , item_segment)
2212
2162
}
2213
2163
2214
2164
_ => return ,
@@ -2247,6 +2197,83 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
2247
2197
self . record_late_bound_vars ( item_segment. hir_id , existing_bound_vars_saved) ;
2248
2198
}
2249
2199
2200
+ /// In a limited fashion, try to resolve the given type-relative path of the given kind.
2201
+ fn limited_resolve_type_relative_path (
2202
+ & self ,
2203
+ tag : ty:: AssocTag ,
2204
+ qself : & ' tcx hir:: Ty < ' tcx > ,
2205
+ segment : & ' tcx hir:: PathSegment < ' tcx > ,
2206
+ speculative : bool ,
2207
+ ) -> Option < ( Vec < ty:: BoundVariableKind > , & ' tcx ty:: AssocItem ) > {
2208
+ // This mimics HIR ty lowering's `lower_assoc_path_shared`.
2209
+ // FIXME: Duplicating efforts is not robust or sustainable/maintainable.
2210
+ // Ideally, we'd simply obtain the resulting type-dependent defs from
2211
+ // HIR ty lowering (not only in FnCtxts but also in ItemCtxts!).
2212
+
2213
+ // First, ignore a qself that isn't a type or `Self` param. Those are the only ones
2214
+ // that support `T::Assoc` anyways in HIR ty lowering at the time of writing.
2215
+ let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , path) ) = qself. kind else {
2216
+ return None ;
2217
+ } ;
2218
+
2219
+ match path. res {
2220
+ Res :: Def ( DefKind :: TyParam , _) | Res :: SelfTyParam { trait_ : _ } => {
2221
+ let mut bounds =
2222
+ self . for_each_trait_bound_on_res ( path. res ) . filter_map ( |trait_def_id| {
2223
+ BoundVarContext :: supertrait_hrtb_vars (
2224
+ self . tcx ,
2225
+ trait_def_id,
2226
+ segment. ident ,
2227
+ tag,
2228
+ )
2229
+ } ) ;
2230
+
2231
+ let Some ( ( bound_vars, assoc_item) ) = bounds. next ( ) else {
2232
+ if !speculative {
2233
+ // This will error in HIR ty lowering.
2234
+ self . tcx
2235
+ . dcx ( )
2236
+ . span_delayed_bug ( path. span , "no resolution for type-relative path" ) ;
2237
+ }
2238
+ return None ;
2239
+ } ;
2240
+
2241
+ // Don't bail if we have identical bounds, which may be collected from
2242
+ // something like `T: Bound + Bound`, or via elaborating supertraits.
2243
+ for ( second_vars, second_assoc_item) in bounds {
2244
+ if second_vars != bound_vars || second_assoc_item != assoc_item {
2245
+ if !speculative {
2246
+ // This will error in HIR ty lowering.
2247
+ self . tcx . dcx ( ) . span_delayed_bug (
2248
+ path. span ,
2249
+ "ambiguous resolution for type-relative path" ,
2250
+ ) ;
2251
+ }
2252
+ return None ;
2253
+ }
2254
+ }
2255
+
2256
+ Some ( ( bound_vars, assoc_item) )
2257
+ }
2258
+ // If we have a self type alias (in an impl), try to resolve an
2259
+ // associated item from one of the supertraits of the impl's trait.
2260
+ Res :: SelfTyAlias { alias_to : impl_def_id, is_trait_impl : true , .. } => {
2261
+ let hir:: ItemKind :: Impl ( hir:: Impl { of_trait : Some ( trait_ref) , .. } ) =
2262
+ self . tcx . hir_node_by_def_id ( impl_def_id. expect_local ( ) ) . expect_item ( ) . kind
2263
+ else {
2264
+ return None ;
2265
+ } ;
2266
+ BoundVarContext :: supertrait_hrtb_vars (
2267
+ self . tcx ,
2268
+ trait_ref. trait_def_id ( ) ?,
2269
+ segment. ident ,
2270
+ tag,
2271
+ )
2272
+ }
2273
+ _ => None ,
2274
+ }
2275
+ }
2276
+
2250
2277
/// Walk the generics of the item for a trait bound whose self type
2251
2278
/// corresponds to the expected res, and return the trait def id.
2252
2279
fn for_each_trait_bound_on_res ( & self , expected_res : Res ) -> impl Iterator < Item = DefId > {
0 commit comments