Stop using HirId for fn-like parents

This commit is contained in:
Michael Goulet 2024-04-11 11:54:39 -04:00
parent 62cffeedcf
commit 68d7c837fc
5 changed files with 84 additions and 34 deletions

View File

@ -2004,16 +2004,17 @@ fn report_return_mismatched_types<'a>(
} }
} }
let parent_id = fcx.tcx.hir().get_parent_item(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.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. // When suggesting return, we need to account for closures and async blocks, not just items.
for (_, node) in fcx.tcx.hir().parent_iter(id) { for (_, node) in fcx.tcx.hir().parent_iter(id) {
match node { match node {
hir::Node::Expr(&hir::Expr { hir::Node::Expr(&hir::Expr {
kind: hir::ExprKind::Closure(hir::Closure { .. }), kind: hir::ExprKind::Closure(hir::Closure { def_id, .. }),
.. ..
}) => { }) => {
parent_item = node; parent_item = node;
parent_id = *def_id;
break; break;
} }
hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => break, hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => break,
@ -2023,13 +2024,7 @@ fn report_return_mismatched_types<'a>(
if let (Some(expr), Some(_), Some(fn_decl)) = (expression, blk_id, parent_item.fn_decl()) { if let (Some(expr), Some(_), Some(fn_decl)) = (expression, blk_id, parent_item.fn_decl()) {
fcx.suggest_missing_break_or_return_expr( fcx.suggest_missing_break_or_return_expr(
&mut err, &mut err, expr, fn_decl, expected, found, id, parent_id,
expr,
fn_decl,
expected,
found,
id,
parent_id.into(),
); );
} }

View File

@ -942,7 +942,7 @@ pub fn resolve_ty_and_res_fully_qualified_call(
pub(in super::super) fn get_node_fn_decl( pub(in super::super) fn get_node_fn_decl(
&self, &self,
node: Node<'tcx>, node: Node<'tcx>,
) -> Option<(hir::HirId, &'tcx hir::FnDecl<'tcx>, Ident, bool)> { ) -> Option<(LocalDefId, &'tcx hir::FnDecl<'tcx>, Ident, bool)> {
match node { match node {
Node::Item(&hir::Item { Node::Item(&hir::Item {
ident, ident,
@ -953,25 +953,20 @@ pub(in super::super) fn get_node_fn_decl(
// This is less than ideal, it will not suggest a return type span on any // 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, // 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. // but it will still present it as the reason for the expected type.
Some(( Some((owner_id.def_id, &sig.decl, ident, ident.name != sym::main))
hir::HirId::make_owner(owner_id.def_id),
&sig.decl,
ident,
ident.name != sym::main,
))
} }
Node::TraitItem(&hir::TraitItem { Node::TraitItem(&hir::TraitItem {
ident, ident,
kind: hir::TraitItemKind::Fn(ref sig, ..), kind: hir::TraitItemKind::Fn(ref sig, ..),
owner_id, 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 { Node::ImplItem(&hir::ImplItem {
ident, ident,
kind: hir::ImplItemKind::Fn(ref sig, ..), kind: hir::ImplItemKind::Fn(ref sig, ..),
owner_id, 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 { Node::Expr(&hir::Expr {
hir_id, hir_id,
kind: kind:
@ -1001,12 +996,7 @@ pub(in super::super) fn get_node_fn_decl(
}) => (ident, sig, owner_id), }) => (ident, sig, owner_id),
_ => return None, _ => return None,
}; };
Some(( Some((owner_id.def_id, &sig.decl, ident, ident.name != sym::main))
hir::HirId::make_owner(owner_id.def_id),
&sig.decl,
ident,
ident.name != sym::main,
))
} }
_ => None, _ => None,
} }
@ -1017,7 +1007,7 @@ pub(in super::super) fn get_node_fn_decl(
pub fn get_fn_decl( pub fn get_fn_decl(
&self, &self,
blk_id: hir::HirId, 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 // 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. // `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| { self.tcx.hir().get_return_block(blk_id).and_then(|blk_id| {

View File

@ -9,6 +9,7 @@
use crate::rustc_middle::ty::Article; use crate::rustc_middle::ty::Article;
use core::cmp::min; use core::cmp::min;
use core::iter; use core::iter;
use hir::def_id::LocalDefId;
use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX}; use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX};
use rustc_data_structures::packed::Pu128; use rustc_data_structures::packed::Pu128;
use rustc_errors::{Applicability, Diag, MultiSpan}; use rustc_errors::{Applicability, Diag, MultiSpan};
@ -796,7 +797,7 @@ pub(in super::super) fn suggest_missing_return_type(
expected: Ty<'tcx>, expected: Ty<'tcx>,
found: Ty<'tcx>, found: Ty<'tcx>,
can_suggest: bool, can_suggest: bool,
fn_id: hir::HirId, fn_id: LocalDefId,
) -> bool { ) -> bool {
let found = let found =
self.resolve_numeric_literals_with_default(self.resolve_vars_if_possible(found)); self.resolve_numeric_literals_with_default(self.resolve_vars_if_possible(found));
@ -923,7 +924,7 @@ fn try_suggest_return_impl_trait(
err: &mut Diag<'_>, err: &mut Diag<'_>,
expected: Ty<'tcx>, expected: Ty<'tcx>,
found: Ty<'tcx>, found: Ty<'tcx>,
fn_id: hir::HirId, fn_id: LocalDefId,
) { ) {
// Only apply the suggestion if: // Only apply the suggestion if:
// - the return type is a generic parameter // - the return type is a generic parameter
@ -937,7 +938,7 @@ fn try_suggest_return_impl_trait(
let ty::Param(expected_ty_as_param) = expected.kind() else { return }; 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 { let hir::Node::Item(hir::Item {
kind: kind:
@ -1031,7 +1032,7 @@ pub(in super::super) fn suggest_missing_break_or_return_expr(
expected: Ty<'tcx>, expected: Ty<'tcx>,
found: Ty<'tcx>, found: Ty<'tcx>,
id: hir::HirId, id: hir::HirId,
fn_id: hir::HirId, fn_id: LocalDefId,
) { ) {
if !expected.is_unit() { if !expected.is_unit() {
return; return;
@ -1083,11 +1084,11 @@ pub(in super::super) fn suggest_missing_break_or_return_expr(
let can_return = match fn_decl.output { let can_return = match fn_decl.output {
hir::FnRetTy::Return(ty) => { hir::FnRetTy::Return(ty) => {
let ty = self.lowerer().lower_ty(ty); let ty = self.lowerer().lower_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 let ty = self
.tcx .tcx
.instantiate_bound_regions_with_erased(Binder::bind_with_vars(ty, bound_vars)); .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(|| { ty::Asyncness::Yes => self.get_impl_future_output_ty(ty).unwrap_or_else(|| {
span_bug!( span_bug!(
fn_decl.output.span(), fn_decl.output.span(),
@ -1108,8 +1109,9 @@ pub(in super::super) fn suggest_missing_break_or_return_expr(
_ => false, _ => false,
}; };
if can_return if can_return
&& let Some(owner_node) = self.tcx.hir_node(fn_id).as_owner() && let Some(span) = expr.span.find_ancestor_inside(
&& let Some(span) = expr.span.find_ancestor_inside(*owner_node.span()) self.tcx.hir().span_with_body(self.tcx.local_def_id_to_hir_id(fn_id)),
)
{ {
err.multipart_suggestion( err.multipart_suggestion(
"you might have meant to return this value", "you might have meant to return this value",

View File

@ -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() {}

View File

@ -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`.