Rust: non-scalar cast: error message is unclear

Created on 25 Jan 2016  路  15Comments  路  Source: rust-lang/rust

C:\CI-Cor\ks\rust-encoding>cargo build
   Compiling encoding v0.3.0-dev (file:///C:/CI-Cor/ks/rust-encoding)
src\indexes.rs:316:54: 316:63 error: mismatched types:
 expected `T`,
    found `u32`
(expected type parameter,
    found u32) [E0308]
src\indexes.rs:316     let offsetPos = BinarySearch(plane, left, right, codepoint);
                                                                        ^~~~~~~~~
src\indexes.rs:316:54: 316:63 help: run `rustc --explain E0308` to see a detailed explanation
src\indexes.rs:322:37: 322:60 error: non-scalar cast: `T` as `u32`
src\indexes.rs:322     let offset = codepoint as u32 - plane[offsetPos] as u32;
                                                       ^~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 2 previous errors
Could not compile `encoding`.

To learn more, run the command again with --verbose.
pub fn indexOfCodePointImpl<T:Ord>(plane: &'static[T], offsets:&[u16], left:usize, right:usize, codepoint: u32) -> u16 {
    let offsetPos = BinarySearch(plane, left, right, codepoint);
    if offsetPos == 0xffff {
        return 0xffff;
    }
    let baseOffset = offsets[offsetPos] as u32;
    let maxOffset = offsets[offsetPos + 1] as u32;
    let offset = codepoint as u32 - plane[offsetPos] as u32;
    let finalOffset = baseOffset + offset as u32;
    if finalOffset >= maxOffset {
        return 0xffff;
    }
    return finalOffset as u16;
}

A-diagnostics

Most helpful comment

I get that _now_, but the error message could be less confusing, perhaps just saying "unable to cast between these types" instead of "non-scalar cast", which is some jargon I am not familiar with.

All 15 comments

The type of plane[offsetPos] is T, so the compiler is complaining that you are trying to cast a T to a u32 in the expression plane[offsetPos] as u32.

You may have meant to do:

let offset = codepoint as u32 - offsets[offsetPos] as u32;

Not a bug in rustc. Error looks quite clear to me. Closing.

Huh, now that it's been pointed out as confusing, I agree: I wouldn't call an error message that just says "non-scalar cast" clear. It's quite jargon-y, and could _easily_ be improved with a note or help such as:

an as expression can only be used to convert between primitive types. Consider using the From trait.

Minimal example:

fn foo<T>(x: T) -> u32 {
    x as u32
}

fn main() {}

Of course, using the From trait would not have helped here - the problem is that the code is broken. Maybe just use "invalid cast" for all broken casts?

Also, casts are quite often used for type ascription - at least until :-ascription stabilizes., so that is not exact.

I don't think we need to make sure the error message precisely covers every case: it is certainly reasonable for some helps/notes to just be heuristics for the most common cases in which an error occurs (but obviously being more precise is better). Especially with something like this, where someone might guess at using as for a random conversion, and so guiding those users toward something that actually might work is what help is designed for. Maybe you'd be happier if the compiler just said something like:

help: if this conversion is on purpose, consider implementing the From trait and calling <typename>::from .

I don't think that would have helped here.

Sorry, I may have been confusing: I see that my original message only implied that the message should be changed to not be so jargon-y, it didn't actually say that removing/expanding the "non-scalar cast" part would be good in addition to adding more help to handle other cases.

[I don't care either way]

That's confusing so I can not do something with integer overrides.
For example, even usize::from also broken, because the usize's from doesn't implemented.

I'd also like to say that I'm getting a confusing error when I'm trying to cast

src/lib.rs:29:23: 29:78 error: non-scalar cast: `fn(*mut std::os::kernel::Struct_file, *const i8, u64, *mut i64) -> i64 {rust_dev_write}` as `unsafe extern "C" fn(*mut std::os::kernel::Struct_file, *const i8, u64, *mut i64) -> i64`
src/lib.rs:29     fops.write = Some(rust_dev_write as unsafe extern "C" fn(_, _, _, _) -> _);

and I'm not sure if it's because of the unsafe or the extern "C" or what. More details on the error than "non-scalar cast" would be nice.

Even just a rustc --explain EXXXXX for what scalar values means would be nice.

@tbelaire

It's because of the extern "C" vs. non-extern-C. This is the default error message for broken casts.

I get that _now_, but the error message could be less confusing, perhaps just saying "unable to cast between these types" instead of "non-scalar cast", which is some jargon I am not familiar with.

By luck, it seems I fixed this issue. I'll link to the PR once opened.

Was this page helpful?
0 / 5 - 0 ratings