@@ -5,6 +5,7 @@ use crate::errors;
5
5
use crate :: FnCtxt ;
6
6
use rustc_ast:: ast:: Mutability ;
7
7
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
8
+ use rustc_errors:: StashKey ;
8
9
use rustc_errors:: {
9
10
pluralize, struct_span_err, Applicability , Diagnostic , DiagnosticBuilder , ErrorGuaranteed ,
10
11
MultiSpan ,
@@ -13,6 +14,7 @@ use rustc_hir as hir;
13
14
use rustc_hir:: def:: DefKind ;
14
15
use rustc_hir:: def_id:: DefId ;
15
16
use rustc_hir:: lang_items:: LangItem ;
17
+ use rustc_hir:: PatKind :: Binding ;
16
18
use rustc_hir:: { ExprKind , Node , QPath } ;
17
19
use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
18
20
use rustc_middle:: traits:: util:: supertraits;
@@ -1407,48 +1409,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1407
1409
false
1408
1410
}
1409
1411
1410
- pub ( crate ) fn suggest_instance_call (
1411
- & self ,
1412
- seg1 : & hir:: PathSegment < ' _ > ,
1413
- seg2 : & hir:: PathSegment < ' _ > ,
1414
- local_span : Span ,
1415
- ) -> bool {
1412
+ /// For code `rect::area(...)`, we try to suggest `rect.area()`
1413
+ /// If `rect` is a local variable and `area` is a valid assoc method for it.
1414
+ pub ( crate ) fn suggest_instance_call ( & self , path : & hir:: Path < ' _ > ) {
1415
+ if path. segments . len ( ) != 2 {
1416
+ return ;
1417
+ }
1418
+ let seg1 = & path. segments [ 0 ] ;
1419
+ let seg2 = & path. segments [ 1 ] ;
1420
+ let Some ( mut diag) =
1421
+ self . tcx . sess . diagnostic ( ) . steal_diagnostic ( seg1. ident . span , StashKey :: CallInstanceMethod ) else { return } ;
1422
+
1416
1423
let map = self . infcx . tcx . hir ( ) ;
1417
1424
let body_id = map. body_owned_by ( seg1. hir_id . owner . def_id ) ;
1418
1425
let body = map. body ( body_id) ;
1419
-
1420
1426
struct LetVisitor < ' a > {
1421
- local_span : Span ,
1422
- result : Option < & ' a Ty < ' a > > ,
1427
+ result : Option < & ' a hir :: Expr < ' a > > ,
1428
+ ident_name : Symbol ,
1423
1429
}
1424
1430
1425
- impl < ' v > Visitor < ' v > for LetVisitor < ' _ > {
1431
+ impl < ' v > Visitor < ' v > for LetVisitor < ' v > {
1426
1432
fn visit_stmt ( & mut self , ex : & ' v hir:: Stmt < ' v > ) {
1427
- if self . result . is_some ( ) {
1428
- return ;
1429
- }
1430
- if let hir:: StmtKind :: Local ( hir:: Local {
1431
- span, ty, init : None , ..
1432
- } ) = & ex. kind && span. contains ( self . local_span ) {
1433
- self . result = ty;
1433
+ if let hir:: StmtKind :: Local ( hir:: Local { pat, init, .. } ) = & ex. kind {
1434
+ if let Binding ( _, _, ident, ..) = pat. kind &&
1435
+ ident. name == self . ident_name {
1436
+ self . result = * init;
1437
+ }
1434
1438
}
1435
1439
hir:: intravisit:: walk_stmt ( self , ex) ;
1436
1440
}
1437
1441
}
1438
1442
1439
- let mut visitor = LetVisitor { local_span , result : None } ;
1443
+ let mut visitor = LetVisitor { result : None , ident_name : seg1 . ident . name } ;
1440
1444
visitor. visit_body ( & body) ;
1441
1445
1442
1446
let parent = self . tcx . hir ( ) . get_parent_node ( seg1. hir_id ) ;
1443
- let parent_expr = self . tcx . hir ( ) . find ( parent) ;
1444
- debug ! ( "yukang parent_expr: {:?}" , parent_expr) ;
1445
- let node = self . tcx . hir ( ) . get_parent_node ( seg1. hir_id ) ;
1446
- let ty = self . typeck_results . borrow ( ) . node_type_opt ( node) ;
1447
-
1448
- debug ! ( "yukang suggest_instance_call ty: {:?}" , ty) ;
1449
1447
if let Some ( Node :: Expr ( call_expr) ) = self . tcx . hir ( ) . find ( parent) &&
1450
- let Some ( self_ty ) = ty {
1451
- debug ! ( "yukang trying to prob method" ) ;
1448
+ let Some ( expr ) = visitor . result {
1449
+ let self_ty = self . check_expr ( expr ) ;
1452
1450
let probe = self . lookup_probe (
1453
1451
seg1. ident . span ,
1454
1452
seg2. ident ,
@@ -1457,11 +1455,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1457
1455
ProbeScope :: TraitsInScope ,
1458
1456
) ;
1459
1457
1460
- if let Ok ( _pick) = probe {
1461
- return true ;
1458
+ if probe. is_ok ( ) {
1459
+ diag. set_primary_message ( format ! (
1460
+ "need to fix call instance method: {:?}" ,
1461
+ seg2. ident
1462
+ ) ) ;
1463
+ diag. emit ( ) ;
1464
+ } else {
1465
+ diag. cancel ( ) ;
1462
1466
}
1463
1467
}
1464
- return false ;
1465
1468
}
1466
1469
1467
1470
fn check_for_field_method (
0 commit comments