Skip to content

isInvalid() Is Finally Semantic #27922

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 6 commits into from
Oct 30, 2019
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: 2 additions & 2 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -807,10 +807,10 @@ class alignas(1 << DeclAlignInBits) Decl {
bool walk(ASTWalker &walker);

/// Return whether this declaration has been determined invalid.
bool isInvalid() const { return Bits.Decl.Invalid; }
bool isInvalid() const;

/// Mark this declaration invalid.
void setInvalid(bool isInvalid = true) { Bits.Decl.Invalid = isInvalid; }
void setInvalid();

/// Determine whether this declaration was implicitly generated by the
/// compiler (rather than explicitly written in source code).
Expand Down
2 changes: 1 addition & 1 deletion lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2366,7 +2366,7 @@ CanType ASTMangler::getDeclTypeForMangling(
parentGenericSig = GenericSignature();

auto &C = decl->getASTContext();
if (!decl->getInterfaceType() || decl->getInterfaceType()->is<ErrorType>()) {
if (decl->isInvalid()) {
if (isa<AbstractFunctionDecl>(decl))
return CanFunctionType::get({AnyFunctionType::Param(C.TheErrorType)},
C.TheErrorType);
Expand Down
4 changes: 2 additions & 2 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2872,7 +2872,7 @@ void PrintAST::printEnumElement(EnumElementDecl *elt) {


auto params = ArrayRef<AnyFunctionType::Param>();
if (elt->hasInterfaceType() && !elt->getInterfaceType()->hasError()) {
if (elt->hasInterfaceType() && !elt->isInvalid()) {
// Walk to the params of the associated values.
// (EnumMetaType) -> (AssocValues) -> Enum
params = elt->getInterfaceType()->castTo<AnyFunctionType>()
Expand Down Expand Up @@ -2969,7 +2969,7 @@ void PrintAST::visitSubscriptDecl(SubscriptDecl *decl) {
}, [&] { // Parameters
printGenericDeclGenericParams(decl);
auto params = ArrayRef<AnyFunctionType::Param>();
if (decl->hasInterfaceType() && !decl->getInterfaceType()->hasError()) {
if (decl->hasInterfaceType() && !decl->isInvalid()) {
// Walk to the params of the subscript's indices.
params = decl->getInterfaceType()->castTo<AnyFunctionType>()->getParams();
}
Expand Down
2 changes: 1 addition & 1 deletion lib/AST/AccessRequests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ AccessLevelRequest::evaluate(Evaluator &evaluator, ValueDecl *D) const {
// Special case for dtors and enum elements: inherit from container
if (D->getKind() == DeclKind::Destructor ||
D->getKind() == DeclKind::EnumElement) {
if (D->isInvalid()) {
if (D->hasInterfaceType() && D->isInvalid()) {
return AccessLevel::Private;
} else {
auto container = cast<NominalTypeDecl>(D->getDeclContext());
Expand Down
71 changes: 71 additions & 0 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,77 @@ DeclContext *Decl::getInnermostDeclContext() const {
return getDeclContext();
}

bool Decl::isInvalid() const {
switch (getKind()) {
#define VALUE_DECL(ID, PARENT)
#define DECL(ID, PARENT) \
case DeclKind::ID:
#include "swift/AST/DeclNodes.def"
return Bits.Decl.Invalid;
case DeclKind::Param: {
// Parameters are special because closure parameters may not have type
// annotations. In which case, the interface type request returns
// ErrorType. Therefore, consider parameters with implicit types to always
// be valid.
auto *PD = cast<ParamDecl>(this);
if (!PD->getTypeRepr() && !PD->hasInterfaceType())
return false;
}
LLVM_FALLTHROUGH;
case DeclKind::Enum:
case DeclKind::Struct:
case DeclKind::Class:
case DeclKind::Protocol:
case DeclKind::OpaqueType:
case DeclKind::TypeAlias:
case DeclKind::GenericTypeParam:
case DeclKind::AssociatedType:
case DeclKind::Module:
case DeclKind::Var:
case DeclKind::Subscript:
case DeclKind::Constructor:
case DeclKind::Destructor:
case DeclKind::Func:
case DeclKind::Accessor:
case DeclKind::EnumElement:
return cast<ValueDecl>(this)->getInterfaceType()->hasError();
}

llvm_unreachable("Unknown decl kind");
}

void Decl::setInvalid() {
switch (getKind()) {
#define VALUE_DECL(ID, PARENT)
#define DECL(ID, PARENT) \
case DeclKind::ID:
#include "swift/AST/DeclNodes.def"
Bits.Decl.Invalid = true;
return;
case DeclKind::Enum:
case DeclKind::Struct:
case DeclKind::Class:
case DeclKind::Protocol:
case DeclKind::OpaqueType:
case DeclKind::TypeAlias:
case DeclKind::GenericTypeParam:
case DeclKind::AssociatedType:
case DeclKind::Module:
case DeclKind::Var:
case DeclKind::Param:
case DeclKind::Subscript:
case DeclKind::Constructor:
case DeclKind::Destructor:
case DeclKind::Func:
case DeclKind::Accessor:
case DeclKind::EnumElement:
cast<ValueDecl>(this)->setInterfaceType(ErrorType::get(getASTContext()));
return;
}

llvm_unreachable("Unknown decl kind");
}

void Decl::setDeclContext(DeclContext *DC) {
Context = DC;
}
Expand Down
11 changes: 6 additions & 5 deletions lib/AST/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,14 +212,15 @@ void SourceLookupCache::addToUnqualifiedLookupCache(Range decls,
if (!NTD->hasUnparsedMembers() || NTD->maybeHasOperatorDeclarations())
addToUnqualifiedLookupCache(NTD->getMembers(), true);

// Avoid populating the cache with the members of invalid extension
// declarations. These members can be used to point validation inside of
// a malformed context.
if (D->isInvalid()) continue;
if (auto *ED = dyn_cast<ExtensionDecl>(D)) {
// Avoid populating the cache with the members of invalid extension
// declarations. These members can be used to point validation inside of
// a malformed context.
if (ED->isInvalid()) continue;

if (auto *ED = dyn_cast<ExtensionDecl>(D))
if (!ED->hasUnparsedMembers() || ED->maybeHasOperatorDeclarations())
addToUnqualifiedLookupCache(ED->getMembers(), true);
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion lib/AST/NameLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ void DebuggerClient::anchor() {}
void AccessFilteringDeclConsumer::foundDecl(
ValueDecl *D, DeclVisibilityKind reason,
DynamicLookupInfo dynamicLookupInfo) {
if (D->isInvalid())
if (D->hasInterfaceType() && D->isInvalid())
return;
if (!D->isAccessibleFrom(DC))
return;
Expand Down
3 changes: 0 additions & 3 deletions lib/AST/TypeCheckRequests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1020,9 +1020,6 @@ void InterfaceTypeRequest::cacheResult(Type type) const {
assert(!type->hasTypeVariable() && "Type variable in interface type");
assert(!type->is<InOutType>() && "Interface type must be materializable");
assert(!type->hasArchetype() && "Archetype in interface type");

if (type->hasError())
decl->setInvalid();
}
decl->TypeAndAccess.setPointer(type);
}
Expand Down
3 changes: 0 additions & 3 deletions lib/AST/USRGeneration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,9 +258,6 @@ swift::USRGenerationRequest::evaluate(Evaluator &evaluator,
llvm::Expected<std::string>
swift::MangleLocalTypeDeclRequest::evaluate(Evaluator &evaluator,
const TypeDecl *D) const {
if (!D->getInterfaceType())
return std::string();

if (isa<ModuleDecl>(D))
return std::string(); // Ignore.

Expand Down
3 changes: 1 addition & 2 deletions lib/IDE/CodeCompletion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2431,8 +2431,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
addTypeAnnotation(Builder, AFT->getResult());
};

if (!AFD || !AFD->getInterfaceType() ||
!AFD->getInterfaceType()->is<AnyFunctionType>()) {
if (!AFD || !AFD->getInterfaceType()->is<AnyFunctionType>()) {
// Probably, calling closure type expression.
foundFunction(AFT);
addPattern();
Expand Down
15 changes: 6 additions & 9 deletions lib/IDE/ExprContextAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,13 +160,11 @@ Expr *swift::ide::findParsedExpr(const DeclContext *DC,

Type swift::ide::getReturnTypeFromContext(const DeclContext *DC) {
if (auto FD = dyn_cast<AbstractFunctionDecl>(DC)) {
if (FD->hasInterfaceType()) {
auto Ty = FD->getInterfaceType();
if (FD->getDeclContext()->isTypeContext())
Ty = FD->getMethodInterfaceType();
if (auto FT = Ty->getAs<AnyFunctionType>())
return DC->mapTypeIntoContext(FT->getResult());
}
auto Ty = FD->getInterfaceType();
if (FD->getDeclContext()->isTypeContext())
Ty = FD->getMethodInterfaceType();
if (auto FT = Ty->getAs<AnyFunctionType>())
return DC->mapTypeIntoContext(FT->getResult());
} else if (auto ACE = dyn_cast<AbstractClosureExpr>(DC)) {
if (ACE->getType() && !ACE->getType()->hasError())
return ACE->getResultType();
Expand Down Expand Up @@ -743,8 +741,7 @@ class ExprContextAnalyzer {
if (!AFD)
return;
auto param = AFD->getParameters()->get(initDC->getIndex());
if (param->hasInterfaceType())
recordPossibleType(AFD->mapTypeIntoContext(param->getInterfaceType()));
recordPossibleType(AFD->mapTypeIntoContext(param->getInterfaceType()));
break;
}
}
Expand Down
4 changes: 2 additions & 2 deletions lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4840,7 +4840,7 @@ Parser::parseDeclVarGetSet(Pattern *pattern, ParseDeclOptions Flags,
VarLoc, Identifier(),
CurDeclContext);
storage->setImplicit(true);
storage->setInvalid(true);
storage->setInvalid();

Pattern *pattern =
TypedPattern::createImplicit(Context, new (Context) NamedPattern(storage),
Expand All @@ -4850,7 +4850,7 @@ Parser::parseDeclVarGetSet(Pattern *pattern, ParseDeclOptions Flags,
auto binding = PatternBindingDecl::create(Context, StaticLoc,
StaticSpelling,
VarLoc, entry, CurDeclContext);
binding->setInvalid(true);
binding->setInvalid();
storage->setParentPatternBinding(binding);

Decls.push_back(binding);
Expand Down
1 change: 0 additions & 1 deletion lib/Sema/CSApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1940,7 +1940,6 @@ namespace {
auto maxFloatTypeDecl = tc.Context.get_MaxBuiltinFloatTypeDecl();

if (!maxFloatTypeDecl ||
!maxFloatTypeDecl->getInterfaceType() ||
!maxFloatTypeDecl->getDeclaredInterfaceType()->is<BuiltinFloatType>()) {
tc.diagnose(expr->getLoc(), diag::no_MaxBuiltinFloatType_found);
return nullptr;
Expand Down
16 changes: 0 additions & 16 deletions lib/Sema/CSDiag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -860,7 +860,6 @@ namespace {
llvm::DenseMap<TypeLoc*, Type> TypeLocTypes;
llvm::DenseMap<Pattern*, Type> PatternTypes;
llvm::DenseMap<ParamDecl*, Type> ParamDeclInterfaceTypes;
llvm::DenseSet<ValueDecl*> PossiblyInvalidDecls;
ExprTypeSaverAndEraser(const ExprTypeSaverAndEraser&) = delete;
void operator=(const ExprTypeSaverAndEraser&) = delete;
public:
Expand Down Expand Up @@ -909,10 +908,6 @@ namespace {
TS->ParamDeclInterfaceTypes[P] = P->getInterfaceType();
P->setInterfaceType(Type());
}
TS->PossiblyInvalidDecls.insert(P);

if (P->isInvalid())
P->setInvalid(false);
}

expr->setType(nullptr);
Expand Down Expand Up @@ -963,16 +958,10 @@ namespace {
paramDeclIfaceElt.first->setInterfaceType(paramDeclIfaceElt.second->getInOutObjectType());
}

if (!PossiblyInvalidDecls.empty())
for (auto D : PossiblyInvalidDecls)
if (D->hasInterfaceType())
D->setInvalid(D->getInterfaceType()->hasError());

// Done, don't do redundant work on destruction.
ExprTypes.clear();
TypeLocTypes.clear();
PatternTypes.clear();
PossiblyInvalidDecls.clear();
}

// On destruction, if a type got wiped out, reset it from null to its
Expand Down Expand Up @@ -1000,11 +989,6 @@ namespace {
paramDeclIfaceElt.first->setInterfaceType(
getParamBaseType(paramDeclIfaceElt));
}

if (!PossiblyInvalidDecls.empty())
for (auto D : PossiblyInvalidDecls)
if (D->hasInterfaceType())
D->setInvalid(D->getInterfaceType()->hasError());
}

private:
Expand Down
4 changes: 0 additions & 4 deletions lib/Sema/CSGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -961,8 +961,6 @@ namespace {
if (!decl)
return nullptr;

// FIXME(InterfaceTypeRequest): isInvalid() should be based on the interface type.
(void)decl->getInterfaceType();
if (decl->isInvalid())
return nullptr;

Expand Down Expand Up @@ -1427,8 +1425,6 @@ namespace {
// If the result is invalid, skip it.
// FIXME: Note this as invalid, in case we don't find a solution,
// so we don't let errors cascade further.
// FIXME(InterfaceTypeRequest): isInvalid() should be based on the interface type.
(void)decls[i]->getInterfaceType();
if (decls[i]->isInvalid())
continue;

Expand Down
6 changes: 0 additions & 6 deletions lib/Sema/CSSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5009,8 +5009,6 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName,
}

// If the result is invalid, skip it.
// FIXME(InterfaceTypeRequest): isInvalid() should be based on the interface type.
(void)decl->getInterfaceType();
if (decl->isInvalid()) {
result.markErrorAlreadyDiagnosed();
return;
Expand Down Expand Up @@ -5386,8 +5384,6 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName,
auto *cand = entry.getValueDecl();

// If the result is invalid, skip it.
// FIXME(InterfaceTypeRequest): isInvalid() should be based on the interface type.
(void)cand->getInterfaceType();
if (cand->isInvalid()) {
result.markErrorAlreadyDiagnosed();
return result;
Expand Down Expand Up @@ -7337,8 +7333,6 @@ ConstraintSystem::simplifyDynamicCallableApplicableFnConstraint(
// Record the 'dynamicallyCall` method overload set.
SmallVector<OverloadChoice, 4> choices;
for (auto candidate : candidates) {
// FIXME(InterfaceTypeRequest): isInvalid() should be based on the interface type.
(void)candidate->getInterfaceType();
if (candidate->isInvalid()) continue;
choices.push_back(
OverloadChoice(type2, candidate, FunctionRefKind::SingleApply));
Expand Down
5 changes: 0 additions & 5 deletions lib/Sema/ConstraintSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -825,11 +825,6 @@ Type ConstraintSystem::getUnopenedTypeOfReference(VarDecl *value, Type baseType,
return getType(param);

if (!var->hasInterfaceType()) {
if (!var->isInvalid()) {
TC.diagnose(var->getLoc(), diag::recursive_decl_reference,
var->getDescriptiveKind(), var->getName());
var->setInterfaceType(ErrorType::get(getASTContext()));
}
return ErrorType::get(TC.Context);
}

Expand Down
2 changes: 0 additions & 2 deletions lib/Sema/DerivedConformanceRawRepresentable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -482,8 +482,6 @@ static bool canSynthesizeRawRepresentable(DerivedConformance &derived) {
if (elt->hasAssociatedValues())
return false;

// FIXME(InterfaceTypeRequest): isInvalid() should be based on the interface type.
(void)elt->getInterfaceType();
if (elt->isInvalid()) {
return false;
}
Expand Down
6 changes: 0 additions & 6 deletions lib/Sema/LookupVisibleDecls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -765,9 +765,6 @@ class OverrideFilteringConsumer : public VisibleDeclConsumer {
if (VD->isRecursiveValidation())
continue;

// FIXME: This is used to compute isInvalid() below.
(void) VD->getInterfaceType();

auto &PossiblyConflicting = DeclsByName[VD->getBaseName()];

if (VD->isInvalid()) {
Expand Down Expand Up @@ -811,9 +808,6 @@ class OverrideFilteringConsumer : public VisibleDeclConsumer {
if (OtherVD->isRecursiveValidation())
continue;

// FIXME: This is used to compute isInvalid() below.
(void) OtherVD->getInterfaceType();

if (OtherVD->isInvalid())
continue;

Expand Down
Loading