mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Sema: Add simulation of buggy Swift 3 typealias accessibility checking
Basically if the underlying type of a typealias was dependent on generic parameters from context, it wouldn't participate in accessibility checking. Turns out people were (accidentally) relying on this behavior, so add a simulation of it in Swift 3 mode by ignoring such typealiases entirely. Fixes <rdar://problem/29549232>.
This commit is contained in:
@@ -1139,6 +1139,7 @@ static void recordSelfContextType(AbstractFunctionDecl *func) {
|
||||
namespace {
|
||||
|
||||
class AccessScopeChecker {
|
||||
ASTContext &Context;
|
||||
const SourceFile *File;
|
||||
TypeChecker::TypeAccessScopeCacheMap &Cache;
|
||||
|
||||
@@ -1147,7 +1148,9 @@ protected:
|
||||
|
||||
AccessScopeChecker(const DeclContext *useDC,
|
||||
decltype(TypeChecker::TypeAccessScopeCache) &caches)
|
||||
: File(useDC->getParentSourceFile()), Cache(caches[File]),
|
||||
: Context(useDC->getASTContext()),
|
||||
File(useDC->getParentSourceFile()),
|
||||
Cache(caches[File]),
|
||||
Scope(AccessScope::getPublic()) {}
|
||||
|
||||
bool visitDecl(ValueDecl *VD) {
|
||||
@@ -1161,6 +1164,12 @@ protected:
|
||||
return true;
|
||||
}
|
||||
|
||||
// Simulation for Swift 3 bug.
|
||||
if (isa<TypeAliasDecl>(VD) &&
|
||||
VD->getInterfaceType()->hasTypeParameter() &&
|
||||
Context.isSwiftVersion3())
|
||||
return true;
|
||||
|
||||
auto cached = Cache.find(VD);
|
||||
if (cached != Cache.end()) {
|
||||
Scope = Scope->intersectWith(cached->second);
|
||||
|
||||
42
test/Compatibility/accessibility_typealias.swift
Normal file
42
test/Compatibility/accessibility_typealias.swift
Normal file
@@ -0,0 +1,42 @@
|
||||
// RUN: %target-typecheck-verify-swift -swift-version 3
|
||||
|
||||
public protocol P {
|
||||
associatedtype Element
|
||||
|
||||
func f() -> Element
|
||||
}
|
||||
|
||||
struct S<T> : P {
|
||||
func f() -> T { while true {} }
|
||||
}
|
||||
|
||||
public struct G<T> {
|
||||
typealias A = S<T>
|
||||
|
||||
public func foo<U : P>(u: U) where U.Element == A.Element {}
|
||||
}
|
||||
|
||||
public final class ReplayableGenerator<S: Sequence> : IteratorProtocol {
|
||||
typealias Sequence = S
|
||||
public typealias Element = Sequence.Iterator.Element
|
||||
|
||||
public func next() -> Element? {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
struct Generic<T> {
|
||||
fileprivate typealias Dependent = T
|
||||
}
|
||||
|
||||
var x: Generic<Int>.Dependent = 3
|
||||
|
||||
func internalFuncWithFileprivateAlias() -> Generic<Int>.Dependent {
|
||||
return 3
|
||||
}
|
||||
|
||||
private func privateFuncWithFileprivateAlias() -> Generic<Int>.Dependent {
|
||||
return 3
|
||||
}
|
||||
|
||||
var y = privateFuncWithFileprivateAlias()
|
||||
@@ -637,21 +637,3 @@ internal struct AssocTypeOuterProblem2 {
|
||||
fileprivate typealias Assoc = Int // expected-error {{type alias 'Assoc' must be as accessible as its enclosing type because it matches a requirement in protocol 'AssocTypeProto'}} {{5-16=internal}}
|
||||
}
|
||||
}
|
||||
|
||||
// This code was accepted in Swift 3
|
||||
public protocol P {
|
||||
associatedtype Element
|
||||
|
||||
func f() -> Element
|
||||
}
|
||||
|
||||
struct S<T> : P {
|
||||
func f() -> T { while true {} }
|
||||
}
|
||||
|
||||
public struct G<T> {
|
||||
typealias A = S<T> // expected-note {{type declared here}}
|
||||
|
||||
public func foo<U : P>(u: U) where U.Element == A.Element {}
|
||||
// expected-error@-1 {{instance method cannot be declared public because its generic requirement uses an internal type}}
|
||||
}
|
||||
|
||||
@@ -210,24 +210,3 @@ fileprivate struct SR2579 {
|
||||
private var outerProperty = Inner().innerProperty // expected-warning {{property should not be declared in this context because its type 'SR2579.Inner.InnerPrivateType' uses a private type}}
|
||||
var outerProperty2 = Inner().innerProperty // expected-warning {{property should be declared private because its type 'SR2579.Inner.InnerPrivateType' uses a private type}}
|
||||
}
|
||||
|
||||
// FIXME: Dependent member lookup of typealiases is not subject
|
||||
// to accessibility checking.
|
||||
struct Generic<T> {
|
||||
fileprivate typealias Dependent = T
|
||||
}
|
||||
|
||||
var x: Generic<Int>.Dependent = 3
|
||||
// expected-error@-1 {{variable must be declared private or fileprivate because its type uses a fileprivate type}}
|
||||
|
||||
func internalFuncWithFileprivateAlias() -> Generic<Int>.Dependent {
|
||||
// expected-error@-1 {{function must be declared private or fileprivate because its result uses a fileprivate type}}
|
||||
return 3
|
||||
}
|
||||
|
||||
private func privateFuncWithFileprivateAlias() -> Generic<Int>.Dependent {
|
||||
return 3
|
||||
}
|
||||
|
||||
// FIXME: No error here
|
||||
var y = privateFuncWithFileprivateAlias()
|
||||
|
||||
46
test/Sema/accessibility_typealias.swift
Normal file
46
test/Sema/accessibility_typealias.swift
Normal file
@@ -0,0 +1,46 @@
|
||||
// RUN: %target-typecheck-verify-swift -swift-version 4
|
||||
|
||||
public protocol P {
|
||||
associatedtype Element
|
||||
|
||||
func f() -> Element
|
||||
}
|
||||
|
||||
struct S<T> : P {
|
||||
func f() -> T { while true {} }
|
||||
}
|
||||
|
||||
public struct G<T> {
|
||||
typealias A = S<T> // expected-note {{type declared here}}
|
||||
|
||||
public func foo<U : P>(u: U) where U.Element == A.Element {}
|
||||
// expected-error@-1 {{instance method cannot be declared public because its generic requirement uses an internal type}}
|
||||
}
|
||||
|
||||
public final class ReplayableGenerator<S: Sequence> : IteratorProtocol {
|
||||
typealias Sequence = S // expected-note {{type declared here}}
|
||||
public typealias Element = Sequence.Iterator.Element // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
|
||||
|
||||
public func next() -> Element? {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Dependent member lookup of typealiases is not subject
|
||||
// to accessibility checking.
|
||||
struct Generic<T> {
|
||||
fileprivate typealias Dependent = T
|
||||
}
|
||||
|
||||
var x: Generic<Int>.Dependent = 3 // expected-error {{variable must be declared private or fileprivate because its type uses a fileprivate type}}
|
||||
|
||||
func internalFuncWithFileprivateAlias() -> Generic<Int>.Dependent { // expected-error {{function must be declared private or fileprivate because its result uses a fileprivate type}}
|
||||
return 3
|
||||
}
|
||||
|
||||
private func privateFuncWithFileprivateAlias() -> Generic<Int>.Dependent {
|
||||
return 3
|
||||
}
|
||||
|
||||
// FIXME: No error here
|
||||
var y = privateFuncWithFileprivateAlias()
|
||||
Reference in New Issue
Block a user