mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +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 {
|
namespace {
|
||||||
|
|
||||||
class AccessScopeChecker {
|
class AccessScopeChecker {
|
||||||
|
ASTContext &Context;
|
||||||
const SourceFile *File;
|
const SourceFile *File;
|
||||||
TypeChecker::TypeAccessScopeCacheMap &Cache;
|
TypeChecker::TypeAccessScopeCacheMap &Cache;
|
||||||
|
|
||||||
@@ -1147,7 +1148,9 @@ protected:
|
|||||||
|
|
||||||
AccessScopeChecker(const DeclContext *useDC,
|
AccessScopeChecker(const DeclContext *useDC,
|
||||||
decltype(TypeChecker::TypeAccessScopeCache) &caches)
|
decltype(TypeChecker::TypeAccessScopeCache) &caches)
|
||||||
: File(useDC->getParentSourceFile()), Cache(caches[File]),
|
: Context(useDC->getASTContext()),
|
||||||
|
File(useDC->getParentSourceFile()),
|
||||||
|
Cache(caches[File]),
|
||||||
Scope(AccessScope::getPublic()) {}
|
Scope(AccessScope::getPublic()) {}
|
||||||
|
|
||||||
bool visitDecl(ValueDecl *VD) {
|
bool visitDecl(ValueDecl *VD) {
|
||||||
@@ -1161,6 +1164,12 @@ protected:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Simulation for Swift 3 bug.
|
||||||
|
if (isa<TypeAliasDecl>(VD) &&
|
||||||
|
VD->getInterfaceType()->hasTypeParameter() &&
|
||||||
|
Context.isSwiftVersion3())
|
||||||
|
return true;
|
||||||
|
|
||||||
auto cached = Cache.find(VD);
|
auto cached = Cache.find(VD);
|
||||||
if (cached != Cache.end()) {
|
if (cached != Cache.end()) {
|
||||||
Scope = Scope->intersectWith(cached->second);
|
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}}
|
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}}
|
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}}
|
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