Skip to content

Commit 6666202

Browse files
committed
Remove importedModules from StaticBuildConfiguration
The set of imported modules in StaticBuildConfiguration cannot really be complete, because canImport can trigger module lookups that only the compiler can do. Remove it from the configuration, and have canImport always throw an error to indicate the issue.
1 parent 02adade commit 6666202

File tree

2 files changed

+22
-76
lines changed

2 files changed

+22
-76
lines changed

Sources/SwiftIfConfig/StaticBuildConfiguration.swift

Lines changed: 13 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ import SwiftSyntax
1515
/// A statically-determined build configuration that can be used with any
1616
/// API that requires a build configuration. Static build configurations can
1717
/// be (de-)serialized via Codable.
18+
///
19+
/// Static build configurations can not be used for canImport checks, because
20+
/// such checks require deeper integration with the compiler itself.
1821
public struct StaticBuildConfiguration: Codable {
1922
public init(
2023
customConditions: Set<String> = [],
2124
features: Set<String> = [],
2225
attributes: Set<String> = [],
23-
importedModules: [String: [VersionedImportModule]] = [:],
2426
targetOSNames: Set<String> = [],
2527
targetArchitectures: Set<String> = [],
2628
targetEnvironments: Set<String> = [],
@@ -36,7 +38,6 @@ public struct StaticBuildConfiguration: Codable {
3638
self.customConditions = customConditions
3739
self.features = features
3840
self.attributes = attributes
39-
self.importedModules = importedModules
4041
self.targetOSNames = targetOSNames
4142
self.targetArchitectures = targetArchitectures
4243
self.targetEnvironments = targetEnvironments
@@ -88,11 +89,6 @@ public struct StaticBuildConfiguration: Codable {
8889
/// ```
8990
public var attributes: Set<String> = []
9091

91-
/// The set of modules that can be imported, and their version and underlying
92-
/// versions (if known). These are organized by top-level module name,
93-
/// with paths (to submodules) handled internally.
94-
public var importedModules: [String: [VersionedImportModule]] = [:]
95-
9692
/// The active target OS names, e.g., "Windows", "iOS".
9793
public var targetOSNames: Set<String> = []
9894

@@ -240,59 +236,10 @@ extension StaticBuildConfiguration: BuildConfiguration {
240236
/// Determine whether a module with the given import path can be imported,
241237
/// with additional version information.
242238
///
243-
/// The availability of a module for import can be checked with `canImport`,
244-
/// e.g.,
245-
///
246-
/// ```swift
247-
/// #if canImport(UIKit)
248-
/// // ...
249-
/// #endif
250-
/// ```
251-
///
252-
/// There is an experimental syntax for providing required module version
253-
/// information, which will translate into the `version` argument.
254-
///
255-
/// - Parameters:
256-
/// - importPath: A nonempty sequence of (token, identifier) pairs
257-
/// describing the imported module, which was written in source as a
258-
/// dotted sequence, e.g., `UIKit.UIViewController` will be passed in as
259-
/// the import path array `[(token, "UIKit"), (token, "UIViewController")]`.
260-
/// - version: The version restriction on the imported module. For the
261-
/// normal `canImport(<import-path>)` syntax, this will always be
262-
/// `CanImportVersion.unversioned`.
263-
/// - Returns: Whether the module can be imported.
264-
public func canImport(importPath: [(TokenSyntax, String)], version: CanImportVersion) -> Bool {
265-
// If we don't have any record of the top-level module, we cannot import it.
266-
guard let topLevelModuleName = importPath.first?.1,
267-
let versionedImports = importedModules[topLevelModuleName]
268-
else {
269-
return false
270-
}
271-
272-
// Match on submodule path.
273-
let submodulePath = Array(importPath.lazy.map(\.1).dropFirst())
274-
guard let matchingImport = versionedImports.first(where: { $0.submodulePath == submodulePath }) else {
275-
return false
276-
}
277-
278-
switch version {
279-
case .unversioned:
280-
return true
281-
282-
case .version(let expectedVersion):
283-
guard let actualVersion = matchingImport.version else {
284-
return false
285-
}
286-
287-
return actualVersion >= expectedVersion
288-
289-
case .underlyingVersion(let expectedVersion):
290-
guard let actualVersion = matchingImport.underlyingVersion else {
291-
return false
292-
}
293-
294-
return actualVersion >= expectedVersion
295-
}
239+
/// This implementation always throws an error, because static build
240+
/// configurations cannot evaluate canImport checks.
241+
public func canImport(importPath: [(TokenSyntax, String)], version: CanImportVersion) throws -> Bool {
242+
throw StaticBuildConfiguration.Error.canImportUnavailable
296243
}
297244

298245
/// Determine whether the given name is the active target OS (e.g., Linux, iOS).
@@ -412,20 +359,10 @@ extension StaticBuildConfiguration: BuildConfiguration {
412359
}
413360
}
414361

415-
/// Information about a potentially-versioned import of a given module.
416-
///
417-
/// Each instance of this struct is associated with a top-level module of some
418-
/// form. When the submodule path is empty, it refers to the top-level module
419-
/// itself.
420-
public struct VersionedImportModule: Codable {
421-
/// The submodule path (which may be empty) from the top-level module to
422-
/// this specific import.
423-
public var submodulePath: [String] = []
424-
425-
/// The version that was imported, if known.
426-
public var version: VersionTuple? = nil
427-
428-
/// The version of the underlying Clang module, if there is one and it is
429-
/// known.
430-
public var underlyingVersion: VersionTuple? = nil
362+
extension StaticBuildConfiguration {
363+
enum Error: Swift.Error {
364+
/// Indicates when the static build configuration was asked to evaluate
365+
/// canImport, which it cannot do correctly.
366+
case canImportUnavailable
367+
}
431368
}

Tests/SwiftIfConfigTest/EvaluateTests.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,15 @@ public class EvaluateTests: XCTestCase {
612612
]
613613
)
614614
}
615+
616+
func testStaticBuildConfigCanImport() throws {
617+
let config = StaticBuildConfiguration(
618+
languageVersion: VersionTuple(6),
619+
compilerVersion: VersionTuple(6)
620+
)
621+
622+
XCTAssertThrowsError(try config.canImport(importPath: [], version: .unversioned))
623+
}
615624
}
616625

617626
/// Assert the results of evaluating the condition within an `#if` against the

0 commit comments

Comments
 (0)