Implicit coercions - dated info?


#1

Hello,

I’ve just started learning Rust.
I was looking for more information about coercions/casting,
and I found this:

( for some reason I can’t publish this link, so just add https:// in front )

And I was wondering, is it still valid? For example, it says:

A coercion is implicit and has no syntax. 
[CUT]
The base cases are:

In argument position for function calls. The value being coerced is the actual parameter and 
it is coerced to the type of the formal parameter. 
For example, where foo is defined as fn foo(x: U) { ... } and is called with foo(e);, 
e is coerced to have type U;

So I tried something very basic (I’m running rust v1.1):

fn f(x:f32) -> f32 {
    x
}

let x1:i32 = 5;
println!("{}", f(x1)); //error, type mismatch

Using “as” solves the problem:

println!("{}", f(x1 as f32)); // this compiles

#2

It’s valid, but it doesn’t do implic casting only coercion.


#3

Hm. I’m not sure I get this.

As far as I understand,
coercion means implicit conversion: conversion still happens, but it
doesn’t need any special syntax in order to happen.

Casting means explicit conversion (in Rust, I need keyword “as” and target type).

So…what exactly is the difference between “implicit casting” - assuming such thing is not an oxymoron :slight_smile: - and coercion?

I guess it would make sense to put clear definitions of these terms in the glossary, which I think is a great idea.


#4

What the text you quoted means is, coercions might happen in the listed places. In other words, coercions will never happen outside of the mentioned places. However, it is not specifying the exact conversion rules that are applied to coercions. What you really want is at a few blocks below:

Coercion is allowed between the following types:

  • T to U if T is a subtype of U (the ‘identity’ case);
  • T_1 to T_3 where T_1 coerces to T_2 and T_2 coerces to T_3
    (transitivity case);
  • &mut T to &T;
  • *mut T to *const T;
  • &T to *const T;
  • &mut T to *mut T;

(and so on)

In short, Rust has very limited type coercion rules. Coercions between i32, i64, f32, f64 are not allowed.

To think about it, if all coercions were allowed without any rules as you said, things like &str -> &i32 would have also been allowed. This does not make sense.


#5

Thanks, it’s much clearer now.

I understand the specific RFC is probably not written with beginners in mind,
but still…it’s pretty confusing. I’m definitely not an expert on technical writing,
still it’s always good to think how certain parts sound if taken out of context:

The value being coerced is the actual parameter and it is coerced to the type of the formal parameter.
For example, where foo is defined as fn foo(x: U) { … } and is called with foo(e);, e is coerced to have type U;

I added emphasis just to show how people usually learn. With so many languages out there, and so many things you have to read just to find out whether this thing is
for you or not, many of us are forced to learn by skimming and focusing on relevant parts.

Maybe using words like can, could, under specific circumstances…instead of “is coerced” would make a difference.

Anyway, just my experience.