about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yaml2
-rw-r--r--crates/hir-def/src/nameres/collector.rs6
-rw-r--r--crates/hir-expand/src/builtin_fn_macro.rs2
-rw-r--r--crates/hir-expand/src/hygiene.rs2
-rw-r--r--crates/hir-ty/src/consteval/tests/intrinsics.rs18
-rw-r--r--crates/hir-ty/src/infer/cast.rs12
-rw-r--r--crates/hir-ty/src/layout.rs3
-rw-r--r--crates/hir-ty/src/mir/eval/shim.rs128
-rw-r--r--crates/hir-ty/src/mir/eval/shim/simd.rs4
-rw-r--r--crates/hir-ty/src/mir/lower.rs17
10 files changed, 136 insertions, 58 deletions
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index ec3128d9ec1..479ca235408 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -98,7 +98,7 @@ jobs:
 
       - name: Run analysis-stats on rust std library
         if: matrix.os == 'ubuntu-latest'
-        run: target/${{ matrix.target }}/debug/rust-analyzer analysis-stats --with-deps $(rustc --print sysroot)/lib/rustlib/src/rust/library/std
+        run: RUSTC_BOOTSTRAP=1 target/${{ matrix.target }}/debug/rust-analyzer analysis-stats --with-deps $(rustc --print sysroot)/lib/rustlib/src/rust/library/std
 
   # Weird targets to catch non-portable code
   rust-cross:
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index e9e71a8747f..2d4586146db 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -1828,7 +1828,11 @@ impl ModCollector<'_, '_> {
             let Some(paths) = attr.parse_path_comma_token_tree(db.upcast(), &hygiene) else {
                 // `#[macro_use]` (without any paths) found, forget collected names and just import
                 // all visible macros.
-                self.def_collector.import_macros_from_extern_crate(target_crate, None, Some(extern_crate_id));
+                self.def_collector.import_macros_from_extern_crate(
+                    target_crate,
+                    None,
+                    Some(extern_crate_id),
+                );
                 return;
             };
             for path in paths {
diff --git a/crates/hir-expand/src/builtin_fn_macro.rs b/crates/hir-expand/src/builtin_fn_macro.rs
index 95c6baf42da..6a48acef963 100644
--- a/crates/hir-expand/src/builtin_fn_macro.rs
+++ b/crates/hir-expand/src/builtin_fn_macro.rs
@@ -692,7 +692,7 @@ pub(crate) fn include_arg_to_tt(
     arg_id: MacroCallId,
 ) -> Result<(triomphe::Arc<(::tt::Subtree<::tt::TokenId>, TokenMap)>, FileId), ExpandError> {
     let loc = db.lookup_intern_macro_call(arg_id);
-    let Some(EagerCallInfo { arg,arg_id, .. }) = loc.eager.as_deref() else {
+    let Some(EagerCallInfo { arg, arg_id, .. }) = loc.eager.as_deref() else {
         panic!("include_arg_to_tt called on non include macro call: {:?}", &loc.eager);
     };
     let path = parse_string(&arg.0)?;
diff --git a/crates/hir-expand/src/hygiene.rs b/crates/hir-expand/src/hygiene.rs
index ade4a592893..ca65db1136c 100644
--- a/crates/hir-expand/src/hygiene.rs
+++ b/crates/hir-expand/src/hygiene.rs
@@ -242,7 +242,7 @@ impl HygieneFrame {
                 krate,
                 call_site: None,
                 def_site: None,
-            }
+            };
         };
 
         let def_site = info.attr_input_or_mac_def_start.map(|it| db.hygiene_frame(it.file_id));
diff --git a/crates/hir-ty/src/consteval/tests/intrinsics.rs b/crates/hir-ty/src/consteval/tests/intrinsics.rs
index 2855f789001..cc3a43fd9ae 100644
--- a/crates/hir-ty/src/consteval/tests/intrinsics.rs
+++ b/crates/hir-ty/src/consteval/tests/intrinsics.rs
@@ -499,24 +499,26 @@ fn offset() {
         r#"
         //- minicore: coerce_unsized, index, slice
         extern "rust-intrinsic" {
-            pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
+            pub fn offset<Ptr, Delta>(dst: Ptr, offset: Delta) -> Ptr;
+            pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
         }
 
-        const GOAL: u8 = unsafe {
-            let ar: &[(u8, u8, u8)] = &[
+        const GOAL: i32 = unsafe {
+            let ar: &[(i32, i32, i32)] = &[
                 (10, 11, 12),
                 (20, 21, 22),
                 (30, 31, 32),
                 (40, 41, 42),
                 (50, 51, 52),
             ];
-            let ar: *const [(u8, u8, u8)] = ar;
-            let ar = ar as *const (u8, u8, u8);
-            let element = *offset(ar, 2);
-            element.1
+            let ar: *const [(i32, i32, i32)] = ar;
+            let ar = ar as *const (i32, i32, i32);
+            let element3 = *offset(ar, 2usize);
+            let element4 = *arith_offset(ar, 3);
+            element3.1 * 100 + element4.0
         };
         "#,
-        31,
+        3140,
     );
 }
 
diff --git a/crates/hir-ty/src/infer/cast.rs b/crates/hir-ty/src/infer/cast.rs
index 9e1c74b16fa..a116d444731 100644
--- a/crates/hir-ty/src/infer/cast.rs
+++ b/crates/hir-ty/src/infer/cast.rs
@@ -39,8 +39,14 @@ impl CastCheck {
 }
 
 fn check_ref_to_ptr_cast(expr_ty: Ty, cast_ty: Ty, table: &mut InferenceTable<'_>) -> bool {
-    let Some((expr_inner_ty, _, _)) = expr_ty.as_reference() else { return false; };
-    let Some((cast_inner_ty, _)) = cast_ty.as_raw_ptr() else { return false; };
-    let TyKind::Array(expr_elt_ty, _) = expr_inner_ty.kind(Interner) else { return false; };
+    let Some((expr_inner_ty, _, _)) = expr_ty.as_reference() else {
+        return false;
+    };
+    let Some((cast_inner_ty, _)) = cast_ty.as_raw_ptr() else {
+        return false;
+    };
+    let TyKind::Array(expr_elt_ty, _) = expr_inner_ty.kind(Interner) else {
+        return false;
+    };
     table.coerce(expr_elt_ty, cast_inner_ty).is_ok()
 }
diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs
index b15339d4434..714930ba667 100644
--- a/crates/hir-ty/src/layout.rs
+++ b/crates/hir-ty/src/layout.rs
@@ -109,7 +109,8 @@ fn layout_of_simd_ty(
     // * the homogeneous field type and the number of fields.
     let (e_ty, e_len, is_array) = if let TyKind::Array(e_ty, _) = f0_ty.kind(Interner) {
         // Extract the number of elements from the layout of the array field:
-        let FieldsShape::Array { count, .. } = db.layout_of_ty(f0_ty.clone(), env.clone())?.fields else {
+        let FieldsShape::Array { count, .. } = db.layout_of_ty(f0_ty.clone(), env.clone())?.fields
+        else {
             user_error!("Array with non array layout");
         };
 
diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs
index 52943e97ac0..18396638940 100644
--- a/crates/hir-ty/src/mir/eval/shim.rs
+++ b/crates/hir-ty/src/mir/eval/shim.rs
@@ -4,7 +4,10 @@
 use std::cmp;
 
 use chalk_ir::TyKind;
-use hir_def::resolver::HasResolver;
+use hir_def::{
+    builtin_type::{BuiltinInt, BuiltinUint},
+    resolver::HasResolver,
+};
 use hir_expand::mod_path::ModPath;
 
 use super::*;
@@ -300,21 +303,36 @@ impl Evaluator<'_> {
             BeginPanic => Err(MirEvalError::Panic("<unknown-panic-payload>".to_string())),
             PanicFmt => {
                 let message = (|| {
-                    let resolver = self.db.crate_def_map(self.crate_id).crate_root().resolver(self.db.upcast());
+                    let resolver = self
+                        .db
+                        .crate_def_map(self.crate_id)
+                        .crate_root()
+                        .resolver(self.db.upcast());
                     let Some(format_fn) = resolver.resolve_path_in_value_ns_fully(
                         self.db.upcast(),
-                        &hir_def::path::Path::from_known_path_with_no_generic(ModPath::from_segments(
-                            hir_expand::mod_path::PathKind::Abs,
-                            [name![std], name![fmt], name![format]].into_iter(),
-                        )),
+                        &hir_def::path::Path::from_known_path_with_no_generic(
+                            ModPath::from_segments(
+                                hir_expand::mod_path::PathKind::Abs,
+                                [name![std], name![fmt], name![format]].into_iter(),
+                            ),
+                        ),
                     ) else {
                         not_supported!("std::fmt::format not found");
                     };
-                    let hir_def::resolver::ValueNs::FunctionId(format_fn) = format_fn else { not_supported!("std::fmt::format is not a function") };
-                    let message_string = self.interpret_mir(self.db.mir_body(format_fn.into()).map_err(|e| MirEvalError::MirLowerError(format_fn, e))?, args.map(|x| IntervalOrOwned::Owned(x.clone())))?;
-                    let addr = Address::from_bytes(&message_string[self.ptr_size()..2 * self.ptr_size()])?;
+                    let hir_def::resolver::ValueNs::FunctionId(format_fn) = format_fn else {
+                        not_supported!("std::fmt::format is not a function")
+                    };
+                    let message_string = self.interpret_mir(
+                        self.db
+                            .mir_body(format_fn.into())
+                            .map_err(|e| MirEvalError::MirLowerError(format_fn, e))?,
+                        args.map(|x| IntervalOrOwned::Owned(x.clone())),
+                    )?;
+                    let addr =
+                        Address::from_bytes(&message_string[self.ptr_size()..2 * self.ptr_size()])?;
                     let size = from_bytes!(usize, message_string[2 * self.ptr_size()..]);
-                    Ok(std::string::String::from_utf8_lossy(self.read_memory(addr, size)?).into_owned())
+                    Ok(std::string::String::from_utf8_lossy(self.read_memory(addr, size)?)
+                        .into_owned())
                 })()
                 .unwrap_or_else(|e| format!("Failed to render panic format args: {e:?}"));
                 Err(MirEvalError::Panic(message))
@@ -483,9 +501,7 @@ impl Evaluator<'_> {
             }
             "syscall" => {
                 let Some((id, rest)) = args.split_first() else {
-                    return Err(MirEvalError::TypeError(
-                        "syscall arg1 is not provided",
-                    ));
+                    return Err(MirEvalError::TypeError("syscall arg1 is not provided"));
                 };
                 let id = from_bytes!(i64, id.get(self)?);
                 self.exec_syscall(id, rest, destination, locals, span)
@@ -710,7 +726,8 @@ impl Evaluator<'_> {
         }
         match name {
             "size_of" => {
-                let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner))
+                let Some(ty) =
+                    generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner))
                 else {
                     return Err(MirEvalError::TypeError("size_of generic arg is not provided"));
                 };
@@ -718,14 +735,17 @@ impl Evaluator<'_> {
                 destination.write_from_bytes(self, &size.to_le_bytes()[0..destination.size])
             }
             "min_align_of" | "pref_align_of" => {
-                let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner)) else {
+                let Some(ty) =
+                    generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner))
+                else {
                     return Err(MirEvalError::TypeError("align_of generic arg is not provided"));
                 };
                 let align = self.layout(ty)?.align.abi.bytes();
                 destination.write_from_bytes(self, &align.to_le_bytes()[0..destination.size])
             }
             "size_of_val" => {
-                let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner))
+                let Some(ty) =
+                    generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner))
                 else {
                     return Err(MirEvalError::TypeError("size_of_val generic arg is not provided"));
                 };
