-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Special-case enum method calls #19634
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
base: master
Are you sure you want to change the base?
Conversation
Btw, this same idea can be applied for:
I will however defer these cases, unless I will find that mypy itself will benefit from these. |
Oh interesting, there is another 3.9 test failure because there is no
Also, segfault happens after printing the traceback. I guess we add an incref too late for the method register (which only exists for non-extension classes) or for the class object register itself, or something similar. I will look tomorrow if there is a simple fix, if no simple fix, I will ignore this, as this is not related to my PR. |
I think I see the bug
but |
It looks a bit trickier than that, in gdb I see segfault occurs on this line
now here is a punishment for not writing docstrings :-) |
hm LOL doesn't look that way
|
It looks like this was broken recently in #19307 cc @brianschubert |
Well, adding some conditional logic looks annoying, I guess we should simply skip adding |
Oh wait, this applies to extension classes as well. Then we should always allocate the docstring on the heap. @brandtbucher I hope you can fix this, segfault on an uncaught exception is a pretty bad behavior. TBH I still don't understand what exactly is going on, like why don't we have this problem if the program exits normally (i.e. without exception)? A minimal test to reproduce:
generates
|
Still catching up, but would something like this do the trick? diff --git a/mypyc/lib-rt/misc_ops.c b/mypyc/lib-rt/misc_ops.c
index 3787ea553..23981f9f3 100644
--- a/mypyc/lib-rt/misc_ops.c
+++ b/mypyc/lib-rt/misc_ops.c
@@ -300,6 +300,19 @@ PyObject *CPyType_FromTemplate(PyObject *template,
Py_XDECREF(dummy_class);
+ if (template_->tp_doc) {
+ // Silently truncate the docstring if it contains a null byte
+ Py_ssize_t size = strlen(template_->tp_doc) + 1;
+ char *tp_doc = (char *)PyMem_Malloc(size);
+ if (tp_doc == NULL) {
+ PyErr_NoMemory();
+ goto error;
+ }
+
+ memcpy(tp_doc, template_->tp_doc, size);
+ t->ht_type.tp_doc = tp_doc;
+ }
+
#if PY_MINOR_VERSION == 11
// This is a hack. Python 3.11 doesn't include good public APIs to work with managed
// dicts, which are the default for heap types. So we try to opt-out until Python 3.12. Following after https://github.com/python/cpython/blob/485b16b4f7b28cefdfb524c2869d473078e349bf/Objects/typeobject.c#L4530-L4540 That seems to resolve the seg fault |
Yeah, that should work, I think we can simply add that chunk to |
(this however still doesn't explain why we don't fail without exception, this means we may have an extra incref for class objects, but this is a much smaller problem) |
…9636) See #19634 (comment) Also took the opportunity to add `PyDoc_STR` to the static docstrings. AFAIK this isn't strictly necessary, but it's better style and in theory makes it possible to compile without docstrings if someone wanted to do that.
I also explored your options 1 and 3, with the same result for 1 and "no, doesn't look right" feeling regarding 3. Such duplication looks quite reasonable here - after all, normally enums are small and do not account for significant portion of a codebase, so this extra size should be negligible. I'll try to look deeper into this tonight, thanks! |
I'm guessing this is a misspelling of "@brianschubert"? Otherwise, sorry to disappoint, but I'm not sure how I can help with this issue specifically. :) |
@brandtbucher Oops, this is some serious misspelling, sorry :-) |
Improves mypyc/mypyc#1121, this gives a bit above 1% on mypy self-check.
This only adds support for regular and overloaded methods without decorators (class/static methods and properties stay slow). When working on this I considered (and actually tried) four options:
__prepare__()
, or don't call it at the right moment. Or maybe I just didn't try hard enough. In general, for some reason this feels risky.CPyDef
s for (non-extension) enum methods, but since they have an extra argument,__mypyc_self__
, we can supplyNULL
there, since we know it is unused. This is actually easy and it works, but IMO it is ultra-ugly, so I decided to not do it.CPyDef
without__mypy_self__
, use it for direct calls, and make existing callable classesCPyDef
s one-line functions that simply call the first one. This is possible, but quite complicated, and I am not sure it is easy to generalize (e.g. on classmethods).