profile
viewpoint

emberian/this-week-in-rust 430

Data for this-week-in-rust.org

Gankra/collect-rs 67

Miscellaneous Collections

Gankra/hash-rs 21

Benchmarks of various hashers

Gankra/gif-rs 10

eats a gif, spits out fully decoded frames

Gankra/cargo-crusader 2

Test the downstream impact of Rust crate changes before publishing

emilio/bindgen-talk 1

https://www.meetup.com/Rust-Berlin/events/252872742/

Gankra/chrexam 1

fuck you

Gankra/geo-kit 1

A collection of algorithms and tools for geometric problem solving in HTML5

issue commentFirefoxGraphics/wr-planning

Re-design clip/spatial API for simplicity

yes, i moved to https://bugzilla.mozilla.org/show_bug.cgi?id=1615646

jbonisteel

comment created time in 4 days

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha 09ad3c9a70e7e50b4c0a4afab412a4e282fab97c

fixup

view details

push time in 8 days

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha 0dc4e406266c61015c989dea693a7bf34ca2a233

fixup

view details

push time in 8 days

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha 91fe06b8b1177fc1136728cfdfb8def9b67e9412

more comms

view details

push time in 8 days

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha a2fc9577c6f15e82875baf06298866f73688d870

update ref

view details

push time in 8 days

issue commentFirefoxGraphics/wr-planning

More SVG Layers

I think this is just a dupe of #56 (https://bugzilla.mozilla.org/show_bug.cgi?id=1595799)

@jrmuizel confirmed?

jbonisteel

comment created time in 9 days

issue commentFirefoxGraphics/wr-planning

Re-design clip/spatial API for simplicity

via @mstange

maybe rephrase as: "Items in a stacking context (which are always part of the same reference frame) should only be clipped by clips in that same reference frame"

and "When a clip from an ancestor reference frame needs to be applied, this clip needs to be set on an ancestor stacking context, and then the stacking context will clip you."

jbonisteel

comment created time in 17 days

issue commentFirefoxGraphics/wr-planning

Re-design clip/spatial API for simplicity

