@@ -887,12 +887,28 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
887887 fn visit_qpath ( & mut self , qpath : & ' tcx hir:: QPath < ' tcx > , id : HirId , _: Span ) {
888888 match qpath {
889889 hir:: QPath :: Resolved ( maybe_qself, path) => {
890+ // Visit the path before the self type since computing the ambient object lifetime default
891+ // for the latter requires all lifetime arguments of the trait ref to be already resolved.
892+ self . visit_path ( path, id) ;
890893 if let Some ( qself) = maybe_qself {
891- // FIXME: Actually determine the ambient object lifetime defaults for the self ty!
892- let scope = Scope :: ObjectLifetimeDefault { lifetime : None , s : self . scope } ;
893- self . with ( scope, |this| this. visit_ty_unambig ( qself) ) ;
894+ let container = match path. res {
895+ Res :: Def ( DefKind :: AssocTy , def_id) => Some ( (
896+ self . tcx . parent ( def_id) ,
897+ & path. segments [ ..path. segments . len ( ) - 1 ] ,
898+ ) ) ,
899+ _ => None ,
900+ } ;
901+ let object_lifetime_defaults =
902+ container. map_or ( Vec :: new ( ) , |( def_id, segs) | {
903+ self . compute_ambient_object_lifetime_defaults ( def_id, segs)
904+ } ) ;
905+ if let Some ( & lt) = object_lifetime_defaults. get ( 0 ) {
906+ let scope = Scope :: ObjectLifetimeDefault { lifetime : lt, s : self . scope } ;
907+ self . with ( scope, |this| this. visit_ty_unambig ( qself) ) ;
908+ } else {
909+ self . visit_ty_unambig ( qself) ;
910+ }
894911 }
895- self . visit_path ( path, id) ;
896912 }
897913 hir:: QPath :: TypeRelative ( qself, segment) => {
898914 // Resolving object lifetime defaults for type-relative paths requires full
@@ -1056,52 +1072,57 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
10561072}
10571073
10581074fn object_lifetime_default ( tcx : TyCtxt < ' _ > , param_def_id : LocalDefId ) -> ObjectLifetimeDefault {
1059- debug_assert_eq ! ( tcx. def_kind( param_def_id) , DefKind :: TyParam ) ;
1060- let hir:: Node :: GenericParam ( param) = tcx. hir_node_by_def_id ( param_def_id) else {
1061- bug ! ( "expected GenericParam for object_lifetime_default" ) ;
1062- } ;
1063- match param. source {
1064- hir:: GenericParamSource :: Generics => {
1065- let parent_def_id = tcx. local_parent ( param_def_id) ;
1066- let generics = tcx. hir_get_generics ( parent_def_id) . unwrap ( ) ;
1067-
1068- // Scan the bounds and where-clauses on parameters to extract bounds
1069- // of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
1070- // for each type parameter.
1071- match param. kind {
1075+ // Scan the bounds and where-clauses on parameters to extract bounds of the form `T: 'a`
1076+ // so as to determine the `ObjectLifetimeDefault` for each type parameter.
1077+
1078+ let Ok ( ( generics, bounds) ) = ( match tcx. hir_node_by_def_id ( param_def_id) {
1079+ hir:: Node :: GenericParam ( param) => match param. source {
1080+ hir:: GenericParamSource :: Generics => match param. kind {
10721081 GenericParamKind :: Type { .. } => {
1073- let mut set = Set1 :: Empty ;
1074-
1075- // Look for `type: ...` where clauses.
1076- for bound in generics. bounds_for_param ( param_def_id) {
1077- // Ignore `for<'a> type: ...` as they can change what
1078- // lifetimes mean (although we could "just" handle it).
1079- if !bound. bound_generic_params . is_empty ( ) {
1080- continue ;
1081- }
1082+ Ok ( ( tcx. hir_get_generics ( tcx. local_parent ( param_def_id) ) . unwrap ( ) , & [ ] [ ..] ) )
1083+ }
1084+ _ => Err ( ( ) ) ,
1085+ } ,
1086+ hir:: GenericParamSource :: Binder => return ObjectLifetimeDefault :: Empty ,
1087+ } ,
1088+ // For `Self` type parameters
1089+ hir:: Node :: Item ( & hir:: Item {
1090+ kind : hir:: ItemKind :: Trait ( _, _, _, _, generics, bounds, _) ,
1091+ ..
1092+ } ) => Ok ( ( generics, bounds) ) ,
1093+ _ => Err ( ( ) ) ,
1094+ } ) else {
1095+ bug ! ( "`object_lifetime_default` must only be called on type parameters" )
1096+ } ;
10821097
1083- for bound in bound. bounds {
1084- if let hir:: GenericBound :: Outlives ( lifetime) = bound {
1085- set. insert ( lifetime. kind ) ;
1086- }
1087- }
1088- }
1098+ let mut set = Set1 :: Empty ;
10891099
1090- match set {
1091- Set1 :: Empty => ObjectLifetimeDefault :: Empty ,
1092- Set1 :: One ( hir:: LifetimeKind :: Static ) => ObjectLifetimeDefault :: Static ,
1093- Set1 :: One ( hir:: LifetimeKind :: Param ( param_def_id) ) => {
1094- ObjectLifetimeDefault :: Param ( param_def_id. to_def_id ( ) )
1095- }
1096- _ => ObjectLifetimeDefault :: Ambiguous ,
1097- }
1098- }
1099- _ => {
1100- bug ! ( "object_lifetime_default must only be called on a type parameter" )
1101- }
1100+ let mut add_outlives_bounds = |bounds : & [ hir:: GenericBound < ' _ > ] | {
1101+ for bound in bounds {
1102+ if let hir:: GenericBound :: Outlives ( lifetime) = bound {
1103+ set. insert ( lifetime. kind ) ;
11021104 }
11031105 }
1104- hir:: GenericParamSource :: Binder => ObjectLifetimeDefault :: Empty ,
1106+ } ;
1107+
1108+ add_outlives_bounds ( bounds) ;
1109+
1110+ // Look for `Type: ...` where clauses.
1111+ for bound in generics. bounds_for_param ( param_def_id) {
1112+ // Ignore `for<'a> Type: ...` as they can change what
1113+ // lifetimes mean (although we could "just" handle it).
1114+ if bound. bound_generic_params . is_empty ( ) {
1115+ add_outlives_bounds ( & bound. bounds ) ;
1116+ }
1117+ }
1118+
1119+ match set {
1120+ Set1 :: Empty => ObjectLifetimeDefault :: Empty ,
1121+ Set1 :: One ( hir:: LifetimeKind :: Static ) => ObjectLifetimeDefault :: Static ,
1122+ Set1 :: One ( hir:: LifetimeKind :: Param ( param_def_id) ) => {
1123+ ObjectLifetimeDefault :: Param ( param_def_id. to_def_id ( ) )
1124+ }
1125+ _ => ObjectLifetimeDefault :: Ambiguous ,
11051126 }
11061127}
11071128
@@ -1690,106 +1711,16 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
16901711
16911712 debug ! ( ?container) ;
16921713
1693- // Compute a vector of ambient object lifetime defaults, one for each type parameter,
1694- // per the rules initially given in RFCs 599 and 1156. Example:
1695- //
1696- // ```rust
1697- // struct Foo<'a, T: 'a + ?Sized, U: ?Sized>(&'a T, &'a U);
1698- // ```
1699- //
1700- // If you have `Foo<'x, dyn Bar, dyn Baz>`, we want to default
1701- // `dyn Bar` to `dyn Bar + 'x` (because of the `T: 'a` bound)
1702- // and `dyn Baz` to `dyn Baz + 'static` (because there is no
1703- // such bound).
1704- //
1705- // Therefore, we would compute a vector like `['x, 'static]`.
1706- // Note that the vector only includes type parameters.
1707- let object_lifetime_defaults = container. map_or_else ( Vec :: new, |( def_id, segments) | {
1708- let in_body = {
1709- let mut scope = self . scope ;
1710- loop {
1711- match * scope {
1712- Scope :: Root { .. } => break false ,
1713-
1714- Scope :: Body { .. } => break true ,
1715-
1716- Scope :: Binder { s, .. }
1717- | Scope :: ObjectLifetimeDefault { s, .. }
1718- | Scope :: Opaque { s, .. }
1719- | Scope :: Supertrait { s, .. }
1720- | Scope :: TraitRefBoundary { s, .. }
1721- | Scope :: LateBoundary { s, .. } => {
1722- scope = s;
1723- }
1724- }
1725- }
1726- } ;
1727-
1728- let rbv = & self . rbv ;
1729- let generics = self . tcx . generics_of ( def_id) ;
1730-
1731- let set_to_region = |set : ObjectLifetimeDefault | match set {
1732- ObjectLifetimeDefault :: Empty => {
1733- if in_body {
1734- None
1735- } else {
1736- Some ( ResolvedArg :: StaticLifetime )
1737- }
1738- }
1739- ObjectLifetimeDefault :: Static => Some ( ResolvedArg :: StaticLifetime ) ,
1740- ObjectLifetimeDefault :: Param ( param_def_id) => {
1741- fn param_to_depth_and_index (
1742- generics : & ty:: Generics ,
1743- tcx : TyCtxt < ' _ > ,
1744- def_id : DefId ,
1745- ) -> ( usize , usize ) {
1746- if let Some ( & index) = generics. param_def_id_to_index . get ( & def_id) {
1747- let has_self = generics. parent . is_none ( ) && generics. has_self ;
1748- ( 0 , index as usize - generics. parent_count - has_self as usize )
1749- } else if let Some ( parent) = generics. parent {
1750- let parent = tcx. generics_of ( parent) ;
1751- let ( depth, index) = param_to_depth_and_index ( parent, tcx, def_id) ;
1752- ( depth + 1 , index)
1753- } else {
1754- unreachable ! ( )
1755- }
1756- }
1757-
1758- let ( depth, index) = param_to_depth_and_index ( generics, self . tcx , param_def_id) ;
1759- segments[ segments. len ( ) - depth - 1 ]
1760- . args
1761- . and_then ( |args| args. args . get ( index) )
1762- . and_then ( |arg| match arg {
1763- GenericArg :: Lifetime ( lt) => rbv. defs . get ( & lt. hir_id . local_id ) . copied ( ) ,
1764- _ => None ,
1765- } )
1766- }
1767- ObjectLifetimeDefault :: Ambiguous => None ,
1768- } ;
1769- generics
1770- . own_params
1771- . iter ( )
1772- . filter_map ( |param| {
1773- match self . tcx . def_kind ( param. def_id ) {
1774- // Generic consts don't impose any constraints.
1775- //
1776- // We still store a dummy value here to allow generic parameters
1777- // in an arbitrary order.
1778- DefKind :: ConstParam => Some ( ObjectLifetimeDefault :: Empty ) ,
1779- DefKind :: TyParam => Some ( self . tcx . object_lifetime_default ( param. def_id ) ) ,
1780- // We may also get a `Trait` or `TraitAlias` because of how generics `Self` parameter
1781- // works. Ignore it because it can't have a meaningful lifetime default.
1782- DefKind :: LifetimeParam | DefKind :: Trait | DefKind :: TraitAlias => None ,
1783- dk => bug ! ( "unexpected def_kind {:?}" , dk) ,
1784- }
1785- } )
1786- . map ( set_to_region)
1787- . collect ( )
1714+ let object_lifetime_defaults = container. map_or_else ( Vec :: new, |( def_id, segs) | {
1715+ self . compute_ambient_object_lifetime_defaults ( def_id, segs)
17881716 } ) ;
17891717
17901718 debug ! ( ?object_lifetime_defaults) ;
17911719
1792- let mut i = 0 ;
1720+ let has_self = container
1721+ . map ( |( def_id, _) | self . tcx . generics_of ( def_id) )
1722+ . is_some_and ( |generics| generics. parent . is_none ( ) && generics. has_self ) ;
1723+ let mut i = has_self as usize ;
17931724 for arg in generic_args. args {
17941725 match arg {
17951726 // We've already visited all lifetime arguments at the start.
@@ -1921,6 +1852,110 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
19211852 }
19221853 }
19231854
1855+ /// Compute a vector of ambient object lifetime defaults, one for each type parameter,
1856+ /// per the rules initially given in RFCs 599 and 1156.
1857+ ///
1858+ /// # Example
1859+ ///
1860+ /// ```ignore (illustrative)
1861+ /// struct Foo<'a, T: 'a + ?Sized, U: ?Sized>(&'a T, &'a U);
1862+ /// ```
1863+ ///
1864+ /// If you have `Foo<'x, dyn Bar, dyn Baz>`, we want to default
1865+ /// `dyn Bar` to `dyn Bar + 'x` (because of the `T: 'a` bound)
1866+ /// and `dyn Baz` to `dyn Baz + 'static` (because there is no
1867+ /// such bound).
1868+ ///
1869+ /// Therefore, we would compute a vector like `['x, 'static]`.
1870+ /// Note that the vector only includes type parameters.
1871+ fn compute_ambient_object_lifetime_defaults (
1872+ & self ,
1873+ def_id : DefId ,
1874+ segments : & [ hir:: PathSegment < ' _ > ] ,
1875+ ) -> Vec < Option < ResolvedArg > > {
1876+ let in_body = {
1877+ let mut scope = self . scope ;
1878+ loop {
1879+ match * scope {
1880+ Scope :: Root { .. } => break false ,
1881+
1882+ Scope :: Body { .. } => break true ,
1883+
1884+ Scope :: Binder { s, .. }
1885+ | Scope :: ObjectLifetimeDefault { s, .. }
1886+ | Scope :: Opaque { s, .. }
1887+ | Scope :: Supertrait { s, .. }
1888+ | Scope :: TraitRefBoundary { s, .. }
1889+ | Scope :: LateBoundary { s, .. } => {
1890+ scope = s;
1891+ }
1892+ }
1893+ }
1894+ } ;
1895+
1896+ let generics = self . tcx . generics_of ( def_id) ;
1897+
1898+ let set_to_region = |set : ObjectLifetimeDefault | match set {
1899+ ObjectLifetimeDefault :: Empty => {
1900+ if in_body {
1901+ None
1902+ } else {
1903+ Some ( ResolvedArg :: StaticLifetime )
1904+ }
1905+ }
1906+ ObjectLifetimeDefault :: Static => Some ( ResolvedArg :: StaticLifetime ) ,
1907+ ObjectLifetimeDefault :: Param ( param_def_id) => {
1908+ fn param_to_depth_and_index (
1909+ generics : & ty:: Generics ,
1910+ tcx : TyCtxt < ' _ > ,
1911+ def_id : DefId ,
1912+ ) -> ( usize , usize ) {
1913+ if let Some ( & index) = generics. param_def_id_to_index . get ( & def_id) {
1914+ let has_self = generics. parent . is_none ( ) && generics. has_self ;
1915+ ( 0 , index as usize - generics. parent_count - has_self as usize )
1916+ } else if let Some ( parent) = generics. parent {
1917+ let parent = tcx. generics_of ( parent) ;
1918+ let ( depth, index) = param_to_depth_and_index ( parent, tcx, def_id) ;
1919+ ( depth + 1 , index)
1920+ } else {
1921+ unreachable ! ( )
1922+ }
1923+ }
1924+
1925+ let ( depth, index) = param_to_depth_and_index ( generics, self . tcx , param_def_id) ;
1926+ segments[ segments. len ( ) - depth - 1 ]
1927+ . args
1928+ . and_then ( |args| args. args . get ( index) )
1929+ . and_then ( |arg| match arg {
1930+ GenericArg :: Lifetime ( lt) => self . rbv . defs . get ( & lt. hir_id . local_id ) . copied ( ) ,
1931+ _ => None ,
1932+ } )
1933+ }
1934+ ObjectLifetimeDefault :: Ambiguous => None ,
1935+ } ;
1936+ generics
1937+ . own_params
1938+ . iter ( )
1939+ . filter_map ( |param| {
1940+ match self . tcx . def_kind ( param. def_id ) {
1941+ // Generic consts don't impose any constraints.
1942+ //
1943+ // We still store a dummy value here to allow generic parameters
1944+ // in an arbitrary order.
1945+ DefKind :: ConstParam => Some ( ObjectLifetimeDefault :: Empty ) ,
1946+ // `Self` type params share the `DefId` of the corresp. trait.
1947+ DefKind :: TyParam | DefKind :: Trait => {
1948+ Some ( self . tcx . object_lifetime_default ( param. def_id ) )
1949+ }
1950+ // `Self` type params of trait aliases may show up here, ignore them.
1951+ DefKind :: LifetimeParam | DefKind :: TraitAlias => None ,
1952+ dk => bug ! ( "unexpected def_kind {:?}" , dk) ,
1953+ }
1954+ } )
1955+ . map ( set_to_region)
1956+ . collect ( )
1957+ }
1958+
19241959 /// Returns all the late-bound vars that come into scope from supertrait HRTBs, based on the
19251960 /// associated type name and starting trait.
19261961 /// For example, imagine we have
0 commit comments