Skip to content

Commit 5043948

Browse files
committed
Auto merge of #156916 - JonathanBrouwer:rollup-CbeVZH2, r=JonathanBrouwer
Rollup of 3 pull requests Successful merges: - #156862 (Convert strict_provenance_lints to late lint passes) - #156879 (Replace rustfmt code of conduct with link) - #156901 (compiletest: Simplify `//@ needs-asm-mnemonic: ret` to just `//@ needs-asm-ret`)
2 parents 6083f78 + 9545845 commit 5043948

19 files changed

Lines changed: 296 additions & 468 deletions

File tree

compiler/rustc_hir_typeck/src/cast.rs

Lines changed: 3 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
//! expression, `e as U2` is not necessarily so (in fact it will only be valid if
2929
//! `U1` coerces to `U2`).
3030
31-
use rustc_ast::util::parser::ExprPrecedence;
3231
use rustc_data_structures::fx::FxHashSet;
3332
use rustc_errors::codes::*;
3433
use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
@@ -860,19 +859,14 @@ impl<'a, 'tcx> CastCheck<'tcx> {
860859
(Ptr(m_e), Ptr(m_c)) => self.check_ptr_ptr_cast(fcx, m_e, m_c), // ptr-ptr-cast
861860

862861
// ptr-addr-cast
863-
(Ptr(m_expr), Int(t_c)) => {
864-
self.lossy_provenance_ptr2int_lint(fcx, t_c);
865-
self.check_ptr_addr_cast(fcx, m_expr)
866-
}
862+
(Ptr(m_expr), Int(_)) => self.check_ptr_addr_cast(fcx, m_expr),
863+
867864
(FnPtr, Int(_)) => {
868865
// FIXME(#95489): there should eventually be a lint for these casts
869866
Ok(CastKind::FnPtrAddrCast)
870867
}
871868
// addr-ptr-cast
872-
(Int(_), Ptr(mt)) => {
873-
self.fuzzy_provenance_int2ptr_lint(fcx);
874-
self.check_addr_ptr_cast(fcx, mt)
875-
}
869+
(Int(_), Ptr(mt)) => self.check_addr_ptr_cast(fcx, mt),
876870
// fn-ptr-cast
877871
(FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt),
878872

@@ -1133,59 +1127,6 @@ impl<'a, 'tcx> CastCheck<'tcx> {
11331127
}
11341128
}
11351129

1136-
fn lossy_provenance_ptr2int_lint(&self, fcx: &FnCtxt<'a, 'tcx>, t_c: ty::cast::IntTy) {
1137-
let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
1138-
let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty);
1139-
1140-
let sugg = self.span.can_be_used_for_suggestions().then(|| {
1141-
let expr_prec = fcx.precedence(self.expr);
1142-
let needs_parens = expr_prec < ExprPrecedence::Unambiguous;
1143-
let needs_cast = !matches!(t_c, ty::cast::IntTy::U(ty::UintTy::Usize));
1144-
let cast_span = self.expr_span.shrink_to_hi().to(self.cast_span);
1145-
let expr_span = self.expr_span.shrink_to_lo();
1146-
match (needs_parens, needs_cast) {
1147-
(true, true) => errors::LossyProvenancePtr2IntSuggestion::NeedsParensCast {
1148-
expr_span,
1149-
cast_span,
1150-
cast_ty,
1151-
},
1152-
(true, false) => {
1153-
errors::LossyProvenancePtr2IntSuggestion::NeedsParens { expr_span, cast_span }
1154-
}
1155-
(false, true) => {
1156-
errors::LossyProvenancePtr2IntSuggestion::NeedsCast { cast_span, cast_ty }
1157-
}
1158-
(false, false) => errors::LossyProvenancePtr2IntSuggestion::Other { cast_span },
1159-
}
1160-
});
1161-
1162-
let lint = errors::LossyProvenancePtr2Int { expr_ty, cast_ty, sugg };
1163-
fcx.tcx.emit_node_span_lint(
1164-
lint::builtin::LOSSY_PROVENANCE_CASTS,
1165-
self.expr.hir_id,
1166-
self.span,
1167-
lint,
1168-
);
1169-
}
1170-
1171-
fn fuzzy_provenance_int2ptr_lint(&self, fcx: &FnCtxt<'a, 'tcx>) {
1172-
let sugg = self.span.can_be_used_for_suggestions().then(|| {
1173-
errors::LossyProvenanceInt2PtrSuggestion {
1174-
lo: self.expr_span.shrink_to_lo(),
1175-
hi: self.expr_span.shrink_to_hi().to(self.cast_span),
1176-
}
1177-
});
1178-
let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
1179-
let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty);
1180-
let lint = errors::LossyProvenanceInt2Ptr { expr_ty, cast_ty, sugg };
1181-
fcx.tcx.emit_node_span_lint(
1182-
lint::builtin::FUZZY_PROVENANCE_CASTS,
1183-
self.expr.hir_id,
1184-
self.span,
1185-
lint,
1186-
);
1187-
}
1188-
11891130
/// Attempt to suggest using `.is_empty` when trying to cast from a
11901131
/// collection type to a boolean.
11911132
fn try_suggest_collection_to_bool(&self, fcx: &FnCtxt<'a, 'tcx>, err: &mut Diag<'_>) {

compiler/rustc_hir_typeck/src/errors.rs

Lines changed: 0 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -377,18 +377,6 @@ impl Subdiagnostic for TypeMismatchFruTypo {
377377
}
378378
}
379379

