Code Monkey home page Code Monkey logo

Comments (18)

farmerpiki avatar farmerpiki commented on August 18, 2024 2

I also agree to keep unsafe narrow for numeric types and have something else for the rest... having narrow in the name when casting a pointer is extremely confusing

from cppfront.

gregmarr avatar gregmarr commented on August 18, 2024 2

In what cases is casting a u8* to void* or the other way around unsafe?

casting a void * to a u8* is unsafe if the pointer refers to something other than a u8 or an array of u8.

from cppfront.

DyXel avatar DyXel commented on August 18, 2024 1

btw I do agree that just having cpp2::unsafe_narrow is not enough, perhaps that one needs to be locked and usable with integral types only, and we need another one maybe called cpp2::unsafe_type_cast that does what the usual static_cast does, which only works for type casting (so anything but integral types).

from cppfront.

hsutter avatar hsutter commented on August 18, 2024 1

Thanks again for this suggestion! OK, here's a draft of what I'm about to push, after also adding test cases and a Clang pre-16 workaround:


Restrict unsafe_narrow, add unsafe_cast

Restrict unsafe_narrow to narrowing cases and arithmetic types

Make as diagnose unsafe pointer casts, with a message to use unsafe_cast instead

Allow both unsafe_narrow and unsafe_cast to be used without cpp2:: qualification in Cpp2 code

Remove some uses of unsafe_narrow in cppfront's own code that weren't actually narrowing

Example:

f: (i: i32, inout s: std::string) = {
    // j := i as i16;                     // error, maybe-lossy narrowing
    j := unsafe_narrow<i16>(i);           // ok, 'unsafe' is explicit

    pv: *void = s&;
    // pi := pv as *std::string;          // error, unsafe cast
    ps := unsafe_cast<*std::string>(pv);  // ok, 'unsafe' is explicit
    ps* = "plugh";
}

main: () = {
    str: std::string = "xyzzy";
    f( 42, str );
    std::cout << str;                     // prints: plush
}

from cppfront.

gregmarr avatar gregmarr commented on August 18, 2024 1

Can unsafe_cast be used for things beyond pointers? If not, should it be unsafe_pointer_cast? If so, would it make sense to have a pointer specific one, so it's obvious that there is no physical conversion?

from cppfront.

MaxSagebaum avatar MaxSagebaum commented on August 18, 2024 1

from cppfront.

farmerpiki avatar farmerpiki commented on August 18, 2024

I just realized there's cpp2::unsafe_narrow, but to my understanding casting void * to [unsigned] char * is safe... so it's misleading IMHO... feel free to close if I'm wrong about this, prefferably with an explanation as to why.

from cppfront.

DyXel avatar DyXel commented on August 18, 2024

I think reinterpret_cast ought to work? At least I see union's implementation using it with no issues...

from cppfront.

farmerpiki avatar farmerpiki commented on August 18, 2024

static_cast works... so does reinterpret_cast but that's more loose, my issue was that it's unintuitive... because we are banned from using them in pure syntax and mmap(...) as *u8 crashes instead of doing a static cast and makes me do cpp2::unsafe_narrow for a case that should not be unsafe?!

from cppfront.

DyXel avatar DyXel commented on August 18, 2024

This is my opinion: Sure, the operation is safe in this specific instance, I mean, if you narrow an integer, that's only "unsafe" if you are losing information by the narrow, which is not most cases. Here the problem is that the compiler has no way to prove that casting the mmap's void* is safe, therefore you need a escape hatch to really say "yes, I know what I am doing!". The verbose cpp2::unsafe_narrow (or whatever other cast you might use) makes this pop out more for awareness, and I think that's the intended design.

from cppfront.

hsutter avatar hsutter commented on August 18, 2024

Thanks! Right, as is intended for safe casts. For casts that are unsafe, my preference is to make people write unsafe_. I didn't realize that unsafe_narrow can be (ab)used for that (ha! cute) but I like @DyXel 's suggestion (and was about to say the same but with the name unsafe_cast... maybe unsafe_type_cast is even better though, verbose is good for important/dangerous operations):

btw I do agree that just having cpp2::unsafe_narrow is not enough, perhaps that one needs to be locked and usable with integral types only, and we need another one maybe called cpp2::unsafe_type_cast that does what the usual static_cast does, which only works for type casting (so anything but integral types).

from cppfront.

jcanizales avatar jcanizales commented on August 18, 2024

the compiler has no way to prove that casting the mmap's void* is safe

In what cases is casting a u8* to void* or the other way around unsafe?

from cppfront.

hsutter avatar hsutter commented on August 18, 2024

unsafe_cast works for anything you can static_cast, such as casting away const and pointer <-> integral conversions. So, more than pointers I think?

from cppfront.

gregmarr avatar gregmarr commented on August 18, 2024

I was wondering if it could somehow be a bit more descriptive of exactly what it's doing, and that would make it more self-documenting.

For example, unsafe_pointer_cast only works if the source and destination pointers are the same size, so you know there is no data loss such as casting an int* to u8, and no user-defined conversion operators could be invoked.

It would also be great if it could report an error or at least a warning if you are using it somewhere that it's not needed, such as casting from int* to void* or derived* to base*. If it's being used where it's not needed, someone could come across it, see that it reports that it's doing something unsafe, and spend time trying to figure out why it's unsafe, when it could just be removed.

from cppfront.

MaxSagebaum avatar MaxSagebaum commented on August 18, 2024

For example, unsafe_pointer_cast only works if the source and destination pointers are the same size, so you know there is no data loss such as casting an int* to u8, and no user-defined conversion operators could be invoked.

What about casting void* or char* to anything else. Here, the size of the input pointer and output pointer would be always different. Adding this restriction would actually make it a dynamic_cast.

from cppfront.

gregmarr avatar gregmarr commented on August 18, 2024

What about casting void* or char* to anything else. Here, the size of the input pointer and output pointer would be always different. Adding this restriction would actually make it a dynamic_cast.

I don't know of any modern architecture where sizeof(void*) and sizeof(char*) are different. Are you thinking sizeof(void) and sizeof(char)?

from cppfront.

MaxSagebaum avatar MaxSagebaum commented on August 18, 2024

I meant void* to anything else or char* to anything else. Both of these cast will change the size of the underlying type.

from cppfront.

gregmarr avatar gregmarr commented on August 18, 2024

I meant void* to anything else or char* to anything else. Both of these cast will change the size of the underlying type.

They change the size of the underlying type, but not the size of the pointer itself, which is what I was talking about. There is no truncation in converting the pointer itself, as there would be if you cast char* to u16. The "changing the size of the underlying type" is covered by this being unsafe_. That's also why this isn't needed for foo* to void* or derived* to base*.

from cppfront.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.