Skip to content

Commit

Permalink
Fix ICE by introducing an expr_or_init variant for outside bodies
Browse files Browse the repository at this point in the history
  • Loading branch information
Urgau committed Sep 27, 2023
1 parent b97d311 commit ffb8f04
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 3 deletions.
39 changes: 38 additions & 1 deletion compiler/rustc_lint/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 that initializer expression is another local or **outside** (`const`/`static`)
/// binding, find its initializer again.
Expand All @@ -1338,7 +1372,10 @@ impl<'tcx> LateContext<'tcx> {
/// dbg!(def);
/// // ^^^ 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();

while let hir::ExprKind::Path(ref qpath) = expr.kind
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_lint/src/invalid_from_utf8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
init = cx.expr_or_init(inner);
init = cx.expr_or_init_with_outside_body(inner);
}
match init.kind {
ExprKind::Lit(Spanned { node: lit, .. }) => {
Expand Down
2 changes: 2 additions & 0 deletions tests/ui/lint/reference_casting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ unsafe fn assign_to_ref() {
}
}

const RAW_PTR: *mut u8 = 1 as *mut u8;
unsafe fn no_warn() {
let num = &3i32;
let mut_num = &mut 3i32;
Expand All @@ -144,6 +145,7 @@ unsafe fn no_warn() {
let mut value = 3;
let value: *const i32 = &mut value;
*(value as *const i16 as *mut i16) = 42;
*RAW_PTR = 42;

fn safe_as_mut<T>(x: &std::cell::UnsafeCell<T>) -> &mut T {
unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) }
Expand Down

0 comments on commit ffb8f04

Please sign in to comment.