@@ -2,6 +2,7 @@ use clippy_config::Conf;
2
2
use clippy_utils:: diagnostics:: span_lint_and_then;
3
3
use clippy_utils:: is_from_proc_macro;
4
4
use clippy_utils:: msrvs:: { self , Msrv } ;
5
+ use clippy_utils:: source:: SpanRangeExt ;
5
6
use hir:: def_id:: DefId ;
6
7
use rustc_errors:: Applicability ;
7
8
use rustc_hir as hir;
@@ -103,7 +104,7 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants {
103
104
104
105
fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx rustc_hir:: Expr < ' tcx > ) {
105
106
// `std::<integer>::<CONST>` check
106
- let ( span , sugg, msg) = if let ExprKind :: Path ( qpath) = & expr. kind
107
+ let ( sugg, msg) = if let ExprKind :: Path ( qpath) = & expr. kind
107
108
&& let QPath :: Resolved ( None , path) = qpath
108
109
&& let Some ( def_id) = path. res . opt_def_id ( )
109
110
&& is_numeric_const ( cx, def_id)
@@ -113,8 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants {
113
114
&& !is_numeric_const_path_canonical ( path, [ * mod_name, * name] )
114
115
{
115
116
(
116
- expr. span ,
117
- format ! ( "{mod_name}::{name}" ) ,
117
+ vec ! [ ( expr. span, format!( "{mod_name}::{name}" ) ) ] ,
118
118
"usage of a legacy numeric constant" ,
119
119
)
120
120
// `<integer>::xxx_value` check
@@ -124,13 +124,24 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants {
124
124
&& let Some ( def_id) = cx. qpath_res ( qpath, func. hir_id ) . opt_def_id ( )
125
125
&& is_integer_method ( cx, def_id)
126
126
{
127
- let name = last_segment. ident . name . as_str ( ) ;
128
- let mod_name = clippy_utils:: source:: snippet ( cx, ty. span , "_" ) ;
129
- (
130
- expr. span ,
131
- format ! ( "{}::{}" , mod_name, name[ ..=2 ] . to_ascii_uppercase( ) ) ,
132
- "usage of a legacy numeric method" ,
133
- )
127
+ let mut sugg = vec ! [
128
+ // Replace the function name up to the end by the constant name
129
+ (
130
+ last_segment. ident. span. to( expr. span. shrink_to_hi( ) ) ,
131
+ last_segment. ident. name. as_str( ) [ ..=2 ] . to_ascii_uppercase( ) ,
132
+ ) ,
133
+ ] ;
134
+ let before_span = expr. span . shrink_to_lo ( ) . until ( ty. span ) ;
135
+ if !before_span. is_empty ( ) {
136
+ // Remove everything before the type name
137
+ sugg. push ( ( before_span, String :: new ( ) ) ) ;
138
+ }
139
+ // Use `::` between the type name and the constant
140
+ let between_span = ty. span . shrink_to_hi ( ) . until ( last_segment. ident . span ) ;
141
+ if !between_span. check_source_text ( cx, |s| s == "::" ) {
142
+ sugg. push ( ( between_span, String :: from ( "::" ) ) ) ;
143
+ }
144
+ ( sugg, "usage of a legacy numeric method" )
134
145
} else {
135
146
return ;
136
147
} ;
@@ -139,9 +150,8 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants {
139
150
&& self . msrv . meets ( cx, msrvs:: NUMERIC_ASSOCIATED_CONSTANTS )
140
151
&& !is_from_proc_macro ( cx, expr)
141
152
{
142
- span_lint_and_then ( cx, LEGACY_NUMERIC_CONSTANTS , span, msg, |diag| {
143
- diag. span_suggestion_verbose (
144
- span,
153
+ span_lint_and_then ( cx, LEGACY_NUMERIC_CONSTANTS , expr. span , msg, |diag| {
154
+ diag. multipart_suggestion_verbose (
145
155
"use the associated constant instead" ,
146
156
sugg,
147
157
Applicability :: MaybeIncorrect ,
0 commit comments