Skip to content

Settle desired semantics of divergence for purposes of coercion #40800

Closed
@nikomatsakis

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.

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, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions