@@ -91,7 +91,14 @@ pub enum TypeParamLoweringMode {
9191
9292impl Ty {
9393 pub fn from_hir ( ctx : & TyLoweringContext < ' _ , impl HirDatabase > , type_ref : & TypeRef ) -> Self {
94- match type_ref {
94+ Ty :: from_hir_ext ( ctx, type_ref) . 0
95+ }
96+ pub fn from_hir_ext (
97+ ctx : & TyLoweringContext < ' _ , impl HirDatabase > ,
98+ type_ref : & TypeRef ,
99+ ) -> ( Self , Option < TypeNs > ) {
100+ let mut res = None ;
101+ let ty = match type_ref {
95102 TypeRef :: Never => Ty :: simple ( TypeCtor :: Never ) ,
96103 TypeRef :: Tuple ( inner) => {
97104 let inner_tys: Arc < [ Ty ] > = inner. iter ( ) . map ( |tr| Ty :: from_hir ( ctx, tr) ) . collect ( ) ;
@@ -100,7 +107,11 @@ impl Ty {
100107 Substs ( inner_tys) ,
101108 )
102109 }
103- TypeRef :: Path ( path) => Ty :: from_hir_path ( ctx, path) ,
110+ TypeRef :: Path ( path) => {
111+ let ( ty, res_) = Ty :: from_hir_path ( ctx, path) ;
112+ res = res_;
113+ ty
114+ }
104115 TypeRef :: RawPtr ( inner, mutability) => {
105116 let inner_ty = Ty :: from_hir ( ctx, inner) ;
106117 Ty :: apply_one ( TypeCtor :: RawPtr ( * mutability) , inner_ty)
@@ -183,7 +194,8 @@ impl Ty {
183194 }
184195 }
185196 TypeRef :: Error => Ty :: Unknown ,
186- }
197+ } ;
198+ ( ty, res)
187199 }
188200
189201 /// This is only for `generic_predicates_for_param`, where we can't just
@@ -217,17 +229,19 @@ impl Ty {
217229 pub ( crate ) fn from_type_relative_path (
218230 ctx : & TyLoweringContext < ' _ , impl HirDatabase > ,
219231 ty : Ty ,
232+ // We need the original resolution to lower `Self::AssocTy` correctly
233+ res : Option < TypeNs > ,
220234 remaining_segments : PathSegments < ' _ > ,
221- ) -> Ty {
235+ ) -> ( Ty , Option < TypeNs > ) {
222236 if remaining_segments. len ( ) == 1 {
223237 // resolve unselected assoc types
224238 let segment = remaining_segments. first ( ) . unwrap ( ) ;
225- Ty :: select_associated_type ( ctx, ty, segment)
239+ ( Ty :: select_associated_type ( ctx, ty, res , segment) , None )
226240 } else if remaining_segments. len ( ) > 1 {
227241 // FIXME report error (ambiguous associated type)
228- Ty :: Unknown
242+ ( Ty :: Unknown , None )
229243 } else {
230- ty
244+ ( ty , res )
231245 }
232246 }
233247
@@ -236,14 +250,14 @@ impl Ty {
236250 resolution : TypeNs ,
237251 resolved_segment : PathSegment < ' _ > ,
238252 remaining_segments : PathSegments < ' _ > ,
239- ) -> Ty {
253+ ) -> ( Ty , Option < TypeNs > ) {
240254 let ty = match resolution {
241255 TypeNs :: TraitId ( trait_) => {
242256 // if this is a bare dyn Trait, we'll directly put the required ^0 for the self type in there
243257 let self_ty = if remaining_segments. len ( ) == 0 { Some ( Ty :: Bound ( 0 ) ) } else { None } ;
244258 let trait_ref =
245259 TraitRef :: from_resolved_path ( ctx, trait_, resolved_segment, self_ty) ;
246- return if remaining_segments. len ( ) == 1 {
260+ let ty = if remaining_segments. len ( ) == 1 {
247261 let segment = remaining_segments. first ( ) . unwrap ( ) ;
248262 let associated_ty = associated_type_by_name_including_super_traits (
249263 ctx. db ,
@@ -269,6 +283,7 @@ impl Ty {
269283 } else {
270284 Ty :: Dyn ( Arc :: new ( [ GenericPredicate :: Implemented ( trait_ref) ] ) )
271285 } ;
286+ return ( ty, None ) ;
272287 }
273288 TypeNs :: GenericParam ( param_id) => {
274289 let generics =
@@ -306,22 +321,25 @@ impl Ty {
306321 TypeNs :: BuiltinType ( it) => Ty :: from_hir_path_inner ( ctx, resolved_segment, it. into ( ) ) ,
307322 TypeNs :: TypeAliasId ( it) => Ty :: from_hir_path_inner ( ctx, resolved_segment, it. into ( ) ) ,
308323 // FIXME: report error
309- TypeNs :: EnumVariantId ( _) => return Ty :: Unknown ,
324+ TypeNs :: EnumVariantId ( _) => return ( Ty :: Unknown , None ) ,
310325 } ;
311326
312- Ty :: from_type_relative_path ( ctx, ty, remaining_segments)
327+ Ty :: from_type_relative_path ( ctx, ty, Some ( resolution ) , remaining_segments)
313328 }
314329
315- pub ( crate ) fn from_hir_path ( ctx : & TyLoweringContext < ' _ , impl HirDatabase > , path : & Path ) -> Ty {
330+ pub ( crate ) fn from_hir_path (
331+ ctx : & TyLoweringContext < ' _ , impl HirDatabase > ,
332+ path : & Path ,
333+ ) -> ( Ty , Option < TypeNs > ) {
316334 // Resolve the path (in type namespace)
317335 if let Some ( type_ref) = path. type_anchor ( ) {
318- let ty = Ty :: from_hir ( ctx, & type_ref) ;
319- return Ty :: from_type_relative_path ( ctx, ty, path. segments ( ) ) ;
336+ let ( ty , res ) = Ty :: from_hir_ext ( ctx, & type_ref) ;
337+ return Ty :: from_type_relative_path ( ctx, ty, res , path. segments ( ) ) ;
320338 }
321339 let ( resolution, remaining_index) =
322340 match ctx. resolver . resolve_path_in_type_ns ( ctx. db , path. mod_path ( ) ) {
323341 Some ( it) => it,
324- None => return Ty :: Unknown ,
342+ None => return ( Ty :: Unknown , None ) ,
325343 } ;
326344 let ( resolved_segment, remaining_segments) = match remaining_index {
327345 None => (
@@ -336,31 +354,27 @@ impl Ty {
336354 fn select_associated_type (
337355 ctx : & TyLoweringContext < ' _ , impl HirDatabase > ,
338356 self_ty : Ty ,
357+ res : Option < TypeNs > ,
339358 segment : PathSegment < ' _ > ,
340359 ) -> Ty {
341- let def = match ctx . resolver . generic_def ( ) {
342- Some ( def ) => def ,
343- None => return Ty :: Unknown , // this can't actually happen
344- } ;
345- let param_id = match self_ty {
346- Ty :: Placeholder ( id ) if ctx . type_param_mode == TypeParamLoweringMode :: Placeholder => id ,
347- Ty :: Bound ( idx ) if ctx . type_param_mode == TypeParamLoweringMode :: Variable => {
348- let generics = generics ( ctx . db , def ) ;
349- let param_id = if let Some ( ( id , _ ) ) = generics . iter ( ) . nth ( idx as usize ) {
350- id
351- } else {
352- return Ty :: Unknown ;
353- } ;
354- param_id
360+ let traits_from_env : Vec < _ > = match res {
361+ Some ( TypeNs :: SelfType ( impl_id ) ) => match ctx . db . impl_trait ( impl_id ) {
362+ None => return Ty :: Unknown ,
363+ Some ( trait_ref ) => vec ! [ trait_ref . value . trait_ ] ,
364+ } ,
365+ Some ( TypeNs :: GenericParam ( param_id ) ) => {
366+ let predicates = ctx . db . generic_predicates_for_param ( param_id ) ;
367+ predicates
368+ . iter ( )
369+ . filter_map ( |pred| match & pred . value {
370+ GenericPredicate :: Implemented ( tr ) => Some ( tr . trait_ ) ,
371+ _ => None ,
372+ } )
373+ . collect ( )
355374 }
356- _ => return Ty :: Unknown , // Error: Ambiguous associated type
375+ _ => return Ty :: Unknown ,
357376 } ;
358- let predicates = ctx. db . generic_predicates_for_param ( param_id) ;
359- let traits_from_env = predicates. iter ( ) . filter_map ( |pred| match & pred. value {
360- GenericPredicate :: Implemented ( tr) => Some ( tr. trait_ ) ,
361- _ => None ,
362- } ) ;
363- let traits = traits_from_env. flat_map ( |t| all_super_traits ( ctx. db , t) ) ;
377+ let traits = traits_from_env. into_iter ( ) . flat_map ( |t| all_super_traits ( ctx. db , t) ) ;
364378 for t in traits {
365379 if let Some ( associated_ty) = ctx. db . trait_data ( t) . associated_type_by_name ( & segment. name )
366380 {
0 commit comments