Fix ICE by introducing an expr_or_init variant for outside bodies
This commit is contained in:
parent
bd360472b1
commit
1b2c1a8583
3 changed files with 44 additions and 3 deletions
|
@ -1316,6 +1316,40 @@ impl<'tcx> LateContext<'tcx> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If the given expression is a local binding, find the initializer expression.
|
||||||
|
/// If that initializer expression is another local binding, find its initializer again.
|
||||||
|
///
|
||||||
|
/// This process repeats as long as possible (but usually no more than once).
|
||||||
|
/// Type-check adjustments are not taken in account in this function.
|
||||||
|
///
|
||||||
|
/// Examples:
|
||||||
|
/// ```
|
||||||
|
/// let abc = 1;
|
||||||
|
/// let def = abc + 2;
|
||||||
|
/// // ^^^^^^^ output
|
||||||
|
/// let def = def;
|
||||||
|
/// dbg!(def);
|
||||||
|
/// // ^^^ input
|
||||||
|
/// ```
|
||||||
|
pub fn expr_or_init<'a>(&self, mut expr: &'a hir::Expr<'tcx>) -> &'a hir::Expr<'tcx> {
|
||||||
|
expr = expr.peel_blocks();
|
||||||
|
|
||||||
|
while let hir::ExprKind::Path(ref qpath) = expr.kind
|
||||||
|
&& let Some(parent_node) = match self.qpath_res(qpath, expr.hir_id) {
|
||||||
|
Res::Local(hir_id) => self.tcx.hir().find_parent(hir_id),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
&& let Some(init) = match parent_node {
|
||||||
|
hir::Node::Expr(expr) => Some(expr),
|
||||||
|
hir::Node::Local(hir::Local { init, .. }) => *init,
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
{
|
||||||
|
expr = init.peel_blocks();
|
||||||
|
}
|
||||||
|
expr
|
||||||
|
}
|
||||||
|
|
||||||
/// If the given expression is a local binding, find the initializer expression.
|
/// If the given expression is a local binding, find the initializer expression.
|
||||||
/// If that initializer expression is another local or **outside** (`const`/`static`)
|
/// If that initializer expression is another local or **outside** (`const`/`static`)
|
||||||
/// binding, find its initializer again.
|
/// binding, find its initializer again.
|
||||||
|
@ -1338,7 +1372,10 @@ impl<'tcx> LateContext<'tcx> {
|
||||||
/// dbg!(def);
|
/// dbg!(def);
|
||||||
/// // ^^^ input
|
/// // ^^^ input
|
||||||
/// ```
|
/// ```
|
||||||
pub fn expr_or_init<'a>(&self, mut expr: &'a hir::Expr<'tcx>) -> &'a hir::Expr<'tcx> {
|
pub fn expr_or_init_with_outside_body<'a>(
|
||||||
|
&self,
|
||||||
|
mut expr: &'a hir::Expr<'tcx>,
|
||||||
|
) -> &'a hir::Expr<'tcx> {
|
||||||
expr = expr.peel_blocks();
|
expr = expr.peel_blocks();
|
||||||
|
|
||||||
while let hir::ExprKind::Path(ref qpath) = expr.kind
|
while let hir::ExprKind::Path(ref qpath) = expr.kind
|
||||||
|
|
|
@ -84,9 +84,9 @@ impl<'tcx> LateLintPass<'tcx> for InvalidFromUtf8 {
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut init = cx.expr_or_init(arg);
|
let mut init = cx.expr_or_init_with_outside_body(arg);
|
||||||
while let ExprKind::AddrOf(.., inner) = init.kind {
|
while let ExprKind::AddrOf(.., inner) = init.kind {
|
||||||
init = cx.expr_or_init(inner);
|
init = cx.expr_or_init_with_outside_body(inner);
|
||||||
}
|
}
|
||||||
match init.kind {
|
match init.kind {
|
||||||
ExprKind::Lit(Spanned { node: lit, .. }) => {
|
ExprKind::Lit(Spanned { node: lit, .. }) => {
|
||||||
|
|
|
@ -130,6 +130,7 @@ unsafe fn assign_to_ref() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RAW_PTR: *mut u8 = 1 as *mut u8;
|
||||||
unsafe fn no_warn() {
|
unsafe fn no_warn() {
|
||||||
let num = &3i32;
|
let num = &3i32;
|
||||||
let mut_num = &mut 3i32;
|
let mut_num = &mut 3i32;
|
||||||
|
@ -144,6 +145,9 @@ unsafe fn no_warn() {
|
||||||
let mut value = 3;
|
let mut value = 3;
|
||||||
let value: *const i32 = &mut value;
|
let value: *const i32 = &mut value;
|
||||||
*(value as *const i16 as *mut i16) = 42;
|
*(value as *const i16 as *mut i16) = 42;
|
||||||
|
*RAW_PTR = 42; // RAW_PTR is defined outside the function body,
|
||||||
|
// make sure we don't ICE on it when trying to
|
||||||
|
// determine if we should lint on it or not.
|
||||||
|
|
||||||
fn safe_as_mut<T>(x: &std::cell::UnsafeCell<T>) -> &mut T {
|
fn safe_as_mut<T>(x: &std::cell::UnsafeCell<T>) -> &mut T {
|
||||||
unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) }
|
unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue