Skip to content

Settle desired semantics of divergence for purposes of coercion #40800

Closed

Description

@nikomatsakis

In #40224, I adopted the rule that one can coerce into the type ! if your expression is considered to diverge (in short, returns, breaks, or must evaluate some expression of type !).

However, the code doens't quite implement that rule. As described in this comment, it actually uses the self.diverges flag of the FnCtxt, which today tracks a property that is different in a subtle way. The property we are checking is: if the coercion of the expression E happens in the context of an expression F, it is permitted to coerce to ! if the expression F has diverged by the time that E finishes evaluating.

So in particular, under the rules I originally envisioned, this would not be allowed (see src/test/compile-fail/coerce-to-bang.rs for more examples):

fn foo(x: usize, y: !) { }
foo(return, 22); // the expression `22` does not diverge

But under the rules as implemented, it is allowed. It's not clear which rules we would prefer. I think I lean towards my original rules: they mean that whether an expression E can be coerced to a type T is purely a function of E (modulo free variables of course). But implementing that will require refactoring the compiler.

In my diverging-types-and-reachability branch, I changed how things work so that divergence is propagated upward, and "reachability" is passed downward. Divergence is thus a property purely of the expression at hand, whereas reachability is computed based on context. We use the combination of the two to drive unreachable warnings -- in particular, when you have reachable code which evaluates a diverging expression, the next thing to be evaluated triggered a warning. The precise setup I had in that branch doesn't work, sadly, because it only computed divergence after all types were known. Some refactoring needed.

Moreover, there are some other places I cut corners in the existing code, and I'm using this same FIXME to track them: in particular, in cast expressions, I am ignoring whether they diverge for the purposes of this check. That's just laziness.

Activity

  1. nikomatsakis commented on Mar 24, 2017

    @nikomatsakis
    ContributorAuthor

    cc @rust-lang/lang @canndrew @arielb1

  2. dhardy commented on May 5, 2017

    @dhardy
    Contributor

    It sounds to me like your original rules are more intuitive and less likely to lead to weird behaviour (e.g. under the current rules, foo(return, 22) is allowed, but bar(22, return) for fn bar(y: !, x: usize) is not allowed). So surely the only question is whether changing the rules now breaks much existing code?

  3. nikomatsakis commented on May 5, 2017

    @nikomatsakis
    ContributorAuthor

    @dhardy yes. I suspect the impact is quite minimal, but hard to know until we put in the implementation effort. I should probably write up some mentoring instructions; I know I don't have time to pursue it myself.

  4. dhardy commented on May 5, 2017

    @dhardy
    Contributor

    Ah, I see. One of these days I should put in the effort of learning the Rust codebase.

  5. changed the title [-]settle desires semantics of divergence for purposes of coercion[/-] [+]Settle desired semantics of divergence for purposes of coercion[/+] on Aug 3, 2017
  6. canndrew commented on Oct 26, 2017

    @canndrew
    Contributor

    @nikomatsakis What's the status of this at the moment? Has any more work been done towards it or do you have any solid ideas about what needs to be done?

  7. nikomatsakis commented on Nov 8, 2017

    @nikomatsakis
    ContributorAuthor

    @arielb1 and I were talking and I've been kind of failing to find the time to write up our conclusions. In the case of this question, we were wondering if would be possible to remove the "coerce into !" semantics entirely -- it's not clear why it's ever useful. There are some examples in run-pass of things that used to do it in the while, but they are very much corner cases. We'd be interested in removing this coercion and doing a crater run to measure the effects. @canndrew -- think you'd be interested in preparing that PR? Wouldn't be too hard (for the purposes of a crater run, just adding an if false in the right place would suffice, I suppose...)

  8. canndrew commented on Nov 9, 2017

    @canndrew
    Contributor

    I'm happy to do whatever needs to be done to get ! stable. I'm about to camping for the next two weeks though, so I won't be able to start until after that...

  9. canndrew commented on Nov 21, 2017

    @canndrew
    Contributor

    just adding an if false in the right place would suffice, I suppose...

    Whereabouts might this "right place" be? I had a look but couldn't see where this coercion happens :/

  10. nikomatsakis commented on Dec 6, 2017

    @nikomatsakis
    ContributorAuthor

    I believe @arielb1 implemented this in #45880, now merged. Closing.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-type-systemArea: Type systemC-bugCategory: This is a bug.I-needs-decisionIssue: In need of a decision.T-langRelevant to the language team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions