@@ -1845,19 +1845,38 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
18451845 assert_eq ! ( old_value, Some ( bad_def) ) ;
18461846 }
18471847
1848- // TODO:
1848+ // When we have a return type notation type in a where clause, like
1849+ // `where <T as Trait>::method(..): Send`, we need to introduce new bound
1850+ // vars to the existing where clause's binder, to represent the lifetimes
1851+ // elided by the return-type-notation syntax.
1852+ //
1853+ // For example, given
1854+ // ```
1855+ // trait Foo {
1856+ // async fn x<'r, T>();
1857+ // }
1858+ // ```
1859+ // and a bound that looks like:
1860+ // `for<'a, 'b> <T as Trait<'a>>::x(): Other<'b>`
1861+ // this is going to expand to something like:
1862+ // `for<'a, 'b, 'r, T> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: Other<'b>`.
1863+ //
1864+ // We handle this similarly for associated-type-bound style return-type-notation
1865+ // in `visit_segment_args`.
18491866 fn try_append_return_type_notation_params (
18501867 & mut self ,
18511868 hir_id : HirId ,
18521869 hir_ty : & ' tcx hir:: Ty < ' tcx > ,
18531870 ) {
18541871 let hir:: TyKind :: Path ( qpath) = hir_ty. kind else {
1855- // TODO:
1872+ // We only care about path types here. All other self types
1873+ // (including nesting the RTN type in another type) don't do
1874+ // anything.
18561875 return ;
18571876 } ;
18581877
18591878 let ( mut bound_vars, item_def_id, item_segment) = match qpath {
1860- // TODO:
1879+ // If we have a fully qualified method, then we don't need to do any special lookup.
18611880 hir:: QPath :: Resolved ( _, path)
18621881 if let [ .., item_segment] = & path. segments [ ..]
18631882 && item_segment. args . is_some_and ( |args| {
@@ -1873,23 +1892,32 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
18731892 ( vec ! [ ] , item_def_id, item_segment)
18741893 }
18751894
1876- // TODO:
1895+ // If we have a type-dependent path, then we do need to do some lookup.
18771896 hir:: QPath :: TypeRelative ( qself, item_segment)
18781897 if item_segment. args . is_some_and ( |args| {
18791898 matches ! ( args. parenthesized, hir:: GenericArgsParentheses :: ReturnTypeNotation )
18801899 } ) =>
18811900 {
1901+ // First, ignore a qself that isn't a type or `Self` param. Those are the
1902+ // only ones that support `T::Assoc` anyways in HIR lowering.
18821903 let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , path) ) = qself. kind else {
18831904 return ;
18841905 } ;
1885-
18861906 match path. res {
18871907 Res :: Def ( DefKind :: TyParam , _) | Res :: SelfTyParam { trait_ : _ } => {
1908+ // Get the generics of this type's hir owner. This is *different*
1909+ // from the generics of the parameter's definition, since we want
1910+ // to be able to resolve an RTN path on a nested body (e.g. method
1911+ // inside an impl) using the where clauses on the method.
18881912 let Some ( generics) = self . tcx . hir_owner_node ( hir_id. owner ) . generics ( )
18891913 else {
18901914 return ;
18911915 } ;
18921916
1917+ // Look for the first bound that contains an associated type that
1918+ // matches the segment that we're looking for. We ignore any subsequent
1919+ // bounds since we'll be emitting a hard error in HIR lowering, so this
1920+ // is purely speculative.
18931921 let one_bound = generics. predicates . iter ( ) . find_map ( |predicate| {
18941922 let hir:: WherePredicate :: BoundPredicate ( predicate) = predicate else {
18951923 return None ;
@@ -1927,7 +1955,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
19271955 _ => return ,
19281956 } ;
19291957
1930- // TODO:
1958+ // Append the early-bound vars on the function, and then the late-bound ones.
1959+ // We actually turn type parameters into higher-ranked types here, but we
1960+ // deny them later in HIR lowering.
19311961 bound_vars. extend ( self . tcx . generics_of ( item_def_id) . own_params . iter ( ) . map ( |param| {
19321962 match param. kind {
19331963 ty:: GenericParamDefKind :: Lifetime => ty:: BoundVariableKind :: Region (
@@ -1941,11 +1971,13 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
19411971 } ) ) ;
19421972 bound_vars. extend ( self . tcx . fn_sig ( item_def_id) . instantiate_identity ( ) . bound_vars ( ) ) ;
19431973
1944- // TODO:
1974+ // SUBTLE: Stash the old bound vars onto the *item segment* before appending
1975+ // the new bound vars. We do this because we need to know how many bound vars
1976+ // are present on the binder explicitly (i.e. not return-type-notation vars)
1977+ // to do bound var shifting correctly in HIR lowering.
19451978 let existing_bound_vars = self . map . late_bound_vars . get_mut ( & hir_id) . unwrap ( ) ;
19461979 let existing_bound_vars_saved = existing_bound_vars. clone ( ) ;
19471980 existing_bound_vars. extend ( bound_vars) ;
1948- // TODO: subtle
19491981 self . record_late_bound_vars ( item_segment. hir_id , existing_bound_vars_saved) ;
19501982 }
19511983}
0 commit comments