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

Expand size_of docs #44648

Merged
merged 1 commit into from
Sep 23, 2017
Merged

Expand size_of docs #44648

merged 1 commit into from
Sep 23, 2017

Conversation

Havvy
Copy link
Contributor

@Havvy Havvy commented Sep 17, 2017

This PR does 3 things.

  1. Adds a description of what pointer size means to the primitive pages for usize and isize.
  2. Says the general size of things is not stable from compiler to compiler.
  3. Adds a table of sizes of things that we do guarantee. As this is the first table in the libstd docs, I've included a picture of how that looks.

@Havvy
Copy link
Contributor Author

Havvy commented Sep 17, 2017

r? @steveklabnik

@Havvy
Copy link
Contributor Author

Havvy commented Sep 17, 2017

At the current state of this PR, I've more questions than I have content, so consider this more like an issue than a PR at the moment.

The wording in size_of really isn't that good. I want help on figuring out how it should be worded, especially since it involves stability guarantees, and I don't know how to properly word that. Perhaps we should say the size is only not guaranteed for #[repr(Rust)]?

I don't like the usage of T and TU in the table. The size of a reference changes depending on whether or not its referring to an unsized object, but I don't know how to put that in the table succinctly. Do we just add reference size and point out in the reference module that a reference is pointer size for sized types and twice pointer sized for unsized types?

Are there any other structs that we guarantee the size for? Box<T> perhaps? Wrapper structs?

/// &T | pointer size
/// &UT | 2 * pointer size
/// Option<&T> | pointer size
/// Option<&U> | 2 * pointer size
Copy link
Member

Choose a reason for hiding this comment

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

small nit: Option<&UT>

