@@ -1834,6 +1834,27 @@ 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
+ /// Visits a `ty::Ty` collecting information about what generic parameters are constrained.
1838
+ ///
1839
+ /// The visitor does not operate on `hir::Ty` so that it can be called on the rhs of a `type Alias<...> = ...;`
1840
+ /// which may live in a separate crate so there would not be any hir available. Instead we use the `type_of`
1841
+ /// query to obtain a `ty::Ty` which will be present even in cross crate scenarios. It also naturally
1842
+ /// handles cycle detection as we go through the query system.
1843
+ ///
1844
+ /// This is necessary in the first place for the following case:
1845
+ /// ```
1846
+ /// type Alias<'a, T> = <T as Trait<'a>>::Assoc;
1847
+ /// fn foo<'a>(_: Alias<'a, ()>) -> Alias<'a, ()> { ... }
1848
+ /// ```
1849
+ ///
1850
+ /// If we conservatively considered `'a` unconstrained then we could break users who had written code before
1851
+ /// we started correctly handling aliases. If we considered `'a` constrained then it would become late bound
1852
+ /// causing an error during astconv as the `'a` is not constrained by the input type `<() as Trait<'a>>::Assoc`
1853
+ /// but appears in the output type `<() as Trait<'a>>::Assoc`.
1854
+ ///
1855
+ /// We must therefore "look into" the `Alias` to see whether we should consider `'a` constrained or not.
1856
+ ///
1857
+ /// See #100508 #85533 #47511 for additional context
1837
1858
struct ConstrainedCollectorPostAstConv {
1838
1859
arg_is_constrained : Box < [ bool ] > ,
1839
1860
}
@@ -1886,17 +1907,8 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
1886
1907
None ,
1887
1908
hir:: Path { res : Res :: Def ( DefKind :: TyAlias , alias_def) , segments, span } ,
1888
1909
) ) => {
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
-
1910
+ // See comments on `ConstrainedCollectorPostAstConv` for why this arm does not just consider
1911
+ // substs to be unconstrained.
1900
1912
let generics = self . tcx . generics_of ( alias_def) ;
1901
1913
let mut walker = ConstrainedCollectorPostAstConv {
1902
1914
arg_is_constrained : vec ! [ false ; generics. params. len( ) ] . into_boxed_slice ( ) ,
0 commit comments