Skip to content

Commit 0f0ea11

Browse files
authored
Unrolled build for rust-lang#132732
Rollup merge of rust-lang#132732 - gavincrawford:as_ptr_attribute, r=Urgau Use attributes for `dangling_pointers_from_temporaries` lint Checking for dangling pointers by function name isn't ideal, and leaves out certain pointer-returning methods that don't follow the `as_ptr` naming convention. Using an attribute for this lint cleans things up and allows more thorough coverage of other methods, such as `UnsafeCell::get()`.
2 parents 70e814b + 01fd384 commit 0f0ea11

File tree

13 files changed

+83
-32
lines changed

13 files changed

+83
-32
lines changed

compiler/rustc_feature/src/builtin_attrs.rs

+5
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
879879
lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, EncodeCrossCrate::No, lang_items,
880880
"lang items are subject to change",
881881
),
882+
rustc_attr!(
883+
rustc_as_ptr, Normal, template!(Word), ErrorFollowing,
884+
EncodeCrossCrate::Yes,
885+
"#[rustc_as_ptr] is used to mark functions returning pointers to their inner allocations."
886+
),
882887
rustc_attr!(
883888
rustc_pass_by_value, Normal, template!(Word), ErrorFollowing,
884889
EncodeCrossCrate::Yes,

compiler/rustc_lint/src/dangling.rs

+13-14
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,10 @@ declare_lint! {
4343
}
4444

4545
/// FIXME: false negatives (i.e. the lint is not emitted when it should be)
46-
/// 1. Method calls that are not checked for:
47-
/// - [`temporary_unsafe_cell.get()`][`core::cell::UnsafeCell::get()`]
48-
/// - [`temporary_sync_unsafe_cell.get()`][`core::cell::SyncUnsafeCell::get()`]
49-
/// 2. Ways to get a temporary that are not recognized:
46+
/// 1. Ways to get a temporary that are not recognized:
5047
/// - `owning_temporary.field`
5148
/// - `owning_temporary[index]`
52-
/// 3. No checks for ref-to-ptr conversions:
49+
/// 2. No checks for ref-to-ptr conversions:
5350
/// - `&raw [mut] temporary`
5451
/// - `&temporary as *(const|mut) _`
5552
/// - `ptr::from_ref(&temporary)` and friends
@@ -133,10 +130,11 @@ impl DanglingPointerSearcher<'_, '_> {
133130

134131
fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) {
135132
if let ExprKind::MethodCall(method, receiver, _args, _span) = expr.kind
136-
&& matches!(method.ident.name, sym::as_ptr | sym::as_mut_ptr)
133+
&& let Some(fn_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
134+
&& cx.tcx.has_attr(fn_id, sym::rustc_as_ptr)
137135
&& is_temporary_rvalue(receiver)
138136
&& let ty = cx.typeck_results().expr_ty(receiver)
139-
&& is_interesting(cx.tcx, ty)
137+
&& owns_allocation(cx.tcx, ty)
140138
{
141139
// FIXME: use `emit_node_lint` when `#[primary_span]` is added.
142140
cx.tcx.emit_node_span_lint(
@@ -199,24 +197,25 @@ fn is_temporary_rvalue(expr: &Expr<'_>) -> bool {
199197
}
200198
}
201199

202-
// Array, Vec, String, CString, MaybeUninit, Cell, Box<[_]>, Box<str>, Box<CStr>,
203-
// or any of the above in arbitrary many nested Box'es.
204-
fn is_interesting(tcx: TyCtxt<'_>, ty: Ty<'_>) -> bool {
200+
// Array, Vec, String, CString, MaybeUninit, Cell, Box<[_]>, Box<str>, Box<CStr>, UnsafeCell,
201+
// SyncUnsafeCell, or any of the above in arbitrary many nested Box'es.
202+
fn owns_allocation(tcx: TyCtxt<'_>, ty: Ty<'_>) -> bool {
205203
if ty.is_array() {
206204
true
207205
} else if let Some(inner) = ty.boxed_ty() {
208206
inner.is_slice()
209207
|| inner.is_str()
210208
|| inner.ty_adt_def().is_some_and(|def| tcx.is_lang_item(def.did(), LangItem::CStr))
211-
|| is_interesting(tcx, inner)
209+
|| owns_allocation(tcx, inner)
212210
} else if let Some(def) = ty.ty_adt_def() {
213-
for lang_item in [LangItem::String, LangItem::MaybeUninit] {
211+
for lang_item in [LangItem::String, LangItem::MaybeUninit, LangItem::UnsafeCell] {
214212
if tcx.is_lang_item(def.did(), lang_item) {
215213
return true;
216214
}
217215
}
218-
tcx.get_diagnostic_name(def.did())
219-
.is_some_and(|name| matches!(name, sym::cstring_type | sym::Vec | sym::Cell))
216+
tcx.get_diagnostic_name(def.did()).is_some_and(|name| {
217+
matches!(name, sym::cstring_type | sym::Vec | sym::Cell | sym::SyncUnsafeCell)
218+
})
220219
} else {
221220
false
222221
}

compiler/rustc_passes/src/check_attr.rs

+3
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
162162
self.check_rustc_std_internal_symbol(attr, span, target)
163163
}
164164
[sym::naked, ..] => self.check_naked(hir_id, attr, span, target, attrs),
165+
[sym::rustc_as_ptr, ..] => {
166+
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
167+
}
165168
[sym::rustc_never_returns_null_ptr, ..] => {
166169
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
167170
}

compiler/rustc_span/src/symbol.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ symbols! {
316316
SubdiagMessage,
317317
Subdiagnostic,
318318
Sync,
319+
SyncUnsafeCell,
319320
T,
320321
Target,
321322
ToOwned,
@@ -409,7 +410,6 @@ symbols! {
409410
arm,
410411
arm_target_feature,
411412
array,
412-
as_mut_ptr,
413413
as_ptr,
414414
as_ref,
415415
as_str,
@@ -1655,6 +1655,7 @@ symbols! {
16551655
rustc_allow_const_fn_unstable,
16561656
rustc_allow_incoherent_impl,
16571657
rustc_allowed_through_unstable_modules,
1658+
rustc_as_ptr,
16581659
rustc_attrs,
16591660
rustc_autodiff,
16601661
rustc_box,

library/alloc/src/boxed.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1500,6 +1500,7 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
15001500
/// [`as_ptr`]: Self::as_ptr
15011501
#[unstable(feature = "box_as_ptr", issue = "129090")]
15021502
#[rustc_never_returns_null_ptr]
1503+
#[cfg_attr(not(bootstrap), rustc_as_ptr)]
15031504
#[inline]
15041505
pub fn as_mut_ptr(b: &mut Self) -> *mut T {
15051506
// This is a primitive deref, not going through `DerefMut`, and therefore not materializing
@@ -1548,6 +1549,7 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
15481549
/// [`as_ptr`]: Self::as_ptr
15491550
#[unstable(feature = "box_as_ptr", issue = "129090")]
15501551
#[rustc_never_returns_null_ptr]
1552+
#[cfg_attr(not(bootstrap), rustc_as_ptr)]
15511553
#[inline]
15521554
pub fn as_ptr(b: &Self) -> *const T {
15531555
// This is a primitive deref, not going through `DerefMut`, and therefore not materializing

library/alloc/src/vec/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1662,6 +1662,7 @@ impl<T, A: Allocator> Vec<T, A> {
16621662
#[stable(feature = "vec_as_ptr", since = "1.37.0")]
16631663
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
16641664
#[rustc_never_returns_null_ptr]
1665+
#[cfg_attr(not(bootstrap), rustc_as_ptr)]
16651666
#[inline]
16661667
pub const fn as_ptr(&self) -> *const T {
16671668
// We shadow the slice method of the same name to avoid going through
@@ -1724,6 +1725,7 @@ impl<T, A: Allocator> Vec<T, A> {
17241725
#[stable(feature = "vec_as_ptr", since = "1.37.0")]
17251726
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
17261727
#[rustc_never_returns_null_ptr]
1728+
#[cfg_attr(not(bootstrap), rustc_as_ptr)]
17271729
#[inline]
17281730
pub const fn as_mut_ptr(&mut self) -> *mut T {
17291731
// We shadow the slice method of the same name to avoid going through

library/core/src/cell.rs

+5
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,7 @@ impl<T: ?Sized> Cell<T> {
587587
#[inline]
588588
#[stable(feature = "cell_as_ptr", since = "1.12.0")]
589589
#[rustc_const_stable(feature = "const_cell_as_ptr", since = "1.32.0")]
590+
#[cfg_attr(not(bootstrap), rustc_as_ptr)]
590591
#[rustc_never_returns_null_ptr]
591592
pub const fn as_ptr(&self) -> *mut T {
592593
self.value.get()
@@ -1149,6 +1150,7 @@ impl<T: ?Sized> RefCell<T> {
11491150
/// ```
11501151
#[inline]
11511152
#[stable(feature = "cell_as_ptr", since = "1.12.0")]
1153+
#[cfg_attr(not(bootstrap), rustc_as_ptr)]
11521154
#[rustc_never_returns_null_ptr]
11531155
pub fn as_ptr(&self) -> *mut T {
11541156
self.value.get()
@@ -2158,6 +2160,7 @@ impl<T: ?Sized> UnsafeCell<T> {
21582160
#[inline(always)]
21592161
#[stable(feature = "rust1", since = "1.0.0")]
21602162
#[rustc_const_stable(feature = "const_unsafecell_get", since = "1.32.0")]
2163+
#[cfg_attr(not(bootstrap), rustc_as_ptr)]
21612164
#[rustc_never_returns_null_ptr]
21622165
pub const fn get(&self) -> *mut T {
21632166
// We can just cast the pointer from `UnsafeCell<T>` to `T` because of
@@ -2271,6 +2274,7 @@ impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<UnsafeCell<U>> for UnsafeCell<T>
22712274
/// See [`UnsafeCell`] for details.
22722275
#[unstable(feature = "sync_unsafe_cell", issue = "95439")]
22732276
#[repr(transparent)]
2277+
#[rustc_diagnostic_item = "SyncUnsafeCell"]
22742278
#[rustc_pub_transparent]
22752279
pub struct SyncUnsafeCell<T: ?Sized> {
22762280
value: UnsafeCell<T>,
@@ -2304,6 +2308,7 @@ impl<T: ?Sized> SyncUnsafeCell<T> {
23042308
/// when casting to `&mut T`, and ensure that there are no mutations
23052309
/// or mutable aliases going on when casting to `&T`
23062310
#[inline]
2311+
#[cfg_attr(not(bootstrap), rustc_as_ptr)]
23072312
#[rustc_never_returns_null_ptr]
23082313
pub const fn get(&self) -> *mut T {
23092314
self.value.get()

library/core/src/ffi/c_str.rs

+1
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,7 @@ impl CStr {
500500
#[must_use]
501501
#[stable(feature = "rust1", since = "1.0.0")]
502502
#[rustc_const_stable(feature = "const_str_as_ptr", since = "1.32.0")]
503+
#[cfg_attr(not(bootstrap), rustc_as_ptr)]
503504
#[rustc_never_returns_null_ptr]
504505
pub const fn as_ptr(&self) -> *const c_char {
505506
self.inner.as_ptr()

library/core/src/mem/maybe_uninit.rs

+2
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,7 @@ impl<T> MaybeUninit<T> {
525525
/// until they are, it is advisable to avoid them.)
526526
#[stable(feature = "maybe_uninit", since = "1.36.0")]
527527
#[rustc_const_stable(feature = "const_maybe_uninit_as_ptr", since = "1.59.0")]
528+
#[cfg_attr(not(bootstrap), rustc_as_ptr)]
528529
#[inline(always)]
529530
pub const fn as_ptr(&self) -> *const T {
530531
// `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer.
@@ -566,6 +567,7 @@ impl<T> MaybeUninit<T> {
566567
/// until they are, it is advisable to avoid them.)
567568
#[stable(feature = "maybe_uninit", since = "1.36.0")]
568569
#[rustc_const_stable(feature = "const_maybe_uninit_as_mut_ptr", since = "1.83.0")]
570+
#[cfg_attr(not(bootstrap), rustc_as_ptr)]
569571
#[inline(always)]
570572
pub const fn as_mut_ptr(&mut self) -> *mut T {
571573
// `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer.

library/core/src/slice/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,7 @@ impl<T> [T] {
735735
#[stable(feature = "rust1", since = "1.0.0")]
736736
#[rustc_const_stable(feature = "const_slice_as_ptr", since = "1.32.0")]
737737
#[rustc_never_returns_null_ptr]
738+
#[cfg_attr(not(bootstrap), rustc_as_ptr)]
738739
#[inline(always)]
739740
#[must_use]
740741
pub const fn as_ptr(&self) -> *const T {
@@ -765,6 +766,7 @@ impl<T> [T] {
765766
#[stable(feature = "rust1", since = "1.0.0")]
766767
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
767768
#[rustc_never_returns_null_ptr]
769+
#[cfg_attr(not(bootstrap), rustc_as_ptr)]
768770
#[inline(always)]
769771
#[must_use]
770772
pub const fn as_mut_ptr(&mut self) -> *mut T {

library/core/src/str/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ impl str {
373373
#[stable(feature = "rust1", since = "1.0.0")]
374374
#[rustc_const_stable(feature = "rustc_str_as_ptr", since = "1.32.0")]
375375
#[rustc_never_returns_null_ptr]
376+
#[cfg_attr(not(bootstrap), rustc_as_ptr)]
376377
#[must_use]
377378
#[inline(always)]
378379
pub const fn as_ptr(&self) -> *const u8 {
@@ -390,6 +391,7 @@ impl str {
390391
#[stable(feature = "str_as_mut_ptr", since = "1.36.0")]
391392
#[rustc_const_stable(feature = "const_str_as_mut", since = "1.83.0")]
392393
#[rustc_never_returns_null_ptr]
394+
#[cfg_attr(not(bootstrap), rustc_as_ptr)]
393395
#[must_use]
394396
#[inline(always)]
395397
pub const fn as_mut_ptr(&mut self) -> *mut u8 {

tests/ui/lint/dangling-pointers-from-temporaries/types.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![deny(dangling_pointers_from_temporaries)]
2+
#![feature(sync_unsafe_cell)]
23

3-
use std::cell::Cell;
4+
use std::cell::{Cell, SyncUnsafeCell, UnsafeCell};
45
use std::ffi::{CStr, CString};
56
use std::mem::MaybeUninit;
67

@@ -47,6 +48,10 @@ fn main() {
4748
//~^ ERROR a dangling pointer will be produced because the temporary `MaybeUninit<u8>` will be dropped
4849
declval::<Vec<AsPtrFake>>().as_ptr();
4950
//~^ ERROR a dangling pointer will be produced because the temporary `Vec<AsPtrFake>` will be dropped
51+
declval::<UnsafeCell<u8>>().get();
52+
//~^ ERROR a dangling pointer will be produced because the temporary `UnsafeCell<u8>` will be dropped
53+
declval::<SyncUnsafeCell<u8>>().get();
54+
//~^ ERROR a dangling pointer will be produced because the temporary `SyncUnsafeCell<u8>` will be dropped
5055
declval::<Box<AsPtrFake>>().as_ptr();
5156
declval::<AsPtrFake>().as_ptr();
5257
}

0 commit comments

Comments
 (0)