Auto merge of #9093 - Jarcho:deref_ice, r=giraffate

Fix ICE in `dereference.rs`

fixes #9089
changelog: Fix ICE when dereferencing or borrowing on explicit returns from closures
This commit is contained in:
bors 2022-07-04 00:22:17 +00:00
commit b15f06e74f
4 changed files with 42 additions and 14 deletions

View file

@ -8,7 +8,7 @@ use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_ty, Visitor}; use rustc_hir::intravisit::{walk_ty, Visitor};
use rustc_hir::{ use rustc_hir::{
self as hir, BindingAnnotation, Body, BodyId, BorrowKind, Expr, ExprKind, GenericArg, HirId, ImplItem, self as hir, BindingAnnotation, Body, BodyId, BorrowKind, Expr, ExprKind, FnRetTy, GenericArg, HirId, ImplItem,
ImplItemKind, Item, ItemKind, Local, MatchSource, Mutability, Node, Pat, PatKind, Path, QPath, TraitItem, ImplItemKind, Item, ItemKind, Local, MatchSource, Mutability, Node, Pat, PatKind, Path, QPath, TraitItem,
TraitItemKind, TyKind, UnOp, TraitItemKind, TyKind, UnOp,
}; };
@ -717,18 +717,32 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (Position, &
Node::Expr(parent) if parent.span.ctxt() == ctxt => match parent.kind { Node::Expr(parent) if parent.span.ctxt() == ctxt => match parent.kind {
ExprKind::Ret(_) => { ExprKind::Ret(_) => {
let output = cx let owner_id = cx.tcx.hir().body_owner(cx.enclosing_body.unwrap());
.tcx Some(
.fn_sig(cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap())) if let Node::Expr(Expr {
.skip_binder() kind: ExprKind::Closure { fn_decl, .. },
.output(); ..
Some(if !output.is_ref() { }) = cx.tcx.hir().get(owner_id)
Position::Other(precedence) {
} else if output.has_placeholders() || output.has_opaque_types() { match fn_decl.output {
Position::ReborrowStable(precedence) FnRetTy::Return(ty) => binding_ty_auto_deref_stability(ty, precedence),
} else { FnRetTy::DefaultReturn(_) => Position::Other(precedence),
Position::DerefStable(precedence) }
}) } else {
let output = cx
.tcx
.fn_sig(cx.tcx.hir().local_def_id(owner_id))
.skip_binder()
.output();
if !output.is_ref() {
Position::Other(precedence)
} else if output.has_placeholders() || output.has_opaque_types() {
Position::ReborrowStable(precedence)
} else {
Position::DerefStable(precedence)
}
},
)
}, },
ExprKind::Call(func, _) if func.hir_id == child_id => (child_id == e.hir_id).then(|| Position::Callee), ExprKind::Call(func, _) if func.hir_id == child_id => (child_id == e.hir_id).then(|| Position::Callee),
ExprKind::Call(func, args) => args ExprKind::Call(func, args) => args

View file

@ -211,4 +211,8 @@ fn main() {
unsafe { unsafe {
var(0, &**x); var(0, &**x);
} }
let s = &"str";
let _ = || return *s;
let _ = || -> &'static str { return s };
} }

View file

@ -211,4 +211,8 @@ fn main() {
unsafe { unsafe {
var(0, &**x); var(0, &**x);
} }
let s = &"str";
let _ = || return *s;
let _ = || -> &'static str { return *s };
} }

View file

@ -192,5 +192,11 @@ error: deref which would be done by auto-deref
LL | f_str(&&**ref_str); // `needless_borrow` will suggest removing only one reference LL | f_str(&&**ref_str); // `needless_borrow` will suggest removing only one reference
| ^^^^^^^^^^ help: try this: `ref_str` | ^^^^^^^^^^ help: try this: `ref_str`
error: aborting due to 32 previous errors error: deref which would be done by auto-deref
--> $DIR/explicit_auto_deref.rs:217:41
|
LL | let _ = || -> &'static str { return *s };
| ^^ help: try this: `s`
error: aborting due to 33 previous errors