Skip to content

Commit 7045044

Browse files
committed
Allow hir::Param to refer to other entity params aside from functions
1 parent 9ff4ffb commit 7045044

9 files changed

Lines changed: 114 additions & 118 deletions

File tree

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

Lines changed: 62 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ pub mod term_search;
3535

3636
mod display;
3737

38-
use std::{iter,mem::discriminant, ops::ControlFlow};
38+
use std::{mem::discriminant, ops::ControlFlow};
3939

4040
use arrayvec::ArrayVec;
4141
use base_db::{CrateDisplayName,CrateId,CrateOrigin,FileId};
@@ -52,7 +52,6 @@ use hir_def::{
5252
path::ImportAlias,
5353
per_ns::PerNs,
5454
resolver::{HasResolver,Resolver},
55-
src::HasSourceas _,
5655
AssocItemId,AssocItemLoc,AttrDefId,ConstId,ConstParamId,CrateRootModuleId,DefWithBodyId,
5756
EnumId,EnumVariantId,ExternCrateId,FunctionId,GenericDefId,GenericParamId,HasModule,
5857
ImplId,InTypeConstId,ItemContainerId,LifetimeParamId,LocalFieldId,Lookup,MacroExpander,
@@ -1965,7 +1964,7 @@ impl Function {
19651964
.enumerate()
19661965
.map(|(idx, ty)| {
19671966
let ty = Type{env: environment.clone(),ty: ty.clone()};
1968-
Param{func:self, ty, idx }
1967+
Param{func:Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx }
19691968
})
19701969
.collect()
19711970
}
@@ -1991,7 +1990,7 @@ impl Function {
19911990
.skip(skip)
19921991
.map(|(idx, ty)| {
19931992
let ty = Type{env: environment.clone(),ty: ty.clone()};
1994-
Param{func:self, ty, idx }
1993+
Param{func:Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx }
19951994
})
19961995
.collect()
19971996
}
@@ -2037,7 +2036,7 @@ impl Function {
20372036
.skip(skip)
20382037
.map(|(idx, ty)| {
20392038
let ty = Type{env: environment.clone(),ty: ty.clone()};
2040-
Param{func:self, ty, idx }
2039+
Param{func:Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx }
20412040
})
20422041
.collect()
20432042
}
@@ -2167,17 +2166,24 @@ impl From<hir_ty::Mutability> for Access {
21672166

21682167
#[derive(Clone,PartialEq,Eq,Hash,Debug)]
21692168
pubstructParam{
2170-
func:Function,
2169+
func:Callee,
21712170
/// The index in parameter list, including self parameter.
21722171
idx:usize,
21732172
ty:Type,
21742173
}
21752174

21762175
implParam{
2177-
pubfnparent_fn(&self) -> Function{
2178-
self.func
2176+
pubfnparent_fn(&self) -> Option<Function>{
2177+
matchself.func{
2178+
Callee::Def(CallableDefId::FunctionId(f)) => Some(f.into()),
2179+
_ => None,
2180+
}
21792181
}
21802182

2183+
// pub fn parent_closure(&self) -> Option<Closure> {
2184+
// self.func.as_ref().right().cloned()
2185+
// }
2186+
21812187
pubfnindex(&self) -> usize{
21822188
self.idx
21832189
}
@@ -2191,7 +2197,11 @@ impl Param {
21912197
}
21922198

21932199
pubfnas_local(&self,db:&dynHirDatabase) -> Option<Local>{
2194-
let parent = DefWithBodyId::FunctionId(self.func.into());
2200+
let parent = matchself.func{
2201+
Callee::Def(CallableDefId::FunctionId(it)) => DefWithBodyId::FunctionId(it),
2202+
Callee::Closure(closure) => db.lookup_intern_closure(closure.into()).0,
2203+
_ => returnNone,
2204+
};
21952205
let body = db.body(parent);
21962206
ifletSome(self_param) = body.self_param.filter(|_| self.idx == 0){
21972207
Some(Local{ parent,binding_id: self_param })
@@ -2205,18 +2215,45 @@ impl Param {
22052215
}
22062216

22072217
pubfnpattern_source(&self,db:&dynHirDatabase) -> Option<ast::Pat>{
2208-
self.source(db).and_then(|p| p.value.pat())
2218+
self.source(db).and_then(|p| p.value.right()?.pat())
22092219
}
22102220

2211-
pubfnsource(&self,db:&dynHirDatabase) -> Option<InFile<ast::Param>>{
2212-
letInFile{ file_id, value } = self.func.source(db)?;
2213-
let params = value.param_list()?;
2214-
if params.self_param().is_some(){
2215-
params.params().nth(self.idx.checked_sub(params.self_param().is_some()asusize)?)
2216-
}else{
2217-
params.params().nth(self.idx)
2221+
pubfnsource(
2222+
&self,
2223+
db:&dynHirDatabase,
2224+
) -> Option<InFile<Either<ast::SelfParam, ast::Param>>>{
2225+
matchself.func{
2226+
Callee::Def(CallableDefId::FunctionId(func)) => {
2227+
letInFile{ file_id, value } = Function{id: func }.source(db)?;
2228+
let params = value.param_list()?;
2229+
ifletSome(self_param) = params.self_param(){
2230+
ifletSome(idx) = self.idx.checked_sub(1asusize){
2231+
params.params().nth(idx).map(Either::Right)
2232+
}else{
2233+
Some(Either::Left(self_param))
2234+
}
2235+
}else{
2236+
params.params().nth(self.idx).map(Either::Right)
2237+
}
2238+
.map(|value| InFile{ file_id, value })
2239+
}
2240+
Callee::Closure(closure) => {
2241+
letInternedClosure(owner, expr_id) = db.lookup_intern_closure(closure.into());
2242+
let(_, source_map) = db.body_with_source_map(owner);
2243+
let ast @ InFile{ file_id, value } = source_map.expr_syntax(expr_id).ok()?;
2244+
let root = db.parse_or_expand(file_id);
2245+
match value.to_node(&root){
2246+
ast::Expr::ClosureExpr(it) => it
2247+
.param_list()?
2248+
.params()
2249+
.nth(self.idx)
2250+
.map(Either::Right)
2251+
.map(|value| InFile{file_id: ast.file_id, value }),
2252+
_ => None,
2253+
}
2254+
}
2255+
_ => None,
22182256
}
2219-
.map(|value| InFile{ file_id, value })
22202257
}
22212258
}
22222259

@@ -4919,7 +4956,7 @@ pub struct Callable {
49194956
pub(crate)is_bound_method:bool,
49204957
}
49214958

4922-
#[derive(Debug)]
4959+
#[derive(Copy,Clone,PartialEq,Eq,Hash,Debug)]
49234960
enumCallee{
49244961
Def(CallableDefId),
49254962
Closure(ClosureId),
@@ -4960,43 +4997,15 @@ impl Callable {
49604997
pubfnn_params(&self) -> usize{
49614998
self.sig.params().len() - ifself.is_bound_method{1}else{0}
49624999
}
4963-
pubfnparams(
4964-
&self,
4965-
db:&dynHirDatabase,
4966-
) -> Vec<(Option<Either<ast::SelfParam, ast::Pat>>,Type)>{
4967-
let types = self
4968-
.sig
5000+
pubfnparams(&self) -> Vec<Param>{
5001+
self.sig
49695002
.params()
49705003
.iter()
5004+
.enumerate()
49715005
.skip(ifself.is_bound_method{1}else{0})
4972-
.map(|ty| self.ty.derived(ty.clone()));
4973-
let map_param = |it: ast::Param| it.pat().map(Either::Right);
4974-
let patterns = matchself.callee{
4975-
Callee::Def(CallableDefId::FunctionId(func)) => {
4976-
let src = func.lookup(db.upcast()).source(db.upcast());
4977-
src.value.param_list().map(|param_list| {
4978-
param_list
4979-
.self_param()
4980-
.map(|it| Some(Either::Left(it)))
4981-
.filter(|_| !self.is_bound_method)
4982-
.into_iter()
4983-
.chain(param_list.params().map(map_param))
4984-
})
4985-
}
4986-
Callee::Closure(closure_id) => matchclosure_source(db, closure_id){
4987-
Some(src) => src.param_list().map(|param_list| {
4988-
param_list
4989-
.self_param()
4990-
.map(|it| Some(Either::Left(it)))
4991-
.filter(|_| !self.is_bound_method)
4992-
.into_iter()
4993-
.chain(param_list.params().map(map_param))
4994-
}),
4995-
None => None,
4996-
},
4997-
_ => None,
4998-
};
4999-
patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect()
5006+
.map(|(idx, ty)| (idx,self.ty.derived(ty.clone())))
5007+
.map(|(idx, ty)| Param{func:self.callee, idx, ty })
5008+
.collect()
50005009
}
50015010
pubfnreturn_type(&self) -> Type{
50025011
self.ty.derived(self.sig.ret().clone())
@@ -5006,18 +5015,6 @@ impl Callable {
50065015
}
50075016
}
50085017

5009-
fnclosure_source(db:&dynHirDatabase,closure:ClosureId) -> Option<ast::ClosureExpr>{
5010-
letInternedClosure(owner, expr_id) = db.lookup_intern_closure(closure.into());
5011-
let(_, source_map) = db.body_with_source_map(owner);
5012-
let ast = source_map.expr_syntax(expr_id).ok()?;
5013-
let root = ast.file_syntax(db.upcast());
5014-
let expr = ast.value.to_node(&root);
5015-
match expr {
5016-
ast::Expr::ClosureExpr(it) => Some(it),
5017-
_ => None,
5018-
}
5019-
}
5020-
50215018
#[derive(Clone,Debug,Eq,PartialEq)]
50225019
pubstructLayout(Arc<TyLayout>,Arc<TargetDataLayout>);
50235020

‎src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,10 @@ pub(crate) fn replace_with_eager_method(acc: &mut Assists, ctx: &AssistContext<'
114114
let callable = ctx.sema.resolve_method_call_as_callable(&call)?;
115115
let(_, receiver_ty) = callable.receiver_param(ctx.sema.db)?;
116116
let n_params = callable.n_params() + 1;
117-
let params = callable.params(ctx.sema.db);
117+
let params = callable.params();
118118

119119
// FIXME: Check that the arg is of the form `() -> T`
120-
if !params.first()?.1.impls_fnonce(ctx.sema.db){
120+
if !params.first()?.ty().impls_fnonce(ctx.sema.db){
121121
returnNone;
122122
}
123123

‎src/tools/rust-analyzer/crates/ide-assists/src/utils/suggest_name.rs‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -253,11 +253,8 @@ fn from_param(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option<St
253253
};
254254

255255
let(idx, _) = arg_list.args().find_position(|it| it == expr).unwrap();
256-
let(pat, _) = func.params(sema.db).into_iter().nth(idx)?;
257-
let pat = match pat? {
258-
either::Either::Right(pat) => pat,
259-
_ => returnNone,
260-
};
256+
let param = func.params().into_iter().nth(idx)?;
257+
let pat = param.source(sema.db)?.value.right()?.pat()?;
261258
let name = var_name_from_pat(&pat)?;
262259
normalize(&name.to_string())
263260
}

‎src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! This module provides functionality for querying callable information about a token.
22
33
use either::Either;
4-
use hir::{Semantics,Type};
4+
use hir::{InFile,Semantics,Type};
55
use parser::T;
66
use syntax::{
77
ast::{self,HasArgList,HasName},
@@ -13,7 +13,7 @@ use crate::RootDatabase;
1313
#[derive(Debug)]
1414
pubstructActiveParameter{
1515
pubty:Type,
16-
pubpat:Option<Either<ast::SelfParam, ast::Pat>>,
16+
pubsrc:Option<InFile<Either<ast::SelfParam, ast::Param>>>,
1717
}
1818

1919
implActiveParameter{
@@ -22,18 +22,18 @@ impl ActiveParameter {
2222
let(signature, active_parameter) = callable_for_token(sema, token)?;
2323

2424
let idx = active_parameter?;
25-
letmut params = signature.params(sema.db);
25+
letmut params = signature.params();
2626
if idx >= params.len(){
2727
cov_mark::hit!(too_many_arguments);
2828
returnNone;
2929
}
30-
let(pat, ty) = params.swap_remove(idx);
31-
Some(ActiveParameter{ ty, pat})
30+
letparam = params.swap_remove(idx);
31+
Some(ActiveParameter{ty: param.ty().clone(),src: param.source(sema.db)})
3232
}
3333

3434
pubfnident(&self) -> Option<ast::Name>{
35-
self.pat.as_ref().and_then(|param| match param {
36-
Either::Right(ast::Pat::IdentPat(ident)) => ident.name(),
35+
self.src.as_ref().and_then(|param| match param.value.as_ref().right()?.pat()?{
36+
ast::Pat::IdentPat(ident) => ident.name(),
3737
_ => None,
3838
})
3939
}

‎src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ pub enum FormatSpecifier {
4141
Escape,
4242
}
4343

44+
// FIXME: Remove this, we can use rustc_format_parse instead
4445
pubfnlex_format_specifiers(
4546
string:&ast::String,
4647
mutcallback:&mutdynFnMut(TextRange,FormatSpecifier),

‎src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@ pub(super) fn hints(
2424

2525
let(callable, arg_list) = get_callable(sema,&expr)?;
2626
let hints = callable
27-
.params(sema.db)
27+
.params()
2828
.into_iter()
2929
.zip(arg_list.args())
30-
.filter_map(|((param, _ty), arg)| {
30+
.filter_map(|(p, arg)| {
3131
// Only annotate hints for expressions that exist in the original file
3232
let range = sema.original_range_opt(arg.syntax())?;
33-
let(param_name, name_syntax) = matchparam.as_ref()?{
33+
let(param_name, name_syntax) = matchp.source(sema.db)?.value.as_ref(){
3434
Either::Left(pat) => (pat.name()?, pat.name()),
35-
Either::Right(pat) => match pat {
35+
Either::Right(param) => matchparam.pat()?{
3636
ast::Pat::IdentPat(it) => (it.name()?, it.name()),
3737
_ => returnNone,
3838
},

‎src/tools/rust-analyzer/crates/ide/src/signature_help.rs‎

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -210,22 +210,25 @@ fn signature_help_for_call(
210210
format_to!(res.signature,"{}", self_param.display(db))
211211
}
212212
letmut buf = String::new();
213-
for(idx,(pat, ty))in callable.params(db).into_iter().enumerate(){
213+
for(idx,p)in callable.params().into_iter().enumerate(){
214214
buf.clear();
215-
ifletSome(pat) = pat {
216-
match pat {
217-
Either::Left(_self) => format_to!(buf,"self: "),
218-
Either::Right(pat) => format_to!(buf,"{}: ", pat),
215+
ifletSome(param) = p.source(sema.db){
216+
match param.value{
217+
Either::Right(param) => match param.pat(){
218+
Some(pat) => format_to!(buf,"{}: ", pat),
219+
None => format_to!(buf,"?: "),
220+
},
221+
Either::Left(_) => format_to!(buf,"self: "),
219222
}
220223
}
221224
// APITs (argument position `impl Trait`s) are inferred as {unknown} as the user is
222225
// in the middle of entering call arguments.
223226
// In that case, fall back to render definitions of the respective parameters.
224227
// This is overly conservative: we do not substitute known type vars
225228
// (see FIXME in tests::impl_trait) and falling back on any unknowns.
226-
match(ty.contains_unknown(), fn_params.as_deref()){
229+
match(p.ty().contains_unknown(), fn_params.as_deref()){
227230
(true,Some(fn_params)) => format_to!(buf,"{}", fn_params[idx].ty().display(db)),
228-
_ => format_to!(buf,"{}",ty.display(db)),
231+
_ => format_to!(buf,"{}",p.ty().display(db)),
229232
}
230233
res.push_call_param(&buf);
231234
}

0 commit comments

Comments
 (0)