@@ -18,7 +18,7 @@ use rustc_middle::bug;
1818use rustc_middle:: hir:: map:: Map ;
1919use rustc_middle:: hir:: nested_filter;
2020use rustc_middle:: middle:: resolve_lifetime:: * ;
21- use rustc_middle:: ty:: { self , DefIdTree , TyCtxt } ;
21+ use rustc_middle:: ty:: { self , DefIdTree , TyCtxt , TypeSuperVisitable , TypeVisitor } ;
2222use rustc_span:: def_id:: DefId ;
2323use rustc_span:: symbol:: { sym, Ident } ;
2424use rustc_span:: Span ;
@@ -1781,7 +1781,7 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
17811781
17821782 let mut late_bound = FxIndexSet :: default ( ) ;
17831783
1784- let mut constrained_by_input = ConstrainedCollector :: default ( ) ;
1784+ let mut constrained_by_input = ConstrainedCollector { regions : Default :: default ( ) , tcx } ;
17851785 for arg_ty in decl. inputs {
17861786 constrained_by_input. visit_ty ( arg_ty) ;
17871787 }
@@ -1834,12 +1834,44 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
18341834 debug ! ( ?late_bound) ;
18351835 return Some ( tcx. arena . alloc ( late_bound) ) ;
18361836
1837- #[ derive( Default ) ]
1838- struct ConstrainedCollector {
1837+ struct ConstrainedCollectorPostAstConv {
1838+ arg_is_constrained : Box < [ bool ] > ,
1839+ }
1840+
1841+ use std:: ops:: ControlFlow ;
1842+ use ty:: Ty ;
1843+ impl < ' tcx > TypeVisitor < ' tcx > for ConstrainedCollectorPostAstConv {
1844+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < !> {
1845+ match t. kind ( ) {
1846+ ty:: Param ( param_ty) => {
1847+ self . arg_is_constrained [ param_ty. index as usize ] = true ;
1848+ }
1849+ ty:: Projection ( _) => return ControlFlow :: Continue ( ( ) ) ,
1850+ _ => ( ) ,
1851+ }
1852+ t. super_visit_with ( self )
1853+ }
1854+
1855+ fn visit_const ( & mut self , _: ty:: Const < ' tcx > ) -> ControlFlow < !> {
1856+ ControlFlow :: Continue ( ( ) )
1857+ }
1858+
1859+ fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> ControlFlow < !> {
1860+ debug ! ( "r={:?}" , r. kind( ) ) ;
1861+ if let ty:: RegionKind :: ReEarlyBound ( region) = r. kind ( ) {
1862+ self . arg_is_constrained [ region. index as usize ] = true ;
1863+ }
1864+
1865+ ControlFlow :: Continue ( ( ) )
1866+ }
1867+ }
1868+
1869+ struct ConstrainedCollector < ' tcx > {
1870+ tcx : TyCtxt < ' tcx > ,
18391871 regions : FxHashSet < LocalDefId > ,
18401872 }
18411873
1842- impl < ' v > Visitor < ' v > for ConstrainedCollector {
1874+ impl < ' v > Visitor < ' v > for ConstrainedCollector < ' _ > {
18431875 fn visit_ty ( & mut self , ty : & ' v hir:: Ty < ' v > ) {
18441876 match ty. kind {
18451877 hir:: TyKind :: Path (
@@ -1850,6 +1882,56 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
18501882 // (defined above)
18511883 }
18521884
1885+ hir:: TyKind :: Path ( hir:: QPath :: Resolved (
1886+ None ,
1887+ hir:: Path { res : Res :: Def ( DefKind :: TyAlias , alias_def) , segments, span } ,
1888+ ) ) => {
1889+ // If this is a top level type alias attempt to "look through" it to see if the args
1890+ // are constrained, instead of assuming they are and inserting all the lifetimes.
1891+ // This is necessary for the following case:
1892+ // ```
1893+ // type Alias<'a, T> = <T as Trait<'a>>::Assoc;
1894+ // fn foo<'a>(_: Alias<'a, ()>) -> Alias<'a, ()> { ... }
1895+ // ```
1896+ // If we considered `'a` constrained then it would become late bound causing an error
1897+ // during astconv as the `'a` is not constrained by the input type `<() as Trait<'a>>::Assoc`
1898+ // but appears in the output type `<() as Trait<'a>>::Assoc`.
1899+
1900+ let generics = self . tcx . generics_of ( alias_def) ;
1901+ let mut walker = ConstrainedCollectorPostAstConv {
1902+ arg_is_constrained : vec ! [ false ; generics. params. len( ) ] . into_boxed_slice ( ) ,
1903+ } ;
1904+ walker. visit_ty ( self . tcx . type_of ( alias_def) ) ;
1905+
1906+ match segments. last ( ) {
1907+ Some ( hir:: PathSegment { args : Some ( args) , .. } ) => {
1908+ let tcx = self . tcx ;
1909+ for constrained_arg in
1910+ args. args . iter ( ) . enumerate ( ) . flat_map ( |( n, arg) | {
1911+ match walker. arg_is_constrained . get ( n) {
1912+ Some ( true ) => Some ( arg) ,
1913+ Some ( false ) => None ,
1914+ None => {
1915+ tcx. sess . delay_span_bug (
1916+ * span,
1917+ format ! (
1918+ "Incorrect generic arg count for alias {:?}" ,
1919+ alias_def
1920+ ) ,
1921+ ) ;
1922+ None
1923+ }
1924+ }
1925+ } )
1926+ {
1927+ self . visit_generic_arg ( constrained_arg) ;
1928+ }
1929+ }
1930+ Some ( _) => ( ) ,
1931+ None => bug ! ( "Path with no segments or self type" ) ,
1932+ }
1933+ }
1934+
18531935 hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , ref path) ) => {
18541936 // consider only the lifetimes on the final
18551937 // segment; I am not sure it's even currently
0 commit comments