-
Notifications
You must be signed in to change notification settings - Fork 252
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
[BUG] int variable casted with as to size_t does not fail on compile time #1257
Comments
The current implementation of `is_narrowing_v` does not handle type conversions correctly. For example, `cpp2::impl::is_narrowing_v<std::size_t, int>` returns `false`, indicating that it mistakenly perceives the conversion from a signed `int` to an unsigned `size_t` as potentially non-narrowing. Closes hsutter#1257
The current implementation of `is_narrowing_v` does not handle type conversions correctly. For example, `cpp2::impl::is_narrowing_v<std::size_t, int>` returns `false`, indicating that it mistakenly perceives the conversion from a signed `int` to an unsigned `size_t` as potentially non-narrowing. Closes hsutter#1257
The current behavior was added intentionally: ede2df2
|
It's different from how we treat other integral types. We take a completely different approach for all unsigned values. I am OK with one or the other approach, but it should be consistent. Having a static assertion at compile time makes things obvious immediately—this is compiler support that I like to have. Moving it to the runtime is not ideal, but if it is how it should be, we should do the same for other integral types to keep consistency. |
This is the relevant discussion, and it lays out Herb's thoughts on why it is the way it is now. #106 (comment) |
The current implementation of `is_narrowing_v` does not handle type conversions correctly. For example, `cpp2::impl::is_narrowing_v<std::size_t, int>` returns `false`, indicating that it mistakenly perceives the conversion from a signed `int` to an unsigned `size_t` as potentially non-narrowing. Closes hsutter#1257
OK, Thanks for recalling that discussion from the past. Since then, I have run many test cases for The issue is easy when handling obvious cases like Imagine the function (I will leave only signature): fun: (i); This function triggers static asserts when you pass The function will also accept The function might look the following: fun: (i) = {
std::cout << (i as std::uint16) << std::endl;
} I am not expecting to choose one or another option. I am expecting consistency. @hsutter proposal looked fine at first ( This made it different from casting polymorphic types, Today, I have thought that maybe we need an additional way of casting:
|
I'm not sure that having the user add unsafe_narrow here is better, because then you lose the safety net of the runtime check.
Unless you install a throwing violation handler. Would you find this more acceptable if it threw an exception instead of calling the contract violation handler?
No, you are going from a larger size to a smaller size, this requires |
No, it is not about using
Yes, you are right. I was thinking about a case when the type is accepted on compile-time, but the value cause terminates at runtime. |
Is this just referring to
Violating a contract doesn't always result in termination. It depends on how your contracts are configured. They might even be just "observe" which logs the error somewhere, or "ignore" which doesn't even evaluate them. Putting |
I am not limiting anything; I am just describing how it works now. This is the check: Lines 1954 to 1967 in 78867f8
Where Lines 951 to 955 in 78867f8
Which, as you can see, calls Lines 921 to 934 in 78867f8
|
https://hsutter.github.io/cppfront/cpp2/contracts/ cpp2::contract_group, and customizable violation handling The contract group object could also provide additional functionality. For example, Cpp2 comes with the cpp2::contract_group type which allows installing a customizable handler for each object. Each object can only have one handler at a time, but the handler can change during the course of the program. contract_group supports: .set_handler(pfunc) accepts a pointer to a handler function with signature * (* const char). .get_handler() returns the current handler function pointer, or null if none is installed. .is_active() returns whether there is a current handler installed. .enforce(condition, message) evaluates condition, and if it is false then calls .report_violation(message). |
OK, thanks for that. I missed that... I will take another look at that issue. Still, that is not consistent... this is the only runtime checked Line 2076 in 78867f8
as for variant uses it explicitly, as for any or optional throws indirectly (soon it will be explicitly:Lines 2115 to 2120 in 4960b77
Lines 2160 to 2168 in 4960b77
So maybe we should move all |
These |
@gregmarr These exceptions are not the issue, but how they are thrown in comparison to other places. I experimented and have prepared an implementation that uses Take a look. If we want to keep these runtime checks, they should follow same approch, something like that, to allow customization of how they fail. |
In the current implementation of cppfront (065a993), the following code compiles and runs:
produces
and should fail to compile with the following error:
A potential error will be caught in runtime, e.g., when the
i
is negative, the following error will be produced:It will save us from the trouble... but a user should be informed to use
cpp2::unsafe_narrow<size_t>(i)
instead.The bug is related to the badly defined
is_narrowing_v
- I have the patch already and will deliver it in next PR.The text was updated successfully, but these errors were encountered: