@@ -1215,8 +1215,9 @@ fn determine_explicit_self_category<'tcx, AC: AstConv<'tcx>,
1215
1215
this : & AC ,
1216
1216
rscope : & RS ,
1217
1217
self_info : & SelfInfo )
1218
- -> ty:: ExplicitSelfCategory {
1219
- match self_info. explicit_self . node {
1218
+ -> ty:: ExplicitSelfCategory
1219
+ {
1220
+ return match self_info. explicit_self . node {
1220
1221
ast:: SelfStatic => ty:: StaticExplicitSelfCategory ,
1221
1222
ast:: SelfValue ( _) => ty:: ByValueExplicitSelfCategory ,
1222
1223
ast:: SelfRegion ( ref lifetime, mutability, _) => {
@@ -1230,57 +1231,63 @@ fn determine_explicit_self_category<'tcx, AC: AstConv<'tcx>,
1230
1231
ast:: SelfExplicit ( ref ast_type, _) => {
1231
1232
let explicit_type = ast_ty_to_ty ( this, rscope, & * * ast_type) ;
1232
1233
1233
- {
1234
- let inference_context = infer:: new_infer_ctxt ( this. tcx ( ) ) ;
1235
- let expected_self = self_info. untransformed_self_ty ;
1236
- let actual_self = explicit_type;
1237
- let result = infer:: mk_eqty (
1238
- & inference_context,
1239
- false ,
1240
- infer:: Misc ( self_info. explicit_self . span ) ,
1241
- expected_self,
1242
- actual_self) ;
1243
- match result {
1244
- Ok ( _) => {
1245
- inference_context. resolve_regions_and_report_errors ( ) ;
1246
- return ty:: ByValueExplicitSelfCategory
1247
- }
1248
- Err ( _) => { }
1234
+ // We wish to (for now) categorize an explicit self
1235
+ // declaration like `self: SomeType` into either `self`,
1236
+ // `&self`, `&mut self`, or `Box<self>`. We do this here
1237
+ // by some simple pattern matching. A more precise check
1238
+ // is done later in `check_method_self_type()`.
1239
+ //
1240
+ // Examples:
1241
+ //
1242
+ // ```
1243
+ // impl Foo for &T {
1244
+ // // Legal declarations:
1245
+ // fn method1(self: &&T); // ByReferenceExplicitSelfCategory
1246
+ // fn method2(self: &T); // ByValueExplicitSelfCategory
1247
+ // fn method3(self: Box<&T>); // ByBoxExplicitSelfCategory
1248
+ //
1249
+ // // Invalid cases will be caught later by `check_method_self_type`:
1250
+ // fn method_err1(self: &mut T); // ByReferenceExplicitSelfCategory
1251
+ // }
1252
+ // ```
1253
+ //
1254
+ // To do the check we just count the number of "modifiers"
1255
+ // on each type and compare them. If they are the same or
1256
+ // the impl has more, we call it "by value". Otherwise, we
1257
+ // look at the outermost modifier on the method decl and
1258
+ // call it by-ref, by-box as appropriate. For method1, for
1259
+ // example, the impl type has one modifier, but the method
1260
+ // type has two, so we end up with
1261
+ // ByReferenceExplicitSelfCategory.
1262
+
1263
+ let impl_modifiers = count_modifiers ( self_info. untransformed_self_ty ) ;
1264
+ let method_modifiers = count_modifiers ( explicit_type) ;
1265
+
1266
+ debug ! ( "determine_explicit_self_category(self_info.untransformed_self_ty={} \
1267
+ explicit_type={} \
1268
+ modifiers=({},{})",
1269
+ self_info. untransformed_self_ty. repr( this. tcx( ) ) ,
1270
+ explicit_type. repr( this. tcx( ) ) ,
1271
+ impl_modifiers,
1272
+ method_modifiers) ;
1273
+
1274
+ if impl_modifiers >= method_modifiers {
1275
+ ty:: ByValueExplicitSelfCategory
1276
+ } else {
1277
+ match ty:: get ( explicit_type) . sty {
1278
+ ty:: ty_rptr( r, mt) => ty:: ByReferenceExplicitSelfCategory ( r, mt. mutbl ) ,
1279
+ ty:: ty_uniq( _) => ty:: ByBoxExplicitSelfCategory ,
1280
+ _ => ty:: ByValueExplicitSelfCategory ,
1249
1281
}
1250
1282
}
1283
+ }
1284
+ } ;
1251
1285
1252
- match ty:: get ( explicit_type) . sty {
1253
- ty:: ty_rptr( region, tm) => {
1254
- typeck:: require_same_types (
1255
- this. tcx ( ) ,
1256
- None ,
1257
- false ,
1258
- self_info. explicit_self . span ,
1259
- self_info. untransformed_self_ty ,
1260
- tm. ty ,
1261
- || "not a valid type for `self`" . to_string ( ) ) ;
1262
- return ty:: ByReferenceExplicitSelfCategory ( region,
1263
- tm. mutbl )
1264
- }
1265
- ty:: ty_uniq( typ) => {
1266
- typeck:: require_same_types (
1267
- this. tcx ( ) ,
1268
- None ,
1269
- false ,
1270
- self_info. explicit_self . span ,
1271
- self_info. untransformed_self_ty ,
1272
- typ,
1273
- || "not a valid type for `self`" . to_string ( ) ) ;
1274
- return ty:: ByBoxExplicitSelfCategory
1275
- }
1276
- _ => {
1277
- this. tcx ( )
1278
- . sess
1279
- . span_err ( self_info. explicit_self . span ,
1280
- "not a valid type for `self`" ) ;
1281
- return ty:: ByValueExplicitSelfCategory
1282
- }
1283
- }
1286
+ fn count_modifiers ( ty : ty:: t ) -> uint {
1287
+ match ty:: get ( ty) . sty {
1288
+ ty:: ty_rptr( _, mt) => count_modifiers ( mt. ty ) + 1 ,
1289
+ ty:: ty_uniq( t) => count_modifiers ( t) + 1 ,
1290
+ _ => 0 ,
1284
1291
}
1285
1292
}
1286
1293
}
0 commit comments