Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of rust-lang#128985 - GrigorenkoPV:instantly-dangling-poin…
Browse files Browse the repository at this point in the history
…ter, r=<try>

Lint against getting pointers from immediately dropped temporaries

Fixes rust-lang#123613

## Changes:
1. New lint: `dangling_pointers_from_temporaries`. Is a generalization of `temporary_cstring_as_ptr` for more types and more ways to get a temporary.
2. `temporary_cstring_as_ptr` is marked as renamed to `dangling_pointers_from_temporaries`.
3. `clippy::temporary_cstring_as_ptr` is marked as renamed to `dangling_pointers_from_temporaries`.
4. `core::cell::Cell` is now `rustc_diagnostic_item = "Cell"`

## TODO:
- [x] ~Add tests for different types~
- [x] ~Add tests for different ways of getting a temporary~
- [x] ~Regroup tests for this and `temporary_cstring_as_ptr`~
- [x] ~Fix a strange ICE when the lint is `allow`ed.~
- [x] ~Check what happens when you `break` with a bound variable from `loop`/`match`/`if`/`block`.~
- [x] ~Document the lint~
- [x] ~Fix tests rust-lang#128985 (comment)
- [x] ~Fix clippy~
- [x] ~Fix miri rust-lang#128985 (review)
- [ ] Crater run?

## Questions:
- [ ] Should we make something like `is_temporary_rvalue` (but not bogus) available in compiler?
- [x] ~Should `temporary_cstring_as_ptr` be deprecated? Across an edition boundary?~
- [ ] Instead of manually checking for a list of known methods, maybe add some sort of annotation to those methods in library and check for the presence of that annotation?
- [ ] Maybe even introduce some form of primitive lifetimes for pointers and check those in borrow-checker?

## Future improvements:
- [ ] Fix false negatives[^fn]
- [ ] Add suggestions rust-lang#128985 (comment)

## Known limitations:

### False negatives[^fn]:

[^fn]: lint **should** be emitted, but **is not**

- `temporary_unsafe_cell.get()`
- `temporary.field.as_ptr()`
- `temporary[index].as_ptr()`
- Converting `&temporary` to pointer with `as` or stuff like `ptr::from_ref`.
- The `&raw [mut] temporary`

### False positives[^fp]:

[^fp]: lint **should not** be emitted, but **is**

Both this lint and the already existing `temporary_cstring_as_ptr` will fire on code like this:
```rust
foo(CString::new("hello").unwrap().as_ptr())
```
even though using the resulting pointer inside of `foo` is completely fine (at least according to miri),
probably due to argument promotion logic.
bors committed Aug 23, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
2 parents b5723af + 56036ea commit 217814b
Showing 26 changed files with 765 additions and 114 deletions.
12 changes: 6 additions & 6 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
@@ -209,12 +209,6 @@ lint_crate_name_in_cfg_attr_deprecated =
lint_crate_type_in_cfg_attr_deprecated =
`crate_type` within an `#![cfg_attr]` attribute is deprecated
lint_cstring_ptr = getting the inner pointer of a temporary `CString`
.as_ptr_label = this pointer will be invalid
.unwrap_label = this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
.note = pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
.help = for more information, see https://doc.rust-lang.org/reference/destructors.html
lint_custom_inner_attribute_unstable = custom inner attributes are unstable
lint_default_hash_types = prefer `{$preferred}` over `{$used}`, it has better performance
@@ -411,6 +405,12 @@ lint_incomplete_include =
lint_inner_macro_attribute_unstable = inner macro attributes are unstable
lint_instantly_dangling = getting a pointer from a temporary `{$ty}` will result in a dangling pointer
.label_ptr = this pointer will immediately be invalid
.label_temporary = this `{$ty}` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
.note = pointers do not have a lifetime; when calling `{$callee}` the `{$ty}` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
.help = for more information, see https://doc.rust-lang.org/reference/destructors.html
lint_invalid_asm_label_binary = avoid using labels containing only the digits `0` and `1` in inline assembly
.label = use a different label that doesn't start with `0` or `1`
.help = start numbering with `2` instead
137 changes: 137 additions & 0 deletions compiler/rustc_lint/src/dangling.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
use rustc_hir::{Expr, ExprKind, LangItem};
use rustc_middle::ty::{Ty, TyCtxt};
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::symbol::sym;

use crate::lints::InstantlyDangling;
use crate::{LateContext, LateLintPass, LintContext};

