]> git.lizzy.rs Git - rust.git/commitdiff
Tweak "non-primitive cast" error
authorEsteban Küber <esteban@kuber.com.ar>
Mon, 15 Jun 2020 04:36:25 +0000 (21:36 -0700)
committerEsteban Küber <esteban@kuber.com.ar>
Mon, 15 Jun 2020 15:57:20 +0000 (08:57 -0700)
- Suggest borrowing expression if it would allow cast to work.
- Suggest using `<Type>::from(<expr>)` when appropriate.
- Minor tweak to `;` typo suggestion.

Partily address #47136.

35 files changed:
src/libcore/convert/mod.rs
src/librustc_parse/parser/diagnostics.rs
src/librustc_span/symbol.rs
src/librustc_typeck/check/cast.rs
src/test/ui/cast/cast-from-nil.stderr
src/test/ui/cast/cast-to-bare-fn.stderr
src/test/ui/cast/cast-to-nil.stderr
src/test/ui/cast/cast-to-unsized-trait-object-suggestion.stderr
src/test/ui/closures/closure-no-fn-3.stderr
src/test/ui/coercion/coerce-to-bang-cast.stderr
src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr
src/test/ui/error-codes/E0604.stderr
src/test/ui/error-codes/E0605.stderr
src/test/ui/error-festival.stderr
src/test/ui/fat-ptr-cast.stderr
src/test/ui/issues/issue-10991.stderr
src/test/ui/issues/issue-16048.rs
src/test/ui/issues/issue-16048.stderr
src/test/ui/issues/issue-17441.stderr
src/test/ui/issues/issue-22289.stderr
src/test/ui/issues/issue-22312.rs
src/test/ui/issues/issue-22312.stderr
src/test/ui/issues/issue-2995.stderr
src/test/ui/issues/issue-45730.stderr
src/test/ui/mismatched_types/cast-rfc0401.stderr
src/test/ui/mismatched_types/issue-26480.stderr
src/test/ui/nonscalar-cast.fixed [new file with mode: 0644]
src/test/ui/nonscalar-cast.rs
src/test/ui/nonscalar-cast.stderr
src/test/ui/order-dependent-cast-inference.stderr
src/test/ui/tag-variant-cast-non-nullary.fixed [new file with mode: 0644]
src/test/ui/tag-variant-cast-non-nullary.rs
src/test/ui/tag-variant-cast-non-nullary.stderr
src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr
src/test/ui/uninhabited/uninhabited-enum-cast.stderr

