Skip to content
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

Match expressions should sometimes have type ! #3231

Closed
1 task
powerboat9 opened this issue Oct 28, 2024 · 3 comments · Fixed by #3256
Closed
1 task

Match expressions should sometimes have type ! #3231

powerboat9 opened this issue Oct 28, 2024 · 3 comments · Fixed by #3256

Comments

@powerboat9
Copy link
Contributor

powerboat9 commented Oct 28, 2024

Summary

Match expressions with no arms should give a value of type !

Reproducer

I tried this code:

pub enum X {}

pub fn foo(x: X) {
    let _a: i32 = match x {};
}

pub fn main() {}

Does the code make use of any (1.49) nightly feature ?

  • Nightly

Godbolt link

link

Actual behavior

<source>:4:5: error: mismatched types, expected 'i32' but got '()' [E0308]
    4 |     let _a: i32 = match x {};
      |     ^~~     ~~~   ~~~~~

Expected behavior

No error

GCC Version

GCCRS master on godbolt

@powerboat9 powerboat9 changed the title Match expressions should sometimes have type '!' Match expressions should sometimes have type ! Oct 28, 2024
@CohenArthur CohenArthur added this to the Remaining typecheck issues milestone Nov 5, 2024
@philberty
Copy link
Member

Whats the logic for never type here ? @flip1995

@CohenArthur
Copy link
Member

@philberty https://github.com/rust-lang/rust/blob/3d1dba830a564d1118361345d7ada47a05241f45/compiler/rustc_hir_typeck/src/_match.rs#L32-L36 I believe

so it should be pretty simple - if there are no arms, then it returns !. if there are no arms when there should be arms, then it's up to the exhaustiveness checker to report an error

@flip1995
Copy link
Member

flip1995 commented Nov 8, 2024

The best documentation I could find was a blog post by Niko. Also take a look at the linked RFC. I think this is something missing in the reference.

I think this paragraph from the RFC explains it best:

let foo: &'static str = match x {};

Reading this, it may be tempting to ask the question "what is the value of foo then?". Remember that this depends on the value of x. As there are no possible values of x it's a meaningless question and besides, the fact that x has type Never gives us a static guarantee that the match block will never be executed.

Because the scrutinee is an uninhabited type (which the never type is), it can never be created. So this match can never be executed. So the type of the expression is ! = never.

@philberty philberty self-assigned this Nov 12, 2024
philberty added a commit that referenced this issue Nov 21, 2024
This is a special case in Rust and the ! type can unify with pretty much
anything its almost a inference variable and a unit-type for special cases.

Fixes #3231
Fixes #2567

gcc/rust/ChangeLog:

	* backend/rust-compile-expr.cc (check_match_scrutinee):
	(CompileExpr::visit): fix assertion
	* checks/errors/rust-hir-pattern-analysis.cc (check_match_usefulness): check for empty
	* typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): resolve to !

gcc/testsuite/ChangeLog:

	* rust/compile/exhaustiveness1.rs: remove bad check
	* rust/compile/issue-2567-1.rs: New test.
	* rust/compile/issue-2567-2.rs: New test.
	* rust/compile/issue-2567-3.rs: New test.
	* rust/compile/issue-3231.rs: New test.

Signed-off-by: Philip Herron <herron.philip@googlemail.com>
philberty added a commit that referenced this issue Nov 21, 2024
This is a special case in Rust and the ! type can unify with pretty much
anything its almost a inference variable and a unit-type for special cases.

Fixes #3231
Fixes #2567

gcc/rust/ChangeLog:

	* backend/rust-compile-expr.cc (check_match_scrutinee): check for empty match
	(CompileExpr::visit): fix assertion
	* checks/errors/rust-hir-pattern-analysis.cc (check_match_usefulness): check for empty
	* typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): resolve to !

gcc/testsuite/ChangeLog:

	* rust/compile/exhaustiveness1.rs: remove bad check
	* rust/compile/issue-2567-1.rs: New test.
	* rust/compile/issue-2567-2.rs: New test.
	* rust/compile/issue-2567-3.rs: New test.
	* rust/compile/issue-3231.rs: New test.

Signed-off-by: Philip Herron <herron.philip@googlemail.com>
github-merge-queue bot pushed a commit that referenced this issue Nov 22, 2024
This is a special case in Rust and the ! type can unify with pretty much
anything its almost a inference variable and a unit-type for special cases.

Fixes #3231
Fixes #2567

gcc/rust/ChangeLog:

	* backend/rust-compile-expr.cc (check_match_scrutinee): check for empty match
	(CompileExpr::visit): fix assertion
	* checks/errors/rust-hir-pattern-analysis.cc (check_match_usefulness): check for empty
	* typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): resolve to !

gcc/testsuite/ChangeLog:

	* rust/compile/exhaustiveness1.rs: remove bad check
	* rust/compile/issue-2567-1.rs: New test.
	* rust/compile/issue-2567-2.rs: New test.
	* rust/compile/issue-2567-3.rs: New test.
	* rust/compile/issue-3231.rs: New test.

Signed-off-by: Philip Herron <herron.philip@googlemail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants