Merge pull request #20281 from ChayimFriedman2/parse-hrtb-const
Some checks are pending
metrics / other_metrics (ripgrep-13.0.0) (push) Blocked by required conditions
metrics / other_metrics (self) (push) Blocked by required conditions
metrics / build_metrics (push) Waiting to run
metrics / other_metrics (diesel-1.4.8) (push) Blocked by required conditions
metrics / other_metrics (hyper-0.14.18) (push) Blocked by required conditions
metrics / other_metrics (webrender-2022) (push) Blocked by required conditions
metrics / generate_final_metrics (push) Blocked by required conditions
rustdoc / rustdoc (push) Waiting to run

fix: Parse `for<'a> [const]`
This commit is contained in:
Shoyu Vanilla (Flint) 2025-07-23 01:50:16 +00:00 committed by GitHub
commit fa64d3b720
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 465 additions and 354 deletions

View file

@ -101,7 +101,7 @@ WhereClause =
'where' predicates:(WherePred (',' WherePred)* ','?)
WherePred =
('for' GenericParamList)? (Lifetime | Type) ':' TypeBoundList?
ForBinder? (Lifetime | Type) ':' TypeBoundList?
//*************************//
@ -534,10 +534,10 @@ FieldExpr =
Attr* Expr '.' NameRef
ClosureExpr =
Attr* ClosureBinder? 'const'? 'static'? 'async'? 'gen'? 'move'? ParamList RetType?
Attr* ForBinder? 'const'? 'static'? 'async'? 'gen'? 'move'? ParamList RetType?
body:Expr
ClosureBinder =
ForBinder =
'for' GenericParamList
IfExpr =
@ -658,7 +658,7 @@ FnPtrType =
'const'? 'async'? 'unsafe'? Abi? 'fn' ParamList RetType?
ForType =
'for' GenericParamList Type
ForBinder Type
ImplTraitType =
'impl' TypeBoundList
@ -671,7 +671,7 @@ TypeBoundList =
TypeBound =
Lifetime
| ('~' 'const' | '[' 'const' ']' | 'const')? 'async'? '?'? Type
| ForBinder? ('~' 'const' | '[' 'const' ']' | 'const')? 'async'? '?'? Type
| 'use' UseBoundGenericArgs
UseBoundGenericArgs =

View file

@ -393,8 +393,7 @@ where
let pred = predicates.next().unwrap();
let mut bounds = pred.type_bound_list().unwrap().bounds();
assert!(pred.for_token().is_none());
assert!(pred.generic_param_list().is_none());
assert!(pred.for_binder().is_none());
assert_eq!("T", pred.ty().unwrap().syntax().text().to_string());
assert_bound("Clone", bounds.next());
assert_bound("Copy", bounds.next());
@ -432,8 +431,10 @@ where
let pred = predicates.next().unwrap();
let mut bounds = pred.type_bound_list().unwrap().bounds();
assert!(pred.for_token().is_some());
assert_eq!("<'a>", pred.generic_param_list().unwrap().syntax().text().to_string());
assert_eq!(
"<'a>",
pred.for_binder().unwrap().generic_param_list().unwrap().syntax().text().to_string()
);
assert_eq!("F", pred.ty().unwrap().syntax().text().to_string());
assert_bound("Fn(&'a str)", bounds.next());
}

View file

