mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Rollup merge of #115313 - gurry:issue-114918-cycle-detected, r=compiler-errors
Make `get_return_block()` return `Some` only for HIR nodes in body
Fixes #114918
The issue occurred while compiling the following input:
```rust
fn uwu() -> [(); { () }] {
loop {}
}
```
It was caused by the code below trying to suggest a missing return type which resulted in a const eval cycle: 1bd043098e/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs (L68-L75)
The root cause was `get_return_block()` returning an `Fn` node for a node in the return type (i.e. the second `()` in the return type `[(); { () }]` of the input) although it is supposed to do so only for nodes that lie in the body of the function and return `None` otherwise (at least as per my understanding).
The PR fixes the issue by fixing this behaviour of `get_return_block()`.
This commit is contained in:
commit
2128efd87f
@ -701,6 +701,8 @@ impl<'hir> Map<'hir> {
|
||||
// expressions.
|
||||
ignore_tail = true;
|
||||
}
|
||||
|
||||
let mut prev_hir_id = None;
|
||||
while let Some((hir_id, node)) = iter.next() {
|
||||
if let (Some((_, next_node)), false) = (iter.peek(), ignore_tail) {
|
||||
match next_node {
|
||||
@ -715,7 +717,14 @@ impl<'hir> Map<'hir> {
|
||||
| Node::ForeignItem(_)
|
||||
| Node::TraitItem(_)
|
||||
| Node::Expr(Expr { kind: ExprKind::Closure { .. }, .. })
|
||||
| Node::ImplItem(_) => return Some(hir_id),
|
||||
| Node::ImplItem(_)
|
||||
// The input node `id` must be enclosed in the method's body as opposed
|
||||
// to some other place such as its return type (fixes #114918).
|
||||
// We verify that indirectly by checking that the previous node is the
|
||||
// current node's body
|
||||
if node.body_id().map(|b| b.hir_id) == prev_hir_id => {
|
||||
return Some(hir_id)
|
||||
}
|
||||
// Ignore `return`s on the first iteration
|
||||
Node::Expr(Expr { kind: ExprKind::Loop(..) | ExprKind::Ret(..), .. })
|
||||
| Node::Local(_) => {
|
||||
@ -723,6 +732,8 @@ impl<'hir> Map<'hir> {
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
prev_hir_id = Some(hir_id);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
10
tests/ui/typeck/issue-114918/const-in-fn-return-type.rs
Normal file
10
tests/ui/typeck/issue-114918/const-in-fn-return-type.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// Regression test for #114918
|
||||
// Test that a const generic enclosed in a block within a return type
|
||||
// produces a type mismatch error instead of triggering a const eval cycle
|
||||
|
||||
#[allow(unused_braces)]
|
||||
fn func() -> [u8; { () } ] { //~ ERROR mismatched types
|
||||
loop {}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,9 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/const-in-fn-return-type.rs:6:21
|
||||
|
|
||||
LL | fn func() -> [u8; { () } ] {
|
||||
| ^^ expected `usize`, found `()`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
20
tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs
Normal file
20
tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs
Normal file
@ -0,0 +1,20 @@
|
||||
// Regression test for #114918
|
||||
// Test that a const generic enclosed in a block within the return type
|
||||
// of an impl fn produces a type mismatch error instead of triggering
|
||||
// a const eval cycle
|
||||
|
||||
|
||||
trait Trait {
|
||||
fn func<const N: u32>() -> [ (); N ];
|
||||
}
|
||||
|
||||
struct S {}
|
||||
|
||||
#[allow(unused_braces)]
|
||||
impl Trait for S {
|
||||
fn func<const N: u32>() -> [ (); { () }] { //~ ERROR mismatched types
|
||||
N
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,9 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/const-in-impl-fn-return-type.rs:15:40
|
||||
|
|
||||
LL | fn func<const N: u32>() -> [ (); { () }] {
|
||||
| ^^ expected `usize`, found `()`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
12
tests/ui/typeck/issue-114918/const-in-struct-type-arg.rs
Normal file
12
tests/ui/typeck/issue-114918/const-in-struct-type-arg.rs
Normal file
@ -0,0 +1,12 @@
|
||||
// Regression test for #114918
|
||||
// Test that a const generic enclosed in a block in a struct's type arg
|
||||
// produces a type mismatch error instead of triggering a const eval cycle
|
||||
|
||||
#[allow(unused_braces)]
|
||||
struct S<const N: usize> {
|
||||
arr: [u8; N]
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s = S::<{ () }> { arr: [5, 6, 7]}; //~ ERROR mismatched types
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/const-in-struct-type-arg.rs:11:19
|
||||
|
|
||||
LL | let s = S::<{ () }> { arr: [5, 6, 7]};
|
||||
| ^^ expected `usize`, found `()`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -0,0 +1,13 @@
|
||||
// Regression test for #114918
|
||||
// Test that a const generic enclosed in a block within the return type
|
||||
// of a trait method produces a type mismatch error instead of triggering
|
||||
// a const eval cycle
|
||||
|
||||
#[allow(unused_braces)]
|
||||
trait Trait {
|
||||
fn func<const N: u32>() -> [ (); { () }] { //~ ERROR mismatched types
|
||||
N
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,9 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/const-in-trait-fn-return-type.rs:8:40
|
||||
|
|
||||
LL | fn func<const N: u32>() -> [ (); { () }] {
|
||||
| ^^ expected `usize`, found `()`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Reference in New Issue
Block a user