index eef9ee7cb0093d811e92c6d3f5b9034e6ffc83e8..8ff1ced53b071840f45edad5e3c3184804fb90c2 100644 (file)
@@ -374,6 +374,7 @@ pub trait Into<T>: Sized {
 /// [`Into`]: trait.Into.html
 /// [`from`]: trait.From.html#tymethod.from
 /// [book]: ../../book/ch09-00-error-handling.html
+#[rustc_diagnostic_item = "from_trait"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(on(
     all(_Self = "&str", T = "std::string::String"),
index 660a63841bcef84680a86bc8a67364968616cedc..dafc0a9e048a45f6d7b0618b0ac2d6fcfa45a7a6 100644 (file)
@@ -961,7 +961,7 @@ pub(super) fn expect_semi(&mut self) -> PResult<'a, ()> {
             self.bump();
             let sp = self.prev_token.span;
             self.struct_span_err(sp, &msg)
-                .span_suggestion(sp, "change this to `;`", ";".to_string(), appl)
+                .span_suggestion_short(sp, "change this to `;`", ";".to_string(), appl)
                 .emit();
             return Ok(());
         } else if self.look_ahead(0, |t| {
index d165409696ecab418e73785329d5cfbc565a9b42..9925e631c5c205a11e890818d1f077c2cee77fc5 100644 (file)
         from_method,
         from_ok,
         from_usize,
+        from_trait,
         fundamental,
         future,
         Future,
index 46d6706cbf42925e674fb8d71c4b05ba94ea6e44..bad009f4039af230abd291d924784cccbd41aa12 100644 (file)
@@ -43,6 +43,7 @@
 use rustc_middle::ty::{self, Ty, TypeAndMut, TypeFoldable};
 use rustc_session::lint;
 use rustc_session::Session;
+use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
@@ -333,10 +334,11 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError) {
                     "only `u8` can be cast as `char`, not `{}`",
                     self.expr_ty
                 )
+                .span_label(self.span, "invalid cast")
                 .emit();
             }
             CastError::NonScalar => {
-                type_error_struct!(
+                let mut err = type_error_struct!(
                     fcx.tcx.sess,
                     self.span,
                     self.expr_ty,
@@ -344,12 +346,75 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError) {
                     "non-primitive cast: `{}` as `{}`",
                     self.expr_ty,
                     fcx.ty_to_string(self.cast_ty)
-                )
-                .note(
-                    "an `as` expression can only be used to convert between \
-                                         primitive types. Consider using the `From` trait",
-                )
-                .emit();
+                );
+                let mut sugg = None;
+                if let ty::Ref(reg, _, mutbl) = self.cast_ty.kind {
+                    if fcx
+                        .try_coerce(
+                            self.expr,
+                            fcx.tcx.mk_ref(reg, TypeAndMut { ty: self.expr_ty, mutbl }),
+                            self.cast_ty,
+                            AllowTwoPhase::No,
+                        )
+                        .is_ok()
+                    {
+                        sugg = Some(format!("&{}", mutbl.prefix_str()));
+                    }
+                }
+                if let Some(sugg) = sugg {
+                    err.span_label(self.span, "invalid cast");
+                    err.span_suggestion_verbose(
+                        self.expr.span.shrink_to_lo(),
+                        "borrow the value for the cast to be valid",
+                        sugg,
+                        Applicability::MachineApplicable,
+                    );
+                } else if !matches!(
+                    self.cast_ty.kind,
+                    ty::FnDef(..) | ty::FnPtr(..) | ty::Closure(..)
+                ) {
+                    let mut label = true;
+                    // Check `impl From<self.expr_ty> for self.cast_ty {}` for accurate suggestion:
+                    if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) {
+                        if let Some(from_trait) = fcx.tcx.get_diagnostic_item(sym::from_trait) {
+                            let ty = fcx.resolve_vars_if_possible(&self.cast_ty);
+                            // Erase regions to avoid panic in `prove_value` when calling
+                            // `type_implements_trait`.
+                            let ty = fcx.tcx.erase_regions(&ty);
+                            let expr_ty = fcx.resolve_vars_if_possible(&self.expr_ty);
+                            let expr_ty = fcx.tcx.erase_regions(&expr_ty);
+                            let ty_params = fcx.tcx.mk_substs_trait(expr_ty, &[]);
+                            // Check for infer types because cases like `Option<{integer}>` would
+                            // panic otherwise.
+                            if !expr_ty.has_infer_types()
+                                && fcx.tcx.type_implements_trait((
+                                    from_trait,
+                                    ty,
+                                    ty_params,
+                                    fcx.param_env,
+                                ))
+                            {
+                                label = false;
+                                err.span_suggestion(
+                                    self.span,
+                                    "consider using the `From` trait instead",
+                                    format!("{}::from({})", self.cast_ty, snippet),
+                                    Applicability::MaybeIncorrect,
+                                );
+                            }
+                        }
+                    }
+                    let msg = "an `as` expression can only be used to convert between primitive \
+                               types or to coerce to a specific trait object";
+                    if label {
+                        err.span_label(self.span, msg);
+                    } else {
+                        err.note(msg);
+                    }
+                } else {
+                    err.span_label(self.span, "invalid cast");
+                }
+                err.emit();
             }
             CastError::SizedUnsizedCast => {
                 use crate::structured_errors::{SizedUnsizedCastError, StructuredDiagnostic};
@@ -370,21 +435,22 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError) {
                 };
                 let mut err = struct_span_err!(
                     fcx.tcx.sess,
-                    self.span,
+                    if unknown_cast_to { self.cast_span } else { self.span },
                     E0641,
                     "cannot cast {} a pointer of an unknown kind",
                     if unknown_cast_to { "to" } else { "from" }
                 );
-                err.note(
-                    "the type information given here is insufficient to check whether \
-                          the pointer cast is valid",
-                );
                 if unknown_cast_to {
-                    err.span_suggestion_short(
-                        self.cast_span,
-                        "consider giving more type information",
-                        String::new(),
-                        Applicability::Unspecified,
+                    err.span_label(self.cast_span, "needs more type information");
+                    err.note(
+                        "the type information given here is insufficient to check whether \
+                        the pointer cast is valid",
+                    );
+                } else {
+                    err.span_label(
+                        self.span,
+                        "the type information given here is insufficient to check whether \
+                        the pointer cast is valid",
                     );
                 }
                 err.emit();
@@ -438,13 +504,16 @@ fn report_cast_to_unsized_type(&self, fcx: &FnCtxt<'a, 'tcx>) {
                     Ok(s) => {
                         err.span_suggestion(
                             self.cast_span,
-                            "try casting to a `Box` instead",
+                            "you can cast to a `Box` instead",
                             format!("Box<{}>", s),
                             Applicability::MachineApplicable,
                         );
                     }
                     Err(_) => {
-                        err.span_help(self.cast_span, &format!("did you mean `Box<{}>`?", tstr));
+                        err.span_help(
+                            self.cast_span,
+                            &format!("you might have meant `Box<{}>`", tstr),
+                        );
                     }
                 }
             }
index c8e3628a7ded89ac6e78e68e0b7cf26bc612ab6b..dab133cfb4b673f06c91352c9dc5cfdba9f72992 100644 (file)
@@ -2,9 +2,7 @@ error[E0605]: non-primitive cast: `()` as `u32`
   --> $DIR/cast-from-nil.rs:2:21
    |
 LL | fn main() { let u = (assert!(true) as u32); }
-   |                     ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+   |                     ^^^^^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error: aborting due to previous error
 
index 84933dca929a4f34637fcd397fa7895edf7c6224..d97b0c5f8aadc736c3fdc1c114e1c3c98b34f814 100644 (file)
@@ -2,17 +2,13 @@ error[E0605]: non-primitive cast: `fn(isize) {foo}` as `extern "C" fn() -> isize
   --> $DIR/cast-to-bare-fn.rs:5:13
    |
 LL |     let x = foo as extern "C" fn() -> isize;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
 
 error[E0605]: non-primitive cast: `u64` as `fn(isize) -> (isize, isize)`
   --> $DIR/cast-to-bare-fn.rs:7:13
    |
 LL |     let y = v as extern "Rust" fn(isize) -> (isize, isize);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
 
 error: aborting due to 2 previous errors
 
index 478f6b69dafc8c01161d14455c2a15258a9b86e5..29a9baffd71d7592268a801d2fcfd26d730aa78b 100644 (file)
@@ -2,9 +2,7 @@ error[E0605]: non-primitive cast: `u32` as `()`
   --> $DIR/cast-to-nil.rs:2:21
    |
 LL | fn main() { let u = 0u32 as (); }
-   |                     ^^^^^^^^^^
-   |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+   |                     ^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error: aborting due to previous error
 
index ffa02533d8b66db7869c917abf13b15225b8c4e8..9b86f8d4def86bd04fcb118e7fcfaeac652f21cf 100644 (file)
@@ -12,7 +12,7 @@ error[E0620]: cast to unsized type: `std::boxed::Box<{integer}>` as `dyn std::ma
 LL |     Box::new(1) as dyn Send;
    |     ^^^^^^^^^^^^^^^--------
    |                    |
