@@ -177,33 +177,33 @@ fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id) {
177
177
*
178
178
* - impl_m: the method in the impl
179
179
* - impl_tps: the type params declared on the impl itself (not the method!)
180
- * - if_m : the method in the trait
181
- * - if_substs : the substitutions used on the type of the trait
180
+ * - trait_m : the method in the trait
181
+ * - trait_substs : the substitutions used on the type of the trait
182
182
* - self_ty: the self type of the impl
183
183
*/
184
184
fn compare_impl_method ( tcx : ty:: ctxt , sp : span ,
185
185
impl_m : ty:: method , impl_tps : uint ,
186
- if_m : ty:: method , if_substs : ty:: substs ,
186
+ trait_m : ty:: method , trait_substs : ty:: substs ,
187
187
self_ty : ty:: t ) {
188
188
189
- if impl_m. tps != if_m . tps {
190
- tcx. sess . span_err ( sp, ~"method `" + * if_m . ident +
189
+ if impl_m. tps != trait_m . tps {
190
+ tcx. sess . span_err ( sp, ~"method `" + * trait_m . ident +
191
191
~"` has an incompatible set of type parameters") ;
192
192
return ;
193
193
}
194
194
195
- if vec:: len ( impl_m. fty . inputs ) != vec:: len ( if_m . fty . inputs ) {
195
+ if vec:: len ( impl_m. fty . inputs ) != vec:: len ( trait_m . fty . inputs ) {
196
196
tcx. sess . span_err ( sp, fmt ! { "method `%s` has %u parameters \
197
197
but the trait has %u",
198
- * if_m . ident,
198
+ * trait_m . ident,
199
199
vec:: len( impl_m. fty. inputs) ,
200
- vec:: len( if_m . fty. inputs) } ) ;
200
+ vec:: len( trait_m . fty. inputs) } ) ;
201
201
return ;
202
202
}
203
203
204
204
// Perform substitutions so that the trait/impl methods are expressed
205
205
// in terms of the same set of type/region parameters:
206
- // - replace trait type parameters with those from `if_substs `
206
+ // - replace trait type parameters with those from `trait_substs `
207
207
// - replace method parameters on the trait with fresh, dummy parameters
208
208
// that correspond to the parameters we will find on the impl
209
209
// - replace self region with a fresh, dummy region
@@ -212,23 +212,23 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span,
212
212
let impl_fty = ty:: mk_fn ( tcx, impl_m. fty ) ;
213
213
replace_bound_self ( tcx, impl_fty, dummy_self_r)
214
214
} ;
215
- let if_fty = {
216
- let dummy_tps = do vec:: from_fn ( ( * if_m . tps ) . len ( ) ) |i| {
215
+ let trait_fty = {
216
+ let dummy_tps = do vec:: from_fn ( ( * trait_m . tps ) . len ( ) ) |i| {
217
217
// hack: we don't know the def id of the impl tp, but it
218
218
// is not important for unification
219
219
ty:: mk_param ( tcx, i + impl_tps, { crate : 0 , node: 0 } )
220
220
} ;
221
221
let substs = {
222
222
self_r : some( dummy_self_r) ,
223
223
self_ty: some ( self_ty) ,
224
- tps: vec:: append ( if_substs . tps , dummy_tps)
224
+ tps: vec:: append ( trait_substs . tps , dummy_tps)
225
225
} ;
226
- let if_fty = ty:: mk_fn ( tcx, if_m . fty ) ;
227
- ty:: subst ( tcx, substs, if_fty )
226
+ let trait_fty = ty:: mk_fn ( tcx, trait_m . fty ) ;
227
+ ty:: subst ( tcx, substs, trait_fty )
228
228
} ;
229
229
require_same_types (
230
- tcx, none, sp, impl_fty, if_fty ,
231
- || ~"method `" + * if_m . ident + ~"` has an incompatible type") ;
230
+ tcx, none, sp, impl_fty, trait_fty ,
231
+ || ~"method `" + * trait_m . ident + ~"` has an incompatible type") ;
232
232
return ;
233
233
234
234
// Replaces bound references to the self region with `with_r`.
@@ -245,36 +245,59 @@ fn check_methods_against_trait(ccx: @crate_ctxt,
245
245
rp : bool ,
246
246
selfty : ty:: t ,
247
247
a_trait_ty : @ast:: trait_ref ,
248
- ms : ~[ converted_method ] ) {
248
+ impl_ms : ~[ converted_method ] ) {
249
249
250
250
let tcx = ccx. tcx ;
251
251
let ( did, tpt) = instantiate_trait_ref ( ccx, a_trait_ty, rp) ;
252
252
if did. crate == ast:: local_crate {
253
253
ensure_trait_methods ( ccx, did. node ) ;
254
254
}
255
- for vec:: each( * ty:: trait_methods( tcx, did) ) |if_m | {
256
- alt vec:: find( ms , |m| if_m . ident == m . mty. ident) {
257
- some ( { mty : m , id, span} ) {
258
- if m . purity != if_m . purity {
255
+ for vec:: each( * ty:: trait_methods( tcx, did) ) |trait_m | {
256
+ alt vec:: find( impl_ms , |impl_m| trait_m . ident == impl_m . mty. ident) {
257
+ some ( { mty : impl_m , id, span} ) {
258
+ if impl_m . purity != trait_m . purity {
259
259
ccx. tcx . sess . span_err (
260
260
span, fmt ! { "method `%s`'s purity does \
261
261
not match the trait method's \
262
- purity", * m . ident} ) ;
262
+ purity", * impl_m . ident} ) ;
263
263
}
264
264
compare_impl_method (
265
- ccx. tcx , span, m , vec:: len ( tps) ,
266
- if_m , tpt. substs , selfty) ;
265
+ ccx. tcx , span, impl_m , vec:: len ( tps) ,
266
+ trait_m , tpt. substs , selfty) ;
267
267
}
268
268
none {
269
- // FIXME (#2794): if there's a default impl in the trait,
270
- // use that.
271
-
272
- tcx. sess . span_err (
273
- a_trait_ty. path . span ,
274
- fmt ! { "missing method `%s`" , * if_m. ident} ) ;
269
+ // If we couldn't find an implementation for trait_m in
270
+ // the impl, then see if there was a default
271
+ // implementation in the trait itself. If not, raise a
272
+ // "missing method" error.
273
+
274
+ alt tcx. items. get ( did. node ) {
275
+ ast_map:: node_item (
276
+ @{ node: ast:: item_trait ( _, _, trait_methods) , _} , _) {
277
+ let ( _, provided_methods) =
278
+ split_trait_methods ( trait_methods) ;
279
+
280
+ alt vec:: find ( provided_methods, |provided_method|
281
+ provided_method. ident == trait_m. ident ) {
282
+ some ( m) {
283
+ // If there's a provided method with the name we
284
+ // want, then we're fine; nothing else to do.
285
+ }
286
+ none {
287
+ tcx. sess . span_err (
288
+ a_trait_ty. path . span ,
289
+ fmt ! { "missing method `%s`" , * trait_m. ident} ) ;
290
+ }
291
+ }
292
+ }
293
+ _ {
294
+ tcx. sess . bug ( ~"check_methods_against_trait ( ) : trait_ref \
295
+ didn' t refer to a trait ") ;
296
+ }
297
+ }
275
298
}
276
299
} // alt
277
- } // |if_m |
300
+ } // |trait_m |
278
301
} // fn
279
302
280
303
fn convert_field ( ccx : @crate_ctxt ,
@@ -324,7 +347,7 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
324
347
write_ty_to_tcx ( tcx, it. id , tpt. ty ) ;
325
348
get_enum_variant_types ( ccx, tpt. ty , variants, ty_params, rp) ;
326
349
}
327
- ast:: item_impl ( tps, trt , selfty, ms) {
350
+ ast:: item_impl ( tps, trait_ref , selfty, ms) {
328
351
let i_bounds = ty_param_bounds ( ccx, tps) ;
329
352
let selfty = ccx. to_ty ( type_rscope ( rp) , selfty) ;
330
353
write_ty_to_tcx ( tcx, it. id , selfty) ;
@@ -334,7 +357,7 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
334
357
ty: selfty} ) ;
335
358
336
359
let cms = convert_methods ( ccx, ms, rp, i_bounds, selfty) ;
337
- for trt . each |t| {
360
+ for trait_ref . each |t| {
338
361
check_methods_against_trait( ccx, tps, rp, selfty, t, cms) ;
339
362
}
340
363
}
@@ -351,11 +374,11 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
351
374
let _cms = convert_methods ( ccx, provided_methods, rp, bounds, selfty) ;
352
375
// FIXME (#2616): something like this, when we start having
353
376
// trait inheritance?
354
- // for trt .each |t| {
377
+ // for trait_ref .each |t| {
355
378
// check_methods_against_trait(ccx, tps, rp, selfty, t, cms);
356
379
// }
357
380
}
358
- ast:: item_class ( tps, traits , members, m_ctor, m_dtor) {
381
+ ast:: item_class ( tps, trait_refs , members, m_ctor, m_dtor) {
359
382
// Write the class type
360
383
let tpt = ty_of_item ( ccx, it) ;
361
384
write_ty_to_tcx ( tcx, it. id , tpt. ty ) ;
@@ -405,11 +428,11 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
405
428
let { bounds, substs} = mk_substs ( ccx, tps, rp) ;
406
429
let selfty = ty:: mk_class ( tcx, local_def ( it. id ) , substs) ;
407
430
let cms = convert_methods ( ccx, methods, rp, bounds, selfty) ;
408
- for traits . each |trt | {
409
- check_methods_against_trait( ccx, tps, rp, selfty, trt , cms) ;
410
- // trt .impl_id represents (class, trait) pair
411
- write_ty_to_tcx ( tcx, trt . impl_id , tpt. ty ) ;
412
- tcx. tcache . insert ( local_def ( trt . impl_id ) , tpt) ;
431
+ for trait_refs . each |trait_ref | {
432
+ check_methods_against_trait( ccx, tps, rp, selfty, trait_ref , cms) ;
433
+ // trait_ref .impl_id represents (class, trait) pair
434
+ write_ty_to_tcx ( tcx, trait_ref . impl_id , tpt. ty ) ;
435
+ tcx. tcache . insert ( local_def ( trait_ref . impl_id ) , tpt) ;
413
436
}
414
437
}
415
438
_ {
0 commit comments