rust/tests/ui/escape_analysis.rs

185 lines
3.1 KiB
Rust
Raw Normal View History

#![feature(box_syntax)]
2019-09-16 17:50:36 +02:00
#![allow(
clippy::borrowed_box,
clippy::needless_pass_by_value,
clippy::unused_unit,
clippy::redundant_clone,
2020-01-26 17:03:39 +01:00
clippy::match_single_binding
2019-09-16 17:50:36 +02:00
)]
#![warn(clippy::boxed_local)]
2015-12-04 11:12:53 +01:00
#[derive(Clone)]
struct A;
impl A {
2018-12-09 23:26:16 +01:00
fn foo(&self) {}
2015-12-04 11:12:53 +01:00
}
2016-02-01 20:37:07 +01:00
trait Z {
fn bar(&self);
}
impl Z for A {
fn bar(&self) {
//nothing
}
}
2018-12-09 23:26:16 +01:00
fn main() {}
2015-12-04 11:12:53 +01:00
fn ok_box_trait(boxed_trait: &Box<dyn Z>) {
2016-02-01 20:37:07 +01:00
let boxed_local = boxed_trait;
// done
}
2015-12-04 11:12:53 +01:00
fn warn_call() {
2017-02-08 14:58:07 +01:00
let x = box A;
2016-09-09 20:24:00 +02:00
x.foo();
2015-12-04 11:12:53 +01:00
}
2017-02-08 14:58:07 +01:00
fn warn_arg(x: Box<A>) {
2015-12-28 15:12:57 +01:00
x.foo();
}
fn nowarn_closure_arg() {
let x = Some(box A);
x.map_or((), |x| take_ref(&x));
}
2015-12-04 11:12:53 +01:00
fn warn_rename_call() {
let x = box A;
2017-02-08 14:58:07 +01:00
let y = x;
2015-12-04 11:12:53 +01:00
y.foo(); // via autoderef
}
fn warn_notuse() {
2017-02-08 14:58:07 +01:00
let bz = box A;
2015-12-04 11:12:53 +01:00
}
fn warn_pass() {
2017-02-08 14:58:07 +01:00
let bz = box A;
2015-12-04 11:12:53 +01:00
take_ref(&bz); // via deref coercion
}
fn nowarn_return() -> Box<A> {
box A // moved out, "escapes"
2015-12-04 11:12:53 +01:00
}
fn nowarn_move() {
let bx = box A;
drop(bx) // moved in, "escapes"
}
fn nowarn_call() {
let bx = box A;
bx.clone(); // method only available to Box, not via autoderef
}
fn nowarn_pass() {
let bx = box A;
take_box(&bx); // fn needs &Box
}
fn take_box(x: &Box<A>) {}
fn take_ref(x: &A) {}
fn nowarn_ref_take() {
// false positive, should actually warn
2017-02-08 14:58:07 +01:00
let x = box A;
2015-12-04 11:12:53 +01:00
let y = &x;
take_box(y);
}
fn nowarn_match() {
let x = box A; // moved into a match
match x {
2018-12-09 23:26:16 +01:00
y => drop(y),
2015-12-04 11:12:53 +01:00
}
}
fn warn_match() {
2017-02-08 14:58:07 +01:00
let x = box A;
2018-12-09 23:26:16 +01:00
match &x {
// not moved
ref y => (),
2015-12-04 11:12:53 +01:00
}
2015-12-28 15:12:57 +01:00
}
2016-07-10 15:23:50 +02:00
fn nowarn_large_array() {
// should not warn, is large array
// and should not be on stack
let x = box [1; 10000];
2018-12-09 23:26:16 +01:00
match &x {
// not moved
ref y => (),
2016-07-10 15:23:50 +02:00
}
}
/// ICE regression test
pub trait Foo {
type Item;
}
impl<'a> Foo for &'a () {
type Item = ();
}
pub struct PeekableSeekable<I: Foo> {
_peeked: I::Item,
}
2018-12-09 23:26:16 +01:00
pub fn new(_needs_name: Box<PeekableSeekable<&()>>) -> () {}
/// Regression for #916, #1123
///
/// This shouldn't warn for `boxed_local`as the implementation of a trait
/// can't change much about the trait definition.
trait BoxedAction {
fn do_sth(self: Box<Self>);
}
impl BoxedAction for u64 {
fn do_sth(self: Box<Self>) {
println!("{}", *self)
}
}
/// Regression for #1478
///
/// This shouldn't warn for `boxed_local`as self itself is a box type.
trait MyTrait {
fn do_sth(self);
}
impl<T> MyTrait for Box<T> {
fn do_sth(self) {}
}
// Issue #3739 - capture in closures
mod issue_3739 {
use super::A;
fn consume<T>(_: T) {}
fn borrow<T>(_: &T) {}
fn closure_consume(x: Box<A>) {
let _ = move || {
consume(x);
};
}
fn closure_borrow(x: Box<A>) {
let _ = || {
borrow(&x);
};
}
}
/// Issue #5542
///
/// This shouldn't warn for `boxed_local` as it is intended to called from non-Rust code.
2020-10-08 14:06:19 +02:00
pub extern "C" fn do_not_warn_me(_c_pointer: Box<String>) -> () {}
#[rustfmt::skip] // Forces rustfmt to not add ABI
pub extern fn do_not_warn_me_no_abi(_c_pointer: Box<String>) -> () {}