Skip to content

Commit a599cfa

Browse files
committed
This adds a new lint with level Warn to check for code like:
```rust fn foo() -> *const i32 { let x = 42; &x } ``` and produce a warning like: ```text error: returning a pointer to stack memory associated with a local variable --> <source>:12:5 | LL| &x | ^^ ``` Disable the lint for another test
1 parent 7f69523 commit a599cfa

9 files changed

+260
-8
lines changed

compiler/rustc_lint/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ lint_builtin_overridden_symbol_name =
138138
lint_builtin_overridden_symbol_section =
139139
the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them
140140
141+
lint_builtin_returning_pointers_to_local_variables = returning a pointer to stack memory associated with a local variable
142+
141143
lint_builtin_special_module_name_used_lib = found module declaration for lib.rs
142144
.note = lib.rs is the root of this crate's library target
143145
.help = to refer to it from other targets, use the library's name as the path

compiler/rustc_lint/src/builtin.rs

+157-4
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,10 @@ use crate::lints::{
5555
BuiltinIncompleteFeatures, BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures,
5656
BuiltinKeywordIdents, BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc,
5757
BuiltinMutablesTransmutes, BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns,
58-
BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasBounds,
59-
BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub,
60-
BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment,
61-
BuiltinUnusedDocCommentSub, BuiltinWhileTrue, InvalidAsmLabel,
58+
BuiltinReturningPointersToLocalVariables, BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds,
59+
BuiltinTypeAliasBounds, BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit,
60+
BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures,
61+
BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub, BuiltinWhileTrue, InvalidAsmLabel,
6262
};
6363
use crate::nonstandard_style::{MethodLateContext, method_context};
6464
use crate::{
@@ -3063,6 +3063,159 @@ impl<'tcx> LateLintPass<'tcx> for AsmLabels {
30633063
}
30643064
}
30653065

