rust-lang/rust · #162106
Helpful suggestions for incorrect address-of mutability (2)
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`.