Skip to content
Merged
4 changes: 1 addition & 3 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3212,9 +3212,7 @@ class ClassDecl : public NominalTypeDecl {
ClassDecl *getSuperclassDecl() const;

/// Set the superclass of this class.
void setSuperclass(Type superclass) {
LazySemanticInfo.Superclass.setPointerAndInt(superclass, true);
}
void setSuperclass(Type superclass);

/// Retrieve the status of circularity checking for class inheritance.
CircularityCheck getCircularityCheck() const {
Expand Down
11 changes: 7 additions & 4 deletions include/swift/AST/ParameterList.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,14 @@ class alignas(ParamDecl *) ParameterList final :
/// null type if one of the ParamDecls does not have a type set for it yet.
Type getType(const ASTContext &C) const;

/// Return a TupleType or ParenType for this parameter list written in terms
/// of interface types.
Type getInterfaceType(DeclContext *DC) const;

/// Return the full function type for a set of curried parameter lists that
/// returns the specified result type. This returns a null type if one of the
/// ParamDecls does not have a type set for it yet.
///
static Type getFullType(Type resultType, ArrayRef<ParameterList*> PL);
/// returns the specified result type written in terms of interface types.
static Type getFullInterfaceType(Type resultType, ArrayRef<ParameterList*> PL,
DeclContext *DC);


/// Return the full source range of this parameter.
Expand Down
6 changes: 2 additions & 4 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2622,8 +2622,6 @@ BoundGenericType *BoundGenericType::get(NominalTypeDecl *TheDecl,
ASTContext &C = TheDecl->getDeclContext()->getASTContext();
llvm::FoldingSetNodeID ID;
RecursiveTypeProperties properties;
if (Parent)
properties |= Parent->getRecursiveProperties();
BoundGenericType::Profile(ID, TheDecl, Parent, GenericArgs, properties);

auto arena = getArena(properties);
Expand Down Expand Up @@ -2657,8 +2655,8 @@ BoundGenericType *BoundGenericType::get(NominalTypeDecl *TheDecl,
} else {
auto theEnum = cast<EnumDecl>(TheDecl);
newType = new (C, arena) BoundGenericEnumType(theEnum, Parent, ArgsCopy,
IsCanonical ? &C : 0,
properties);
IsCanonical ? &C : 0,
properties);
}
C.Impl.getArena(arena).BoundGenericTypes.InsertNode(newType, InsertPos);

Expand Down
2 changes: 1 addition & 1 deletion lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -843,7 +843,7 @@ void ASTPrinter::printTypeRef(Type T, const TypeDecl *RefTo, Identifier Name) {
if (GP->isProtocolSelf())
Context = PrintNameContext::GenericParameter;
} else if (T && T->is<DynamicSelfType>()) {
assert(T->getAs<DynamicSelfType>()->getSelfType()->getAnyNominal() &&
assert(T->castTo<DynamicSelfType>()->getSelfType()->getAnyNominal() &&
"protocol Self handled as GenericTypeParamDecl");
Context = PrintNameContext::ClassDynamicSelf;
}
Expand Down
33 changes: 19 additions & 14 deletions lib/AST/ArchetypeBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2020,13 +2020,7 @@ void ArchetypeBuilder::dump(llvm::raw_ostream &out) {

Type ArchetypeBuilder::mapTypeIntoContext(const DeclContext *dc, Type type,
LazyResolver *resolver) {
// If the type is not dependent, there's nothing to map.
if (!type->hasTypeParameter())
return type;

auto genericParams = dc->getGenericParamsOfContext();
assert(genericParams && "Missing generic parameters for dependent context");

return mapTypeIntoContext(dc->getParentModule(), genericParams, type,
resolver);
}
Expand All @@ -2035,13 +2029,15 @@ Type ArchetypeBuilder::mapTypeIntoContext(Module *M,
GenericParamList *genericParams,
Type type,
LazyResolver *resolver) {
// If the type is not dependent, or we have no generic params, there's nothing
// to map.
if (!genericParams || !type->hasTypeParameter())
auto canType = type->getCanonicalType();
assert(!canType->hasArchetype() && "already have a contextual type");
if (!canType->hasTypeParameter())
return type;

assert(genericParams && "dependent type in non-generic context");

unsigned genericParamsDepth = genericParams->getDepth();
return type.transform([&](Type type) -> Type {
type = type.transform([&](Type type) -> Type {
// Map a generic parameter type to its archetype.
if (auto gpType = type->getAs<GenericTypeParamType>()) {
auto index = gpType->getIndex();
Expand All @@ -2064,7 +2060,7 @@ Type ArchetypeBuilder::mapTypeIntoContext(Module *M,
if (!myGenericParams->getAllArchetypes().empty())
return myGenericParams->getPrimaryArchetypes()[index];

// During type-checking, we may try to mapTypeInContext before
// During type-checking, we may try to mapTypeIntoContext before
// AllArchetypes has been built, so fall back to the generic params.
return myGenericParams->getParams()[index]->getArchetype();
}
Expand All @@ -2078,6 +2074,9 @@ Type ArchetypeBuilder::mapTypeIntoContext(Module *M,

return type;
});

assert(!type->hasTypeParameter() && "not fully substituted");
return type;
}

Type
Expand All @@ -2089,10 +2088,13 @@ ArchetypeBuilder::mapTypeOutOfContext(const DeclContext *dc, Type type) {
Type ArchetypeBuilder::mapTypeOutOfContext(ModuleDecl *M,
GenericParamList *genericParams,
Type type) {
// If the context is non-generic, we're done.
if (!genericParams)
auto canType = type->getCanonicalType();
assert(!canType->hasTypeParameter() && "already have an interface type");
if (!canType->hasArchetype())
return type;

assert(genericParams && "dependent type in non-generic context");

// Capture the archetype -> interface type mapping.
TypeSubstitutionMap subs;
for (auto params = genericParams; params != nullptr;
Expand All @@ -2102,7 +2104,10 @@ Type ArchetypeBuilder::mapTypeOutOfContext(ModuleDecl *M,
}
}

return type.subst(M, subs, SubstFlags::AllowLoweredTypes);
type = type.subst(M, subs, SubstFlags::AllowLoweredTypes);

assert(!type->hasArchetype() && "not fully substituted");
return type;
}

bool ArchetypeBuilder::addGenericSignature(GenericSignature *sig,
Expand Down
62 changes: 33 additions & 29 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1690,10 +1690,9 @@ Type ValueDecl::getInterfaceType() const {

if (auto assocType = dyn_cast<AssociatedTypeDecl>(this)) {
auto proto = cast<ProtocolDecl>(getDeclContext());
if (!proto->getProtocolSelf())
auto selfTy = proto->getSelfInterfaceType();
if (!selfTy)
return Type();
auto selfTy = proto->getProtocolSelf()->getDeclaredType();
assert(selfTy);
auto &ctx = getASTContext();
InterfaceTy = DependentMemberType::get(
selfTy,
Expand Down Expand Up @@ -2584,7 +2583,7 @@ bool ProtocolDecl::existentialConformsToSelfSlow() {
/// Determine whether the given type is the 'Self' generic parameter
/// of a protocol.
static bool isProtocolSelf(const ProtocolDecl *proto, Type type) {
return proto->getProtocolSelf()->getDeclaredType()->isEqual(type);
return proto->getSelfInterfaceType()->isEqual(type);
}

/// Classify usages of Self in the given type.
Expand Down Expand Up @@ -3600,6 +3599,8 @@ ParamDecl::ParamDecl(ParamDecl *PD)

/// \brief Retrieve the type of 'self' for the given context.
Type DeclContext::getSelfTypeInContext() const {
assert(isTypeContext());

// For a protocol or extension thereof, the type is 'Self'.
if (getAsProtocolOrProtocolExtensionContext()) {
// In the parser, generic parameters won't be wired up yet, just give up on
Expand All @@ -3613,6 +3614,8 @@ Type DeclContext::getSelfTypeInContext() const {

/// \brief Retrieve the interface type of 'self' for the given context.
Type DeclContext::getSelfInterfaceType() const {
assert(isTypeContext());

// For a protocol or extension thereof, the type is 'Self'.
if (getAsProtocolOrProtocolExtensionContext()) {
// In the parser, generic parameters won't be wired up yet, just give up on
Expand Down Expand Up @@ -3684,21 +3687,28 @@ ParamDecl *ParamDecl::createSelf(SourceLoc loc, DeclContext *DC,
bool isStaticMethod, bool isInOut) {
ASTContext &C = DC->getASTContext();
auto selfType = DC->getSelfTypeInContext();
auto selfInterfaceType = DC->getSelfInterfaceType();

assert(!!selfType == !!selfInterfaceType);

// If we have a selfType (i.e. we're not in the parser before we know such
// things, configure it.
if (selfType) {
if (isStaticMethod)
if (selfType && selfInterfaceType) {
if (isStaticMethod) {
selfType = MetatypeType::get(selfType);
selfInterfaceType = MetatypeType::get(selfInterfaceType);
}

if (isInOut)
if (isInOut) {
selfType = InOutType::get(selfType);
selfInterfaceType = InOutType::get(selfInterfaceType);
}
}

auto *selfDecl = new (C) ParamDecl(/*IsLet*/!isInOut, SourceLoc(),SourceLoc(),
Identifier(), loc, C.Id_self, selfType,DC);
selfDecl->setImplicit();
selfDecl->setInterfaceType(DC->getSelfInterfaceType());
selfDecl->setInterfaceType(selfInterfaceType);
return selfDecl;
}

Expand Down Expand Up @@ -3876,12 +3886,10 @@ static Type getSelfTypeForContainer(AbstractFunctionDecl *theMethod,
// For a protocol, the type of 'self' is the parameter type 'Self', not
// the protocol itself.
if (containerTy->is<ProtocolType>()) {
if (auto self = dc->getProtocolSelf()) {
if (wantInterfaceType)
selfTy = self->getDeclaredType();
else
selfTy = self->getArchetype();
}
if (wantInterfaceType)
selfTy = dc->getSelfInterfaceType();
else
selfTy = dc->getSelfTypeInContext();
} else
selfTy = containerTy;
}
Expand Down Expand Up @@ -4419,26 +4427,16 @@ DynamicSelfType *FuncDecl::getDynamicSelf() const {
if (!hasDynamicSelf())
return nullptr;

auto extType = getExtensionType();
if (extType->is<ProtocolType>())
return DynamicSelfType::get(getDeclContext()->getProtocolSelf()
->getArchetype(),
getASTContext());

return DynamicSelfType::get(extType, getASTContext());
return DynamicSelfType::get(getDeclContext()->getSelfTypeInContext(),
getASTContext());
}

DynamicSelfType *FuncDecl::getDynamicSelfInterface() const {
if (!hasDynamicSelf())
return nullptr;

auto extType = getDeclContext()->getDeclaredInterfaceType();
if (extType->is<ProtocolType>())
return DynamicSelfType::get(getDeclContext()->getProtocolSelf()
->getDeclaredType(),
getASTContext());

return DynamicSelfType::get(extType, getASTContext());
return DynamicSelfType::get(getDeclContext()->getSelfInterfaceType(),
getASTContext());
}

SourceRange FuncDecl::getSourceRange() const {
Expand Down Expand Up @@ -4771,3 +4769,9 @@ ClassDecl *ClassDecl::getSuperclassDecl() const {
return superclass->getClassOrBoundGenericClass();
return nullptr;
}

void ClassDecl::setSuperclass(Type superclass) {
assert((!superclass || !superclass->hasArchetype())
&& "superclass must be interface type");
LazySemanticInfo.Superclass.setPointerAndInt(superclass, true);
}
4 changes: 2 additions & 2 deletions lib/AST/LookupVisibleDecls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,7 @@ class OverrideFilteringConsumer : public VisibleDeclConsumer {
}

// Does it make sense to substitute types?
bool shouldSubst = !isa<UnboundGenericType>(BaseTy.getPointer()) &&
bool shouldSubst = !BaseTy->hasUnboundGenericType() &&
!isa<AnyMetatypeType>(BaseTy.getPointer()) &&
!BaseTy->isAnyExistentialType();
ModuleDecl *M = DC->getParentModule();
Expand Down Expand Up @@ -831,7 +831,7 @@ void swift::lookupVisibleDecls(VisibleDeclConsumer &Consumer,
DC = DC->getParent();

if (DC->getAsProtocolExtensionContext())
ExtendedType = DC->getProtocolSelf()->getArchetype();
ExtendedType = DC->getSelfTypeInContext();

if (auto *FD = dyn_cast<FuncDecl>(AFD))
if (FD->isStatic())
Expand Down
9 changes: 2 additions & 7 deletions lib/AST/NameLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -436,8 +436,7 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,

if (AFD->getExtensionType()) {
if (AFD->getDeclContext()->getAsProtocolOrProtocolExtensionContext()) {
ExtendedType = AFD->getDeclContext()->getProtocolSelf()
->getArchetype();
ExtendedType = AFD->getDeclContext()->getSelfTypeInContext();

// Fallback path.
if (!ExtendedType)
Expand Down Expand Up @@ -481,11 +480,7 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,
if (!isCascadingUse.hasValue())
isCascadingUse = ACE->isCascadingContextForLookup(false);
} else if (ExtensionDecl *ED = dyn_cast<ExtensionDecl>(DC)) {
if (ED->getAsProtocolOrProtocolExtensionContext()) {
ExtendedType = ED->getProtocolSelf()->getArchetype();
} else {
ExtendedType = ED->getExtendedType();
}
ExtendedType = ED->getSelfTypeInContext();

BaseDecl = ED->getAsNominalTypeOrNominalTypeExtensionContext();
MetaBaseDecl = BaseDecl;
Expand Down
41 changes: 36 additions & 5 deletions lib/AST/Parameter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,23 +131,54 @@ Type ParameterList::getType(const ASTContext &C) const {
return TupleType::get(argumentInfo, C);
}

/// Hack to deal with the fact that Sema/CodeSynthesis.cpp creates ParamDecls
/// containing contextual types.
Type ParameterList::getInterfaceType(DeclContext *DC) const {
auto &C = DC->getASTContext();

if (size() == 0)
return TupleType::getEmpty(C);

SmallVector<TupleTypeElt, 8> argumentInfo;

for (auto P : *this) {
assert(P->hasType());

Type type;
if (P->hasInterfaceType())
type = P->getInterfaceType();
else if (!P->getTypeLoc().hasLocation())
type = ArchetypeBuilder::mapTypeOutOfContext(DC, P->getType());
else
type = P->getType();
assert(!type->hasArchetype());

argumentInfo.push_back({
type, P->getArgumentName(),
P->getDefaultArgumentKind(), P->isVariadic()
});
}

return TupleType::get(argumentInfo, C);
}


/// Return the full function type for a set of curried parameter lists that
/// returns the specified result type. This returns a null type if one of the
/// ParamDecls does not have a type set for it yet.
///
Type ParameterList::getFullType(Type resultType, ArrayRef<ParameterList*> PLL) {
Type ParameterList::getFullInterfaceType(Type resultType,
ArrayRef<ParameterList*> PLL,
DeclContext *DC) {
auto result = resultType;
auto &C = result->getASTContext();

for (auto PL : reversed(PLL)) {
auto paramType = PL->getType(C);
if (!paramType) return Type();
auto paramType = PL->getInterfaceType(DC);
result = FunctionType::get(paramType, result);
}
return result;
}


/// Return the full source range of this parameter list.
SourceRange ParameterList::getSourceRange() const {
// If we have locations for the parens, then they define our range.
Expand Down
Loading