Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions crates/hir-def/src/path/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub(super) fn lower_path(ctx: &mut LowerCtx<'_>, mut path: ast::Path) -> Option<
.or_else(|| {
lower_generic_args_from_fn_path(
ctx,
segment.param_list(),
segment.parenthesized_arg_list(),
segment.ret_type(),
)
});
Expand Down Expand Up @@ -247,12 +247,12 @@ pub(super) fn lower_generic_args(
/// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`).
fn lower_generic_args_from_fn_path(
ctx: &mut LowerCtx<'_>,
params: Option<ast::ParamList>,
args: Option<ast::ParenthesizedArgList>,
ret_type: Option<ast::RetType>,
) -> Option<GenericArgs> {
let params = params?;
let params = args?;
let mut param_types = Vec::new();
for param in params.params() {
for param in params.type_args() {
let type_ref = TypeRef::from_ast_opt(ctx, param.ty());
param_types.push(type_ref);
}
Expand Down
3 changes: 2 additions & 1 deletion crates/ide-db/src/path_transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,8 @@ impl Ctx<'_> {
return None;
}
if path.segment().map_or(false, |s| {
s.param_list().is_some() || (s.self_token().is_some() && path.parent_path().is_none())
s.parenthesized_arg_list().is_some()
|| (s.self_token().is_some() && path.parent_path().is_none())
}) {
// don't try to qualify `Fn(Foo) -> Bar` paths, they are in prelude anyway
// don't try to qualify sole `self` either, they are usually locals, but are returned as modules due to namespace clashing
Expand Down
4 changes: 2 additions & 2 deletions crates/ide-ssr/src/matching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,8 +359,8 @@ impl<'db, 'sema> Matcher<'db, 'sema> {
)?;
self.attempt_match_opt(
phase,
pattern_segment.param_list(),
code_segment.param_list(),
pattern_segment.parenthesized_arg_list(),
code_segment.parenthesized_arg_list(),
)?;
}
if matches!(phase, Phase::Second(_)) {
Expand Down
94 changes: 51 additions & 43 deletions crates/ide/src/inlay_hints/lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,15 @@ pub(super) fn fn_hints(
fd,
config,
file_id,
param_list,
param_list.params().filter_map(|it| {
Some((
it.pat().and_then(|it| match it {
ast::Pat::IdentPat(p) => p.name(),
_ => None,
}),
it.ty()?,
))
}),
generic_param_list,
ret_type,
self_param,
Expand Down Expand Up @@ -90,7 +98,15 @@ pub(super) fn fn_ptr_hints(
fd,
config,
file_id,
param_list,
param_list.params().filter_map(|it| {
Some((
it.pat().and_then(|it| match it {
ast::Pat::IdentPat(p) => p.name(),
_ => None,
}),
it.ty()?,
))
}),
generic_param_list,
ret_type,
None,
Expand Down Expand Up @@ -148,7 +164,7 @@ pub(super) fn fn_path_hints(
fd,
config,
file_id,
param_list,
param_list.type_args().filter_map(|it| Some((None, it.ty()?))),
generic_param_list,
ret_type,
None,
Expand Down Expand Up @@ -177,8 +193,8 @@ pub(super) fn fn_path_hints(
)
}

fn path_as_fn(path: &ast::Path) -> Option<(ast::ParamList, Option<ast::RetType>)> {
path.segment().and_then(|it| it.param_list().zip(Some(it.ret_type())))
fn path_as_fn(path: &ast::Path) -> Option<(ast::ParenthesizedArgList, Option<ast::RetType>)> {
path.segment().and_then(|it| it.parenthesized_arg_list().zip(Some(it.ret_type())))
}

fn hints_(
Expand All @@ -187,7 +203,7 @@ fn hints_(
FamousDefs(_, _): &FamousDefs<'_, '_>,
config: &InlayHintsConfig,
_file_id: EditionedFileId,
param_list: ast::ParamList,
params: impl Iterator<Item = (Option<ast::Name>, ast::Type)>,
generic_param_list: Option<ast::GenericParamList>,
ret_type: Option<ast::RetType>,
self_param: Option<ast::SelfParam>,
Expand Down Expand Up @@ -217,45 +233,34 @@ fn hints_(
let is_elided = is_elided(&lifetime);
acc.push((None, self_param.amp_token(), lifetime, is_elided));
}
param_list
.params()
.filter_map(|it| {
Some((
it.pat().and_then(|it| match it {
ast::Pat::IdentPat(p) => p.name(),
_ => None,
}),
it.ty()?,
))
})
.for_each(|(name, ty)| {
// FIXME: check path types
walk_ty(&ty, &mut |ty| match ty {
ast::Type::RefType(r) => {
let lifetime = r.lifetime();
let is_elided = is_elided(&lifetime);
acc.push((name.clone(), r.amp_token(), lifetime, is_elided));
false
}
ast::Type::FnPtrType(_) => {
params.for_each(|(name, ty)| {
// FIXME: check path types
walk_ty(&ty, &mut |ty| match ty {
ast::Type::RefType(r) => {
let lifetime = r.lifetime();
let is_elided = is_elided(&lifetime);
acc.push((name.clone(), r.amp_token(), lifetime, is_elided));
false
}
ast::Type::FnPtrType(_) => {
is_trivial = false;
true
}
ast::Type::PathType(t) => {
if t.path()
.and_then(|it| it.segment())
.and_then(|it| it.parenthesized_arg_list())
.is_some()
{
is_trivial = false;
true
} else {
false
}
ast::Type::PathType(t) => {
if t.path()
.and_then(|it| it.segment())
.and_then(|it| it.param_list())
.is_some()
{
is_trivial = false;
true
} else {
false
}
}
_ => false,
})
});
}
_ => false,
})
});
acc
};

Expand Down Expand Up @@ -339,7 +344,10 @@ fn hints_(
true
}
ast::Type::PathType(t) => {
if t.path().and_then(|it| it.segment()).and_then(|it| it.param_list()).is_some()
if t.path()
.and_then(|it| it.segment())
.and_then(|it| it.parenthesized_arg_list())
.is_some()
{
is_trivial = false;
true
Expand Down
2 changes: 1 addition & 1 deletion crates/parser/src/grammar/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ fn method_call_expr<const FLOAT_RECOVERY: bool>(
p.bump(T![.]);
}
name_ref(p);
generic_args::opt_generic_arg_list(p, true);
generic_args::opt_generic_arg_list_expr(p);
if p.at(T!['(']) {
arg_list(p);
} else {
Expand Down
65 changes: 24 additions & 41 deletions crates/parser/src/grammar/generic_args.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
use super::*;

// test_err generic_arg_list_recover
// type T = T<0, ,T>;
pub(super) fn opt_generic_arg_list(p: &mut Parser<'_>, colon_colon_required: bool) {
// test_err generic_arg_list_recover_expr
// const _: () = T::<0, ,T>;
// const _: () = T::<0, ,T>();
pub(super) fn opt_generic_arg_list_expr(p: &mut Parser<'_>) {
let m;
if p.at(T![::]) && p.nth(2) == T![<] {
m = p.start();
p.bump(T![::]);
} else if !colon_colon_required && p.at(T![<]) && p.nth(1) != T![=] {
m = p.start();
} else {
return;
}
Expand All @@ -25,7 +24,7 @@ pub(super) fn opt_generic_arg_list(p: &mut Parser<'_>, colon_colon_required: boo
m.complete(p, GENERIC_ARG_LIST);
}

const GENERIC_ARG_FIRST: TokenSet = TokenSet::new(&[
pub(crate) const GENERIC_ARG_FIRST: TokenSet = TokenSet::new(&[
LIFETIME_IDENT,
IDENT,
T!['{'],
Expand All @@ -47,20 +46,23 @@ const GENERIC_ARG_RECOVERY_SET: TokenSet = TokenSet::new(&[T![>], T![,]]);

// test generic_arg
// type T = S<i32>;
fn generic_arg(p: &mut Parser<'_>) -> bool {
pub(crate) fn generic_arg(p: &mut Parser<'_>) -> bool {
match p.current() {
LIFETIME_IDENT if !p.nth_at(1, T![+]) => lifetime_arg(p),
T!['{'] | T![true] | T![false] | T![-] => const_arg(p),
k if k.is_literal() => const_arg(p),
// test associated_type_bounds
// fn print_all<T: Iterator<Item, Item::Item, Item::<true>, Item: Display, Item<'a> = Item>>(printables: T) {}
// test generic_arg_bounds
// type Plain = Foo<Item, Item::Item, Item: Bound, Item = Item>;
// type GenericArgs = Foo<Item<T>, Item::<T>, Item<T>: Bound, Item::<T>: Bound, Item<T> = Item, Item::<T> = Item>;
// type ParenthesizedArgs = Foo<Item(T), Item::(T), Item(T): Bound, Item::(T): Bound, Item(T) = Item, Item::(T) = Item>;
// type RTN = Foo<Item(..), Item(..), Item(..): Bound, Item(..): Bound, Item(..) = Item, Item(..) = Item>;

// test macro_inside_generic_arg
// type A = Foo<syn::Token![_]>;
IDENT if [T![<], T![=], T![:]].contains(&p.nth(1)) && !p.nth_at(1, T![::]) => {
IDENT => {
let m = p.start();
name_ref(p);
opt_generic_arg_list(p, false);
paths::opt_path_type_args(p);
match p.current() {
T![=] => {
p.bump_any();
Expand Down Expand Up @@ -88,45 +90,26 @@ fn generic_arg(p: &mut Parser<'_>) -> bool {
}
// test assoc_type_bound
// type T = StreamingIterator<Item<'a>: Clone>;
// type T = StreamingIterator<Item(T): Clone>;
T![:] if !p.at(T![::]) => {
generic_params::bounds(p);
m.complete(p, ASSOC_TYPE_ARG);
}
// Turned out to be just a normal path type (mirror `path_or_macro_type`)
_ => {
let m = m.complete(p, PATH_SEGMENT).precede(p).complete(p, PATH);
let m = paths::type_path_for_qualifier(p, m);
m.precede(p).complete(p, PATH_TYPE).precede(p).complete(p, TYPE_ARG);
let m = if p.at(T![!]) && !p.at(T![!=]) {
let m = m.precede(p);
items::macro_call_after_excl(p);
m.complete(p, MACRO_CALL).precede(p).complete(p, MACRO_TYPE)
} else {
m.precede(p).complete(p, PATH_TYPE)
};
types::opt_type_bounds_as_dyn_trait_type(p, m).precede(p).complete(p, TYPE_ARG);
}
}
}
IDENT if p.nth_at(1, T!['(']) => {
let m = p.start();
name_ref(p);
if p.nth_at(1, T![..]) {
let rtn = p.start();
p.bump(T!['(']);
p.bump(T![..]);
p.expect(T![')']);
rtn.complete(p, RETURN_TYPE_SYNTAX);
// test return_type_syntax_assoc_type_bound
// fn foo<T: Trait<method(..): Send>>() {}
generic_params::bounds(p);
m.complete(p, ASSOC_TYPE_ARG);
} else {
params::param_list_fn_trait(p);
// test bare_dyn_types_with_paren_as_generic_args
// type A = S<Fn(i32)>;
// type A = S<Fn(i32) + Send>;
// type B = S<Fn(i32) -> i32>;
// type C = S<Fn(i32) -> i32 + Send>;
opt_ret_type(p);
let m = m.complete(p, PATH_SEGMENT).precede(p).complete(p, PATH);
let m = paths::type_path_for_qualifier(p, m);
let m = m.precede(p).complete(p, PATH_TYPE);
let m = types::opt_type_bounds_as_dyn_trait_type(p, m);
m.precede(p).complete(p, TYPE_ARG);
}
}
_ if p.at_ts(types::TYPE_FIRST) => type_arg(p),
_ => return false,
}
Expand Down Expand Up @@ -190,7 +173,7 @@ pub(super) fn const_arg(p: &mut Parser<'_>) {
m.complete(p, CONST_ARG);
}

fn type_arg(p: &mut Parser<'_>) {
pub(crate) fn type_arg(p: &mut Parser<'_>) {
let m = p.start();
types::type_(p);
m.complete(p, TYPE_ARG);
Expand Down
18 changes: 3 additions & 15 deletions crates/parser/src/grammar/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@ pub(super) fn param_list_fn_def(p: &mut Parser<'_>) {
list_(p, Flavor::FnDef);
}

// test param_list_opt_patterns
// fn foo<F: FnMut(&mut Foo<'a>)>(){}
pub(super) fn param_list_fn_trait(p: &mut Parser<'_>) {
list_(p, Flavor::FnTrait);
}

pub(super) fn param_list_fn_ptr(p: &mut Parser<'_>) {
list_(p, Flavor::FnPointer);
}
Expand All @@ -28,10 +22,9 @@ pub(super) fn param_list_closure(p: &mut Parser<'_>) {
list_(p, Flavor::Closure);
}

#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Flavor {
FnDef, // Includes trait fn params; omitted param idents are not supported
FnTrait, // Params for `Fn(...)`/`FnMut(...)`/`FnOnce(...)` annotations
FnDef, // Includes trait fn params; omitted param idents are not supported
FnPointer,
Closure,
}
Expand All @@ -41,7 +34,7 @@ fn list_(p: &mut Parser<'_>, flavor: Flavor) {

let (bra, ket) = match flavor {
Closure => (T![|], T![|]),
FnDef | FnTrait | FnPointer => (T!['('], T![')']),
FnDef | FnPointer => (T!['('], T![')']),
};

let list_marker = p.start();
Expand Down Expand Up @@ -119,11 +112,6 @@ fn param(p: &mut Parser<'_>, m: Marker, flavor: Flavor) {
}
}
}
// test value_parameters_no_patterns
// type F = Box<Fn(i32, &i32, &i32, ())>;
Flavor::FnTrait => {
types::type_(p);
}
// test fn_pointer_param_ident_path
// type Foo = fn(Bar::Baz);
// type Qux = fn(baz: Bar::Baz);
Expand Down
Loading
Loading