@@ -4,7 +4,7 @@ use chalk_ir::cast::Cast;
44use hir_def:: {
55 path:: { Path , PathSegment } ,
66 resolver:: { ResolveValueResult , TypeNs , ValueNs } ,
7- AdtId , AssocItemId , EnumVariantId , ItemContainerId , Lookup ,
7+ AdtId , AssocItemId , EnumVariantId , GenericDefId , ItemContainerId , Lookup ,
88} ;
99use hir_expand:: name:: Name ;
1010use stdx:: never;
@@ -13,22 +13,33 @@ use crate::{
1313 builder:: ParamKind ,
1414 consteval,
1515 method_resolution:: { self , VisibleFromModule } ,
16+ to_chalk_trait_id,
1617 utils:: generics,
1718 InferenceDiagnostic , Interner , Substitution , TraitRefExt , Ty , TyBuilder , TyExt , TyKind ,
1819 ValueTyDefId ,
1920} ;
2021
2122use super :: { ExprOrPatId , InferenceContext , TraitRef } ;
2223
23- impl < ' a > InferenceContext < ' a > {
24+ impl InferenceContext < ' _ > {
2425 pub ( super ) fn infer_path ( & mut self , path : & Path , id : ExprOrPatId ) -> Option < Ty > {
25- let ty = self . resolve_value_path ( path, id) ?;
26- let ty = self . insert_type_vars ( ty) ;
26+ let ( value_def, generic_def, substs) = match self . resolve_value_path ( path, id) ? {
27+ ValuePathResolution :: GenericDef ( value_def, generic_def, substs) => {
28+ ( value_def, generic_def, substs)
29+ }
30+ ValuePathResolution :: NonGeneric ( ty) => return Some ( ty) ,
31+ } ;
32+ let substs = self . insert_type_vars ( substs) ;
33+ let substs = self . normalize_associated_types_in ( substs) ;
34+
35+ self . add_required_obligations_for_value_path ( generic_def, & substs) ;
36+
37+ let ty = self . db . value_ty ( value_def) . substitute ( Interner , & substs) ;
2738 let ty = self . normalize_associated_types_in ( ty) ;
2839 Some ( ty)
2940 }
3041
31- fn resolve_value_path ( & mut self , path : & Path , id : ExprOrPatId ) -> Option < Ty > {
42+ fn resolve_value_path ( & mut self , path : & Path , id : ExprOrPatId ) -> Option < ValuePathResolution > {
3243 let ( value, self_subst) = if let Some ( type_ref) = path. type_anchor ( ) {
3344 let last = path. segments ( ) . last ( ) ?;
3445
@@ -56,9 +67,9 @@ impl<'a> InferenceContext<'a> {
5667 }
5768 } ;
5869
59- let typable : ValueTyDefId = match value {
70+ let value_def = match value {
6071 ValueNs :: LocalBinding ( pat) => match self . result . type_of_binding . get ( pat) {
61- Some ( ty) => return Some ( ty. clone ( ) ) ,
72+ Some ( ty) => return Some ( ValuePathResolution :: NonGeneric ( ty. clone ( ) ) ) ,
6273 None => {
6374 never ! ( "uninferred pattern?" ) ;
6475 return None ;
@@ -82,36 +93,81 @@ impl<'a> InferenceContext<'a> {
8293 let substs = generics. placeholder_subst ( self . db ) ;
8394 let ty = self . db . impl_self_ty ( impl_id) . substitute ( Interner , & substs) ;
8495 if let Some ( ( AdtId :: StructId ( struct_id) , substs) ) = ty. as_adt ( ) {
85- let ty = self . db . value_ty ( struct_id. into ( ) ) . substitute ( Interner , & substs) ;
86- return Some ( ty) ;
96+ return Some ( ValuePathResolution :: GenericDef (
97+ struct_id. into ( ) ,
98+ struct_id. into ( ) ,
99+ substs. clone ( ) ,
100+ ) ) ;
87101 } else {
88102 // FIXME: report error, invalid Self reference
89103 return None ;
90104 }
91105 }
92- ValueNs :: GenericParam ( it) => return Some ( self . db . const_param_ty ( it) ) ,
106+ ValueNs :: GenericParam ( it) => {
107+ return Some ( ValuePathResolution :: NonGeneric ( self . db . const_param_ty ( it) ) )
108+ }
93109 } ;
94110
95111 let ctx = crate :: lower:: TyLoweringContext :: new ( self . db , & self . resolver ) ;
96- let substs = ctx. substs_from_path ( path, typable , true ) ;
112+ let substs = ctx. substs_from_path ( path, value_def , true ) ;
97113 let substs = substs. as_slice ( Interner ) ;
98114 let parent_substs = self_subst. or_else ( || {
99- let generics = generics ( self . db . upcast ( ) , typable . to_generic_def_id ( ) ?) ;
115+ let generics = generics ( self . db . upcast ( ) , value_def . to_generic_def_id ( ) ?) ;
100116 let parent_params_len = generics. parent_generics ( ) ?. len ( ) ;
101117 let parent_args = & substs[ substs. len ( ) - parent_params_len..] ;
102118 Some ( Substitution :: from_iter ( Interner , parent_args) )
103119 } ) ;
104120 let parent_substs_len = parent_substs. as_ref ( ) . map_or ( 0 , |s| s. len ( Interner ) ) ;
105121 let mut it = substs. iter ( ) . take ( substs. len ( ) - parent_substs_len) . cloned ( ) ;
106- let ty = TyBuilder :: value_ty ( self . db , typable, parent_substs)
122+
123+ let Some ( generic_def) = value_def. to_generic_def_id ( ) else {
124+ // `value_def` is the kind of item that can never be generic (i.e. statics, at least
125+ // currently). We can just skip the binders to get its type.
126+ let ( ty, binders) = self . db . value_ty ( value_def) . into_value_and_skipped_binders ( ) ;
127+ stdx:: always!(
128+ parent_substs. is_none( ) && binders. is_empty( Interner ) ,
129+ "non-empty binders for non-generic def" ,
130+ ) ;
131+ return Some ( ValuePathResolution :: NonGeneric ( ty) ) ;
132+ } ;
133+ let builder = TyBuilder :: subst_for_def ( self . db , generic_def, parent_substs) ;
134+ let substs = builder
107135 . fill ( |x| {
108136 it. next ( ) . unwrap_or_else ( || match x {
109137 ParamKind :: Type => self . result . standard_types . unknown . clone ( ) . cast ( Interner ) ,
110138 ParamKind :: Const ( ty) => consteval:: unknown_const_as_generic ( ty. clone ( ) ) ,
111139 } )
112140 } )
113141 . build ( ) ;
114- Some ( ty)
142+
143+ Some ( ValuePathResolution :: GenericDef ( value_def, generic_def, substs) )
144+ }
145+
146+ fn add_required_obligations_for_value_path ( & mut self , def : GenericDefId , subst : & Substitution ) {
147+ let predicates = self . db . generic_predicates ( def) ;
148+ for predicate in predicates. iter ( ) {
149+ let ( predicate, binders) =
150+ predicate. clone ( ) . substitute ( Interner , & subst) . into_value_and_skipped_binders ( ) ;
151+ // Quantified where clauses are not yet handled.
152+ stdx:: always!( binders. is_empty( Interner ) ) ;
153+ self . push_obligation ( predicate. cast ( Interner ) ) ;
154+ }
155+
156+ // We need to add `Self: Trait` obligation when `def` is a trait assoc item.
157+ let container = match def {
158+ GenericDefId :: FunctionId ( id) => id. lookup ( self . db . upcast ( ) ) . container ,
159+ GenericDefId :: ConstId ( id) => id. lookup ( self . db . upcast ( ) ) . container ,
160+ _ => return ,
161+ } ;
162+
163+ if let ItemContainerId :: TraitId ( trait_) = container {
164+ let param_len = generics ( self . db . upcast ( ) , def) . len_self ( ) ;
165+ let parent_subst =
166+ Substitution :: from_iter ( Interner , subst. iter ( Interner ) . skip ( param_len) ) ;
167+ let trait_ref =
168+ TraitRef { trait_id : to_chalk_trait_id ( trait_) , substitution : parent_subst } ;
169+ self . push_obligation ( trait_ref. cast ( Interner ) ) ;
170+ }
115171 }
116172
117173 fn resolve_assoc_item (
@@ -307,3 +363,10 @@ impl<'a> InferenceContext<'a> {
307363 Some ( ( ValueNs :: EnumVariantId ( variant) , subst. clone ( ) ) )
308364 }
309365}
366+
367+ enum ValuePathResolution {
368+ // It's awkward to wrap a single ID in two enums, but we need both and this saves fallible
369+ // conversion between them + `unwrap()`.
370+ GenericDef ( ValueTyDefId , GenericDefId , Substitution ) ,
371+ NonGeneric ( Ty ) ,
372+ }
0 commit comments