-   |                    help: try casting to a `Box` instead: `Box<dyn Send>`
+   |                    help: you can cast to a `Box` instead: `Box<dyn Send>`
 
 error: aborting due to 2 previous errors
 
index ab6056b65473edd8241d651f6998f010a3ab697d..4b3b4be798fc1e541a2f7b98df22ef6c737b8db3 100644 (file)
@@ -2,9 +2,7 @@ error[E0605]: non-primitive cast: `[closure@$DIR/closure-no-fn-3.rs:6:27: 6:37 b
   --> $DIR/closure-no-fn-3.rs:6:27
    |
 LL |     let baz: fn() -> u8 = (|| { b }) as fn() -> u8;
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
 
 error: aborting due to previous error
 
index ff30ebc09c63acf5b43aee6dadee8f8c63160660..d3adbd5158dbbbffc6f0a72484039f9c5819c9c0 100644 (file)
@@ -2,17 +2,13 @@ error[E0605]: non-primitive cast: `i32` as `!`
   --> $DIR/coerce-to-bang-cast.rs:6:13
    |
 LL |     let y = {return; 22} as !;
-   |             ^^^^^^^^^^^^^^^^^
-   |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+   |             ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error[E0605]: non-primitive cast: `i32` as `!`
   --> $DIR/coerce-to-bang-cast.rs:11:13
    |
 LL |     let y = 22 as !;
-   |             ^^^^^^^
-   |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+   |             ^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error: aborting due to 2 previous errors
 
index 5b2c4116c4b1dc9aa7c44b24bb6c207b3235e175..e4d256c0ad19201b93438af57daec0badf1fb1d3 100644 (file)
@@ -16,7 +16,7 @@ error[E0604]: only `u8` can be cast as `char`, not `i8`
   --> $DIR/const-eval-overflow-4b.rs:25:13
    |
 LL |     : [u32; 5i8 as char as usize]
-   |             ^^^^^^^^^^^
+   |             ^^^^^^^^^^^ invalid cast
 
 error: aborting due to 3 previous errors
 
index 5861bdcb7a953c7cc07fd36b9bc491159991c87b..18835310bd5e87ec6541fa49df36540a60be1c64 100644 (file)
@@ -2,7 +2,7 @@ error[E0604]: only `u8` can be cast as `char`, not `u32`
   --> $DIR/E0604.rs:2:5
    |
 LL |     1u32 as char;
-   |     ^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^ invalid cast
 
 error: aborting due to previous error
 
index 95e899db8b7e94db190ec8016beb412ea848e979..f23d2008e0b5f2c4cd38904b074ac9c48bc5747c 100644 (file)
@@ -2,17 +2,13 @@ error[E0605]: non-primitive cast: `u8` as `std::vec::Vec<u8>`
   --> $DIR/E0605.rs:3:5
    |
 LL |     x as Vec<u8>;
-   |     ^^^^^^^^^^^^
-   |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+   |     ^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error[E0605]: non-primitive cast: `*const u8` as `&u8`
   --> $DIR/E0605.rs:6:5
    |
 LL |     v as &u8;
-   |     ^^^^^^^^
-   |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+   |     ^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error: aborting due to 2 previous errors
 
index 7f524230ef00633a7ecc45a9a0273a596744be5c..905195d4ad963fe4b963a1dc31e03a1b9a115a27 100644 (file)
@@ -42,15 +42,13 @@ error[E0604]: only `u8` can be cast as `char`, not `u32`
   --> $DIR/error-festival.rs:25:5
    |
 LL |     0u32 as char;
-   |     ^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^ invalid cast
 
 error[E0605]: non-primitive cast: `u8` as `std::vec::Vec<u8>`
   --> $DIR/error-festival.rs:29:5
    |
 LL |     x as Vec<u8>;
-   |     ^^^^^^^^^^^^
-   |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+   |     ^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error[E0054]: cannot cast as `bool`
   --> $DIR/error-festival.rs:33:24
index 93e1471838f72acdf8d97aa1bc05924c15275d52..56d5a26beb04ee0d37e823799155373569c068a4 100644 (file)
@@ -34,9 +34,7 @@ error[E0605]: non-primitive cast: `std::boxed::Box<[i32]>` as `usize`
   --> $DIR/fat-ptr-cast.rs:14:5
    |
 LL |     b as usize;
-   |     ^^^^^^^^^^
-   |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+   |     ^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error[E0606]: casting `*const [i32]` as `usize` is invalid
   --> $DIR/fat-ptr-cast.rs:15:5
index f12539b47cf44c15b9a23201f77215e9f1efcc38..5b8a1823386936929c5200ea19a420515be3608e 100644 (file)
@@ -2,9 +2,7 @@ error[E0605]: non-primitive cast: `()` as `usize`
   --> $DIR/issue-10991.rs:3:14
    |
 LL |     let _t = nil as usize;
-   |              ^^^^^^^^^^^^
-   |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+   |              ^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error: aborting due to previous error
 
index 7d24f3a40a742e2669664ff54553ceae0d400e69..eaf6acff26bf35cf92b704ebca96c4c0bdaaebb0 100644 (file)
@@ -18,12 +18,12 @@ fn new(buf: &'a mut [u8]) -> Foo<'a> {
 }
 
 impl<'a> NoLifetime for Foo<'a> {
-    fn get<'p, T : Test<'a>>(&self) -> T {
+    fn get<'p, T: Test<'a> + From<Foo<'a>>>(&self) -> T {
     //~^ ERROR E0195
     //~| NOTE lifetimes do not match method in trait
         return *self as T;
         //~^ ERROR non-primitive cast: `Foo<'a>` as `T`