380-
#[derive(Diagnostic)]
381-
#[diag("strict provenance disallows casting integer `{$expr_ty}` to pointer `{$cast_ty}`")]
382-
#[help(
383-
"if you can't comply with strict provenance and don't have a pointer with the correct provenance you can use `std::ptr::with_exposed_provenance()` instead"
384-
)]
385-
pub(crate) struct LossyProvenanceInt2Ptr<'tcx> {
386-
pub expr_ty: Ty<'tcx>,
387-
pub cast_ty: Ty<'tcx>,
388-
#[subdiagnostic]
389-
pub sugg: Option<LossyProvenanceInt2PtrSuggestion>,
390-
}
391-
392380
#[derive(Diagnostic)]
393381
#[diag("cannot add {$traits_len ->
394382
[1] auto trait {$traits}
@@ -404,76 +392,6 @@ pub(crate) struct PtrCastAddAutoToObject {
404392
pub traits: DiagSymbolList<String>,
405393
}
406394

407-
#[derive(Subdiagnostic)]
408-
#[multipart_suggestion(
409-
"use `.with_addr()` to adjust a valid pointer in the same allocation, to this address",
410-
applicability = "has-placeholders"
411-
)]
412-
pub(crate) struct LossyProvenanceInt2PtrSuggestion {
413-
#[suggestion_part(code = "(...).with_addr(")]
414-
pub lo: Span,
415-
#[suggestion_part(code = ")")]
416-
pub hi: Span,
417-
}
418-
419-
#[derive(Diagnostic)]
420-
#[diag(
421-
"under strict provenance it is considered bad style to cast pointer `{$expr_ty}` to integer `{$cast_ty}`"
422-
)]
423-
#[help(
424-
"if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_provenance()` instead"
425-
)]
426-
pub(crate) struct LossyProvenancePtr2Int<'tcx> {
427-
pub expr_ty: Ty<'tcx>,
428-
pub cast_ty: Ty<'tcx>,
429-
#[subdiagnostic]
430-
pub sugg: Option<LossyProvenancePtr2IntSuggestion<'tcx>>,
431-
}
432-
433-
#[derive(Subdiagnostic)]
434-
pub(crate) enum LossyProvenancePtr2IntSuggestion<'tcx> {
435-
#[multipart_suggestion(
436-
"use `.addr()` to obtain the address of a pointer",
437-
applicability = "maybe-incorrect"
438-
)]
439-
NeedsParensCast {
440-
#[suggestion_part(code = "(")]
441-
expr_span: Span,
442-
#[suggestion_part(code = ").addr() as {cast_ty}")]
443-
cast_span: Span,
444-
cast_ty: Ty<'tcx>,
445-
},
446-
#[multipart_suggestion(
447-
"use `.addr()` to obtain the address of a pointer",
448-
applicability = "maybe-incorrect"
449-
)]
450-
NeedsParens {
451-
#[suggestion_part(code = "(")]
452-
expr_span: Span,
453-
#[suggestion_part(code = ").addr()")]
454-
cast_span: Span,
455-
},
456-
#[suggestion(
457-
"use `.addr()` to obtain the address of a pointer",
458-
code = ".addr() as {cast_ty}",
459-
applicability = "maybe-incorrect"
460-
)]
461-
NeedsCast {
462-
#[primary_span]
463-
cast_span: Span,
464-
cast_ty: Ty<'tcx>,
465-
},
466-
#[suggestion(
467-
"use `.addr()` to obtain the address of a pointer",
468-
code = ".addr()",
469-
applicability = "maybe-incorrect"
470-
)]
471-
Other {
472-
#[primary_span]
473-
cast_span: Span,
474-
},
475-
}
476-
477395
#[derive(Subdiagnostic)]
478396
pub(crate) enum HelpUseLatestEdition {
479397
#[help("set `edition = \"{$edition}\"` in `Cargo.toml`")]
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
use rustc_hir as hir;
2+
use rustc_session::{declare_lint, declare_lint_pass};
3+
4+
use crate::lints::{LossyProvenanceInt2Ptr, LossyProvenanceInt2PtrSuggestion};
5+
use crate::{LateContext, LateLintPass};
6+
7+
declare_lint! {
8+
/// The `fuzzy_provenance_casts` lint detects an `as` cast between an integer
9+
/// and a pointer.
10+
///
11+
/// ### Example
12+
///
13+
/// ```rust
14+
/// #![feature(strict_provenance_lints)]
15+
/// #![warn(fuzzy_provenance_casts)]
16+
///
17+
/// fn main() {
18+
/// let _dangling = 16_usize as *const u8;
19+
/// }
20+
/// ```
21+
///
22+
/// {{produces}}
23+
///
24+
/// ### Explanation
25+
///
26+
/// This lint is part of the strict provenance effort, see [issue #95228].
27+
/// Casting an integer to a pointer is considered bad style, as a pointer
28+
/// contains, besides the *address* also a *provenance*, indicating what
29+
/// memory the pointer is allowed to read/write. Casting an integer, which
30+
/// doesn't have provenance, to a pointer requires the compiler to assign
31+
/// (guess) provenance. The compiler assigns "all exposed valid" (see the
32+
/// docs of [`ptr::with_exposed_provenance`] for more information about this
33+
/// "exposing"). This penalizes the optimiser and is not well suited for
34+
/// dynamic analysis/dynamic program verification (e.g. Miri or CHERI
35+
/// platforms).
36+
///
37+
/// It is much better to use [`ptr::with_addr`] instead to specify the
38+
/// provenance you want. If using this function is not possible because the
39+
/// code relies on exposed provenance then there is as an escape hatch
40+
/// [`ptr::with_exposed_provenance`].
41+
///
42+
/// [issue #95228]: https://github.com/rust-lang/rust/issues/95228
43+
/// [`ptr::with_addr`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.with_addr
44+
/// [`ptr::with_exposed_provenance`]: https://doc.rust-lang.org/core/ptr/fn.with_exposed_provenance.html
45+
pub FUZZY_PROVENANCE_CASTS,
46+
Allow,
47+
"a fuzzy integer to pointer cast is used",
48+
@feature_gate = strict_provenance_lints;
49+
}
50+
51+
declare_lint_pass!(
52+
/// Lint for `as` casts between an integer and a pointer.
53+
FuzzyProvenanceCasts => [FUZZY_PROVENANCE_CASTS]
54+
);
55+
56+
impl<'tcx> LateLintPass<'tcx> for FuzzyProvenanceCasts {
57+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
58+
let hir::ExprKind::Cast(cast_from_expr, cast_to_hir) = expr.kind else { return };
59+
60+
let typeck_results = cx.typeck_results();
61+
// Only lint casts from integer to pointer
62+
let cast_from_ty = typeck_results.expr_ty(cast_from_expr);
63+
if !cast_from_ty.is_integral() {
64+
return;
65+
}
66+
let cast_to_ty = typeck_results.expr_ty(expr);
67+
if !cast_to_ty.is_raw_ptr() {
68+
return;
69+
}
70+
71+
let sugg =
72+
expr.span.can_be_used_for_suggestions().then(|| LossyProvenanceInt2PtrSuggestion {
73+
lo: cast_from_expr.span.shrink_to_lo(),
74+
hi: cast_from_expr.span.shrink_to_hi().to(cast_to_hir.span),
75+
});
76+
let lint = LossyProvenanceInt2Ptr { expr_ty: cast_from_ty, cast_ty: cast_to_ty, sugg };
77+
cx.tcx.emit_node_span_lint(FUZZY_PROVENANCE_CASTS, expr.hir_id, expr.span, lint)
78+
}
79+
}

