nim-lang / RFCs

A repository for your Nim proposals.
136 stars 26 forks source link

'cast' as pragma #258

Closed Araq closed 3 years ago

Araq commented 3 years ago

This is a proposal to add {.cast(noSideEffect).}: to Nim and to deprecate the existing {.noSideEffect.}: block syntax.

Rationale

Easier to grep for unsafe language constructs, allows for extensibility, enables a better async macro.

Details

I propose to support all of the following:

In combination with the new getRaisesList this should allow Nim's async macro to become precise about the effects an async proc can produce.

mratsim commented 3 years ago

noSideEffect instead of noSideffect

ghost commented 3 years ago

noSideEffect instead of noSideffect

Well, you can write it any way you want, for example n_O_s_I_d_E_e_F_f_E_c_T , who doesn't love case insensitivity :)

juancarlospaco commented 3 years ago

Can it be like an overload to the push ?, the same but instead of cast use push, improve it to take arguments, and you dont need to add new syntax, docs, etc to the language.

ghost commented 3 years ago

@juancarlospaco well, push itself is not unsafe, but usage of pragmas for code blocks is unsafe, because you lie to the compiler about the code effects. So with cast you'll be easily able to search for unsafe features used in code bases

disruptek commented 3 years ago

Well, you can write it any way you want, for example n_O_s_I_d_E_e_F_f_E_c_T , who doesn't love case insensitivity :)

I believe the point is that noSideEffect has three es.

Can we have a way to deprecate or test that these (and other) cast calls are gratuitous or do I have to manually alter the code and re-run the compiler to check?

Araq commented 3 years ago

Well, you can write it any way you want, for example n_O_s_I_d_E_e_F_f_E_c_T , who doesn't love case insensitivity :)

I know you're joking but that has little to do with case insensitivity, all that case sensitivity does is that it enforces you to be consistent in your n_O_s_I_d_E_e_F_f_E_c_T spelling. This is valid code in C/C++/Java/C#/etc:

int n_O_s_I_d_E_e_F_f_E_c_T = 0;

if (n_O_s_I_d_E_e_F_f_E_c_T != 0) { ... }

In fact, sensitivity allows for much more cowboy coding styles:

int n_O_s_I_d_E_e_F_f_E_c_T = 0;
float n_O_s_I_d_E_e_f_F_E_c_T = 0.0;

if (n_O_s_I_d_E_e_F_f_E_c_T != 0) { ... }
bluenote10 commented 3 years ago

Here are my thoughts even though it might be too late now already:

Very good idea in general. I'm just not sure about the word cast. It is so strongly connected to "type casting" that I even misread the RFC upon first skimming, and I find it awkward to explain what the pragma does using the word "cast". Some alternatives:

Araq commented 3 years ago

@bluenote10 We considered these alternative names but in the end cast did win because it's already known to be unsafe and also because technically the block is casted to a proc with the given properties.

bluenote10 commented 3 years ago

cast did win because it's already known to be unsafe

Depending on the developer's background, a "cast" is much less unsafe compared to an effect system override. For a Rust developer, a cast is as innocent as 16 as i8, and nothing like unsafe.

also because technically the block is casted to a proc

I don't think naming should focus on technical internals, but express what is relevant from a user perspective.

I can relate to the confusion that came up in https://github.com/nim-lang/RFCs/issues/302. In this case: {.pretend(tags: not Dangerous).} would result in a sentence that makes intuitive sense in plain English, whereas {.cast(tags: not Dangerous).} simply confuses me.

I think it is because the "cast" has no association to the "block" it is operating on. We would have to read it as "cast the block so that the visible tags are not dangerous". But one confuses the object with the predicate: "cast the tags to not dangerous ...", however it isn't the tags that get cast, it's the block. With the "pretend" variant this association problem doesn't arise: "pretend the tags are not dangerous in the following block".

Araq commented 3 years ago

The "technical details" are more objective than opinions about what is "confusing". When I started programming the "for" keyword was super confusing. Everything is confusing for somebody, it's not an interesting statement.