-        //~| NOTE an `as` expression can only be used to convert between primitive types.
+        //~| NOTE an `as` expression can only be used to convert between primitive types
     }
 }
 
index a137bcdf1915edd39ec053786aa664e5bc76a514..73610942d7a7ed358ded73169f73004ff5bfac24 100644 (file)
@@ -4,16 +4,16 @@ error[E0195]: lifetime parameters or bounds on method `get` do not match the tra
 LL |     fn get<'p, T : Test<'p>>(&self) -> T;
    |           ------------------ lifetimes in impl do not match this method in trait
 ...
-LL |     fn get<'p, T : Test<'a>>(&self) -> T {
-   |           ^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
+LL |     fn get<'p, T: Test<'a> + From<Foo<'a>>>(&self) -> T {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
 
 error[E0605]: non-primitive cast: `Foo<'a>` as `T`
   --> $DIR/issue-16048.rs:24:16
    |
 LL |         return *self as T;
-   |                ^^^^^^^^^^
+   |                ^^^^^^^^^^ help: consider using the `From` trait instead: `T::from(*self)`
    |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+   = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error: aborting due to 2 previous errors
 
index 0ab035515a0515220d72b1824996c69d6641681c..b63a3995d255dd523a3518f7e891845f57bd5069 100644 (file)
@@ -16,7 +16,7 @@ error[E0620]: cast to unsized type: `std::boxed::Box<usize>` as `dyn std::fmt::D
 LL |     let _bar = Box::new(1_usize) as dyn std::fmt::Debug;
    |                ^^^^^^^^^^^^^^^^^^^^^-------------------
    |                                     |
-   |                                     help: try casting to a `Box` instead: `Box<dyn std::fmt::Debug>`
+   |                                     help: you can cast to a `Box` instead: `Box<dyn std::fmt::Debug>`
 
 error[E0620]: cast to unsized type: `usize` as `dyn std::fmt::Debug`
   --> $DIR/issue-17441.rs:8:16
index cc7ace30cabef108eff333f1c6b428fa847a885c..4c35deb1fbe4e0b566c14fc9026d09f5883cfff3 100644 (file)
@@ -2,9 +2,12 @@ error[E0605]: non-primitive cast: `i32` as `&(dyn std::any::Any + 'static)`
   --> $DIR/issue-22289.rs:2:5
    |
 LL |     0 as &dyn std::any::Any;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
    |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+help: borrow the value for the cast to be valid
+   |
+LL |     &0 as &dyn std::any::Any;
+   |     ^
 
 error: aborting due to previous error
 
index 250fec2588702c0e94ec3155b40e36e2a86f2202..4e359b3412a71e8400aca880fea2c4cadf9f93f6 100644 (file)
@@ -1,6 +1,6 @@
 use std::ops::Index;
 
-pub trait Array2D: Index<usize> {
+pub trait Array2D: Index<usize> + Sized {
     fn rows(&self) -> usize;
     fn columns(&self) -> usize;
     fn get<'a>(&'a self, y: usize, x: usize) -> Option<&'a <Self as Index<usize>>::Output> {
index fc32fd376b75a9eb023d3fc8b5e54dc184bc19fc..28564b074633bf2fd402729008e8f39644b90f7d 100644 (file)
@@ -2,9 +2,12 @@ error[E0605]: non-primitive cast: `Self` as `&dyn std::ops::Index<usize, Output
   --> $DIR/issue-22312.rs:11:24
    |
 LL |         let indexer = &(*self as &dyn Index<usize, Output = <Self as Index<usize>>::Output>);
-   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
    |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+help: borrow the value for the cast to be valid
+   |
+LL |         let indexer = &(&*self as &dyn Index<usize, Output = <Self as Index<usize>>::Output>);
+   |                         ^
 
 error: aborting due to previous error
 
index c316780d5f6a5c972bed74f0a84254b6dbeea847..9f5968399a37d8a730bced19a959071fba7e0bf9 100644 (file)
@@ -2,9 +2,7 @@ error[E0605]: non-primitive cast: `*const isize` as `&isize`
   --> $DIR/issue-2995.rs:2:22
    |
 LL |     let _q: &isize = p as &isize;
-   |                      ^^^^^^^^^^^
-   |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+   |                      ^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error: aborting due to previous error
 
index d4ddba52df14a9f9f812dc3621361a6bf39733a7..d00f3d91b49da640f3a063a9c071155fc7e663ae 100644 (file)
@@ -1,30 +1,24 @@
 error[E0641]: cannot cast to a pointer of an unknown kind
-  --> $DIR/issue-45730.rs:3:23
+  --> $DIR/issue-45730.rs:3:28
    |
 LL |     let x: *const _ = 0 as _;
-   |                       ^^^^^-
-   |                            |
-   |                            help: consider giving more type information
+   |                            ^ needs more type information
    |
    = note: the type information given here is insufficient to check whether the pointer cast is valid
 
 error[E0641]: cannot cast to a pointer of an unknown kind
-  --> $DIR/issue-45730.rs:5:23
+  --> $DIR/issue-45730.rs:5:28
    |
 LL |     let x: *const _ = 0 as *const _;
-   |                       ^^^^^--------
-   |                            |
-   |                            help: consider giving more type information
+   |                            ^^^^^^^^ needs more type information
    |
    = note: the type information given here is insufficient to check whether the pointer cast is valid
 
 error[E0641]: cannot cast to a pointer of an unknown kind
-  --> $DIR/issue-45730.rs:8:13
+  --> $DIR/issue-45730.rs:8:44
    |
 LL |     let x = 0 as *const i32 as *const _ as *mut _;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------
-   |                                            |
-   |                                            help: consider giving more type information
+   |                                            ^^^^^^ needs more type information
    |
    = note: the type information given here is insufficient to check whether the pointer cast is valid
 
index f94dfd100a6f4dff17580d211659a5e2ee014fd3..95936de218b8fe5d25de453501655ddde3c5ba76 100644 (file)
@@ -24,41 +24,31 @@ error[E0605]: non-primitive cast: `*const u8` as `&u8`
   --> $DIR/cast-rfc0401.rs:29:13
    |
 LL |     let _ = v as &u8;
-   |             ^^^^^^^^
-   |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+   |             ^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error[E0605]: non-primitive cast: `*const u8` as `E`
   --> $DIR/cast-rfc0401.rs:30:13
    |
 LL |     let _ = v as E;
-   |             ^^^^^^
-   |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+   |             ^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error[E0605]: non-primitive cast: `*const u8` as `fn()`
   --> $DIR/cast-rfc0401.rs:31:13
    |
 LL |     let _ = v as fn();
-   |             ^^^^^^^^^
-   |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+   |             ^^^^^^^^^ invalid cast
 
 error[E0605]: non-primitive cast: `*const u8` as `(u32,)`
   --> $DIR/cast-rfc0401.rs:32:13
    |
 LL |     let _ = v as (u32,);
-   |             ^^^^^^^^^^^
-   |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+   |             ^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error[E0605]: non-primitive cast: `std::option::Option<&*const u8>` as `*const u8`
   --> $DIR/cast-rfc0401.rs:33:13
    |
 LL |     let _ = Some(&v) as *const u8;
-   |             ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+   |             ^^^^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error[E0606]: casting `*const u8` as `f32` is invalid
   --> $DIR/cast-rfc0401.rs:35:13
@@ -102,7 +92,7 @@ error[E0604]: only `u8` can be cast as `char`, not `u32`
   --> $DIR/cast-rfc0401.rs:41:13
    |
 LL |     let _ = 0x61u32 as char;
-   |             ^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^^ invalid cast
 
 error[E0606]: casting `bool` as `f32` is invalid
   --> $DIR/cast-rfc0401.rs:43:13
index 69a9d03e474bab2b1c85316a787eaaa346d833d3..d39b0a3207763a37eb1f89165afd06be0bd5dcca 100644 (file)
@@ -17,12 +17,11 @@ error[E0605]: non-primitive cast: `{integer}` as `()`
   --> $DIR/issue-26480.rs:22:19
    |
 LL |     ($x:expr) => ($x as ())
-   |                   ^^^^^^^^
+   |                   ^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 ...
 LL |     cast!(2);
    |     --------- in this macro invocation
    |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/nonscalar-cast.fixed b/src/test/ui/nonscalar-cast.fixed
new file mode 100644 (file)
index 0000000..0a4b984
--- /dev/null
@@ -0,0 +1,16 @@
+// run-rustfix
+
+#[derive(Debug)]
+struct Foo {
+    x: isize
+}
+
+impl From<Foo> for isize {
+    fn from(val: Foo) -> isize {
+        val.x
+    }
+}
+
+fn main() {
+    println!("{}", isize::from(Foo { x: 1 })); //~ non-primitive cast: `Foo` as `isize` [E0605]
+}
index 7e6f1fd038fb7a0bb0ba20cbfe9e33e9894f1156..59fcf09666b24f32aa36a63b8029b8acd1064dba 100644 (file)
@@ -1,8 +1,16 @@
+// run-rustfix
+
 #[derive(Debug)]
 struct Foo {
     x: isize
 }
 
+impl From<Foo> for isize {
+    fn from(val: Foo) -> isize {
+        val.x
+    }
+}
+
 fn main() {
     println!("{}", Foo { x: 1 } as isize); //~ non-primitive cast: `Foo` as `isize` [E0605]
 }
index 9338688b037ffd7f798d720f347dec311c56e11a..2a7037121876d8725202c24c4131c23e8b811df4 100644 (file)
@@ -1,10 +1,10 @@
 error[E0605]: non-primitive cast: `Foo` as `isize`
-  --> $DIR/nonscalar-cast.rs:7:20
+  --> $DIR/nonscalar-cast.rs:15:20
    |
 LL |     println!("{}", Foo { x: 1 } as isize);
-   |                    ^^^^^^^^^^^^^^^^^^^^^
+   |                    ^^^^^^^^^^^^^^^^^^^^^ help: consider using the `From` trait instead: `isize::from(Foo { x: 1 })`
    |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+   = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error: aborting due to previous error
 
index ad50b415869dd6f322e2b567dcf5dc5012541fc8..9f4ac0fea36ef03ba41bb048a197ad87627bb0af 100644 (file)
@@ -1,10 +1,8 @@
 error[E0641]: cannot cast to a pointer of an unknown kind
-  --> $DIR/order-dependent-cast-inference.rs:5:17
+  --> $DIR/order-dependent-cast-inference.rs:5:22
    |
 LL |     let mut y = 0 as *const _;
-   |                 ^^^^^--------
-   |                      |
-   |                      help: consider giving more type information
+   |                      ^^^^^^^^ needs more type information
    |
    = note: the type information given here is insufficient to check whether the pointer cast is valid
 
diff --git a/src/test/ui/tag-variant-cast-non-nullary.fixed b/src/test/ui/tag-variant-cast-non-nullary.fixed
new file mode 100644 (file)
index 0000000..53e68c2
--- /dev/null
@@ -0,0 +1,20 @@
+// run-rustfix
+#![allow(dead_code, unused_variables)]
+enum NonNullary {
+    Nullary,
+    Other(isize),
+}
+
+impl From<NonNullary> for isize {
+    fn from(val: NonNullary) -> isize {
+        match val {
+            NonNullary::Nullary => 0,
+            NonNullary::Other(i) => i,
+        }
+    }
+}
+
+fn main() {
+    let v = NonNullary::Nullary;
+    let val = isize::from(v); //~ ERROR non-primitive cast: `NonNullary` as `isize` [E0605]
+}
index bb34e82cdca374cbef1f97d6536add58f46c1203..0d0c6188ad114f2d3cb5c8efd121092f228ab320 100644 (file)
@@ -1,8 +1,19 @@
+// run-rustfix
+#![allow(dead_code, unused_variables)]
 enum NonNullary {
     Nullary,
     Other(isize),
 }
 
+impl From<NonNullary> for isize {
+    fn from(val: NonNullary) -> isize {
+        match val {
+            NonNullary::Nullary => 0,
+            NonNullary::Other(i) => i,
+        }
+    }
+}
+
 fn main() {
     let v = NonNullary::Nullary;
     let val = v as isize; //~ ERROR non-primitive cast: `NonNullary` as `isize` [E0605]
index 87ec20f20d789de2925220635f5b6848397a1a91..ae2f5a7aead552f9346eb0a231865d2d2690ce62 100644 (file)
@@ -1,10 +1,10 @@
 error[E0605]: non-primitive cast: `NonNullary` as `isize`
-  --> $DIR/tag-variant-cast-non-nullary.rs:8:15
+  --> $DIR/tag-variant-cast-non-nullary.rs:19:15
    |
 LL |     let val = v as isize;
-   |               ^^^^^^^^^^
+   |               ^^^^^^^^^^ help: consider using the `From` trait instead: `isize::from(v)`
    |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+   = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error: aborting due to previous error
 
index 70c99c944d654d8f142f6c6992274b9f31b7cc45..360633bba622b9cf462f090b39729fa783a18fd8 100644 (file)
@@ -16,9 +16,7 @@ error[E0605]: non-primitive cast: `NoReveal` as `&'static str`
   --> $DIR/never_reveal_concrete_type.rs:14:13
    |
 LL |     let _ = x as &'static str;
-   |             ^^^^^^^^^^^^^^^^^
-   |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+   |             ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error: aborting due to 2 previous errors
 
index a39af7832f8c959600b5726f2b91f0a920157289..a9f10dfec994a9e4c7a71ca776e2fca44abb058f 100644 (file)
@@ -2,9 +2,7 @@ error[E0605]: non-primitive cast: `E` as `isize`
   --> $DIR/uninhabited-enum-cast.rs:4:20
    |
 LL |     println!("{}", (e as isize).to_string());
-   |                    ^^^^^^^^^^^^
-   |
-   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+   |                    ^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error: aborting due to previous error