Skip to content

Add PyObjectPayload trait and use it for PyObject.payload #670

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

Merged
merged 11 commits into from
Mar 15, 2019

Conversation

coolreader18
Copy link
Member

@coolreader18 coolreader18 commented Mar 12, 2019

I'm not sure about the name; I'm willing to change it to pretty much anything but I can't think of anything else right now. The main goal of this is to have a good Debug implementation for PyObject.payload, as discussed in #664.

Edit: this would close #664.

@coolreader18 coolreader18 changed the title Add PyValuePayload trait and use it for PyObject.payload Add PyObjectPayload trait and use it for PyObject.payload Mar 13, 2019
@coolreader18
Copy link
Member Author

@OddCoincidence any idea why it's failing with a segfault?

@OddCoincidence
Copy link
Contributor

OddCoincidence commented Mar 13, 2019

Where are you seeing a segfault?

I'm just seeing this in travis:

error[E0599]: no method named `downcast_ref` found for type `std::boxed::Box<(dyn rustpython_vm::pyobject::PyObjectPayload + 'static)>` in the current scope
   --> wasm/lib/src/browser_module.rs:174:40
    |
174 |     if let Some(promise) = obj.payload.downcast_ref::<PyPromise>() {
    |                                        ^^^^^^^^^^^^
error: aborting due to previous error

EDIT: I see it now, not sure why though...

@coolreader18
Copy link
Member Author

It's in the pytest tests, command died with Signals.SIGSEGV.

@OddCoincidence
Copy link
Contributor

OddCoincidence commented Mar 13, 2019

Okay, so I did some debugging, here's what I found.

The new init_type_hierarchy method @adrian17 added today makes use of a FromPyObjectRef impl for PyRef<PyClass>. If that fails, it does this:

            panic!("Error getting inner type: {:?}", obj.typ)

but at that point obj.typ is uninitialized memory. So it segfaults in the debug impl.

            typ: mem::uninitialized(), // !

(So the lesson is basically that mem::uninitialized is just ridiculously hard to ever use correctly.)

So why does that impl fail? Because of this line:

        let payload: &dyn Any = &self.payload;

The concrete type for this trait object is a Box<dyn PyObjectPayload>, so when that impl tries to downcast it to a PyClass, it fails because it's actually a Box<dyn PyObjectPayload>.

@coolreader18
Copy link
Member Author

coolreader18 commented Mar 13, 2019

Okay, I fixed it by using an as_any() method on the trait as suggested in this StackOverflow answer.

@coolreader18
Copy link
Member Author

Great job figuring that out, by the way; that probably would have taken me an hour.

@coolreader18
Copy link
Member Author

Oh boy, now it's a stack overflow. I didn't think this would be that hard.

@OddCoincidence
Copy link
Contributor

OddCoincidence commented Mar 13, 2019

Oh boy, now it's a stack overflow.

@coolreader18 I mentioned this on gitter, but in case you didn't see, I noticed that it only occurs with trace logging enabled, so that may be a good clue to help with troubleshooting this.

@coolreader18
Copy link
Member Author

That's interesting, I'll look into that.

@BenLewis-Seequent
Copy link

I have hit a similar issue before. It happened when trying to print Debug representation of a recursive value. This wasn't really a problem with the old PyObjectPayload as it only outputted the type of the payload rather than the value itself.

@coolreader18
Copy link
Member Author

coolreader18 commented Mar 13, 2019

Ah, so it's probably because the typ of object_type and type_type point to each other, so it's trying to print that and going on forever. Maybe.

@coolreader18
Copy link
Member Author

coolreader18 commented Mar 13, 2019

Yes, all the tests that are failing are ones that define some function, and it fails just after tracing with StoreName { that function }. It then tries to trace the current scope and for whatever reason a function object 's debug impl is recursive. I'll try to fix this once I get home.

@coolreader18
Copy link
Member Author

coolreader18 commented Mar 14, 2019

Alright, found the culprit: Scope! For whatever reason trying to format the RcList in it was recursive and that caused the stack overflow. I'm not sure why this wasn't a problem before, nor am I sure how to fully fix it. For now I'm just formatting it with the string "Scope", but I think the Frame Debug impl is informative enough for locals, and that's printed after every bytecode instruction.

@coolreader18
Copy link
Member Author

The remaining failures are due to recursive objects, e.g. locals() or the recursive array in test/snippets/list.py. What should we do about this? Should we use the ReprGuard for Debug formatting?

@BenLewis-Seequent
Copy link

If we want a detailed Debug formatting then we kinda do need something similar to that. We probably don't want to use the same guard as it could get weird if it's printed in a repr.

@coolreader18
Copy link
Member Author

I think for now it's probably fine to do like we did when we had PyObjectPayload as an enum and just have them be very basic strings, e.g "dict", "list", etc.

@OddCoincidence
Copy link
Contributor

Rather than changing the Debug impls, maybe we can create a new method on PyValue called type_name or something and use that for the logging?

@coolreader18
Copy link
Member Author

I think we do want to provide good Debug impls for tracing; just not right now, probably in a separate PR, and incrementally.

Copy link
Contributor

@OddCoincidence OddCoincidence left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me

@coolreader18 coolreader18 merged commit a1e0c03 into RustPython:master Mar 15, 2019
@coolreader18 coolreader18 deleted the pyvaluepayload branch March 15, 2019 02:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Debug implementation changed: Trace output has become a lot less useful.
3 participants