Change:
https://crater- https://crater- https://crater- https://crater- https://crater- https://crater- is likely cause (cc
I'll fix this.
Fixed on beta with and on master. will be a more complete change and will likely land in 1.63 (or later).

Discussion:
#[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "write_macro")] macro_rules! write { <del> ($dst:expr, $($arg:tt)*) => { $dst.write_fmt($crate::format_args!($($arg)*)) }; </del> <ins> ($dst:expr, $($arg:tt)*) => {{ let result = $dst.write_fmt($crate::format_args!($($arg)*)); result }}; </ins> } /// Write formatted data into a buffer, with a newline appended.

($dst:expr $(,)?) => { $crate::write!($dst, "n") }; <del> ($dst:expr, $($arg:tt)*) => { $dst.write_fmt($crate::format_args_nl!($($arg)*)) }; </del> <ins> ($dst:expr, $($arg:tt)*) => {{ let result = $dst.write_fmt($crate::format_args_nl!($($arg)*)); result }}; </ins> } /// Indicates unreachable code.

#[cfg_attr(not(test), rustc_diagnostic_item = "print_macro")] #[allow_internal_unstable(print_internals)] macro_rules! print { <del> ($($arg:tt)*) => { $crate::io::_print($crate::format_args!($($arg)*)) }; </del> <ins> ($($arg:tt)*) => {{ $crate::io::_print($crate::format_args!($($arg)*)); }}; </ins> } /// Prints to the standard output, with a newline.

#[cfg_attr(not(test), rustc_diagnostic_item = "eprint_macro")] #[allow_internal_unstable(print_internals)] macro_rules! eprint { <del> ($($arg:tt)*) => { $crate::io::_eprint($crate::format_args!($($arg)*)) }; </del> <ins> ($($arg:tt)*) => {{ $crate::io::_eprint($crate::format_args!($($arg)*)); }}; </ins> } /// Prints to the standard error, with a newline.

<ins> // check-pass use std::fmt::{self, Display}; struct Mutex; impl Mutex { fn lock(&self) -> MutexGuard { MutexGuard(self) } } struct MutexGuard<'a>(&'a Mutex); impl<'a> Drop for MutexGuard<'a> { fn drop(&mut self) { // Empty but this is a necessary part of the repro. Otherwise borrow // checker is fine with 'a dangling at the time that MutexGuard goes out // of scope. } } impl<'a> MutexGuard<'a> { fn write_fmt(&self, _args: fmt::Arguments) {} } impl<'a> Display for MutexGuard<'a> { fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { Ok(()) } } fn main() { let _write = { let out = Mutex; let mutex = Mutex; write!(out.lock(), "{}", mutex.lock()) /* no semicolon */ }; let _writeln = { let out = Mutex; let mutex = Mutex; writeln!(out.lock(), "{}", mutex.lock()) /* no semicolon */ }; let _print = { let mutex = Mutex; print!("{}", mutex.lock()) /* no semicolon */ }; let _println = { let mutex = Mutex; println!("{}", mutex.lock()) /* no semicolon */ }; let _eprint = { let mutex = Mutex; eprint!("{}", mutex.lock()) /* no semicolon */ }; let _eprintln = { let mutex = Mutex; eprintln!("{}", mutex.lock()) /* no semicolon */ }; let _panic = { let mutex = Mutex; panic!("{}", mutex.lock()) /* no semicolon */ }; } </ins>

use clippy_utils::{is_expn_of, match_function_call, paths}; use if_chain::if_chain; use rustc_errors::Applicability; <del> use rustc_hir::{Expr, ExprKind}; </del> <ins> use rustc_hir::def::Res; use rustc_hir::{BindingAnnotation, Block, BlockCheckMode, Expr, ExprKind, Node, PatKind, QPath, Stmt, StmtKind}; </ins> use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::sym;

if let ExprKind::MethodCall(unwrap_fun, [write_call], _) = expr.kind; if unwrap_fun.ident.name == sym::unwrap; // match call to write_fmt <del> if let ExprKind::MethodCall(write_fun, [write_recv, write_arg], _) = write_call.kind; </del> <ins> if let ExprKind::MethodCall(write_fun, [write_recv, write_arg], _) = look_in_block(cx, &write_call.kind); </ins> if write_fun.ident.name == sym!(write_fmt); // match calls to std::io::stdout() / std::io::stderr () if let Some(dest_name) = if match_function_call(cx, write_recv, &paths::STDOUT).is_some() {

} } } <ins> /// If `kind` is a block that looks like `{ let result = $expr; result }` then /// returns $expr. Otherwise returns `kind`. fn look_in_block<'tcx, 'hir>(cx: &LateContext<'tcx>, kind: &'tcx ExprKind<'hir>) -> &'tcx ExprKind<'hir> { if_chain! { if let ExprKind::Block(block, _label @ None) = kind; if let Block { stmts: [Stmt { kind: StmtKind::Local(local), .. }], expr: Some(expr_end_of_block), rules: BlockCheckMode::DefaultBlock, .. } = block; // Find id of the local that expr_end_of_block resolves to if let ExprKind::Path(QPath::Resolved(None, expr_path)) = expr_end_of_block.kind; if let Res::Local(expr_res) = expr_path.res; if let Some(Node::Binding(res_pat)) = cx.tcx.hir().find(expr_res); // Find id of the local we found in the block if let PatKind::Binding(BindingAnnotation::Unannotated, local_hir_id, _ident, None) = local.pat.kind; // If those two are the same hir id if res_pat.hir_id == local_hir_id; if let Some(init) = local.init; then { return &init.kind; } } kind } </ins>