@@ -277,7 +277,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
277
277
ExprKind :: Struct ( ref qpath, fields, ref base_expr) => {
278
278
self . check_expr_struct ( expr, expected, qpath, fields, base_expr)
279
279
}
280
- ExprKind :: Field ( ref base, field) => self . check_field ( expr, needs, & base, field) ,
280
+ ExprKind :: Field ( ref base, field, _ ) => self . check_field ( expr, needs, & base, field) ,
281
281
ExprKind :: Index ( ref base, ref idx) => self . check_expr_index ( base, idx, needs, expr) ,
282
282
ExprKind :: Yield ( ref value, ref src) => self . check_expr_yield ( value, expr, src) ,
283
283
hir:: ExprKind :: Err => tcx. types . err ,
@@ -1440,6 +1440,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1440
1440
display
1441
1441
}
1442
1442
1443
+ fn complain_about_invalid_type_params ( & self , args : Option < Span > ) {
1444
+ if let Some ( args) = args {
1445
+ self . tcx
1446
+ . sess
1447
+ . struct_span_err ( args, "field expressions may not have generic arguments" )
1448
+ . emit ( ) ;
1449
+ }
1450
+ }
1451
+
1443
1452
// Check field access expressions
1444
1453
fn check_field (
1445
1454
& self ,
@@ -1452,6 +1461,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1452
1461
let expr_t = self . structurally_resolved_type ( base. span , expr_t) ;
1453
1462
let mut private_candidate = None ;
1454
1463
let mut autoderef = self . autoderef ( expr. span , expr_t) ;
1464
+ let invalid_args = match & expr. kind {
1465
+ ExprKind :: Field ( _, _, Some ( args) ) => Some ( * args) ,
1466
+ _ => None ,
1467
+ } ;
1455
1468
while let Some ( ( base_t, _) ) = autoderef. next ( ) {
1456
1469
match base_t. kind {
1457
1470
ty:: Adt ( base_def, substs) if !base_def. is_enum ( ) => {
@@ -1471,6 +1484,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1471
1484
autoderef. finalize ( self ) ;
1472
1485
1473
1486
self . tcx . check_stability ( field. did , Some ( expr. hir_id ) , expr. span ) ;
1487
+ self . complain_about_invalid_type_params ( invalid_args) ;
1474
1488
return field_ty;
1475
1489
}
1476
1490
private_candidate = Some ( ( base_def. did , field_ty) ) ;
@@ -1486,6 +1500,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1486
1500
autoderef. finalize ( self ) ;
1487
1501
1488
1502
self . write_field_index ( expr. hir_id , index) ;
1503
+ self . complain_about_invalid_type_params ( invalid_args) ;
1489
1504
return field_ty. expect_ty ( ) ;
1490
1505
}
1491
1506
}
@@ -1501,8 +1516,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1501
1516
return field_ty;
1502
1517
}
1503
1518
1519
+ let method_exists = self . method_exists ( field, expr_t, expr. hir_id , true ) ;
1520
+ if let ( false , ExprKind :: Field ( _, _, Some ( _) ) ) = ( method_exists, & expr. kind ) {
1521
+ // Only complain about incorrect field expressions with type parameters like
1522
+ // `foo.bar::<baz>` when `bar` isn't a valid method.
1523
+ self . complain_about_invalid_type_params ( invalid_args) ;
1524
+ }
1504
1525
if field. name == kw:: Invalid {
1505
- } else if self . method_exists ( field , expr_t , expr . hir_id , true ) {
1526
+ } else if method_exists {
1506
1527
self . ban_take_value_of_method ( expr, expr_t, field) ;
1507
1528
} else if !expr_t. is_primitive_ty ( ) {
1508
1529
self . ban_nonexisting_field ( field, base, expr, expr_t) ;
0 commit comments