@@ -741,8 +761,12 @@ impl Evaluator<'_> {
                 }
             }
             "min_align_of_val" => {
-                let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner)) else {
-                    return Err(MirEvalError::TypeError("min_align_of_val generic arg is not provided"));
+                let Some(ty) =
+                    generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner))
+                else {
+                    return Err(MirEvalError::TypeError(
+                        "min_align_of_val generic arg is not provided",
+                    ));
                 };
                 let [arg] = args else {
                     return Err(MirEvalError::TypeError("min_align_of_val args are not provided"));
@@ -756,7 +780,8 @@ impl Evaluator<'_> {
                 }
             }
             "type_name" => {
-                let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner))
+                let Some(ty) =
+                    generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner))
                 else {
                     return Err(MirEvalError::TypeError("type_name generic arg is not provided"));
                 };
@@ -779,7 +804,8 @@ impl Evaluator<'_> {
                     .write_from_bytes(self, &len.to_le_bytes())
             }
             "needs_drop" => {
-                let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner))
+                let Some(ty) =
+                    generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner))
                 else {
                     return Err(MirEvalError::TypeError("size_of generic arg is not provided"));
                 };
@@ -831,9 +857,12 @@ impl Evaluator<'_> {
                 let lhs = i128::from_le_bytes(pad16(lhs.get(self)?, false));
                 let rhs = i128::from_le_bytes(pad16(rhs.get(self)?, false));
                 let ans = lhs.wrapping_sub(rhs);
