-
-
Notifications
You must be signed in to change notification settings - Fork 805
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
VIP: uint256 as a first class citizen #764
Comments
Agree with remove functions. All type comparisons and assignments will no longer perform any implict conversions under this suggestion, therefore conversions will have to be explicitly provided. This should round out our type system upgrade for the beta release. |
From the meeting it become clear this is some syntax to consider:
should not be allowed.
should be allowed. Thoughts? |
I disagree. I think
|
Implicit casting may introduce some complexity in the compiler because you need to check different range for number literal under different context. For example, |
There are cases where it is not trivial to identify (or define a semantics of) the "context". For example, is the following inequality
There are two possible interpretations of the type of the expression:
One more cute example. The following would probably be rejected, although it seems trivially
|
I think these corner cases could throw "undetermined type" by an implict literal type checking algorithm I hesitate to call it an implict conversion, because you use contextual information from the other types to determine what the type is of the literal conversion. I think at first it should even reject mathematical operations, preferring instead to explicitly write the literal value out. Together with the decimal demarcation differentiating decimal literals from integer literals, we should have enough information to determine type in a vast majority of cases without confusion on the reader's behalf. |
@fubuloubu I agree with the fact that my example is not common, and no sane developer will write this kind of programs. :) OK. Then, just to make sure, let me spell out your type checking algorithm a bit. Let's consider only the two types: Case 1. Now, in Case 3, the type of the literal can be identified as follows. First, we reject an integer expression (arithmetic, comparison, etc.) whose sub-expressions are all integer literals. (This restriction should be acceptable by users, as @fubuloubu pointed out.) Then, for any integer expression, there is a non-literal sub-expression whose type can be deterministically identified, and we can infer the type of a literal based on the type of its non-literal sibling. (TODO: prove/check that any non-literal expression's type can be deterministically identified.) |
I was picturing it more like this: a statement is a collection of literal and non literal members, connected through expressions and operators. On an assignment or assertion expression, there is a clearly identified type on the LHS. The RHS must therefore clearly evaluate it's type to match the LHS. Evaluation of the expression through it's operators must match down to the literal and non literal values that make it up. Since non literals have explicit types, that means it should be clearly defined through the operators what type the matching literal should have. This may become more complex if arbitrary combinations of literals are allowed to take place, but it should still be possible to figure it out if even one node of the AST is a statically typed non-literal value. Corner cases occur when an operator accepts more than one type and implicitly casts, but since we are removing that more generally we shouldn't have to worry as much. |
I think we are on the same page. I can take a look again once it is implemented. |
I think the way Go handles literals should be followed post-beta. (Ie. numeric literals have no type, they have arbitrary precision, operators between literals are executed at compile time with unlimited precision math. On assignment or comparison between a variable and a literal, it is checked if the literal cleanly converts to the variable's type (eg. is integer if the variable is integer, fits in variable range, etc.), and if yes, it's treated as that type, if not, a compile time error is thrown.) |
@daniel-jozsef that makes sense to me. |
Hi @jacqueswww , @daniel-jozsef , @DavidKnott could I please get some advice on a Vyper equivalent to Solidity’s SafeMath functionality. I would like to add a paragraph to this Vyper chapter < https://github.com/ethereumbook/ethereumbook/blob/develop/vyper.asciidoc > but need your help answering the following questions for the readers:
Alternatively to the above, perhaps the following is more accurate
I write about this in light of the recent overflow issue in a Solidity smart contract < https://medium.com/@peckshield/alert-new-batchoverflow-bug-in-multiple-erc20-smart-contracts-cve-2018-10299-511067db6536 > where a mistake was made even though SafeMath was available. It would be great to make this crystal clear for future Vyper developers seeing’s how Vyper is so safety focussed. Any advice (big or small) and links to code would be greatly appreciated. |
@tpmccallum Vyper has implemented SafeMath at the compiler level so there is no need to worry about that. |
Hi @ben-kaufman |
Yes SafeMath is built into vyper: https://github.com/ethereum/vyper/blob/master/vyper/parser/expr.py#L275 So any airithmetic with a
|
To answer the question on safety, vyper has 2 methods of protecting against overflows. 1.) safemath on ints (as indicated above). Clamps are enforced whenever a literal constant is loaded, a value is passed into a function or a variable is assigned. Hope that answers your questions - I am on the gitter channel as well if you need further explanations 😄 |
Hi @jacqueswww |
Hey Tim! LLL is the IR (https://en.m.wikipedia.org/wiki/Intermediate_representation) we use for vyper. So that means these safety measures will always be included and can not be switched off if you use vyper (at beta release since int128 safemath work will be done soon, uint256 has already been done). |
Hi @jacqueswww |
Hi again @jacqueswww Is it safe to say that Vyper does not support variable typecasting? I would be pleased if this is the case, seeings how typecasting can cause odd behaviour and confusion (truncating etc). Just fact checking as I tick off the final TODO in the Vyper book chapter. |
Hi @tpmccallum , We do allow type casting (using the convert function), however if you are trying to convert a too big Additionally we do precompilation of literals, and disallow assigning a too large Up until recently we did allow implicit conversions in arithmetic ie. between uint256/int128/decimal, but this is partly (and soon fully) removed. Please checkout the discussions on the below VIPs, the comments are useful to the reasoning behind this removal ;) |
Preamble
Simple Summary
Allow generic arithmetic operations to work instead of using specific functions.
Abstract
Currently using uint256 can be very tedious and difficult because all arithmetic has to occur with
Motivation
Initially it was thought that working with unsigned integer are needed and the very large signed integer types could be used and converted. However time, and time again the need for
uint256
to exist as arisen. Usinguint256_*
functions do do any arbitrary calculation becomes a serious issue for readability.Specification
NB comparison between uint256 and other types should not be implicit.
It is important double check SafeMath is inserted, however working of the functions templates should insert the existing SafeMath behaviour, as seen in:
https://github.com/ethereum/vyper/blob/master/vyper/functions/functions.py#L559
Literal integer assignment cases to handled on assignment (as discussed below):
Backwards Compatibility
We can consider keeping
uint256_
functions. But I think removing those functions is best to avoid confusion for new comers.Copyright
Copyright and related rights waived via CC0
The text was updated successfully, but these errors were encountered: