Stop using HirId for fn-like parents
(cherry picked from commit 68d7c837fc377ac4145d931171fa2b1d1bd1670f)
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 792359c..7f73515 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1859,16 +1859,17 @@
}
}
- let parent_id = fcx.tcx.hir().get_parent_item(id);
- let mut parent_item = fcx.tcx.hir_node_by_def_id(parent_id.def_id);
+ let mut parent_id = fcx.tcx.hir().get_parent_item(id).def_id;
+ let mut parent_item = fcx.tcx.hir_node_by_def_id(parent_id);
// When suggesting return, we need to account for closures and async blocks, not just items.
for (_, node) in fcx.tcx.hir().parent_iter(id) {
match node {
hir::Node::Expr(&hir::Expr {
- kind: hir::ExprKind::Closure(hir::Closure { .. }),
+ kind: hir::ExprKind::Closure(hir::Closure { def_id, .. }),
..
}) => {
parent_item = node;
+ parent_id = *def_id;
break;
}
hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => break,
@@ -1878,13 +1879,7 @@
if let (Some(expr), Some(_), Some(fn_decl)) = (expression, blk_id, parent_item.fn_decl()) {
fcx.suggest_missing_break_or_return_expr(
- &mut err,
- expr,
- fn_decl,
- expected,
- found,
- id,
- parent_id.into(),
+ &mut err, expr, fn_decl, expected, found, id, parent_id,
);
}
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index dd44fdd..0045d00 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -932,7 +932,7 @@
pub(in super::super) fn get_node_fn_decl(
&self,
node: Node<'tcx>,
- ) -> Option<(hir::HirId, &'tcx hir::FnDecl<'tcx>, Ident, bool)> {
+ ) -> Option<(LocalDefId, &'tcx hir::FnDecl<'tcx>, Ident, bool)> {
match node {
Node::Item(&hir::Item {
ident,
@@ -943,25 +943,20 @@
// This is less than ideal, it will not suggest a return type span on any
// method called `main`, regardless of whether it is actually the entry point,
// but it will still present it as the reason for the expected type.
- Some((
- hir::HirId::make_owner(owner_id.def_id),
- &sig.decl,
- ident,
- ident.name != sym::main,
- ))
+ Some((owner_id.def_id, &sig.decl, ident, ident.name != sym::main))
}
Node::TraitItem(&hir::TraitItem {
ident,
kind: hir::TraitItemKind::Fn(ref sig, ..),
owner_id,
..
- }) => Some((hir::HirId::make_owner(owner_id.def_id), &sig.decl, ident, true)),
+ }) => Some((owner_id.def_id, &sig.decl, ident, true)),
Node::ImplItem(&hir::ImplItem {
ident,
kind: hir::ImplItemKind::Fn(ref sig, ..),
owner_id,
..
- }) => Some((hir::HirId::make_owner(owner_id.def_id), &sig.decl, ident, false)),
+ }) => Some((owner_id.def_id, &sig.decl, ident, false)),
Node::Expr(&hir::Expr {
hir_id,
kind:
@@ -991,12 +986,7 @@
}) => (ident, sig, owner_id),
_ => return None,
};
- Some((
- hir::HirId::make_owner(owner_id.def_id),
- &sig.decl,
- ident,
- ident.name != sym::main,
- ))
+ Some((owner_id.def_id, &sig.decl, ident, ident.name != sym::main))
}
_ => None,
}
@@ -1007,7 +997,7 @@
pub fn get_fn_decl(
&self,
blk_id: hir::HirId,
- ) -> Option<(hir::HirId, &'tcx hir::FnDecl<'tcx>, bool)> {
+ ) -> Option<(LocalDefId, &'tcx hir::FnDecl<'tcx>, bool)> {
// Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or
// `while` before reaching it, as block tail returns are not available in them.
self.tcx.hir().get_return_block(blk_id).and_then(|blk_id| {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 3f6f4cc..29f05ed 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -10,6 +10,7 @@
use crate::ty::TypeAndMut;
use core::cmp::min;
use core::iter;
+use hir::def_id::LocalDefId;
use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX};
use rustc_data_structures::packed::Pu128;
use rustc_errors::{Applicability, Diag, MultiSpan};
@@ -796,7 +797,7 @@
expected: Ty<'tcx>,
found: Ty<'tcx>,
can_suggest: bool,
- fn_id: hir::HirId,
+ fn_id: LocalDefId,
) -> bool {
let found =
self.resolve_numeric_literals_with_default(self.resolve_vars_if_possible(found));
@@ -912,7 +913,7 @@
err: &mut Diag<'_>,
expected: Ty<'tcx>,
found: Ty<'tcx>,
- fn_id: hir::HirId,
+ fn_id: LocalDefId,
) {
// Only apply the suggestion if:
// - the return type is a generic parameter
@@ -926,7 +927,7 @@
let ty::Param(expected_ty_as_param) = expected.kind() else { return };
- let fn_node = self.tcx.hir_node(fn_id);
+ let fn_node = self.tcx.hir_node_by_def_id(fn_id);
let hir::Node::Item(hir::Item {
kind:
@@ -1020,7 +1021,7 @@
expected: Ty<'tcx>,
found: Ty<'tcx>,
id: hir::HirId,
- fn_id: hir::HirId,
+ fn_id: LocalDefId,
) {
if !expected.is_unit() {
return;
@@ -1072,11 +1073,11 @@
let can_return = match fn_decl.output {
hir::FnRetTy::Return(ty) => {
let ty = self.astconv().ast_ty_to_ty(ty);
- let bound_vars = self.tcx.late_bound_vars(fn_id);
+ let bound_vars = self.tcx.late_bound_vars(self.tcx.local_def_id_to_hir_id(fn_id));
let ty = self
.tcx
.instantiate_bound_regions_with_erased(Binder::bind_with_vars(ty, bound_vars));
- let ty = match self.tcx.asyncness(fn_id.owner) {
+ let ty = match self.tcx.asyncness(fn_id) {
ty::Asyncness::Yes => self.get_impl_future_output_ty(ty).unwrap_or_else(|| {
span_bug!(
fn_decl.output.span(),
@@ -1097,8 +1098,9 @@
_ => false,
};
if can_return
- && let Some(owner_node) = self.tcx.hir_node(fn_id).as_owner()
- && let Some(span) = expr.span.find_ancestor_inside(*owner_node.span())
+ && let Some(span) = expr.span.find_ancestor_inside(
+ self.tcx.hir().span_with_body(self.tcx.local_def_id_to_hir_id(fn_id)),
+ )
{
err.multipart_suggestion(
"you might have meant to return this value",
diff --git a/tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.rs b/tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.rs
new file mode 100644
index 0000000..8ad99a4
--- /dev/null
+++ b/tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.rs
@@ -0,0 +1,17 @@
+//@ edition: 2021
+
+fn call(_: impl Fn() -> bool) {}
+
+async fn test() {
+ call(|| -> Option<()> {
+ //~^ ERROR expected
+ if true {
+ false
+ //~^ ERROR mismatched types
+ }
+ true
+ //~^ ERROR mismatched types
+ })
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.stderr b/tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.stderr
new file mode 100644
index 0000000..70cd9f9
--- /dev/null
+++ b/tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.stderr
@@ -0,0 +1,46 @@
+error[E0308]: mismatched types
+ --> $DIR/dont-ice-for-type-mismatch-in-closure-in-async.rs:9:13
+ |
+LL | / if true {
+LL | | false
+ | | ^^^^^ expected `()`, found `bool`
+LL | |
+LL | | }
+ | |_________- expected this to be `()`
+
+error[E0308]: mismatched types
+ --> $DIR/dont-ice-for-type-mismatch-in-closure-in-async.rs:12:9
+ |
+LL | true
+ | ^^^^ expected `Option<()>`, found `bool`
+ |
+ = note: expected enum `Option<()>`
+ found type `bool`
+
+error[E0271]: expected `{closure@dont-ice-for-type-mismatch-in-closure-in-async.rs:6:10}` to be a closure that returns `bool`, but it returns `Option<()>`
+ --> $DIR/dont-ice-for-type-mismatch-in-closure-in-async.rs:6:10
+ |
+LL | call(|| -> Option<()> {
+ | _____----_^
+ | | |
+ | | required by a bound introduced by this call
+LL | |
+LL | | if true {
+LL | | false
+... |
+LL | |
+LL | | })
+ | |_____^ expected `bool`, found `Option<()>`
+ |
+ = note: expected type `bool`
+ found enum `Option<()>`
+note: required by a bound in `call`
+ --> $DIR/dont-ice-for-type-mismatch-in-closure-in-async.rs:3:25
+ |
+LL | fn call(_: impl Fn() -> bool) {}
+ | ^^^^ required by this bound in `call`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0271, E0308.
+For more information about an error, try `rustc --explain E0271`.