@@ -814,7 +814,14 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
814814 fn check_call ( fcx : @fn_ctxt , sp : span , call_expr_id : ast:: node_id ,
815815 f : @ast:: expr , args : ~[ @ast:: expr ] ) -> bool {
816816
817- let mut bot = check_expr ( fcx, f, none) ;
817+ // Index expressions need to be handled seperately, to inform
818+ // them that they appear in call position.
819+ let mut bot = alt f. node {
820+ ast:: expr_field ( base, field, tys) {
821+ check_field ( fcx, f, true , base, field, tys)
822+ }
823+ _ { check_expr( fcx, f, none) }
824+ } ;
818825 let fn_ty = fcx. expr_ty ( f) ;
819826
820827 // Call the generic checker.
@@ -1051,6 +1058,101 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
10511058 is_loop_body, some ( fcx) ) ;
10521059 }
10531060
1061+ // Check field access expressions
1062+ fn check_field ( fcx : @fn_ctxt , expr : @ast:: expr , is_callee : bool ,
1063+ base : @ast:: expr , field : ast:: ident , tys : ~[ @ast:: ty ] )
1064+ -> bool {
1065+ let tcx = fcx. ccx . tcx ;
1066+ let bot = check_expr ( fcx, base, none) ;
1067+ let expr_t = structurally_resolved_type ( fcx, expr. span ,
1068+ fcx. expr_ty ( base) ) ;
1069+ let base_t = do_autoderef ( fcx, expr. span , expr_t) ;
1070+ let mut handled = false ;
1071+ let n_tys = vec:: len ( tys) ;
1072+ alt structure_of ( fcx, expr. span , base_t) {
1073+ ty:: ty_rec ( fields) {
1074+ alt ty:: field_idx ( field, fields) {
1075+ some ( ix) {
1076+ if n_tys > 0 u {
1077+ tcx. sess . span_err ( expr. span ,
1078+ "can't provide type parameters \
1079+ to a field access") ;
1080+ }
1081+ fcx. write_ty ( expr. id , fields[ ix] . mt . ty ) ;
1082+ handled = true ;
1083+ }
1084+ _ { }
1085+ }
1086+ }
1087+ ty:: ty_class ( base_id, substs) {
1088+ // This is just for fields -- the same code handles
1089+ // methods in both classes and traits
1090+
1091+ // (1) verify that the class id actually has a field called
1092+ // field
1093+ #debug ( "class named %s" , ty_to_str ( tcx, base_t) ) ;
1094+ /*
1095+ check whether this is a self-reference or not, which
1096+ determines whether we look at all fields or only public
1097+ ones
1098+ */
1099+ let cls_items = if self_ref ( fcx, base. id ) {
1100+ // base expr is "self" -- consider all fields
1101+ ty:: lookup_class_fields ( tcx, base_id)
1102+ }
1103+ else {
1104+ lookup_public_fields ( tcx, base_id)
1105+ } ;
1106+ alt lookup_field_ty ( tcx, base_id, cls_items, field, substs) {
1107+ some ( field_ty) {
1108+ // (2) look up what field's type is, and return it
1109+ fcx. write_ty ( expr. id , field_ty) ;
1110+ handled = true ;
1111+ }
1112+ none { }
1113+ }
1114+ }
1115+ _ { }
1116+ }
1117+ if !handled {
1118+ let tps = vec:: map ( tys, |ty| fcx. to_ty ( ty) ) ;
1119+ let is_self_ref = self_ref ( fcx, base. id ) ;
1120+
1121+ // this will be the call or block that immediately
1122+ // encloses the method call
1123+ let borrow_scope = fcx. tcx ( ) . region_map . get ( expr. id ) ;
1124+
1125+ let lkup = method:: lookup ( fcx, expr, base, borrow_scope,
1126+ expr. id , field, expr_t, tps,
1127+ is_self_ref) ;
1128+ alt lkup. method ( ) {
1129+ some ( entry) {
1130+ fcx. ccx . method_map . insert ( expr. id , entry) ;
1131+
1132+ // If we have resolved to a method but this is not in
1133+ // a callee position, error
1134+ if !is_callee {
1135+ tcx. sess . span_err (
1136+ expr. span ,
1137+ "attempted to take value of method \
1138+ (try writing an anonymous function)") ;
1139+ }
1140+ }
1141+ none {
1142+ let t_err = fcx. infcx . resolve_type_vars_if_possible ( expr_t) ;
1143+ let msg = #fmt[ "attempted access of field `%s` on type `%s`, \
1144+ but no public field or method with that name \
1145+ was found",
1146+ * field, fcx. infcx . ty_to_str ( t_err) ] ;
1147+ tcx. sess . span_err ( expr. span , msg) ;
1148+ // NB: Adding a bogus type to allow typechecking to continue
1149+ fcx. write_ty ( expr. id , fcx. infcx . next_ty_var ( ) ) ;
1150+ }
1151+ }
1152+ }
1153+ ret bot;
1154+ }
1155+
10541156
10551157 let tcx = fcx. ccx . tcx ;
10561158 let id = expr. id ;
@@ -1489,84 +1591,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
14891591 }
14901592 }
14911593 ast:: expr_field ( base, field, tys) {
1492- bot |= check_expr ( fcx, base, none) ;
1493- let expr_t = structurally_resolved_type ( fcx, expr. span ,
1494- fcx. expr_ty ( base) ) ;
1495- let base_t = do_autoderef ( fcx, expr. span , expr_t) ;
1496- let mut handled = false ;
1497- let n_tys = vec:: len ( tys) ;
1498- alt structure_of ( fcx, expr. span , base_t) {
1499- ty:: ty_rec ( fields) {
1500- alt ty:: field_idx ( field, fields) {
1501- some ( ix) {
1502- if n_tys > 0 u {
1503- tcx. sess . span_err ( expr. span ,
1504- "can't provide type parameters \
1505- to a field access") ;
1506- }
1507- fcx. write_ty ( id, fields[ ix] . mt . ty ) ;
1508- handled = true ;
1509- }
1510- _ { }
1511- }
1512- }
1513- ty:: ty_class ( base_id, substs) {
1514- // This is just for fields -- the same code handles
1515- // methods in both classes and traits
1516-
1517- // (1) verify that the class id actually has a field called
1518- // field
1519- #debug ( "class named %s" , ty_to_str ( tcx, base_t) ) ;
1520- /*
1521- check whether this is a self-reference or not, which
1522- determines whether we look at all fields or only public
1523- ones
1524- */
1525- let cls_items = if self_ref ( fcx, base. id ) {
1526- // base expr is "self" -- consider all fields
1527- ty:: lookup_class_fields ( tcx, base_id)
1528- }
1529- else {
1530- lookup_public_fields ( tcx, base_id)
1531- } ;
1532- alt lookup_field_ty ( tcx, base_id, cls_items, field, substs) {
1533- some ( field_ty) {
1534- // (2) look up what field's type is, and return it
1535- fcx. write_ty ( id, field_ty) ;
1536- handled = true ;
1537- }
1538- none { }
1539- }
1540- }
1541- _ { }
1542- }
1543- if !handled {
1544- let tps = vec:: map ( tys, |ty| fcx. to_ty ( ty) ) ;
1545- let is_self_ref = self_ref ( fcx, base. id ) ;
1546-
1547- // this will be the call or block that immediately
1548- // encloses the method call
1549- let borrow_scope = fcx. tcx ( ) . region_map . get ( expr. id ) ;
1550-
1551- let lkup = method:: lookup ( fcx, expr, base, borrow_scope,
1552- expr. id , field, expr_t, tps,
1553- is_self_ref) ;
1554- alt lkup. method ( ) {
1555- some ( entry) {
1556- fcx. ccx . method_map . insert ( id, entry) ;
1557- }
1558- none {
1559- let t_err = fcx. infcx . resolve_type_vars_if_possible ( expr_t) ;
1560- let msg = #fmt[ "attempted access of field `%s` on type `%s`, \
1561- but no public field or method with that name \
1562- was found",
1563- * field, fcx. infcx . ty_to_str ( t_err) ] ;
1564- tcx. sess . span_err ( expr. span , msg) ;
1565- // NB: Adding a bogus type to allow typechecking to continue
1566- fcx. write_ty ( id, fcx. infcx . next_ty_var ( ) ) ;
1567- }
1568- }
1569- }
1594+ bot = check_field ( fcx, expr, false , base, field, tys) ;
15701595 }
15711596 ast:: expr_index ( base, idx) {
15721597 bot |= check_expr ( fcx, base, none) ;
0 commit comments