11use hir:: { db:: AstDatabase , HirDisplay , Type } ;
2- use ide_db:: { famous_defs:: FamousDefs , source_change:: SourceChange } ;
2+ use ide_db:: {
3+ base_db:: { FileRange , SourceDatabase } ,
4+ famous_defs:: FamousDefs ,
5+ source_change:: SourceChange ,
6+ } ;
37use syntax:: {
4- ast:: { BlockExpr , ExprStmt } ,
8+ algo:: find_node_at_range,
9+ ast:: { self , BlockExpr , ExprStmt } ,
510 AstNode ,
611} ;
712use text_edit:: TextEdit ;
@@ -13,14 +18,26 @@ use crate::{fix, Assist, Diagnostic, DiagnosticsContext};
1318// This diagnostic is triggered when the type of an expression does not match
1419// the expected type.
1520pub ( crate ) fn type_mismatch ( ctx : & DiagnosticsContext < ' _ > , d : & hir:: TypeMismatch ) -> Diagnostic {
21+ let FileRange { file_id, range } =
22+ ctx. sema . diagnostics_display_range ( d. expr . clone ( ) . map ( |it| it. into ( ) ) ) ;
23+
24+ let source_file = ctx. sema . db . parse ( file_id) ;
25+ let block = find_node_at_range :: < ast:: BlockExpr > ( & source_file. syntax_node ( ) , range)
26+ . filter ( |it| it. syntax ( ) . text_range ( ) == range) ;
27+ let display_range = block
28+ . and_then ( |it| it. stmt_list ( ) )
29+ . and_then ( |it| it. r_curly_token ( ) )
30+ . map ( |it| it. text_range ( ) )
31+ . unwrap_or ( range) ;
32+
1633 let mut diag = Diagnostic :: new (
1734 "type-mismatch" ,
1835 format ! (
1936 "expected {}, found {}" ,
2037 d. expected. display( ctx. sema. db) ,
2138 d. actual. display( ctx. sema. db)
2239 ) ,
23- ctx . sema . diagnostics_display_range ( d . expr . clone ( ) . map ( |it| it . into ( ) ) ) . range ,
40+ display_range ,
2441 )
2542 . with_fixes ( fixes ( ctx, d) ) ;
2643 if diag. fixes . is_none ( ) {
@@ -545,4 +562,18 @@ fn test() -> String {
545562 "# ,
546563 ) ;
547564 }
565+
566+ #[ test]
567+ fn type_mismatch_on_block ( ) {
568+ check_diagnostics (
569+ r#"
570+ fn f() -> i32 {
571+ let x = 1;
572+ let y = 2;
573+ let _ = x + y;
574+ }
575+ //^ error: expected i32, found ()
576+ "# ,
577+ ) ;
578+ }
548579}
0 commit comments