Skip to content
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

Rust UI: improve messages returned to python #2138

Merged
merged 3 commits into from
Apr 4, 2022
Merged

Conversation

mmilata
Copy link
Member

@mmilata mmilata commented Feb 19, 2022

Built on top of #2092. Pyright fails since we no longer generate the .pyi files, can we do better than just ignoring these issues? Some other questions inline.

Fixes #2118.

args: *const Obj,
kwargs: *const Map,
) -> Obj {
extern "C" fn new_confirm_text(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
Copy link
Member Author

Choose a reason for hiding this comment

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

Note that I changed *const Map to *mut Map to pass type check.

Copy link
Contributor

Choose a reason for hiding this comment

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

I can't check it now, but it should match the type the C-side expects.

@@ -18,7 +18,7 @@ use crate::{
};

pub enum PinKeyboardMsg {
Confirmed,
Confirmed(Vec<u8, MAX_LENGTH>),
Copy link
Member Author

Choose a reason for hiding this comment

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

Since the pin() method exists I guess it was supposed to be used to obtain the pin, but haven't figured out how to get a reference to the layout object at the time the result is constructed.

Copy link
Contributor

Choose a reason for hiding this comment

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

This is exactly the usecase the ObjComponentMsg trait (hope I remember the name right) is supposed to address.

Copy link
Contributor

Choose a reason for hiding this comment

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

If you omit the TryInto impl for the msg type, you should be able to impl the above trait and get a ref to the component for the conversion. Then you can pull the PIN out of it and convert into Obj.

Copy link
Contributor

Choose a reason for hiding this comment

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

If you omit the TryInto impl for the msg type, you should be able to impl the above trait and get a ref to the component for the conversion. Then you can pull the PIN out of it and convert into Obj.

Copy link
Member Author

@mmilata mmilata Feb 20, 2022

Choose a reason for hiding this comment

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

When I implement the trait like

impl ComponentMsgObj for PinKeyboard {
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
let result: (Obj, Obj) = match msg {
PinKeyboardMsg::Cancelled => (CANCELLED.as_obj(), Obj::const_none()),
PinKeyboardMsg::Confirmed => (CONFIRMED.as_obj(), self.pin().try_into()?),
};
result.try_into()
}
}

then I get error regarding conflicting implementations:

error[E0119]: conflicting implementations of trait `ui::layout::obj::ComponentMsgObj` for type `ui::model_tt::component::keyboard::pin::PinKeyboard`
  --> src/ui/model_tt/layout.rs:57:1
   |
57 |   impl ComponentMsgObj for PinKeyboard
   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `ui::model_tt::component::keyboard::pin::PinKeyboard`
   |
  ::: src/ui/layout/obj.rs:37:1
   |
37 | / impl<T> ComponentMsgObj for T
38 | | where
39 | |     T: Component,
40 | |     T::Msg: TryInto<Obj, Error = Error>,
...  |
44 | |     }
45 | | }
   | |_- first implementation here

What am I missing?

Copy link
Member Author

Choose a reason for hiding this comment

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

The TryInto implementation is not there anymore, perhaps the compiler is not smart enough to figure out that T::Msg: TryInto<Obj, Error = Error> is false?

Copy link
Member Author

Choose a reason for hiding this comment

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

As discussed, we may be hitting rust-lang/rust#20400. I rewrote all the TryInto conversions to explicit ComponentMsgObj impls, it's a bit ugly but uses less magic.

@@ -145,7 +145,7 @@ impl Component for PinKeyboard {

fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
if let Some(Clicked) = self.confirm_btn.event(ctx, event) {
return Some(PinKeyboardMsg::Confirmed);
return Some(PinKeyboardMsg::Confirmed(self.digits.clone()));
Copy link
Member Author

Choose a reason for hiding this comment

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

If we keep this, is there a way to zero out the pin being cloned in a way that doesn't get optimized out?

Copy link
Contributor

Choose a reason for hiding this comment

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

See above, we can get rid of PIN being stored in the message altogether. Re. reliable data zeroing, there are some crates, let's investigate how they work in a nostd env.

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

Not storing the pin in the message anymore so zeroing isn't needed (yet). But good to know such crate exists.

Copy link
Contributor

Choose a reason for hiding this comment

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

maybe you should zero out the source buffer for the PIN though?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point, though that would require to modify the type of ComponentMsgObj::msg_try_into_obj to fn msg_try_into_obj(&mut self, msg: Self::Msg) -> Result<Obj, Error>. I propose to solve this in another PR, wanted to add this as a TODO item to #1922 but github is probably broken and won't let me edit:/

Copy link
Contributor

Choose a reason for hiding this comment

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

👍
added the TODO

honestly, couldn't we just consume the layout object instead? self instead of &mut self
(probably not because something something reference in the Python-held object, but still something that seems semantically more correct)

Copy link
Member Author

Choose a reason for hiding this comment

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

@matejcik
Copy link
Contributor

we can extend tools/build_mocks relatively easily to also walk Rust files (maybe only obj.rs ?) and generate mocks in the same format as the modtrezor*.h files.

@mmilata
Copy link
Member Author

mmilata commented Mar 10, 2022

I've addressed the comments and extended build_mocks to also scan .rs file for definitions, please take a look. I think this shouldn't conflict with #2155 much so marking as ready for review.

@mmilata mmilata marked this pull request as ready for review March 10, 2022 14:21
@mmilata mmilata requested a review from prusnak as a code owner March 10, 2022 14:21
@mmilata
Copy link
Member Author

mmilata commented Mar 10, 2022

Also rebased to master.
cc @grdddj

@mmilata mmilata requested review from jpochyla and matejcik and removed request for prusnak March 10, 2022 14:26
Copy link
Contributor

@matejcik matejcik left a comment

Choose a reason for hiding this comment

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

LGTM structure wise, leaving the details to @jpochyla

big 👍 on build_mocks handling

core/SConscript.unix Show resolved Hide resolved
core/embed/rust/src/micropython/macros.rs Show resolved Hide resolved
core/embed/rust/src/micropython/obj.rs Outdated Show resolved Hide resolved
@mmilata
Copy link
Member Author

mmilata commented Mar 11, 2022

Noticed that rustc doesn't like /// for the mocks:

warning: unused doc comment
   --> src/ui/model_tt/layout.rs:153:5
    |
153 |     /// CONFIRMED: object
    |     ^^^^^^^^^^^^^^^^^^^^^
154 |     Qstr::MP_QSTR_CONFIRMED => CONFIRMED.as_obj(),
    |     ----------------------- rustdoc does not generate documentation for expressions
    |
    = note: `#[warn(unused_doc_comments)]` on by default
    = help: use `//` for a plain comment

I've added #[allow(unused_doc_comments)] but let me know if using different prefix is preferable.

@mmilata mmilata force-pushed the mmilata/rs2py-messaging branch 4 times, most recently from 2c3647d to df9cdc3 Compare March 23, 2022 23:17
Copy link
Contributor

@matejcik matejcik left a comment

Choose a reason for hiding this comment

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

small nitpicks, otherwise very nice

core/embed/rust/src/ui/geometry.rs Show resolved Hide resolved
core/embed/rust/src/ui/model_tt/layout.rs Show resolved Hide resolved
jpochyla and others added 2 commits April 4, 2022 10:48
[no changelog]

Co-authored-by: Martin Milata <martin@martinmilata.cz>
@mmilata mmilata merged commit 38f4ab0 into master Apr 4, 2022
@mmilata mmilata deleted the mmilata/rs2py-messaging branch April 4, 2022 11:32
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.

Improve messages returned from rust layouts
3 participants