@@ -180,6 +180,31 @@ pub fn forget<T>(t: T) {
/// More specifically, this is the offset in bytes between successive
/// items of the same type, including alignment padding.
Copy link
Member

Choose a reason for hiding this comment

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

While you're here, consider mentioning that this is "successive elements in an array with that item type", since layout optimization can (in theory at least) change the layout of "successive items of the same type" in a struct.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@@ -710,6 +710,10 @@ mod prim_u128 { }
//
/// The pointer-sized signed integer type.
///
/// The size of this primitive is how many bytes it takes to reference any
/// one byte in memory. For example, on a 32 bit target, this is 4 bytes
Copy link
Member

Choose a reason for hiding this comment

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

nit: "one byte" here distracted me, though perhaps only in context of reviewing something about sizes. Perhaps a phrasing like "to reference any location in memory"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If I change it to this, I have to also describe what a location in memory is, no?

Copy link
Member

Choose a reason for hiding this comment

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

Hmm, *T::offset talks of "allocated object", so maybe use that instead of location? Though I don't know if it's defined anywhere (other than LLVM) either...

@@ -180,6 +180,31 @@ pub fn forget<T>(t: T) {
/// More specifically, this is the offset in bytes between successive
Copy link
Member

@scottmcm scottmcm Sep 18, 2017

Choose a reason for hiding this comment

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

Perhaps mention that it's always a multiple of align_of::<T>(), as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't know what you mean by this.

/// isize | pointer size
/// [T, n] | `size_of::<T>() * n`
/// &T | pointer size
/// &UT | 2 * pointer size
Copy link
Member

Choose a reason for hiding this comment

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

I think the accepted extern types RFC means that there will exist types that are not Sized but are none-the-less thin pointers. And there has been discussion of extra-fat pointers for things like dyn (Debug + Add). So it might be better to not mention this particularly, especially since use cases for relying on it are kinda sketchy.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So basically the size of &T is generally unstable?

/// usize | pointer size
/// isize | pointer size
/// [T, n] | `size_of::<T>() * n`
/// &T | pointer size
Copy link
Member

Choose a reason for hiding this comment

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

Should probably have *const T and *mut T as well.

/// items of the same type, including alignment padding.
/// More specifically, this is the offset in bytes between successive elements
/// in an array with that item type including alignment padding. Thus, for any
/// type `T` and length `n`, [T; n] will have a size of `n * size_of<T>()`.
Copy link
Member

Choose a reason for hiding this comment

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

[00:03:45] tidy error: /checkout/src/libcore/mem.rs:182: trailing whitespace

Copy link
Contributor

Choose a reason for hiding this comment

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

and size_of::<T>() here as well

@steveklabnik
Copy link
Member

@rust-lang/libs, are you okay with what we are guaranteeing stable here?

@sfackler
Copy link
Member

They seem reasonable to me.

/// assert_eq!(4, mem::size_of::<i32>());
/// assert_eq!(8, mem::size_of::<f64)());
Copy link
Member

Choose a reason for hiding this comment

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

Typo.

assert_eq!(8, mem::size_of::<f64)());
//                              ^ should be `>`

Copy link
Member

Choose a reason for hiding this comment

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

As kennytm wrote, there is a typo after f64.

///
/// The types `*T`, `&T`, and `Box<T>` have the same size
/// and `Option`s of `&T` and `Box<T>` have the same size as the pointer.
/// Pointers to sized types will be the same size as `usize`.
Copy link
Member

Choose a reason for hiding this comment

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

Could we say "are" instead of "will be", and "has"/"have" instead of "will have" above? The rest of this documentation is written in present tense so "will" makes it seem like those features are not implemented yet.

/// Furthermore, `usize` and `isize` will have the same size.
///
/// The types `*T`, `&T`, and `Box<T>` have the same size
/// and `Option`s of `&T` and `Box<T>` have the same size as the pointer.
Copy link
Member

Choose a reason for hiding this comment

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

I found this a little hard to parse. A skeptical reader would read this as:

Options    &T
       \  /
        of     Box<T>
          \   /
           and                       the pointer
              \                     /
               have the same size as

instead of

        &T     Box<T>
          \   /
Options    and
       \  /
        of                       the pointer
          \                     /
           have the same size as

because that sounds more plausible to someone skeptical of zero overhead abstractions.

Is there a way to word this that shows the full types Option<&T> and Option<Box<T>> in the sentence?

Maybe something straightforward like:

The types *T, &T, Box<T>, Option<&T>, and Option<Box<T>> all have the same size. If T is Sized, all of those have the same size as usize.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I was sort of floundering with that section. That reads a lot better.

@carols10cents carols10cents added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Sep 18, 2017
///
/// The following table gives the size for primitives.
///
/// Type | size_of<Type>()
Copy link
Contributor

Choose a reason for hiding this comment

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

size_of::<Type>()

Copy link
Member

Choose a reason for hiding this comment

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

As durka wrote, this would be clearer as size_of::<Type>() instead of size_of<Type>().

Copy link
Member

Choose a reason for hiding this comment

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

Also I believe these need to be in backticks or escaped with a backslash. Otherwise markdown will treat it as a <Type> HTML tag.

`Type` | `size_of::<Type>()`
Type | size_of::\<Type>()

///
/// Furthermore, `usize` and `isize` will have the same size.
///
/// The types `*T`, `&T`, and `Box<T>` have the same size
Copy link
Contributor

Choose a reason for hiding this comment

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

This might be the first place we say *T instead of *const T/*mut T? Likewise, everything here about &T applies to &mut T.

///
///
/// // Pointer size equality
/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<*i32>());
Copy link
Contributor

Choose a reason for hiding this comment

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

error: expected mut or const in raw pointer type (use `*mut T` or `*const T` as appropriate)

/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<*i32>());
/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<Box<i32>());
/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<Option<&i32>>());
/// assert_eq!(mem::size_of::<Box<i32>>(), mem::size_of::<Option<Box<32>>>());
Copy link
Contributor

Choose a reason for hiding this comment

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

typo Box<32>

@dtolnay
Copy link
Member

dtolnay commented Sep 18, 2017

One more type we guarantee is extern "C" fn(_) -> _ and Option<extern "C" fn(_) -> _> which are guaranteed to be the same size as _ (*)(_) in C. I don't know whether we also guarantee the same for extern "Rust" or whether the size is guaranteed to be the same as usize.

/// // Some arrays
/// assert_eq!(8, mem::size_of::<[i32; 2]>());
/// assert_eq!(12, mem::size_of::<[i32, 3]>());
/// assert_eq!(0, mem::size_of::<[i32, 0]>());
Copy link
Contributor

Choose a reason for hiding this comment

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

; to separate i32 from the length.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought I was running the doctests; I actually wasn't.

@Havvy
Copy link
Contributor Author

Havvy commented Sep 20, 2017

All nits should be fixed. I don't have dtolnay's thing here. I'm wondering if the null pointer optimization for Option-shaped enums is actually stable, and if so, we could just say that, and then point out what the common nullable pointer types are, including fn pointers.

I'm avoiding talking about #[repr(C)] or any other representation here, since I want to do that in its own PR if we want to talk about representations at all in size_of.

I can also squash all the commits into one if you want.

@scottmcm
Copy link
Member

I like what you have here; the Option<&_> and Option<Box<_>> cases are certainly the critical ones.

Details about enum size is probably mixed up in #27730 & rust-lang/rfcs#1230, and fine to leave for later.

/// items of the same type, including alignment padding.
/// More specifically, this is the offset in bytes between successive elements
/// in an array with that item type including alignment padding. Thus, for any
/// type `T` and length `n`, [T; n] will have a size of `n * size_of::<T>()`.
Copy link
Member

Choose a reason for hiding this comment

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

[T; n] should be in backticks.

///
/// The following table gives the size for primitives.
///
/// Type | size_of<Type>()
Copy link
Member

Choose a reason for hiding this comment

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

As durka wrote, this would be clearer as size_of::<Type>() instead of size_of<Type>().

/// f64 | 8
/// char | 4
///
/// Furthermore, `usize` and `isize` will have the same size.
Copy link
Member

Choose a reason for hiding this comment

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

The rest of this documentation is in present tense so "will have" makes it sound like this part is not implemented yet. Plain "have" should be sufficient I think.

/// assert_eq!(4, mem::size_of::<i32>());
/// assert_eq!(8, mem::size_of::<f64)());
Copy link
Member

Choose a reason for hiding this comment

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

As kennytm wrote, there is a typo after f64.

///
/// // Some arrays
/// assert_eq!(8, mem::size_of::<[i32; 2]>());
/// assert_eq!(12, mem::size_of::<[i32, 3]>());
Copy link
Member

Choose a reason for hiding this comment

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

This should say [i32; 3] instead of [i32, 3].

@dtolnay
Copy link
Member

dtolnay commented Sep 20, 2017

r=me after the last few typos are addressed. I agree we don't need to include fn and repr(C) in this PR.

@Havvy
Copy link
Contributor Author

Havvy commented Sep 21, 2017

Finally figured out how to get rustdoc tests to compile for this. Items in libstd from the libcore facade don't actually get tested from ./x.py test src/libstd and I have to do ./x.py test src/libcore instead.

Also rebased everything into a single commit to avoid polluting the commit log with typo fixing and whatnot.

@dtolnay
Copy link
Member

dtolnay commented Sep 21, 2017

@bors r+

@bors
Copy link
Contributor

bors commented Sep 21, 2017

📌 Commit 548686f has been approved by dtolnay

@arielb1
Copy link
Contributor

arielb1 commented Sep 21, 2017

@bors rollup

GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this pull request Sep 21, 2017
Expand size_of docs

This PR does 3 things.

1. Adds a description of what pointer size means to the primitive pages for usize and isize.
2. Says the general size of things is not stable from compiler to compiler.
3. Adds a table of sizes of things that we do guarantee. As this is the first table in the libstd docs, I've included a picture of how that looks.

![](https://i.imgur.com/YZ6IChH.png?1)
frewsxcv added a commit to frewsxcv/rust that referenced this pull request Sep 23, 2017
Expand size_of docs

This PR does 3 things.

1. Adds a description of what pointer size means to the primitive pages for usize and isize.
2. Says the general size of things is not stable from compiler to compiler.
3. Adds a table of sizes of things that we do guarantee. As this is the first table in the libstd docs, I've included a picture of how that looks.

![](https://i.imgur.com/YZ6IChH.png?1)
bors added a commit that referenced this pull request Sep 23, 2017
Rollup of 14 pull requests

- Successful merges: #44554, #44648, #44658, #44712, #44717, #44726, #44745, #44746, #44749, #44759, #44770, #44773, #44776, #44778
- Failed merges:
@bors bors merged commit 548686f into rust-lang:master Sep 23, 2017
@dtolnay dtolnay assigned dtolnay and unassigned steveklabnik Mar 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author.
Projects
None yet
Development

Successfully merging this pull request may close these issues.