Skip to content

[FixCode] Add @escaping when overriding mismatch is because of it. #4593

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
Sep 2, 2016
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
32 changes: 30 additions & 2 deletions lib/Sema/MiscDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1130,8 +1130,8 @@ bool swift::fixItOverrideDeclarationTypes(TypeChecker &TC,
// override uses a reference type, and the value type is bridged to the
// reference type. This is a way to migrate code that makes use of types
// that previously were not bridged to value types.
auto checkType = [&](Type overrideTy, Type baseTy,
SourceRange typeRange) -> bool {
auto checkValueReferenceType = [&](Type overrideTy, Type baseTy,
SourceRange typeRange) -> bool {
if (typeRange.isInvalid())
return false;

Expand Down Expand Up @@ -1184,6 +1184,34 @@ bool swift::fixItOverrideDeclarationTypes(TypeChecker &TC,
return true;
};

// Check if overriding fails because we lack @escaping attribute on the function
// type repr.
auto checkTypeMissingEscaping = [&](Type overrideTy, Type baseTy,
SourceRange typeRange) -> bool {
// Fix-it needs position to apply.
if (typeRange.isInvalid())
return false;
auto overrideFnTy = overrideTy->getAs<AnyFunctionType>();
auto baseFnTy = baseTy->getAs<AnyFunctionType>();

// Both types should be function.
if (overrideFnTy && baseFnTy &&
// The overriding function type should be no escaping.
overrideFnTy->getExtInfo().isNoEscape() &&
// The overriden function type should be escaping.
!baseFnTy->getExtInfo().isNoEscape()) {
diag.fixItInsert(typeRange.Start, "@escaping ");
return true;
}
return false;
};

auto checkType = [&](Type overrideTy, Type baseTy,
SourceRange typeRange) -> bool {
return checkValueReferenceType(overrideTy, baseTy, typeRange) ||
checkTypeMissingEscaping(overrideTy, baseTy, typeRange);
};

if (auto *var = dyn_cast<VarDecl>(decl)) {
SourceRange typeRange = var->getTypeSourceRangeForDiagnostics();
return checkType(var->getType(), base->getType(), typeRange);
Expand Down
18 changes: 18 additions & 0 deletions test/Constraints/override.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,21 @@ func removeOverrides<SomeSub: Sub>(concrete: Sub, generic: SomeSub) {
_ = concrete.foo()
_ = generic.foo()
}

class Base1 {
func foo1(a : Int, b : @escaping ()->()) {} // expected-note{{potential overridden instance method 'foo1(a:b:)' here}}
func foo2(a : @escaping (Int)->(Int), b : @escaping ()->()) {} // expected-note{{potential overridden instance method 'foo2(a:b:)' here}}
}

class Sub1 : Base1 {
override func foo1(a : Int, b : ()->()) {} // expected-error {{method does not override any method from its superclass}} expected-note {{type does not match superclass instance method with type '(Int, @escaping () -> ()) -> ()'}} {{34-34=@escaping }}
override func foo2(a : (Int)->(Int), b : ()->()) {} // expected-error {{method does not override any method from its superclass}} expected-note{{type does not match superclass instance method with type '(@escaping (Int) -> (Int), @escaping () -> ()) -> ()'}} {{25-25=@escaping }} {{43-43=@escaping }}
}

class Base2 {
func foo<T>(a : @escaping (T) ->()) {} // expected-note{{potential overridden instance method 'foo(a:)' here}}
}

class Sub2 : Base2 {
override func foo<T>(a : (T) ->()) {} // expected-error {{method does not override any method from its superclass}} expected-note{{type does not match superclass instance method with type '<T> (a: (T) -> ()) -> ()'}}{{28-28=@escaping }}
}
2 changes: 1 addition & 1 deletion test/attr/attr_autoclosure.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class Super {
class Sub : Super {
override func f1(_ x: @autoclosure(escaping)() -> ()) { }
// expected-warning@-1{{@autoclosure(escaping) is deprecated; use @autoclosure @escaping instead}} {{37-47= @escaping }}
override func f2(_ x: @autoclosure () -> ()) { } // expected-error{{does not override any method}}
override func f2(_ x: @autoclosure () -> ()) { } // expected-error{{does not override any method}} // expected-note{{type does not match superclass instance method with type '(@autoclosure @escaping () -> ()) -> ()'}}
override func f3(_ x: @autoclosure(escaping) () -> ()) { } // expected-error{{does not override any method}}
// expected-warning@-1{{@autoclosure(escaping) is deprecated; use @autoclosure @escaping instead}} {{37-47= @escaping}}
}
Expand Down