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

Full enablement of Unions using nightly Rust #402

Merged
merged 1 commit into from
Jul 7, 2017

Conversation

flukejones
Copy link
Contributor

Unions are fully enabled behind a feature-gate. Both non-nightly and nightly Rust appear to be working well.

@EPashkin
Copy link
Member

EPashkin commented Jul 6, 2017

@Luke-Nukem Can you rebase this to master with removing merges?
Why GVariantBuilder_u1 etc. added to all generated libs in https://github.com/gtk-rs/sys when this feature enabled?
Bad changes in glib-sys with bitsized fields: GDate as example

#[repr(C)]
 pub struct GDate {
-    _truncated_record_marker: c_void,
-    //julian_days: guint: 32,
-    //julian: guint: 1,
-    //dmy: guint: 1,
-    //day: guint: 6,
-    //month: guint: 4,
-    //year: guint: 16,
+    pub julian_days: c_uint,
+    pub julian: c_uint,
+    pub dmy: c_uint,
+    pub day: c_uint,
+    pub month: c_uint,
+    pub year: c_uint,
 }

Strange that GScanner has //union comments before, but now it seems fixed, thanks

src/parser.rs Outdated
// TODO: unsure of how to handle this
//if attrs.by_name("is-gtype-struct").is_some() {
// return Ok(());
//}
Copy link
Member

Choose a reason for hiding this comment

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

Seems read_record return type need change to Result<Option<Type>>

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes but it also needs an initialised Type to return. This is where I am unsure what to do... I could maybe return a default() initialised Type?

Copy link
Member

Choose a reason for hiding this comment

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

Why it can't return Ok(None) in this case? And don't add type in read_record_start

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Result<Option<Type>>.... I don't know why my mind completely ignored that....
Done.

@flukejones
Copy link
Contributor Author

Regarding the appending of _u1 to various unions or _s1 to nested union->structs, it's because without it we end up with each struct->union->struct having the same c_type, and thus the same name for each.

Regarding

#[repr(C)]
 pub struct GDate {
-    _truncated_record_marker: c_void,
-    //julian_days: guint: 32,
-    //julian: guint: 1,
-    //dmy: guint: 1,
-    //day: guint: 6,
-    //month: guint: 4,
-    //year: guint: 16,
+    pub julian_days: c_uint,
+    pub julian: c_uint,
+    pub dmy: c_uint,
+    pub day: c_uint,
+    pub month: c_uint,
+    pub year: c_uint,
 }

Well of course... We can't initialise a newly created struct like that. Have to declare it first, then initialise it. If it were an enum instead of a struct then it might work.

If you look at;

struct GDate {
  guint julian_days : 32; /* julian days representation - we use a
                           *  bitfield hoping that 64 bit platforms
                           *  will pack this whole struct in one big
                           *  int
                           */

  guint julian : 1;    /* julian is valid */
  guint dmy    : 1;    /* dmy is valid */

  /* DMY representation */
  guint day    : 6;
  guint month  : 4;
  guint year   : 16;
};

each field is a guint, which translates to a c_uint. And they are initialised (which we can't do in rust).

@EPashkin
Copy link
Member

EPashkin commented Jul 6, 2017

As I remember size GDate in C will be 64bit or 8bytes with julian, dmy and day stored in byte 5)
Your version: 6*4=24 bytes;

@flukejones
Copy link
Contributor Author

As I remember size GDate in C will be 64bit or 8bytes with julian, dmy and day stored in byte 5)
Your version: 6*4=24 bytes;

Looking at guint it seems it will be a particular size depending on a #define G_MAXUINT UINT_MAX.

UINT_MAX is defined in Rust too, and c_uint size is defined by that. So essentially it looks like both guint and c_uint are defined the same way, and so should be the same size.

src/parser.rs Outdated
@@ -21,6 +21,7 @@ pub fn is_empty_c_type(c_type: &str) -> bool {
c_type == EMPTY_CTYPE
}


Copy link
Member

Choose a reason for hiding this comment

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

Unneeded extra line

src/parser.rs Outdated
let mut name = try!(attrs.by_name("name")
.ok_or_else(|| mk_error!("Missing record name", parser)));
let mut c_type = try!(attrs.by_name("type")
.ok_or_else(|| mk_error!("Missing c:type attribute", parser)));
Copy link
Member

Choose a reason for hiding this comment

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

rustfmt-nigthly change this 2 variables back.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, my rustfmt is outdated. Are you running everything through rustfmt?

Copy link
Member

Choose a reason for hiding this comment

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

Not on regular basic, but sometimes.

Copy link
Member

