Rollup merge of #104786 - WaffleLapkin:amp-mut-help, r=compiler-errors
Use the power of adding helper function to simplify code w/ `Mutability` r? `@compiler-errors`
This commit is contained in:
commit
a2e485c25c
@ -775,8 +775,9 @@ pub enum PatKind {
|
|||||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
|
||||||
#[derive(HashStable_Generic, Encodable, Decodable)]
|
#[derive(HashStable_Generic, Encodable, Decodable)]
|
||||||
pub enum Mutability {
|
pub enum Mutability {
|
||||||
Mut,
|
// N.B. Order is deliberate, so that Not < Mut
|
||||||
Not,
|
Not,
|
||||||
|
Mut,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mutability {
|
impl Mutability {
|
||||||
@ -787,12 +788,39 @@ impl Mutability {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prefix_str(&self) -> &'static str {
|
/// Returns `""` (empty string) or `"mut "` depending on the mutability.
|
||||||
|
pub fn prefix_str(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Mutability::Mut => "mut ",
|
Mutability::Mut => "mut ",
|
||||||
Mutability::Not => "",
|
Mutability::Not => "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `"&"` or `"&mut "` depending on the mutability.
|
||||||
|
pub fn ref_prefix_str(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Mutability::Not => "&",
|
||||||
|
Mutability::Mut => "&mut ",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `""` (empty string) or `"mutably "` depending on the mutability.
|
||||||
|
pub fn mutably_str(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Mutability::Not => "",
|
||||||
|
Mutability::Mut => "mutably ",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return `true` if self is mutable
|
||||||
|
pub fn is_mut(self) -> bool {
|
||||||
|
matches!(self, Self::Mut)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return `true` if self is **not** mutable
|
||||||
|
pub fn is_not(self) -> bool {
|
||||||
|
matches!(self, Self::Not)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The kind of borrow in an `AddrOf` expression,
|
/// The kind of borrow in an `AddrOf` expression,
|
||||||
|
@ -1781,14 +1781,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
// Given we are only considering `ImplicitSelf` types, we needn't consider
|
// Given we are only considering `ImplicitSelf` types, we needn't consider
|
||||||
// the case where we have a mutable pattern to a reference as that would
|
// the case where we have a mutable pattern to a reference as that would
|
||||||
// no longer be an `ImplicitSelf`.
|
// no longer be an `ImplicitSelf`.
|
||||||
TyKind::Rptr(_, mt)
|
TyKind::Rptr(_, mt) if mt.ty.kind.is_implicit_self() => match mt.mutbl {
|
||||||
if mt.ty.kind.is_implicit_self() && mt.mutbl == ast::Mutability::Mut =>
|
hir::Mutability::Not => hir::ImplicitSelfKind::ImmRef,
|
||||||
{
|
hir::Mutability::Mut => hir::ImplicitSelfKind::MutRef,
|
||||||
hir::ImplicitSelfKind::MutRef
|
},
|
||||||
}
|
|
||||||
TyKind::Rptr(_, mt) if mt.ty.kind.is_implicit_self() => {
|
|
||||||
hir::ImplicitSelfKind::ImmRef
|
|
||||||
}
|
|
||||||
_ => hir::ImplicitSelfKind::None,
|
_ => hir::ImplicitSelfKind::None,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
@ -716,19 +716,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
let moved_place = &self.move_data.move_paths[move_out.path].place;
|
let moved_place = &self.move_data.move_paths[move_out.path].place;
|
||||||
let move_spans = self.move_spans(moved_place.as_ref(), move_out.source);
|
let move_spans = self.move_spans(moved_place.as_ref(), move_out.source);
|
||||||
let move_span = move_spans.args_or_use();
|
let move_span = move_spans.args_or_use();
|
||||||
let suggestion = if borrow_level == hir::Mutability::Mut {
|
let suggestion = borrow_level.ref_prefix_str().to_owned();
|
||||||
"&mut ".to_string()
|
|
||||||
} else {
|
|
||||||
"&".to_string()
|
|
||||||
};
|
|
||||||
(move_span.shrink_to_lo(), suggestion)
|
(move_span.shrink_to_lo(), suggestion)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
err.multipart_suggestion_verbose(
|
err.multipart_suggestion_verbose(
|
||||||
&format!(
|
format!("consider {}borrowing {value_name}", borrow_level.mutably_str()),
|
||||||
"consider {}borrowing {value_name}",
|
|
||||||
if borrow_level == hir::Mutability::Mut { "mutably " } else { "" }
|
|
||||||
),
|
|
||||||
sugg,
|
sugg,
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
|
@ -389,13 +389,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
// diagnostic: if the span starts with a mutable borrow of
|
// diagnostic: if the span starts with a mutable borrow of
|
||||||
// a local variable, then just suggest the user remove it.
|
// a local variable, then just suggest the user remove it.
|
||||||
PlaceRef { local: _, projection: [] }
|
PlaceRef { local: _, projection: [] }
|
||||||
if {
|
if self
|
||||||
if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
|
.infcx
|
||||||
snippet.starts_with("&mut ")
|
.tcx
|
||||||
} else {
|
.sess
|
||||||
false
|
.source_map()
|
||||||
}
|
.span_to_snippet(span)
|
||||||
} =>
|
.map_or(false, |snippet| snippet.starts_with("&mut ")) =>
|
||||||
{
|
{
|
||||||
err.span_label(span, format!("cannot {ACT}", ACT = act));
|
err.span_label(span, format!("cannot {ACT}", ACT = act));
|
||||||
err.span_suggestion(
|
err.span_suggestion(
|
||||||
|
@ -257,9 +257,9 @@ pub(crate) fn data_id_for_alloc_id(
|
|||||||
mutability: rustc_hir::Mutability,
|
mutability: rustc_hir::Mutability,
|
||||||
) -> DataId {
|
) -> DataId {
|
||||||
cx.todo.push(TodoItem::Alloc(alloc_id));
|
cx.todo.push(TodoItem::Alloc(alloc_id));
|
||||||
*cx.anon_allocs.entry(alloc_id).or_insert_with(|| {
|
*cx.anon_allocs
|
||||||
module.declare_anonymous_data(mutability == rustc_hir::Mutability::Mut, false).unwrap()
|
.entry(alloc_id)
|
||||||
})
|
.or_insert_with(|| module.declare_anonymous_data(mutability.is_mut(), false).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn data_id_for_static(
|
fn data_id_for_static(
|
||||||
@ -343,12 +343,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let data_id = *cx.anon_allocs.entry(alloc_id).or_insert_with(|| {
|
let data_id = *cx.anon_allocs.entry(alloc_id).or_insert_with(|| {
|
||||||
module
|
module.declare_anonymous_data(alloc.inner().mutability.is_mut(), false).unwrap()
|
||||||
.declare_anonymous_data(
|
|
||||||
alloc.inner().mutability == rustc_hir::Mutability::Mut,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
});
|
});
|
||||||
(data_id, alloc, None)
|
(data_id, alloc, None)
|
||||||
}
|
}
|
||||||
|
@ -1500,7 +1500,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||||||
let (_, element_ty1) = arg_tys[1].simd_size_and_type(bx.tcx());
|
let (_, element_ty1) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||||
let (_, element_ty2) = arg_tys[2].simd_size_and_type(bx.tcx());
|
let (_, element_ty2) = arg_tys[2].simd_size_and_type(bx.tcx());
|
||||||
let (pointer_count, underlying_ty) = match element_ty1.kind() {
|
let (pointer_count, underlying_ty) = match element_ty1.kind() {
|
||||||
ty::RawPtr(p) if p.ty == in_elem && p.mutbl == hir::Mutability::Mut => {
|
ty::RawPtr(p) if p.ty == in_elem && p.mutbl.is_mut() => {
|
||||||
(ptr_count(element_ty1), non_ptr(element_ty1))
|
(ptr_count(element_ty1), non_ptr(element_ty1))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -130,10 +130,7 @@ impl hir::Pat<'_> {
|
|||||||
pub fn contains_explicit_ref_binding(&self) -> Option<hir::Mutability> {
|
pub fn contains_explicit_ref_binding(&self) -> Option<hir::Mutability> {
|
||||||
let mut result = None;
|
let mut result = None;
|
||||||
self.each_binding(|annotation, _, _, _| match annotation {
|
self.each_binding(|annotation, _, _, _| match annotation {
|
||||||
hir::BindingAnnotation::REF => match result {
|
hir::BindingAnnotation::REF if result.is_none() => result = Some(hir::Mutability::Not),
|
||||||
None | Some(hir::Mutability::Not) => result = Some(hir::Mutability::Not),
|
|
||||||
_ => {}
|
|
||||||
},
|
|
||||||
hir::BindingAnnotation::REF_MUT => result = Some(hir::Mutability::Mut),
|
hir::BindingAnnotation::REF_MUT => result = Some(hir::Mutability::Mut),
|
||||||
_ => {}
|
_ => {}
|
||||||
});
|
});
|
||||||
|
@ -370,7 +370,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
|
|||||||
let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
|
let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
|
||||||
mt_b: ty::TypeAndMut<'tcx>,
|
mt_b: ty::TypeAndMut<'tcx>,
|
||||||
mk_ptr: &dyn Fn(Ty<'tcx>) -> Ty<'tcx>| {
|
mk_ptr: &dyn Fn(Ty<'tcx>) -> Ty<'tcx>| {
|
||||||
if (mt_a.mutbl, mt_b.mutbl) == (hir::Mutability::Not, hir::Mutability::Mut) {
|
if mt_a.mutbl < mt_b.mutbl {
|
||||||
infcx
|
infcx
|
||||||
.err_ctxt()
|
.err_ctxt()
|
||||||
.report_mismatched_types(
|
.report_mismatched_types(
|
||||||
|
@ -292,7 +292,7 @@ fn emit_newtype_suggestion_for_raw_ptr(
|
|||||||
diag: &mut Diagnostic,
|
diag: &mut Diagnostic,
|
||||||
) {
|
) {
|
||||||
if !self_ty.needs_subst() {
|
if !self_ty.needs_subst() {
|
||||||
let mut_key = if ptr_ty.mutbl == rustc_middle::mir::Mutability::Mut { "mut " } else { "" };
|
let mut_key = ptr_ty.mutbl.prefix_str();
|
||||||
let msg_sugg = "consider introducing a new wrapper type".to_owned();
|
let msg_sugg = "consider introducing a new wrapper type".to_owned();
|
||||||
let sugg = vec![
|
let sugg = vec![
|
||||||
(
|
(
|
||||||
|
@ -398,7 +398,7 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
hir::ForeignItemKind::Static(t, m) => {
|
hir::ForeignItemKind::Static(t, m) => {
|
||||||
self.head("static");
|
self.head("static");
|
||||||
if m == hir::Mutability::Mut {
|
if m.is_mut() {
|
||||||
self.word_space("mut");
|
self.word_space("mut");
|
||||||
}
|
}
|
||||||
self.print_ident(item.ident);
|
self.print_ident(item.ident);
|
||||||
@ -519,7 +519,7 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
hir::ItemKind::Static(ty, m, expr) => {
|
hir::ItemKind::Static(ty, m, expr) => {
|
||||||
self.head("static");
|
self.head("static");
|
||||||
if m == hir::Mutability::Mut {
|
if m.is_mut() {
|
||||||
self.word_space("mut");
|
self.word_space("mut");
|
||||||
}
|
}
|
||||||
self.print_ident(item.ident);
|
self.print_ident(item.ident);
|
||||||
|
@ -574,8 +574,5 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn arms_contain_ref_bindings<'tcx>(arms: &'tcx [hir::Arm<'tcx>]) -> Option<hir::Mutability> {
|
fn arms_contain_ref_bindings<'tcx>(arms: &'tcx [hir::Arm<'tcx>]) -> Option<hir::Mutability> {
|
||||||
arms.iter().filter_map(|a| a.pat.contains_explicit_ref_binding()).max_by_key(|m| match *m {
|
arms.iter().filter_map(|a| a.pat.contains_explicit_ref_binding()).max()
|
||||||
hir::Mutability::Mut => 1,
|
|
||||||
hir::Mutability::Not => 0,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
@ -257,15 +257,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
let mutbl = match mutbl {
|
// For initial two-phase borrow
|
||||||
hir::Mutability::Not => AutoBorrowMutability::Not,
|
// deployment, conservatively omit
|
||||||
hir::Mutability::Mut => AutoBorrowMutability::Mut {
|
// overloaded function call ops.
|
||||||
// For initial two-phase borrow
|
let mutbl = AutoBorrowMutability::new(*mutbl, AllowTwoPhase::No);
|
||||||
// deployment, conservatively omit
|
|
||||||
// overloaded function call ops.
|
|
||||||
allow_two_phase_borrow: AllowTwoPhase::No,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
autoref = Some(Adjustment {
|
autoref = Some(Adjustment {
|
||||||
kind: Adjust::Borrow(AutoBorrow::Ref(*region, mutbl)),
|
kind: Adjust::Borrow(AutoBorrow::Ref(*region, mutbl)),
|
||||||
target: method.sig.inputs()[0],
|
target: method.sig.inputs()[0],
|
||||||
|
@ -951,7 +951,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||||||
m_cast: ty::TypeAndMut<'tcx>,
|
m_cast: ty::TypeAndMut<'tcx>,
|
||||||
) -> Result<CastKind, CastError> {
|
) -> Result<CastKind, CastError> {
|
||||||
// array-ptr-cast: allow mut-to-mut, mut-to-const, const-to-const
|
// array-ptr-cast: allow mut-to-mut, mut-to-const, const-to-const
|
||||||
if m_expr.mutbl == hir::Mutability::Mut || m_cast.mutbl == hir::Mutability::Not {
|
if m_expr.mutbl >= m_cast.mutbl {
|
||||||
if let ty::Array(ety, _) = m_expr.ty.kind() {
|
if let ty::Array(ety, _) = m_expr.ty.kind() {
|
||||||
// Due to the limitations of LLVM global constants,
|
// Due to the limitations of LLVM global constants,
|
||||||
// region pointers end up pointing at copies of
|
// region pointers end up pointing at copies of
|
||||||
|
@ -202,7 +202,7 @@ fn check_panic_info_fn(
|
|||||||
let arg_is_panic_info = match *inputs[0].kind() {
|
let arg_is_panic_info = match *inputs[0].kind() {
|
||||||
ty::Ref(region, ty, mutbl) => match *ty.kind() {
|
ty::Ref(region, ty, mutbl) => match *ty.kind() {
|
||||||
ty::Adt(ref adt, _) => {
|
ty::Adt(ref adt, _) => {
|
||||||
adt.did() == panic_info_did && mutbl == hir::Mutability::Not && !region.is_static()
|
adt.did() == panic_info_did && mutbl.is_not() && !region.is_static()
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
|
@ -108,11 +108,7 @@ fn coerce_mutbls<'tcx>(
|
|||||||
from_mutbl: hir::Mutability,
|
from_mutbl: hir::Mutability,
|
||||||
to_mutbl: hir::Mutability,
|
to_mutbl: hir::Mutability,
|
||||||
) -> RelateResult<'tcx, ()> {
|
) -> RelateResult<'tcx, ()> {
|
||||||
match (from_mutbl, to_mutbl) {
|
if from_mutbl >= to_mutbl { Ok(()) } else { Err(TypeError::Mutability) }
|
||||||
(hir::Mutability::Mut, hir::Mutability::Mut | hir::Mutability::Not)
|
|
||||||
| (hir::Mutability::Not, hir::Mutability::Not) => Ok(()),
|
|
||||||
(hir::Mutability::Not, hir::Mutability::Mut) => Err(TypeError::Mutability),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Do not require any adjustments, i.e. coerce `x -> x`.
|
/// Do not require any adjustments, i.e. coerce `x -> x`.
|
||||||
@ -456,7 +452,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
return Err(err);
|
return Err(err);
|
||||||
};
|
};
|
||||||
|
|
||||||
if ty == a && mt_a.mutbl == hir::Mutability::Not && autoderef.step_count() == 1 {
|
if ty == a && mt_a.mutbl.is_not() && autoderef.step_count() == 1 {
|
||||||
// As a special case, if we would produce `&'a *x`, that's
|
// As a special case, if we would produce `&'a *x`, that's
|
||||||
// a total no-op. We end up with the type `&'a T` just as
|
// a total no-op. We end up with the type `&'a T` just as
|
||||||
// we started with. In that case, just skip it
|
// we started with. In that case, just skip it
|
||||||
@ -468,7 +464,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
// `self.x` both have `&mut `type would be a move of
|
// `self.x` both have `&mut `type would be a move of
|
||||||
// `self.x`, but we auto-coerce it to `foo(&mut *self.x)`,
|
// `self.x`, but we auto-coerce it to `foo(&mut *self.x)`,
|
||||||
// which is a borrow.
|
// which is a borrow.
|
||||||
assert_eq!(mutbl_b, hir::Mutability::Not); // can only coerce &T -> &U
|
assert!(mutbl_b.is_not()); // can only coerce &T -> &U
|
||||||
return success(vec![], ty, obligations);
|
return success(vec![], ty, obligations);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,12 +478,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
let ty::Ref(r_borrow, _, _) = ty.kind() else {
|
let ty::Ref(r_borrow, _, _) = ty.kind() else {
|
||||||
span_bug!(span, "expected a ref type, got {:?}", ty);
|
span_bug!(span, "expected a ref type, got {:?}", ty);
|
||||||
};
|
};
|
||||||
let mutbl = match mutbl_b {
|
let mutbl = AutoBorrowMutability::new(mutbl_b, self.allow_two_phase);
|
||||||
hir::Mutability::Not => AutoBorrowMutability::Not,
|
|
||||||
hir::Mutability::Mut => {
|
|
||||||
AutoBorrowMutability::Mut { allow_two_phase_borrow: self.allow_two_phase }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
adjustments.push(Adjustment {
|
adjustments.push(Adjustment {
|
||||||
kind: Adjust::Borrow(AutoBorrow::Ref(*r_borrow, mutbl)),
|
kind: Adjust::Borrow(AutoBorrow::Ref(*r_borrow, mutbl)),
|
||||||
target: ty,
|
target: ty,
|
||||||
@ -556,15 +547,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
|
|
||||||
let coercion = Coercion(self.cause.span);
|
let coercion = Coercion(self.cause.span);
|
||||||
let r_borrow = self.next_region_var(coercion);
|
let r_borrow = self.next_region_var(coercion);
|
||||||
let mutbl = match mutbl_b {
|
|
||||||
hir::Mutability::Not => AutoBorrowMutability::Not,
|
// We don't allow two-phase borrows here, at least for initial
|
||||||
hir::Mutability::Mut => AutoBorrowMutability::Mut {
|
// implementation. If it happens that this coercion is a function argument,
|
||||||
// We don't allow two-phase borrows here, at least for initial
|
// the reborrow in coerce_borrowed_ptr will pick it up.
|
||||||
// implementation. If it happens that this coercion is a function argument,
|
let mutbl = AutoBorrowMutability::new(mutbl_b, AllowTwoPhase::No);
|
||||||
// the reborrow in coerce_borrowed_ptr will pick it up.
|
|
||||||
allow_two_phase_borrow: AllowTwoPhase::No,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
Some((
|
Some((
|
||||||
Adjustment { kind: Adjust::Deref(None), target: ty_a },
|
Adjustment { kind: Adjust::Deref(None), target: ty_a },
|
||||||
Adjustment {
|
Adjustment {
|
||||||
|
@ -19,6 +19,7 @@ use rustc_trait_selection::traits::ObligationCause;
|
|||||||
|
|
||||||
use super::method::probe;
|
use super::method::probe;
|
||||||
|
|
||||||
|
use std::cmp::min;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
@ -855,31 +856,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
..
|
..
|
||||||
})) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id))
|
})) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id))
|
||||||
{
|
{
|
||||||
if mutability == hir::Mutability::Mut {
|
if mutability.is_mut() {
|
||||||
// Suppressing this diagnostic, we'll properly print it in `check_expr_assign`
|
// Suppressing this diagnostic, we'll properly print it in `check_expr_assign`
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let sugg_expr = if needs_parens { format!("({src})") } else { src };
|
let sugg_expr = if needs_parens { format!("({src})") } else { src };
|
||||||
return Some(match mutability {
|
return Some((
|
||||||
hir::Mutability::Mut => (
|
sp,
|
||||||
sp,
|
format!("consider {}borrowing here", mutability.mutably_str()),
|
||||||
"consider mutably borrowing here".to_string(),
|
format!("{prefix}{}{sugg_expr}", mutability.ref_prefix_str()),
|
||||||
format!("{prefix}&mut {sugg_expr}"),
|
Applicability::MachineApplicable,
|
||||||
Applicability::MachineApplicable,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
));
|
||||||
),
|
|
||||||
hir::Mutability::Not => (
|
|
||||||
sp,
|
|
||||||
"consider borrowing here".to_string(),
|
|
||||||
format!("{prefix}&{sugg_expr}"),
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -937,51 +928,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
&& let Ok(src) = sm.span_to_snippet(sp)
|
&& let Ok(src) = sm.span_to_snippet(sp)
|
||||||
{
|
{
|
||||||
let derefs = "*".repeat(steps);
|
let derefs = "*".repeat(steps);
|
||||||
if let Some((span, src, applicability)) = match mutbl_b {
|
let old_prefix = mutbl_a.ref_prefix_str();
|
||||||
hir::Mutability::Mut => {
|
let new_prefix = mutbl_b.ref_prefix_str().to_owned() + &derefs;
|
||||||
let new_prefix = "&mut ".to_owned() + &derefs;
|
|
||||||
match mutbl_a {
|
let suggestion = replace_prefix(&src, old_prefix, &new_prefix).map(|_| {
|
||||||
hir::Mutability::Mut => {
|
// skip `&` or `&mut ` if both mutabilities are mutable
|
||||||
replace_prefix(&src, "&mut ", &new_prefix).map(|_| {
|
let lo = sp.lo() + BytePos(min(old_prefix.len(), mutbl_b.ref_prefix_str().len()) as _);
|
||||||
let pos = sp.lo() + BytePos(5);
|
// skip `&` or `&mut `
|
||||||
let sp = sp.with_lo(pos).with_hi(pos);
|
let hi = sp.lo() + BytePos(old_prefix.len() as _);
|
||||||
(sp, derefs, Applicability::MachineApplicable)
|
let sp = sp.with_lo(lo).with_hi(hi);
|
||||||
})
|
|
||||||
}
|
(
|
||||||
hir::Mutability::Not => {
|
sp,
|
||||||
replace_prefix(&src, "&", &new_prefix).map(|_| {
|
format!("{}{derefs}", if mutbl_a != mutbl_b { mutbl_b.prefix_str() } else { "" }),
|
||||||
let pos = sp.lo() + BytePos(1);
|
if mutbl_b <= mutbl_a { Applicability::MachineApplicable } else { Applicability::MaybeIncorrect }
|
||||||
let sp = sp.with_lo(pos).with_hi(pos);
|
)
|
||||||
(
|
});
|
||||||
sp,
|
|
||||||
format!("mut {derefs}"),
|
if let Some((span, src, applicability)) = suggestion {
|
||||||
Applicability::Unspecified,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hir::Mutability::Not => {
|
|
||||||
let new_prefix = "&".to_owned() + &derefs;
|
|
||||||
match mutbl_a {
|
|
||||||
hir::Mutability::Mut => {
|
|
||||||
replace_prefix(&src, "&mut ", &new_prefix).map(|_| {
|
|
||||||
let lo = sp.lo() + BytePos(1);
|
|
||||||
let hi = sp.lo() + BytePos(5);
|
|
||||||
let sp = sp.with_lo(lo).with_hi(hi);
|
|
||||||
(sp, derefs, Applicability::MachineApplicable)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
hir::Mutability::Not => {
|
|
||||||
replace_prefix(&src, "&", &new_prefix).map(|_| {
|
|
||||||
let pos = sp.lo() + BytePos(1);
|
|
||||||
let sp = sp.with_lo(pos).with_hi(pos);
|
|
||||||
(sp, derefs, Applicability::MachineApplicable)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} {
|
|
||||||
return Some((
|
return Some((
|
||||||
span,
|
span,
|
||||||
"consider dereferencing".to_string(),
|
"consider dereferencing".to_string(),
|
||||||
@ -1005,10 +969,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
// If the expression has `&`, removing it would fix the error
|
// If the expression has `&`, removing it would fix the error
|
||||||
prefix_span = prefix_span.with_hi(inner.span.lo());
|
prefix_span = prefix_span.with_hi(inner.span.lo());
|
||||||
expr = inner;
|
expr = inner;
|
||||||
remove += match mutbl {
|
remove.push_str(mutbl.ref_prefix_str());
|
||||||
hir::Mutability::Not => "&",
|
|
||||||
hir::Mutability::Mut => "&mut ",
|
|
||||||
};
|
|
||||||
steps -= 1;
|
steps -= 1;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
@ -345,8 +345,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
if annotation {
|
if annotation {
|
||||||
let suggest_annotation = match expr.peel_drop_temps().kind {
|
let suggest_annotation = match expr.peel_drop_temps().kind {
|
||||||
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, _) => "&",
|
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mutbl, _) => mutbl.ref_prefix_str(),
|
||||||
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, _) => "&mut ",
|
|
||||||
_ => return true,
|
_ => return true,
|
||||||
};
|
};
|
||||||
let mut tuple_indexes = Vec::new();
|
let mut tuple_indexes = Vec::new();
|
||||||
|
@ -170,14 +170,11 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||||||
let base_ty = target;
|
let base_ty = target;
|
||||||
|
|
||||||
target = self.tcx.mk_ref(region, ty::TypeAndMut { mutbl, ty: target });
|
target = self.tcx.mk_ref(region, ty::TypeAndMut { mutbl, ty: target });
|
||||||
let mutbl = match mutbl {
|
|
||||||
hir::Mutability::Not => AutoBorrowMutability::Not,
|
// Method call receivers are the primary use case
|
||||||
hir::Mutability::Mut => AutoBorrowMutability::Mut {
|
// for two-phase borrows.
|
||||||
// Method call receivers are the primary use case
|
let mutbl = AutoBorrowMutability::new(mutbl, AllowTwoPhase::Yes);
|
||||||
// for two-phase borrows.
|
|
||||||
allow_two_phase_borrow: AllowTwoPhase::Yes,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
adjustments.push(Adjustment {
|
adjustments.push(Adjustment {
|
||||||
kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)),
|
kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)),
|
||||||
target,
|
target,
|
||||||
@ -202,7 +199,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||||||
Some(probe::AutorefOrPtrAdjustment::ToConstPtr) => {
|
Some(probe::AutorefOrPtrAdjustment::ToConstPtr) => {
|
||||||
target = match target.kind() {
|
target = match target.kind() {
|
||||||
&ty::RawPtr(ty::TypeAndMut { ty, mutbl }) => {
|
&ty::RawPtr(ty::TypeAndMut { ty, mutbl }) => {
|
||||||
assert_eq!(mutbl, hir::Mutability::Mut);
|
assert!(mutbl.is_mut());
|
||||||
self.tcx.mk_ptr(ty::TypeAndMut { mutbl: hir::Mutability::Not, ty })
|
self.tcx.mk_ptr(ty::TypeAndMut { mutbl: hir::Mutability::Not, ty })
|
||||||
}
|
}
|
||||||
other => panic!("Cannot adjust receiver type {:?} to const ptr", other),
|
other => panic!("Cannot adjust receiver type {:?} to const ptr", other),
|
||||||
|
@ -5,7 +5,6 @@ use crate::{
|
|||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
use hir::HirId;
|
use hir::HirId;
|
||||||
use hir::ItemKind;
|
use hir::ItemKind;
|
||||||
use rustc_ast::Mutability;
|
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||||
@ -88,14 +87,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
let derefs = "*".repeat(pick.autoderefs);
|
let derefs = "*".repeat(pick.autoderefs);
|
||||||
|
|
||||||
let autoref = match pick.autoref_or_ptr_adjustment {
|
let autoref = match pick.autoref_or_ptr_adjustment {
|
||||||
Some(probe::AutorefOrPtrAdjustment::Autoref {
|
Some(probe::AutorefOrPtrAdjustment::Autoref { mutbl, .. }) => {
|
||||||
mutbl: Mutability::Mut,
|
mutbl.ref_prefix_str()
|
||||||
..
|
}
|
||||||
}) => "&mut ",
|
|
||||||
Some(probe::AutorefOrPtrAdjustment::Autoref {
|
|
||||||
mutbl: Mutability::Not,
|
|
||||||
..
|
|
||||||
}) => "&",
|
|
||||||
Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "",
|
Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "",
|
||||||
};
|
};
|
||||||
if let Ok(self_expr) = self.sess().source_map().span_to_snippet(self_expr.span)
|
if let Ok(self_expr) = self.sess().source_map().span_to_snippet(self_expr.span)
|
||||||
@ -386,8 +380,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
let derefs = "*".repeat(pick.autoderefs);
|
let derefs = "*".repeat(pick.autoderefs);
|
||||||
|
|
||||||
let autoref = match pick.autoref_or_ptr_adjustment {
|
let autoref = match pick.autoref_or_ptr_adjustment {
|
||||||
Some(probe::AutorefOrPtrAdjustment::Autoref { mutbl: Mutability::Mut, .. }) => "&mut ",
|
Some(probe::AutorefOrPtrAdjustment::Autoref { mutbl, .. }) => mutbl.ref_prefix_str(),
|
||||||
Some(probe::AutorefOrPtrAdjustment::Autoref { mutbl: Mutability::Not, .. }) => "&",
|
|
||||||
Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "",
|
Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1147,19 +1147,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
&& assoc.kind == ty::AssocKind::Fn
|
&& assoc.kind == ty::AssocKind::Fn
|
||||||
{
|
{
|
||||||
let sig = self.tcx.fn_sig(assoc.def_id);
|
let sig = self.tcx.fn_sig(assoc.def_id);
|
||||||
if let Some(first) = sig.inputs().skip_binder().get(0) {
|
sig.inputs().skip_binder().get(0).and_then(|first| if first.peel_refs() == rcvr_ty.peel_refs() {
|
||||||
if first.peel_refs() == rcvr_ty.peel_refs() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(if first.is_region_ptr() {
|
|
||||||
if first.is_mutable_ptr() { "&mut " } else { "&" }
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
None
|
||||||
}
|
} else {
|
||||||
|
Some(first.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()))
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -2627,11 +2619,7 @@ fn print_disambiguation_help<'tcx>(
|
|||||||
let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
|
let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
|
||||||
let args = format!(
|
let args = format!(
|
||||||
"({}{})",
|
"({}{})",
|
||||||
if rcvr_ty.is_region_ptr() {
|
rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()),
|
||||||
if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
},
|
|
||||||
std::iter::once(receiver)
|
std::iter::once(receiver)
|
||||||
.chain(args.iter())
|
.chain(args.iter())
|
||||||
.map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
|
.map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
|
||||||
|
@ -263,14 +263,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
let by_ref_binop = !op.node.is_by_value();
|
let by_ref_binop = !op.node.is_by_value();
|
||||||
if is_assign == IsAssign::Yes || by_ref_binop {
|
if is_assign == IsAssign::Yes || by_ref_binop {
|
||||||
if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].kind() {
|
if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].kind() {
|
||||||
let mutbl = match mutbl {
|
let mutbl = AutoBorrowMutability::new(*mutbl, AllowTwoPhase::Yes);
|
||||||
hir::Mutability::Not => AutoBorrowMutability::Not,
|
|
||||||
hir::Mutability::Mut => AutoBorrowMutability::Mut {
|
|
||||||
// Allow two-phase borrows for binops in initial deployment
|
|
||||||
// since they desugar to methods
|
|
||||||
allow_two_phase_borrow: AllowTwoPhase::Yes,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
let autoref = Adjustment {
|
let autoref = Adjustment {
|
||||||
kind: Adjust::Borrow(AutoBorrow::Ref(*region, mutbl)),
|
kind: Adjust::Borrow(AutoBorrow::Ref(*region, mutbl)),
|
||||||
target: method.sig.inputs()[0],
|
target: method.sig.inputs()[0],
|
||||||
@ -280,14 +273,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
if by_ref_binop {
|
if by_ref_binop {
|
||||||
if let ty::Ref(region, _, mutbl) = method.sig.inputs()[1].kind() {
|
if let ty::Ref(region, _, mutbl) = method.sig.inputs()[1].kind() {
|
||||||
let mutbl = match mutbl {
|
// Allow two-phase borrows for binops in initial deployment
|
||||||
hir::Mutability::Not => AutoBorrowMutability::Not,
|
// since they desugar to methods
|
||||||
hir::Mutability::Mut => AutoBorrowMutability::Mut {
|
let mutbl = AutoBorrowMutability::new(*mutbl, AllowTwoPhase::Yes);
|
||||||
// Allow two-phase borrows for binops in initial deployment
|
|
||||||
// since they desugar to methods
|
|
||||||
allow_two_phase_borrow: AllowTwoPhase::Yes,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
let autoref = Adjustment {
|
let autoref = Adjustment {
|
||||||
kind: Adjust::Borrow(AutoBorrow::Ref(*region, mutbl)),
|
kind: Adjust::Borrow(AutoBorrow::Ref(*region, mutbl)),
|
||||||
target: method.sig.inputs()[1],
|
target: method.sig.inputs()[1],
|
||||||
|
@ -702,7 +702,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut_var_suggestion = 'block: {
|
let mut_var_suggestion = 'block: {
|
||||||
if !matches!(mutbl, ast::Mutability::Mut) {
|
if mutbl.is_not() {
|
||||||
break 'block None;
|
break 'block None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -749,7 +749,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
format!("to take parameter `{binding}` by reference, move `&{mutability}` to the type"),
|
format!("to take parameter `{binding}` by reference, move `&{mutability}` to the type"),
|
||||||
vec![
|
vec![
|
||||||
(pat.span.until(inner.span), "".to_owned()),
|
(pat.span.until(inner.span), "".to_owned()),
|
||||||
(ty_span.shrink_to_lo(), format!("&{}", mutbl.prefix_str())),
|
(ty_span.shrink_to_lo(), mutbl.ref_prefix_str().to_owned()),
|
||||||
],
|
],
|
||||||
Applicability::MachineApplicable
|
Applicability::MachineApplicable
|
||||||
);
|
);
|
||||||
|
@ -15,7 +15,7 @@ use rustc_hir::intravisit::{self, Visitor};
|
|||||||
use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, Local, LocalSource};
|
use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, Local, LocalSource};
|
||||||
use rustc_middle::hir::nested_filter;
|
use rustc_middle::hir::nested_filter;
|
||||||
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
||||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
|
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
|
||||||
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
|
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
|
||||||
use rustc_middle::ty::{self, DefIdTree, InferConst};
|
use rustc_middle::ty::{self, DefIdTree, InferConst};
|
||||||
use rustc_middle::ty::{GenericArg, GenericArgKind, SubstsRef};
|
use rustc_middle::ty::{GenericArg, GenericArgKind, SubstsRef};
|
||||||
@ -508,10 +508,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
[
|
[
|
||||||
..,
|
..,
|
||||||
Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(_, mut_)), target: _ },
|
Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(_, mut_)), target: _ },
|
||||||
] => match mut_ {
|
] => hir::Mutability::from(*mut_).ref_prefix_str(),
|
||||||
AutoBorrowMutability::Mut { .. } => "&mut ",
|
|
||||||
AutoBorrowMutability::Not => "&",
|
|
||||||
},
|
|
||||||
_ => "",
|
_ => "",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1268,10 +1268,10 @@ declare_lint_pass!(MutableTransmutes => [MUTABLE_TRANSMUTES]);
|
|||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
|
impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
|
||||||
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
|
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
|
||||||
if let Some((&ty::Ref(_, _, from_mt), &ty::Ref(_, _, to_mt))) =
|
if let Some((&ty::Ref(_, _, from_mutbl), &ty::Ref(_, _, to_mutbl))) =
|
||||||
get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (ty1.kind(), ty2.kind()))
|
get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (ty1.kind(), ty2.kind()))
|
||||||
{
|
{
|
||||||
if to_mt == hir::Mutability::Mut && from_mt == hir::Mutability::Not {
|
if from_mutbl < to_mutbl {
|
||||||
cx.struct_span_lint(
|
cx.struct_span_lint(
|
||||||
MUTABLE_TRANSMUTES,
|
MUTABLE_TRANSMUTES,
|
||||||
expr.span,
|
expr.span,
|
||||||
|
@ -159,6 +159,18 @@ pub enum AutoBorrowMutability {
|
|||||||
Not,
|
Not,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AutoBorrowMutability {
|
||||||
|
/// Creates an `AutoBorrowMutability` from a mutability and allowance of two phase borrows.
|
||||||
|
///
|
||||||
|
/// Note that when `mutbl.is_not()`, `allow_two_phase_borrow` is ignored
|
||||||
|
pub fn new(mutbl: hir::Mutability, allow_two_phase_borrow: AllowTwoPhase) -> Self {
|
||||||
|
match mutbl {
|
||||||
|
hir::Mutability::Not => Self::Not,
|
||||||
|
hir::Mutability::Mut => Self::Mut { allow_two_phase_borrow },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<AutoBorrowMutability> for hir::Mutability {
|
impl From<AutoBorrowMutability> for hir::Mutability {
|
||||||
fn from(m: AutoBorrowMutability) -> Self {
|
fn from(m: AutoBorrowMutability) -> Self {
|
||||||
match m {
|
match m {
|
||||||
|
@ -169,7 +169,7 @@ impl<'hir> Sig for hir::Ty<'hir> {
|
|||||||
let mut prefix = "&".to_owned();
|
let mut prefix = "&".to_owned();
|
||||||
prefix.push_str(&lifetime.name.ident().to_string());
|
prefix.push_str(&lifetime.name.ident().to_string());
|
||||||
prefix.push(' ');
|
prefix.push(' ');
|
||||||
if let hir::Mutability::Mut = mt.mutbl {
|
if mt.mutbl.is_mut() {
|
||||||
prefix.push_str("mut ");
|
prefix.push_str("mut ");
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -332,7 +332,7 @@ impl<'hir> Sig for hir::Item<'hir> {
|
|||||||
match self.kind {
|
match self.kind {
|
||||||
hir::ItemKind::Static(ref ty, m, ref body) => {
|
hir::ItemKind::Static(ref ty, m, ref body) => {
|
||||||
let mut text = "static ".to_owned();
|
let mut text = "static ".to_owned();
|
||||||
if m == hir::Mutability::Mut {
|
if m.is_mut() {
|
||||||
text.push_str("mut ");
|
text.push_str("mut ");
|
||||||
}
|
}
|
||||||
let name = self.ident.to_string();
|
let name = self.ident.to_string();
|
||||||
|
@ -622,7 +622,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
match inner_ty.kind() {
|
match inner_ty.kind() {
|
||||||
ty::Str if *mutbl == hir::Mutability::Not => {
|
ty::Str if mutbl.is_not() => {
|
||||||
match ct.kind() {
|
match ct.kind() {
|
||||||
ty::ConstKind::Value(valtree) => {
|
ty::ConstKind::Value(valtree) => {
|
||||||
let slice =
|
let slice =
|
||||||
|
@ -1055,7 +1055,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
{
|
{
|
||||||
(
|
(
|
||||||
mk_result(old_pred.map_bound(|trait_pred| (trait_pred, *ty))),
|
mk_result(old_pred.map_bound(|trait_pred| (trait_pred, *ty))),
|
||||||
matches!(mutability, hir::Mutability::Mut),
|
mutability.is_mut(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(false, false)
|
(false, false)
|
||||||
@ -1344,7 +1344,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
.sess
|
.sess
|
||||||
.source_map()
|
.source_map()
|
||||||
.span_take_while(span, |c| c.is_whitespace() || *c == '&');
|
.span_take_while(span, |c| c.is_whitespace() || *c == '&');
|
||||||
if points_at_arg && mutability == hir::Mutability::Not && refs_number > 0 {
|
if points_at_arg && mutability.is_not() && refs_number > 0 {
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
sp,
|
sp,
|
||||||
"consider changing this borrow's mutability",
|
"consider changing this borrow's mutability",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user