diff --git a/crates/hir-def/src/expr_store/pretty.rs b/crates/hir-def/src/expr_store/pretty.rs index 293adfc9bd45..ccc08a34d714 100644 --- a/crates/hir-def/src/expr_store/pretty.rs +++ b/crates/hir-def/src/expr_store/pretty.rs @@ -14,7 +14,7 @@ use stdx::never; use syntax::ast::{HasName, RangeOp}; use crate::{ - AdtId, DefWithBodyId, FunctionId, GenericDefId, StructId, TypeParamId, VariantId, + AdtId, DefWithBodyId, FunctionId, GenericDefId, MacroId, StructId, TypeParamId, VariantId, attrs::AttrFlags, expr_store::path::{GenericArg, GenericArgs}, hir::{ @@ -1136,6 +1136,9 @@ impl Printer<'_> { LangItemTarget::TraitId(it) => write_name!(it), LangItemTarget::EnumVariantId(it) => write_name!(it), LangItemTarget::ConstId(it) => write_name!(it), + LangItemTarget::MacroId(MacroId::Macro2Id(it)) => write_name!(it), + LangItemTarget::MacroId(MacroId::MacroRulesId(it)) => write_name!(it), + LangItemTarget::MacroId(MacroId::ProcMacroId(it)) => write_name!(it), } if let Some(s) = s { diff --git a/crates/hir-def/src/lang_item.rs b/crates/hir-def/src/lang_item.rs index f9d5a843bd8c..04dfdb7d1627 100644 --- a/crates/hir-def/src/lang_item.rs +++ b/crates/hir-def/src/lang_item.rs @@ -26,10 +26,11 @@ pub enum LangItemTarget { TraitId(TraitId), EnumVariantId(EnumVariantId), ConstId(ConstId), + MacroId(MacroId), } impl_from!( - EnumId, FunctionId, ImplId, StaticId, StructId, UnionId, TypeAliasId, TraitId, EnumVariantId, ConstId for LangItemTarget + EnumId, FunctionId, ImplId, StaticId, StructId, UnionId, TypeAliasId, TraitId, EnumVariantId, ConstId, MacroId for LangItemTarget ); /// Salsa query. This will look for lang items in a specific crate. @@ -276,7 +277,6 @@ impl LangItems { (self.BitXorAssign, &mut self.BitXorAssign_bitxor_assign, sym::bitxor_assign), (self.BitOrAssign, &mut self.BitOrAssign_bitor_assign, sym::bitor_assign), (self.BitAndAssign, &mut self.BitAndAssign_bitand_assign, sym::bitand_assign), - (self.Drop, &mut self.Drop_drop, sym::drop), (self.Debug, &mut self.Debug_fmt, sym::fmt), (self.Deref, &mut self.Deref_deref, sym::deref), (self.DerefMut, &mut self.DerefMut_deref_mut, sym::deref_mut), @@ -307,6 +307,13 @@ impl LangItems { ); Some(()) })(); + (|| { + methods( + self.Drop?, + &mut [(&mut self.Drop_drop, sym::drop), (&mut self.Drop_pin_drop, sym::pin_drop)], + ); + Some(()) + })(); } } @@ -397,11 +404,15 @@ macro_rules! language_item_table { } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + #[allow(non_camel_case_types)] pub enum LangItemEnum { $( $(#[$attr])* $lang_item, )* + $( $non_lang_trait, )* + $( $non_lang_macro_field, )* + $( $resolve_manually, )* } impl LangItemEnum { @@ -409,6 +420,9 @@ macro_rules! language_item_table { pub fn from_lang_items(self, lang_items: &LangItems) -> Option { match self { $( LangItemEnum::$lang_item => lang_items.$lang_item.map(Into::into), )* + $( LangItemEnum::$non_lang_trait => lang_items.$non_lang_trait.map(Into::into), )* + $( LangItemEnum::$non_lang_macro_field => lang_items.$non_lang_macro_field.map(Into::into), )* + $( LangItemEnum::$resolve_manually => lang_items.$resolve_manually.map(Into::into), )* } } @@ -716,6 +730,7 @@ language_item_table! { LangItems => PartialOrd_ge, FunctionId; PartialOrd_gt, FunctionId; Drop_drop, FunctionId; + Drop_pin_drop, FunctionId; Debug_fmt, FunctionId; Deref_deref, FunctionId; DerefMut_deref_mut, FunctionId; diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index 0062e6c17078..c16ad9b4f286 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -195,7 +195,8 @@ impl<'db> Resolver<'db> { LangItemTarget::FunctionId(_) | LangItemTarget::ImplId(_) | LangItemTarget::StaticId(_) - | LangItemTarget::ConstId(_) => return None, + | LangItemTarget::ConstId(_) + | LangItemTarget::MacroId(_) => return None, }; return Some(( type_ns, @@ -343,7 +344,8 @@ impl<'db> Resolver<'db> { | LangItemTarget::ImplId(_) | LangItemTarget::TypeAliasId(_) | LangItemTarget::TraitId(_) - | LangItemTarget::EnumId(_) => return None, + | LangItemTarget::EnumId(_) + | LangItemTarget::MacroId(_) => return None, }), ResolvePathResultPrefixInfo::default(), )); @@ -359,7 +361,8 @@ impl<'db> Resolver<'db> { LangItemTarget::FunctionId(_) | LangItemTarget::ImplId(_) | LangItemTarget::StaticId(_) - | LangItemTarget::ConstId(_) => return None, + | LangItemTarget::ConstId(_) + | LangItemTarget::MacroId(_) => return None, }; // Remaining segments start from 0 because lang paths have no segments other than the remaining. return Some(( diff --git a/crates/hir-expand/src/name.rs b/crates/hir-expand/src/name.rs index 3ddc305f9592..b511bc3c15ff 100644 --- a/crates/hir-expand/src/name.rs +++ b/crates/hir-expand/src/name.rs @@ -201,10 +201,15 @@ impl Name { #[inline] pub fn is_generated(&self) -> bool { - self.as_str().starts_with("") + is_generated(self.as_str()) } } +#[inline] +pub fn is_generated(name: &str) -> bool { + name.starts_with("") +} + struct Display<'a> { name: &'a Name, edition: Edition, diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index d187763151a2..85b87c593fe4 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -164,7 +164,7 @@ pub use { }, inert_attr_macro::AttributeTemplate, mod_path::{ModPath, PathKind, tool_path}, - name::Name, + name::{self, Name}, prettify_macro_expansion, proc_macro::{ProcMacros, ProcMacrosBuilder}, tt, @@ -2283,6 +2283,14 @@ impl fmt::Debug for Function { } impl Function { + pub fn lang(db: &dyn HirDatabase, krate: Crate, lang_item: LangItem) -> Option { + let lang_items = hir_def::lang_item::lang_items(db, krate.id); + match lang_item.from_lang_items(lang_items)? { + LangItemTarget::FunctionId(it) => Some(it.into()), + _ => None, + } + } + pub fn module(self, db: &dyn HirDatabase) -> Module { match self.id { AnyFunctionId::FunctionId(id) => id.module(db).into(), diff --git a/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/crates/ide-assists/src/handlers/add_missing_impl_members.rs index efbe3817e12f..1e8fb51a3e18 100644 --- a/crates/ide-assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ide-assists/src/handlers/add_missing_impl_members.rs @@ -2637,6 +2637,69 @@ struct Struct; impl Trait for Struct { $0 +} + "#, + ); + } + + #[test] + fn drop_pin_drop() { + check_assist_not_applicable( + add_missing_impl_members, + r#" +//- minicore: drop, pin +struct Foo; +impl Drop for Foo {$0 + fn drop(&mut self) {} +} + "#, + ); + check_assist_not_applicable( + add_missing_impl_members, + r#" +//- minicore: drop, pin +struct Foo; +impl Drop for Foo {$0 + fn pin_drop(self: core::pin::Pin<&mut Self>) {} +} + "#, + ); + + check_assist_not_applicable( + add_missing_default_members, + r#" +//- minicore: drop, pin +struct Foo; +impl Drop for Foo {$0 + fn drop(&mut self) {} +} + "#, + ); + check_assist_not_applicable( + add_missing_default_members, + r#" +//- minicore: drop, pin +struct Foo; +impl Drop for Foo {$0 + fn pin_drop(self: core::pin::Pin<&mut Self>) {} +} + "#, + ); + + check_assist( + add_missing_impl_members, + r#" +//- minicore: drop, pin +struct Foo; +impl Drop for Foo {$0 +} + "#, + r#" +struct Foo; +impl Drop for Foo { + fn drop(&mut self) { + ${0:todo!()} + } } "#, ); diff --git a/crates/ide-db/src/traits.rs b/crates/ide-db/src/traits.rs index d38d9b67080f..994427ac76f8 100644 --- a/crates/ide-db/src/traits.rs +++ b/crates/ide-db/src/traits.rs @@ -1,7 +1,7 @@ //! Functionality for obtaining data related to traits from the DB. use crate::{RootDatabase, defs::Definition}; -use hir::{AsAssocItem, Semantics, db::HirDatabase}; +use hir::{AsAssocItem, HasCrate, Semantics, db::HirDatabase, sym}; use rustc_hash::FxHashSet; use syntax::{AstNode, ast}; @@ -51,19 +51,38 @@ pub fn get_missing_assoc_items( } } - imp.trait_(sema.db).map_or(vec![], |target_trait| { - target_trait - .items(sema.db) - .into_iter() - .filter(|i| match i { - hir::AssocItem::Function(f) => !impl_fns_consts.contains(&f.name(sema.db)), - hir::AssocItem::TypeAlias(t) => !impl_type.contains(&t.name(sema.db)), - hir::AssocItem::Const(c) => { - c.name(sema.db).map(|n| !impl_fns_consts.contains(&n)).unwrap_or_default() - } - }) - .collect() - }) + let Some(target_trait) = imp.trait_(sema.db) else { return Vec::new() }; + + // `Drop` has two methods, `drop()` and `pin_drop()`, and you can only implement one of them, so + // we consider `pin_drop()` to not exist, unless you already implement it. + let drop_trait = hir::Trait::lang(sema.db, imp.krate(sema.db), hir::LangItem::Drop); + if let Some(drop_trait) = drop_trait + && target_trait == drop_trait + { + return if impl_fns_consts.is_empty() { + // No method implemented, return `drop()`. + let drop_drop = drop_trait.function(sema.db, sym::drop); + match drop_drop { + Some(drop_drop) => vec![hir::AssocItem::Function(drop_drop)], + None => Vec::new(), + } + } else { + // Some method is already implemented, leave it. + Vec::new() + }; + } + + target_trait + .items(sema.db) + .into_iter() + .filter(|i| match i { + hir::AssocItem::Function(f) => !impl_fns_consts.contains(&f.name(sema.db)), + hir::AssocItem::TypeAlias(t) => !impl_type.contains(&t.name(sema.db)), + hir::AssocItem::Const(c) => { + c.name(sema.db).map(|n| !impl_fns_consts.contains(&n)).unwrap_or_default() + } + }) + .collect() } /// Converts associated trait impl items to their trait definition counterpart diff --git a/crates/ide/src/inlay_hints/implicit_drop.rs b/crates/ide/src/inlay_hints/implicit_drop.rs index f6b13cbe0b94..9387573cf7ac 100644 --- a/crates/ide/src/inlay_hints/implicit_drop.rs +++ b/crates/ide/src/inlay_hints/implicit_drop.rs @@ -9,6 +9,7 @@ use hir::{ DefWithBody, db::HirDatabase as _, mir::{MirSpan, TerminatorKind}, + name, }; use ide_db::{FileRange, famous_defs::FamousDefs}; @@ -95,7 +96,7 @@ pub(super) fn hints( }; let binding = &hir[binding_idx]; let name = binding.name.display_no_db(display_target.edition).to_smolstr(); - if name.starts_with(" i32 { foo + bar } +async fn test_async(foo: i32, _: i32) {} fn main() { let not_literal = 1; @@ -631,6 +633,8 @@ fn main() { None, //^^^^ docs ); + test_async(1, 2) + //^ foo }"#, ); } diff --git a/crates/intern/src/symbol/symbols.rs b/crates/intern/src/symbol/symbols.rs index e5f66a202ee6..fe303aa0e0c3 100644 --- a/crates/intern/src/symbol/symbols.rs +++ b/crates/intern/src/symbol/symbols.rs @@ -295,6 +295,7 @@ define_symbols! { doc, drop_in_place, drop, + pin_drop, dyn_metadata, efiapi, eh_catch_typeinfo, diff --git a/crates/test-utils/src/minicore.rs b/crates/test-utils/src/minicore.rs index bd15dca609b1..c5ebc0d24880 100644 --- a/crates/test-utils/src/minicore.rs +++ b/crates/test-utils/src/minicore.rs @@ -655,6 +655,10 @@ pub mod ops { #[lang = "drop"] pub trait Drop { fn drop(&mut self); + + // region:pin + fn pin_drop(self: crate::pin::Pin<&mut Self>) {} + // endregion:pin } // endregion:drop