compiler/rustc_lint/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ mod expect;
4545
mod for_loops_over_fallibles;
4646
mod foreign_modules;
4747
mod function_cast_as_integer;
48+
mod fuzzy_provenance_casts;
4849
mod gpukernel_abi;
4950
mod if_let_rescope;
5051
mod impl_trait_overcaptures;
@@ -56,6 +57,7 @@ mod let_underscore;
5657
mod levels;
5758
pub mod lifetime_syntax;
5859
mod lints;
60+
mod lossy_provenance_casts;
5961
mod macro_expr_fragment_specifier_2024_migration;
6062
mod map_unit_fn;
6163
mod multiple_supertrait_upcastable;
@@ -92,6 +94,7 @@ use drop_forget_useless::*;
9294
use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
9395
use for_loops_over_fallibles::*;
9496
use function_cast_as_integer::*;
97+
use fuzzy_provenance_casts::FuzzyProvenanceCasts;
9598
use gpukernel_abi::*;
9699
use if_let_rescope::IfLetRescope;
97100
use impl_trait_overcaptures::ImplTraitOvercaptures;
@@ -100,6 +103,7 @@ use internal::*;
100103
use invalid_from_utf8::*;
101104
use let_underscore::*;
102105
use lifetime_syntax::*;
106+
use lossy_provenance_casts::LossyProvenanceCasts;
103107
use macro_expr_fragment_specifier_2024_migration::*;
104108
use map_unit_fn::*;
105109
use multiple_supertrait_upcastable::*;
@@ -250,6 +254,8 @@ late_lint_methods!(
250254
CheckTransmutes: CheckTransmutes,
251255
LifetimeSyntax: LifetimeSyntax,
252256
InternalEqTraitMethodImpls: InternalEqTraitMethodImpls,
257+
FuzzyProvenanceCasts: FuzzyProvenanceCasts,
258+
LossyProvenanceCasts: LossyProvenanceCasts,
253259
]
254260
]
255261
);

