@@ -1862,19 +1862,38 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
18621862 assert_eq ! ( old_value, Some ( bad_def) ) ;
18631863 }
18641864
1865- // TODO:
1865+ // When we have a return type notation type in a where clause, like
1866+ // `where <T as Trait>::method(..): Send`, we need to introduce new bound
1867+ // vars to the existing where clause's binder, to represent the lifetimes
1868+ // elided by the return-type-notation syntax.
1869+ //
1870+ // For example, given
1871+ // ```
1872+ // trait Foo {
1873+ // async fn x<'r, T>();
1874+ // }
1875+ // ```
1876+ // and a bound that looks like:
1877+ // `for<'a, 'b> <T as Trait<'a>>::x(): Other<'b>`
1878+ // this is going to expand to something like:
1879+ // `for<'a, 'b, 'r, T> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: Other<'b>`.
1880+ //
1881+ // We handle this similarly for associated-type-bound style return-type-notation
1882+ // in `visit_segment_args`.
18661883 fn try_append_return_type_notation_params (
18671884 & mut self ,
18681885 hir_id : HirId ,
18691886 hir_ty : & ' tcx hir:: Ty < ' tcx > ,
18701887 ) {
18711888 let hir:: TyKind :: Path ( qpath) = hir_ty. kind else {
1872- // TODO:
1889+ // We only care about path types here. All other self types
1890+ // (including nesting the RTN type in another type) don't do
1891+ // anything.
18731892 return ;
18741893 } ;
18751894
18761895 let ( mut bound_vars, item_def_id, item_segment) = match qpath {
1877- // TODO:
1896+ // If we have a fully qualified method, then we don't need to do any special lookup.
18781897 hir:: QPath :: Resolved ( _, path)
18791898 if let [ .., item_segment] = & path. segments [ ..]
18801899 && item_segment. args . is_some_and ( |args| {
@@ -1890,23 +1909,32 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
18901909 ( vec ! [ ] , item_def_id, item_segment)
18911910 }
18921911
1893- // TODO:
1912+ // If we have a type-dependent path, then we do need to do some lookup.
18941913 hir:: QPath :: TypeRelative ( qself, item_segment)
18951914 if item_segment. args . is_some_and ( |args| {
18961915 matches ! ( args. parenthesized, hir:: GenericArgsParentheses :: ReturnTypeNotation )
18971916 } ) =>
18981917 {
1918+ // First, ignore a qself that isn't a type or `Self` param. Those are the
1919+ // only ones that support `T::Assoc` anyways in HIR lowering.
18991920 let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , path) ) = qself. kind else {
19001921 return ;
19011922 } ;
1902-
19031923 match path. res {
19041924 Res :: Def ( DefKind :: TyParam , _) | Res :: SelfTyParam { trait_ : _ } => {
1925+ // Get the generics of this type's hir owner. This is *different*
1926+ // from the generics of the parameter's definition, since we want
1927+ // to be able to resolve an RTN path on a nested body (e.g. method
1928+ // inside an impl) using the where clauses on the method.
19051929 let Some ( generics) = self . tcx . hir_owner_node ( hir_id. owner ) . generics ( )
19061930 else {
19071931 return ;
19081932 } ;
19091933
1934+ // Look for the first bound that contains an associated type that
1935+ // matches the segment that we're looking for. We ignore any subsequent
1936+ // bounds since we'll be emitting a hard error in HIR lowering, so this
1937+ // is purely speculative.
19101938 let one_bound = generics. predicates . iter ( ) . find_map ( |predicate| {
19111939 let hir:: WherePredicate :: BoundPredicate ( predicate) = predicate else {
19121940 return None ;
@@ -1944,7 +1972,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
19441972 _ => return ,
19451973 } ;
19461974
1947- // TODO:
1975+ // Append the early-bound vars on the function, and then the late-bound ones.
1976+ // We actually turn type parameters into higher-ranked types here, but we
1977+ // deny them later in HIR lowering.
19481978 bound_vars. extend ( self . tcx . generics_of ( item_def_id) . own_params . iter ( ) . map ( |param| {
19491979 match param. kind {
19501980 ty:: GenericParamDefKind :: Lifetime => ty:: BoundVariableKind :: Region (
@@ -1958,11 +1988,13 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
19581988 } ) ) ;
19591989 bound_vars. extend ( self . tcx . fn_sig ( item_def_id) . instantiate_identity ( ) . bound_vars ( ) ) ;
19601990
1961- // TODO:
1991+ // SUBTLE: Stash the old bound vars onto the *item segment* before appending
1992+ // the new bound vars. We do this because we need to know how many bound vars
1993+ // are present on the binder explicitly (i.e. not return-type-notation vars)
1994+ // to do bound var shifting correctly in HIR lowering.
19621995 let existing_bound_vars = self . map . late_bound_vars . get_mut ( & hir_id) . unwrap ( ) ;
19631996 let existing_bound_vars_saved = existing_bound_vars. clone ( ) ;
19641997 existing_bound_vars. extend ( bound_vars) ;
1965- // TODO: subtle
19661998 self . record_late_bound_vars ( item_segment. hir_id , existing_bound_vars_saved) ;
19671999 }
19682000}
0 commit comments