Commit | Line | Data |
5dbb47c8 |
1 | == Todo for 2.0400 |
85910734 |
2 | |
1b1eb1ca |
3 | === RT Tickets |
4 | |
c78a59d7 |
5 | RT#67731 - Union types reports spurious parent types - |
6 | https://rt.cpan.org/Ticket/Display.html?id=67731 |
7 | |
8 | RT#59478/RT#63000 - 0+ overload causes NV conversion on == on perls before |
9 | 5.14 - this causes comparisons to fail when the number can't fit in an NV |
10 | without precision loss. I'd like to fix this in a more general way (forcing |
11 | anyone else who might be using == on tc objects to do weird things isn't very |
12 | good), although it's hard to test to see what actually works. |
13 | |
14 | RT#69839 - UNIVERSAL methods should show up as methods, so things like method |
15 | modifiers work |
1b1eb1ca |
16 | |
b927b1d4 |
17 | === Register implicitly created class/role types |
18 | |
19 | When you do has foo => (isa => 'Bar'), it returns a class_type for Bar, but |
20 | doesn't register it. This means that later you can declare "subtype 'Bar', as |
21 | 'Str', ..." and it'll work, and later instances of the 'Bar' type will use that |
22 | one. We should register the implicitly created ones so that trying to redefine |
23 | it after it's used throws an error. |
24 | |
25 | == Todo for 2.0600 |
26 | |
85910734 |
27 | === Revise MetaRole API to reunify class/role metaroles: |
28 | |
29 | apply_metaroles( |
30 | for => $meta, |
31 | roles => { |
32 | attribute => [...], |
33 | class => [...], |
34 | role_attribute => [ ... ], |
35 | } |
36 | ); |
37 | |
38 | If the $meta is a class, we apply the roles to the class. If it's a role, we |
39 | hold onto them and apply them as part of applying the role to a class. |
40 | |
41 | To make this all work nicely, we'll probably want to track the original role |
42 | where a method was defined, just like we do with attributes currently. We'll |
43 | also need to store method modifiers with their original role, which may mean |
44 | adding some sort of Moose::Meta::Role::MethodModifier class. |
45 | |
46 | For each role-specific thing (methods, attributes, etc.) we should allow a |
47 | role_attribute, role_method, etc. key. The common case will be that the |
48 | metaroles are intended for the consuming class, but we should allow for |
49 | metaroles on the role's metaobjects as well. |
50 | |
ef0801e7 |
51 | === Deprecate old-style Moose extensions |
52 | |
53 | Moose extensions that work by calling Moose->init_meta(metaclass => |
54 | 'Some::Custom::Metaclass', ...) during their own init_meta should be |
55 | deprecated, so they can be removed later (this should fix the issues with |
56 | init_meta generation in Moose::Exporter, see RT51561) |
57 | |
d8fed7e3 |
58 | This needs to wait until the previous fix gets in, since it will hopefully eliminate the need to write custom init_meta methods entirely. |
59 | |
24b9aca7 |
60 | === Attributes in roles need to be able to participate in role composition |
61 | |
62 | Right now, this fails with no decent workaround: |
63 | |
64 | package R1; |
65 | use Moose::Role; |
66 | has foo => (is => 'ro'); |
67 | |
68 | package R2; |
69 | use Moose::Role; |
70 | with 'R1'; |
71 | requires 'foo'; |
72 | |
73 | package C; |
74 | use Moose; |
75 | with 'R2'; |
76 | |
77 | Role attributes really need to be able to participate in role-role combination. |
78 | This should also fix "with 'Role1', 'Role2'" being broken when Role1 implements |
79 | a method as an accessor and Role2 requires that method, but at least in that |
80 | case you can split it into two 'with' statements with minimal loss of |
81 | functionality. |
82 | |
83 | === Method modifiers in roles should silently add 'requires' for them |
84 | |
85 | This shouldn't be a functionality change, just a better error message (and |
86 | better introspectability). This shouldn't happen if the role already contains a |
87 | method by that name, so it'll depend on the previous fix going in (so "has foo |
88 | => (is => 'ro'); around foo => sub { }" doesn't produce a 'requires' entry). |
89 | |
90 | === Add overloading support |
91 | |
92 | or at least, don't break existing overloading support |
93 | |
94 | This shouldn't treat the overloading stuff as actual methods, since that's just |
95 | an implementation detail, but we should provide an API for add_overload, |
96 | get_overload, get_overload_list, etc. In particular, this would allow |
97 | namespace::autoclean to not break things. |
98 | |
99 | Also, MooseX::Role::WithOverloading should probably be cored. |
100 | |
d8fed7e3 |
101 | This should probably also wait for the metarole unification fix, to avoid the |
102 | ::WithOverloading stuff being too insane. |
103 | |
24b9aca7 |
104 | |
105 | == Todo for later |
106 | |
3091d476 |
107 | === has +foo in roles |
108 | |
109 | There's no actual reason for this not to work, and it gets asked often enough |
110 | that we really should just do it at some point. |
111 | |
24b9aca7 |
112 | === Actual API for metaclass extensions |
113 | |
114 | Right now, the only way to bundle multiple metaclass traits is via |
115 | Moose::Exporter. This is unhelpful if you want to apply the extension to a |
116 | metaclass object rather than a class you're actually writing. We should come up |
117 | with an API for doing this. |
118 | |
119 | === MooseX::NonMoose in core |
120 | |
121 | I think all of the actual issues are solved at this point. The only issue is |
122 | the (necessary) implementation weirdness - it sets up multiple inheritance |
123 | between the non-Moose class and Moose::Object, and it installs a custom |
124 | constructor method at 'extends' time (although perhaps this could be solved by |
125 | moving some of the logic back into Moose::Object::new?). Other than that, it |
126 | handles everything transparently as far as I can tell. |
127 | |
128 | === Fix attribute and method metaclass compatibility |
129 | |
130 | So i got this wrong when rewriting it last year - right now, metaclass compat |
131 | checks the default attribute and method metaclasses, which is wrong. This means |
132 | that if a parent class does "use MooseX::FollowPBP", then attributes declared |
133 | in a subclass will get PBP-style accessors, which is quite surprising. |
134 | |
135 | On the other hand, sometimes metaclasses might need to be able to say "I'm |
136 | going to assume that all of my attributes at least inherit from this custom |
137 | class", so we might need to split it into "default specified by the user" and |
138 | "default specified by the metaclass" and only do compat checking on the second? |
139 | I'm not actually sure this is a valid use case though. |
140 | |
141 | Something that probably should be taken into account though is attributes and |
142 | methods that extend existing attributes or methods from a superclass should |
143 | inherit the metaclass of the existing one. Also not sure if this is correct, |
144 | but something to think about. |
145 | |
146 | === Rename a bunch of the public API methods |
147 | |
148 | Right now the public API is kind of a mess - we have things like get_method vs |
149 | find_method_by_name (you almost always want to use the latter), there being no |
150 | has_method equivalent that checks superclasses, get_method_list being public |
151 | but only returning method names, while _get_local_methods is private (returning |
152 | method objects), and yet neither of those looks at superclasses, and basically |
153 | none of this naming follows any kind of consistent pattern. |
154 | |
155 | What we really need is a consistent and easy to remember API where the method |
156 | that people would think to use first is the method that they actually mean. |
157 | Something like renaming find_method_by_name to find_method, and get_method to |
158 | find_local_method or something along those lines. |
159 | |
6ddfb832 |
160 | === use Sub::Identify instead of doing our own thing with get_code_info |
161 | |
162 | No idea why we stopped using Sub::Identify in the past, but there's no reason |
163 | not to do this. We have a bug fix in our version (the isGV_with_GP thing), so |
164 | this should be submitted to Sub::Identify first. |
165 | |
c762df57 |
166 | === Move method modifiers out to an external module |
167 | |
168 | Class::Method::Modifiers uses a different method for doing method modifiers, |
169 | which I'm not sure why we aren't using in Moose right now. Optionally using |
170 | Class::Method::Modifiers::Fast would be even better - it uses Data::Util to |
171 | implement XS method modifiers, which could help things a lot. |
172 | |
173 | === Move type constraints out to an external module |
174 | |
175 | There's nothing about our type constraint system that requires being tied to |
176 | Moose - it's conceptually an entirely separate system that Moose just happens |
177 | to use. Splitting it out into its own thing (that Moose could extend to add |
178 | things like role types) would make things conceptually a lot cleaner, and would |
179 | let people interested in just the type system have that. |
180 | |
181 | === Merge Class::MOP and Moose |
182 | |
183 | This is a long term goal, but would allow for a lot of things to be cleaned up. |
184 | There's a bunch of stuff that's duplicated, and other stuff that's not |
185 | implemented as well as it could be (Class::MOP::Method::Wrapped should be a |
186 | role, for instance). |
187 | |
24b9aca7 |
188 | |
189 | == Things to contemplate |
190 | |
191 | === Does applying metaroles really need to reinitialize the metaclass? |
192 | |
193 | Seems like the logic that's actually necessary is already contained in |
194 | rebless_instance, and not reinitializing means that existing attributes and |
195 | methods won't be blown away when metaroles are applied. |
196 | |
197 | === Do we want to core namespace::autoclean behavior somehow? |
198 | |
199 | This would add Variable::Magic as a required XS dep (not a huge deal at the |
200 | moment, since Sub::Name is also a required XS dep, but it'd be nice for Moose |
201 | to be able to be pure perl again at some point in the future, and I'm not sure |
202 | what the relative chances of Sub::Name vs Variable::Magic making it into core |
203 | are). If we enabled it by default, this would also break things for people who |
204 | have introduced Moose into legacy-ish systems where roles are faked using |
205 | exporters (since those imported methods would be cleaned). |
206 | |
207 | If we decide we want this, we may want to core it as an option first ("use |
208 | Moose -clean" or so), and move to making it the default later. |
209 | |
210 | === Fix the error system |
211 | |
212 | oh god it's terrible |
213 | |
214 | More specifically, we really want exception objects. |
215 | |
216 | === Should using -excludes with a role add 'requires' for excluded methods? |
217 | |
218 | It seems to make sense, since otherwise you're violating the role's API |
219 | contract. |
220 | |
221 | |
85910734 |
222 | == Old todo (does anyone look at this?) |
223 | |
8b59f8d6 |
224 | ------------------------------------------------------------------------------- |
7af2c1d2 |
225 | BUGS |
d03bd989 |
226 | ------------------------------------------------------------------------------- |
43d599e5 |
227 | |
228 | ------------------------------------------------------------------------------- |
7af2c1d2 |
229 | FEATURES |
8b59f8d6 |
230 | ------------------------------------------------------------------------------- |
231 | |
d4967760 |
232 | - DDuncan's Str types |
233 | |
d03bd989 |
234 | subtype 'Str' |
235 | => as 'Value' |
236 | => where { Encode::is_utf8( $_[0] ) or $_[0] !~ m/[^0x00-0x7F]/x } |
d4967760 |
237 | => optimize_as { defined($_[0]) && !ref($_[0]) }; |
238 | |
d03bd989 |
239 | subtype 'Blob' |
240 | => as 'Value' |
241 | => where { !Encode::is_utf8( $_[0] ) } |
d4967760 |
242 | => optimize_as { defined($_[0]) && !ref($_[0]) }; |
243 | |
8b59f8d6 |
244 | - type unions |
245 | |
d03bd989 |
246 | Add support for doing it with Classes which do not have |
8b59f8d6 |
247 | a type constraint yet created |
248 | |
249 | - type intersections |
250 | |
251 | Mostly just for Roles |
252 | |
253 | - inherited slot specs |
254 | |
db1ab48d |
255 | 'does' can be added to,.. but not changed |
256 | (need type unions for this) |
8b59f8d6 |
257 | |
8b59f8d6 |
258 | - proxy attributes |
259 | |
db1ab48d |
260 | a proxied attribute is an attribute |
d03bd989 |
261 | which looks like an attribute, |
262 | talks like an attribute, smells |
263 | like an attribute,.. but if you |
264 | look behind the curtain,.. its |
db1ab48d |
265 | over there.. in that other object |
266 | |
267 | (... probably be a custom metaclass) |
8b59f8d6 |
268 | |
f90e052d |
269 | - local coerce |
270 | |
271 | [13:16] mst stevan: slight problem with coerce |
272 | [13:16] mst I only get to declare it once |
273 | [13:17] mst so if I'm trying to declare it cast-style per-source-class rather than per-target-class |
274 | [13:17] mst I am extremely screwed |
275 | [13:17] stevan yes |
d03bd989 |
276 | [13:17] stevan they are not class specific |
f90e052d |
277 | [13:18] stevan they are attached to the type constraint itself |
278 | [13:18] * stevan ponders anon-coercion-metaobjects |
279 | [13:18] mst yes, that's fine |
280 | [13:19] mst but when I declare a class |
281 | [13:19] mst I want to be able to say "this class coerces to X type via <this>" |
282 | [13:19] stevan yeah something like that |
283 | [13:19] stevan oh,.. hmm |
284 | [13:20] stevan sort of like inflate/deflate? |
285 | [13:20] stevan around the accessors? |
286 | [13:25] * bluefeet has quit (Remote host closed the connection) |
287 | [13:27] mst no |
288 | [13:27] mst nothing like that |
289 | [13:27] mst like a cast |
290 | [13:31] mst stevan: $obj->foo($bar); where 'foo' expects a 'Foo' object |
291 | [13:31] mst stevan: is effectively <Foo>$bar, right? |
292 | [13:32] mst stevan: I want to be able to say in package Bar |
293 | [13:32] mst stevan: coerce_to 'Foo' via { ... }; |
294 | [13:32] mst etc. |
d03bd989 |
295 | [13:53] stevan hmm |
296 | |
f3dc2e80 |
297 | ----------------------------------------------------------- |
298 | -- Type Constraints refactor |
299 | ----------------------------------------------------------- |
300 | |
301 | - add support for locally scoped TC |
302 | |
303 | This would borrow from MooseX::TypeLibrary to prefix the TC with the name |
304 | of the package. It would then be accesible from the outside as the fully |
305 | scoped name, but the local attributes would use it first. (this would need support |
306 | in the registry for this). |
307 | |
308 | - look into sugar extensions |
309 | |
310 | Use roles as sugar layer function providers (ala MooseX::AttributeHelpers). This |
311 | would allow custom metaclasses to provide roles to extend the sugar syntax with. |
312 | |
313 | (NOTE: Talk to phaylon a bit more on this) |
314 | |
315 | - allow a switch of some kind to optionally turn TC checking off at runtime |
316 | |
317 | The type checks can get expensive and some people have suggested that allowing |
318 | the checks to be turned off would be helpful for deploying into performance |
319 | intensive systems. Perhaps this can actually be done as an option to make_immutable? |
320 | |
321 | - misc. minor bits |
322 | |
323 | * make the errors for TCs use ->message |
324 | * look into localizing the messages too |
325 | * make ANON TCs be lazy, so they can possibly be subsituted for the real thing later |
326 | * make ANON TCs more introspectable |
327 | * add this ... |
328 | |
329 | # |
330 | # Type Definition |
331 | # |
332 | subtype 'Username', |
333 | from 'Str', |
334 | where { (/[a-z][a-z0-9]+/i or fail('Invalid character(s)')) |
335 | and (length($_) >= 5 or fail('Too short (less than 5 chars)')) |
336 | } |
337 | on_fail { MyException->throw(value => $_[0], message => $_[1]) }; |
338 | |
339 | # fail() will just return false unless the call is made via |
340 | $tc->check_or_fail($value); |
341 | |
342 | * and then something like this: |
343 | |
344 | subtype Foo => as Bar => where { ... } => scoped => -global; |
345 | subtype Foo => as Bar => where { ... } => scoped => -local; |
346 | |
347 | # or |
348 | |
349 | subtype Foo => as Bar => where { ... } => in __PACKAGE__ ; |
350 | |
351 | # or (not sure if it would be possible) |
352 | |
353 | my $Foo = subtype Bar => where { ... }; |
354 | |
355 | # ---------- |
356 | |
357 | [17:10] <autarch> stevan: it should do it if I pass coerce => 1 as part of the attribute definition |
358 | [17:12] <stevan> autarch: what I am not 100% sure of is how to tell it to deep coerce and when to not |
359 | [17:13] <stevan> cause a basic coerce is from A to B |
360 | [17:13] <autarch> hmm |
361 | [17:13] <stevan> which is valid for collection types too |
362 | [17:13] <stevan> deep coercion is what you are asking for |
363 | [17:13] <autarch> yeah |
364 | [17:13] <stevan> so perhaps we add deep_coerce => 1 |
365 | [17:13] <stevan> which will do it |
366 | [17:13] <autarch> that's fine for me |
367 | [17:13] <stevan> k |
368 | |
369 | coerce_deeply => 1 # reads better |
370 | |
7af2c1d2 |
371 | ------------------------------------------------------------------------------- |
372 | INTERNALS |
373 | ------------------------------------------------------------------------------- |
374 | |
375 | - rationalize all the get_X methods for classes (and roles) |
376 | |
377 | We have get_attribute, get_attributes_list, get_all_attributes, |
378 | etc. First, we need to make the method names consistent. If something |
379 | returns an attribute vs a name, that needs to be clear from the method |
380 | name. We also need to make sure that local vs. "entire inheritance |
381 | chain" is clear from the name. |
382 | |
7af2c1d2 |
383 | This is mostly a CMOP change. |
384 | |
385 | - Metaclass constructors |
386 | |
387 | There's a _lot_ of different conventions in here. Some things to consider: |
388 | |
389 | * new vs _new |
390 | * allowing new( 'name', %args ) vs ( name => 'name', %args ) |
391 | * Method->wrap vs Method->new |
392 | |
7af2c1d2 |
393 | - Moose::Meta::TypeConstraint::Parameter{izable,ized} |
394 | |
395 | The relationship between these two classes is very odd. In particular, |
396 | this line in Parameterized is insane: |
397 | |
398 | foreach my $type (Moose::Util::TypeConstraints::get_all_parameterizable_types()) { |
399 | |
400 | Why does it need to loop through all parameterizable types? Shouldn't |
401 | it know which parameterizable type it "came from"? |
402 | |
403 | - Moose::Util::TypeConstraints vs Moose::Meta::Type{Coercion,Constraint} |
404 | |
405 | The Util module has _way_ too much functionality. It needs to be |
406 | refactored so it's a thin sugar layer on top of the meta API. As it |
407 | stands now, it does things like parse type names (and determine if |
408 | they're valid), manage the registry, and much more. |
409 | |
7af2c1d2 |
410 | - Anything with a _(meta)?class method |
411 | |
412 | Every method that returns a class name needs to become a rw attribute |
413 | that can be set via the constructor. |
d03bd989 |
414 | |
cac484fa |
415 | - The Moose::Error stuff |
416 | |
417 | This is sort of half-implemented. We still use Carp directly, and the |
418 | internals can't decide how to throw an error (is it |
419 | Moose->throw_error, __PACKAGE__->throw_error, what?). |
420 | |
421 | The internals need to be made consistent before we expose this to the |
422 | rest of the world. |
423 | |
8b59f8d6 |
424 | ------------------------------------------------------------------------------- |
425 | TO PONDER |
426 | ------------------------------------------------------------------------------- |
427 | |
428 | - Moose "strict" mode |
429 | |
430 | use Moose 'strict'; This would allow us to have all sort of expensive tests |
d03bd989 |
431 | which can be turned off in prod. |
432 | |
8b59f8d6 |
433 | - Moose::Philosophy.pod |
434 | |
435 | To explain Moose from a very high level |
436 | |
687e52bb |
437 | - moosedoc |
8b59f8d6 |
438 | |
687e52bb |
439 | We certainly have enough meta-information to make pretty complete POD docs. |
d03bd989 |
440 | |
441 | |
442 | |