View Issue Details

IDProjectCategoryView StatusLast Update
0000340LDMud 3.5LPC Compiler/Preprocessorpublic2010-07-13 15:40
Reporter_xtian_ Assigned Tozesstra  
PrioritynormalSeverityfeatureReproducibilityN/A
Status resolvedResolutionfixed 
Target Version3.5.0Fixed in Version3.5.0 
Summary0000340: "obsolete" modifier
DescriptionAn "obsolete" modifier for lfuns, sefuns which throws a compilation/runtime warning if the so marked function is called (compiled function call as well as as call_others at runtime).

This is another item, that would help handling big libs with a lot of historical accumulated nonesense.
Additional Informationnote that this behaviour can be simulated by explicitely notifying wizards, writing into a bug-database, etc.
But I would favour an easy, fast, standarized way to handle this.
TagsNo tags attached.

Relationships

child of 0000749 resolvedzesstra LDMud 3.3 backport deprecated modifier to 3.3.x ("obsolete" modifier) 

Activities

_xtian_

2005-01-11 11:16

reporter   ~0000298

ah, and it could help MUDs prepare their switch to 3.3 by masking the efuns that are to vanish with an "obsolete" sefun

_xtian_

2005-01-19 06:15

reporter   ~0000310

come to think about it "deprecated" probably wouldn't sound that harsh.

zesstra

2010-02-12 19:14

administrator   ~0001718

Oh, BTW: I like that idea (Although it might be difficult to find a bit for that flag in the function header.) We have plenty of old nonsense floating around... I am surprised that I did not comment earlier.

Coogan

2010-03-03 18:00

reporter   ~0001749

Years ago, I wrapped each obsoleted efun by an sefun of the same name, giving a warning each time it was used. In the second stage, the sefun throws an error, pointing to the particular successor function.
This way it's quite comfortable to switch to a more recent driver version with "vanished" efuns.

zesstra

2010-03-03 18:11

administrator   ~0001750

Yes, that works good for efuns. But for them we have such a mechanism in the driver source which we also use (e.g. cat(), tail() in 3.3.x).

But in this case (lfuns, sefuns) it does not really work. You might define sefuns for obsolete lfuns, but you will have difficulties to defer from the sefun to private/protected lfuns. And if it triggers a warning on each call you might be flooded with scroll.
Additionally it does not catch call_others. You might define a call_other sefun and check on each call. But that introduces a signifcant slowdown for each call_other...
I think, the driver would be better suited, because it can do a lot things at compile-time and the remaining (call_other) much more efficient.

Bardioc

2010-03-05 14:15

reporter   ~0001767

I would love to have this modifier! Even though EverLIB is not old, parts of the domains are, and this would help alot!

zesstra

2010-03-07 12:02

administrator   ~0001768

I worked on this a bit. It is not committed to the driver sources yet, because I would like to have some comments first.
I added a modifier 'deprecated' for functions (in theory it could be extended to variables at some point), which will set TYPE_MOD_DEPRECATED in the function flags. Upon calling such a function (intra-object + sefuns) the compiler will issue a warning at compile-time. Callothers and lfun closure evaluations will cause a warning at runtime (this could trigger a huge number of warnings, be warned).

There are still two caveats to be solved:
1) the warning in case of lfun closures will not include the correct line number + defining program (the correct solution would be to check before pushing a new control stack frame, but therefore I need a possibility to get the function flags indepedent of setup_new_frame1()).
2) If you call a not-defined function and this will be defined later by inheritance/cross-definition the compiler will miss any deprecated modifier, because the call was generated when the flag was unknown.

You can find the changeset at: http://github.com/zesstra/ldmud-dev/compare/deprecated_mod and the deprecated_mod branch is at http://github.com/zesstra/ldmud-dev/tree/deprecated_mod. Comments welcome.

zesstra

2010-03-10 16:29

administrator   ~0001776

BTW: Should it be possible to 'loose' the deprecated flags by redefining the function in inheritees?
Pro: I deprecate a specific function (e.g core lib) and don't care about redefined function as long as they don't call me.
Contra: Maybe I want to deprecate an interface as a whole, not only the function I define myself...

_xtian_

2010-03-10 17:22

reporter   ~0001778

We would use "deprecated" if we want to change or eliminate parts of APIs. In that case we don't even want another user to keep on redefining that function - which he surely only did redefine in the first place to extend the inherited API.

In that case redefining the function will not work any more as expected and the user should be notified of this.

So: Pro: "deprecated" should not go away.

_xtian_

2010-03-10 17:29

reporter   ~0001779

Concerning 2) (external declarations of functions):
In uni-libs, at least if we haven't diverged that much, we use external declarations quite a bit for the core living and player objects (the code is deployed over several inherits), so this limitation might be a bit hindering.

Could a work-around be to issue a warning if the compiler encounters a redefinition where not all declarations are "deprecated"?

Gnomi

2010-03-11 04:55

manager   ~0001784