@ -377,22 +377,13 @@ impl CastExpr {
#[inline]
pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
}
pub struct ClosureBinder {
pub(crate) syntax: SyntaxNode,
}
impl ClosureBinder {
#[inline]
pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
#[inline]
pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
}
pub struct ClosureExpr {
pub(crate) syntax: SyntaxNode,
}
impl ast::HasAttrs for ClosureExpr {}
impl ClosureExpr {
#[inline]
pub fn closure_binder(&self) -> Option<ClosureBinder> { support::child(&self.syntax) }
pub fn for_binder(&self) -> Option<ForBinder> { support::child(&self.syntax) }
#[inline]
pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
#[inline]
@ -615,6 +606,15 @@ impl FnPtrType {
#[inline]
pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
}
pub struct ForBinder {
pub(crate) syntax: SyntaxNode,
}
impl ForBinder {
#[inline]
pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
#[inline]
pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
}
pub struct ForExpr {
pub(crate) syntax: SyntaxNode,
}
@ -632,11 +632,9 @@ pub struct ForType {
}
impl ForType {
#[inline]
pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
pub fn for_binder(&self) -> Option<ForBinder> { support::child(&self.syntax) }
#[inline]
pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
#[inline]
pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
}
pub struct FormatArgsArg {
pub(crate) syntax: SyntaxNode,
@ -1765,6 +1763,8 @@ pub struct TypeBound {
pub(crate) syntax: SyntaxNode,
}
impl TypeBound {
#[inline]
pub fn for_binder(&self) -> Option<ForBinder> { support::child(&self.syntax) }
#[inline]
pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
#[inline]
@ -1938,13 +1938,11 @@ pub struct WherePred {
impl ast::HasTypeBounds for WherePred {}
impl WherePred {
#[inline]
pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
pub fn for_binder(&self) -> Option<ForBinder> { support::child(&self.syntax) }
#[inline]
pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
#[inline]
pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
#[inline]
pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
}
pub struct WhileExpr {
pub(crate) syntax: SyntaxNode,
@ -3239,42 +3237,6 @@ impl fmt::Debug for CastExpr {
f.debug_struct("CastExpr").field("syntax", &self.syntax).finish()
}
}
impl AstNode for ClosureBinder {
#[inline]
fn kind() -> SyntaxKind
where
Self: Sized,
{
CLOSURE_BINDER
}
#[inline]
fn can_cast(kind: SyntaxKind) -> bool { kind == CLOSURE_BINDER }
#[inline]
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
#[inline]
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl hash::Hash for ClosureBinder {
fn hash<H: hash::Hasher>(&self, state: &mut H) { self.syntax.hash(state); }
}
impl Eq for ClosureBinder {}
impl PartialEq for ClosureBinder {
fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax }
}
impl Clone for ClosureBinder {
fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } }
}
impl fmt::Debug for ClosureBinder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ClosureBinder").field("syntax", &self.syntax).finish()
}
}
impl AstNode for ClosureExpr {
#[inline]
fn kind() -> SyntaxKind
@ -3815,6 +3777,42 @@ impl fmt::Debug for FnPtrType {
f.debug_struct("FnPtrType").field("syntax", &self.syntax).finish()
}
}
impl AstNode for ForBinder {
#[inline]
fn kind() -> SyntaxKind
where
Self: Sized,
{
FOR_BINDER
}
#[inline]
fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_BINDER }
#[inline]
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
#[inline]
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl hash::Hash for ForBinder {
fn hash<H: hash::Hasher>(&self, state: &mut H) { self.syntax.hash(state); }
}
impl Eq for ForBinder {}
impl PartialEq for ForBinder {
fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax }
}
impl Clone for ForBinder {
fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } }
}
impl fmt::Debug for ForBinder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ForBinder").field("syntax", &self.syntax).finish()
}
}
impl AstNode for ForExpr {
#[inline]
fn kind() -> SyntaxKind
@ -10146,11 +10144,6 @@ impl std::fmt::Display for CastExpr {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for ClosureBinder {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for ClosureExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
@ -10226,6 +10219,11 @@ impl std::fmt::Display for FnPtrType {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for ForBinder {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for ForExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)

View file

@ -805,9 +805,7 @@ impl ast::SelfParam {
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum TypeBoundKind {
/// Trait
PathType(ast::PathType),
/// for<'a> ...
ForType(ast::ForType),
PathType(Option<ast::ForBinder>, ast::PathType),
/// use
Use(ast::UseBoundGenericArgs),
/// 'a
@ -817,9 +815,7 @@ pub enum TypeBoundKind {
impl ast::TypeBound {
pub fn kind(&self) -> TypeBoundKind {
if let Some(path_type) = support::children(self.syntax()).next() {
TypeBoundKind::PathType(path_type)
} else if let Some(for_type) = support::children(self.syntax()).next() {
TypeBoundKind::ForType(for_type)
TypeBoundKind::PathType(self.for_binder(), path_type)
} else if let Some(args) = self.use_bound_generic_args() {
TypeBoundKind::Use(args)
} else if let Some(lifetime) = self.lifetime() {