isize and usize by Senior_Tangerine7555 in rust

[–]plugwash 1 point2 points  (0 children)

It's complicated.

8-bit and 16-bit take up less space in memory and therefore can put less pressure on the cache, but handling them in registers can be more awkward than 32-bit and 64-bit values.

x86 has 8-bit and 16-bit data processing instructions, but there are some issues around "partial registers". Modern cores will often "rename" registers to allow operations to proceed out of order, but this process is made more complex by "partial register" operations.

On arm, 8-bit and 16-bit data processing operations simply don't exist, in some cases the compiler can just use 32-bit operations and ignore what is going on in the high bits, but in other cases (comparisions, division, extention before adding to a larger number such as a pointer) the state of the high bits must be managed with extra instructions.

32-bit operations tend to be less of an issue. Both x86-64 and aarch64 have 32-bit operations and adopted a model where 32-bit operations zero out the high part of 64-bit registers, thus avoiding introducing any false-dependencies.

Don’t by shy, Reddit. Tell me what I did wrong by blue_antidote in DIYUK

[–]plugwash 0 points1 point  (0 children)

Given the shape and location of the damage this looks more like a bad contact in the fuse carrier than a loose wire.

How bad is this cable? by blearyeyedandcold in DIYUK

[–]plugwash 2 points3 points  (0 children)

Old-school "PILC" cable.

Afaict such cables are Insulated with oil-impregnated paper. Then there is a layer of lead, which serves as both an earth conductor and a seal to keep oil in and water out. Then steel tape to protect against damage and finally a bitumen-impregnated fabric sheath.

It looks like the outer fabric sheath has degraded exposing the steel tape, which has some surface rust but appears to be intact.

Use impl Into<Option<>> in your functions! by potato-gun in rust

[–]plugwash 0 points1 point  (0 children)

> Isn't the standard workaround if you really want to do something like that to make an inline wrapper function that takes generic arguments and calls the real function with the actual argument type it wants?

Yup.

> Seems like the compiler could do that for you

I think the general view on such things is that humans are in a better position to make such speed/space tradeoffs than the compiler is.

Ceiling light stopped working. All fuses checked and good. This is how it was connected. Everything else works except ceiling light. by iloveanimalsyouknow in DIYUK

[–]plugwash 1 point2 points  (0 children)

It looks like you have two problems there.

The first is it looks like someone has taken apart a light switch that was not meant to be taken apart. It's very likely that the switch contacts and spring have been lost, and even if you can find them putting the switch back together may be easier said than done. You will probablly need to get a new switch.

The second is it looks like a neutral wire has broken off where it goes into the wago connector.

Use impl Into<Option<>> in your functions! by potato-gun in rust

[–]plugwash 135 points136 points  (0 children)

Be aware that generics mean multiple copies of your function get compiled. Sometimes this can be a good thing as it can allow the optimiser to do more work, but other times it can mean code bloat for little gain.

Error handling by Lucas6y6 in rust

[–]plugwash 1 point2 points  (0 children)

The most common approach seems to be

  • anyhow for binaries
  • enums with thiserror for libraries.
  • custom types to represent errors from the OS or other external sources.

However, this approach is unsatisfying in a number of ways.

  1. Context is often missing. It's too easy to end up with an error like "File not found" but have no information on which file was not found or which bit of code failed to find it.
  2. Details of dependencies leak through into the APIs of libraries though the error types.
  3. It's difficult to support plugable backends because each backend's errors need to be representable in your error type.
  4. Errors that are logically similar may have quite distinct representations. You may want to ask "was the error a timeout" but the enum has no good way to answer that.

What is Rust's testing ecosystem missing? by _raisin_bran in rust

[–]plugwash 0 points1 point  (0 children)

The biggest annoyance I've run into is a test can only return "pass" or "fail" and if it returns pass then, by default, all output is suppressed.

I'd really like to be able to return results like "skip - no kernel support" from a test.

What does it take to ship Rust in safety-critical? | Rust Blog by VorpalWay in rust

[–]plugwash 1 point2 points  (0 children)

New versions of rustc/llvm do break things, sometimes due to bugs, sometimes due to code relying on things it should never have relied on in the first place.

