Rust: use of partially moved values - rust

In Rust 0.8:
struct TwoStr {
one: ~str,
two: ~str,
}
#[test]
fn test_contents() {
let strs = TwoStr {
one: ~"pillar",
two: ~"post",
};
assert_eq!(strs.one, ~"pillar");
assert_eq!(strs.two, ~"post");
}
The code won't even compile. The rust test thinks there's an error in the second assert_eq:
error: use of partially moved value: strs
It is somewhat counter-intuitive. I mean, whatever effects the first assert_eq may have, it should be well out of the scope when the execution reaches the second assert_eq. Unless of course, it does some spawn behind the scene. Does it?
If not, why this mysterious error? Hopefully there's no fundamental flaws in my understanding of Rust pointers.

In Rust 0.8, assert_eq! is defined as
macro_rules! assert_eq (
($given:expr , $expected:expr) => (
{
let given_val = $given;
let expected_val = $expected;
// check both directions of equality....
if !((given_val == expected_val) && (expected_val == given_val)) {
fail!(\"assertion failed: `(left == right) && (right == \
left)` (left: `%?`, right: `%?`)\", given_val, expected_val);
}
}
)
)
Note here that it moves both arguments into local let-bindings given_val and expected_val. This is what is causing your error.
In current master, this has been fixed. assert_eq! now takes references to the arguments:
macro_rules! assert_eq (
($given:expr , $expected:expr) => (
{
let given_val = &($given);
let expected_val = &($expected);
// check both directions of equality....
if !((*given_val == *expected_val) &&
(*expected_val == *given_val)) {
fail!("assertion failed: `(left == right) && (right == left)` \
(left: `{:?}`, right: `{:?}`)", *given_val, *expected_val)
}
}
)
)
This means that it no longer moves its arguments, which fixes your error.
If you need to stick with rust 0.8, you can change this to using assert!() instead and do the comparison directly, which will avoid the move. But my recommendation is to upgrade to latest master.

It works on Git master. It must be a bug that was fixed after 0.8 was cut. In general, the released versions are not constrained to be particularly stable before release - they're essentially just snapshots.
The definition of the assert_eq! macro, in libsyntax, takes references to the arguments, so the arguments should not be moved and you can use them after you call the macro.
If you do find another bug, try to compile master if you can, or just make a new issue.

Related

What's wrong with this groovy for-loop of Closures? [duplicate]

In the context of Jenkins pipelines, I have some Groovy code that's enumerating a list, creating closures, and then using that value in the closure as a key to lookup another value in a map. This appears to be rife with some sort of anomaly or race condition almost every time.
This is a simplification of the code:
def tasks = [:]
for (platformName in platforms) {
// ...
tasks[platformName] = {
def componentUploadPath = componentUploadPaths[platformName]
echo "Uploading for platform [${platformName}] to [${componentUploadPath}]."
// ...
}
tasks.failFast = true
parallel(tasks)
platforms has two values. I will usually see two iterations and two tasks registered and the keys in tasks will be correct, but the echo statement inside the closure indicates that we're just running one of the platforms twice:
14:20:02 [platform2] Uploading for platform [platform1] to [some_path/platform1].
14:20:02 [platform1] Uploading for platform [platform1] to [some_path/platform1].
It's ridiculous.
What do I need to add or do differently?
It's the same issue as you'd see in Javascript.
When you generate the closures in a for loop, they are bound to a variable, not the value of the variable.
When the loop exits, and the closures are run, they will all be using the same value...that is -- the last value in the for loop before it exited
For example, you'd expect the following to print 1 2 3 4, but it doesn't
def closures = []
for (i in 1..4) {
closures << { -> println i }
}
closures.each { it() }
It prints 4 4 4 4
To fix this, you need to do one of two things... First, you could capture the value in a locally scoped variable, then close over this variable:
for (i in 1..4) {
def n = i
closures << { -> println n }
}
The second thing you could do is use groovy's each or collect as each time they are called, the variable is a different instance, so it works again:
(1..4).each { i ->
closures << { -> println i }
}
For your case, you can loop over platforms and collect into a map at the same time by using collectEntries:
def tasks = platforms.collectEntries { platformName ->
[
platformName,
{ ->
def componentUploadPath = componentUploadPaths[platformName]
echo "Uploading for platform [${platformName}] to [${componentUploadPath}]."
}
]
}
Hope this helps!

Rust: macro to keep same frame rate does not work

To keep a certain frame rate, i've been using std::thread::sleep() to wait until enough time has passed. Calculating how much it sleeps messes up the code a bit, so I tried making a macro for it. This is it now, but it does not work:
macro_rules! fps30 {
($($body: expr;);*) => {
let time = std::time::Instant::now()
$($body)*
let time_elapsed = time.elapsed().as_micros();
if FRAME_TIME_30FPS_IN_MICROS > time_elapsed {
let time_to_sleep = FRAME_TIME_30FPS_IN_MICROS - time_elapsed;
std::thread::sleep(std::time::Duration::from_micros(time_to_sleep as u64));
}
};
}
And I want to use it like this:
loop {
fps30!{
// do everything I want to do in the loop
}
}
When I don't implement it as a macro (by pasting the code in the loop directly) it works, and retains a nice 29 frames per second (I guess not 30 because of the small overhead the sleep calculations give). The error it gives during compilation states: no rules expected the token 'p', where p is an object/struct instance I use in the macro.
Any suggestions?
The problem is with the handling of the ; in:
$($($body: expr;);*)
When you want to accept a ; separated list of expressions you should either write $($($body: expr;)*) or $($($body: expr);*). The former means a list of ;-terminated expressions, while the latter is a list of ;-separated expressions.
The difference is subtle but important. If you add both then you would need to write two ;; to separate every expression.
It would be better if you accepted a list of ; terminated expressions, so do:
$($($body: expr;)*)
Then you have a couple of errors in the body of the macro, also related to ;. You are missing the ; before the expansion of the $body:
let time = std::time::Instant::now();
And you are missing the ; in the expansion of $body itself, because the ; is not part of the captured expr:
$($body;)*
With these changed it works, except if you try:
fps30!{
if a {
}
if a {
}
}
Because there is no ; after the if expressions!!! You could try switching to:
$($($body: expr);*)
But it will not work either, now because there is no ; between the expressiones!
You could accept a single $body: block but then you will be required to write an additional couple of {}. Not ideal...
If you really want to accept any kind of block of code, I recommend to accept a list of token trees (tt). And when expanding them, enclose them in a {}, in case it does not end with a ;.
macro_rules! fps30 {
($($body: tt)*) => {
let time = std::time::Instant::now();
{ $($body)* }
let time_elapsed = time.elapsed().as_micros();
//...
};
}
Now your macro will accept any kind of syntax, and will expand it dumbly inside macro.
You could even add the possibility of $body having a type and a value, and make fps30 evaluate to that value`:
let res = { $($body)* };
//...
res
As an additional bonus, if you write a syntax error, it will fail when compiling the code, not when expanding the macro, which is much easier to debug.

Make msvc C4706 go away without pragmas

Following code in MSVC generates warning about assignment in conditional expression.
https://godbolt.org/z/i_rwY9
int main()
{
int a;
if ((a = 5)) {
return 1;
}
return a;
}
Note that I tried to use the double () around if since that makes the warning go away with g++, but I do not know how to make it go away in msvc without extracting the assignment from condition.
Is there a way to nudge msvc to figure out that this assignment is intentional?
I know I can use pragmas to disable this warning, but pattern is very common so I would like to get a solution without pragmas if one exists.
The MSVC compiler will give this warning unless you can convince it that you really do know what you're doing. Adding at least one 'real' logical test will achieve this:
int main()
{
int a;
if ((a = 5) != 0) {
return 1;
}
return a;
}
Note that the constant 5 can readily be replaced with any variable or valid expression: adding the explicit != 0 test does nothing to actually change the outcome of the code (and it is unlikely to change the generated assembly).

Why does a match expression not report an error for a catch-all arm (_) prior to other arms?

Rust has a construct called match which looks very similar to switch in other languages. However I observed a very peculiar behavior of match.
let some_u32_value = 3;
match some_u32_value {
_ => (),
3 => println!("three"),
}
match respects the order in which the cases/patterns are mentioned. Why does it not report an error if the default (_) case is at the top? It does give a warning though:
warning: unreachable pattern
--> src/main.rs:5:9
|
5 | 3 => println!("three"),
| ^
|
= note: #[warn(unreachable_patterns)] on by default
A similar construct in Java, the switch, does not preserve any order, so having a default prior to other cases is not an error (ignoring the fall through behavior).
int x = 0;
switch (x) {
default:
System.out.println("default");
break;
case 0:
System.out.println("Zero");
}
Is there some purpose for doing this explicitly?
An unreachable pattern is not strictly an error, I mean: it does not prevent the compiler from "understanding" the code nor does it make the code unsafe.
Similarly, in C, for example, you can return a reference to a local variable without triggering an error (at least with gcc):
#include <stdio.h>
int* foo() {
int x = 0;
return &x;
}
int main() {
printf("%d", *foo());
return 0;
}
Generally, you should not consider a warning as "oh, that's only a warning, I don't care". A warning is an actual useful advice/information given by the compiler.
I like the definition given in warnings:
A warning is often issued on recognizing a potential high-risk situation, a probable misunderstanding, degraded service or imminent failure.
because it helps to understand the difference between an error and a warning:
An error is an error,
A warning is a potential/probable error or a problematic thing.
In this situation, the last arm of the match is some dead code, so the compiler reports it accordingly.
Rust's match expressions are a lot more powerful than Java switch statements, and you can do a lot more than just matching numbers.
In particular, it supports pattern matching which lets you match pieces of your data, based on either its structure or the values it contains. When you have more complex patterns to match, it's important to be able to specify the order because the patterns may overlap. For example:
let value = Some((Some(3), "hello"));
let s = match value {
None => "Nothing there!".to_owned(),
Some((Some(3), _)) => "The number is exactly 3!".to_owned(),
Some((Some(n), _)) if n > 3 => format!("Got a number bigger than 3: {}", n),
Some((None, msg)) => format!("Message with no number: {}", msg),
Some((_, msg)) => format!("Got the message, ignore the rest: {}", msg),
_ => "Anything else?".to_owned()
};
println!("result = {}", s);
The last case here is actually impossible because the other branches cover everything. The compiler will give a warning, in case that isn't what you intended.

Handling f64 or Complex64 return types. Generics? Either?

I have a functioning Rust program using real doubles (f64) as the underlying type and wish to extend the system such that it can also handle complex values (num::complex::Complex64).
A (cut down example) function takes some configuration struct config, and depending on that input generates a potential value at an index idx:
fn potential(config: &Config, idx: &Index3) -> Result<f64, Error> {
let num = &config.grid.size;
match config.potential {
PotentialType::NoPotential => Ok(0.0),
PotentialType::Cube => {
if (idx.x > num.x / 4 && idx.x <= 3 * num.x / 4) &&
(idx.y > num.y / 4 && idx.y <= 3 * num.y / 4) &&
(idx.z > num.z / 4 && idx.z <= 3 * num.z / 4) {
Ok(-10.0)
} else {
Ok(0.0)
}
}
PotentialType::Coulomb => {
let r = config.grid.dn * (calculate_r2(idx, &config.grid)).sqrt();
if r < config.grid.dn {
Ok(-1. / config.grid.dn)
} else {
Ok(-1. / r)
}
}
}
}
I now wish to add a ComplexCoulomb match which returns a Complex64 value:
PotentialType::ComplexCoulomb => {
let r = config.grid.dn * (calculate_r2(idx, &config.grid)).sqrt();
if r < config.grid.dn {
Ok(Complex64::new(-1. / config.grid.dn, 1.))
} else {
Ok(Complex64::new(-1. / r, 1.))
}
}
This function is an early entry point in my program, which fills an ndarray::Array3; currently I'm operating on a number of variables with the type ndarray::Array3<f64> - so I need to generalise the whole program, not just this function.
How can I extend this program to use both types based on the input from config? This struct comes from parsing a configuration file on disk and will match a number of PotentialType::Complex* values.
I'm aware of two possible options, but am unsure if either fits my criteria.
Use something similar to Either and return Left for real and Right for complex; then use additional logic to treat the values separately in other functions.
Use generic types. This isn't something I've done too much of before and generalisation over many types seems like a fair chunk of complicated alteration of my current code base. Is there a way to reduce the complexity here?
If you have any other suggestions I'd love to hear them!
There might be a lot of code change, but using generic parameters is probably the most flexible approach, and it won't impact performance. Passing around an enum will be less performant, partly because the enum will be bigger (the size of the larger variant plus a tag to discriminate between them) and partly because the enum variant will have to be frequently checked.
One thing that can get cumbersome is the potentially long list of traits that constrain your type parameter. This can be done on the impl level, rather than on each function, to save repetition. There isn't currently a way to alias a set of traits, which would make this more ergonomic, but there is an RFC approved for that.
I made a very similar change in the Euclid library. It was more than a year ago, so much has changed since then, both in Rust and in that library, but a quick look over that commit should still give you an idea of the amount of changes necessary.
This is the current state of the same (renamed) implementation:
impl <T, Src, Dst> TypedTransform3D<T, Src, Dst>
where T: Copy + Clone +
Add<T, Output=T> +
Sub<T, Output=T> +
Mul<T, Output=T> +
Div<T, Output=T> +
Neg<Output=T> +
ApproxEq<T> +
PartialOrd +
Trig +
One + Zero {
// methods of TypedTransform3D defined here...
}
Some of those traits (Trig, One, Zero) are actually defined inside the crate, as they aren't in the standard library.

Resources