Choose a reason for hiding this comment

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

Mostly because latest tend to split function declaration to multiple lines.

@EPashkin
Copy link
Member

EPashkin commented Jul 6, 2017

Seems you ignore that

guint julian : 1;
guint dmy : 1; 

stored in one byte and all struct size can be lesser that guint size (not *2 as in your case).
Rust IMHO don't support this syntax,
this why we "ignore" stucts with these fields.
good that seems none of these structs used in unions,
so you can fallback to old code for this case

Also still not solved problem with including GVariantBuilder_u1 and GVariantBuilder_s1 without next usage to all your sys crates.

@flukejones
Copy link
Contributor Author

flukejones commented Jul 6, 2017

guint julian : 1;
guint dmy : 1; 

Hmm, I thought that was using the full guint, but declaring only 'n' bits of that integer were used... I'll have a look at the bitflags crate.

Also still not solved problem with including GVariantBuilder_u1 and GVariantBuilder_s1 without next usage to all your sys crates.

I don't understand what you mean... The result is;

#[repr(C)]
pub struct GVariantBuilder {
    pub u1: GVariantBuilder_u1,
}
 
#[repr(C)]
pub union GVariantBuilder_u1 {
    pub s1: GVariantBuilder_s1,
    pub x: [size_t; 16],
}
 
#[repr(C)]
pub struct GVariantBuilder_s1 {
    pub partial_magic: size_t,
    pub type_: *const GVariantType,
    pub y: [size_t; 14],
}

which to me seems fine. You would need to write the API on top of this to accommodate the nesting...
As far as I can tell, the end result is the same as the C definition? fields s1 and u1 are just addresses to the "anonymous" struct/union right?

I think the whole issue comes from in the gir;

   <record (trimmed info)>
      <union name="u" c:type="u">
        <record name="s" c:type="s">

I can't seem to get those names out, and if I did and the C_Type ended up being name 'u' or 's' then this would cause issues. I can make a small change to not add a number to those two fields, but then I'm not sure it that will cause issues later either.

Very sorry if I seem to be lacking an understanding on some things here.

@EPashkin
Copy link
Member

EPashkin commented Jul 6, 2017

Result is fine. Problem that it added to all sys crates not only on glib (7 unused copies for each these union and inner struct).

@EPashkin
Copy link
Member

EPashkin commented Jul 6, 2017

Same with GDoubleIEEE754_s1, GFloatIEEE754_s1.
Problem at seems that Library::record and Library::union add type to MAIN_NAMESPACE

@flukejones
Copy link
Contributor Author

flukejones commented Jul 6, 2017

EDIT:

Is it that MAIN_NAMESPACE do you think? I couldn't get it going with INTERNAL_NAMESPACE, it wouldn't include the extra structs/unions.

I see we commented at almost the same time 😃

Regarding the bit field structs, I'll see if I can use bitflags crate.

@EPashkin
Copy link
Member

EPashkin commented Jul 6, 2017

Yes, it one of functions, that cause problem (I thought that it in Library). It need ns_id: u16 parameter.
Bitflags IMHO don't help with this and better just use "old" code with commenting.

@flukejones
Copy link
Contributor Author

@EPashkin are you sure about the bitflags? Mozilla is using it with bindgen for their servo stuff, and the results seem to wok well.

@EPashkin
Copy link
Member

EPashkin commented Jul 6, 2017

You can try ;)

@EPashkin
Copy link
Member

EPashkin commented Jul 6, 2017