-                let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner))
+                let Some(ty) =
+                    generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner))
                 else {
-                    return Err(MirEvalError::TypeError("ptr_offset_from generic arg is not provided"));
+                    return Err(MirEvalError::TypeError(
+                        "ptr_offset_from generic arg is not provided",
+                    ));
                 };
                 let size = self.size_of_sized(ty, locals, "ptr_offset_from arg")? as i128;
                 let ans = ans / size;
@@ -940,7 +969,8 @@ impl Evaluator<'_> {
                         "copy_nonoverlapping args are not provided",
                     ));
                 };
-                let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner))
+                let Some(ty) =
+                    generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner))
                 else {
                     return Err(MirEvalError::TypeError(
                         "copy_nonoverlapping generic arg is not provided",
@@ -959,9 +989,45 @@ impl Evaluator<'_> {
                 let [ptr, offset] = args else {
                     return Err(MirEvalError::TypeError("offset args are not provided"));
                 };
-                let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner))
-                else {
-                    return Err(MirEvalError::TypeError("offset generic arg is not provided"));
+                let ty = if name == "offset" {
+                    let Some(ty0) =
+                        generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner))
+                    else {
+                        return Err(MirEvalError::TypeError("offset generic arg is not provided"));
+                    };
+                    let Some(ty1) =
+                        generic_args.as_slice(Interner).get(1).and_then(|it| it.ty(Interner))
+                    else {
+                        return Err(MirEvalError::TypeError("offset generic arg is not provided"));
+                    };
+                    if !matches!(
+                        ty1.as_builtin(),
+                        Some(
+                            BuiltinType::Int(BuiltinInt::Isize)
+                                | BuiltinType::Uint(BuiltinUint::Usize)
+                        )
+                    ) {
+                        return Err(MirEvalError::TypeError(
+                            "offset generic arg is not usize or isize",
+                        ));
+                    }
+                    match ty0.as_raw_ptr() {
+                        Some((ty, _)) => ty,
+                        None => {
+                            return Err(MirEvalError::TypeError(
+                                "offset generic arg is not a raw pointer",
+                            ));
+                        }
+                    }
+                } else {
+                    let Some(ty) =
+                        generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner))
+                    else {
+                        return Err(MirEvalError::TypeError(
+                            "arith_offset generic arg is not provided",
+                        ));
+                    };
+                    ty
                 };
                 let ptr = u128::from_le_bytes(pad16(ptr.get(self)?, false));
                 let offset = u128::from_le_bytes(pad16(offset.get(self)?, false));
