Skip to content

Commit 24bf53d

Browse files
committed
Auto merge of #17268 - Veykril:signatures, r=Veykril
feat: More callable info With this PR we retain more info about callables other than functions, allowing for closure parameter type inlay hints to be linkable as well as better signature help around closures and `Fn*` implementors.
2 parents 9f4b651 + 6438554 commit 24bf53d

17 files changed

Lines changed: 388 additions & 226 deletions

File tree

‎src/tools/rust-analyzer/crates/hir-def/src/attr/builtin.rs‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@ use std::sync::OnceLock;
1212

1313
use rustc_hash::FxHashMap;
1414

15-
/// Ignored attribute namespaces used by tools.
16-
pubconstTOOL_MODULES:&[&str] = &["rustfmt","clippy"];
17-
1815
pubstructBuiltinAttribute{
1916
pubname:&'staticstr,
2017
pubtemplate:AttributeTemplate,

‎src/tools/rust-analyzer/crates/hir-def/src/nameres.rs‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,14 @@ use crate::{
8484
LocalModuleId,Lookup,MacroExpander,MacroId,ModuleId,ProcMacroId,UseId,
8585
};
8686

87+
constPREDEFINED_TOOLS:&[SmolStr] = &[
88+
SmolStr::new_static("clippy"),
89+
SmolStr::new_static("rustfmt"),
90+
SmolStr::new_static("diagnostic"),
91+
SmolStr::new_static("miri"),
92+
SmolStr::new_static("rust_analyzer"),
93+
];
94+
8795
/// Contains the results of (early) name resolution.
8896
///
8997
/// A `DefMap` stores the module tree and the definitions that are in scope in every module after
@@ -160,7 +168,7 @@ impl DefMapCrateData {
160168
fn_proc_macro_mapping:FxHashMap::default(),
161169
proc_macro_loading_error:None,
162170
registered_attrs:Vec::new(),
163-
registered_tools:Vec::new(),
171+
registered_tools:PREDEFINED_TOOLS.into(),
164172
unstable_features:FxHashSet::default(),
165173
rustc_coherence_is_core:false,
166174
no_core:false,

‎src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use syntax::{ast, SmolStr};
1010
use triomphe::Arc;
1111

1212
usecrate::{
13-
attr::builtin::{find_builtin_attr_idx,TOOL_MODULES},
13+
attr::builtin::find_builtin_attr_idx,
1414
db::DefDatabase,
1515
item_scope::BuiltinShadowMode,
1616
nameres::path_resolution::ResolveMode,
@@ -82,8 +82,7 @@ impl DefMap {
8282
let name = name.to_smol_str();
8383
let pred = |n:&_| *n == name;
8484

85-
let registered = self.data.registered_tools.iter().map(SmolStr::as_str);
86-
let is_tool = TOOL_MODULES.iter().copied().chain(registered).any(pred);
85+
let is_tool = self.data.registered_tools.iter().map(SmolStr::as_str).any(pred);
8786
// FIXME: tool modules can be shadowed by actual modules
8887
if is_tool {
8988
returntrue;

‎src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs‎

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -797,19 +797,22 @@ impl<'a> InferenceTable<'a> {
797797
})
798798
.build();
799799

800-
let projection = {
801-
let b = TyBuilder::subst_for_def(self.db, fn_once_trait,None);
802-
if b.remaining() != 2{
803-
returnNone;
804-
}
805-
let fn_once_subst = b.push(ty.clone()).push(arg_ty).build();
800+
let b = TyBuilder::trait_ref(self.db, fn_once_trait);
801+
if b.remaining() != 2{
802+
returnNone;
803+
}
804+
letmut trait_ref = b.push(ty.clone()).push(arg_ty).build();
806805

807-
TyBuilder::assoc_type_projection(self.db, output_assoc_type,Some(fn_once_subst))
808-
.build()
806+
let projection = {
807+
TyBuilder::assoc_type_projection(
808+
self.db,
809+
output_assoc_type,
810+
Some(trait_ref.substitution.clone()),
811+
)
812+
.build()
809813
};
810814

811815
let trait_env = self.trait_env.env.clone();
812-
letmut trait_ref = projection.trait_ref(self.db);
813816
let obligation = InEnvironment{
814817
goal: trait_ref.clone().cast(Interner),
815818
environment: trait_env.clone(),

‎src/tools/rust-analyzer/crates/hir-ty/src/lib.rs‎

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,10 @@ impl CallableSig {
570570
}
571571
}
572572

573+
pubfnabi(&self) -> FnAbi{
574+
self.abi
575+
}
576+
573577
pubfnparams(&self) -> &[Ty]{
574578
&self.params_and_return[0..self.params_and_return.len() - 1]
575579
}
@@ -892,20 +896,16 @@ where
892896
Canonical{ value,binders: chalk_ir::CanonicalVarKinds::from_iter(Interner, kinds)}
893897
}
894898

895-
pubfncallable_sig_from_fnonce(
896-
mutself_ty:&Ty,
897-
env:Arc<TraitEnvironment>,
899+
pubfncallable_sig_from_fn_trait(
900+
self_ty:&Ty,
901+
trait_env:Arc<TraitEnvironment>,
898902
db:&dynHirDatabase,
899-
) -> Option<CallableSig>{
900-
ifletSome((ty, _, _)) = self_ty.as_reference(){
901-
// This will happen when it implements fn or fn mut, since we add a autoborrow adjustment
902-
self_ty = ty;
903-
}
904-
let krate = env.krate;
903+
) -> Option<(FnTrait,CallableSig)>{
904+
let krate = trait_env.krate;
905905
let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?;
906906
let output_assoc_type = db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
907907

908-
letmut table = InferenceTable::new(db,env);
908+
letmut table = InferenceTable::new(db,trait_env.clone());
909909
let b = TyBuilder::trait_ref(db, fn_once_trait);
910910
if b.remaining() != 2{
911911
returnNone;
@@ -915,23 +915,56 @@ pub fn callable_sig_from_fnonce(
915915
// - Self: FnOnce<?args_ty>
916916
// - <Self as FnOnce<?args_ty>>::Output == ?ret_ty
917917
let args_ty = table.new_type_var();
918-
let trait_ref = b.push(self_ty.clone()).push(args_ty.clone()).build();
918+
letmuttrait_ref = b.push(self_ty.clone()).push(args_ty.clone()).build();
919919
let projection = TyBuilder::assoc_type_projection(
920920
db,
921921
output_assoc_type,
922922
Some(trait_ref.substitution.clone()),
923923
)
924924
.build();
925-
table.register_obligation(trait_ref.cast(Interner));
926-
let ret_ty = table.normalize_projection_ty(projection);
927-
928-
let ret_ty = table.resolve_completely(ret_ty);
929-
let args_ty = table.resolve_completely(args_ty);
930925

931-
let params =
932-
args_ty.as_tuple()?.iter(Interner).map(|it| it.assert_ty_ref(Interner)).cloned().collect();
933-
934-
Some(CallableSig::from_params_and_return(params, ret_ty,false,Safety::Safe,FnAbi::RustCall))
926+
let block = trait_env.block;
927+
let trait_env = trait_env.env.clone();
928+
let obligation =
929+
InEnvironment{goal: trait_ref.clone().cast(Interner),environment: trait_env.clone()};
930+
let canonical = table.canonicalize(obligation.clone());
931+
if db.trait_solve(krate, block, canonical.cast(Interner)).is_some(){
932+
table.register_obligation(obligation.goal);
933+
let return_ty = table.normalize_projection_ty(projection);
934+
for fn_x in[FnTrait::Fn,FnTrait::FnMut,FnTrait::FnOnce]{
935+
let fn_x_trait = fn_x.get_id(db, krate)?;
936+
trait_ref.trait_id = to_chalk_trait_id(fn_x_trait);
937+
let obligation: chalk_ir::InEnvironment<chalk_ir::Goal<Interner>> = InEnvironment{
938+
goal: trait_ref.clone().cast(Interner),
939+
environment: trait_env.clone(),
940+
};
941+
let canonical = table.canonicalize(obligation.clone());
942+
if db.trait_solve(krate, block, canonical.cast(Interner)).is_some(){
943+
let ret_ty = table.resolve_completely(return_ty);
944+
let args_ty = table.resolve_completely(args_ty);
945+
let params = args_ty
946+
.as_tuple()?
947+
.iter(Interner)
948+
.map(|it| it.assert_ty_ref(Interner))
949+
.cloned()
950+
.collect();
951+
952+
returnSome((
953+
fn_x,
954+
CallableSig::from_params_and_return(
955+
params,
956+
ret_ty,
957+
false,
958+
Safety::Safe,
959+
FnAbi::RustCall,
960+
),
961+
));
962+
}
963+
}
964+
unreachable!("It should at least implement FnOnce at this point");
965+
}else{
966+
None
967+
}
935968
}
936969

937970
structPlaceholderCollector<'db>{

‎src/tools/rust-analyzer/crates/hir-ty/src/traits.rs‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Trait solving using Chalk.
22
3+
use core::fmt;
34
use std::env::var;
45

56
use chalk_ir::{fold::TypeFoldable,DebruijnIndex,GoalData};
@@ -209,7 +210,25 @@ pub enum FnTrait {
209210
Fn,
210211
}
211212

213+
impl fmt::DisplayforFnTrait{
214+
fnfmt(&self,f:&mut fmt::Formatter<'_>) -> fmt::Result{
215+
matchself{
216+
FnTrait::FnOnce => write!(f,"FnOnce"),
217+
FnTrait::FnMut => write!(f,"FnMut"),
218+
FnTrait::Fn => write!(f,"Fn"),
219+
}
220+
}
221+
}
222+
212223
implFnTrait{
224+
pubconstfnfunction_name(&self) -> &'staticstr{
225+
matchself{
226+
FnTrait::FnOnce => "call_once",
227+
FnTrait::FnMut => "call_mut",
228+
FnTrait::Fn => "call",
229+
}
230+
}
231+
213232
constfnlang_item(self) -> LangItem{
214233
matchself{
215234
FnTrait::FnOnce => LangItem::FnOnce,

0 commit comments

Comments
 (0)