Skip to content

Revert "[Typed throws] Support overrides that are contravariant in the thrown error" #69921

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 16, 2023
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
3 changes: 0 additions & 3 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -3366,9 +3366,6 @@ ERROR(override_class_declaration_in_extension,none,
ERROR(override_with_more_effects,none,
"cannot override non-%1 %0 with %1 %0",
(DescriptiveDeclKind, StringRef))
ERROR(override_typed_throws,none,
"%0 that throws %1 cannot override one that throws %2",
(DescriptiveDeclKind, Type, Type))
ERROR(override_throws_objc,none,
"overriding a throwing @objc %select{method|initializer}0 with "
"a non-throwing %select{method|initializer}0 is not supported", (bool))
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/ExtInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ class ASTExtInfoBuilder {
return bits == other.bits &&
(useClangTypes ? (clangTypeInfo == other.clangTypeInfo) : true) &&
globalActor.getPointer() == other.globalActor.getPointer() &&
thrownError.getPointer() == other.thrownError.getPointer();
thrownError.getPointer() == thrownError.getPointer();
}

constexpr std::tuple<unsigned, const void *, const void *, const void *>
Expand Down
3 changes: 1 addition & 2 deletions lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3421,8 +3421,7 @@ static bool matchesFunctionType(CanAnyFunctionType fn1, CanAnyFunctionType fn2,
if (matchMode.contains(TypeMatchFlags::AllowOverride)) {
// Removing 'throwing' is ABI-compatible for synchronous functions, but
// not for async ones.
if (ext2.isThrowing() && !ext1.isThrowing() &&
ext2.getThrownError().isNull() &&
if (ext2.isThrowing() &&
!(ext2.isAsync() &&
matchMode.contains(TypeMatchFlags::AllowABICompatible))) {
ext1 = ext1.withThrows(true, ext2.getThrownError());
Expand Down
47 changes: 4 additions & 43 deletions lib/Sema/TypeCheckDeclOverride.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#include "TypeCheckAvailability.h"
#include "TypeCheckConcurrency.h"
#include "TypeCheckDecl.h"
#include "TypeCheckEffects.h"
#include "TypeCheckObjC.h"
#include "TypeChecker.h"
#include "swift/AST/ASTVisitor.h"
Expand Down Expand Up @@ -2037,54 +2036,16 @@ static bool checkSingleOverride(ValueDecl *override, ValueDecl *base) {
diags.diagnose(base, diag::overridden_here);
}
}

// Check effects.
// If the overriding declaration is 'throws' but the base is not,
// complain. Do the same for 'async'
if (auto overrideFn = dyn_cast<AbstractFunctionDecl>(override)) {
// Determine the thrown errors in the base and override declarations.
auto baseFn = cast<AbstractFunctionDecl>(base);
Type overrideThrownError =
overrideFn->getEffectiveThrownErrorType().value_or(ctx.getNeverType());
Type baseThrownError =
baseFn->getEffectiveThrownErrorType().value_or(ctx.getNeverType());

if (baseThrownError && baseThrownError->hasTypeParameter()) {
auto subs = SubstitutionMap::getOverrideSubstitutions(base, override);
baseThrownError = baseThrownError.subst(subs);
baseThrownError = overrideFn->mapTypeIntoContext(baseThrownError);
}

if (overrideThrownError)
overrideThrownError = overrideFn->mapTypeIntoContext(overrideThrownError);

// Check for a subtyping relationship.
switch (compareThrownErrorsForSubtyping(
overrideThrownError, baseThrownError, overrideFn)) {
case ThrownErrorSubtyping::DropsThrows:
if (overrideFn->hasThrows() &&
!cast<AbstractFunctionDecl>(base)->hasThrows()) {
diags.diagnose(override, diag::override_with_more_effects,
override->getDescriptiveKind(), "throwing");
diags.diagnose(base, diag::overridden_here);
break;

case ThrownErrorSubtyping::Mismatch:
diags.diagnose(override, diag::override_typed_throws,
override->getDescriptiveKind(), overrideThrownError,
baseThrownError);
diags.diagnose(base, diag::overridden_here);
break;

case ThrownErrorSubtyping::ExactMatch:
case ThrownErrorSubtyping::Subtype:
// Proper subtyping.
break;

case ThrownErrorSubtyping::Dependent:
// Only in already ill-formed code.
assert(ctx.Diags.hadAnyError());
break;
}

// If the override is 'async' but the base declaration is not, we have a
// problem.
if (overrideFn->hasAsync() &&
!cast<AbstractFunctionDecl>(base)->hasAsync()) {
diags.diagnose(override, diag::override_with_more_effects,
Expand Down
7 changes: 0 additions & 7 deletions lib/Sema/TypeCheckEffects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3595,13 +3595,6 @@ ThrownErrorSubtyping
swift::compareThrownErrorsForSubtyping(
Type subThrownError, Type superThrownError, DeclContext *dc
) {
// Deal with NULL errors. This should only occur when there is no standard
// library.
if (!subThrownError || !superThrownError) {
assert(!dc->getASTContext().getStdlibModule() && "NULL thrown error type");
return ThrownErrorSubtyping::ExactMatch;
}

// Easy case: exact match.
if (superThrownError->isEqual(subThrownError))
return ThrownErrorSubtyping::ExactMatch;
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ endif()
# STAGING: Temporarily avoids having to write #fileID in Swift.swiftinterface.
list(APPEND swift_stdlib_compile_flags "-Xfrontend" "-enable-experimental-concise-pound-file")

list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "TypedThrows")
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "Macros")
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "FreestandingMacros")
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "Extern")

Expand Down
18 changes: 3 additions & 15 deletions stdlib/public/core/Collection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1190,10 +1190,9 @@ extension Collection {
/// - Returns: An array containing the transformed elements of this
/// sequence.
@inlinable
@_alwaysEmitIntoClient
public func map<T, E>(
_ transform: (Element) throws(E) -> T
) throws(E) -> [T] {
public func map<T>(
_ transform: (Element) throws -> T
) rethrows -> [T] {
// TODO: swift-3-indexing-model - review the following
let n = self.count
if n == 0 {
Expand All @@ -1214,17 +1213,6 @@ extension Collection {
return Array(result)
}

// ABI-only entrypoint for the rethrows version of map, which has been
// superseded by the typed-throws version. Expressed as "throws", which is
// ABI-compatible with "rethrows".
@usableFromInline
@_silgen_name("$sSlsE3mapySayqd__Gqd__7ElementQzKXEKlF")
func __rethrows_map<T>(
_ transform: (Element) throws -> T
) throws -> [T] {
try map(transform)
}

/// Returns a subsequence containing all but the given number of initial
/// elements.
///
Expand Down
106 changes: 21 additions & 85 deletions stdlib/public/core/ExistentialCollection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ internal class _AnySequenceBox<Element> {
@inlinable
internal func _map<T>(
_ transform: (Element) throws -> T
) throws -> [T] {
) rethrows -> [T] {
_abstract()
}

Expand Down Expand Up @@ -525,8 +525,8 @@ internal final class _SequenceBox<S: Sequence>: _AnySequenceBox<S.Element> {
@inlinable
internal override func _map<T>(
_ transform: (Element) throws -> T
) throws -> [T] {
try _base.map(transform)
) rethrows -> [T] {
return try _base.map(transform)
}
@inlinable
internal override func _filter(
Expand Down Expand Up @@ -618,8 +618,8 @@ internal final class _CollectionBox<S: Collection>: _AnyCollectionBox<S.Element>
@inlinable
internal override func _map<T>(
_ transform: (Element) throws -> T
) throws -> [T] {
try _base.map(transform)
) rethrows -> [T] {
return try _base.map(transform)
}
@inlinable
internal override func _filter(
Expand Down Expand Up @@ -813,8 +813,8 @@ internal final class _BidirectionalCollectionBox<S: BidirectionalCollection>
@inlinable
internal override func _map<T>(
_ transform: (Element) throws -> T
) throws -> [T] {
try _base.map(transform)
) rethrows -> [T] {
return try _base.map(transform)
}
@inlinable
internal override func _filter(
Expand Down Expand Up @@ -1026,8 +1026,8 @@ internal final class _RandomAccessCollectionBox<S: RandomAccessCollection>
@inlinable
internal override func _map<T>(
_ transform: (Element) throws -> T
) throws -> [T] {
try _base.map(transform)
) rethrows -> [T] {
return try _base.map(transform)
}
@inlinable
internal override func _filter(
Expand Down Expand Up @@ -1303,26 +1303,10 @@ extension AnySequence {
}

@inlinable
@_alwaysEmitIntoClient
public func map<T, E>(
_ transform: (Element) throws(E) -> T
) throws(E) -> [T] {
do {
return try _box._map(transform)
} catch {
throw error as! E
}
}

// ABI-only entrypoint for the rethrows version of map, which has been
// superseded by the typed-throws version. Expressed as "throws", which is
// ABI-compatible with "rethrows".
@usableFromInline
@_silgen_name("$ss11AnySequenceV3mapySayqd__Gqd__xKXEKlF")
func __rethrows_map<T>(
public func map<T>(
_ transform: (Element) throws -> T
) throws -> [T] {
try map(transform)
) rethrows -> [T] {
return try _box._map(transform)
}

@inlinable
Expand Down Expand Up @@ -1406,26 +1390,10 @@ extension AnyCollection {
}

@inlinable
@_alwaysEmitIntoClient
public func map<T, E>(
_ transform: (Element) throws(E) -> T
) throws(E) -> [T] {
do {
return try _box._map(transform)
} catch {
throw error as! E
}
}

// ABI-only entrypoint for the rethrows version of map, which has been
// superseded by the typed-throws version. Expressed as "throws", which is
// ABI-compatible with "rethrows".
@usableFromInline
@_silgen_name("$ss13AnyCollectionV3mapySayqd__Gqd__xKXEKlF")
func __rethrows_map<T>(
public func map<T>(
_ transform: (Element) throws -> T
) throws -> [T] {
try map(transform)
) rethrows -> [T] {
return try _box._map(transform)
}

@inlinable
Expand Down Expand Up @@ -1515,26 +1483,10 @@ extension AnyBidirectionalCollection {
}

@inlinable
@_alwaysEmitIntoClient
public func map<T, E>(
_ transform: (Element) throws(E) -> T
) throws(E) -> [T] {
do {
return try _box._map(transform)
} catch {
throw error as! E
}
}

// ABI-only entrypoint for the rethrows version of map, which has been
// superseded by the typed-throws version. Expressed as "throws", which is
// ABI-compatible with "rethrows".
@usableFromInline
@_silgen_name("$ss26AnyBidirectionalCollectionV3mapySayqd__Gqd__xKXEKlF")
func __rethrows_map<T>(
public func map<T>(
_ transform: (Element) throws -> T
) throws -> [T] {
try map(transform)
) rethrows -> [T] {
return try _box._map(transform)
}

@inlinable
Expand Down Expand Up @@ -1626,26 +1578,10 @@ extension AnyRandomAccessCollection {
}

@inlinable
@_alwaysEmitIntoClient
public func map<T, E>(
_ transform: (Element) throws(E) -> T
) throws(E) -> [T] {
do {
return try _box._map(transform)
} catch {
throw error as! E
}
}

// ABI-only entrypoint for the rethrows version of map, which has been
// superseded by the typed-throws version. Expressed as "throws", which is
// ABI-compatible with "rethrows".
@usableFromInline
@_silgen_name("$ss25AnyRandomAccessCollectionV3mapySayqd__Gqd__xKXEKlF")
func __rethrows_map<T>(
public func map<T>(
_ transform: (Element) throws -> T
) throws -> [T] {
try map(transform)
) rethrows -> [T] {
return try _box._map(transform)
}

@inlinable
Expand Down
11 changes: 0 additions & 11 deletions stdlib/public/core/Misc.swift
Original file line number Diff line number Diff line change
Expand Up @@ -159,17 +159,6 @@ public func _unsafePerformance<T>(_ c: () -> T) -> T {
return c()
}

// Helper function that exploits a bug in rethrows checking to
// allow us to call rethrows functions from generic typed-throws functions
// and vice-versa.
@usableFromInline
@_alwaysEmitIntoClient
@inline(__always)
func _rethrowsViaClosure(_ fn: () throws -> ()) rethrows {
try fn()
}


/// This marker protocol represents types that support copying.
/// This type is not yet available for use to express explicit
/// constraints on generics in your programs. It is currently
Expand Down
18 changes: 3 additions & 15 deletions stdlib/public/core/Sequence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -670,10 +670,9 @@ extension Sequence {
///
/// - Complexity: O(*n*), where *n* is the length of the sequence.
@inlinable
@_alwaysEmitIntoClient
public func map<T, E>(
_ transform: (Element) throws(E) -> T
) throws(E) -> [T] {
public func map<T>(
_ transform: (Element) throws -> T
) rethrows -> [T] {
let initialCapacity = underestimatedCount
var result = ContiguousArray<T>()
result.reserveCapacity(initialCapacity)
Expand All @@ -691,17 +690,6 @@ extension Sequence {
return Array(result)
}

// ABI-only entrypoint for the rethrows version of map, which has been
// superseded by the typed-throws version. Expressed as "throws", which is
// ABI-compatible with "rethrows".
@usableFromInline
@_silgen_name("$sSTsE3mapySayqd__Gqd__7ElementQzKXEKlF")
func __rethrows_map<T>(
_ transform: (Element) throws -> T
) throws -> [T] {
try map(transform)
}

/// Returns an array containing, in order, the elements of the sequence
/// that satisfy the given predicate.
///
Expand Down
7 changes: 3 additions & 4 deletions test/Constraints/closures.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1143,11 +1143,11 @@ struct R_76250381<Result, Failure: Error> {

// https://github.com/apple/swift/issues/55926
(0..<10).map { x, y in }
// expected-error@-1 {{contextual closure type '(Range<Int>.Element) -> ()' (aka '(Int) -> ()') expects 1 argument, but 2 were used in closure body}}
// expected-error@-1 {{contextual closure type '(Range<Int>.Element) throws -> ()' (aka '(Int) throws -> ()') expects 1 argument, but 2 were used in closure body}}
(0..<10).map { x, y, z in }
// expected-error@-1 {{contextual closure type '(Range<Int>.Element) -> ()' (aka '(Int) -> ()') expects 1 argument, but 3 were used in closure body}}
// expected-error@-1 {{contextual closure type '(Range<Int>.Element) throws -> ()' (aka '(Int) throws -> ()') expects 1 argument, but 3 were used in closure body}}
(0..<10).map { x, y, z, w in }
// expected-error@-1 {{contextual closure type '(Range<Int>.Element) -> ()' (aka '(Int) -> ()') expects 1 argument, but 4 were used in closure body}}
// expected-error@-1 {{contextual closure type '(Range<Int>.Element) throws -> ()' (aka '(Int) throws -> ()') expects 1 argument, but 4 were used in closure body}}

// rdar://77022842 - crash due to a missing argument to a ternary operator
func rdar77022842(argA: Bool? = nil, argB: Bool? = nil) {
Expand All @@ -1171,7 +1171,6 @@ func rdar76058892() {
test { // expected-error {{contextual closure type '() -> String' expects 0 arguments, but 1 was used in closure body}}
if let arr = arr {
arr.map($0.test) // expected-note {{anonymous closure parameter '$0' is used here}} // expected-error {{generic parameter 'T' could not be inferred}}
// expected-error@-1 {{generic parameter 'E' could not be inferred}}
}
}
}
Expand Down
Loading