Skip to content

Change which type variables fall back to ! #40801

Closed
@nikomatsakis

Description

@nikomatsakis

Right now, type variables fallback to ! if they are the result of a return etc. The idea was that this represents a "dead control flow path", but it is not clear that this is the right rule, because those type variables often get 'caught up' in other paths.

In #40224, I outlined another possibility in a comment:

In talking with @pnkfelix, we had an alternative idea that yields a similar result, but does so in a more tailored way. Specifically, we could say that when you instantiate one enum variant (say, Err), any type parameters which do not appear in the variant in question get a diverging fallback. So the type of Err(x) is Result<?T, X>, where ?T falls back to !.

This would allow Err(x)? to work as expected, while making Deserialize::deserialize()? fail as requiring a type annotation.

...

This result is not perfect. One can still write things like:

let mut x = Err(E);
x = Ok(Deserialize::deserialize()?);

in particular, this would mean that Deserialize::deserialize()?; would error out, whereas today it defaults to deserializing the ! type (and hence ... probably ... panics?). This feels like a case where I would expect an "unconstrained type variable" error -- but we don't get one today because one of the arms is dead, and hence generates a diverging fallback when coerced.

There is an obvious backwards compatibility concern here. It's not clear how much we can change these paths. But I suspect we have some leeway, if what we do is tailored enough.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-type-systemArea: Type systemC-feature-requestCategory: A feature request, i.e: not implemented / a PR.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