rust-lang/rust · #162106

Helpful suggestions for incorrect address-of mutability (2)

TirushOne · merged Oct 9, 20264 files · 177 + / 17 −
compiler/rustc_hir_typeck/src/diagnostics.rs24 + / 0 −
@@ -679,6 +679,30 @@ pub(crate) struct SuggestPtrNullMut {     pub span: Span, } +#[derive(Subdiagnostic)]+#[suggestion(+    "consider using `&mut` instead",+    applicability = "maybe-incorrect",+    style = "verbose",+    code = "&mut "+)]+pub(crate) struct SuggestRefMut {+    #[primary_span]+    pub span: Span,+}++#[derive(Subdiagnostic)]+#[suggestion(+    "consider using `&raw mut` instead",+    applicability = "maybe-incorrect",+    style = "verbose",+    code = "&raw mut "+)]+pub(crate) struct SuggestRawMut {+    #[primary_span]+    pub span: Span,+}+ #[derive(Diagnostic)] #[diag(     "trivial {$numeric ->
compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs50 + / 11 −
@@ -37,7 +37,7 @@ use crate::Expectation::*; use crate::TupleArgumentsFlag::*; use crate::callee::SplatLoweringInfo; use crate::coercion::CoerceMany;-use crate::diagnostics::{ExprParenthesesNeeded, SuggestPtrNullMut};+use crate::diagnostics::{ExprParenthesesNeeded, SuggestPtrNullMut, SuggestRawMut, SuggestRefMut}; use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx}; use crate::gather_locals::Declaration; use crate::inline_asm::InlineAsmCtxt;@@ -982,23 +982,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {         err.emit()     } -    fn suggest_ptr_null_mut(+    fn suggest_mut_addr(         &self,         expected_ty: Ty<'tcx>,         provided_ty: Ty<'tcx>,         arg: &hir::Expr<'tcx>,         err: &mut Diag<'_>,     ) {-        if let ty::RawPtr(_, hir::Mutability::Mut) = expected_ty.kind()-            && let ty::RawPtr(_, hir::Mutability::Not) = provided_ty.kind()-            && let hir::ExprKind::Call(callee, _) = arg.kind-            && let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = callee.kind-            && let Res::Def(_, def_id) = path.res-            && self.tcx.get_diagnostic_item(sym::ptr_null) == Some(def_id)-        {+        match (expected_ty.kind(), provided_ty.kind(), arg.kind) {             // The user provided `ptr::null()`, but the function expects             // `ptr::null_mut()`.-            err.subdiagnostic(SuggestPtrNullMut { span: arg.span });+            (+                ty::RawPtr(_, hir::Mutability::Mut),+                ty::RawPtr(_, hir::Mutability::Not),+                hir::ExprKind::Call(callee, _),+            ) if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = callee.kind+                && let Res::Def(_, def_id) = path.res+                && self.tcx.get_diagnostic_item(sym::ptr_null) == Some(def_id) =>+            {+                err.subdiagnostic(SuggestPtrNullMut { span: arg.span });+            }+            // &mut T expected, &T or *const/mut T found+            // suggestion: replace `&` or `&raw const/mut` with `&mut`+            (+                ty::Ref(_, expected_ty, hir::Mutability::Mut),+                ty::Ref(_, provided_ty, hir::Mutability::Not),+                hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, expr),+            )+            | (+                ty::Ref(_, expected_ty, hir::Mutability::Mut),+                ty::RawPtr(provided_ty, _),+                hir::ExprKind::AddrOf(hir::BorrowKind::Raw, _, expr),+            ) if expected_ty == provided_ty => {+                let span = arg.span.until(expr.span);+                err.subdiagnostic(SuggestRefMut { span });+            }+            // *mut T expected, *const T found+            // suggestion: replace `&raw const` with `&raw mut`+            (+                ty::RawPtr(expected_ty, hir::Mutability::Mut),+                ty::RawPtr(provided_ty, hir::Mutability::Not),+                hir::ExprKind::AddrOf(hir::BorrowKind::Raw, hir::Mutability::Not, expr),+            ) if expected_ty == provided_ty => {+                let span = arg.span.until(expr.span);+                err.subdiagnostic(SuggestRawMut { span });+            }+            // *mut T expected, &T found+            // suggestion: replace `&` `&mut`+            (+                ty::RawPtr(expected_ty, hir::Mutability::Mut),+                ty::Ref(_, provided_ty, hir::Mutability::Not),+                hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, expr),+            ) if expected_ty == provided_ty => {+                let span = arg.span.until(expr.span);+                err.subdiagnostic(SuggestRefMut { span });+            }+            _ => {}         }     } @@ -2491,7 +2530,7 @@ impl<'a, 'tcx> FnCallDiagCtxt<'a, 'tcx> {                 );             } -            self.suggest_ptr_null_mut(+            self.suggest_mut_addr(                 expected_ty,                 provided_ty,                 self.provided_args[provided_idx],
tests/ui/span/coerce-suggestions.rs10 + / 0 −
@@ -2,6 +2,7 @@ fn test(_x: &mut String) {}  fn test2(_x: &mut i32) {} +fn test3(_x: *mut String) {}  fn main() {     let x: usize = String::new();@@ -11,9 +12,18 @@ fn main() {     let y = String::new();     test(&y);     //~^ ERROR E0308+    test(&raw const y);+    //~^ ERROR E0308+    test(&raw mut y);+    //~^ ERROR E0308     test2(&y);     //~^ ERROR E0308     let s = &mut String::new();     s = format!("foo");     //~^ ERROR E0308+    let s = String::new();+    test3(&raw const s);+    //~^ ERROR E0308+    test3(&s);+    //~^ ERROR E0308 }
tests/ui/span/coerce-suggestions.stderr93 + / 6 −
@@ -1,13 +1,13 @@ error[E0308]: mismatched types-  --> $DIR/coerce-suggestions.rs:7:20+  --> $DIR/coerce-suggestions.rs:8:20    | LL |     let x: usize = String::new();    |            -----   ^^^^^^^^^^^^^ expected `usize`, found `String`    |            |    |            expected due to this  error[E0308]: mismatched types-  --> $DIR/coerce-suggestions.rs:9:19+  --> $DIR/coerce-suggestions.rs:10:19    | LL |     let x: &str = String::new();    |            ----   ^^^^^^^^^^^^^ expected `&str`, found `String`@@ -20,7 +20,7 @@ LL |     let x: &str = &String::new();    |                   +  error[E0308]: mismatched types-  --> $DIR/coerce-suggestions.rs:12:10+  --> $DIR/coerce-suggestions.rs:13:10    | LL |     test(&y);    |     ---- ^^ types differ in mutability@@ -34,9 +34,55 @@ note: function defined here    | LL | fn test(_x: &mut String) {}    |    ^^^^ ---------------+help: consider using `&mut` instead+   |+LL |     test(&mut y);+   |           +++  error[E0308]: mismatched types-  --> $DIR/coerce-suggestions.rs:14:11+  --> $DIR/coerce-suggestions.rs:15:10+   |+LL |     test(&raw const y);+   |     ---- ^^^^^^^^^^^^ expected `&mut String`, found `*const String`+   |     |+   |     arguments to this function are incorrect+   |+   = note: expected mutable reference `&mut String`+                    found raw pointer `*const String`+note: function defined here+  --> $DIR/coerce-suggestions.rs:1:4+   |+LL | fn test(_x: &mut String) {}+   |    ^^^^ ---------------+help: consider using `&mut` instead+   |+LL -     test(&raw const y);+LL +     test(&mut y);+   |++error[E0308]: mismatched types+  --> $DIR/coerce-suggestions.rs:17:10+   |+LL |     test(&raw mut y);+   |     ---- ^^^^^^^^^^ expected `&mut String`, found `*mut String`+   |     |+   |     arguments to this function are incorrect+   |+   = note: expected mutable reference `&mut String`+                    found raw pointer `*mut String`+note: function defined here+  --> $DIR/coerce-suggestions.rs:1:4+   |+LL | fn test(_x: &mut String) {}+   |    ^^^^ ---------------+help: consider using `&mut` instead+   |+LL -     test(&raw mut y);+LL +     test(&mut y);+   |++error[E0308]: mismatched types+  --> $DIR/coerce-suggestions.rs:19:11    | LL |     test2(&y);    |     ----- ^^ types differ in mutability@@ -52,11 +98,52 @@ LL | fn test2(_x: &mut i32) {}    |    ^^^^^ ------------  error[E0308]: mismatched types-  --> $DIR/coerce-suggestions.rs:17:9+  --> $DIR/coerce-suggestions.rs:22:9    | LL |     s = format!("foo");    |         ^^^^^^^^^^^^^^ expected `&mut String`, found `String` -error: aborting due to 5 previous errors+error[E0308]: mismatched types+  --> $DIR/coerce-suggestions.rs:25:11+   |+LL |     test3(&raw const s);+   |     ----- ^^^^^^^^^^^^ types differ in mutability+   |     |+   |     arguments to this function are incorrect+   |+   = note: expected raw pointer `*mut String`+              found raw pointer `*const String`+note: function defined here+  --> $DIR/coerce-suggestions.rs:5:4+   |+LL | fn test3(_x: *mut String) {}+   |    ^^^^^ ---------------+help: consider using `&raw mut` instead+   |+LL -     test3(&raw const s);+LL +     test3(&raw mut s);+   |++error[E0308]: mismatched types+  --> $DIR/coerce-suggestions.rs:27:11+   |+LL |     test3(&s);+   |     ----- ^^ types differ in mutability+   |     |+   |     arguments to this function are incorrect+   |+   = note: expected raw pointer `*mut String`+                found reference `&String`+note: function defined here+  --> $DIR/coerce-suggestions.rs:5:4+   |+LL | fn test3(_x: *mut String) {}+   |    ^^^^^ ---------------+help: consider using `&mut` instead+   |+LL |     test3(&mut s);+   |            +++++error: aborting due to 9 previous errors  For more information about this error, try `rustc --explain E0308`.