Parse associated return type bounds

This commit is contained in:
Ryo Yoshida 2023-05-06 20:29:13 +09:00
parent d7d8971203
commit fa2340a4df
No known key found for this signature in database
GPG key ID: E25698A930586171
12 changed files with 361 additions and 5 deletions

View file

@ -189,6 +189,10 @@ pub(super) fn lower_generic_args(
args.push(GenericArg::Type(type_ref));
}
ast::GenericArg::AssocTypeArg(assoc_type_arg) => {
if assoc_type_arg.param_list().is_some() {
// We currently ignore associated return type bounds.
continue;
}
if let Some(name_ref) = assoc_type_arg.name_ref() {
let name = name_ref.as_name();
let args = assoc_type_arg

View file

@ -76,6 +76,29 @@ fn generic_arg(p: &mut Parser<'_>) -> bool {
}
}
}
IDENT if p.nth_at(1, T!['(']) => {
let m = p.start();
name_ref(p);
params::param_list_fn_trait(p);
if p.at(T![:]) && !p.at(T![::]) {
// test associated_return_type_bounds
// fn foo<T: Foo<foo(): Send, bar(i32): Send, baz(i32, i32): Send>>() {}
generic_params::bounds(p);
m.complete(p, ASSOC_TYPE_ARG);
} else {
// 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,
}

View file

@ -136,6 +136,7 @@ fn opt_path_type_args(p: &mut Parser<'_>, mode: Mode) {
Mode::Type => {
// test typepathfn_with_coloncolon
// type F = Start::(Middle) -> (Middle)::End;
// type GenericArg = S<Start(Middle)::End>;
if p.at(T![::]) && p.nth_at(2, T!['(']) {
p.bump(T![::]);
}

View file

@ -337,13 +337,16 @@ pub(super) fn path_type_(p: &mut Parser<'_>, allow_bounds: bool) {
/// This turns a parsed PATH_TYPE or FOR_TYPE optionally into a DYN_TRAIT_TYPE
/// with a TYPE_BOUND_LIST
fn opt_type_bounds_as_dyn_trait_type(p: &mut Parser<'_>, type_marker: CompletedMarker) {
pub(super) fn opt_type_bounds_as_dyn_trait_type(
p: &mut Parser<'_>,
type_marker: CompletedMarker,
) -> CompletedMarker {
assert!(matches!(
type_marker.kind(),
SyntaxKind::PATH_TYPE | SyntaxKind::FOR_TYPE | SyntaxKind::MACRO_TYPE
));
if !p.at(T![+]) {
return;
return type_marker;
}
// First create a TYPE_BOUND from the completed PATH_TYPE
@ -360,5 +363,5 @@ fn opt_type_bounds_as_dyn_trait_type(p: &mut Parser<'_>, type_marker: CompletedM
let m = generic_params::bounds_without_colon_m(p, m);
// Finally precede everything with DYN_TRAIT_TYPE
m.precede(p).complete(p, DYN_TRAIT_TYPE);
m.precede(p).complete(p, DYN_TRAIT_TYPE)
}

View file

@ -41,3 +41,41 @@ SOURCE_FILE
IDENT "End"
SEMICOLON ";"
WHITESPACE "\n"
TYPE_ALIAS
TYPE_KW "type"
WHITESPACE " "
NAME
IDENT "GenericArg"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "S"
GENERIC_ARG_LIST
L_ANGLE "<"
TYPE_ARG
PATH_TYPE
PATH
PATH
PATH_SEGMENT
NAME_REF
IDENT "Start"
PARAM_LIST
L_PAREN "("
PARAM
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Middle"
R_PAREN ")"
COLON2 "::"
PATH_SEGMENT
NAME_REF
IDENT "End"
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"

View file

@ -1 +1,2 @@
type F = Start::(Middle) -> (Middle)::End;
type GenericArg = S<Start(Middle)::End>;

View file

@ -0,0 +1,102 @@
SOURCE_FILE
FN
FN_KW "fn"
WHITESPACE " "
NAME
IDENT "foo"
GENERIC_PARAM_LIST
L_ANGLE "<"
TYPE_PARAM
NAME
IDENT "T"
COLON ":"
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Foo"
GENERIC_ARG_LIST
L_ANGLE "<"
ASSOC_TYPE_ARG
NAME_REF
IDENT "foo"
PARAM_LIST
L_PAREN "("
R_PAREN ")"
COLON ":"
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Send"
COMMA ","
WHITESPACE " "
ASSOC_TYPE_ARG
NAME_REF
IDENT "bar"
PARAM_LIST
L_PAREN "("
PARAM
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "i32"
R_PAREN ")"
COLON ":"
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Send"
COMMA ","
WHITESPACE " "
ASSOC_TYPE_ARG
NAME_REF
IDENT "baz"
PARAM_LIST
L_PAREN "("
PARAM
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "i32"
COMMA ","
WHITESPACE " "
PARAM
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "i32"
R_PAREN ")"
COLON ":"
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Send"
R_ANGLE ">"
R_ANGLE ">"
PARAM_LIST
L_PAREN "("
R_PAREN ")"
WHITESPACE " "
BLOCK_EXPR
STMT_LIST
L_CURLY "{"
R_CURLY "}"
WHITESPACE "\n"

View file

@ -0,0 +1 @@
fn foo<T: Foo<foo(): Send, bar(i32): Send, baz(i32, i32): Send>>() {}

View file

@ -0,0 +1,175 @@
SOURCE_FILE
TYPE_ALIAS
TYPE_KW "type"
WHITESPACE " "
NAME
IDENT "A"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "S"
GENERIC_ARG_LIST
L_ANGLE "<"
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Fn"
PARAM_LIST
L_PAREN "("
PARAM
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "i32"
R_PAREN ")"
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"
TYPE_ALIAS
TYPE_KW "type"
WHITESPACE " "
NAME
IDENT "A"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "S"
GENERIC_ARG_LIST
L_ANGLE "<"
TYPE_ARG
DYN_TRAIT_TYPE
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Fn"
PARAM_LIST
L_PAREN "("
PARAM
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "i32"
R_PAREN ")"
WHITESPACE " "
PLUS "+"
WHITESPACE " "
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Send"
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"
TYPE_ALIAS
TYPE_KW "type"
WHITESPACE " "
NAME
IDENT "B"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "S"
GENERIC_ARG_LIST
L_ANGLE "<"
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Fn"
PARAM_LIST
L_PAREN "("
PARAM
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "i32"
R_PAREN ")"
WHITESPACE " "
RET_TYPE
THIN_ARROW "->"
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "i32"
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"
TYPE_ALIAS
TYPE_KW "type"
WHITESPACE " "
NAME
IDENT "C"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "S"
GENERIC_ARG_LIST
L_ANGLE "<"
TYPE_ARG
DYN_TRAIT_TYPE
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Fn"
PARAM_LIST
L_PAREN "("
PARAM
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "i32"
R_PAREN ")"
WHITESPACE " "
RET_TYPE
THIN_ARROW "->"
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "i32"
WHITESPACE " "
PLUS "+"
WHITESPACE " "
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Send"
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"

View file

@ -0,0 +1,4 @@
type A = S<Fn(i32)>;
type A = S<Fn(i32) + Send>;
type B = S<Fn(i32) -> i32>;
type C = S<Fn(i32) -> i32 + Send>;

View file

@ -51,7 +51,9 @@ TypeArg =
Type
AssocTypeArg =
NameRef GenericArgList? (':' TypeBoundList | ('=' Type | ConstArg))
NameRef
(GenericArgList | ParamList RetType?)?
(':' TypeBoundList | ('=' Type | ConstArg))
LifetimeArg =
Lifetime
@ -581,7 +583,7 @@ ImplTraitType =
'impl' TypeBoundList
DynTraitType =
'dyn' TypeBoundList
'dyn'? TypeBoundList
TypeBoundList =
bounds:(TypeBound ('+' TypeBound)* '+'?)

View file

@ -121,6 +121,8 @@ impl ast::HasTypeBounds for AssocTypeArg {}
impl AssocTypeArg {
pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) }
pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
pub fn const_arg(&self) -> Option<ConstArg> { support::child(&self.syntax) }