Strange, but duplicates still present :(

src/parser.rs Outdated

fn read_record(&mut self, parser: &mut Reader, ns_id: u16, attrs: &Attributes)
-> Result<Option<Type>> {
let name = try!(
Copy link
Member

Choose a reason for hiding this comment

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

let mut name

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Doh!

@flukejones
Copy link
Contributor Author

I'm not seeing any duplicates here 😕

@EPashkin
Copy link
Member

EPashkin commented Jul 6, 2017

I meant that (for example) both atk-sys/src/lib.rs and glib-sys/src/lib.rs
have GVariantBuilder_u1, and it don't used in atk-sys at all.

@EPashkin
Copy link
Member

EPashkin commented Jul 6, 2017

Sorry, something bugged on my machine: duplicate actually removed.
Only last problem with bitsized structs

@EPashkin
Copy link
Member

EPashkin commented Jul 6, 2017

Minor bug in result formating:
https://github.com/gtk-rs/gir/pull/402/files#diff-0c37b0c87c3c91119e579feee853b5d0R368 only needed if feature disabled.

@flukejones
Copy link
Contributor Author

Okay, that should be the final issue. Except the result formatting? I can't see what you are referring too.

@EPashkin
Copy link
Member

EPashkin commented Jul 6, 2017

Seems github generate broken links.
I meant last write in codegen/sys/lib_::generate_unions

    if !items.is_empty() {
        try!(writeln!(w, ""));
    }

@EPashkin
Copy link
Member

EPashkin commented Jul 6, 2017

Now produce strange results for GIOChannel, GScannerConfig, gobject-sys::GClosure. gtk-sys::GtkTextAttributes.
Before all after bit-sized fields was commented too.

#[repr(C)]
pub struct GIOChannel {
    pub ref_count: c_int,
    pub funcs: *mut GIOFuncs,
    pub encoding: *mut c_char,
    pub read_cd: GIConv,
    pub write_cd: GIConv,
    pub line_term: *mut c_char,
    pub line_term_len: c_uint,
    pub buf_size: size_t,
    pub read_buf: *mut GString,
    pub encoded_read_buf: *mut GString,
    pub write_buf: *mut GString,
    pub partial_write_buf: [c_char; 6],
    _truncated_record_marker: c_void,
    //use_buffer: guint: 1,
    //do_encode: guint: 1,
    //close_on_unref: guint: 1,
    //is_readable: guint: 1,
    //is_writeable: guint: 1,
    //is_seekable: guint: 1,
    pub reserved1: gpointer,
    pub reserved2: gpointer,
}

@EPashkin
Copy link
Member

EPashkin commented Jul 6, 2017

Hm, Seems rust-lang/rust#42068 already stabilized part of unions and it in already beta.
Glib has only problem with bit-sized GDoubleIEEE754_s1 and GFloatIEEE754_s1 as it non-Copy.

@EPashkin
Copy link
Member

EPashkin commented Jul 6, 2017

Good thing that I don't see usage GFloatIEEE754 and GDoubleIEEE754 in any functions and we can try ignore its after next release.

@flukejones
Copy link
Contributor Author

We're almost there 😄

I see why the proper truncation is required for fields after bitflags. Just needed to allow either is_bits or !truncated.

@EPashkin
Copy link
Member

EPashkin commented Jul 7, 2017

Thanks, @Luke-Nukem, Now I don't see any potential problems in generated code.
Can you remove empty line after generate_unions declaration?
And also please squash this PR to one commit as there too many merges in it.

@flukejones
Copy link
Contributor Author

flukejones commented Jul 7, 2017

I think I did the squash correctly? It's commit #f56da73.

@EPashkin
Copy link
Member

EPashkin commented Jul 7, 2017

Yes, #f56da73 is good, but next is not (it merge again).
Please, reset your master branch to this commit, and force push it to your repo.

@flukejones
Copy link
Contributor Author

Got it. Figured if there was an issue it would be an easy solve. Never done a squash before, very handy.

@flukejones
Copy link
Contributor Author

Hold fire a few minutes, I'll clean up the commit log

@EPashkin
Copy link
Member

EPashkin commented Jul 7, 2017

Actually you added to squashed commit some changes from current master (like adding external_libraries.rs and using it) but git is smart and will ignore it on merge.
Or you can do git rebase 9e3f4ccff85d1e to be sure that it contains only your changes.

@flukejones flukejones force-pushed the master branch 3 times, most recently from 59a3d75 to 52be615 Compare July 7, 2017 06:10
@flukejones
Copy link
Contributor Author

Okay, I think we're good now?

@EPashkin
Copy link
Member

EPashkin commented Jul 7, 2017

Previous was good (based on 9e3f4cc - current upstream master)

@EPashkin
Copy link
Member

EPashkin commented Jul 7, 2017

Just to git rebase 9e3f4ccff85d1e again

This commit enables full genertion of unions if using nightly Rust with feature
"use-unions" enabled. It also enables successful generation of nested (anonymous) struct->union->struct.
@EPashkin
Copy link
Member

EPashkin commented Jul 7, 2017

Yes, now it good.
Thanks again for unions and readme clarification.
I wait for CI just it case and merge

@EPashkin
Copy link
Member

EPashkin commented Jul 7, 2017

And excuse me for a lot of nitpicking 😉

@flukejones
Copy link
Contributor Author

Nitpicking is good. You caught a few things I just didn't think about (or know), or had missed. And it's good practice for me 😉

I'm looking forward to union stabilization in Rust. And when I get more time (or need it) I'll work on the bit-fields in multitype-structs.

@EPashkin EPashkin merged commit 2192ae7 into gtk-rs:master Jul 7, 2017
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.

2 participants