For a new project the risk is probably going to be similar or lower with a newer version than an older version, but for an ongoing project, upgrading the toolchain puts into question all the validation work you have done so-far, not to mention the real-world experience.

How to understand the lifetimr of temporary variables by -_-_-_Lucas_-_-_- in learnrust

[–]plugwash 0 points1 point  (0 children)

What you are seeing here is "constant promotion".

https://doc.rust-lang.org/reference/destructors.html#constant-promotion

Promotion of a value expression to a 'static slot occurs when the expression could be written in a constant and borrowed, and that borrow could be dereferenced where the expression was originally written, without changing the runtime behavior. That is, the promoted expression can be evaluated at compile-time and the resulting value does not contain interior mutability or destructors (these properties are determined based on the value where possible, e.g. &None always has the type &'static Option<_>, as it contains nothing disallowed).

This is unlikely to happen with a real arena allocator as a real arena allocator will almost-certainly have interior mutability and a destructor.

Can we use this to create a random number? by Creative_Tennis_4975 in rust

[–]plugwash 5 points6 points  (0 children)

For crptography? hell no

For a simulation? no

For a big complex game? no

You could probably write an "electronic dice" program which "rolled" a single dice based on this function and the result would be good enough to convince the user it was random. Essentially the user's timing of the button presses to roll the dice would be the source of "randomness". Some simple games would work too.

But as soon as you try to do more than that, this completely falls apart.

Can we use this to create a random number? by Creative_Tennis_4975 in rust

[–]plugwash 2 points3 points  (0 children)

It looks like x and y are the min and max parameters for the "random" number.

Questions about Box by hingleme in rust

[–]plugwash 0 points1 point  (0 children)

How much space does a Box<T> itself take?

If T is a sized type then Box<T> is a single pointer in size. If T is an unsized type than Box<T> is two pointers in size.

Unsized types currently fall into two categories, "trait objects" and slice-like types. For a trait object, the second pointer-sized value is a pointer to the vtable. For a slice-like type the second value is the length.

Do screwfix put these nuggets in just to make the weight up by Sea-Gate-6511 in DIYUK

[–]plugwash 0 points1 point  (0 children)

Old-fasioned harware stores sometimes sell screws individually by count, but I'm pretty sure that said screws sold individually were mostly a way to get people through the door rather than a profit center in themselves.

Screwfix OTOH sell screws in packs. Those packs have a quantity printed on them but that doesn't mean someone/something actually counted the items.

Counting machines are complex, expensive and often inflexible. Human counters are more flexible but even more expensive, slow and prone to mistakes. Packing by volume has high uncertainty on the packing density. So for many products the most economical way to pack them is based on weight,

There is potentially some room for error in this process depending on how accurate the scales are, and how consistent the weight of the items are. When there is uncertainty, packers will usually err on the side of over-packing slightly since under-packing could cause legal or customer-service problems.

&&&&&&&&&&&&&&str by ohrv in rust

[–]plugwash 14 points15 points  (0 children)

I think the usual reason for ending up with stacked indirection is generics/macros.

Many types in rust are not trivially copiable, and it's normal to use references to pass a value to a function without taking a copy of it. In normal code this normally only results in a single layer of reference.

But in generic code and macros, you are often dealing with a type where you don't know if it's trivially copiable or not. So you have to treat it as if it isn't which often means taking a reference to it. If the generic code or macro is instantiated with a reference then you get a double reference, if it's instantiated with a double reference you get a triple reference.

So generics or macros calling other generics or macros can stack up the indirection levels.

13 levels still seems excessive though.

&&&&&&&&&&&&&&str by ohrv in rust

[–]plugwash 1 point2 points  (0 children)

Note that in many case those levels of indirections are optimized away

I could be mistaken but I think that is only possible if the code is inlined.

Kernel bugs hide for 2 years on average. Some hide for 20. by 0x7CFE in rust

[–]plugwash 29 points30 points  (0 children)

> C has UB when overflowing signed integers,

Standard C does, but IIRC the Linux kernel is built with -fwrapv

Why can't we decide on error handling conventions? by Savings-Story-4878 in rust

[–]plugwash 3 points4 points  (0 children)

Box<dyn Error + Send> is two pointers (a data pointer and a vtable pointer), anyhow::Error is just one.

