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

Make get_return_block() return Some only for HIR nodes in body #115313

Merged
merged 1 commit into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion compiler/rustc_middle/src/hir/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -715,14 +717,23 @@ 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(_) => {
return None;
}
_ => {}
}

prev_hir_id = Some(hir_id);
}
None
}
Expand Down
10 changes: 10 additions & 0 deletions tests/ui/typeck/issue-114918/const-in-fn-return-type.rs
Original file line number Diff line number Diff line change
@@ -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() {}
9 changes: 9 additions & 0 deletions tests/ui/typeck/issue-114918/const-in-fn-return-type.stderr
Original file line number Diff line number Diff line change
@@ -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 changes: 20 additions & 0 deletions tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs
Original file line number Diff line number Diff line change
@@ -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() {}
Original file line number Diff line number Diff line change
@@ -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 changes: 12 additions & 0 deletions tests/ui/typeck/issue-114918/const-in-struct-type-arg.rs
Original file line number Diff line number Diff line change
@@ -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
}
9 changes: 9 additions & 0 deletions tests/ui/typeck/issue-114918/const-in-struct-type-arg.stderr
Original file line number Diff line number Diff line change
@@ -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`.
13 changes: 13 additions & 0 deletions tests/ui/typeck/issue-114918/const-in-trait-fn-return-type.rs
Original file line number Diff line number Diff line change
@@ -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() {}
Original file line number Diff line number Diff line change
@@ -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