@@ -16,7 +16,7 @@ use rustc_ast::ptr::P;
16
16
use rustc_ast:: visit:: { self , AssocCtxt , BoundKind , FnCtxt , FnKind , Visitor } ;
17
17
use rustc_ast:: * ;
18
18
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet , FxIndexMap } ;
19
- use rustc_errors:: { DiagnosticArgValue , DiagnosticId , IntoDiagnosticArg } ;
19
+ use rustc_errors:: { Applicability , DiagnosticArgValue , DiagnosticId , IntoDiagnosticArg } ;
20
20
use rustc_hir:: def:: Namespace :: { self , * } ;
21
21
use rustc_hir:: def:: { self , CtorKind , DefKind , LifetimeRes , PartialRes , PerNS } ;
22
22
use rustc_hir:: def_id:: { DefId , LocalDefId , CRATE_DEF_ID , LOCAL_CRATE } ;
@@ -536,6 +536,9 @@ struct DiagnosticMetadata<'ast> {
536
536
in_assignment : Option < & ' ast Expr > ,
537
537
is_assign_rhs : bool ,
538
538
539
+ /// Used to detect possible `.` -> `..` typo when calling methods.
540
+ in_range : Option < ( & ' ast Expr , & ' ast Expr ) > ,
541
+
539
542
/// If we are currently in a trait object definition. Used to point at the bounds when
540
543
/// encountering a struct or enum.
541
544
current_trait_object : Option < & ' ast [ ast:: GenericBound ] > ,
@@ -3320,17 +3323,14 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
3320
3323
) ;
3321
3324
}
3322
3325
3326
+ #[ instrument( level = "debug" , skip( self ) ) ]
3323
3327
fn smart_resolve_path_fragment (
3324
3328
& mut self ,
3325
3329
qself : & Option < P < QSelf > > ,
3326
3330
path : & [ Segment ] ,
3327
3331
source : PathSource < ' ast > ,
3328
3332
finalize : Finalize ,
3329
3333
) -> PartialRes {
3330
- debug ! (
3331
- "smart_resolve_path_fragment(qself={:?}, path={:?}, finalize={:?})" ,
3332
- qself, path, finalize,
3333
- ) ;
3334
3334
let ns = source. namespace ( ) ;
3335
3335
3336
3336
let Finalize { node_id, path_span, .. } = finalize;
@@ -3341,8 +3341,20 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
3341
3341
3342
3342
let def_id = this. parent_scope . module . nearest_parent_mod ( ) ;
3343
3343
let instead = res. is_some ( ) ;
3344
- let suggestion =
3345
- if res. is_none ( ) { this. report_missing_type_error ( path) } else { None } ;
3344
+ let suggestion = if let Some ( ( start, end) ) = this. diagnostic_metadata . in_range
3345
+ && path[ 0 ] . ident . span . lo ( ) == end. span . lo ( )
3346
+ {
3347
+ Some ( (
3348
+ start. span . between ( end. span ) ,
3349
+ "you might have meant to write a method call instead of a range" ,
3350
+ "." . to_string ( ) ,
3351
+ Applicability :: MaybeIncorrect ,
3352
+ ) )
3353
+ } else if res. is_none ( ) {
3354
+ this. report_missing_type_error ( path)
3355
+ } else {
3356
+ None
3357
+ } ;
3346
3358
3347
3359
this. r . use_injections . push ( UseError {
3348
3360
err,
@@ -4005,6 +4017,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
4005
4017
self . visit_expr ( rhs) ;
4006
4018
self . diagnostic_metadata . is_assign_rhs = false ;
4007
4019
}
4020
+ ExprKind :: Range ( Some ( ref start) , Some ( ref end) , RangeLimits :: HalfOpen ) => {
4021
+ self . diagnostic_metadata . in_range = Some ( ( start, end) ) ;
4022
+ self . resolve_expr ( start, Some ( expr) ) ;
4023
+ self . resolve_expr ( end, Some ( expr) ) ;
4024
+ self . diagnostic_metadata . in_range = None ;
4025
+ }
4008
4026
_ => {
4009
4027
visit:: walk_expr ( self , expr) ;
4010
4028
}
0 commit comments