@@ -1079,7 +1145,8 @@ impl Evaluator<'_> {
                 let [arg] = args else {
                     return Err(MirEvalError::TypeError("discriminant_value arg is not provided"));
                 };
-                let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner))
+                let Some(ty) =
+                    generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner))
                 else {
                     return Err(MirEvalError::TypeError(
                         "discriminant_value generic arg is not provided",
@@ -1139,11 +1206,10 @@ impl Evaluator<'_> {
                 };
                 let count = from_bytes!(usize, count.get(self)?);
                 let val = from_bytes!(u8, val.get(self)?);
-                let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner))
+                let Some(ty) =
+                    generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner))
                 else {
-                    return Err(MirEvalError::TypeError(
-                        "write_bytes generic arg is not provided",
-                    ));
+                    return Err(MirEvalError::TypeError("write_bytes generic arg is not provided"));
                 };
                 let dst = Address::from_bytes(dst.get(self)?)?;
                 let size = self.size_of_sized(ty, locals, "copy_nonoverlapping ptr type")?;
diff --git a/crates/hir-ty/src/mir/eval/shim/simd.rs b/crates/hir-ty/src/mir/eval/shim/simd.rs
index ec746310487..51900662426 100644
--- a/crates/hir-ty/src/mir/eval/shim/simd.rs
+++ b/crates/hir-ty/src/mir/eval/shim/simd.rs
@@ -45,7 +45,9 @@ impl Evaluator<'_> {
                 };
                 match try_const_usize(self.db, len) {
                     Some(len) => {
-                        let Some(ty) = subst.as_slice(Interner).get(0).and_then(|it| it.ty(Interner)) else {
+                        let Some(ty) =
+                            subst.as_slice(Interner).get(0).and_then(|it| it.ty(Interner))
+                        else {
                             return Err(MirEvalError::TypeError("simd type with no ty param"));
                         };
                         Ok((len as usize, ty.clone()))
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index 51cf882d053..7c15aa42fd2 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -1201,7 +1201,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
                     let Some(values) = elements
                         .iter()
                         .map(|it| {
-                            let Some((o, c)) = self.lower_expr_to_some_operand(*it, current)? else {
+                            let Some((o, c)) = self.lower_expr_to_some_operand(*it, current)?
+                            else {
                                 return Ok(None);
                             };
                             current = c;
@@ -1259,7 +1260,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
                         *expr,
                         rhs.project(ProjectionElem::TupleOrClosureField(i)),
                         span,
-                    )? else {
+                    )?
+                    else {
                         return Ok(None);
                     };
                     current = c;
@@ -1268,8 +1270,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
             }
             Expr::Underscore => Ok(Some(current)),
             _ => {
-                let Some((lhs_place, current)) =
-                    self.lower_expr_as_place(current, lhs, false)?
+                let Some((lhs_place, current)) = self.lower_expr_as_place(current, lhs, false)?
                 else {
                     return Ok(None);
                 };
@@ -1286,9 +1287,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
         rhs: ExprId,
         span: MirSpan,
     ) -> Result<Option<BasicBlockId>> {
-        let Some((rhs_op, current)) =
-            self.lower_expr_to_some_operand(rhs, current)?
-        else {
+        let Some((rhs_op, current)) = self.lower_expr_to_some_operand(rhs, current)? else {
             return Ok(None);
         };
         if matches!(&self.body.exprs[lhs], Expr::Underscore) {
@@ -1303,9 +1302,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
             self.push_assignment(current, temp.clone(), rhs_op.into(), span);
             return self.lower_destructing_assignment(current, lhs, temp, span);
         }
-        let Some((lhs_place, current)) =
-            self.lower_expr_as_place(current, lhs, false)?
-        else {
+        let Some((lhs_place, current)) = self.lower_expr_as_place(current, lhs, false)? else {
             return Ok(None);
         };
         self.push_assignment(current, lhs_place, rhs_op.into(), span);