]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_hir_analysis/src/check/intrinsicck.rs
Add examples for `pointer::mask`
[rust.git] / compiler / rustc_hir_analysis / src / check / intrinsicck.rs
index 25228f424cd0793688b3ba19671c624aed959ca5..a026f8033c8cb5029a89602d5b249a48d7aa1e2f 100644 (file)
-use hir::HirId;
 use rustc_ast::InlineAsmTemplatePiece;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::struct_span_err;
 use rustc_hir as hir;
-use rustc_index::vec::Idx;
-use rustc_middle::ty::layout::{LayoutError, SizeSkeleton};
 use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitable, UintTy};
 use rustc_session::lint;
 use rustc_span::{Symbol, DUMMY_SP};
-use rustc_target::abi::{Pointer, VariantIdx};
 use rustc_target::asm::{InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType};
 
-use super::FnCtxt;
-
-/// If the type is `Option<T>`, it will return `T`, otherwise
-/// the type itself. Works on most `Option`-like types.
-fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
-    let ty::Adt(def, substs) = *ty.kind() else { return ty };
-
-    if def.variants().len() == 2 && !def.repr().c() && def.repr().int.is_none() {
-        let data_idx;
-
-        let one = VariantIdx::new(1);
-        let zero = VariantIdx::new(0);
-
-        if def.variant(zero).fields.is_empty() {
-            data_idx = one;
-        } else if def.variant(one).fields.is_empty() {
-            data_idx = zero;
-        } else {
-            return ty;
-        }
-
-        if def.variant(data_idx).fields.len() == 1 {
-            return def.variant(data_idx).fields[0].ty(tcx, substs);
-        }
-    }
-
-    ty
-}
-
-impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
-    pub fn check_transmute(&self, from: Ty<'tcx>, to: Ty<'tcx>, hir_id: HirId) {
-        let tcx = self.tcx;
-        let span = tcx.hir().span(hir_id);
-        let normalize = |ty| {
-            let ty = self.resolve_vars_if_possible(ty);
-            self.tcx.normalize_erasing_regions(self.param_env, ty)
-        };
-        let from = normalize(from);
-        let to = normalize(to);
-        trace!(?from, ?to);
-
-        // Transmutes that are only changing lifetimes are always ok.
-        if from == to {
-            return;
-        }
-
-        let skel = |ty| SizeSkeleton::compute(ty, tcx, self.param_env);
-        let sk_from = skel(from);
-        let sk_to = skel(to);
-        trace!(?sk_from, ?sk_to);
-
-        // Check for same size using the skeletons.
-        if let (Ok(sk_from), Ok(sk_to)) = (sk_from, sk_to) {
-            if sk_from.same_size(sk_to) {
-                return;
-            }
-
-            // Special-case transmuting from `typeof(function)` and
-            // `Option<typeof(function)>` to present a clearer error.
-            let from = unpack_option_like(tcx, from);
-            if let (&ty::FnDef(..), SizeSkeleton::Known(size_to)) = (from.kind(), sk_to) && size_to == Pointer.size(&tcx) {
-                struct_span_err!(tcx.sess, span, E0591, "can't transmute zero-sized type")
-                    .note(&format!("source type: {from}"))
-                    .note(&format!("target type: {to}"))
-                    .help("cast with `as` to a pointer instead")
-                    .emit();
-                return;
-            }
-        }
-
-        // Try to display a sensible error with as much information as possible.
-        let skeleton_string = |ty: Ty<'tcx>, sk| match sk {
-            Ok(SizeSkeleton::Known(size)) => format!("{} bits", size.bits()),
-            Ok(SizeSkeleton::Pointer { tail, .. }) => format!("pointer to `{tail}`"),
-            Err(LayoutError::Unknown(bad)) => {
-                if bad == ty {
-                    "this type does not have a fixed size".to_owned()
-                } else {
-                    format!("size can vary because of {bad}")
-                }
-            }
-            Err(err) => err.to_string(),
-        };
-
-        let mut err = struct_span_err!(
-            tcx.sess,
-            span,
-            E0512,
-            "cannot transmute between types of different sizes, \
-                                        or dependently-sized types"
-        );
-        if from == to {
-            err.note(&format!("`{from}` does not have a fixed size"));
-        } else {
-            err.note(&format!("source type: `{}` ({})", from, skeleton_string(from, sk_from)))
-                .note(&format!("target type: `{}` ({})", to, skeleton_string(to, sk_to)));
-        }
-        err.emit();
-    }
-}
-
 pub struct InlineAsmCtxt<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,