// FIXME: does not catch UnsafeCell::get
// FIXME: does not catch getting a ref to a temporary and then converting it to a ptr
declare_lint! {
/// The `dangling_pointers_from_temporaries` lint detects getting a pointer to data
/// of a temporary that will immediately get dropped.
///
/// ### Example
///
/// ```rust
/// # #![allow(unused)]
/// # unsafe fn use_data(ptr: *const u8) {
/// # dbg!(unsafe { ptr.read() });
/// # }
/// fn gather_and_use(bytes: impl Iterator<Item = u8>) {
/// let x: *const u8 = bytes.collect::<Vec<u8>>().as_ptr();
/// unsafe { use_data(x) }
/// }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Getting a pointer from a temporary value will not prolong its lifetime,
/// which means that the value can be dropped and the allocation freed
/// while the pointer still exists, making the pointer dangling.
/// This is not an error (as far as the type system is concerned)
/// but probably is not what the user intended either.
///
/// If you need stronger guarantees, consider using references instead,
/// as they are statically verified by the borrow-checker to never dangle.
pub DANGLING_POINTERS_FROM_TEMPORARIES,
Warn,
"detects getting a pointer from a temporary"
}

declare_lint_pass!(DanglingPointers => [DANGLING_POINTERS_FROM_TEMPORARIES]);

impl<'tcx> LateLintPass<'tcx> for DanglingPointers {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if let ExprKind::MethodCall(method, receiver, _args, _span) = expr.kind
&& matches!(method.ident.name, sym::as_ptr | sym::as_mut_ptr)
&& is_temporary_rvalue(receiver)
&& let ty = cx.typeck_results().expr_ty(receiver)
&& is_interesting(cx.tcx, ty)
{
cx.emit_span_lint(
DANGLING_POINTERS_FROM_TEMPORARIES,
method.ident.span,
InstantlyDangling {
callee: method.ident.name,
ty,
ptr_span: method.ident.span,
temporary_span: receiver.span,
},
)
}
}
}

fn is_temporary_rvalue(expr: &Expr<'_>) -> bool {
match expr.kind {
// Const is not temporary.
ExprKind::ConstBlock(..) | ExprKind::Repeat(..) | ExprKind::Lit(..) => false,

// This is literally lvalue.
ExprKind::Path(..) => false,

// Calls return rvalues.
ExprKind::Call(..) | ExprKind::MethodCall(..) | ExprKind::Binary(..) => true,

// Inner blocks are rvalues.
ExprKind::If(..) | ExprKind::Loop(..) | ExprKind::Match(..) | ExprKind::Block(..) => true,

// FIXME: these should probably recurse and typecheck along the way.
// Some false negatives are possible for now.
ExprKind::Index(..) | ExprKind::Field(..) | ExprKind::Unary(..) => false,

ExprKind::Struct(..) => true,

// FIXME: this has false negatives, but I do not want to deal with 'static/const promotion just yet.
ExprKind::Array(..) => false,

// These typecheck to `!`
ExprKind::Break(..) | ExprKind::Continue(..) | ExprKind::Ret(..) | ExprKind::Become(..) => {
false
}

// These typecheck to `()`
ExprKind::Assign(..) | ExprKind::AssignOp(..) | ExprKind::Yield(..) => false,

// Compiler-magic macros
ExprKind::AddrOf(..) | ExprKind::OffsetOf(..) | ExprKind::InlineAsm(..) => false,

// We are not interested in these
ExprKind::Cast(..)
| ExprKind::Closure(..)
| ExprKind::Tup(..)
| ExprKind::DropTemps(..)
| ExprKind::Let(..) => false,

// Not applicable
ExprKind::Type(..) | ExprKind::Err(..) => false,
}
}

