Semantics of *mut _


#1

I’ve seen ptr as *mut _ being used, but I can’t find semantics of the underscore in this context explicitly defined anywhere.

I expected it to be mentioned in Casting Between Types section of the book, but there was nothing. Am I looking at the wrong place or is it not yet documented?


#2

_ in type position is just “the type hole”. It means “there’s a type here, but I can’t be bothered to tell you what it is; you figure it out”. It causes the compiler to infer the type in that position.

It’s not explicitly defined there because it’s not specifically part of *mut or casting; it’s just a thing in the type system. In that particular context, it’s casting from *const u8 to *mut _, so the _ is u8.


#3

The underscore is called a “type placeholder”, and it is mentioned very briefly in the book, but I cannot remember where :frowning: Basically, it’s used when you want Rust to figure out the type, but syntax demands it. So in this example, it could be as *mut u8, but instead, decided to let Rust figure out that u8 is there.

https://doc.rust-lang.org/book/syntax-index.html is usually the first place to go to learn about syntax, but it only covers _ in patterns, apparently!


#4

Thanks! It makes it a bit more clear now. Should I file an issue on GitHub about adding this section to the book?

Also, a question about inference then. For example, if I call a function some_function(foo as *mut _), where foo is *const i8 and function header is fn some_function(arg: *mut u8), should I always expect it to infer _ from the function header (that is, in this case it would be u8 and not i8)?


#5

In that case, it should fail to compile because those two types don’t unify. blah blah blah


#6

Normally I would say “yes”, but the existing book isn’t being worked on, as I’m working on its replacement instead.


#7

@DanielKeep what about this code (it’s nonsensical, but it compiles and runs on nightly):

fn test(arg: *mut u8) {
    unsafe {
        println!("{}", *arg);
    }
}

fn main() {
    let x: i8 = 10;
    let y: *const i8 = &x as *const i8;
    test(y as *mut _);
}

#8

@steveklabnik glad to hear about the new book! At least I brought this thing up, maybe you’ll get a chance to mention it in the new resource :slight_smile:


#9

Well, there you go. I assume it prioritises the result type in an as, which makes sense.