@@ -2,6 +2,7 @@ use clippy_config::Conf;
22use clippy_utils:: diagnostics:: span_lint_and_then;
33use clippy_utils:: is_from_proc_macro;
44use clippy_utils:: msrvs:: { self , Msrv } ;
5+ use clippy_utils:: source:: SpanRangeExt ;
56use hir:: def_id:: DefId ;
67use rustc_errors:: Applicability ;
78use rustc_hir as hir;
@@ -103,7 +104,7 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants {
103104
104105 fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx rustc_hir:: Expr < ' tcx > ) {
105106 // `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
107108 && let QPath :: Resolved ( None , path) = qpath
108109 && let Some ( def_id) = path. res . opt_def_id ( )
109110 && is_numeric_const ( cx, def_id)
@@ -113,8 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants {
113114 && !is_numeric_const_path_canonical ( path, [ * mod_name, * name] )
114115 {
115116 (
116- expr. span ,
117- format ! ( "{mod_name}::{name}" ) ,
117+ vec ! [ ( expr. span, format!( "{mod_name}::{name}" ) ) ] ,
118118 "usage of a legacy numeric constant" ,
119119 )
120120 // `<integer>::xxx_value` check
@@ -124,13 +124,24 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants {
124124 && let Some ( def_id) = cx. qpath_res ( qpath, func. hir_id ) . opt_def_id ( )
125125 && is_integer_method ( cx, def_id)
126126 {
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" )
134145 } else {
135146 return ;
136147 } ;
@@ -139,9 +150,8 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants {
139150 && self . msrv . meets ( cx, msrvs:: NUMERIC_ASSOCIATED_CONSTANTS )
140151 && !is_from_proc_macro ( cx, expr)
141152 {
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 (
145155 "use the associated constant instead" ,
146156 sugg,
147157 Applicability :: MaybeIncorrect ,
0 commit comments