// Array, Vec, String, CString, MaybeUninit, Cell, Box<[_]>, Box<str>, Box<CStr>,
// or any of the above in arbitrary many nested Box'es.
fn is_interesting(tcx: TyCtxt<'_>, ty: Ty<'_>) -> bool {
if ty.is_array() {
true
} else if ty.is_box() {
let inner = ty.boxed_ty();
inner.is_slice()
|| inner.is_str()
|| inner.ty_adt_def().is_some_and(|def| tcx.is_lang_item(def.did(), LangItem::CStr))
|| is_interesting(tcx, inner)
} else if let Some(def) = ty.ty_adt_def() {
for lang_item in [LangItem::String, LangItem::MaybeUninit] {
if tcx.is_lang_item(def.did(), lang_item) {
return true;
}
}
tcx.get_diagnostic_name(def.did())
.is_some_and(|name| matches!(name, sym::cstring_type | sym::Vec | sym::Cell))
} else {
false
}
}
7 changes: 4 additions & 3 deletions compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
@@ -45,6 +45,7 @@ mod async_closures;
mod async_fn_in_trait;
pub mod builtin;
mod context;
mod dangling;
mod deref_into_dyn_supertrait;
mod drop_forget_useless;
mod early;
@@ -63,7 +64,6 @@ mod levels;
mod lints;
mod macro_expr_fragment_specifier_2024_migration;
mod map_unit_fn;
mod methods;
mod multiple_supertrait_upcastable;
mod non_ascii_idents;
mod non_fmt_panic;
@@ -87,6 +87,7 @@ mod unused;
use async_closures::AsyncClosureUsage;
use async_fn_in_trait::AsyncFnInTrait;
use builtin::*;
use dangling::*;
use deref_into_dyn_supertrait::*;
use drop_forget_useless::*;
use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
@@ -98,7 +99,6 @@ use invalid_from_utf8::*;
use let_underscore::*;
use macro_expr_fragment_specifier_2024_migration::*;
use map_unit_fn::*;
use methods::*;
use multiple_supertrait_upcastable::*;
use non_ascii_idents::*;
use non_fmt_panic::NonPanicFmt;
@@ -225,7 +225,7 @@ late_lint_methods!(
UngatedAsyncFnTrackCaller: UngatedAsyncFnTrackCaller,
ShadowedIntoIter: ShadowedIntoIter,
DropTraitConstraints: DropTraitConstraints,
TemporaryCStringAsPtr: TemporaryCStringAsPtr,
DanglingPointers: DanglingPointers,
NonPanicFmt: NonPanicFmt,
NoopMethodCall: NoopMethodCall,
EnumIntrinsicsNonEnums: EnumIntrinsicsNonEnums,
@@ -346,6 +346,7 @@ fn register_builtins(store: &mut LintStore) {
store.register_renamed("non_fmt_panic", "non_fmt_panics");
store.register_renamed("unused_tuple_struct_fields", "dead_code");
store.register_renamed("static_mut_ref", "static_mut_refs");
store.register_renamed("temporary_cstring_as_ptr", "dangling_pointers_from_temporaries");

// These were moved to tool lints, but rustc still sees them when compiling normally, before
// tool lints are registered, so `check_tool_name_for_backwards_compat` doesn't work. Use
17 changes: 10 additions & 7 deletions compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
@@ -1124,16 +1124,19 @@ pub struct IgnoredUnlessCrateSpecified<'a> {
pub name: Symbol,
}

// methods.rs
// dangling.rs
#[derive(LintDiagnostic)]
#[diag(lint_cstring_ptr)]
#[diag(lint_instantly_dangling)]
#[note]
#[help]
pub struct CStringPtr {
#[label(lint_as_ptr_label)]
pub as_ptr: Span,
#[label(lint_unwrap_label)]
pub unwrap: Span,
// FIXME: use #[primary_span]
pub struct InstantlyDangling<'tcx> {
pub callee: Symbol,
pub ty: Ty<'tcx>,
#[label(lint_label_ptr)]
pub ptr_span: Span,
#[label(lint_label_temporary)]
pub temporary_span: Span,
}

// multiple_supertrait_upcastable.rs
70 changes: 0 additions & 70 deletions compiler/rustc_lint/src/methods.rs

This file was deleted.

2 changes: 2 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
@@ -170,6 +170,7 @@ symbols! {
CallOnceFuture,
CallRefFuture,
Capture,
Cell,
Center,
Cleanup,
Clone,
@@ -411,6 +412,7 @@ symbols! {
arm,
arm_target_feature,
array,
as_mut_ptr,
as_ptr,
as_ref,
as_str,
1 change: 1 addition & 0 deletions library/alloc/tests/boxed.rs
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ use core::mem::MaybeUninit;
use core::ptr::NonNull;

#[test]
#[cfg_attr(not(bootstrap), expect(dangling_pointers_from_temporaries))]
fn uninitialized_zero_size_box() {
assert_eq!(
&*Box::<()>::new_uninit() as *const _,
1 change: 1 addition & 0 deletions library/core/src/cell.rs
Original file line number Diff line number Diff line change
@@ -304,6 +304,7 @@ pub use once::OnceCell;
/// ```
///
/// See the [module-level documentation](self) for more.
#[cfg_attr(not(test), rustc_diagnostic_item = "Cell")]
#[stable(feature = "rust1", since = "1.0.0")]
#[repr(transparent)]
pub struct Cell<T: ?Sized> {
4 changes: 3 additions & 1 deletion library/core/src/ffi/c_str.rs
Original file line number Diff line number Diff line change
@@ -463,7 +463,9 @@ impl CStr {
/// behavior when `ptr` is used inside the `unsafe` block:
///
/// ```no_run
/// # #![allow(unused_must_use)] #![allow(temporary_cstring_as_ptr)]
/// # #![allow(unused_must_use)]
/// # #![cfg_attr(bootstrap, expect(temporary_cstring_as_ptr))]
/// # #![cfg_attr(not(bootstrap), expect(dangling_pointers_from_temporaries))]
/// use std::ffi::CString;
///
/// // Do not do this:
2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_lints/src/deprecated_lints.rs
Original file line number Diff line number Diff line change
@@ -166,7 +166,7 @@ declare_with_version! { RENAMED(RENAMED_VERSION): &[(&str, &str)] = &[
#[clippy::version = ""]
("clippy::positional_named_format_parameters", "named_arguments_used_positionally"),
#[clippy::version = ""]
("clippy::temporary_cstring_as_ptr", "temporary_cstring_as_ptr"),
("clippy::temporary_cstring_as_ptr", "dangling_pointers_from_temporaries"),
#[clippy::version = ""]
("clippy::undropped_manually_drops", "undropped_manually_drops"),
#[clippy::version = ""]
4 changes: 2 additions & 2 deletions src/tools/clippy/tests/ui/rename.fixed
Original file line number Diff line number Diff line change
@@ -54,7 +54,7 @@
#![allow(enum_intrinsics_non_enums)]
#![allow(non_fmt_panics)]
#![allow(named_arguments_used_positionally)]
#![allow(temporary_cstring_as_ptr)]
#![allow(dangling_pointers_from_temporaries)]
#![allow(undropped_manually_drops)]
#![allow(unknown_lints)]
#![allow(unused_labels)]
@@ -120,7 +120,7 @@
#![warn(unexpected_cfgs)] //~ ERROR: lint `clippy::mismatched_target_os`
#![warn(non_fmt_panics)] //~ ERROR: lint `clippy::panic_params`
#![warn(named_arguments_used_positionally)] //~ ERROR: lint `clippy::positional_named_format_parameters`
#![warn(temporary_cstring_as_ptr)] //~ ERROR: lint `clippy::temporary_cstring_as_ptr`
#![warn(dangling_pointers_from_temporaries)] //~ ERROR: lint `clippy::temporary_cstring_as_ptr`
#![warn(undropped_manually_drops)] //~ ERROR: lint `clippy::undropped_manually_drops`
#![warn(unknown_lints)] //~ ERROR: lint `clippy::unknown_clippy_lints`
#![warn(unused_labels)] //~ ERROR: lint `clippy::unused_label`
18 changes: 12 additions & 6 deletions src/tools/clippy/tests/ui/rename.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
error: lint `temporary_cstring_as_ptr` has been renamed to `dangling_pointers_from_temporaries`
--> tests/ui/rename.rs:57:10
|
LL | #![allow(temporary_cstring_as_ptr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `dangling_pointers_from_temporaries`
|
= note: `-D renamed-and-removed-lints` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(renamed_and_removed_lints)]`

error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
--> tests/ui/rename.rs:63:9
|
LL | #![warn(clippy::almost_complete_letter_range)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
|
= note: `-D renamed-and-removed-lints` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(renamed_and_removed_lints)]`

error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
--> tests/ui/rename.rs:64:9
@@ -361,11 +367,11 @@ error: lint `clippy::positional_named_format_parameters` has been renamed to `na
LL | #![warn(clippy::positional_named_format_parameters)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`

error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `dangling_pointers_from_temporaries`
--> tests/ui/rename.rs:123:9
|
LL | #![warn(clippy::temporary_cstring_as_ptr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `dangling_pointers_from_temporaries`

error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops`
--> tests/ui/rename.rs:124:9
@@ -397,5 +403,5 @@ error: lint `clippy::reverse_range_loop` has been renamed to `clippy::reversed_e
LL | #![warn(clippy::reverse_range_loop)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::reversed_empty_ranges`

error: aborting due to 66 previous errors
error: aborting due to 67 previous errors

7 changes: 5 additions & 2 deletions tests/ui/consts/zst_no_llvm_alloc.rs
Original file line number Diff line number Diff line change
@@ -17,8 +17,11 @@ fn main() {

// The exact addresses returned by these library functions are not necessarily stable guarantees
// but for now we assert that we're still matching.
assert_eq!(<Vec<i32>>::new().as_ptr(), <&[i32]>::default().as_ptr());
assert_eq!(<Box<[i32]>>::default().as_ptr(), (&[]).as_ptr());
#[expect(dangling_pointers_from_temporaries)]
{
assert_eq!(<Vec<i32>>::new().as_ptr(), <&[i32]>::default().as_ptr());
assert_eq!(<Box<[i32]>>::default().as_ptr(), (&[]).as_ptr());
};

// statics must have a unique address (see https://github.com/rust-lang/rust/issues/18297, not
// clear whether this is a stable guarantee)
9 changes: 9 additions & 0 deletions tests/ui/lint/dangling-pointers-from-temporaries/allow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//@ check-pass

// This should not ICE.

#![allow(dangling_pointers_from_temporaries)]

fn main() {
dbg!(String::new().as_ptr());
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![deny(temporary_cstring_as_ptr)]
//~^ WARNING lint `temporary_cstring_as_ptr` has been renamed to `dangling_pointers_from_temporaries`

use std::ffi::CString;
use std::os::raw::c_char;
@@ -7,5 +8,5 @@ fn some_function(data: *const c_char) {}

fn main() {
some_function(CString::new("").unwrap().as_ptr());
//~^ ERROR getting the inner pointer of a temporary `CString`
//~^ ERROR getting a pointer from a temporary `CString` will result in a dangling pointer
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
error: getting the inner pointer of a temporary `CString`
--> $DIR/lint-temporary-cstring-as-param.rs:9:45
warning: lint `temporary_cstring_as_ptr` has been renamed to `dangling_pointers_from_temporaries`
--> $DIR/cstring-as-param.rs:1:9
|
LL | #![deny(temporary_cstring_as_ptr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `dangling_pointers_from_temporaries`
|
= note: `#[warn(renamed_and_removed_lints)]` on by default

error: getting a pointer from a temporary `CString` will result in a dangling pointer
--> $DIR/cstring-as-param.rs:10:45
|
LL | some_function(CString::new("").unwrap().as_ptr());
| ------------------------- ^^^^^^ this pointer will be invalid
| ------------------------- ^^^^^^ this pointer will immediately be invalid
| |
| this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html
note: the lint level is defined here
--> $DIR/lint-temporary-cstring-as-param.rs:1:9
--> $DIR/cstring-as-param.rs:1:9
|
LL | #![deny(temporary_cstring_as_ptr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error
error: aborting due to 1 previous error; 1 warning emitted

Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
// this program is not technically incorrect, but is an obscure enough style to be worth linting
#![deny(temporary_cstring_as_ptr)]
//~^ WARNING lint `temporary_cstring_as_ptr` has been renamed to `dangling_pointers_from_temporaries`

use std::ffi::CString;

macro_rules! mymacro {
() => {
let s = CString::new("some text").unwrap().as_ptr();
//~^ ERROR getting the inner pointer of a temporary `CString`
//~^ ERROR getting a pointer from a temporary `CString` will result in a dangling pointer
}
}

fn main() {
let s = CString::new("some text").unwrap().as_ptr();
//~^ ERROR getting the inner pointer of a temporary `CString`
//~^ ERROR getting a pointer from a temporary `CString` will result in a dangling pointer
mymacro!();
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,32 @@
error: getting the inner pointer of a temporary `CString`
--> $DIR/lint-temporary-cstring-as-ptr.rs:14:48
warning: lint `temporary_cstring_as_ptr` has been renamed to `dangling_pointers_from_temporaries`
--> $DIR/cstring-as-ptr.rs:2:9
|
LL | #![deny(temporary_cstring_as_ptr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `dangling_pointers_from_temporaries`
|
= note: `#[warn(renamed_and_removed_lints)]` on by default

error: getting a pointer from a temporary `CString` will result in a dangling pointer
--> $DIR/cstring-as-ptr.rs:15:48
|
LL | let s = CString::new("some text").unwrap().as_ptr();
| ---------------------------------- ^^^^^^ this pointer will be invalid
| ---------------------------------- ^^^^^^ this pointer will immediately be invalid
| |
| this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html
note: the lint level is defined here
--> $DIR/lint-temporary-cstring-as-ptr.rs:2:9
--> $DIR/cstring-as-ptr.rs:2:9
|
LL | #![deny(temporary_cstring_as_ptr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^

error: getting the inner pointer of a temporary `CString`
--> $DIR/lint-temporary-cstring-as-ptr.rs:8:52
error: getting a pointer from a temporary `CString` will result in a dangling pointer
--> $DIR/cstring-as-ptr.rs:9:52
|
LL | let s = CString::new("some text").unwrap().as_ptr();
| ---------------------------------- ^^^^^^ this pointer will be invalid
| ---------------------------------- ^^^^^^ this pointer will immediately be invalid
| |
| this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
...
@@ -29,5 +37,5 @@ LL | mymacro!();
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html
= note: this error originates in the macro `mymacro` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 2 previous errors
error: aborting due to 2 previous errors; 1 warning emitted

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#![deny(dangling_pointers_from_temporaries)]

const MAX_PATH: usize = 260;
fn main() {
let str1 = String::with_capacity(MAX_PATH).as_mut_ptr();
//~^ ERROR getting a pointer from a temporary `String` will result in a dangling pointer
let str2 = String::from("TotototototototototototototototototoT").as_ptr();
//~^ ERROR getting a pointer from a temporary `String` will result in a dangling pointer
unsafe {
std::ptr::copy_nonoverlapping(str2, str1, 30);
println!("{:?}", String::from_raw_parts(str1, 30, 30));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
error: getting a pointer from a temporary `String` will result in a dangling pointer
--> $DIR/example-from-issue123613.rs:5:48
|
LL | let str1 = String::with_capacity(MAX_PATH).as_mut_ptr();
| ------------------------------- ^^^^^^^^^^ this pointer will immediately be invalid
| |
| this `String` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_mut_ptr` the `String` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html
note: the lint level is defined here
--> $DIR/example-from-issue123613.rs:1:9
|
LL | #![deny(dangling_pointers_from_temporaries)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: getting a pointer from a temporary `String` will result in a dangling pointer
--> $DIR/example-from-issue123613.rs:7:70
|
LL | let str2 = String::from("TotototototototototototototototototoT").as_ptr();
| ----------------------------------------------------- ^^^^^^ this pointer will immediately be invalid
| |
| this `String` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `String` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html

error: aborting due to 2 previous errors

8 changes: 8 additions & 0 deletions tests/ui/lint/dangling-pointers-from-temporaries/methods.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![deny(dangling_pointers_from_temporaries)]

fn main() {
vec![0u8].as_ptr();
//~^ ERROR getting a pointer from a temporary `Vec<u8>` will result in a dangling pointer
vec![0u8].as_mut_ptr();
//~^ ERROR getting a pointer from a temporary `Vec<u8>` will result in a dangling pointer
}
29 changes: 29 additions & 0 deletions tests/ui/lint/dangling-pointers-from-temporaries/methods.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
error: getting a pointer from a temporary `Vec<u8>` will result in a dangling pointer
--> $DIR/methods.rs:4:15
|
LL | vec![0u8].as_ptr();
| --------- ^^^^^^ this pointer will immediately be invalid
| |
| this `Vec<u8>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `Vec<u8>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html
note: the lint level is defined here
--> $DIR/methods.rs:1:9
|
LL | #![deny(dangling_pointers_from_temporaries)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: getting a pointer from a temporary `Vec<u8>` will result in a dangling pointer
--> $DIR/methods.rs:6:15
|
LL | vec![0u8].as_mut_ptr();
| --------- ^^^^^^^^^^ this pointer will immediately be invalid
| |
| this `Vec<u8>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_mut_ptr` the `Vec<u8>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html

error: aborting due to 2 previous errors

136 changes: 136 additions & 0 deletions tests/ui/lint/dangling-pointers-from-temporaries/temporaries.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#![allow(unused)]
#![deny(dangling_pointers_from_temporaries)]

fn string() -> String {
"hello".into()
}

struct Wrapper(String);

fn main() {
// ConstBlock
const { String::new() }.as_ptr();

// Array
{
[string()].as_ptr(); // False negative
[true].as_ptr();
}

// Call
string().as_ptr();
//~^ ERROR getting a pointer from a temporary `String` will result in a dangling pointer

// MethodCall
"hello".to_string().as_ptr();
//~^ ERROR getting a pointer from a temporary `String` will result in a dangling pointer

// Tup
// impossible

// Binary
(string() + "hello").as_ptr();
//~^ ERROR getting a pointer from a temporary `String` will result in a dangling pointer

// Path
{
let x = string();
x.as_ptr();
}

// Unary
{
let x = string();
let x: &String = &x;
(*x).as_ptr();
(&[0u8]).as_ptr();
(&string()).as_ptr(); // False negative
(*&string()).as_ptr(); // False negative
}

// Lit
"hello".as_ptr();

// Cast
// impossible

// Type
// impossible

// DropTemps
// impossible

// Let
// impossible

// If
{
(if true { String::new() } else { "hello".into() }).as_ptr();
//~^ ERROR getting a pointer from a temporary `String` will result in a dangling pointer
}

// Loop
{
(loop {
break String::new();
})
.as_ptr();
//~^ ERROR getting a pointer from a temporary `String` will result in a dangling pointer
}

// Match
{
match string() {
s => s,
}
.as_ptr();
//~^ ERROR getting a pointer from a temporary `String` will result in a dangling pointer
}

// Closure
// impossible

// Block
{ string() }.as_ptr();
//~^ ERROR getting a pointer from a temporary `String` will result in a dangling pointer

// Assign, AssignOp
// impossible

// Field
{
Wrapper(string()).0.as_ptr(); // False negative
let x = Wrapper(string());
x.0.as_ptr();
}

// Index
{
vec![string()][0].as_ptr(); // False negative
let x = vec![string()];
x[0].as_ptr();
}

// AddrOf, InlineAsm, OffsetOf
// impossible

// Break, Continue, Ret
// are !

// Become, Yield
// unstable, are !

// Repeat
[0u8; 100].as_ptr();
[const { String::new() }; 100].as_ptr();

// Struct
// Cannot test this without access to private fields of the linted types.

// Err
// impossible

// Macro
vec![0u8].as_ptr();
//~^ ERROR getting a pointer from a temporary `Vec<u8>` will result in a dangling pointer
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
error: getting a pointer from a temporary `String` will result in a dangling pointer
--> $DIR/temporaries.rs:21:14
|
LL | string().as_ptr();
| -------- ^^^^^^ this pointer will immediately be invalid
| |
| this `String` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `String` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html
note: the lint level is defined here
--> $DIR/temporaries.rs:2:9
|
LL | #![deny(dangling_pointers_from_temporaries)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: getting a pointer from a temporary `String` will result in a dangling pointer
--> $DIR/temporaries.rs:25:25
|
LL | "hello".to_string().as_ptr();
| ------------------- ^^^^^^ this pointer will immediately be invalid
| |
| this `String` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `String` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html

error: getting a pointer from a temporary `String` will result in a dangling pointer
--> $DIR/temporaries.rs:32:26
|
LL | (string() + "hello").as_ptr();
| -------------------- ^^^^^^ this pointer will immediately be invalid
| |
| this `String` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `String` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html

error: getting a pointer from a temporary `String` will result in a dangling pointer
--> $DIR/temporaries.rs:68:61
|
LL | (if true { String::new() } else { "hello".into() }).as_ptr();
| --------------------------------------------------- ^^^^^^ this pointer will immediately be invalid
| |
| this `String` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `String` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html

error: getting a pointer from a temporary `String` will result in a dangling pointer
--> $DIR/temporaries.rs:77:10
|
LL | / (loop {
LL | | break String::new();
LL | | })
| |__________- this `String` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
LL | .as_ptr();
| ^^^^^^ this pointer will immediately be invalid
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `String` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html

error: getting a pointer from a temporary `String` will result in a dangling pointer
--> $DIR/temporaries.rs:86:10
|
LL | / match string() {
LL | | s => s,
LL | | }
| |_________- this `String` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
LL | .as_ptr();
| ^^^^^^ this pointer will immediately be invalid
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `String` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html

error: getting a pointer from a temporary `String` will result in a dangling pointer
--> $DIR/temporaries.rs:94:18
|
LL | { string() }.as_ptr();
| ------------ ^^^^^^ this pointer will immediately be invalid
| |
| this `String` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `String` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html

error: getting a pointer from a temporary `Vec<u8>` will result in a dangling pointer
--> $DIR/temporaries.rs:134:15
|
LL | vec![0u8].as_ptr();
| --------- ^^^^^^ this pointer will immediately be invalid
| |
| this `Vec<u8>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `Vec<u8>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html

error: aborting due to 8 previous errors

52 changes: 52 additions & 0 deletions tests/ui/lint/dangling-pointers-from-temporaries/types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#![deny(dangling_pointers_from_temporaries)]

use std::cell::Cell;
use std::ffi::{CStr, CString};
use std::mem::MaybeUninit;

struct AsPtrFake;

impl AsPtrFake {
fn as_ptr(&self) -> *const () {
std::ptr::null()
}
}

fn declval<T>() -> T {
loop {}
}

fn main() {
declval::<CString>().as_ptr();
//~^ ERROR getting a pointer from a temporary `CString` will result in a dangling pointer
declval::<String>().as_ptr();
//~^ ERROR getting a pointer from a temporary `String` will result in a dangling pointer
declval::<Vec<u8>>().as_ptr();
//~^ ERROR getting a pointer from a temporary `Vec<u8>` will result in a dangling pointer
declval::<Box<CString>>().as_ptr();
//~^ ERROR getting a pointer from a temporary `Box<CString>` will result in a dangling pointer
declval::<Box<[u8]>>().as_ptr();
//~^ ERROR getting a pointer from a temporary `Box<[u8]>` will result in a dangling pointer
declval::<Box<str>>().as_ptr();
//~^ ERROR getting a pointer from a temporary `Box<str>` will result in a dangling pointer
declval::<Box<CStr>>().as_ptr();
//~^ ERROR getting a pointer from a temporary `Box<CStr>` will result in a dangling pointer
declval::<[u8; 10]>().as_ptr();
//~^ ERROR getting a pointer from a temporary `[u8; 10]` will result in a dangling pointer
declval::<Box<[u8; 10]>>().as_ptr();
//~^ ERROR getting a pointer from a temporary `Box<[u8; 10]>` will result in a dangling pointer
declval::<Box<Vec<u8>>>().as_ptr();
//~^ ERROR getting a pointer from a temporary `Box<Vec<u8>>` will result in a dangling pointer
declval::<Box<String>>().as_ptr();
//~^ ERROR getting a pointer from a temporary `Box<String>` will result in a dangling pointer
declval::<Box<Box<Box<Box<[u8]>>>>>().as_ptr();
//~^ ERROR getting a pointer from a temporary `Box<Box<Box<Box<[u8]>>>>` will result in a dangling pointer
declval::<Cell<u8>>().as_ptr();
//~^ ERROR getting a pointer from a temporary `Cell<u8>` will result in a dangling pointer
declval::<MaybeUninit<u8>>().as_ptr();
//~^ ERROR getting a pointer from a temporary `MaybeUninit<u8>` will result in a dangling pointer
declval::<Vec<AsPtrFake>>().as_ptr();
//~^ ERROR getting a pointer from a temporary `Vec<AsPtrFake>` will result in a dangling pointer
declval::<Box<AsPtrFake>>().as_ptr();
declval::<AsPtrFake>().as_ptr();
}
172 changes: 172 additions & 0 deletions tests/ui/lint/dangling-pointers-from-temporaries/types.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
error: getting a pointer from a temporary `CString` will result in a dangling pointer
--> $DIR/types.rs:20:26
|
LL | declval::<CString>().as_ptr();
| -------------------- ^^^^^^ this pointer will immediately be invalid
| |
| this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html
note: the lint level is defined here
--> $DIR/types.rs:1:9
|
LL | #![deny(dangling_pointers_from_temporaries)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: getting a pointer from a temporary `String` will result in a dangling pointer
--> $DIR/types.rs:22:25
|
LL | declval::<String>().as_ptr();
| ------------------- ^^^^^^ this pointer will immediately be invalid
| |
| this `String` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `String` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html

error: getting a pointer from a temporary `Vec<u8>` will result in a dangling pointer
--> $DIR/types.rs:24:26
|
LL | declval::<Vec<u8>>().as_ptr();
| -------------------- ^^^^^^ this pointer will immediately be invalid
| |
| this `Vec<u8>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `Vec<u8>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html

error: getting a pointer from a temporary `Box<CString>` will result in a dangling pointer
--> $DIR/types.rs:26:31
|
LL | declval::<Box<CString>>().as_ptr();
| ------------------------- ^^^^^^ this pointer will immediately be invalid
| |
| this `Box<CString>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `Box<CString>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html

error: getting a pointer from a temporary `Box<[u8]>` will result in a dangling pointer
--> $DIR/types.rs:28:28
|
LL | declval::<Box<[u8]>>().as_ptr();
| ---------------------- ^^^^^^ this pointer will immediately be invalid
| |
| this `Box<[u8]>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `Box<[u8]>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html

error: getting a pointer from a temporary `Box<str>` will result in a dangling pointer
--> $DIR/types.rs:30:27
|
LL | declval::<Box<str>>().as_ptr();
| --------------------- ^^^^^^ this pointer will immediately be invalid
| |
| this `Box<str>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `Box<str>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html

error: getting a pointer from a temporary `Box<CStr>` will result in a dangling pointer
--> $DIR/types.rs:32:28
|
LL | declval::<Box<CStr>>().as_ptr();
| ---------------------- ^^^^^^ this pointer will immediately be invalid
| |
| this `Box<CStr>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `Box<CStr>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html

error: getting a pointer from a temporary `[u8; 10]` will result in a dangling pointer
--> $DIR/types.rs:34:27
|
LL | declval::<[u8; 10]>().as_ptr();
| --------------------- ^^^^^^ this pointer will immediately be invalid
| |
| this `[u8; 10]` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `[u8; 10]` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html

error: getting a pointer from a temporary `Box<[u8; 10]>` will result in a dangling pointer
--> $DIR/types.rs:36:32
|
LL | declval::<Box<[u8; 10]>>().as_ptr();
| -------------------------- ^^^^^^ this pointer will immediately be invalid
| |
| this `Box<[u8; 10]>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `Box<[u8; 10]>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html

error: getting a pointer from a temporary `Box<Vec<u8>>` will result in a dangling pointer
--> $DIR/types.rs:38:31
|
LL | declval::<Box<Vec<u8>>>().as_ptr();
| ------------------------- ^^^^^^ this pointer will immediately be invalid
| |
| this `Box<Vec<u8>>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `Box<Vec<u8>>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html

error: getting a pointer from a temporary `Box<String>` will result in a dangling pointer
--> $DIR/types.rs:40:30
|
LL | declval::<Box<String>>().as_ptr();
| ------------------------ ^^^^^^ this pointer will immediately be invalid
| |
| this `Box<String>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `Box<String>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html

error: getting a pointer from a temporary `Box<Box<Box<Box<[u8]>>>>` will result in a dangling pointer
--> $DIR/types.rs:42:43
|
LL | declval::<Box<Box<Box<Box<[u8]>>>>>().as_ptr();
| ------------------------------------- ^^^^^^ this pointer will immediately be invalid
| |
| this `Box<Box<Box<Box<[u8]>>>>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `Box<Box<Box<Box<[u8]>>>>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html

error: getting a pointer from a temporary `Cell<u8>` will result in a dangling pointer
--> $DIR/types.rs:44:27
|
LL | declval::<Cell<u8>>().as_ptr();
| --------------------- ^^^^^^ this pointer will immediately be invalid
| |
| this `Cell<u8>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `Cell<u8>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html

error: getting a pointer from a temporary `MaybeUninit<u8>` will result in a dangling pointer
--> $DIR/types.rs:46:34
|
LL | declval::<MaybeUninit<u8>>().as_ptr();
| ---------------------------- ^^^^^^ this pointer will immediately be invalid
| |
| this `MaybeUninit<u8>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `MaybeUninit<u8>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html

error: getting a pointer from a temporary `Vec<AsPtrFake>` will result in a dangling pointer
--> $DIR/types.rs:48:33
|
LL | declval::<Vec<AsPtrFake>>().as_ptr();
| --------------------------- ^^^^^^ this pointer will immediately be invalid
| |
| this `Vec<AsPtrFake>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: pointers do not have a lifetime; when calling `as_ptr` the `Vec<AsPtrFake>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html

error: aborting due to 15 previous errors

0 comments on commit 217814b

Please sign in to comment.