Skip to content

[Sema] Diagnose availability via TypeReprs rather than Types. #6036

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
Dec 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
4 changes: 4 additions & 0 deletions lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,10 @@ TypeDecl *TypeBase::getDirectlyReferencedTypeDecl() const {
return nullptr;
}

if (auto substituted = dyn_cast<SubstitutedType>(this)) {
return substituted->getOriginal()->getDirectlyReferencedTypeDecl();
}

return nullptr;
}

Expand Down
52 changes: 7 additions & 45 deletions lib/Sema/TypeCheckType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1340,55 +1340,18 @@ static Type resolveIdentTypeComponent(
unsatisfiedDependency);
}

static bool checkTypeDeclAvailability(const TypeDecl *TypeDecl,
IdentTypeRepr *IdType,
SourceLoc Loc, DeclContext *DC,
TypeChecker &TC,
bool AllowPotentiallyUnavailableProtocol){
if (isa<ComponentIdentTypeRepr>(IdType)) {
return diagnoseDeclAvailability(TypeDecl, TC, DC, Loc,
AllowPotentiallyUnavailableProtocol,
false);
}

return false;
}


static bool diagnoseAvailability(Type ty, IdentTypeRepr *IdType, SourceLoc Loc,
static bool diagnoseAvailability(IdentTypeRepr *IdType,
DeclContext *DC, TypeChecker &TC,
bool AllowPotentiallyUnavailableProtocol) {
if (auto *NAT = dyn_cast<NameAliasType>(ty.getPointer())) {
if (checkTypeDeclAvailability(NAT->getDecl(), IdType, Loc, DC, TC,
AllowPotentiallyUnavailableProtocol))
return true;
}

if (auto *GPT = dyn_cast<GenericTypeParamType>(ty.getPointer())) {
if (auto GP = GPT->getDecl()) {
if (checkTypeDeclAvailability(GP, IdType, Loc, DC, TC,
AllowPotentiallyUnavailableProtocol)) {
for (auto comp : IdType->getComponentRange()) {
if (auto typeDecl = dyn_cast_or_null<TypeDecl>(comp->getBoundDecl())) {
if (diagnoseDeclAvailability(typeDecl, TC, DC, comp->getIdLoc(),
AllowPotentiallyUnavailableProtocol,
false))
return true;
}
}
}

// Look through substituted types to diagnose when the original
// type is marked unavailable.
if (auto *ST = dyn_cast<SubstitutedType>(ty.getPointer())) {
if (diagnoseAvailability(ST->getOriginal(), IdType, Loc, DC, TC,
AllowPotentiallyUnavailableProtocol)) {
return true;
}
}

CanType canTy = ty.getCanonicalTypeOrNull();
if (canTy.isNull())
return false;
if (auto NTD = canTy.getAnyNominal())
return checkTypeDeclAvailability(NTD, IdType, Loc, DC, TC,
AllowPotentiallyUnavailableProtocol);

return false;
}

Expand Down Expand Up @@ -1468,8 +1431,7 @@ Type TypeChecker::resolveIdentifierType(

// Check the availability of the type.
if (!(options & TR_AllowUnavailable) &&
diagnoseAvailability(result, IdType,
Components.back()->getIdLoc(), DC, *this,
diagnoseAvailability(IdType, DC, *this,
AllowPotentiallyUnavailableProtocol)) {
Components.back()->setInvalid();
return ErrorType::get(Context);
Expand Down
2 changes: 2 additions & 0 deletions test/Interpreter/SDK/submodules_smoke_test.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import AppKit.NSPanGestureRecognizer

@available(OSX, introduced: 10.10)
typealias PanRecognizer = NSPanGestureRecognizer

@available(OSX, introduced: 10.10)
typealias PanRecognizer2 = AppKit.NSPanGestureRecognizer

#if !NO_ERROR
Expand Down
15 changes: 13 additions & 2 deletions test/Sema/availability.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-typecheck-verify-swift
// RUN: %target-typecheck-verify-swift -module-name MyModule

// REQUIRES: OS=macosx

Expand All @@ -10,10 +10,21 @@ func test() {
}

@available(*,unavailable,message: "use 'Int' instead")
struct NSUInteger {} // expected-note 2 {{explicitly marked unavailable here}}
struct NSUInteger {} // expected-note 3 {{explicitly marked unavailable here}}

struct Outer {
@available(*,unavailable,message: "use 'UInt' instead")
struct NSUInteger {} // expected-note 2 {{explicitly marked unavailable here}}
}

func foo(x : NSUInteger) { // expected-error {{'NSUInteger' is unavailable: use 'Int' instead}}
let y : NSUInteger = 42 // expected-error {{'NSUInteger' is unavailable: use 'Int' instead}}

let z : MyModule.NSUInteger = 42 // expected-error {{'NSUInteger' is unavailable: use 'Int' instead}}

let z2 : Outer.NSUInteger = 42 // expected-error {{'NSUInteger' is unavailable: use 'UInt' instead}}

let z3 : MyModule.Outer.NSUInteger = 42 // expected-error {{'NSUInteger' is unavailable: use 'UInt' instead}}
}

// Test preventing overrides of unavailable methods.
Expand Down