|
1 | 1 | #![allow(clippy::float_cmp)]
|
2 | 2 |
|
| 3 | +use crate::macros::HirNode; |
3 | 4 | use crate::source::{get_source_text, walk_span_to_context};
|
4 | 5 | use crate::{clip, is_direct_expn_of, sext, unsext};
|
5 | 6 |
|
@@ -529,6 +530,59 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
|
529 | 530 | }
|
530 | 531 | }
|
531 | 532 |
|
| 533 | + /// Simple constant folding to determine if an expression depends on an external crate |
| 534 | + /// excluding crates listed in exceptions |
| 535 | + pub fn expr_is_external(&mut self, e: &Expr<'_>, exceptions: &[Symbol]) -> bool { |
| 536 | + match e.kind { |
| 537 | + ExprKind::ConstBlock(ConstBlock { body, .. }) => { |
| 538 | + self.expr_is_external(self.lcx.tcx.hir().body(body).value, exceptions) |
| 539 | + }, |
| 540 | + ExprKind::DropTemps(e) => self.expr_is_external(e, exceptions), |
| 541 | + ExprKind::Path(ref qpath) => { |
| 542 | + if let Some(def_id) = self.lcx.qpath_res(qpath, e.hir_id()).opt_def_id() { |
| 543 | + def_id.is_local() || exceptions.iter().all(|e| self.lcx.tcx.crate_name(def_id.krate) != *e) |
| 544 | + } else { |
| 545 | + true |
| 546 | + } |
| 547 | + }, |
| 548 | + ExprKind::Block(block, _) => { |
| 549 | + if block.stmts.is_empty() |
| 550 | + && let Some(expr) = block.expr |
| 551 | + { |
| 552 | + self.expr_is_external(expr, exceptions) |
| 553 | + } else { |
| 554 | + false |
| 555 | + } |
| 556 | + }, |
| 557 | + ExprKind::Array(vec) => vec.iter().any(|elem| self.expr_is_external(elem, exceptions)), |
| 558 | + ExprKind::Tup(tup) => tup.iter().any(|elem| self.expr_is_external(elem, exceptions)), |
| 559 | + ExprKind::Repeat(value, _) => self.expr_is_external(value, exceptions), |
| 560 | + ExprKind::Unary(_, operand) => self.expr_is_external(operand, exceptions), |
| 561 | + ExprKind::If(cond, then, ref otherwise) => { |
| 562 | + if let Some(Constant::Bool(b)) = self.expr(cond) { |
| 563 | + if b { |
| 564 | + self.expr_is_external(then, exceptions) |
| 565 | + } else { |
| 566 | + otherwise |
| 567 | + .as_ref() |
| 568 | + .is_some_and(|expr| self.expr_is_external(expr, exceptions)) |
| 569 | + } |
| 570 | + } else { |
| 571 | + false |
| 572 | + } |
| 573 | + }, |
| 574 | + ExprKind::Binary(_, left, right) => { |
| 575 | + self.expr_is_external(left, exceptions) || self.expr_is_external(right, exceptions) |
| 576 | + }, |
| 577 | + ExprKind::Index(arr, index, _) => { |
| 578 | + self.expr_is_external(arr, exceptions) || self.expr_is_external(index, exceptions) |
| 579 | + }, |
| 580 | + ExprKind::AddrOf(_, _, inner) => self.expr_is_external(inner, exceptions), |
| 581 | + ExprKind::Field(local_expr, _) => self.expr_is_external(local_expr, exceptions), |
| 582 | + _ => false, |
| 583 | + } |
| 584 | + } |
| 585 | + |
532 | 586 | #[expect(clippy::cast_possible_wrap)]
|
533 | 587 | fn constant_not(&self, o: &Constant<'tcx>, ty: Ty<'_>) -> Option<Constant<'tcx>> {
|
534 | 588 | use self::Constant::{Bool, Int};
|
|
0 commit comments