11use crate :: prelude:: * ;
22
3- use crate :: ty:: { Constraints , Solver , TypeVars } ;
3+ use crate :: ty:: { Constraints , Solver , TypeVarId , TypeVars } ;
44
55use hir:: * ;
66use thir:: Thir ;
@@ -37,10 +37,19 @@ impl<'ctx, 'hir> Pass<'ctx, 'hir> for ThirGen<'ctx, 'hir> {
3737 thir_gen. add_function_constraints ( function) ;
3838 }
3939
40+ // Add constraints for each trait implementation.
41+ for trait_implementation in thir_gen. hir . trait_implementations . keys ( ) {
42+ thir_gen. add_trait_implementation ( trait_implementation) ;
43+ }
44+
45+ // Collect trait implementations.
46+ let trait_implementations = thir_gen. hir . trait_implementations . keys ( ) . cloned ( ) . collect ( ) ;
47+
4048 // Run the solver.
4149 let types = Solver :: run (
4250 & mut thir_gen. ctx . types ,
4351 & mut thir_gen. type_vars ,
52+ & trait_implementations,
4453 & thir_gen. constraints ,
4554 ) ;
4655
@@ -65,13 +74,18 @@ impl<'ctx, 'hir> ThirGen<'ctx, 'hir> {
6574 fn add_function_declaration ( & mut self , function_id : FunctionId ) {
6675 let function = & self . hir [ function_id] ;
6776
68- self . constraints . equal (
69- self . type_vars . intern ( function. binding ) ,
70- self . type_vars . intern ( self . ctx . types . function (
71- function. signature . parameters . iter ( ) . map ( |( _, ty) | * ty) ,
72- function. signature . return_ty ,
73- ) ) ,
74- ) ;
77+ let binding = self . type_vars . intern ( function. binding ) ;
78+ let signature = self . signature_as_type_var ( & function. signature ) ;
79+
80+ self . constraints . equal ( binding, signature) ;
81+ }
82+
83+ /// Produce a [`TypeVar`] for the given [`FunctionSignature`].
84+ fn signature_as_type_var ( & mut self , signature : & FunctionSignature ) -> TypeVarId {
85+ self . type_vars . intern ( self . ctx . types . function (
86+ signature. parameters . iter ( ) . map ( |( _, ty) | * ty) ,
87+ signature. return_ty ,
88+ ) )
7589 }
7690
7791 fn add_function_constraints ( & mut self , function_id : FunctionId ) {
@@ -96,6 +110,32 @@ impl<'ctx, 'hir> ThirGen<'ctx, 'hir> {
96110 self . add_block_constraints ( & ctx, function. entry ) ;
97111 }
98112
113+ /// Add constraints required to check a trait implementation. Will ensure that all implemented
114+ /// methods match the signature of the trait, but does not verify whether all methods were
115+ /// implemented.
116+ fn add_trait_implementation ( & mut self , implementation_key : & TraitImplementationKey ) {
117+ let implementation = & self . hir [ implementation_key] ;
118+ let target_trait = & self . hir [ implementation_key. trait_id ] ;
119+
120+ let implementing_ty = implementation_key. ty ;
121+
122+ for ( method_id, method) in implementation. methods . iter_pairs ( ) {
123+ // Fetch the intended signature.
124+ let trait_method_signature = self . signature_as_type_var (
125+ & target_trait. methods [ method_id]
126+ . clone ( )
127+ . with_self ( implementing_ty) ,
128+ ) ;
129+
130+ // Fetch the method signature.
131+ let implemented_signature = self . signature_as_type_var ( & self . hir [ * method] . signature ) ;
132+
133+ // Emit constraint that they're equal.
134+ self . constraints
135+ . equal ( trait_method_signature, implemented_signature) ;
136+ }
137+ }
138+
99139 fn add_block_constraints ( & mut self , ctx : & ConstraintCtx , block_id : BlockId ) {
100140 let block = & self . hir [ block_id] ;
101141
@@ -342,6 +382,25 @@ impl<'ctx, 'hir> ThirGen<'ctx, 'hir> {
342382 self . type_vars . intern ( TypeVar :: Field ( lhs, * field) ) ,
343383 ) ;
344384 }
385+ Expression :: Path ( Path {
386+ ty,
387+ target_trait,
388+ item,
389+ } ) => {
390+ let ty_var = self . type_vars . intern ( * ty) ;
391+
392+ // Enforce the type implements the trait.
393+ self . constraints . implements ( ty_var, * target_trait) ;
394+
395+ // This expression results in the signature of the trait item.
396+ let item_signature = self . hir [ * target_trait] . methods [ * item]
397+ . clone ( )
398+ // Since the trait method signature is used, substitute `Self` with the current
399+ // type.
400+ . with_self ( * ty) ;
401+ let signature_var = self . signature_as_type_var ( & item_signature) ;
402+ self . constraints . equal ( expression, signature_var) ;
403+ }
345404 }
346405 }
347406
0 commit comments