Skip to content

Rollup of 5 pull requests #114176

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 14 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1655,11 +1655,11 @@ impl HandlerInner {
let backtrace = std::env::var_os("RUST_BACKTRACE").map_or(true, |x| &x != "0");
for bug in bugs {
if let Some(file) = self.ice_file.as_ref()
&& let Ok(mut out) = std::fs::File::options().append(true).open(file)
&& let Ok(mut out) = std::fs::File::options().create(true).append(true).open(file)
{
let _ = write!(
&mut out,
"\n\ndelayed span bug: {}\n{}",
"delayed span bug: {}\n{}\n",
bug.inner.styled_message().iter().filter_map(|(msg, _)| msg.as_str()).collect::<String>(),
&bug.note
);
8 changes: 6 additions & 2 deletions compiler/rustc_hir_typeck/src/callee.rs
Original file line number Diff line number Diff line change
@@ -531,8 +531,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return;
}

let up_to_rcvr_span = segment.ident.span.until(callee_expr.span);
let rest_span = callee_expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
let Some(callee_expr_span) = callee_expr.span.find_ancestor_inside(call_expr.span)
else {
return;
};
let up_to_rcvr_span = segment.ident.span.until(callee_expr_span);
let rest_span = callee_expr_span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
let rest_snippet = if let Some(first) = rest.first() {
self.tcx
.sess
4 changes: 2 additions & 2 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
@@ -155,8 +155,6 @@ lint_builtin_unused_doc_comment = unused doc comment
lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}`
.suggestion = use `loop`
lint_cast_ref_to_mut = casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
lint_check_name_deprecated = lint name `{$lint_name}` is deprecated and does not have an effect anymore. Use: {$new_name}
lint_check_name_unknown = unknown lint: `{$lint_name}`
@@ -320,6 +318,8 @@ lint_invalid_nan_comparisons_eq_ne = incorrect NaN comparison, NaN cannot be dir
lint_invalid_nan_comparisons_lt_le_gt_ge = incorrect NaN comparison, NaN is not orderable
lint_invalid_reference_casting = casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
lint_lintpass_by_hand = implementing `LintPass` by hand
.help = try using `declare_lint_pass!` or `impl_lint_pass!` instead
6 changes: 3 additions & 3 deletions compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
@@ -50,7 +50,6 @@ extern crate tracing;

mod array_into_iter;
pub mod builtin;
mod cast_ref_to_mut;
mod context;
mod deref_into_dyn_supertrait;
mod drop_forget_useless;
@@ -78,6 +77,7 @@ mod opaque_hidden_inferred_bound;
mod pass_by_value;
mod passes;
mod redundant_semicolon;
mod reference_casting;
mod traits;
mod types;
mod unused;
@@ -99,7 +99,6 @@ use rustc_span::Span;

use array_into_iter::ArrayIntoIter;
use builtin::*;
use cast_ref_to_mut::*;
use deref_into_dyn_supertrait::*;
use drop_forget_useless::*;
use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
@@ -119,6 +118,7 @@ use noop_method_call::*;
use opaque_hidden_inferred_bound::*;
use pass_by_value::*;
use redundant_semicolon::*;
use reference_casting::*;
use traits::*;
use types::*;
use unused::*;
@@ -218,7 +218,7 @@ late_lint_methods!(
BoxPointers: BoxPointers,
PathStatements: PathStatements,
LetUnderscore: LetUnderscore,
CastRefToMut: CastRefToMut,
InvalidReferenceCasting: InvalidReferenceCasting,
// Depends on referenced function signatures in expressions
UnusedResults: UnusedResults,
NonUpperCaseGlobals: NonUpperCaseGlobals,
6 changes: 3 additions & 3 deletions compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
@@ -743,10 +743,10 @@ pub enum InvalidFromUtf8Diag {
},
}

// cast_ref_to_mut.rs
// reference_casting.rs
#[derive(LintDiagnostic)]
#[diag(lint_cast_ref_to_mut)]
pub struct CastRefToMutDiag;
#[diag(lint_invalid_reference_casting)]
pub struct InvalidReferenceCastingDiag;

// hidden_unicode_codepoints.rs
#[derive(LintDiagnostic)]
Original file line number Diff line number Diff line change
@@ -3,15 +3,16 @@ use rustc_hir::{Expr, ExprKind, MutTy, TyKind, UnOp};
use rustc_middle::ty;
use rustc_span::sym;

use crate::{lints::CastRefToMutDiag, LateContext, LateLintPass, LintContext};
use crate::{lints::InvalidReferenceCastingDiag, LateContext, LateLintPass, LintContext};

declare_lint! {
/// The `cast_ref_to_mut` lint checks for casts of `&T` to `&mut T`
/// The `invalid_reference_casting` lint checks for casts of `&T` to `&mut T`
/// without using interior mutability.
///
/// ### Example
///
/// ```rust,compile_fail
/// # #![deny(invalid_reference_casting)]
/// fn x(r: &i32) {
/// unsafe {
/// *(r as *const i32 as *mut i32) += 1;
@@ -28,14 +29,14 @@ declare_lint! {
///
/// `UnsafeCell` is the only way to obtain aliasable data that is considered
/// mutable.
CAST_REF_TO_MUT,
Deny,
INVALID_REFERENCE_CASTING,
Allow,
"casts of `&T` to `&mut T` without interior mutability"
}

declare_lint_pass!(CastRefToMut => [CAST_REF_TO_MUT]);
declare_lint_pass!(InvalidReferenceCasting => [INVALID_REFERENCE_CASTING]);

impl<'tcx> LateLintPass<'tcx> for CastRefToMut {
impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
let ExprKind::Unary(UnOp::Deref, e) = &expr.kind else {
return;
@@ -68,7 +69,7 @@ impl<'tcx> LateLintPass<'tcx> for CastRefToMut {

let e = e.peel_blocks();
if let ty::Ref(..) = cx.typeck_results().node_type(e.hir_id).kind() {
cx.emit_spanned_lint(CAST_REF_TO_MUT, expr.span, CastRefToMutDiag);
cx.emit_spanned_lint(INVALID_REFERENCE_CASTING, expr.span, InvalidReferenceCastingDiag);
}
}
}
7 changes: 3 additions & 4 deletions compiler/rustc_mir_transform/src/coverage/spans.rs
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ use rustc_middle::ty::TyCtxt;
use rustc_span::source_map::original_sp;
use rustc_span::{BytePos, ExpnKind, MacroKind, Span, Symbol};

use std::cell::RefCell;
use std::cell::OnceCell;
use std::cmp::Ordering;

#[derive(Debug, Copy, Clone)]
@@ -67,7 +67,7 @@ impl CoverageStatement {
pub(super) struct CoverageSpan {
pub span: Span,
pub expn_span: Span,
pub current_macro_or_none: RefCell<Option<Option<Symbol>>>,
pub current_macro_or_none: OnceCell<Option<Symbol>>,
pub bcb: BasicCoverageBlock,
pub coverage_statements: Vec<CoverageStatement>,
pub is_closure: bool,
@@ -175,8 +175,7 @@ impl CoverageSpan {
/// If the span is part of a macro, returns the macro name symbol.
pub fn current_macro(&self) -> Option<Symbol> {
self.current_macro_or_none
.borrow_mut()
.get_or_insert_with(|| {
.get_or_init(|| {
if let ExpnKind::Macro(MacroKind::Bang, current_macro) =
self.expn_span.ctxt().outer_expn_data().kind
{
2 changes: 1 addition & 1 deletion library/std/src/panicking.rs
Original file line number Diff line number Diff line change
@@ -300,7 +300,7 @@ pub fn panic_hook_with_disk_dump(info: &PanicInfo<'_>, path: Option<&crate::path
};

if let Some(path) = path
&& let Ok(mut out) = crate::fs::File::options().create(true).write(true).open(&path)
&& let Ok(mut out) = crate::fs::File::options().create(true).append(true).open(&path)
{
write(&mut out, BacktraceStyle::full());
}
2 changes: 1 addition & 1 deletion src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
@@ -2818,7 +2818,7 @@ fn clean_use_statement_inner<'tcx>(
cx: &mut DocContext<'tcx>,
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
) -> Vec<Item> {
if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = path.res {
if should_ignore_res(path.res) {
return Vec::new();
}
// We need this comparison because some imports (for std types for example)
34 changes: 33 additions & 1 deletion src/librustdoc/clean/utils.rs
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ use rustc_ast as ast;
use rustc_ast::tokenstream::TokenTree;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
use rustc_middle::mir;
use rustc_middle::mir::interpret::ConstValue;
use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, TyCtxt};
@@ -629,3 +629,35 @@ pub(super) fn display_macro_source(
}
}
}

pub(crate) fn inherits_doc_hidden(
tcx: TyCtxt<'_>,
mut def_id: LocalDefId,
stop_at: Option<LocalDefId>,
) -> bool {
let hir = tcx.hir();
while let Some(id) = tcx.opt_local_parent(def_id) {
if let Some(stop_at) = stop_at && id == stop_at {
return false;
}
def_id = id;
if tcx.is_doc_hidden(def_id.to_def_id()) {
return true;
} else if let Some(node) = hir.find_by_def_id(def_id) &&
matches!(
node,
hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }),
)
{
// `impl` blocks stand a bit on their own: unless they have `#[doc(hidden)]` directly
// on them, they don't inherit it from the parent context.
return false;
}
}
false
}

#[inline]
pub(crate) fn should_ignore_res(res: Res) -> bool {
matches!(res, Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..))
}
156 changes: 82 additions & 74 deletions src/librustdoc/html/render/mod.rs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/librustdoc/passes/check_doc_test_visibility.rs
Original file line number Diff line number Diff line change
@@ -7,11 +7,11 @@
use super::Pass;
use crate::clean;
use crate::clean::utils::inherits_doc_hidden;
use crate::clean::*;
use crate::core::DocContext;
use crate::html::markdown::{find_testable_code, ErrorCodes, Ignore, LangString};
use crate::visit::DocVisitor;
use crate::visit_ast::inherits_doc_hidden;
use rustc_hir as hir;
use rustc_middle::lint::LintLevelSource;
use rustc_session::lint;
2 changes: 1 addition & 1 deletion src/librustdoc/passes/strip_hidden.rs
Original file line number Diff line number Diff line change
@@ -6,11 +6,11 @@ use rustc_span::symbol::sym;
use std::mem;

use crate::clean;
use crate::clean::utils::inherits_doc_hidden;
use crate::clean::{Item, ItemIdSet};
use crate::core::DocContext;
use crate::fold::{strip_item, DocFolder};
use crate::passes::{ImplStripper, Pass};
use crate::visit_ast::inherits_doc_hidden;

pub(crate) const STRIP_HIDDEN: Pass = Pass {
name: "strip-hidden",
2 changes: 1 addition & 1 deletion src/librustdoc/passes/stripper.rs
Original file line number Diff line number Diff line change
@@ -3,10 +3,10 @@ use rustc_hir::def_id::DefId;
use rustc_middle::ty::{TyCtxt, Visibility};
use std::mem;

use crate::clean::utils::inherits_doc_hidden;
use crate::clean::{self, Item, ItemId, ItemIdSet};
use crate::fold::{strip_item, DocFolder};
use crate::formats::cache::Cache;
use crate::visit_ast::inherits_doc_hidden;
use crate::visit_lib::RustdocEffectiveVisibilities;

pub(crate) struct Stripper<'a, 'tcx> {
30 changes: 2 additions & 28 deletions src/librustdoc/visit_ast.rs
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@ use rustc_span::Span;

use std::mem;

use crate::clean::utils::{inherits_doc_hidden, should_ignore_res};
use crate::clean::{cfg::Cfg, reexport_chain, AttributesExt, NestedAttributesExt};
use crate::core;

@@ -73,33 +74,6 @@ fn def_id_to_path(tcx: TyCtxt<'_>, did: DefId) -> Vec<Symbol> {
std::iter::once(crate_name).chain(relative).collect()
}

pub(crate) fn inherits_doc_hidden(
tcx: TyCtxt<'_>,
mut def_id: LocalDefId,
stop_at: Option<LocalDefId>,
) -> bool {
let hir = tcx.hir();
while let Some(id) = tcx.opt_local_parent(def_id) {
if let Some(stop_at) = stop_at && id == stop_at {
return false;
}
def_id = id;
if tcx.is_doc_hidden(def_id.to_def_id()) {
return true;
} else if let Some(node) = hir.find_by_def_id(def_id) &&
matches!(
node,
hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }),
)
{
// `impl` blocks stand a bit on their own: unless they have `#[doc(hidden)]` directly
// on them, they don't inherit it from the parent context.
return false;
}
}
false
}

pub(crate) struct RustdocVisitor<'a, 'tcx> {
cx: &'a mut core::DocContext<'tcx>,
view_item_stack: LocalDefIdSet,
@@ -466,7 +440,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
for &res in &path.res {
// Struct and variant constructors and proc macro stubs always show up alongside
// their definitions, we've already processed them so just discard these.
if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = res {
if should_ignore_res(res) {
continue;
}

2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_lints/src/renamed_lints.rs
Original file line number Diff line number Diff line change
@@ -31,7 +31,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
("clippy::stutter", "clippy::module_name_repetitions"),
("clippy::to_string_in_display", "clippy::recursive_format_impl"),
("clippy::zero_width_space", "clippy::invisible_characters"),
("clippy::cast_ref_to_mut", "cast_ref_to_mut"),
("clippy::cast_ref_to_mut", "invalid_reference_casting"),
("clippy::clone_double_ref", "suspicious_double_ref_op"),
("clippy::cmp_nan", "invalid_nan_comparisons"),
("clippy::drop_bounds", "drop_bounds"),
4 changes: 2 additions & 2 deletions src/tools/clippy/tests/ui/rename.fixed
Original file line number Diff line number Diff line change
@@ -28,9 +28,9 @@
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::recursive_format_impl)]
#![allow(clippy::invisible_characters)]
#![allow(cast_ref_to_mut)]
#![allow(suspicious_double_ref_op)]
#![allow(invalid_nan_comparisons)]
#![allow(invalid_reference_casting)]
#![allow(drop_bounds)]
#![allow(dropping_copy_types)]
#![allow(dropping_references)]
@@ -79,7 +79,7 @@
#![warn(clippy::module_name_repetitions)]
#![warn(clippy::recursive_format_impl)]
#![warn(clippy::invisible_characters)]
#![warn(cast_ref_to_mut)]
#![warn(invalid_reference_casting)]
#![warn(suspicious_double_ref_op)]
#![warn(invalid_nan_comparisons)]
#![warn(drop_bounds)]
2 changes: 1 addition & 1 deletion src/tools/clippy/tests/ui/rename.rs
Original file line number Diff line number Diff line change
@@ -28,9 +28,9 @@
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::recursive_format_impl)]
#![allow(clippy::invisible_characters)]
#![allow(cast_ref_to_mut)]
#![allow(suspicious_double_ref_op)]
#![allow(invalid_nan_comparisons)]
#![allow(invalid_reference_casting)]
#![allow(drop_bounds)]
#![allow(dropping_copy_types)]
#![allow(dropping_references)]
4 changes: 2 additions & 2 deletions src/tools/clippy/tests/ui/rename.stderr
Original file line number Diff line number Diff line change
@@ -174,11 +174,11 @@ error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_ch
LL | #![warn(clippy::zero_width_space)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`

error: lint `clippy::cast_ref_to_mut` has been renamed to `cast_ref_to_mut`
error: lint `clippy::cast_ref_to_mut` has been renamed to `invalid_reference_casting`
--> $DIR/rename.rs:82:9
|
LL | #![warn(clippy::cast_ref_to_mut)]
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `cast_ref_to_mut`
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_reference_casting`

error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
--> $DIR/rename.rs:83:9
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//@revisions: stack tree
//@[tree]compile-flags: -Zmiri-tree-borrows

#![allow(cast_ref_to_mut)]
#![allow(invalid_reference_casting)]

fn foo(x: &mut i32) -> i32 {
*x = 5;
2 changes: 1 addition & 1 deletion src/tools/miri/tests/fail/modifying_constants.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// This should fail even without validation/SB
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows

#![allow(cast_ref_to_mut)]
#![allow(invalid_reference_casting)]

fn main() {
let x = &1; // the `&1` is promoted to a constant, but it used to be that only the pointer is marked static, not the pointee
1 change: 0 additions & 1 deletion tests/ui/const-generics/issues/issue-100313.rs
Original file line number Diff line number Diff line change
@@ -9,7 +9,6 @@ impl <const B: &'static bool> T<B> {
unsafe {
*(B as *const bool as *mut bool) = false;
//~^ ERROR evaluation of constant value failed [E0080]
//~| ERROR casting `&T` to `&mut T` is undefined behavior
}
}
}
12 changes: 2 additions & 10 deletions tests/ui/const-generics/issues/issue-100313.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/issue-100313.rs:10:13
|
LL | *(B as *const bool as *mut bool) = false;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[deny(cast_ref_to_mut)]` on by default

error[E0080]: evaluation of constant value failed
--> $DIR/issue-100313.rs:10:13
|
@@ -18,11 +10,11 @@ note: inside `T::<&true>::set_false`
LL | *(B as *const bool as *mut bool) = false;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: inside `_`
--> $DIR/issue-100313.rs:19:5
--> $DIR/issue-100313.rs:18:5
|
LL | x.set_false();
| ^^^^^^^^^^^^^

error: aborting due to 2 previous errors
error: aborting due to previous error

For more information about this error, try `rustc --explain E0080`.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// check-fail

#![feature(ptr_from_ref)]
#![deny(invalid_reference_casting)]

extern "C" {
// N.B., mutability can be easily incorrect in FFI calls -- as
Original file line number Diff line number Diff line change
@@ -1,61 +1,65 @@
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/cast_ref_to_mut.rs:19:9
--> $DIR/reference_casting.rs:20:9
|
LL | (*(a as *const _ as *mut String)).push_str(" world");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[deny(cast_ref_to_mut)]` on by default
note: the lint level is defined here
--> $DIR/reference_casting.rs:4:9
|
LL | #![deny(invalid_reference_casting)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/cast_ref_to_mut.rs:21:9
--> $DIR/reference_casting.rs:22:9
|
LL | *(a as *const _ as *mut _) = String::from("Replaced");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^

error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/cast_ref_to_mut.rs:23:9
--> $DIR/reference_casting.rs:24:9
|
LL | *(a as *const _ as *mut String) += " world";
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/cast_ref_to_mut.rs:25:25
--> $DIR/reference_casting.rs:26:25
|
LL | let _num = &mut *(num as *const i32 as *mut i32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/cast_ref_to_mut.rs:27:25
--> $DIR/reference_casting.rs:28:25
|
LL | let _num = &mut *(num as *const i32).cast_mut();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/cast_ref_to_mut.rs:29:20
--> $DIR/reference_casting.rs:30:20
|
LL | let _num = *{ num as *const i32 }.cast_mut();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/cast_ref_to_mut.rs:31:9
--> $DIR/reference_casting.rs:32:9
|
LL | *std::ptr::from_ref(num).cast_mut() += 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/cast_ref_to_mut.rs:33:9
--> $DIR/reference_casting.rs:34:9
|
LL | *std::ptr::from_ref({ num }).cast_mut() += 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/cast_ref_to_mut.rs:35:9
--> $DIR/reference_casting.rs:36:9
|
LL | *{ std::ptr::from_ref(num) }.cast_mut() += 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/cast_ref_to_mut.rs:37:9
--> $DIR/reference_casting.rs:38:9
|
LL | *(std::ptr::from_ref({ num }) as *mut i32) += 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6 changes: 6 additions & 0 deletions tests/ui/methods/suggest-method-on-call-with-macro-rcvr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// issue: 114131

fn main() {
let hello = len(vec![]);
//~^ ERROR cannot find function `len` in this scope
}
15 changes: 15 additions & 0 deletions tests/ui/methods/suggest-method-on-call-with-macro-rcvr.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0425]: cannot find function `len` in this scope
--> $DIR/suggest-method-on-call-with-macro-rcvr.rs:4:17
|
LL | let hello = len(vec![]);
| ^^^ not found in this scope
|
help: use the `.` operator to call the method `len` on `&Vec<_>`
|
LL - let hello = len(vec![]);
LL + let hello = vec![].len();
|

error: aborting due to previous error

For more information about this error, try `rustc --explain E0425`.