Skip to content

Commit 028fd12

Browse files
committed
Migrate 'lossy ptr2int cast' diagnostic
1 parent e7f9f48 commit 028fd12

File tree

3 files changed

+76
-42
lines changed

3 files changed

+76
-42
lines changed

compiler/rustc_hir_typeck/messages.ftl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ hir_typeck_lang_start_incorrect_param = parameter {$param_num} of the `start` la
6363
hir_typeck_lang_start_incorrect_ret_ty = the return type of the `start` lang item is incorrect
6464
.suggestion = change the type from `{$found_ty}` to `{$expected_ty}`
6565
66+
hir_typeck_lossy_provenance_ptr2int =
67+
under strict provenance it is considered bad style to cast pointer `{$expr_ty}` to integer `{$cast_ty}`
68+
.suggestion = use `.addr()` to obtain the address of a pointer
69+
.help = if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
70+
6671
hir_typeck_method_call_on_unknown_raw_pointee =
6772
cannot call a method on a raw pointer with an unknown pointee type
6873

compiler/rustc_hir_typeck/src/cast.rs

Lines changed: 26 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
3131
use super::FnCtxt;
3232

33+
use crate::errors;
3334
use crate::type_error_struct;
3435
use hir::ExprKind;
3536
use rustc_errors::{
@@ -1007,50 +1008,34 @@ impl<'a, 'tcx> CastCheck<'tcx> {
10071008
}
10081009

10091010
fn lossy_provenance_ptr2int_lint(&self, fcx: &FnCtxt<'a, 'tcx>, t_c: ty::cast::IntTy) {
1010-
fcx.tcx.struct_span_lint_hir(
1011+
let expr_prec = self.expr.precedence().order();
1012+
let needs_parens = expr_prec < rustc_ast::util::parser::PREC_POSTFIX;
1013+
1014+
let needs_cast = !matches!(t_c, ty::cast::IntTy::U(ty::UintTy::Usize));
1015+
let cast_span = self.expr_span.shrink_to_hi().to(self.cast_span);
1016+
let cast_ty = self.cast_ty;
1017+
let expr_span = self.expr_span.shrink_to_lo();
1018+
let sugg = match (needs_parens, needs_cast) {
1019+
(true, true) => errors::LossyProvenancePtr2IntSuggestion::NeedsParensCast {
1020+
expr_span,
1021+
cast_span,
1022+
cast_ty,
1023+
},
1024+
(true, false) => {
1025+
errors::LossyProvenancePtr2IntSuggestion::NeedsParens { expr_span, cast_span }
1026+
}
1027+
(false, true) => {
1028+
errors::LossyProvenancePtr2IntSuggestion::NeedsCast { cast_span, cast_ty }
1029+
}
1030+
(false, false) => errors::LossyProvenancePtr2IntSuggestion::Other { cast_span },
1031+
};
1032+
1033+
let lint = errors::LossyProvenancePtr2Int { expr_ty: self.expr_ty, cast_ty, sugg };
1034+
fcx.tcx.emit_spanned_lint(
10111035
lint::builtin::LOSSY_PROVENANCE_CASTS,
10121036
self.expr.hir_id,
10131037
self.span,
1014-
DelayDm(|| format!(
1015-
"under strict provenance it is considered bad style to cast pointer `{}` to integer `{}`",
1016-
self.expr_ty, self.cast_ty
1017-
)),
1018-
|lint| {
1019-
let msg = "use `.addr()` to obtain the address of a pointer";
1020-
1021-
let expr_prec = self.expr.precedence().order();
1022-
let needs_parens = expr_prec < rustc_ast::util::parser::PREC_POSTFIX;
1023-
1024-
let scalar_cast = match t_c {
1025-
ty::cast::IntTy::U(ty::UintTy::Usize) => String::new(),
1026-
_ => format!(" as {}", self.cast_ty),
1027-
};
1028-
1029-
let cast_span = self.expr_span.shrink_to_hi().to(self.cast_span);
1030-
1031-
if needs_parens {
1032-
let suggestions = vec![
1033-
(self.expr_span.shrink_to_lo(), String::from("(")),
1034-
(cast_span, format!(").addr(){scalar_cast}")),
1035-
];
1036-
1037-
lint.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
1038-
} else {
1039-
lint.span_suggestion(
1040-
cast_span,
1041-
msg,
1042-
format!(".addr(){scalar_cast}"),
1043-
Applicability::MaybeIncorrect,
1044-
);
1045-
}
1046-
1047-
lint.help(
1048-
"if you can't comply with strict provenance and need to expose the pointer \
1049-
provenance you can use `.expose_addr()` instead"
1050-
);
1051-
1052-
lint
1053-
},
1038+
lint,
10541039
);
10551040
}
10561041

compiler/rustc_hir_typeck/src/errors.rs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_errors::{
66
AddToDiagnostic, Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnosticArg, MultiSpan,
77
SubdiagnosticMessage,
88
};
9-
use rustc_macros::{Diagnostic, Subdiagnostic};
9+
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
1010
use rustc_middle::ty::Ty;
1111
use rustc_span::{
1212
edition::{Edition, LATEST_STABLE_EDITION},
@@ -231,6 +231,50 @@ pub struct LangStartIncorrectRetTy<'tcx> {
231231
pub found_ty: Ty<'tcx>,
232232
}
233233

234+
#[derive(LintDiagnostic)]
235+
#[diag(hir_typeck_lossy_provenance_ptr2int)]
236+
#[help]
237+
pub struct LossyProvenancePtr2Int<'tcx> {
238+
pub expr_ty: Ty<'tcx>,
239+
pub cast_ty: Ty<'tcx>,
240+
#[subdiagnostic]
241+
pub sugg: LossyProvenancePtr2IntSuggestion<'tcx>,
242+
}
243+
244+
#[derive(Subdiagnostic)]
245+
pub enum LossyProvenancePtr2IntSuggestion<'tcx> {
246+
#[multipart_suggestion(hir_typeck_suggestion, applicability = "maybe-incorrect")]
247+
NeedsParensCast {
248+
#[suggestion_part(code = "(")]
249+
expr_span: Span,
250+
#[suggestion_part(code = ").addr() as {cast_ty}")]
251+
cast_span: Span,
252+
cast_ty: Ty<'tcx>,
253+
},
254+
#[multipart_suggestion(hir_typeck_suggestion, applicability = "maybe-incorrect")]
255+
NeedsParens {
256+
#[suggestion_part(code = "(")]
257+
expr_span: Span,
258+
#[suggestion_part(code = ").addr()")]
259+
cast_span: Span,
260+
},
261+
#[suggestion(
262+
hir_typeck_suggestion,
263+
code = ".addr() as {cast_ty}",
264+
applicability = "maybe-incorrect"
265+
)]
266+
NeedsCast {
267+
#[primary_span]
268+
cast_span: Span,
269+
cast_ty: Ty<'tcx>,
270+
},
271+
#[suggestion(hir_typeck_suggestion, code = ".addr()", applicability = "maybe-incorrect")]
272+
Other {
273+
#[primary_span]
274+
cast_span: Span,
275+
},
276+
}
277+
234278
#[derive(Subdiagnostic)]
235279
pub enum HelpUseLatestEdition {
236280
#[help(hir_typeck_help_set_edition_cargo)]

0 commit comments

Comments
 (0)