Fix ICE in dereference.rs

This commit is contained in:
Jason Newcomb 2022-07-02 00:59:58 -04:00
parent 8c341d66a1
commit 3e80d3988d
4 changed files with 42 additions and 14 deletions

View File

@ -8,7 +8,7 @@
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_ty, Visitor};
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,
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 {
ExprKind::Ret(_) => {
let output = cx
.tcx
.fn_sig(cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap()))
.skip_binder()
.output();
Some(if !output.is_ref() {
Position::Other(precedence)
} else if output.has_placeholders() || output.has_opaque_types() {
Position::ReborrowStable(precedence)
} else {
Position::DerefStable(precedence)
})
let owner_id = cx.tcx.hir().body_owner(cx.enclosing_body.unwrap());
Some(
if let Node::Expr(Expr {
kind: ExprKind::Closure { fn_decl, .. },
..
}) = cx.tcx.hir().get(owner_id)
{
match fn_decl.output {
FnRetTy::Return(ty) => binding_ty_auto_deref_stability(ty, precedence),
FnRetTy::DefaultReturn(_) => Position::Other(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, args) => args

View File

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

View File

@ -211,4 +211,8 @@ fn _f5(x: &u32) -> u32 {
unsafe {
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
| ^^^^^^^^^^ 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