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

View File

@ -942,7 +942,7 @@ pub fn resolve_ty_and_res_fully_qualified_call(
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,
@ -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
// 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:
@ -1001,12 +996,7 @@ pub(in super::super) fn get_node_fn_decl(
}) => (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,
}
@ -1017,7 +1007,7 @@ pub(in super::super) fn get_node_fn_decl(
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| {

View File

@ -9,6 +9,7 @@
use crate::rustc_middle::ty::Article;
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 @@ pub(in super::super) fn suggest_missing_return_type(
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));
@ -923,7 +924,7 @@ fn try_suggest_return_impl_trait(
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
@ -937,7 +938,7 @@ fn try_suggest_return_impl_trait(
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:
@ -1031,7 +1032,7 @@ pub(in super::super) fn suggest_missing_break_or_return_expr(
expected: Ty<'tcx>,
found: Ty<'tcx>,
id: hir::HirId,
fn_id: hir::HirId,
fn_id: LocalDefId,
) {
if !expected.is_unit() {
return;
@ -1083,11 +1084,11 @@ pub(in super::super) fn suggest_missing_break_or_return_expr(
let can_return = match fn_decl.output {
hir::FnRetTy::Return(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
.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(),
@ -1108,8 +1109,9 @@ pub(in super::super) fn suggest_missing_break_or_return_expr(
_ => 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",

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