There's a few things I want to try here, and not sure how they'll pan out:

  • Make ClipChain into a single clip, use parenting for all relationships
    • Eliminate ClipChain in favour of direct clip parenting
    • OR remove clip parenting
  • If ClipChain/Clip distinction is to be preserved:
    • Make ClipId only Clips, and not ClipChains
    • Make ClipChains only contain ClipIds
    • Make items only clipped by ClipChainIds
  • Pull image masks out of clips, make them into a kind of Filter (since they're similar to the Opacity filter)
  • Factor out SpatialTree and ClipTree from the display list as explicit seperate structures, so that SceneBuilding doesn't need to untangle them itself
  • Break StackingContexts into FilterItem, BlendItem, and Picture to make a clearer seperation of concerns..?

Properties that are True about the web, which we might be relying on and which we might want to enforce at the API level:

  • All items in the same StackingContext must be part of the same ReferenceFrame (but not necessarily the same ScrollFrame..?)
  • One should only ever be clipped by a clip in an ancestor stacking context
    • One should only ever be clipped by a clip in the same stacking context (ancestor clipping handled by the fact that the stacking context itself will clip you)
jbonisteel

comment created time in 18 days

issue commentFirefoxGraphics/wr-planning

SVG Container Item Handling

what's this? @jrmuizel (note #68 also exists)

jbonisteel

comment created time in 18 days

PR closed rust-lang/nomicon

Update send-and-sync.md

I think this line is trying to give &T as an example of something that is Sync.

+1 -1

1 comment

1 changed file

ChrisGreenaway

pr closed time in a month

pull request commentrust-lang/nomicon

Update send-and-sync.md

No, it's trying to say something is T: Sync iff &T: Send

ChrisGreenaway

comment created time in a month

issue commentdjg/peek-poke

Publish on crates.io

I wouldn't be comfortable publishing this without several strong disclaimers indicating that this library isn't designed to be used outside of webrender, and that you should prefer using bincode until you have determined that its performance is unacceptable.

It would also need to better document its footguns and corner cases, which I handwaived for the webrender usecase because I had a solid understanding of the kinds of things it would be used for/with.

kvark

comment created time in a month

pull request commentrust-lang/hashbrown

Make HaspMap and RawTable to be repr(C)

Oh right yea I was discussing this more with kvark and reminded myself of The Destructor Problem. Destructors affect ABI significantly, so in reality HashMap shouldn't ever be passed by-value, it should be passed by-mutable-ref and swapped. That said it's still "fine" to store in C++ as long as you're fine with leaks.

kvark

comment created time in a month

pull request commentrust-lang/hashbrown

Make HaspMap and RawTable to be repr(C)

we don't need size/align to be guaranteed, only for it to be derivable from the source code (using cbindgen to generate a header at build time). without repr(c) this cannot be done reliably as rust makes no guarantees. furthermore, field ordering/types are required for pass-by-value, because ABIs scalarize the fields of structs into registers based on their types.

On Mon, Jan 13, 2020 at 2:51 PM Amanieu notifications@github.com wrote:

I don't think repr(C) will really help here since all it does is fix the field order in the struct. Generally the internal details of the HashMap type, including its fields and their ordering, is not something that we provide API guarantees for.

Your best bet here might be to have an assert to check that the HashMap size/align are what you expect them to be, and then silence the FFI-unsafe warning.

Could you show me the code where you try to pass a HashMap through FFI?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/rust-lang/hashbrown/pull/140?email_source=notifications&email_token=AAIVRYGH6LUAECUBW56NFN3Q5TA4VA5CNFSM4KGGJHXKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEI2BVFY#issuecomment-573840023, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAIVRYBFFU7X7VLEQ3KM6NTQ5TA4VANCNFSM4KGGJHXA .

kvark

comment created time in a month

pull request commentrust-lang/hashbrown

Make HaspMap and RawTable to be repr(C)

Clarification: adding an FFI-hostile item to the representation would be "breaking". So anything non-trivial from std, or almost any tagged union besides Option<NonNull>.

kvark

comment created time in a month

pull request commentrust-lang/hashbrown

Make HaspMap and RawTable to be repr(C)

I think this should be ~fine to do, as we aren't guaranteeing these facts in the standard library, just in HashBrown, which is ostensibly dedicated to being a particular implementation. Furthermore the cbindgen usecase doesn't preclude actually changing the layout of these structs, because all that usecase needs is the ability to compute the current layout; not a guarantee that future versions won't change the layout.

Specifically outlining/inling/removing/adding fields is fine. More specifically, adding an Allocator generic parameter/field is also fine, because the default Global one should be zero-sized, and cbindgen ignores zero-sized things (just as it would for BuildHasherDefault).

kvark

comment created time in a month

issue commenteqrion/cbindgen

Support generating opaque type with correct size and alignment for non-`#[repr(C)]` types

I am no longer of the opinion that it's a good idea to use things like -Zprint-type-sizes or other such hacks. The original premise of this bug is flawed, you need detailed information on the shape of the struct, as I discuss here:

https://gankra.github.io/blah/rust-layouts-and-abis/#abi

jrmuizel

comment created time in a month

push eventcontain-rs/linked-hash-map

Tad Hardesty

commit sha df65b33f8a9dbd06b95b0a6af7521f0d47233545

Fix mem::uninitialized UB warning

view details

Alexis Beingessner

commit sha 4f681be6f3b1b2c7d67647ce3abbe48470e20855

Merge pull request #100 from SpaceManiac/fix-ub-warnings Fix mem::uninitialized UB warning

view details

push time in 2 months

PR merged contain-rs/linked-hash-map

Fix mem::uninitialized UB warning

Scary-looking warning fixable as far as I can tell with one-line patch

warning: use of deprecated item 'std::mem::uninitialized': use `mem::MaybeUninit` instead
    --> src/lib.rs:1138:29
     |
1138 |         self.map = unsafe { mem::uninitialized() };
     |                             ^^^^^^^^^^^^^^^^^^
     |
     = note: `#[warn(deprecated)]` on by default

warning: the type `std::collections::HashMap<KeyRef<K>, *mut Node<K, V>, S>` does not permit being left uninitialized
    --> src/lib.rs:1138:29
     |
1138 |         self.map = unsafe { mem::uninitialized() };
     |                             ^^^^^^^^^^^^^^^^^^^^
     |                             |
     |                             this code causes undefined behavior when executed
     |                             help: use `MaybeUninit<T>` instead
     |
     = note: `#[warn(invalid_value)]` on by default
note: std::ptr::NonNull<u8> must be non-null (in this struct field)
+1 -1

0 comment

1 changed file

SpaceManiac

pr closed time in 2 months

issue commenteqrion/cbindgen

support emitting a types-only subheader

I think you have it backwards? The function signatures one would include the types header and be effectively the same as today's header. But it would be nice to have the types header split out for things that only need to pass those types around.

This would make it possible to mess around with the function signatures without needing to rebuild as much, as long as all the types stay the same.

Gankra

comment created time in 2 months

issue commenteqrion/cbindgen

support emitting a types-only subheader

also it's fine that such a header would include auto-generated methods like ctors/dtors/operators. those presumably only change in lockstep with the type, so you need to rebuild the world anyway.

Gankra

comment created time in 2 months

issue commenteqrion/cbindgen

support emitting a types-only subheader

context: a lot of code randomly traffics in webrender types, but doesn't care about the actual WR API. It would be nice if API changes didn't make us rebuild all those type-referencing files.

Gankra

comment created time in 2 months

issue openedeqrion/cbindgen

support emitting a types-only subheader

Looking at the code this is actually probably pretty easy. We buffer up literally everything until the end, so we should in theory be able to emit just the types into another file. Ideally the "full" header would just include the types header in this mode.

Specifically you would want a version of write_to_file that takes two files and splits this general item-processing part across the two:

https://github.com/eqrion/cbindgen/blob/9b5dd80d84cc4b0e0b696383b3d9b314d752bcbd/src/bindgen/bindings.rs#L226-L235

And then invoke it here:

https://github.com/eqrion/cbindgen/blob/b8140911ee843af93e6314fee72be96e30df63a6/src/main.rs#L255-L267

created time in 2 months

pull request commentrust-unofficial/too-many-lists

fixed spelling in fifth-unsafe.md

lint is correct

but thanks!

patmuk

comment created time in 2 months

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha 49d45a56524092dc08020365afbef24006446d4d

comms

view details

push time in 2 months

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha 56540e8cd886c8c42e763c9be107676d46323694

comms

view details

push time in 2 months

push eventcontain-rs/bit-vec

yihuang

commit sha 88b27b34c35560bc1b6311d2b801a370debdbdac

Remove unneeded unstable feature I think we don't need alloc_prelude since alloc is stablized.

view details

Alexis Beingessner

commit sha 7d08dccf546fff969cd9b9ed958c23eb3264afa6

Merge pull request #64 from yihuang/patch-1 Remove unneeded unstable feature

view details

push time in 3 months

PR merged contain-rs/bit-vec

Remove unneeded unstable feature

I think we don't need alloc_prelude since alloc is stablized.

+0 -1

0 comment

1 changed file

yihuang

pr closed time in 3 months

pull request commentrust-lang/rust

BTreeMap/BTreeSet drain & retain

ok yeah sorry i don't have the spare bandwidth for this review

ssomers

comment created time in 3 months

issue commentrust-lang/rust

Tracking issue for SIMD support

Ah, excellent!

   Compiling playground v0.0.1 (/playground)
error: use of SIMD type `Test` in FFI is highly experimental and may result in invalid code
 --> src/main.rs:9:19
  |
9 |     fn hello(val: Test);
  |                   ^^^^
  |
  = help: add `#![feature(simd_ffi)]` to the crate attributes to enable

Ok then I think it's ok to pretend repr-simd doesn't exist for the purposes of ffi/abi docs.

alexcrichton

comment created time in 3 months

pull request commentrust-lang/rust

BTreeMap/BTreeSet drain & retain

Do we need to do anything special to check this against miri? BTreeMap has historically been very good at running afoul of it.

ssomers

comment created time in 3 months

issue commentrust-lang/rust

Tracking issue for SIMD support

It has calling-convention implications in the sysv x64 ABI (It gives the type the SSE/SSEUP class), so it's kinda important for FFI. Not hugely important but it feels in scope for the new FFI section I'm writing for the rustonomicon. (e.g. gcc's __float128 is treated equivalently to repr(simd), and I believe can be bridged to our __m128 type).

It's plausible that we don't want to admit this is true, but by default I'm inclined to document it.

alexcrichton

comment created time in 3 months

issue commentrust-lang/rust

Tracking issue for SIMD support

Which are those? All the references to simd types on stable are dead links or closed RFCs, and nothing shows up in std's rustdoc instance.

alexcrichton

comment created time in 3 months

issue commentrust-lang/rust

Tracking issue for SIMD support

Just confirming for the sake of documentation: we don't actually publicly (and stably?) expose any repr(simd) types, right?

alexcrichton

comment created time in 3 months

push eventrust-lang/nomicon

CreepySkeleton

commit sha 8be35b201f9cf0a4c3fcc96c83ac21671dcf3112

Update unwinding.md `catch_unwind` is not unstable anymore

view details

push time in 3 months

PR merged rust-lang/nomicon

Update unwinding.md

catch_unwind is not unstable anymore

+1 -1

0 comment

1 changed file

CreepySkeleton

pr closed time in 3 months

push eventrust-lang/nomicon

Lzu Tao

commit sha f2f2e4b60b8e1a9d94466b20bb50a54773ca7955

ci: remove needless rust-docs component

view details

push time in 3 months

issue commentservo/webrender

Update serde

the serde patch should have been removed months ago, fwiw. it was obsoleted when we shipped peek-poke.

nox

comment created time in 3 months

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha 742e78a8feb0a45bf7f2d11c65aa5d01479dc08b

update comms

view details

push time in 3 months

pull request commentapple/swift

Eager HashedCollections Bridging

i feel like y'all should maybe have a better understanding of what your project should do than me, someone who hasn't worked here for 3 years?

Gankra

comment created time in 3 months

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha 954cb12b009bb17180dc4312d48d068e57d59d6f

21 pages

view details

push time in 3 months

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha 61e804e4d4f0541c05344f7b0becc8bb943d2a30

yerp

view details

push time in 3 months

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha fbd2b294cd07eb182595cc540f868144e545e773

add articles to index

view details

push time in 3 months

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha 3c9840c4b94076a40ada5f516d3668c3091e9e7a

trivia

view details

push time in 3 months

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha 3be7fe4a3d9aaadadb5fa6ff6b366df0d694804d

Better wording

view details

push time in 3 months

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha 0e10f23d4285c31cc8203014e94189e4f7aebcc0

Better wording

view details

push time in 3 months

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha b5df6955bb282b7304ad1f11c40479d276dd97c0

tweak link

view details

push time in 3 months

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha 208a6e8a99f2d9b4bb937fe6751eca6cecb780c0

update layout with bool link

view details

push time in 3 months

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha 180717ed2fee2d674b369a1db1c81fc473efde13

ship it

view details

push time in 3 months

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha b46b2ec8c859ae36c3ad24af04f4afb017f6d6f2

remove aside

view details

push time in 3 months

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha 3fee1fd8e1e11ae495613bd88a64c7ce5120e3fe

remove aside

view details

push time in 3 months

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha 766bd6564138e7aa7d9c6286d09c6ed695490fc5

ownership compare

view details

push time in 3 months

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha eca1b517947659b4781c57f43734942b22be9e86

ownership compare

view details

push time in 3 months

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha 8c66f5304a25253260fdfcb9294b15547cf138f0

ownership compare

view details

push time in 3 months

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha ed57a7f6d7a11ec6fcd9aa8b5a4fb3bce70f6904

ABI and style rework

view details

push time in 3 months

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha 53fcc804e22d1aa041c4aa296f08e82fb79fa6c4

swift abi tweaks from discussion

view details

push time in 3 months

push eventGankra/gankra.github.io

Alexis Beingessner

commit sha b133ccf00d2ae8e4e5cb9445c2a9792ad73b1b2c

swift abi wip

view details

push time in 3 months

Pull request review commentapple/swift

[docs] Modernize LibraryEvolution.rst, part 2

+# Introduction++This document is intended to discuss current issues in and possible future expansions of Swift's model for ABI-stable _library evolution,_ described in [LibraryEvolution.rst][]. Like other "manifesto" documents in the Swift community, it sets out related tasks in service of a general goal, though this is still an exploration of the space more than a to-do list.++[LibraryEvolution.rst]: ./LibraryEvolution.rst+++# Open Issues+++## Recompiling changes a protocol's implementation		++```swift+// Library, version 1+protocol MagicType {}+protocol Wearable {}+func use<T: MagicType>(_ item: T) {}+```++```swift+// Client, version 1+struct Amulet : MagicType, Wearable {}+use(Amulet())+```++```swift+// Library, version 2+protocol MagicType {+  @available(dishwasherOS 2.0, *)+  func equip()+}+extension MagicType {+  @available(dishwasherOS 2.0, *)+  func equip() { print("Equipped.") }+}++protocol Wearable {}+extension Wearable where Self: MagicType {+  @available(dishwasherOS 2.0, *)+  func equip() { print("You put it on.") }+}++func use<T: MagicType>(_ item: T) { item.equip() }+```++Let's say we're running dishwasherOS 2.0. Before the client is recompiled, the implementation of `equip()` used for `Amulet` instances can only be the default implementation, i.e. the one that prints "Equipped". However, recompiling the client will result in the constrained implementation being considered a "better" match for the protocol requirement, thus changing the behavior of the program.++This should never change the *meaning* of a program, since the default implementation for a newly-added requirement should always be *correct.* However, it may have significantly different performance characteristics or side effects that would make the difference in behavior a surprise.++This is similar to adding a new overload to an existing set of functions, which can also change the meaning of client code just by recompiling. However, the difference here is that the before-recompilation behavior was never requested or acknowledged by the client; it's just the best the library can do.++A possible solution here is to require the client to acknowledge the added requirement in some way when it is recompiled.++(We do not want to perform overload resolution at run time to find the best possible default implementation for a given type.)+++# Evolving Attributes++A number of annotations (attributes and modifiers) would benefit from being able to change between releases of a library. For example:++- Making a `public` class `open`.+- Making a `public` class `final`.+- Making a struct or enum `@frozen`.+- Making a function `@inlinable`.++However, all of these changes have to be associated with a specific release to be correct:++- The newly-`open` class can't be subclassed if the client's deployment target is too old.+- Convenience initializers on a newly-`final` class can't satisfy protocol requirements if the client's deployment target is too old.+- A newly-`@frozen` struct may have had more private stored properties in the past.+- A newly-`@inlinable` function's body may not work correctly with older versions of the library.++While solutions can be tailored to each of these problems, they have a common need to record the OS version when an annotation is added or changed. Without that, we're locked in to the way a declaration is originally published, or having to take correctness on faith.++## Limitations

Also is frozen the only example of a non-addable ABI attr? The wording suggested there are more, but I can't think of any other obvious ones (might be good to enumerate them here if they exist?)

jrose-apple

comment created time in 4 months

Pull request review commentapple/swift

[docs] Modernize LibraryEvolution.rst, part 2

+# Introduction++This document is intended to discuss current issues in and possible future expansions of Swift's model for ABI-stable _library evolution,_ described in [LibraryEvolution.rst][]. Like other "manifesto" documents in the Swift community, it sets out related tasks in service of a general goal, though this is still an exploration of the space more than a to-do list.++[LibraryEvolution.rst]: ./LibraryEvolution.rst+++# Open Issues+++## Recompiling changes a protocol's implementation		++```swift+// Library, version 1+protocol MagicType {}+protocol Wearable {}+func use<T: MagicType>(_ item: T) {}+```++```swift+// Client, version 1+struct Amulet : MagicType, Wearable {}+use(Amulet())+```++```swift+// Library, version 2+protocol MagicType {+  @available(dishwasherOS 2.0, *)+  func equip()+}+extension MagicType {+  @available(dishwasherOS 2.0, *)+  func equip() { print("Equipped.") }+}++protocol Wearable {}+extension Wearable where Self: MagicType {+  @available(dishwasherOS 2.0, *)+  func equip() { print("You put it on.") }+}++func use<T: MagicType>(_ item: T) { item.equip() }+```++Let's say we're running dishwasherOS 2.0. Before the client is recompiled, the implementation of `equip()` used for `Amulet` instances can only be the default implementation, i.e. the one that prints "Equipped". However, recompiling the client will result in the constrained implementation being considered a "better" match for the protocol requirement, thus changing the behavior of the program.++This should never change the *meaning* of a program, since the default implementation for a newly-added requirement should always be *correct.* However, it may have significantly different performance characteristics or side effects that would make the difference in behavior a surprise.++This is similar to adding a new overload to an existing set of functions, which can also change the meaning of client code just by recompiling. However, the difference here is that the before-recompilation behavior was never requested or acknowledged by the client; it's just the best the library can do.++A possible solution here is to require the client to acknowledge the added requirement in some way when it is recompiled.++(We do not want to perform overload resolution at run time to find the best possible default implementation for a given type.)+++# Evolving Attributes++A number of annotations (attributes and modifiers) would benefit from being able to change between releases of a library. For example:++- Making a `public` class `open`.+- Making a `public` class `final`.+- Making a struct or enum `@frozen`.+- Making a function `@inlinable`.++However, all of these changes have to be associated with a specific release to be correct:++- The newly-`open` class can't be subclassed if the client's deployment target is too old.+- Convenience initializers on a newly-`final` class can't satisfy protocol requirements if the client's deployment target is too old.+- A newly-`@frozen` struct may have had more private stored properties in the past.+- A newly-`@inlinable` function's body may not work correctly with older versions of the library.++While solutions can be tailored to each of these problems, they have a common need to record the OS version when an annotation is added or changed. Without that, we're locked in to the way a declaration is originally published, or having to take correctness on faith.++## Limitations

did you not mangle the frozen and non-frozen versions differently? (which would allow you to just export both versions for some APIs)

jrose-apple

comment created time in 4 months

pull request commentapple/swift

[docs] Modernize LibraryEvolution.rst, part 1

Aha, access control deals with it, perfect!

(The static usableFromInline check, and the fact that the default initializers cannot be annotated at all, are also necessary to fully tie this knot, btw. It's subtle enough that I would still err on the side of having a throwaway line explicitly clarifying it, but ymmv.)

jrose-apple

comment created time in 4 months

pull request commentapple/swift

[docs] Modernize LibraryEvolution.rst, part 1

Following up on twitter discussion, you should maybe remove the link to your hosted rendering that's at the top of this document, assuming you don't want that to exist anymore.

jrose-apple

comment created time in 4 months

pull request commentapple/swift

[docs] Modernize LibraryEvolution.rst, part 1

request: please explicitly call out the implications of a struct with a "please pass all the fields" default initializer. A naive reading of this document suggests it "should" be ABI-compatible to add a field, but it's not because it changes the signature of the default initializer, and I don't see any way that version attributes would allow the old version of the initializer to continue to exist (since nothing declares a default value to use).

(Might be implied by a section I skimmed over, happy to be wrong)


// Library Code

// version 1
struct MyTypeV1 {
    public var x: Int;
}

// version 2
struct MyTypeV2 {
    public var x: Int;
    public var y: Int;
}




// App Code

MyTypeV1(x: 0); // linked against v1
MyTypeV2(x: 0); // linked against v2

// error: missing argument for parameter 'y' in call
// MyTypeV2(x: 0); // linked against v2
//              ^
//              , y: <#Int#>
jrose-apple

comment created time in 4 months

issue commentrust-unofficial/too-many-lists

First example fails to induce E0072

No idea what's happening for you, but it definitely seems to still not build on nightly: https://play.rust-lang.org/?version=nightly&mode=release&edition=2018&gist=f782daa65ed8da173d9e63d0facf6e8b

My only guess is that you're literally not building the file you put that code in?

MatthijsBlom

comment created time in 4 months

issue commentservo/webrender

peek-poke is unsound

The code predates MaybeUninit's stabilization, so yeah we could reasonably update to use it so we can "forget" about the issue and have it solved for us later.

Just not a big deal in my mind.

nox

comment created time in 4 months

issue commentservo/webrender

peek-poke is unsound

That's just the same code hidden behind a function call :)

nox

comment created time in 4 months

issue commentservo/webrender

peek-poke is unsound

Yeah it's "Documentation UB" in that it's reserved just to be conservative but it's pretty obvious this pattern needs to be doable somehow, so it's only UB insofar as the lang team has failed to design a mechanism that they're happy with for expressing this pattern.

Which is to say, this code is fine today. I maintain the docs that say this is UB, and I reviewed the code, so this code was accepted with full awareness of the situation. Ralf is also aware of my stance on this problem from the discussion we've had on the aforementionned docs.

Some day, the lang team might either:

  • Decide it's fine (no changes needed)
  • Design a new thing to express this pattern (like &raw or offsetof) and then we can update the code to use that.

Note that I made peek_from only work with *mut T so this is literally the &raw/offsetof usecase (transiently creating an &mut simply because we lack another way to compute an address).

nox

comment created time in 4 months

PR closed rust-lang-nursery/nomicon

Fix the versioning of libc

The following versioning libc = "0.2" should be better?

ref:crate.io, README

+1 -1

3 comments

1 changed file

chansuke

pr closed time in 4 months

pull request commentrust-lang-nursery/nomicon

Fix the versioning of libc

yeah i like the full version too, but thanks for the patch!

chansuke

comment created time in 4 months

pull request commentrust-lang-nursery/nomicon

Fix the versioning of libc

@steveklabnik any opinion from the SemVer guru who also wrote this section?

chansuke

comment created time in 4 months

issue commentrust-lang/rust

FCP for toolstate changes

yes the effort/impact calculus is a bit different between An Entire Interpretter and The Docs (I was tagged into this thread for the docs I maintain).

Mark-Simulacrum

comment created time in 4 months

PR merged contain-rs/bit-set

Upgrade to bit-vec 0.6.1
+1 -2

0 comment

1 changed file

wfarner

pr closed time in 4 months

push eventcontain-rs/bit-set

Bill Farner

commit sha 90ad34c4cb15d15c310f5926c9e5d1b76617e699

Upgrade to bit-vec 0.6.1

view details

Alexis Beingessner

commit sha c27082fb8a37766909be6e323c0c82a6f8bdfe58

Merge pull request #18 from wfarner/bit-vec Upgrade to bit-vec 0.6.1

view details

push time in 4 months

issue commentrust-lang/rust

FCP for toolstate changes

I still maintain that including these projects in-tree is the ideal solution. That way the tools cannot ever break, everyone is responsible for keeping them working, and mutual changes can be performed atomically. e.g. When an unstable API is changed, the uses of that API must also be changed, and there is no ordering that works -- both must happen at the same time.

"Everyone is responsible" is especially important because generally the person making a breaking change can trivially fix the tools (because they intimately understand the implications), but the maintainers of the tools just get sudden broken builds and they need to spend a ton of time asking around about what changed and how they're supposed to handle it.

Additionally I think it is a significant detriment to the various pieces of documentation that they are completely hidden from the folks that develop the features being documented. This helps documentation get reviewed and triaged in a timely and robust fashion.


Alternatively, tools could have a two-tiered CI:

  • master build: always builds with the rust master, warns on failure
  • pinned build: always builds with that version, hard errors on failure

(For maintenance reasons, the pinned build should auto-bump whenever the master build passes)

This would allow us to distinguish between "the build is broken because rust-lang broke us" and "the build is broken because we made bad changes". This would also "fix" the atomic unstable API problem, as rust could move first, then the tools could update to work on the new rust, and then rust could update the submodule.

As it is, we have to rely on janky hacks where:

  1. the tool makes a second branch that "should" work with the new rust implementation
  2. rust updates and also repoints the submodule at that branch
  3. the branch is merged into the tools master
  4. rust updates to point at master

This is especially problematic because branch management is not something bors and friends support doing, requiring a github-acknolwedged admin of the repo to get involved. Step 1 also bypasses CI, so we can only catch problems at step 2, sending us back to step 1.

Mark-Simulacrum

comment created time in 5 months

Pull request review commentrust-lang-nursery/nomicon

Update sample code with stable alloc crate

 method of RawVec. ```rust,ignore impl<T> RawVec<T> {     fn new() -> Self {-        // !0 is usize::MAX. This branch should be stripped at compile time.-        let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 };-+        // This branch should be stripped at compile time.+        let cap = if mem::size_of::<T>() == 0 {+            std::usize::MAX+        } else {+            0+        };         // Unique::empty() doubles as "unallocated" and "zero-sized allocation"-        RawVec { ptr: Unique::empty(), cap: cap }+        Self {+            ptr: Unique::empty(),+            cap,+        }     }      fn grow(&mut self) {         unsafe {-            let elem_size = mem::size_of::<T>();--            // since we set the capacity to usize::MAX when elem_size is+            // Since we set the capacity to `usize::MAX` for ZST is             // 0, getting to here necessarily means the Vec is overfull.-            assert!(elem_size != 0, "capacity overflow");+            assert!(mem::size_of::<T>() != 0, "capacity overflow"); -            let align = mem::align_of::<T>();+            let layout = alloc::Layout::new::<T>();              let (new_cap, ptr) = if self.cap == 0 {-                let ptr = heap::allocate(elem_size, align);+                let ptr = alloc::alloc(layout);                 (1, ptr)             } else {-                let new_cap = 2 * self.cap;-                let ptr = heap::reallocate(self.ptr.as_ptr() as *mut _,-                                            self.cap * elem_size,-                                            new_cap * elem_size,-                                            align);+                let new_cap = self.cap * 2;+                let ptr = alloc::realloc(+                    self.ptr.as_ptr() as *mut u8,+                    layout,+                    new_cap * mem::size_of::<T>(),+                );                 (new_cap, ptr)             };              // If allocate or reallocate fail, we'll get `null` back-            if ptr.is_null() { oom() }+            if ptr.is_null() {+                alloc::handle_alloc_error(layout);+            } -            self.ptr = Unique::new(ptr as *mut _);+            self.ptr = Unique::new_unchecked(ptr as *mut T);             self.cap = new_cap;         }     } }  impl<T> Drop for RawVec<T> {     fn drop(&mut self) {-        let elem_size = mem::size_of::<T>();--        // don't free zero-sized allocations, as they were never allocated.-        if self.cap != 0 && elem_size != 0 {-            let align = mem::align_of::<T>();--            let num_bytes = elem_size * self.cap;+        // Do not free zero-sized allocations, as they were never allocated.+        if self.cap != 0 && mem::size_of::<T>() != 0 {             unsafe {-                heap::deallocate(self.ptr.as_ptr() as *mut _, num_bytes, align);+                alloc::dealloc(self.ptr.as_ptr() as *mut u8, alloc::Layout::new::<T>());

Another incorrect layout.

lzutao

comment created time in 5 months

Pull request review commentrust-lang-nursery/nomicon

Update sample code with stable alloc crate

 impl<T> Drop for IntoIter<T> { impl<T> Vec<T> {     pub fn into_iter(self) -> IntoIter<T> {         unsafe {-            // need to use ptr::read to unsafely move the buf out since it's+            // need to use `ptr::read` to unsafely move the buf out since it's             // not Copy, and Vec implements Drop (so we can't destructure it).             let buf = ptr::read(&self.buf);             let len = self.len;             mem::forget(self);              IntoIter {-                start: *buf.ptr,-                end: buf.ptr.offset(len as isize),+                start: buf.ptr.as_ptr(),+                end: if buf.cap == 0 {+                    // can't offset off this pointer, it's not allocated!+                    buf.ptr.as_ptr()+                } else {+                    buf.ptr.as_ptr().offset(len as isize)+                },

I'm pretty sure this is unnecessary, but it's fair this isn't documented properly.

https://github.com/rust-lang/rust/issues/65108

lzutao

comment created time in 5 months

Pull request review commentrust-lang-nursery/nomicon

Update sample code with stable alloc crate

 method of RawVec. ```rust,ignore impl<T> RawVec<T> {     fn new() -> Self {-        // !0 is usize::MAX. This branch should be stripped at compile time.-        let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 };-+        // This branch should be stripped at compile time.+        let cap = if mem::size_of::<T>() == 0 {+            std::usize::MAX+        } else {+            0+        };         // Unique::empty() doubles as "unallocated" and "zero-sized allocation"-        RawVec { ptr: Unique::empty(), cap: cap }+        Self {+            ptr: Unique::empty(),+            cap,+        }     }      fn grow(&mut self) {         unsafe {-            let elem_size = mem::size_of::<T>();--            // since we set the capacity to usize::MAX when elem_size is+            // Since we set the capacity to `usize::MAX` for ZST is             // 0, getting to here necessarily means the Vec is overfull.-            assert!(elem_size != 0, "capacity overflow");+            assert!(mem::size_of::<T>() != 0, "capacity overflow"); -            let align = mem::align_of::<T>();+            let layout = alloc::Layout::new::<T>();              let (new_cap, ptr) = if self.cap == 0 {-                let ptr = heap::allocate(elem_size, align);+                let ptr = alloc::alloc(layout);                 (1, ptr)             } else {-                let new_cap = 2 * self.cap;-                let ptr = heap::reallocate(self.ptr.as_ptr() as *mut _,-                                            self.cap * elem_size,-                                            new_cap * elem_size,-                                            align);+                let new_cap = self.cap * 2;+                let ptr = alloc::realloc(+                    self.ptr.as_ptr() as *mut u8,+                    layout,

Another wrong layout.

lzutao

comment created time in 5 months

Pull request review commentrust-lang-nursery/nomicon

Update sample code with stable alloc crate

 method of RawVec. ```rust,ignore impl<T> RawVec<T> {     fn new() -> Self {-        // !0 is usize::MAX. This branch should be stripped at compile time.-        let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 };-+        // This branch should be stripped at compile time.+        let cap = if mem::size_of::<T>() == 0 {+            std::usize::MAX+        } else {+            0+        };         // Unique::empty() doubles as "unallocated" and "zero-sized allocation"-        RawVec { ptr: Unique::empty(), cap: cap }+        Self {+            ptr: Unique::empty(),+            cap,+        }     }      fn grow(&mut self) {         unsafe {-            let elem_size = mem::size_of::<T>();--            // since we set the capacity to usize::MAX when elem_size is+            // Since we set the capacity to `usize::MAX` for ZST is             // 0, getting to here necessarily means the Vec is overfull.-            assert!(elem_size != 0, "capacity overflow");+            assert!(mem::size_of::<T>() != 0, "capacity overflow");

You should make this check the layout.size(), but I guess that doesn't matter because you probably need to redo this code because this is the wrong layout in the general case.

lzutao

comment created time in 5 months

Pull request review commentrust-lang-nursery/nomicon

Update sample code with stable alloc crate

 impl<T> Drop for IntoIter<T> {         if self.cap != 0 {             // drop any remaining elements             for _ in &mut *self {}--            let align = mem::align_of::<T>();-            let elem_size = mem::size_of::<T>();-            let num_bytes = elem_size * self.cap;             unsafe {-                heap::deallocate(self.buf.as_ptr() as *mut _, num_bytes, align);+                alloc::dealloc(self.buf.as_ptr() as *mut _, alloc::Layout::new::<T>());

Another place with an incorrect Layout.

lzutao

comment created time in 5 months

Pull request review commentrust-lang-nursery/nomicon

Update sample code with stable alloc crate

 impl<T> Drop for IntoIter<T> { impl<T> Vec<T> {     pub fn into_iter(self) -> IntoIter<T> {         unsafe {-            // need to use ptr::read to unsafely move the buf out since it's+            // need to use `ptr::read` to unsafely move the buf out since it's

These backticks aren't really helpful inside comments, since the markdown is never rendered.

lzutao

comment created time in 5 months

Pull request review commentrust-lang-nursery/nomicon

Update sample code with stable alloc crate

 using the old len. pub fn insert(&mut self, index: usize, elem: T) {     // Note: `<=` because it's valid to insert after everything     // which would be equivalent to push.-    assert!(index <= self.len, "index out of bounds");-    if self.cap == self.len { self.grow(); }+    assert!(self.len >= index, "index is out of bounds");

Why did you invert this assertion? This is not standard style.

lzutao

comment created time in 5 months

Pull request review commentrust-lang-nursery/nomicon

Update sample code with stable alloc crate

 Remove behaves in the opposite manner. We need to shift all the elements from ```rust,ignore pub fn remove(&mut self, index: usize) -> T {     // Note: `<` because it's *not* valid to remove after everything-    assert!(index < self.len, "index out of bounds");+    assert!(self.len > index, "index is out of bounds");+

Another changed assertion.

lzutao

comment created time in 5 months

Pull request review commentrust-lang-nursery/nomicon

Update sample code with stable alloc crate

 using the old len. pub fn insert(&mut self, index: usize, elem: T) {     // Note: `<=` because it's valid to insert after everything     // which would be equivalent to push.-    assert!(index <= self.len, "index out of bounds");-    if self.cap == self.len { self.grow(); }+    assert!(self.len >= index, "index is out of bounds");+    if self.cap == self.len {+        self.grow();+    }      unsafe {         if index < self.len {-            // ptr::copy(src, dest, len): "copy from source to dest len elems"-            ptr::copy(self.ptr.offset(index as isize),-                      self.ptr.offset(index as isize + 1),-                      self.len - index);+            ptr::copy(+                self.ptr.as_ptr().offset(index as isize),+                self.ptr.as_ptr().offset(index as isize + 1),+                self.len - index,+            );

Why did you remove this comment?

lzutao

comment created time in 5 months

Pull request review commentrust-lang-nursery/nomicon

Update sample code with stable alloc crate

 such we will guard against this case explicitly. Ok with all the nonsense out of the way, let's actually allocate some memory:  ```rust,ignore-use std::alloc::oom;+use std::alloc;  fn grow(&mut self) {     // this is all pretty delicate, so let's say it's all unsafe     unsafe {-        // current API requires us to specify size and alignment manually.-        let align = mem::align_of::<T>();-        let elem_size = mem::size_of::<T>();+        let layout = alloc::Layout::new::<T>();          let (new_cap, ptr) = if self.cap == 0 {-            let ptr = heap::allocate(elem_size, align);+            let ptr = alloc::alloc(layout);             (1, ptr)         } else {             // as an invariant, we can assume that `self.cap < isize::MAX`,             // so this doesn't need to be checked.             let new_cap = self.cap * 2;             // Similarly this can't overflow due to previously allocating this-            let old_num_bytes = self.cap * elem_size;+            let old_num_bytes = self.cap * mem::size_of::<T>();              // check that the new allocation doesn't exceed `isize::MAX` at all             // regardless of the actual size of the capacity. This combines the             // `new_cap <= isize::MAX` and `new_num_bytes <= usize::MAX` checks             // we need to make. We lose the ability to allocate e.g. 2/3rds of             // the address space with a single Vec of i16's on 32-bit though.             // Alas, poor Yorick -- I knew him, Horatio.-            assert!(old_num_bytes <= (::std::isize::MAX as usize) / 2,-                    "capacity overflow");+            assert!(+                old_num_bytes <= (std::isize::MAX as usize) / 2,+                "capacity overflow"+            );              let new_num_bytes = old_num_bytes * 2;-            let ptr = heap::reallocate(self.ptr.as_ptr() as *mut _,-                                        old_num_bytes,-                                        new_num_bytes,-                                        align);+            let ptr = alloc::realloc(self.ptr.as_ptr() as *mut u8, layout, new_num_bytes);

This isn't correct. The layout you need to pass here is for an array, but this is the layout for a single value. You must use from_size_align_unchecked or from_size_align (generally the former is more appropriate since we're doing our own error-handling).

lzutao

comment created time in 5 months

Pull request review commentrust-lang-nursery/nomicon

Update sample code with stable alloc crate

 struct RawVec<T> { impl<T> RawVec<T> {     fn new() -> Self {         assert!(mem::size_of::<T>() != 0, "TODO: implement ZST support");-        RawVec { ptr: Unique::empty(), cap: 0 }+        Self {+            ptr: Unique::empty(),+            cap: 0,+        }     }      // unchanged from Vec     fn grow(&mut self) {+        // this is all pretty delicate, so let's say it's all unsafe         unsafe {-            let align = mem::align_of::<T>();-            let elem_size = mem::size_of::<T>();+            let layout = alloc::Layout::new::<T>();              let (new_cap, ptr) = if self.cap == 0 {-                let ptr = heap::allocate(elem_size, align);+                let ptr = alloc::alloc(layout);                 (1, ptr)             } else {-                let new_cap = 2 * self.cap;-                let ptr = heap::reallocate(self.ptr.as_ptr() as *mut _,-                                            self.cap * elem_size,-                                            new_cap * elem_size,-                                            align);+                let new_cap = self.cap * 2;+                let ptr = alloc::realloc(+                    self.ptr.as_ptr() as *mut u8,+                    layout,+                    new_cap * mem::size_of::<T>(),+                );                 (new_cap, ptr)             };              // If allocate or reallocate fail, we'll get `null` back-            if ptr.is_null() { oom() }+            if ptr.is_null() {+                alloc::handle_alloc_error(layout);+            } -            self.ptr = Unique::new(ptr as *mut _);+            self.ptr = Unique::new_unchecked(ptr as *mut T);             self.cap = new_cap;         }     } } - impl<T> Drop for RawVec<T> {     fn drop(&mut self) {         if self.cap != 0 {-            let align = mem::align_of::<T>();-            let elem_size = mem::size_of::<T>();-            let num_bytes = elem_size * self.cap;             unsafe {-                heap::deallocate(self.ptr.as_mut() as *mut _, num_bytes, align);+                alloc::dealloc(self.ptr.as_ptr() as *mut u8, alloc::Layout::new::<T>());

Another incorrect Layout

lzutao

comment created time in 5 months

Pull request review commentrust-lang-nursery/nomicon

Update sample code with stable alloc crate

 Remove behaves in the opposite manner. We need to shift all the elements from ```rust,ignore pub fn remove(&mut self, index: usize) -> T {     // Note: `<` because it's *not* valid to remove after everything-    assert!(index < self.len, "index out of bounds");+    assert!(self.len > index, "index is out of bounds");+     unsafe {         self.len -= 1;-        let result = ptr::read(self.ptr.offset(index as isize));-        ptr::copy(self.ptr.offset(index as isize + 1),-                  self.ptr.offset(index as isize),-                  self.len - index);+        let result = ptr::read(self.ptr.as_ptr().offset(index as isize));++        ptr::copy(+            self.ptr.as_ptr().offset(index as isize + 1),+            self.ptr.as_ptr().offset(index as isize),+            self.len - index,+        );+

Why are you reformatting the code?

lzutao

comment created time in 5 months

issue commentrust-lang/rust

ptr::offset should explicitly clarify 0-sized offset semantics

(For anyone driving by, the ZST branch is an irrelevant distraction. We guarantee ZST ops do nothing, and this code is specially making the offset non-zero so it can use the pointer difference as a counter.)

Gankra

comment created time in 5 months

issue commentrust-lang/rust

ptr::offset should explicitly clarify 0-sized offset semantics

cc @RalfJung

Gankra

comment created time in 5 months

issue openedrust-lang/rust

ptr::offset should explicitly clarify 0-sized offset semantics

https://doc.rust-lang.org/std/primitive.pointer.html#method.offset

I can't remember the past arguments we definitely had about this, but it would be nice to explicitly call out the answer in the docs.

As a relevant example, Vec::into_iter currently unconditionally computes the "end" pointer of the array by offsetting by len (as long as size_of T > 0). This means that we offset a dangling pointer by 0 when iterating an empty Vec. This is obviously useful to support and annoying to have to guard against, so I would hope that's well-defined.

https://doc.rust-lang.org/src/alloc/vec.rs.html#1860

fn into_iter(mut self) -> IntoIter<T> {
        unsafe {
            let begin = self.as_mut_ptr();
            let end = if mem::size_of::<T>() == 0 {
                arith_offset(begin as *const i8, self.len() as isize) as *const T
            } else {
                // SAFE when `begin` dangles and `len == 0`???
                begin.add(self.len()) as *const T
            };
            let cap = self.buf.capacity();
            mem::forget(self);
            IntoIter {
                buf: NonNull::new_unchecked(begin),
                phantom: PhantomData,
                cap,
                ptr: begin,
                end,
            }
        }
    }

created time in 5 months

issue commentrust-unofficial/too-many-lists

second "let new_tail =" shadows first one in push!

This is kinda a standard rust idiom for expressing the same logical value changing type as you refine/compute it. But also it's kinda just confusing here?

GregDavidson

comment created time in 5 months

issue commentrust-unofficial/too-many-lists

Clarifying where and why pop deallocates first node from the heap

I'm actually not 100% certain, because iirc this code uses the obscure and 100% special DerefMove semantics of Box that allow the allocation to be partially moved out of. I would expect the deallocation to happen at the end of the scope, but wouldn't be surprised if it happens earlier.

GregDavidson

comment created time in 5 months

PR closed rust-unofficial/too-many-lists

Exchange T(Sync) &T(Send) to T(Send) &T(Sync)

Is T is Send and &T is Sync ?

+2 -2

1 comment

1 changed file

fooofei

pr closed time in 5 months

pull request commentrust-unofficial/too-many-lists

Exchange T(Sync) &T(Send) to T(Send) &T(Sync)

No, the current writing is correct. T:Sync is saying "it's ok to share me across threads" which implies "it's ok to send references to me to other threads".

fooofei

comment created time in 5 months

push eventrust-lang-nursery/nomicon

Ralf Jung

commit sha cbbe63b561e4ff4573a351908bcdd6ac018e3ac1

use sound/unsound terminology

view details

push time in 5 months

PR merged rust-lang-nursery/nomicon

use sound/unsound terminology

This is basically the Nomicon side of https://github.com/rust-lang-nursery/reference/pull/647. I was not sure what the best place would be to introduce this terminology.

+12 -8

0 comment

1 changed file

RalfJung

pr closed time in 5 months

issue commenteqrion/cbindgen

Rust Option to C

I'm having trouble reproducing this. Can you provide a standalone project I can build, and/or specify what platform you're targeting?

Also interestingly in the bare repr(C) case our codegen is probably slightly incorrect. repr(C) is "C enum sized", which is platform/implementation-defined thing that Rust has to vaguely guess at (usually int iirc). But a C++ enum class is guaranteed to be int.

pmirabel

comment created time in 5 months

pull request commentrust-lang-nursery/nomicon

adjust for current reality wrt. wide raw pointers

Just want to throw my hat out there again that I think the nomicon should be in the rust-lang/rust repo so that unstable code examples can be atomically adjusted along with the APIs.

RalfJung

comment created time in 5 months

Pull request review commentrust-lang-nursery/nomicon

fix and expand what we say about ZST

 support values.  Safe code need not worry about ZSTs, but *unsafe* code must be careful about the consequence of types with no size. In particular, pointer offsets are no-ops,-and standard allocators may return `null` when a zero-sized allocation is-requested, which is indistinguishable from the out of memory result.

clarification for historians: in C(++?) it's "only" implementation-defined to pass 0 to malloc: https://en.cppreference.com/w/c/memory/malloc

Since all the major allocators target this API, they all have this semantic. I'm guessing you're saying that the Rust interface makes a stricter claim? (which is fine by me, since the implementation-defined-ness might as well be UB in practice).

RalfJung

comment created time in 5 months

issue commenteqrion/cbindgen

make a proper example

I never really had a clear picture in my mind. Certainly it would be ideal if it showed off key features like generics, bitflags, and tagged unions.

But I don't really know what makes an example "good".

Gankra

comment created time in 5 months

more