3066+
declare_lint! {
3067+
/// The `returning_pointers_to_local_variables` lint detects when pointer
3068+
/// to stack memory associated with a local variable is returned. That
3069+
/// pointer is immediately dangling.
3070+
///
3071+
/// ### Example
3072+
///
3073+
/// ```rust,no_run
3074+
/// fn foo() -> *const i32 {
3075+
/// let x = 42;
3076+
/// &x
3077+
/// }
3078+
/// ```
3079+
///
3080+
/// {{produces}}
3081+
///
3082+
/// ### Explanation
3083+
///
3084+
/// Returning a pointer to memory refering to a local variable will always
3085+
/// end up in a dangling pointer after returning.
3086+
pub RETURNING_POINTERS_TO_LOCAL_VARIABLES,
3087+
Warn,
3088+
"returning a pointer to stack memory associated with a local variable",
3089+
}
3090+
3091+
declare_lint_pass!(ReturningPointersToLocalVariables => [RETURNING_POINTERS_TO_LOCAL_VARIABLES]);
3092+
3093+
impl<'tcx> LateLintPass<'tcx> for ReturningPointersToLocalVariables {
3094+
fn check_fn(
3095+
&mut self,
3096+
cx: &LateContext<'tcx>,
3097+
_: HirFnKind<'tcx>,
3098+
fn_decl: &'tcx FnDecl<'tcx>,
3099+
body: &'tcx Body<'tcx>,
3100+
_: Span,
3101+
_: LocalDefId,
3102+
) {
3103+
let hir::FnRetTy::Return(&hir::Ty { kind: hir::TyKind::Ptr(ptr_ty), .. }) = fn_decl.output
3104+
else {
3105+
return;
3106+
};
3107+
if matches!(ptr_ty.ty.kind, hir::TyKind::Tup([])) {
3108+
return;
3109+
}
3110+
3111+
// Check the block of the function that we're looking at.
3112+
if let Some(block) = Self::get_enclosing_block(cx, body.value.hir_id) {
3113+
match block {
3114+
&hir::Block {
3115+
stmts:
3116+
&[
3117+
..,
3118+
hir::Stmt {
3119+
kind:
3120+
hir::StmtKind::Semi(&hir::Expr {
3121+
kind: hir::ExprKind::Ret(Some(return_expr)),
3122+
..
3123+
}),
3124+
..
3125+
},
3126+
],
3127+
..
3128+
} => {
3129+
Self::maybe_lint_return_expr(cx, return_expr, fn_decl.inputs);
3130+
}
3131+
hir::Block { expr: Some(return_expr), .. } => {
3132+
Self::maybe_lint_return_expr(cx, return_expr, fn_decl.inputs);
3133+
}
3134+
_ => return,
3135+
}
3136+
}
3137+
}
3138+
}
3139+
3140+
impl ReturningPointersToLocalVariables {
3141+
/// Evaluates the return expression of a function and emits a lint if it
3142+
/// returns a pointer to a local variable.
3143+
fn maybe_lint_return_expr<'tcx>(
3144+
cx: &LateContext<'tcx>,
3145+
return_expr: &hir::Expr<'tcx>,
3146+
params: &'tcx [hir::Ty<'tcx>],
3147+
) {
3148+
// Early exit if we see that this is a pointer to an input parameter.
3149+
if Self::expr_is_param(cx.typeck_results(), return_expr, params) {
3150+
return;
3151+
}
3152+
3153+
match return_expr {
3154+
hir::Expr { kind: hir::ExprKind::AddrOf(_, _, addr_expr), .. } => {
3155+
Self::maybe_lint_return_expr(cx, addr_expr, params)
3156+
}
3157+
hir::Expr {
3158+
kind:
3159+
hir::ExprKind::Cast(
3160+
hir::Expr { kind: hir::ExprKind::AddrOf(_, _, addr_expr), .. },
3161+
_,
3162+
),
3163+
..
3164+
} => Self::maybe_lint_return_expr(cx, addr_expr, params),
3165+
hir::Expr { kind: hir::ExprKind::Cast(expr, _), .. } => {
3166+
Self::maybe_lint_return_expr(cx, expr, params)
3167+
}
3168+
hir::Expr {
3169+
kind:
3170+
hir::ExprKind::Path(
3171+
hir::QPath::Resolved(_, hir::Path { res: hir::def::Res::Local(_), .. }),
3172+
..,
3173+
),
3174+
..
3175+
} => cx.emit_span_lint(
3176+
RETURNING_POINTERS_TO_LOCAL_VARIABLES,
3177+
return_expr.span,
3178+
BuiltinReturningPointersToLocalVariables,
3179+
),
3180+
_ => (),
3181+
}
3182+
}
3183+
3184+
fn expr_is_param<'tcx>(
3185+
typeck_results: &ty::TypeckResults<'tcx>,
3186+
expr: &hir::Expr<'tcx>,
3187+
params: &'tcx [hir::Ty<'tcx>],
3188+
) -> bool {
3189+
params
3190+
.iter()
3191+
.map(|param| typeck_results.type_dependent_def_id(param.hir_id))
3192+
.collect::<Vec<_>>()
3193+
.contains(&typeck_results.type_dependent_def_id(expr.hir_id))
3194+
}
3195+
3196+
/// Returns the enclosing block for a [hir::HirId], if available.
3197+
fn get_enclosing_block<'tcx>(
3198+
cx: &LateContext<'tcx>,
3199+
hir_id: hir::HirId,
3200+
) -> Option<&'tcx hir::Block<'tcx>> {
3201+
let enclosing_node = cx
3202+
.tcx
3203+
.hir_get_enclosing_scope(hir_id)
3204+
.map(|enclosing_id| cx.tcx.hir_node(enclosing_id));
3205+
enclosing_node.and_then(|node| match node {
3206+
hir::Node::Block(block) => Some(block),
3207+
hir::Node::Item(&hir::Item { kind: hir::ItemKind::Fn { body: eid, .. }, .. })
3208+
| hir::Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, eid), .. }) => {
3209+
match cx.tcx.hir_body(eid).value.kind {
3210+
hir::ExprKind::Block(block, _) => Some(block),
3211+
_ => None,
3212+
}
3213+
}
3214+
_ => None,
3215+
})
3216+
}
3217+
}
3218+
30663219
declare_lint! {
30673220
/// The `special_module_name` lint detects module
30683221
/// declarations for files that have a special meaning.

compiler/rustc_lint/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ late_lint_methods!(
243243
IfLetRescope: IfLetRescope::default(),
244244
StaticMutRefs: StaticMutRefs,
245245
UnqualifiedLocalImports: UnqualifiedLocalImports,
246+
ReturningPointersToLocalVariables : ReturningPointersToLocalVariables,
246247
]
247248
]
248249
);

compiler/rustc_lint/src/lints.rs

+4
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,10 @@ pub(crate) enum BuiltinSpecialModuleNameUsed {
529529
Main,
530530
}
531531

532+
#[derive(LintDiagnostic)]
533+
#[diag(lint_builtin_returning_pointers_to_local_variables)]
534+
pub(crate) struct BuiltinReturningPointersToLocalVariables;
535+
532536
// deref_into_dyn_supertrait.rs
533537
#[derive(LintDiagnostic)]
534538
#[diag(lint_supertrait_as_deref_target)]

src/tools/miri/tests/fail/validity/dangling_ref3.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Make sure we catch this even without Stacked Borrows
22
//@compile-flags: -Zmiri-disable-stacked-borrows
3+
#![allow(returning_pointers_to_local_variables)]
34
use std::mem;
45

