New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Type Ascribed Coercions #2623

Open
wants to merge 8 commits into
base: master
from

Conversation

Projects
None yet
4 participants
@haslersn
Copy link

haslersn commented Jan 5, 2019

Rendered

This improves on the merged RFC 803.

Motivation and summary

The subsection "Type ascription and temporaries" of the merged RFC 803 defines certain contexts (so-called reference contexts) in which a type ascription that needs coercion can not occur. Meanwhile and in contrast, the Rust reference defines coercion sites which are contexts in which a coercion can occur.

For consistency, we change the specification as of RFC 803 such that a type ascribed expression that needs to be coerced can only occur at these coercion sites. The aim is to reduce language complexity and increase consistency.

This change shouldn't in any way conflict with RCF 2522.

@@ -161,7 +161,7 @@ as an lvalue (i.e., no new temporary), then there is potential for unsoundness:
```
let mut foo: S = ...;
{
let bar = &mut (foo: T); // S <: T, no coercion required
let bar = &mut (foo: T); // S <: T, coercion from S to T

This comment has been minimized.

@haslersn

haslersn Jan 5, 2019

In case you wonder: "no coercion required" was wrong because this is one type of coercion.

haslersn added some commits Jan 6, 2019

RFC 803: Revert semantical change
The change is now covered by the paper of RFC 2623

@haslersn haslersn changed the title RFC 803: Change where type ascribed expressions can be coerced RFC: Change where type ascribed expressions can be coerced Jan 6, 2019

@haslersn haslersn changed the title RFC: Change where type ascribed expressions can be coerced RFC: Type Ascribed Coercions Jan 6, 2019

@ExpHP

This comment has been minimized.

Copy link

ExpHP commented Jan 7, 2019

It's not clear to me if this needs an RFC? (i.e. is there anything here for the general public to discuss?)

RFCs are not authorative, especially with regards to implementation, and in cases like this where an "obvious right solution" arises somewhere down the road, I believe the course of action taken in the past has been to simply implement that obvious right solution.

(unless perhaps somebody believes this change is not so "obviously right" as I suggest? :P)

Personally, I am familiar with the concept of coercion sites as defined in the Rust reference, and the very first thing I thought of upon seeing the unsound example was, "I don't think that's a coercion site?" I'd probably just shrug it off on the basis that the RFC is 3 years old, knowing how much our vocabulary and concepts for discussing the language have changed since then.

@ExpHP

This comment has been minimized.

Copy link

ExpHP commented Jan 7, 2019

I guess the most accessible thing to focus on is the disadvantages.

let _ = e : T; // ERROR, not a coercion site

This snippet uses a _ pattern, but does it extend to more general cases? (e.g. patterns that aren't _? Or _ patterns embedded in a larger pattern? I'm guessing "no; yes"?) I guess this could be a little surprising, but it's hard to picture where it would ever come up. (it seems pointless to write, so it would have to come up as a result of macro codegen)


Also, I assume this still works for selecting types for type inference?

// should be ok, since `V where V: FromIterator<i32>` can be unified with Vec<i32>?
let _ = (0..1).collect(): Vec<i32>;
let _ = (&(0..1).collect()): &Vec<i32>;

// presumably this is not ok since it requires a coercion?
let _ = (&(0..1).collect::<Vec<_>>()): &[i32];

fn reborrow<'b, 'a: 'b>(x: &'a i32) -> &'b i32 {
    // hopefully okay since subtyping doesn't *require* a coercion site?
    // (or does it?)
    x: &'b i32
}
@haslersn

This comment has been minimized.

Copy link

haslersn commented Jan 7, 2019

@ExpHP

RFCs are not authorative, especially with regards to implementation, and in cases like this where an "obvious right solution" arises somewhere down the road, I believe the course of action taken in the past has been to simply implement that obvious right solution.

I came to Rust 2 weeks ago and am still unfamiliar with the processes.

I'd probably just shrug it off on the basis that the RFC is 3 years old, knowing how much our vocabulary and concepts for discussing the language have changed since then.

I also thought about that being a possible reason, why it's not already like I proposed.

This snippet uses a _ pattern, but does it extend to more general cases?

Like stated: Once RFC #2522 gets merged, we can help type inference at the left side of the assignment, even with arbitrary patterns. Example:

let (alpha: u8, beta: i16, gamma: bool) = (1, -2, true);

If there'd still be code that surprisingly doesn't compile, we could still fix it later.

@haslersn

This comment has been minimized.

Copy link

haslersn commented Jan 7, 2019

@ExpHP

fn reborrow<'b, 'a: 'b>(x: &'a i32) -> &'b i32 {
    // hopefully okay since subtyping doesn't *require* a coercion site?
    // (or does it?)
    x: &'b i32
}

It's okay, but for a different reason: The last expression of a block is a coercion site.

@ExpHP

This comment has been minimized.

Copy link

ExpHP commented Jan 7, 2019

Ah, indeed. After reading the RFC more thoroughly that does sound like the correct explanation for the third example.

I came to Rust 2 weeks ago and am still unfamiliar with the processes.

This is still pretty good! The RFC is excellently written, I just mention this because writing an RFC can be a pretty big time sink (so when the process can be avoided, that's a good idea). Proposing these ideas first on internals as a Pre-RFC can also garner suggestions on how to get things moving in the right direction.

I'd probably just shrug it off on the basis that the RFC is 3 years old, knowing how much our vocabulary and concepts for discussing the language have changed since then.

I also thought about that being a possible reason, why it's not already like I proposed.

In this vein, mind: The reference is a Pretty New Thing (TM) and still a work in progress. For a long time, the only big resources on Rust were RTPL (which isn't much of a reference), the Nomicon (which has stagnated and is limited in topics), and any language features documented in the standard library documentation (which is very limited in scope).

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Jan 15, 2019

Hmm, so, I like the overall definition here, but I think perhaps there may be different expectations as to what constitutes a "coercion site". In particular, I would have assumed that the "initializer in a let" was considered a "coercion site" (unless the pattern contained a ref binding), precisely because let <pat>: T = <expr> will coerce the type of expression to T (unless pat contains an explicit ref-mod binding).

I guess I have to revisit the "pattern binding" RFC. It seems like in general we could make let _ = x: T be considered a coercion site, in which case -- are there other examples where coercions might reasonable by expected but do not, in fact work?

On the other hand, that might just mean that the RFC is basically "identical" to the existing, already accepted solution? (Since any non-coercion site is a "reference site"?)

I do agree with @ExpHP that this doesn't have to be an RFC per se, but it's the sort of conversation where our current process doesn't have an ideal home. Something I'd like to change. =)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment