Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How could rust multiply &i32 with i32?

Tags:

rust

Consider this example:

fn main() {
    let v: Vec<i32> = vec![1, 2, 3, 4, 5];
    let b: i32 = (&v[2]) * 4.0;
    println!("product of third value with 4 is {}", b);
}

This fails as expected as float can't be multiplied with &i32.

error[E0277]: cannot multiply `{float}` to `&i32`
 --> src\main.rs:3:23
  |
3 |   let b: i32 = (&v[2]) * 4.0;
  |                        ^ no implementation for `&i32 * {float}`
  |
  = help: the trait `std::ops::Mul<{float}>` is not implemented for `&i32`

But when I change the float to int, it works fine.

fn main() {
    let v: Vec<i32> = vec![1, 2, 3, 4, 5];
    let b: i32 = (&v[2]) * 4;
    println!("product of third value with 4 is {}", b);
}

Did the compiler implement the operation between &i32 and i32? If yes, how is this operation justified in such a type safe language?

like image 814
manikawnth Avatar asked Aug 31 '19 16:08

manikawnth


2 Answers

Did the compiler implement the operation between &i32 and i32?

Yes. Well, not the compiler, but rather the standard library. You can see the impl in the documentation.

If yes, how is this operation justified in such a type safe language?

"Type safe" is not a Boolean property, but rather a spectrum. Most C++ programmers would say that C++ is type safe. Yet, C++ has many features that automatically cast between types (constructors, operator T, taking references of values, ...). When designing a programming language, one has to balance the risk of bugs (when introducing convenient type conversions) with the inconvenience (when not having them).

As an extreme example: consider if Option<T> would deref to T and panic if it was None. That's the behavior of most languages that have null. I think it's pretty clear that this "feature" has led to numerous bugs in the real world (search term "billion dollar mistake"). On the other hand, let's consider what bugs could be caused by having &i32 * i32 compile. I honestly can't think of any. Maaaybe someone wanted to multiply the raw pointer of one value with an integer? Rather unlikely in Rust. So since the chance of introducing bugs with this feature is very low, but it is convenient, it was decided to be implemented.

This is always something the designers have to balance. Different languages are in a different position on this spectrum. Rust would likely be considered "more typesafe" than C++, but not doubt, there are even "more typesafe" languages than Rust out there. In this context, "more typesafe" just meant: decisions leaned more towards "inconvenience instead of potential bugs".

like image 187
Lukas Kalbertodt Avatar answered Nov 15 '22 09:11

Lukas Kalbertodt


I think you may be confusing &i32 from rust with &var from C.

In C,

int var = 5;
int newvar = &var * 4;  /* this would be bad code, 
                           should not multiply an address by an integer!
                           Of course, C will let you. */

the '&' operator returns the address of the variable 'var'.

However, in rust, the '&' operator borrows use of the variable var.

In Rust,

let var: i32 = 5;
assert_eq!(&var * 8, 40);

This works, because &var refers to 5, not to the address of var. Note that in C, the & is an operator. In Rust, the & is acting as part of the type of the variable. Hence, the type is &i32.

This is very confusing. If there were more characters left on standard keyboard, i am sure the designers would have used a different one.

Please see the book and carefully follow the diagrams. The examples in the book use String, which is allocated on the heap. Primitives, like i32 are normally allocated on the stack and may be completely optimized away by the compiler. Also, primitives are frequently copied even when reference notation is used, so that gets confusing. Still, I think it is easier to look at the heap examples using String first and then to consider how this would apply to primitives. The logic is the same, but the actual storage and optimization my be different.

like image 27
Gardener Avatar answered Nov 15 '22 10:11

Gardener