@@ -18,7 +18,7 @@ use rustc_middle::bug;
18
18
use rustc_middle:: hir:: map:: Map ;
19
19
use rustc_middle:: hir:: nested_filter;
20
20
use rustc_middle:: middle:: resolve_lifetime:: * ;
21
- use rustc_middle:: ty:: { self , DefIdTree , TyCtxt } ;
21
+ use rustc_middle:: ty:: { self , DefIdTree , TyCtxt , TypeSuperVisitable , TypeVisitor } ;
22
22
use rustc_span:: def_id:: DefId ;
23
23
use rustc_span:: symbol:: { sym, Ident } ;
24
24
use rustc_span:: Span ;
@@ -1781,7 +1781,7 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
1781
1781
1782
1782
let mut late_bound = FxIndexSet :: default ( ) ;
1783
1783
1784
- let mut constrained_by_input = ConstrainedCollector :: default ( ) ;
1784
+ let mut constrained_by_input = ConstrainedCollector { regions : Default :: default ( ) , tcx } ;
1785
1785
for arg_ty in decl. inputs {
1786
1786
constrained_by_input. visit_ty ( arg_ty) ;
1787
1787
}
@@ -1834,12 +1834,44 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
1834
1834
debug ! ( ?late_bound) ;
1835
1835
return Some ( tcx. arena . alloc ( late_bound) ) ;
1836
1836
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 > ,
1839
1871
regions : FxHashSet < LocalDefId > ,
1840
1872
}
1841
1873
1842
- impl < ' v > Visitor < ' v > for ConstrainedCollector {
1874
+ impl < ' v > Visitor < ' v > for ConstrainedCollector < ' _ > {
1843
1875
fn visit_ty ( & mut self , ty : & ' v hir:: Ty < ' v > ) {
1844
1876
match ty. kind {
1845
1877
hir:: TyKind :: Path (
@@ -1850,6 +1882,56 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
1850
1882
// (defined above)
1851
1883
}
1852
1884
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
+
1853
1935
hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , ref path) ) => {
1854
1936
// consider only the lifetimes on the final
1855
1937
// segment; I am not sure it's even currently
0 commit comments