I disagree. I might have a program with a function fun() that is perfectly valid and will stay. And just because some other program had a fun() that is now deprecated, this doesn't make my fun() invalid or deprecated as well, just because both programs were inherited together in another program. And I'd rather not differentiate between redefining a function and cross-defining it to another inherited program (because it's basically the same and moving a function to an inherited program should be a valid refactoring step, so it should behave similarly).

In other words, the deprecated flag should warn whenever the removal of that function declaration with this flag alters the behavior at the point of the warning (might not compile anymore or might call a function that was hidden until now). And when a deprecated function is redefined by a non-deprecated function the removal of the deprecated function changes nothing for the caller (which still calls the non-deprecated one), so no warning there.

zesstra

2010-03-11 05:33

administrator   ~0001785

Right, so to summarize the two different wishes:
a) Gnomi wishes to deprecate functions
b) Xtian wishes to deprecate interfaces

Unfortunately both are mutually exclusive. Gnomi offered the opinion, that we probably can't do b) consistently. One issue is, that we can't prevent somebody from implementing a deprecated interface himself and not inheriting the original program defining the interface at all. Although that is IMHO very rare (might in theory be excluded by code-style conventions).

Actually I could probably use both a) and b) independently in our lib... ;-) Usually I would deprecate functions. But there are some exceptions. e.g. we have an interface do_wear() which is obsolete and we do things differently now. If a wizard redefined do_wear() and did not call ::do_wear() there would be no warning, but his do_wear() will a) do the wrong things to wear a piece of clothing or b) his object will completely miss when a player wears the object (e.g fail to enforce restrictions).

So far, I guess you would have to use first deprecated, then a deprecated+nomask empty function to deprecate interfaces.

_xtian_

2010-03-11 14:01

reporter   ~0001787

Yes, my wish (point b) can actually be realized by using "deprecated" (as Gnomi argued) and "nomask", or even the "warn_nomask" (http://mantis.bearnip.com/view.php?id=734) idea.

Please note, that we once proposed a "required" modifier which guaranteed that a inherited function would call ::fun() (http://mantis.bearnip.com/view.php?id=352). All these suggestions come from the frustrating experiences of maintaining an API over decades and inexperienced programmers, btw so all have real used cases. (yes, I remember that "required" still had some difficulties)

zesstra

2010-03-11 14:26

administrator   ~0001788

Yes, I fully share that frustration, we also have our share of ancient APIs and wizards who just copy a function from the core lib and the copy is never maintained anymore, gets no updates or bugfixes, until some ugly enough bug happens. (BTW: that suggestion about 'required' is still here in Mantis. Although I guess, we can't make it happen until we have a compiler which can analyze the execution flow. :-()

zesstra

2010-03-14 10:54

administrator   ~0001794

Ah, concerning the issue with the cross-defined functions: IMHO it not so big as it seems.
If you have a (matching) prototype with deprecated, the driver will warn. If you don't have a prototype, AFAIK you can only call the function if the calling function is compiled without type testing (it has no function type, which is not allowed with anything other than weak_types.
If you don't call a function without prototype yourself, that leaves call_other and symbol_function at runtime. And at runtime, the flags from the cross-defined functions are available (and would contain the deprecated flag).

zesstra

2010-03-14 11:40

administrator   ~0001797

Updated my test branch for this: the flag is now checked upon creation of closures, not at evaluation time (symbol_function, compiler (#'fun, #'::fun)).

zesstra

2010-03-21 12:25

administrator   ~0001811

I added checks for usages of deprecated global variables and committed my patch series to the trunk of 3.5. for testing.

zesstra

2010-07-13 15:40

administrator   ~0001870

Ok, no complaints so far. Closing this one for now.

Issue History

Date Modified Username Field Change
2005-01-11 10:59 _xtian_ New Issue
2005-01-11 11:16 _xtian_ Note Added: 0000298
2005-01-19 06:15 _xtian_ Note Added: 0000310
2010-02-12 19:14 zesstra Note Added: 0001718
2010-03-03 18:00 Coogan Note Added: 0001749
2010-03-03 18:11 zesstra Note Added: 0001750
2010-03-03 18:14 zesstra Project LDMud => LDMud 3.5
2010-03-03 18:15 zesstra Relationship added related to 0000703
2010-03-05 14:15 Bardioc Note Added: 0001767
2010-03-07 12:02 zesstra Note Added: 0001768
2010-03-07 12:02 zesstra Status new => assigned
2010-03-07 12:02 zesstra Assigned To => zesstra
2010-03-10 16:29 zesstra Note Added: 0001776
2010-03-10 17:22 _xtian_ Note Added: 0001778
2010-03-10 17:29 _xtian_ Note Added: 0001779
2010-03-11 04:55 Gnomi Note Added: 0001784
2010-03-11 05:33 zesstra Note Added: 0001785
2010-03-11 14:01 _xtian_ Note Added: 0001787
2010-03-11 14:26 zesstra Note Added: 0001788
2010-03-14 10:54 zesstra Note Added: 0001794
2010-03-14 11:40 zesstra Note Added: 0001797
2010-03-21 12:25 zesstra Note Added: 0001811
2010-03-21 12:25 zesstra Relationship deleted related to 0000703
2010-03-27 06:22 zesstra Target Version => 3.5.0
2010-04-29 14:08 zesstra Relationship added child of 0000749
2010-07-13 15:40 zesstra Note Added: 0001870
2010-07-13 15:40 zesstra Status assigned => resolved
2010-07-13 15:40 zesstra Fixed in Version => 3.5.0
2010-07-13 15:40 zesstra Resolution open => fixed