Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type assertion error i8 vs u8 #60226

Closed
bgrieder opened this issue Apr 24, 2019 · 6 comments
Closed

Type assertion error i8 vs u8 #60226

bgrieder opened this issue Apr 24, 2019 · 6 comments

Comments

@bgrieder
Copy link

bgrieder commented Apr 24, 2019

i8_u8_issue

Rustc 1.33. The following code:
#[no_mangle]
pub extern "C" fn i8_u8_issue(result: *mut c_char) {
    // recover a mutable slice over the passed in C char buffer of len 512
    let mut slice = unsafe { std::slice::from_raw_parts_mut(result, 512) };
    // create a C String and copy its chars in the slice
    let cs = CString::new("-123456").expect("CString::new failed");
    let mut i = 0;
    cs.into_bytes_with_nul().iter().for_each(|c| {
        slice[i] = *c;
        i = i + 1;
    });
}

will generate a compilation error

378 |         slice[i] = *c;
    |                    ^^ expected i8, found u8

On my system (MacOS) c_char is aliased to u8 so this should be fine.
Actually, casting *c to i8 will compile but the Rust plugin of IntelliJ will report an error (see attached picture)

@bgrieder
Copy link
Author

Playground

@hellow554
Copy link
Contributor

so this should be fine

Nah, I have to disagree. The C-Standard does not define whether a char is signed or unsigned. Read https://stackoverflow.com/q/2054939/ .

Actually, casting *c to i8 will compile

Then what's the problem with doing it? *c as i8. This will give you cross platform capabilities.

but the Rust plugin of IntelliJ will report an error

That's third party code and not the official rust compiler. They use their own code IIRC.

@bgrieder
Copy link
Author

No sorry, I disagree, this is not a C issue, this is a Rust type inference coherence issue: c_char is aliased to u8

In ra/mod.rs

#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8;

In the code above, type inference is used for all variables. Since result is a pointer to c_char i.e. u8, slice should be a slice of u8 not i8.

@hellow554
Copy link
Contributor

You forgot the cfg block (https://doc.rust-lang.org/src/std/os/raw/mod.rs.html#12)

#[cfg(any(all(target_os = "linux", any(target_arch = "aarch64",
                                       target_arch = "arm",
                                       target_arch = "powerpc",
                                       target_arch = "powerpc64",
                                       target_arch = "s390x")),
          all(target_os = "android", any(target_arch = "aarch64",
                                         target_arch = "arm")),
          all(target_os = "l4re", target_arch = "x86_64"),
          all(target_os = "freebsd", any(target_arch = "aarch64",
                                         target_arch = "arm",
                                         target_arch = "powerpc",
                                         target_arch = "powerpc64")),
          all(target_os = "netbsd", any(target_arch = "aarch64",
                                        target_arch = "arm",
                                        target_arch = "powerpc")),
          all(target_os = "openbsd", target_arch = "aarch64"),
          all(target_os = "fuchsia", target_arch = "aarch64")))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8;
#[doc(include = "os/raw/char.md")]
#[cfg(not(any(all(target_os = "linux", any(target_arch = "aarch64",
                                           target_arch = "arm",
                                           target_arch = "powerpc",
                                           target_arch = "powerpc64",
                                           target_arch = "s390x")),
              all(target_os = "android", any(target_arch = "aarch64",
                                             target_arch = "arm")),
              all(target_os = "l4re", target_arch = "x86_64"),
              all(target_os = "freebsd", any(target_arch = "aarch64",
                                             target_arch = "arm",
                                             target_arch = "powerpc",
                                             target_arch = "powerpc64")),
              all(target_os = "netbsd", any(target_arch = "aarch64",
                                            target_arch = "arm",
                                            target_arch = "powerpc")),
              all(target_os = "openbsd", target_arch = "aarch64"),
              all(target_os = "fuchsia", target_arch = "aarch64"))))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8;

@nagisa
Copy link
Member

nagisa commented Apr 24, 2019

CString::into_bytes_with_nul returns a Vec<u8> – a byte vector – regardless of what c_char on your platform is, so the variable c inside the closure has type &u8 on all platforms.

From the code snippet above it is fairly clear that c_char on MacOS will end up being a i8 and therefore slice variable is &[i8].

The types in this example therefore are all concrete (there are no inference variables), therefore inference cannot plausibly be a cause of any sort of a bug here.

This indeed does not appear to be a bug. Therefore closing, but do complain if you still feel otherwise.

@nagisa nagisa closed this as completed Apr 24, 2019
@bgrieder
Copy link
Author

bgrieder commented Apr 24, 2019

@hellow554 @nagisa
You are right, I forgot the cfgblock !

Now I researched why on MacOS c_charwould map to i8 and not u8as on linux but could not find any reasonable explanation. (and this worries me in terms of portability). nah, not even it seems to be i8 for all OSes on x86_64 except l4re..

Obviously the IntelliJ parser ignores the cfgblock. I will open a ticket with them.
Thanks

jbielick added a commit to jbielick/cpp-bindings that referenced this issue Oct 13, 2022
similar to:
sportsball-ai/blackmagic-raw-rs#3

> Apparently c_char is aliased to u8 on linux/arm64, whereas it's i8 on linux/amd64.
> Some context here: rust-lang/rust#60226
> And see c_char_definition here: https://doc.rust-lang.org/src/std/os/raw/mod.rs.html#103
lks128 added a commit to lks128/fork-elephantry that referenced this issue Feb 14, 2023
The error was following:

```
error[E0308]: mismatched types
  --> /home/[redacted]/.cargo/registry/src/jackfan.us.kg-1ecc6299db9ec823/elephantry-3.0.0/src/connection.rs:41:50
   |
41 |             connection.set_notice_processor(Some(notice_processor), std::ptr::null_mut());
   |                                             ---- ^^^^^^^^^^^^^^^^ expected `u8`, found `i8`
   |                                             |
   |                                             arguments to this enum variant are incorrect
   |
   = note: expected fn pointer `unsafe extern "C" fn(_, *const u8)`
                 found fn item `extern "C" fn(_, *const i8) {notice_processor}`
```

Relevant links:
- rust-lang/rust#60226
- https://github.com/sportsball-ai/blackmagic-raw-rs/pull/3/files
lks128 added a commit to lks128/fork-elephantry that referenced this issue Feb 14, 2023
Commit fixes following error when building on linux arm64 (Ubuntu in Docker on Apple M1):

error[E0308]: mismatched types
  --> /home/[redacted]/.cargo/registry/src/jackfan.us.kg-1ecc6299db9ec823/elephantry-3.0.0/src/connection.rs:41:50
   |
41 |             connection.set_notice_processor(Some(notice_processor), std::ptr::null_mut());
   |                                             ---- ^^^^^^^^^^^^^^^^ expected `u8`, found `i8`
   |                                             |
   |                                             arguments to this enum variant are incorrect
   |
   = note: expected fn pointer `unsafe extern "C" fn(_, *const u8)`
                 found fn item `extern "C" fn(_, *const i8) {notice_processor}`

Relevant links:
- rust-lang/rust#60226
- https://github.com/sportsball-ai/blackmagic-raw-rs/pull/3/files
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants