View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0000072 | LDMud 3.5 | LPC Compiler/Preprocessor | public | 2004-06-30 03:06 | 2011-02-13 21:47 |
Reporter | dan | Assigned To | |||
Priority | normal | Severity | major | Reproducibility | always |
Status | closed | Resolution | suspended | ||
Platform | Gueldenland / LDMud | OS | FreeBSD | OS Version | 3.2.11-dev.645 |
Summary | 0000072: clash between several features re. type-safety | ||||
Description | I'm not sure which of the following 'features' were present on LPmud, and I have no idea how the code below behaved on it, since I don't have access to a MUD not running on LDmud anymore. 1. Assignment operators ignore target type. 2. A function requiring its parameters to be of a certain type may be passed arguments of different types when called via call_other. 3. Casts of values to their own type at least generate a warning. This leads to workarounds in the mudlib along the lines of: void do_something_or_other(int x) { x = (int)(float)x; // cast any number to int, because x = x % 10; // modulo doesn't work on floats } The culprit in our case was code such as: int value; value *= 1.5; do_something_or_other(value); It is also possible to assign any other type than int to value, and operators such as *= and /= will result in a value of type float if the rhs is of type float, and so on. The calling expression is not allowed to explicitly cast the value it passes to the callee to int, because this would generate a warning. Possible fixes: - assignment operators should cast their result to the declared type of the target variable - values should be cast to their declared type any time a variable is modified, direct assignment of an incompatible value should result in an error - call_other could result in a runtime error on type mismatch | ||||
Steps To Reproduce | int a = 3; a *= 1.5; printf("%O\n", a); | ||||
Tags | No tags attached. | ||||
|
This behavior is historic: in the beginning LPC was a typeless language, and types were added over time. At runtime (which is when call_others are resolved and executed), all type information of the variables and parameters is lost. The typechecking in the compiler also suffers from this in being spotty and incomplete. The whole situation is kinda an ongoing defect :-) However, for your mudlib, the proper solution is not to use casts like that, but to define the function properly: void do_something_or_other (mixed x) { x = to_int(x); // cast any number to int, because x = x % 10; // modulo doesn't work on floats } as casting of a value to its own type is usually a strong indication that the type declaration of the value is wrong in the first place. |
|
Changing the argument type to mixed would make the function work, but it *is* meant to be an int, and it was only ever called with values believed to be ints because the variables that held them where declared int. If I have to change the type of an argument, then cast it to the desired type, this is a serious flaw of the language. By this reasoning, I have to change *any* argument type to mixed because I can't ever be sure of the actual type of arguments that are passed ot the function. I know of the historical origin of this problem, but at least LPMud never complained. The code in question did work too, though I'm not sure what it really did. I'd much prefer the compiler to just add the cast by itself. No compile-time knowledge is required at run time. |
|
What you request is typechecking at runtime. In my opinion, your "int value; value *= 1.5;" example should throw an error at compile time because of incompatible types (it does that already in 3.2.10-dev.616). As for the casting - there are many ways to skin a cat, and I don't like yours. In my opinion, when a function gets passed parameters of the wrong type, that's an important error which shouldn't be hidden by a cast. I don't cast parameters, but rather check them like this and throw an error if necessary: void foo(int x) { if(!intp(x)) { raise_error("Bad arg 1 to foo: not an int.\n"); } } If the compiler did a cast here by itself like you want it to, checks like this one wouldn't work anymore. If Lars really wants to add such a feature, a lot more thought has to be put into this. |
|
I agree with Menaures. A comment to Lars suggestion: If you want to gracefully convert wrong argument types, you can still do: void do_something_or_other (int x) { x = to_int(x); // cast any number to int, because ... } There is no need to declare the argument 'mixed', if the function is not designed to receive anything other than int. But I usually prefer Menaures approach to raise an error. There are the pragmas strict_types/strong_types in combination with save_types which solves quite a lot of these problems, because they can be detected at compile-time. Concerning call_other/run-time type checking... First, a check is only possible if the type information is still available (without save_types it is discarded after compilation). But we could only introduce it optionally, because otherwise people start yelling at us and it introduces an additional overhead into function calls (maybe the run-time check might be restricted to all the inter-object calls). Let's discuss, if it worth it. :-) |
|
If I don't overlook something here, this seems to be obsolete since we started to introduce the runtime type checks. They are not complete yet, but we hopefully get there in 3.5.x and this discussion seems to done. Please tell me if you disagree. |
Date Modified | Username | Field | Change |
---|---|---|---|
2004-06-30 03:06 | dan | New Issue | |
2004-07-01 22:08 |
|
Note Added: 0000075 | |
2004-07-01 22:09 |
|
Status | new => acknowledged |
2004-07-01 22:09 |
|
Description Updated | |
2004-07-02 00:45 | dan | Note Added: 0000078 | |
2004-07-03 10:57 | menaures | Note Added: 0000080 | |
2004-12-29 01:34 |
|
Project | LDMud 3.2-dev => LDMud |
2009-03-04 15:25 | zesstra | Note Added: 0000971 | |
2009-03-04 15:25 | zesstra | Status | acknowledged => feedback |
2009-03-04 15:26 | zesstra | Project | LDMud => LDMud 3.5 |
2009-06-24 06:13 | zesstra | Relationship added | related to 0000666 |
2011-02-13 21:47 | zesstra | Note Added: 0001967 | |
2011-02-13 21:47 | zesstra | Status | feedback => closed |
2011-02-13 21:47 | zesstra | Resolution | open => suspended |