Skip to main content

rustc_const_eval/util/
mod.rs

1use rustc_hir::def::DefKind;
2use rustc_hir::def_id::DefId;
3use rustc_middle::mir;
4use rustc_middle::ty::TyCtxt;
5use rustc_span::Span;
6
7mod alignment;
8pub(crate) mod caller_location;
9mod check_validity_requirement;
10mod compare_types;
11mod type_name;
12
13pub use self::alignment::{most_packed_projection, place_unalignment};
14pub use self::check_validity_requirement::check_validity_requirement;
15pub(crate) use self::check_validity_requirement::validate_scalar_in_layout;
16pub use self::compare_types::{relate_types, sub_types};
17pub use self::type_name::type_name;
18
19/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
20/// same type as the result.
21#[inline]
22pub fn binop_left_homogeneous(op: mir::BinOp) -> bool {
23    use mir::BinOp::*;
24    match op {
25        Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Div | Rem | BitXor
26        | BitAnd | BitOr | Offset | Shl | ShlUnchecked | Shr | ShrUnchecked => true,
27        AddWithOverflow | SubWithOverflow | MulWithOverflow | Eq | Ne | Lt | Le | Gt | Ge | Cmp => {
28            false
29        }
30    }
31}
32
33/// Classify whether an operator is "right-homogeneous", i.e., the RHS has the
34/// same type as the LHS.
35#[inline]
36pub fn binop_right_homogeneous(op: mir::BinOp) -> bool {
37    use mir::BinOp::*;
38    match op {
39        Add | AddUnchecked | AddWithOverflow | Sub | SubUnchecked | SubWithOverflow | Mul
40        | MulUnchecked | MulWithOverflow | Div | Rem | BitXor | BitAnd | BitOr | Eq | Ne | Lt
41        | Le | Gt | Ge | Cmp => true,
42        Offset | Shl | ShlUnchecked | Shr | ShrUnchecked => false,
43    }
44}
45
46/// Classify whether an operator is "homogeneous", i.e., the operand has the
47/// same type as the result.
48#[inline]
49pub fn unop_homogeneous(op: mir::UnOp) -> bool {
50    match op {
51        mir::UnOp::Not | mir::UnOp::Neg => true,
52        mir::UnOp::PtrMetadata => false,
53    }
54}
55
56pub fn context_spans(tcx: TyCtxt<'_>, span: Span, def_id: DefId) -> Vec<Span> {
57    // For consts where the enclosing item might be useful context, include their spans in the
58    // diagnostic.
59    let instance_span = tcx.def_span(def_id).shrink_to_lo();
60    let parent = tcx.parent(def_id);
61    let parent_span = tcx.def_span(parent).shrink_to_lo();
62    let mut span = span;
63    if let Some(sp) = span.macro_backtrace().last() {
64        // We want the outermost span when macros are involved, as we don't care about the
65        // macro's internal consts for the purposes of adding context.
66        span = sp.call_site;
67    }
68    match (tcx.def_kind(def_id), tcx.def_kind(parent)) {
69        (
70            _,
71            DefKind::Struct
72            | DefKind::Union
73            | DefKind::Enum
74            | DefKind::Trait
75            | DefKind::Impl { .. }
76            | DefKind::TyAlias
77            | DefKind::Const
78            | DefKind::Fn
79            | DefKind::Static { .. },
80        )
81        | (DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy, _)
82            if span.eq_ctxt(instance_span) && span.eq_ctxt(parent_span) =>
83        {
84            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [instance_span, parent_span]))vec![instance_span, parent_span]
85        }
86        (_, DefKind::Variant) if span.eq_ctxt(instance_span) && span.eq_ctxt(parent_span) => {
87            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [instance_span, parent_span,
                tcx.def_span(tcx.parent(parent)).shrink_to_lo()]))vec![instance_span, parent_span, tcx.def_span(tcx.parent(parent)).shrink_to_lo()]
88        }
89        (DefKind::Const | DefKind::Static { .. }, _) if span.eq_ctxt(instance_span) => {
90            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [instance_span]))vec![instance_span]
91        }
92        _ => ::alloc::vec::Vec::new()vec![],
93    }
94}