56
fn dangling() -> *const u8 {

tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// Regression test for #114484: This used to ICE during monomorphization, because we treated
55
// `<VirtualWrapper<...> as Pointee>::Metadata` as a rigid projection after reaching the recursion
66
// limit when finding the struct tail.
7+
#![allow(returning_pointers_to_local_variables)]
78

89
use std::marker::PhantomData;
910

tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ error: reached the recursion limit finding the struct tail for `[u8; 256]`
1818
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
1919

2020
note: the above error was encountered while instantiating `fn virtualize_my_trait::<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<SomeData<256>, 0>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>>`
21-
--> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:24:18
21+
--> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:25:18
2222
|
2323
LL | unsafe { virtualize_my_trait(L, self) }
2424
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -43,7 +43,7 @@ error: reached the recursion limit finding the struct tail for `SomeData<256>`
4343
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
4444

4545
note: the above error was encountered while instantiating `fn virtualize_my_trait::<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<SomeData<256>, 0>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>>`
46-
--> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:24:18
46+
--> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:25:18
4747
|
4848
LL | unsafe { virtualize_my_trait(L, self) }
4949
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -68,15 +68,15 @@ error: reached the recursion limit finding the struct tail for `VirtualWrapper<S
6868
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
6969

7070
note: the above error was encountered while instantiating `fn virtualize_my_trait::<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<SomeData<256>, 0>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>>`
71-
--> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:24:18
71+
--> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:25:18
7272
|
7373
LL | unsafe { virtualize_my_trait(L, self) }
7474
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7575

7676
error: reached the recursion limit while instantiating `<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<..., 1>, 1>, 1>, 1>, 1> as MyTrait>::virtualize`
7777
|
7878
note: `<VirtualWrapper<T, L> as MyTrait>::virtualize` defined here
79-
--> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:23:5
79+
--> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:24:5
8080
|
8181
LL | fn virtualize(&self) -> &dyn MyTrait {
8282
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//@ check-pass
2+
3+
#![warn(returning_pointers_to_local_variables)]
4+
5+
fn foo() -> *const u32 {
6+
let empty = 42u32;
7+
return &empty as *const _;
8+
//~^ WARN returning a pointer to stack memory associated with a local variable
9+
}
10+
11+
fn bar() -> *const u32 {
12+
let empty = 42u32;
13+
&empty as *const _
14+
//~^ WARN returning a pointer to stack memory associated with a local variable
15+
}
16+
17+
fn baz() -> *const u32 {
18+
let empty = 42u32;
19+
return &empty;
20+
//~^ WARN returning a pointer to stack memory associated with a local variable
21+
}
22+
23+
fn faa() -> *const u32 {
24+
let empty = 42u32;
25+
&empty
26+
//~^ WARN returning a pointer to stack memory associated with a local variable
27+
}
28+
29+
fn pointer_to_pointer() -> *const *mut u32 {
30+
let mut empty = 42u32;
31+
&(&mut empty as *mut u32) as *const _
32+
//~^ WARN returning a pointer to stack memory associated with a local variable
33+
}
34+
35+
fn dont_lint_unit() -> *const () {
36+
let foo = ();
37+
&foo as *const _
38+
}
39+
40+
fn dont_lint_param(val: u32) -> *const u32 {
41+
&val
42+
}
43+
44+
struct Foo {}
45+
46+
impl Foo {
47+
fn dont_lint_self_param(&self) -> *const Foo {
48+
self
49+
}
50+
}
51+
52+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
warning: returning a pointer to stack memory associated with a local variable
2+
--> $DIR/lint-returning-pointers-to-local-variables.rs:7:13
3+
|
4+
LL | return &empty as *const _;
5+
| ^^^^^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/lint-returning-pointers-to-local-variables.rs:3:9
9+
|
10+
LL | #![warn(returning_pointers_to_local_variables)]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
warning: returning a pointer to stack memory associated with a local variable
14+
--> $DIR/lint-returning-pointers-to-local-variables.rs:13:6
15+
|
16+
LL | &empty as *const _
17+
| ^^^^^
18+
19+
warning: returning a pointer to stack memory associated with a local variable
20+
--> $DIR/lint-returning-pointers-to-local-variables.rs:19:13
21+
|
22+
LL | return &empty;
23+
| ^^^^^
24+
25+
warning: returning a pointer to stack memory associated with a local variable
26+
--> $DIR/lint-returning-pointers-to-local-variables.rs:25:6
27+
|
28+
LL | &empty
29+
| ^^^^^
30+
31+
warning: returning a pointer to stack memory associated with a local variable
32+
--> $DIR/lint-returning-pointers-to-local-variables.rs:31:12
33+
|
34+
LL | &(&mut empty as *mut u32) as *const _
35+
| ^^^^^
36+
37+
warning: 5 warnings emitted
38+

0 commit comments

Comments
 (0)