mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-29 20:46:07 +03:00
Revert "Rollup merge of #154074 - dianne:dbg-temp-scopes, r=Mark-Simulacrum"
This reverts commit2a18b885ce, reversing changes made tocd14b73b4a. (cherry picked from commitc9d9448c98)
This commit is contained in:
@@ -588,6 +588,8 @@ fn visit_pat(&mut self, p: &'hir hir::Pat<'hir>) {
|
||||
}
|
||||
|
||||
// for dbg!(x) which may take ownership, suggest dbg!(&x) instead
|
||||
// but here we actually do not check whether the macro name is `dbg!`
|
||||
// so that we may extend the scope a bit larger to cover more cases
|
||||
fn suggest_ref_for_dbg_args(
|
||||
&self,
|
||||
body: &hir::Expr<'_>,
|
||||
@@ -601,41 +603,29 @@ fn suggest_ref_for_dbg_args(
|
||||
});
|
||||
let Some(var_info) = var_info else { return };
|
||||
let arg_name = var_info.name;
|
||||
struct MatchArgFinder<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
move_span: Span,
|
||||
struct MatchArgFinder {
|
||||
expr_span: Span,
|
||||
match_arg_span: Option<Span>,
|
||||
arg_name: Symbol,
|
||||
match_arg_span: Option<Span> = None,
|
||||
}
|
||||
impl Visitor<'_> for MatchArgFinder<'_> {
|
||||
impl Visitor<'_> for MatchArgFinder {
|
||||
fn visit_expr(&mut self, e: &hir::Expr<'_>) {
|
||||
// dbg! is expanded into a match pattern, we need to find the right argument span
|
||||
if let hir::ExprKind::Match(scrutinee, ..) = &e.kind
|
||||
&& let hir::ExprKind::Tup(args) = scrutinee.kind
|
||||
&& e.span.macro_backtrace().any(|expn| {
|
||||
expn.macro_def_id.is_some_and(|macro_def_id| {
|
||||
self.tcx.is_diagnostic_item(sym::dbg_macro, macro_def_id)
|
||||
})
|
||||
})
|
||||
if let hir::ExprKind::Match(expr, ..) = &e.kind
|
||||
&& let hir::ExprKind::Path(hir::QPath::Resolved(
|
||||
_,
|
||||
path @ Path { segments: [seg], .. },
|
||||
)) = &expr.kind
|
||||
&& seg.ident.name == self.arg_name
|
||||
&& self.expr_span.source_callsite().contains(expr.span)
|
||||
{
|
||||
for arg in args {
|
||||
if let hir::ExprKind::Path(hir::QPath::Resolved(
|
||||
_,
|
||||
path @ Path { segments: [seg], .. },
|
||||
)) = &arg.kind
|
||||
&& seg.ident.name == self.arg_name
|
||||
&& self.move_span.source_equal(arg.span)
|
||||
{
|
||||
self.match_arg_span = Some(path.span);
|
||||
return;
|
||||
}
|
||||
}
|
||||
self.match_arg_span = Some(path.span);
|
||||
}
|
||||
hir::intravisit::walk_expr(self, e);
|
||||
}
|
||||
}
|
||||
|
||||
let mut finder = MatchArgFinder { tcx: self.infcx.tcx, move_span, arg_name, .. };
|
||||
let mut finder = MatchArgFinder { expr_span: move_span, match_arg_span: None, arg_name };
|
||||
finder.visit_expr(body);
|
||||
if let Some(macro_arg_span) = finder.match_arg_span {
|
||||
err.span_suggestion_verbose(
|
||||
|
||||
@@ -748,7 +748,6 @@
|
||||
custom_mir,
|
||||
custom_test_frameworks,
|
||||
d32,
|
||||
dbg_macro,
|
||||
dead_code,
|
||||
dealloc,
|
||||
debug,
|
||||
|
||||
+39
-43
@@ -5,9 +5,6 @@
|
||||
//! library.
|
||||
// ignore-tidy-dbg
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
#[doc = include_str!("../../core/src/macros/panic.md")]
|
||||
#[macro_export]
|
||||
#[rustc_builtin_macro(std_panic)]
|
||||
@@ -362,16 +359,19 @@ macro_rules! dbg {
|
||||
};
|
||||
}
|
||||
|
||||
/// Internal macro that processes a list of expressions, binds their results
|
||||
/// with `match`, calls `eprint!` with the collected information, and returns
|
||||
/// all the evaluated expressions in a tuple.
|
||||
/// Internal macro that processes a list of expressions and produces a chain of
|
||||
/// nested `match`es, one for each expression, before finally calling `eprint!`
|
||||
/// with the collected information and returning all the evaluated expressions
|
||||
/// in a tuple.
|
||||
///
|
||||
/// E.g. `dbg_internal!(() () (1, 2))` expands into
|
||||
/// ```rust, ignore
|
||||
/// match (1, 2) {
|
||||
/// (tmp_1, tmp_2) => {
|
||||
/// eprint!("...", &tmp_1, &tmp_2, /* some other arguments */);
|
||||
/// (tmp_1, tmp_2)
|
||||
/// match 1 {
|
||||
/// tmp_1 => match 2 {
|
||||
/// tmp_2 => {
|
||||
/// eprint!("...", &tmp_1, &tmp_2, /* some other arguments */);
|
||||
/// (tmp_1, tmp_2)
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
@@ -380,43 +380,39 @@ macro_rules! dbg {
|
||||
#[doc(hidden)]
|
||||
#[rustc_macro_transparency = "semiopaque"]
|
||||
pub macro dbg_internal {
|
||||
(($($piece:literal),+) ($($processed:expr => $bound:ident),+) ()) => {
|
||||
(($($piece:literal),+) ($($processed:expr => $bound:expr),+) ()) => {{
|
||||
$crate::eprint!(
|
||||
$crate::concat!($($piece),+),
|
||||
$(
|
||||
$crate::stringify!($processed),
|
||||
// The `&T: Debug` check happens here (not in the format literal desugaring)
|
||||
// to avoid format literal related messages and suggestions.
|
||||
&&$bound as &dyn $crate::fmt::Debug
|
||||
),+,
|
||||
// The location returned here is that of the macro invocation, so
|
||||
// it will be the same for all expressions. Thus, label these
|
||||
// arguments so that they can be reused in every piece of the
|
||||
// formatting template.
|
||||
file=$crate::file!(),
|
||||
line=$crate::line!(),
|
||||
column=$crate::column!()
|
||||
);
|
||||
// Comma separate the variables only when necessary so that this will
|
||||
// not yield a tuple for a single expression, but rather just parenthesize
|
||||
// the expression.
|
||||
($($bound),+)
|
||||
}},
|
||||
(($($piece:literal),*) ($($processed:expr => $bound:expr),*) ($val:expr $(,$rest:expr)*)) => {
|
||||
// Use of `match` here is intentional because it affects the lifetimes
|
||||
// of temporaries - https://stackoverflow.com/a/48732525/1063961
|
||||
// Always put the arguments in a tuple to avoid an unused parens lint on the pattern.
|
||||
match ($($processed,)+) {
|
||||
($($bound,)+) => {
|
||||
$crate::eprint!(
|
||||
$crate::concat!($($piece),+),
|
||||
$(
|
||||
$crate::stringify!($processed),
|
||||
// The `&T: Debug` check happens here (not in the format literal desugaring)
|
||||
// to avoid format literal related messages and suggestions.
|
||||
&&$bound as &dyn $crate::fmt::Debug
|
||||
),+,
|
||||
// The location returned here is that of the macro invocation, so
|
||||
// it will be the same for all expressions. Thus, label these
|
||||
// arguments so that they can be reused in every piece of the
|
||||
// formatting template.
|
||||
file=$crate::file!(),
|
||||
line=$crate::line!(),
|
||||
column=$crate::column!()
|
||||
);
|
||||
// Comma separate the variables only when necessary so that this will
|
||||
// not yield a tuple for a single expression, but rather just parenthesize
|
||||
// the expression.
|
||||
($($bound),+)
|
||||
|
||||
}
|
||||
match $val {
|
||||
tmp => $crate::macros::dbg_internal!(
|
||||
($($piece,)* "[{file}:{line}:{column}] {} = {:#?}\n")
|
||||
($($processed => $bound,)* $val => tmp)
|
||||
($($rest),*)
|
||||
),
|
||||
}
|
||||
},
|
||||
(($($piece:literal),*) ($($processed:expr => $bound:ident),*) ($val:expr $(,$rest:expr)*)) => {
|
||||
$crate::macros::dbg_internal!(
|
||||
($($piece,)* "[{file}:{line}:{column}] {} = {:#?}\n")
|
||||
($($processed => $bound,)* $val => tmp)
|
||||
($($rest),*)
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
// ignore-tidy-dbg
|
||||
|
||||
/// Test for <https://github.com/rust-lang/rust/issues/153850>:
|
||||
/// `dbg!` shouldn't drop arguments' temporaries.
|
||||
#[test]
|
||||
fn no_dropping_temps() {
|
||||
fn temp() {}
|
||||
|
||||
*dbg!(&temp());
|
||||
*dbg!(&temp(), 1).0;
|
||||
*dbg!(0, &temp()).1;
|
||||
*dbg!(0, &temp(), 2).1;
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
use clippy_utils::{is_in_test, sym};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Closure, ClosureKind, CoroutineKind, Expr, ExprKind, LetStmt, LocalSource, Node, Stmt, StmtKind};
|
||||
use rustc_hir::{Arm, Closure, ClosureKind, CoroutineKind, Expr, ExprKind, LetStmt, LocalSource, Node, Stmt, StmtKind};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::{Span, SyntaxContext};
|
||||
@@ -92,15 +92,16 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
(macro_call.span, String::from("()"))
|
||||
}
|
||||
},
|
||||
ExprKind::Match(args, _, _) => {
|
||||
let suggestion = match args.kind {
|
||||
ExprKind::Match(first, arms, _) => {
|
||||
let vals = collect_vals(first, arms);
|
||||
let suggestion = match *vals.as_slice() {
|
||||
// dbg!(1) => 1
|
||||
ExprKind::Tup([val]) => {
|
||||
[val] => {
|
||||
snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability)
|
||||
.to_string()
|
||||
},
|
||||
// dbg!(2, 3) => (2, 3)
|
||||
ExprKind::Tup([first, .., last]) => {
|
||||
[first, .., last] => {
|
||||
let snippet = snippet_with_applicability(
|
||||
cx,
|
||||
first.span.source_callsite().to(last.span.source_callsite()),
|
||||
@@ -164,3 +165,39 @@ fn is_async_move_desugar<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx
|
||||
fn first_dbg_macro_in_expansion(cx: &LateContext<'_>, span: Span) -> Option<MacroCall> {
|
||||
macro_backtrace(span).find(|mc| cx.tcx.is_diagnostic_item(sym::dbg_macro, mc.def_id))
|
||||
}
|
||||
|
||||
/// Extracts all value expressions from the `match`-tree generated by `dbg!`.
|
||||
///
|
||||
/// E.g. from
|
||||
/// ```rust, ignore
|
||||
/// match 1 {
|
||||
/// tmp_1 => match 2 {
|
||||
/// tmp_2 => {
|
||||
/// /* printing */
|
||||
/// (tmp_1, tmp_2)
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
/// this extracts `1` and `2`.
|
||||
fn collect_vals<'hir>(first: &'hir Expr<'hir>, mut arms: &'hir [Arm<'hir>]) -> Vec<&'hir Expr<'hir>> {
|
||||
let mut vals = vec![first];
|
||||
loop {
|
||||
let [arm] = arms else {
|
||||
unreachable!("dbg! macro expansion only has single-arm matches")
|
||||
};
|
||||
|
||||
match is_async_move_desugar(arm.body)
|
||||
.unwrap_or(arm.body)
|
||||
.peel_drop_temps()
|
||||
.kind
|
||||
{
|
||||
ExprKind::Block(..) => return vals,
|
||||
ExprKind::Match(val, a, _) => {
|
||||
vals.push(val);
|
||||
arms = a;
|
||||
},
|
||||
_ => unreachable!("dbg! macro expansion only results in block or match expressions"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,6 +201,7 @@ macro_rules! generate {
|
||||
cx,
|
||||
cycle,
|
||||
cyclomatic_complexity,
|
||||
dbg_macro,
|
||||
de,
|
||||
debug_struct,
|
||||
deprecated_in_future,
|
||||
|
||||
@@ -2,7 +2,7 @@ error: Undefined Behavior: memory access failed: ALLOC has been freed, so this p
|
||||
--> tests/fail/dangling_pointers/dangling_primitive.rs:LL:CC
|
||||
|
|
||||
LL | dbg!(*ptr);
|
||||
| ^^^^ Undefined Behavior occurred here
|
||||
| ^^^^^^^^^^ Undefined Behavior occurred here
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
||||
@@ -7,7 +7,7 @@ error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is unin
|
||||
--> tests/fail/function_calls/return_pointer_on_unwind.rs:LL:CC
|
||||
|
|
||||
LL | dbg!(x.0);
|
||||
| ^^^ Undefined Behavior occurred here
|
||||
| ^^^^^^^^^ Undefined Behavior occurred here
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
||||
@@ -1,44 +1,67 @@
|
||||
//! Diagnostic test for <https://github.com/rust-lang/rust/issues/120327>: suggest borrowing
|
||||
//! variables passed to `dbg!` that are later used.
|
||||
//@ dont-require-annotations: HELP
|
||||
|
||||
fn s() -> String {
|
||||
let a = String::new();
|
||||
dbg!(a); //~ HELP consider borrowing instead of transferring ownership
|
||||
dbg!(a);
|
||||
return a; //~ ERROR use of moved value:
|
||||
}
|
||||
|
||||
fn m() -> String {
|
||||
let a = String::new();
|
||||
dbg!(1, 2, a, 1, 2); //~ HELP consider borrowing instead of transferring ownership
|
||||
dbg!(1, 2, a, 1, 2);
|
||||
return a; //~ ERROR use of moved value:
|
||||
}
|
||||
|
||||
fn t(a: String) -> String {
|
||||
let b: String = "".to_string();
|
||||
dbg!(a, b); //~ HELP consider borrowing instead of transferring ownership
|
||||
dbg!(a, b);
|
||||
return b; //~ ERROR use of moved value:
|
||||
}
|
||||
|
||||
fn x(a: String) -> String {
|
||||
let b: String = "".to_string();
|
||||
dbg!(a, b); //~ HELP consider borrowing instead of transferring ownership
|
||||
dbg!(a, b);
|
||||
return a; //~ ERROR use of moved value:
|
||||
}
|
||||
|
||||
fn two_of_them(a: String) -> String {
|
||||
dbg!(a, a); //~ ERROR use of moved value
|
||||
//~| HELP consider borrowing instead of transferring ownership
|
||||
//~| HELP consider borrowing instead of transferring ownership
|
||||
return a; //~ ERROR use of moved value
|
||||
macro_rules! my_dbg {
|
||||
() => {
|
||||
eprintln!("[{}:{}:{}]", file!(), line!(), column!())
|
||||
};
|
||||
($val:expr $(,)?) => {
|
||||
match $val {
|
||||
tmp => {
|
||||
eprintln!("[{}:{}:{}] {} = {:#?}",
|
||||
file!(), line!(), column!(), stringify!($val), &tmp);
|
||||
tmp
|
||||
}
|
||||
}
|
||||
};
|
||||
($($val:expr),+ $(,)?) => {
|
||||
($(my_dbg!($val)),+,)
|
||||
};
|
||||
}
|
||||
|
||||
fn test_my_dbg() -> String {
|
||||
let b: String = "".to_string();
|
||||
my_dbg!(b, 1);
|
||||
return b; //~ ERROR use of moved value:
|
||||
}
|
||||
|
||||
fn test_not_macro() -> String {
|
||||
let a = String::new();
|
||||
let _b = match a {
|
||||
tmp => {
|
||||
eprintln!("dbg: {}", tmp);
|
||||
tmp
|
||||
}
|
||||
};
|
||||
return a; //~ ERROR use of moved value:
|
||||
}
|
||||
|
||||
fn get_expr(_s: String) {}
|
||||
|
||||
// The suggestion is purely syntactic; applying it here will result in a type error.
|
||||
fn test() {
|
||||
let a: String = "".to_string();
|
||||
let _res = get_expr(dbg!(a)); //~ HELP consider borrowing instead of transferring ownership
|
||||
let _res = get_expr(dbg!(a));
|
||||
let _l = a.len(); //~ ERROR borrow of moved value
|
||||
}
|
||||
|
||||
|
||||
@@ -1,133 +1,112 @@
|
||||
error[E0382]: use of moved value: `a`
|
||||
--> $DIR/dbg-issue-120327.rs:8:12
|
||||
--> $DIR/dbg-issue-120327.rs:4:12
|
||||
|
|
||||
LL | let a = String::new();
|
||||
| - move occurs because `a` has type `String`, which does not implement the `Copy` trait
|
||||
LL | dbg!(a);
|
||||
| - value moved here
|
||||
| ------- value moved here
|
||||
LL | return a;
|
||||
| ^ value used here after move
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | dbg!(a.clone());
|
||||
| ++++++++
|
||||
help: consider borrowing instead of transferring ownership
|
||||
|
|
||||
LL | dbg!(&a);
|
||||
| +
|
||||
|
||||
error[E0382]: use of moved value: `a`
|
||||
--> $DIR/dbg-issue-120327.rs:14:12
|
||||
--> $DIR/dbg-issue-120327.rs:10:12
|
||||
|
|
||||
LL | let a = String::new();
|
||||
| - move occurs because `a` has type `String`, which does not implement the `Copy` trait
|
||||
LL | dbg!(1, 2, a, 1, 2);
|
||||
| - value moved here
|
||||
| ------------------- value moved here
|
||||
LL | return a;
|
||||
| ^ value used here after move
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | dbg!(1, 2, a.clone(), 1, 2);
|
||||
| ++++++++
|
||||
help: consider borrowing instead of transferring ownership
|
||||
|
|
||||
LL | dbg!(1, 2, &a, 1, 2);
|
||||
| +
|
||||
|
||||
error[E0382]: use of moved value: `b`
|
||||
--> $DIR/dbg-issue-120327.rs:20:12
|
||||
--> $DIR/dbg-issue-120327.rs:16:12
|
||||
|
|
||||
LL | let b: String = "".to_string();
|
||||
| - move occurs because `b` has type `String`, which does not implement the `Copy` trait
|
||||
LL | dbg!(a, b);
|
||||
| - value moved here
|
||||
| ---------- value moved here
|
||||
LL | return b;
|
||||
| ^ value used here after move
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | dbg!(a, b.clone());
|
||||
| ++++++++
|
||||
help: consider borrowing instead of transferring ownership
|
||||
|
|
||||
LL | dbg!(a, &b);
|
||||
| +
|
||||
|
||||
error[E0382]: use of moved value: `a`
|
||||
--> $DIR/dbg-issue-120327.rs:26:12
|
||||
--> $DIR/dbg-issue-120327.rs:22:12
|
||||
|
|
||||
LL | fn x(a: String) -> String {
|
||||
| - move occurs because `a` has type `String`, which does not implement the `Copy` trait
|
||||
LL | let b: String = "".to_string();
|
||||
LL | dbg!(a, b);
|
||||
| - value moved here
|
||||
| ---------- value moved here
|
||||
LL | return a;
|
||||
| ^ value used here after move
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | dbg!(a.clone(), b);
|
||||
| ++++++++
|
||||
help: consider borrowing instead of transferring ownership
|
||||
|
|
||||
LL | dbg!(&a, b);
|
||||
| +
|
||||
|
||||
error[E0382]: use of moved value: `a`
|
||||
--> $DIR/dbg-issue-120327.rs:30:13
|
||||
error[E0382]: use of moved value: `b`
|
||||
--> $DIR/dbg-issue-120327.rs:46:12
|
||||
|
|
||||
LL | fn two_of_them(a: String) -> String {
|
||||
| - move occurs because `a` has type `String`, which does not implement the `Copy` trait
|
||||
LL | dbg!(a, a);
|
||||
| - ^ value used here after move
|
||||
| |
|
||||
| value moved here
|
||||
LL | tmp => {
|
||||
| --- value moved here
|
||||
...
|
||||
LL | let b: String = "".to_string();
|
||||
| - move occurs because `b` has type `String`, which does not implement the `Copy` trait
|
||||
LL | my_dbg!(b, 1);
|
||||
LL | return b;
|
||||
| ^ value used here after move
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | dbg!(a.clone(), a);
|
||||
| ++++++++
|
||||
help: consider borrowing instead of transferring ownership
|
||||
|
|
||||
LL | dbg!(&a, a);
|
||||
| +
|
||||
LL | my_dbg!(&b, 1);
|
||||
| +
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | ref tmp => {
|
||||
| +++
|
||||
|
||||
error[E0382]: use of moved value: `a`
|
||||
--> $DIR/dbg-issue-120327.rs:33:12
|
||||
--> $DIR/dbg-issue-120327.rs:57:12
|
||||
|
|
||||
LL | fn two_of_them(a: String) -> String {
|
||||
| - move occurs because `a` has type `String`, which does not implement the `Copy` trait
|
||||
LL | dbg!(a, a);
|
||||
| - value moved here
|
||||
LL | let a = String::new();
|
||||
| - move occurs because `a` has type `String`, which does not implement the `Copy` trait
|
||||
LL | let _b = match a {
|
||||
LL | tmp => {
|
||||
| --- value moved here
|
||||
...
|
||||
LL | return a;
|
||||
| ^ value used here after move
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | dbg!(a, a.clone());
|
||||
| ++++++++
|
||||
help: consider borrowing instead of transferring ownership
|
||||
|
|
||||
LL | dbg!(a, &a);
|
||||
| +
|
||||
LL | ref tmp => {
|
||||
| +++
|
||||
|
||||
error[E0382]: borrow of moved value: `a`
|
||||
--> $DIR/dbg-issue-120327.rs:42:14
|
||||
--> $DIR/dbg-issue-120327.rs:65:14
|
||||
|
|
||||
LL | let a: String = "".to_string();
|
||||
| - move occurs because `a` has type `String`, which does not implement the `Copy` trait
|
||||
LL | let _res = get_expr(dbg!(a));
|
||||
| - value moved here
|
||||
| ------- value moved here
|
||||
LL | let _l = a.len();
|
||||
| ^ value borrowed here after move
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let _res = get_expr(dbg!(a.clone()));
|
||||
| ++++++++
|
||||
help: consider borrowing instead of transferring ownership
|
||||
|
|
||||
LL | let _res = get_expr(dbg!(&a));
|
||||
|
||||
@@ -98,7 +98,7 @@ pub fn g<T: Default>(mut v: T) {
|
||||
}
|
||||
|
||||
pub fn h<T: Copy + Default + std::fmt::Debug>() {
|
||||
let mut z = T::default(); //~ WARN unused variable: `z`
|
||||
let mut z = T::default();
|
||||
let _ = move |b| {
|
||||
loop {
|
||||
if b {
|
||||
|
||||
@@ -157,14 +157,6 @@ LL | z = T::default();
|
||||
|
|
||||
= help: maybe it is overwritten before being read?
|
||||
|
||||
warning: unused variable: `z`
|
||||
--> $DIR/liveness-upvars.rs:101:9
|
||||
|
|
||||
LL | let mut z = T::default();
|
||||
| ^^^^^ help: if this is intentional, prefix it with an underscore: `_z`
|
||||
|
|
||||
= note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
|
||||
|
||||
warning: value captured by `state` is never read
|
||||
--> $DIR/liveness-upvars.rs:131:9
|
||||
|
|
||||
@@ -206,5 +198,5 @@ LL | s = yield ();
|
||||
LL | s = 3;
|
||||
| ----- `s` is overwritten here before the previous value is read
|
||||
|
||||
warning: 25 warnings emitted
|
||||
warning: 24 warnings emitted
|
||||
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
error[E0382]: use of moved value: `a`
|
||||
--> $DIR/dbg-macro-move-semantics.rs:9:18
|
||||
--> $DIR/dbg-macro-move-semantics.rs:9:13
|
||||
|
|
||||
LL | let a = NoCopy(0);
|
||||
| - move occurs because `a` has type `NoCopy`, which does not implement the `Copy` trait
|
||||
LL | let _ = dbg!(a);
|
||||
| - value moved here
|
||||
| ------- value moved here
|
||||
LL | let _ = dbg!(a);
|
||||
| ^ value used here after move
|
||||
| ^^^^^^^ value used here after move
|
||||
|
|
||||
note: if `NoCopy` implemented `Clone`, you could clone the value
|
||||
--> $DIR/dbg-macro-move-semantics.rs:4:1
|
||||
|
|
||||
LL | struct NoCopy(usize);
|
||||
| ^^^^^^^^^^^^^ consider implementing `Clone` for this type
|
||||
...
|
||||
LL | let _ = dbg!(a);
|
||||
| - you could clone this value
|
||||
help: consider borrowing instead of transferring ownership
|
||||
|
|
||||
LL | let _ = dbg!(&a);
|
||||
|
||||
Reference in New Issue
Block a user