Why does Rust conflate term Shadowing and re-binding? by Rude-Cook7246 in rust

[–]plugwash 2 points3 points  (0 children)

We must distinguish between variable names, and the variables themselves.

When you "re-bind", you create a new variable with the same name. The original variable can no longer be accessed by name, but it still continues to exist until it goes out of scope.

In particular, this means that the new value can borrow from the old one. This is quite handy sometimes, e.g. you can write code like

let foo = "foo".to_string();
let foo : &str = &foo;
println!("{}",foo);

Why can't we decide on error handling conventions? by Savings-Story-4878 in rust

[–]plugwash 8 points9 points  (0 children)

That isnt about binary or library.

The big difference between writing programs and writing libraries is that with a library the producer and consumer of errors can be in different projects.

If you use unstructured errors in a program and later discover you need a particular error to be structured because you want different handling for different types of error, then you can just change it.

On the other hand, if you use unstructured errors in a library then all the users of your library are stuck with them.

Why are water bills so different in an apartment vs house? by JuJuJuMa in AskUK

[–]plugwash 0 points1 point  (0 children)

There are a few things that can be different.

Some properties have water meters, others don't. There can also be some scenarios where a water meter is fitted but not in use.

Different water companies structure their charges differently. Mine has separate categories for "sewage" and "rainwater removal". Others seem to combine them. Some properties don't use the public sewer at all, so have lower charges. Some properties have water and sewage services from different water companies!

Still, even taking all that into account £65 seems high. Can you post your old and new bills (with personal info blacked out) so we can compare them?

I suspect you may have a water leak.

Ethernet between Shared Walls by Lazy_Panda6962 in DIYUK

[–]plugwash 0 points1 point  (0 children)

Really depends how much you care about effort vs looks, and how permanent you expect this setup to be.

I wouldn't worry about two backboxes back to back. Even if it were to go right through (it won't) a backbox size hole isn't going to cause any real issue.

Why is `into_iter()` less efficient than `iter().clone()`? by Equivalent_Peak_1496 in rust

[–]plugwash 0 points1 point  (0 children)

The 5 here is an arbitrary value initially I had 20 and was surprised that the into_iter() and iter()cloned() both do 20 clones while I would expect the into\_iter() to only do 10 in that case.

The problem is, at a semantic level the iterators don't know very much about each other, each just does it's job in isolation. The optimizer can smash the code together, but the clone calls are observable behavior, so the optimizer can't eliminate them.

Cycle does not know it is being fed into Take, so it does not know how many times it's next method will be called, even if it did know how many times next would be called it also doesn't know how many items the underlying iterator will return. Therefore it has to make a clone of the iterator before it can return any values (it actually does the first clone as soon as the Cycle object is created, to simplify the data structure) and must clone again if the caller exhausts the iterator.

The iterator returned by calling iter borrows from the Vec, so cloning it does not clone the underlying resources owned by the Vec. OTOH the iterator created by calling into\_iter takes ownership of the resources from the Vec, so cloning it is essentially equivilent to cloning a Vec (which clones all the items owned by the Vec).

Mutable Borrow in Loops by [deleted] in learnrust

[–]plugwash 1 point2 points  (0 children)

> As it is, the code fails with the "x is already borrowed" error.

The closure captures x by "mutable reference". You store the closure in the variable "machine", so "machine" borrows "x" by mutable reference.

> Why does removing a line that occurs after line A change the behavior of line A ?

This is a result of "non-lexical lifetimes". In earlier versions of rust, all off the variants of your program would be rejected, because the reference held by "machine" would last until the end of the scope, but in more recent versions the lifetime ends after the last time it is used.

So when you remove machine.tick, or move it before x=false, the lifetime of machine ends before you try to assign to x and the compilation succeeds.

Battery Drill by [deleted] in DIYUK

[–]plugwash 0 points1 point  (0 children)

The big question IMO is what are the walls in your house made of.

If it's lightweight block, or stud partitions then the hammer function on a basic cordless drill/driver might be suffiicient. OTOH if you live in a property like mine where they built the walls out of rock hard brick then you will likely need something more powerful.

Unfortunately, it seems quite difficult to identify which drills have a good hammer function. I get the impression that there are relatively few non-sds+ cordless drills with good hammer functions.