compiler/rustc_lint/src/lints.rs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2932,3 +2932,85 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion {
29322932
#[diag("`Eq::assert_receiver_is_total_eq` should never be implemented by hand")]
29332933
#[note("this method was used to add checks to the `Eq` derive macro")]
29342934
pub(crate) struct EqInternalMethodImplemented;
2935+
2936+
#[derive(Diagnostic)]
2937+
#[diag("strict provenance disallows casting integer `{$expr_ty}` to pointer `{$cast_ty}`")]
2938+
#[help(
2939+
"if you can't comply with strict provenance and don't have a pointer with the correct provenance you can use `std::ptr::with_exposed_provenance()` instead"
2940+
)]
2941+
pub(crate) struct LossyProvenanceInt2Ptr<'tcx> {
2942+
pub expr_ty: Ty<'tcx>,
2943+
pub cast_ty: Ty<'tcx>,
2944+
#[subdiagnostic]
2945+
pub sugg: Option<LossyProvenanceInt2PtrSuggestion>,
2946+
}
2947+
2948+
#[derive(Subdiagnostic)]
2949+
#[multipart_suggestion(
2950+
"use `.with_addr()` to adjust a valid pointer in the same allocation, to this address",
2951+
applicability = "has-placeholders"
2952+
)]
2953+
pub(crate) struct LossyProvenanceInt2PtrSuggestion {
2954+
#[suggestion_part(code = "(...).with_addr(")]
2955+
pub lo: Span,
2956+
#[suggestion_part(code = ")")]
2957+
pub hi: Span,
2958+
}
2959+
2960+
#[derive(Diagnostic)]
2961+
#[diag(
2962+
"under strict provenance it is considered bad style to cast pointer `{$cast_from_ty}` to integer `{$cast_to_ty}`"
2963+
)]
2964+
#[help(
2965+
"if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_provenance()` instead"
2966+
)]
2967+
pub(crate) struct LossyProvenancePtr2Int<'tcx> {
2968+
pub cast_from_ty: Ty<'tcx>,
2969+
pub cast_to_ty: Ty<'tcx>,
2970+
#[subdiagnostic]
2971+
pub sugg: Option<LossyProvenancePtr2IntSuggestion<'tcx>>,
2972+
}
2973+
2974+
#[derive(Subdiagnostic)]
2975+
pub(crate) enum LossyProvenancePtr2IntSuggestion<'tcx> {
2976+
#[multipart_suggestion(
2977+
"use `.addr()` to obtain the address of a pointer",
2978+
applicability = "maybe-incorrect"
2979+
)]
2980+
NeedsParensCast {
2981+
#[suggestion_part(code = "(")]
2982+
expr_span: Span,
2983+
#[suggestion_part(code = ").addr() as {cast_to_ty}")]
2984+
cast_span: Span,
2985+
cast_to_ty: Ty<'tcx>,
2986+
},
2987+
#[multipart_suggestion(
2988+
"use `.addr()` to obtain the address of a pointer",
2989+
applicability = "maybe-incorrect"
2990+
)]
2991+
NeedsParens {
2992+
#[suggestion_part(code = "(")]
2993+
expr_span: Span,
2994+
#[suggestion_part(code = ").addr()")]
2995+
cast_span: Span,
2996+
},
2997+
#[suggestion(
2998+
"use `.addr()` to obtain the address of a pointer",
2999+
code = ".addr() as {cast_to_ty}",
3000+
applicability = "maybe-incorrect"
3001+
)]
3002+
NeedsCast {
3003+
#[primary_span]
3004+
cast_span: Span,
3005+
cast_to_ty: Ty<'tcx>,
3006+
},
3007+
#[suggestion(
3008+
"use `.addr()` to obtain the address of a pointer",
3009+
code = ".addr()",
3010+
applicability = "maybe-incorrect"
3011+
)]
3012+
Other {
3013+
#[primary_span]
3014+
cast_span: Span,
3015+
},
3016+
}

0 commit comments

Comments
 (0)