diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs index 31f9131799..4eefd66d47 100644 --- a/crates/hir-def/src/data/adt.rs +++ b/crates/hir-def/src/data/adt.rs @@ -60,7 +60,7 @@ bitflags! { /// Indicates whether this struct is `ManuallyDrop`. const IS_MANUALLY_DROP = 1 << 6; /// Indicates whether this struct is `UnsafeCell`. - const IS_UNSAFE_CELL = 1 << 6; + const IS_UNSAFE_CELL = 1 << 7; } } diff --git a/crates/hir-ty/src/lang_items.rs b/crates/hir-ty/src/lang_items.rs index adfdb01e72..85ed46b963 100644 --- a/crates/hir-ty/src/lang_items.rs +++ b/crates/hir-ty/src/lang_items.rs @@ -7,7 +7,7 @@ use crate::db::HirDatabase; pub fn is_box(db: &dyn HirDatabase, adt: AdtId) -> bool { let AdtId::StructId(id) = adt else { return false }; - db.struct_data(id).flags.contains(StructFlags::IS_UNSAFE_CELL) + db.struct_data(id).flags.contains(StructFlags::IS_BOX) } pub fn is_unsafe_cell(db: &dyn HirDatabase, adt: AdtId) -> bool { diff --git a/crates/hir-ty/src/mir.rs b/crates/hir-ty/src/mir.rs index d830ae263b..1146431bcd 100644 --- a/crates/hir-ty/src/mir.rs +++ b/crates/hir-ty/src/mir.rs @@ -3,8 +3,8 @@ use std::{fmt::Display, iter}; use crate::{ - db::HirDatabase, infer::PointerCast, ClosureId, Const, ConstScalar, InferenceResult, Interner, - MemoryMap, Substitution, Ty, TyKind, + db::HirDatabase, display::HirDisplay, infer::PointerCast, lang_items::is_box, ClosureId, Const, + ConstScalar, InferenceResult, Interner, MemoryMap, Substitution, Ty, TyKind, }; use chalk_ir::Mutability; use hir_def::{ @@ -115,8 +115,11 @@ impl ProjectionElem { match self { ProjectionElem::Deref => match &base.data(Interner).kind { TyKind::Raw(_, inner) | TyKind::Ref(_, _, inner) => inner.clone(), + TyKind::Adt(adt, subst) if is_box(db, adt.0) => { + subst.at(Interner, 0).assert_ty_ref(Interner).clone() + } _ => { - never!("Overloaded deref is not a projection"); + never!("Overloaded deref on type {} is not a projection", base.display(db)); return TyKind::Error.intern(Interner); } }, diff --git a/crates/hir-ty/src/tests/method_resolution.rs b/crates/hir-ty/src/tests/method_resolution.rs index f62a3cfabe..1e57a4ae29 100644 --- a/crates/hir-ty/src/tests/method_resolution.rs +++ b/crates/hir-ty/src/tests/method_resolution.rs @@ -1939,3 +1939,54 @@ fn foo() { "#, ); } + +#[test] +fn box_deref_is_builtin() { + check( + r#" +//- minicore: deref +use core::ops::Deref; + +#[lang = "owned_box"] +struct Box(*mut T); + +impl Box { + fn new(t: T) -> Self { + loop {} + } +} + +impl Deref for Box { + type Target = T; + fn deref(&self) -> &Self::Target; +} + +struct Foo; +impl Foo { + fn foo(&self) {} +} +fn test() { + Box::new(Foo).foo(); + //^^^^^^^^^^^^^ adjustments: Deref(None), Borrow(Ref(Not)) +} +"#, + ); +} + +#[test] +fn manually_drop_deref_is_not_builtin() { + check( + r#" +//- minicore: manually_drop, deref +struct Foo; +impl Foo { + fn foo(&self) {} +} +use core::mem::ManuallyDrop; +fn test() { + ManuallyDrop::new(Foo).foo(); + //^^^^^^^^^^^^^^^^^^^^^^ adjustments: Deref(Some(OverloadedDeref(Some(Not)))), Borrow(Ref(Not)) +} +"#, + ); +} diff --git a/crates/test-utils/src/minicore.rs b/crates/test-utils/src/minicore.rs index 2f0c086092..ca1dbf532c 100644 --- a/crates/test-utils/src/minicore.rs +++ b/crates/test-utils/src/minicore.rs @@ -31,6 +31,7 @@ //! infallible: //! iterator: option //! iterators: iterator, fn +//! manually_drop: drop //! non_zero: //! option: panic //! ord: eq, option @@ -194,6 +195,30 @@ pub mod convert { // region:drop pub mod mem { + // region:manually_drop + #[lang = "manually_drop"] + #[repr(transparent)] + pub struct ManuallyDrop { + value: T, + } + + impl ManuallyDrop { + pub const fn new(value: T) -> ManuallyDrop { + ManuallyDrop { value } + } + } + + // region:deref + impl crate::ops::Deref for ManuallyDrop { + type Target = T; + fn deref(&self) -> &T { + &self.value + } + } + // endregion:deref + + // endregion:manually_drop + pub fn drop(_x: T) {} } // endregion:drop