@@ -11,47 +11,112 @@ use syntax::ast::item_impl;
11
11
use syntax:: ast:: node_id;
12
12
use syntax:: ast:: self_ty_;
13
13
use syntax:: ast:: trait_ref;
14
- use syntax:: ast_util:: def_id_of_def;
14
+ use syntax:: ast_util:: { def_id_of_def, dummy_sp } ;
15
15
use syntax:: codemap:: span;
16
16
use syntax:: print:: pprust;
17
17
use syntax:: visit:: { default_simple_visitor, mk_simple_visitor, visit_crate} ;
18
18
use middle:: resolve:: { Impl , MethodInfo } ;
19
19
use middle:: ty;
20
- use middle:: ty:: { substs, ty_class, ty_enum, ty_param_bounds_and_ty} ;
20
+ use middle:: ty:: { DerivedFieldInfo , substs, ty_class, ty_enum} ;
21
+ use middle:: ty:: { ty_param_bounds_and_ty} ;
21
22
use /*middle::typeck::*/ check:: method;
23
+ use /*middle::typeck::*/ check:: vtable;
22
24
use /*middle::typeck::*/ infer:: infer_ctxt;
25
+ use /*middle::typeck::*/ vtable:: { LocationInfo , VtableContext } ;
26
+ use util:: ppaux;
27
+
28
+ struct MethodMatch {
29
+ method_def_id : def_id ,
30
+ type_parameter_substitutions : @~[ ty:: t ] ,
31
+ vtable_result : Option < vtable_res >
32
+ }
23
33
24
34
struct DerivingChecker {
25
- crate_context : @crate_ctxt ,
26
- inference_context : infer_ctxt
35
+ crate_context : @crate_ctxt
27
36
}
28
37
29
38
fn DerivingChecker_new ( crate_context : @crate_ctxt ) -> DerivingChecker {
30
39
DerivingChecker {
31
40
crate_context : crate_context,
32
- inference_context : infer:: new_infer_ctxt ( crate_context. tcx )
33
41
}
34
42
}
35
43
44
+ struct TyParamSubstsAndVtableResult {
45
+ type_parameter_substitutions : @~[ ty:: t ] ,
46
+ vtable_result : Option < vtable_res >
47
+ }
48
+
36
49
impl DerivingChecker {
37
50
/// Matches one substructure type against an implementation.
38
51
fn match_impl_method ( impl_info : @Impl ,
39
52
substructure_type : ty:: t ,
40
- method_info : @MethodInfo ) -> bool {
41
- // XXX: Generics and regions are not handled properly.
53
+ method_info : @MethodInfo ,
54
+ span : span ) ->
55
+ Option < TyParamSubstsAndVtableResult > {
42
56
let tcx = self . crate_context . tcx ;
43
- let impl_self_ty = ty:: lookup_item_type ( tcx, impl_info. did ) . ty ;
57
+
58
+ let impl_self_tpbt = ty:: lookup_item_type ( tcx, impl_info. did ) ;
44
59
let transformed_type = method:: transform_self_type_for_method (
45
- tcx, None , impl_self_ty, method_info. self_type ) ;
46
- return infer:: can_mk_subty ( self . inference_context ,
47
- substructure_type,
48
- transformed_type) . is_ok ( ) ;
60
+ tcx, None , impl_self_tpbt. ty , method_info. self_type ) ;
61
+
62
+ let inference_context = infer:: new_infer_ctxt ( self . crate_context . tcx ) ;
63
+ let substs = {
64
+ self_r: None ,
65
+ self_ty: None ,
66
+ tps: inference_context. next_ty_vars ( impl_self_tpbt. bounds . len ( ) )
67
+ } ;
68
+ let transformed_type = ty:: subst (
69
+ self . crate_context . tcx , & substs, transformed_type) ;
70
+
71
+ debug ! ( "(matching impl method) substructure type %s, transformed \
72
+ type %s, subst tps %u",
73
+ ppaux:: ty_to_str( self . crate_context. tcx, substructure_type) ,
74
+ ppaux:: ty_to_str( self . crate_context. tcx, transformed_type) ,
75
+ substs. tps. len( ) ) ;
76
+
77
+ if !infer:: mk_subty ( inference_context,
78
+ true ,
79
+ ast_util:: dummy_sp ( ) ,
80
+ substructure_type,
81
+ transformed_type) . is_ok ( ) {
82
+ return None ;
83
+ }
84
+
85
+ // Get the vtables.
86
+ let vtable_result;
87
+ if substs. tps . len ( ) == 0 {
88
+ vtable_result = None ;
89
+ } else {
90
+ let vcx = VtableContext {
91
+ ccx : self . crate_context ,
92
+ infcx : inference_context
93
+ } ;
94
+ let location_info = LocationInfo {
95
+ span : span,
96
+ id : impl_info. did . node
97
+ } ;
98
+ vtable_result = Some ( vtable:: lookup_vtables ( & vcx,
99
+ & location_info,
100
+ impl_self_tpbt. bounds ,
101
+ & substs,
102
+ false ,
103
+ false ) ) ;
104
+ }
105
+
106
+ // Extract the type parameter substitutions.
107
+ let type_parameter_substitutions = @substs. tps . map ( |ty_var|
108
+ inference_context. resolve_type_vars_if_possible ( * ty_var) ) ;
109
+
110
+ Some ( TyParamSubstsAndVtableResult {
111
+ type_parameter_substitutions : type_parameter_substitutions,
112
+ vtable_result : vtable_result
113
+ } )
49
114
}
50
115
51
116
fn check_deriving_for_substructure_type( substructure_type : ty:: t ,
52
117
trait_ref : @trait_ref ,
53
118
impl_span : span ) ->
54
- Option < def_id > {
119
+ Option < MethodMatch > {
55
120
let tcx = self . crate_context . tcx ;
56
121
let sess = tcx. sess ;
57
122
let coherence_info = self . crate_context . coherence_info ;
@@ -64,12 +129,25 @@ impl DerivingChecker {
64
129
Some ( impls) => {
65
130
// Try to unify each of these impls with the substructure
66
131
// type.
67
- for impls. each |impl_info| {
68
- for impl_info. methods. each |method_info| {
69
- if self . match_impl_method ( * impl_info,
70
- substructure_type,
71
- * method_info) {
72
- return Some ( method_info. did ) ;
132
+ //
133
+ // NB: Using range to avoid a recursive-use-of-dvec error.
134
+ for uint:: range( 0 , impls. len( ) ) |i| {
135
+ let impl_info = impls[ i] ;
136
+ for uint:: range( 0 , impl_info. methods. len( ) ) |j| {
137
+ let method_info = impl_info. methods [ j] ;
138
+ match self . match_impl_method ( impl_info,
139
+ substructure_type,
140
+ method_info,
141
+ trait_ref. path . span ) {
142
+ Some ( move result) => {
143
+ return Some ( MethodMatch {
144
+ method_def_id : method_info. did ,
145
+ type_parameter_substitutions :
146
+ result. type_parameter_substitutions ,
147
+ vtable_result : result. vtable_result
148
+ } ) ;
149
+ }
150
+ None => { } // Continue.
73
151
}
74
152
}
75
153
}
@@ -91,8 +169,15 @@ impl DerivingChecker {
91
169
match self . check_deriving_for_substructure_type( field_type,
92
170
trait_ref,
93
171
impl_span) {
94
- Some ( method_target_def_id) => {
95
- field_info. push ( method_static ( method_target_def_id) ) ;
172
+ Some ( method_match) => {
173
+ field_info. push( DerivedFieldInfo {
174
+ method_origin :
175
+ method_static( method_match. method_def_id) ,
176
+ type_parameter_substitutions :
177
+ method_match. type_parameter_substitutions,
178
+ vtable_result :
179
+ method_match. vtable_result
180
+ } ) ;
96
181
}
97
182
None => {
98
183
let trait_str = pprust:: path_to_str(
@@ -127,9 +212,15 @@ impl DerivingChecker {
127
212
for enum_variant_info. args. eachi |i, variant_arg_type| {
128
213
match self . check_deriving_for_substructure_type(
129
214
* variant_arg_type, trait_ref, impl_span) {
130
- Some ( method_target_def_id) => {
131
- variant_methods. push ( method_static (
132
- method_target_def_id) ) ;
215
+ Some ( method_match) => {
216
+ variant_methods. push( DerivedFieldInfo {
217
+ method_origin :
218
+ method_static( method_match. method_def_id) ,
219
+ type_parameter_substitutions :
220
+ method_match. type_parameter_substitutions,
221
+ vtable_result :
222
+ method_match. vtable_result
223
+ } ) ;
133
224
}
134
225
None => {
135
226
let trait_str = pprust:: path_to_str(
0 commit comments