Swift 2023 年代码之夏总结
Swift 项目定期参与 Google 代码之夏,以帮助开源生态系统的新手尝试为 Swift 及其不断发展的生态系统做出贡献。
在 2023 年的计划中,我们运行了三个项目,所有项目都成功完成了分配的任务。
本届的项目是
- Swift Memcache 库
- SwiftParser 中的增量解析
- 键路径推断和诊断改进
我们要衷心感谢参与者和导师,他们为这些项目投入了时间和热情,并利用这篇文章向更广泛的社区强调他们的工作。下面,每个项目都以简短的摘要进行描述。
让我们来看看每个项目,以下是学员和导师自己的描述
Swift Memcache
- 学员:Delkhaz Ibrahimi
- 导师:Franz Busch
该项目的目标是为服务器端 Swift 生态系统开发一个原生的 Memcached 连接抽象。此连接使用 SwiftNIO
实现,提供原生 Swift 并发 API,并与服务器生态系统的其余部分良好集成。使用 Swift Concurrency 构建此类客户端的好处在于,它可以利用结构化并发,从而在未来实现取消、执行器感知以及与 分布式追踪的简单集成。
该项目的重点是实现 Memcache 元命令协议,并提供基本的 get
和 set
功能。
下面是一个简短的示例,说明如何使用新的 MemcacheConnection
类型为给定键 set
和 get
值
// Instantiate a new MemcacheConnection with host, port, and event loop group
let memcacheConnection = MemcacheConnection(host: "127.0.0.1", port: 11211, eventLoopGroup: .singleton)
// Initialize the service group
let serviceGroup = ServiceGroup(services: [memcacheConnection], logger: logger)
try await withThrowingTaskGroup(of: Void.self) { group in
group.addTask { try await serviceGroup.run() }
// Set a value for a key.
let setValue = "bar"
try await memcacheConnection.set("foo", value: setValue)
// Get the value for a key.
// Specify the expected type for the value returned from Memcache.
let getValue = try await memcacheConnection.get("foo", as: String.self)
}
在完成实现 get
和 set
命令的基础工作之后,添加了对 delete
、append
、prepend
、increment
和 decrement
的支持。最后,添加了对检查和更新键的生存时间的支持。
新的 MemcacheConnection
类型为实现更高级别的 MemcacheClient
奠定了基础,后者提供额外的功能,例如连接池、重试、跨节点的密钥分发等等。但是,实现这样的客户端不在今年 GSoC 项目的范围之内。
如果您想了解有关此项目和 Delkhaz 经验的更多信息,请参阅 Swift 论坛上的这个帖子。
在 SwiftParser 中实现增量重新解析
- 学员:Ziyang Huang
- 导师:Alex Hoppen
该项目旨在提高 SwiftParser 在编辑器语法高亮等场景下的性能,在这些场景中,会对文件应用少量编辑。通过添加增量解析并重用语法树中保持不变的部分,可以实现大幅的性能提升。
该项目最具挑战性的部分是确保我们正确解析源文件。考虑以下代码片段
foo() {}
someLabel: switch x {
default: break
}
此源代码被解析为 FunctionCallExprSyntax
和 LabeledStmtSyntax
。当我们删除此代码的“switch x
”部分时,一个幼稚的实现可能会重用 foo() {}
作为函数调用,因为编辑没有触及它。但这是不正确的,因为 someLabel
块现在变成了 foo() {}
的标签式尾随闭包。
为了解决这个问题,我们在初始解析期间为每个语法节点收集一些额外的信息,以标记每个节点可能受影响的范围。该信息用于正确地重新解析 foo()
函数调用,并将 someLabel
作为标签式尾随闭包包含在调用中。
该实现将增量解析源的速度提高了约 10 倍,同时在正常解析期间仅带来 2~3% 的性能损失。
如果您想阅读更多关于此项目以及 Ziyang 亲身经历的信息,请访问 Swift 论坛上他的 GSoC 经验帖子。
键路径推断和诊断改进
- 学员:Amritpan Kaur
- 导师:Pavel Yaskevich
该项目侧重于键路径文字表达式的类型检查的性能和诊断改进,以及对 SE-0249 为语言引入的新功能(例如键路径作为函数)的改进。
在编译期间,键路径表达式的根和值按顺序进行类型检查,以从此上下文中解析键路径类型。但是,类型检查器对键路径组件类型、它们彼此之间的关系以及键路径功能的评估设计导致了难以理解的编译器错误,甚至无法类型检查某些有效的 Swift 代码。
以下代码示例可以说明这种方法的一些问题
struct User {
var name: Name
}
struct Name {
let firstName: String
}
func test(_: WritableKeyPath<User, String>) {}
test(\.name.firstName)
编译器产生以下错误
error: key path value type 'WritableKeyPath<User, String>' cannot be converted to contextual type 'KeyPath<User, String>'
test(\.name.firstName)
^
此错误诊断存在多个问题:上下文类型实际上是 WritableKeyPath
,键路径应推断为只读,源信息丢失,并且编译器无法指出函数 test
调用的参数存在问题。
为了解决这些问题和其他问题,我们探索了一种不同的键路径文字表达式类型检查设计:首先推断键路径的根类型,并将该信息传播到组件,并根据组件推断功能,然后在为键路径表达式设置类型之前进行推断。这使得诊断上下文类型故障和支持先前失败的转换变得容易得多。这种方法还提高了性能,因为仅当上下文期望键路径并且根类型由开发人员显式提供或可以从上下文中推断出来时,才会解析文字。
使用新方法实现后,编译器现在生成以下诊断
error: cannot convert value of type 'KeyPath<User, String>' to expected argument type 'WritableKeyPath<User, String>'
test(\.name.firstName)
^
如果您想了解有关此项目详细信息的更多信息,我们建议您查看 Amritpan 在论坛上撰写的这篇优秀且非常详细的总结。
学员印象
很高兴看到我们的 GSoC 学员今年完成了哪些项目!更棒的是看到参与者享受他们在 Swift 项目中的工作时光,因为代码之夏的重要组成部分是为学员(和导师)提供成长和学习开源开发的空间。
以下是学员对他们经历的一些印象
Delkhaz (Swift Memcache)
当我们结束这份技术更新时,对我来说,分享我作为 Google 代码之夏学生的正式旅程已经结束,这既是苦乐参半的时刻,但这是一段多么不可思议的旅程。这种变革性的经历丰富了我对开源开发的理解,并磨练了我作为开发人员的技能。我要衷心感谢每一位与我一起参与这次冒险的人。
虽然这一章节可能即将结束,但我很高兴地宣布,我将继续积极参与该项目。我特别兴奋地为将该项目推向 v1 或生产阶段做出贡献。所以,这不是告别;这只是新篇章的开始。期待与大家保持联系并继续这段旅程。
特别感谢我的导师 Franz,感谢他在我参与该计划期间给予的杰出指导。他在我们的每周会议中的智慧和见解对我作为一名开发人员来说,简直是变革性的。无论是驾驭开源贡献的复杂性,还是在我们 API 开发中力求最高标准,Franz 的指导都是不可或缺的。由于他的持续支持,我对软件开发有了多方面的理解。我无法要求获得更有影响力的指导体验,对此我深表感谢。
Ziyang (在 SwiftParser 中实现增量重新解析)
经过测量,我们的实现将增量解析源的速度提高了约 10 倍,同时仅为正常解析带来 2~3% 的性能损失。🎉 🎉
我还将此功能引入了 sourcekit-lsp 和 swift-stress-tester,看到我的工作能够真正投入使用真是令人兴奋。
特别感谢我的导师 Alex 的快速响应、详细的审查和富有启发性的想法。
Amritpan (键路径推断和诊断改进)
我很高兴今年能参与这个项目,主要是因为它是一个挑战,让我能够加深对求解器实现的理解,利用我去年对调试输出所做的改进,并对编译器代码库进行更具影响力的更改。
去年重构调试输出帮助我理解了类型检查器收集的各种信息是如何评估的,然后从上下文中分配类型。查看键路径表达式类型检查失败揭示了约束系统和求解器的一些缺陷,以及各种设计决策选择如何解决某些问题,同时又导致其他问题。
我们希望这篇总结能激励您申请与我们合作或在未来的 Swift 项目中成为导师!
我们一直在寻找关于如何使 Swift 生态系统更具包容性且更易于参与的想法、导师和一般性意见。如果您有一些想法,想要在未来的版本中成为导师,或者您只是对以前版本中提出的其他项目想法感到好奇,请访问 Swift 论坛上的专门的 GSoC 类别。您还可以查看去年的 GSoC 总结博客文章,我们在其中重点介绍了去年的项目。