diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 7c9730e1eb3b5..12c368119a67f 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -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 { diff --git a/include/swift/AST/ParameterList.h b/include/swift/AST/ParameterList.h index 0662fefc56c2c..c965de3f72e7b 100644 --- a/include/swift/AST/ParameterList.h +++ b/include/swift/AST/ParameterList.h @@ -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 PL); + /// returns the specified result type written in terms of interface types. + static Type getFullInterfaceType(Type resultType, ArrayRef PL, + DeclContext *DC); /// Return the full source range of this parameter. diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 9a9fc3b4ecef2..c6625816b75ea 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -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); @@ -2657,8 +2655,8 @@ BoundGenericType *BoundGenericType::get(NominalTypeDecl *TheDecl, } else { auto theEnum = cast(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); diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index c29673a465e59..71295b8734374 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -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()) { - assert(T->getAs()->getSelfType()->getAnyNominal() && + assert(T->castTo()->getSelfType()->getAnyNominal() && "protocol Self handled as GenericTypeParamDecl"); Context = PrintNameContext::ClassDynamicSelf; } diff --git a/lib/AST/ArchetypeBuilder.cpp b/lib/AST/ArchetypeBuilder.cpp index 36b651e3d85e2..699078f2c894a 100644 --- a/lib/AST/ArchetypeBuilder.cpp +++ b/lib/AST/ArchetypeBuilder.cpp @@ -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); } @@ -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()) { auto index = gpType->getIndex(); @@ -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(); } @@ -2078,6 +2074,9 @@ Type ArchetypeBuilder::mapTypeIntoContext(Module *M, return type; }); + + assert(!type->hasTypeParameter() && "not fully substituted"); + return type; } Type @@ -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; @@ -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, diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 5fbcb54ab1443..8367ebe462ff8 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1690,10 +1690,9 @@ Type ValueDecl::getInterfaceType() const { if (auto assocType = dyn_cast(this)) { auto proto = cast(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, @@ -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. @@ -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 @@ -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 @@ -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; } @@ -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()) { - 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; } @@ -4419,26 +4427,16 @@ DynamicSelfType *FuncDecl::getDynamicSelf() const { if (!hasDynamicSelf()) return nullptr; - auto extType = getExtensionType(); - if (extType->is()) - 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()) - return DynamicSelfType::get(getDeclContext()->getProtocolSelf() - ->getDeclaredType(), - getASTContext()); - - return DynamicSelfType::get(extType, getASTContext()); + return DynamicSelfType::get(getDeclContext()->getSelfInterfaceType(), + getASTContext()); } SourceRange FuncDecl::getSourceRange() const { @@ -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); +} diff --git a/lib/AST/LookupVisibleDecls.cpp b/lib/AST/LookupVisibleDecls.cpp index f2413c5875cc7..ee2bdc0ad0a67 100644 --- a/lib/AST/LookupVisibleDecls.cpp +++ b/lib/AST/LookupVisibleDecls.cpp @@ -716,7 +716,7 @@ class OverrideFilteringConsumer : public VisibleDeclConsumer { } // Does it make sense to substitute types? - bool shouldSubst = !isa(BaseTy.getPointer()) && + bool shouldSubst = !BaseTy->hasUnboundGenericType() && !isa(BaseTy.getPointer()) && !BaseTy->isAnyExistentialType(); ModuleDecl *M = DC->getParentModule(); @@ -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(AFD)) if (FD->isStatic()) diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index aac2a34b40528..b5530a86a42ff 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -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) @@ -481,11 +480,7 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC, if (!isCascadingUse.hasValue()) isCascadingUse = ACE->isCascadingContextForLookup(false); } else if (ExtensionDecl *ED = dyn_cast(DC)) { - if (ED->getAsProtocolOrProtocolExtensionContext()) { - ExtendedType = ED->getProtocolSelf()->getArchetype(); - } else { - ExtendedType = ED->getExtendedType(); - } + ExtendedType = ED->getSelfTypeInContext(); BaseDecl = ED->getAsNominalTypeOrNominalTypeExtensionContext(); MetaBaseDecl = BaseDecl; diff --git a/lib/AST/Parameter.cpp b/lib/AST/Parameter.cpp index 18ed78fe8e0bb..83bec7acaa09c 100644 --- a/lib/AST/Parameter.cpp +++ b/lib/AST/Parameter.cpp @@ -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 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 PLL) { +Type ParameterList::getFullInterfaceType(Type resultType, + ArrayRef 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. diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 9df419c6724f8..d2cc1b7dbbf6a 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -296,8 +296,7 @@ ArrayRef TypeBase::getAllGenericArgs(SmallVectorImpl &scratch) { if (auto protoType = type->getAs()) { auto proto = protoType->getDecl(); allGenericArgs.push_back( - llvm::makeArrayRef( - proto->getProtocolSelf()->getDeclaredInterfaceType())); + llvm::makeArrayRef(proto->getSelfInterfaceType())); // Continue up to the parent. type = protoType->getParent(); @@ -1598,76 +1597,37 @@ bool TypeBase::isSpelledLike(Type other) { } Type TypeBase::getSuperclass(LazyResolver *resolver) { - // If this type is either a bound generic type, or a nested type inside a - // bound generic type, we will need to fish out the generic parameters. - Type specializedTy; - - ClassDecl *classDecl; - if (auto classTy = getAs()) { - classDecl = classTy->getDecl(); - if (auto parentTy = classTy->getParent()) { - if (parentTy->isSpecialized()) - specializedTy = parentTy; - } - } else if (auto boundTy = getAs()) { - classDecl = dyn_cast(boundTy->getDecl()); - specializedTy = this; - } else if (auto archetype = getAs()) { - return archetype->getSuperclass(); - } else if (auto dynamicSelfTy = getAs()) { - return dynamicSelfTy->getSelfType(); - } else { - // No other types have superclasses. - return nullptr; - } + ClassDecl *classDecl = getClassOrBoundGenericClass(); - // Get the superclass type. If the class is generic, the superclass type may - // contain generic type parameters from the signature of the class. - Type superclassTy; - if (classDecl) - superclassTy = classDecl->getSuperclass(); + // Handle some special non-class types here. + if (!classDecl) { + if (auto archetype = getAs()) + return archetype->getSuperclass(); - // If there's no superclass, return a null type. If the class is not in a - // generic context, return the original superclass type. - if (!superclassTy || !classDecl->isGenericContext()) - return superclassTy; + if (auto dynamicSelfTy = getAs()) + return dynamicSelfTy->getSelfType(); - // The class is defined in a generic context, so its superclass type may refer - // to generic parameters of the class or some parent type of the class. Map - // it to a contextual type. + // No other types have superclasses. + return nullptr; + } - // FIXME: Lame to rely on archetypes in the substitution below. - superclassTy = ArchetypeBuilder::mapTypeIntoContext(classDecl, superclassTy); + // We have a class, so get the superclass type. + // + // If the derived class is generic, the superclass type may contain + // generic type parameters from the signature of the derived class. + Type superclassTy = classDecl->getSuperclass(); - // If the type does not bind any generic parameters, return the superclass - // type as-is. - if (!specializedTy) + // If there's no superclass, or it is fully concrete, we're done. + if (!superclassTy || !superclassTy->hasTypeParameter()) return superclassTy; - // If the type is specialized, we need to gather all of the substitutions - // for the type and any parent types. - TypeSubstitutionMap substitutions; - while (specializedTy) { - if (auto nominalTy = specializedTy->getAs()) { - specializedTy = nominalTy->getParent(); - continue; - } - - // Introduce substitutions for each of the generic parameters/arguments. - auto boundTy = specializedTy->castTo(); - auto gp = boundTy->getDecl()->getGenericParams()->getParams(); - for (unsigned i = 0, n = boundTy->getGenericArgs().size(); i != n; ++i) { - auto archetype = gp[i]->getArchetype(); - substitutions[archetype] = boundTy->getGenericArgs()[i]; - } - - specializedTy = boundTy->getParent(); - } - - // Perform substitutions into the superclass type to yield the - // substituted superclass type. + // Gather substitutions from the self type, and apply them to the original + // superclass type to form the substituted superclass type. Module *module = classDecl->getModuleContext(); - return superclassTy.subst(module, substitutions, None); + auto *sig = classDecl->getGenericSignatureOfContext(); + auto subs = sig->getSubstitutionMap(gatherAllSubstitutions(module, resolver)); + + return superclassTy.subst(module, subs, None); } bool TypeBase::isExactSuperclassOf(Type ty, LazyResolver *resolver) { @@ -2606,8 +2566,8 @@ ArchetypeType::NestedType ArchetypeType::getNestedType(Identifier Name) const { conformanceType = metatypeType->getInstanceType().getPointer(); if (auto protocolType = dyn_cast(conformanceType)) { - conformanceType = protocolType->getDecl()->getProtocolSelf() - ->getArchetype(); + conformanceType = protocolType->getDecl() + ->getSelfTypeInContext().getPointer(); } } @@ -2965,8 +2925,9 @@ TypeSubstitutionMap TypeBase::getMemberSubstitutions(const DeclContext *dc) { if (dc->getAsProtocolOrProtocolExtensionContext()) { // FIXME: This feels painfully inefficient. We're creating a dense map // for a single substitution. - substitutions[dc->getProtocolSelf()->getDeclaredType() - ->getCanonicalType()->castTo()] + substitutions[dc->getSelfInterfaceType() + ->getCanonicalType() + ->castTo()] = baseTy; return substitutions; } diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index 953151831172e..a28cdb21198eb 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -347,7 +347,7 @@ makeEnumRawValueConstructor(ClangImporter::Implementation &Impl, auto enumTy = enumDecl->getDeclaredTypeInContext(); auto metaTy = MetatypeType::get(enumTy); - auto selfDecl = ParamDecl::createUnboundSelf(SourceLoc(), enumDecl, + auto selfDecl = ParamDecl::createSelf(SourceLoc(), enumDecl, /*static*/false, /*inout*/true); auto param = new (C) ParamDecl(/*let*/ true, SourceLoc(), @@ -413,7 +413,7 @@ static FuncDecl *makeEnumRawValueGetter(ClangImporter::Implementation &Impl, VarDecl *rawValueDecl) { ASTContext &C = Impl.SwiftContext; - auto selfDecl = ParamDecl::createUnboundSelf(SourceLoc(), enumDecl); + auto selfDecl = ParamDecl::createSelf(SourceLoc(), enumDecl); ParameterList *params[] = { ParameterList::createWithoutLoc(selfDecl), @@ -428,8 +428,8 @@ static FuncDecl *makeEnumRawValueGetter(ClangImporter::Implementation &Impl, /*GenericParams=*/nullptr, params, Type(), TypeLoc::withoutLoc(enumDecl->getRawType()), enumDecl); getterDecl->setImplicit(); - getterDecl->setType(ParameterList::getFullType(enumDecl->getRawType(), - params)); + getterDecl->setType(ParameterList::getFullInterfaceType(enumDecl->getRawType(), + params, enumDecl)); getterDecl->setBodyResultType(enumDecl->getRawType()); getterDecl->setAccessibility(Accessibility::Public); @@ -470,7 +470,7 @@ static FuncDecl *makeNewtypeBridgedRawValueGetter( VarDecl *storedVar) { ASTContext &C = Impl.SwiftContext; - auto selfDecl = ParamDecl::createUnboundSelf(SourceLoc(), structDecl); + auto selfDecl = ParamDecl::createSelf(SourceLoc(), structDecl); ParameterList *params[] = { ParameterList::createWithoutLoc(selfDecl), @@ -488,7 +488,8 @@ static FuncDecl *makeNewtypeBridgedRawValueGetter( params, Type(), TypeLoc::withoutLoc(computedType), structDecl); getterDecl->setImplicit(); - getterDecl->setType(ParameterList::getFullType(computedType, params)); + getterDecl->setType(ParameterList::getFullInterfaceType(computedType, params, + structDecl)); getterDecl->setBodyResultType(computedType); getterDecl->setAccessibility(Accessibility::Public); @@ -517,7 +518,7 @@ static FuncDecl *makeFieldGetterDecl(ClangImporter::Implementation &Impl, VarDecl *importedFieldDecl, ClangNode clangNode = ClangNode()) { auto &C = Impl.SwiftContext; - auto selfDecl = ParamDecl::createUnboundSelf(SourceLoc(), importedDecl); + auto selfDecl = ParamDecl::createSelf(SourceLoc(), importedDecl); ParameterList *params[] = { ParameterList::createWithoutLoc(selfDecl), @@ -534,7 +535,8 @@ static FuncDecl *makeFieldGetterDecl(ClangImporter::Implementation &Impl, /*GenericParams=*/nullptr, params, Type(), TypeLoc::withoutLoc(getterType), importedDecl, clangNode); getterDecl->setAccessibility(Accessibility::Public); - getterDecl->setType(ParameterList::getFullType(getterType, params)); + getterDecl->setType(ParameterList::getFullInterfaceType(getterType, params, + importedDecl)); getterDecl->setBodyResultType(getterType); return getterDecl; @@ -545,7 +547,7 @@ static FuncDecl *makeFieldSetterDecl(ClangImporter::Implementation &Impl, VarDecl *importedFieldDecl, ClangNode clangNode = ClangNode()) { auto &C = Impl.SwiftContext; - auto selfDecl = ParamDecl::createUnboundSelf(SourceLoc(), importedDecl, + auto selfDecl = ParamDecl::createSelf(SourceLoc(), importedDecl, /*isStatic*/false, /*isInOut*/true); auto newValueDecl = new (C) ParamDecl(/*isLet */ true,SourceLoc(),SourceLoc(), Identifier(), SourceLoc(), C.Id_value, @@ -567,7 +569,8 @@ static FuncDecl *makeFieldSetterDecl(ClangImporter::Implementation &Impl, /*GenericParams=*/nullptr, params, Type(), TypeLoc::withoutLoc(voidTy), importedDecl, clangNode); - setterDecl->setType(ParameterList::getFullType(voidTy, params)); + setterDecl->setType(ParameterList::getFullInterfaceType(voidTy, params, + importedDecl)); setterDecl->setBodyResultType(voidTy); setterDecl->setAccessibility(Accessibility::Public); setterDecl->setMutating(); @@ -946,9 +949,10 @@ static bool addErrorDomain(NominalTypeDecl *swiftDecl, DeclRefExpr(ConcreteDeclRef(swiftValueDecl), {}, isImplicit); ParameterList *params[] = { ParameterList::createWithoutLoc( - ParamDecl::createUnboundSelf(SourceLoc(), swiftDecl, isStatic)), + ParamDecl::createSelf(SourceLoc(), swiftDecl, isStatic)), ParameterList::createEmpty(C)}; - auto toStringTy = ParameterList::getFullType(stringTy, params); + auto toStringTy = ParameterList::getFullInterfaceType(stringTy, params, + swiftDecl); FuncDecl *getterDecl = FuncDecl::create(C, /*StaticLoc=*/SourceLoc(), StaticSpellingKind::None, @@ -1666,7 +1670,7 @@ namespace { auto &context = Impl.SwiftContext; // Create the 'self' declaration. - auto selfDecl = ParamDecl::createUnboundSelf(SourceLoc(), structDecl, + auto selfDecl = ParamDecl::createSelf(SourceLoc(), structDecl, /*static*/false, /*inout*/true); // self & param. @@ -1907,7 +1911,7 @@ namespace { auto &context = Impl.SwiftContext; // Create the 'self' declaration. - auto selfDecl = ParamDecl::createUnboundSelf(SourceLoc(), structDecl, + auto selfDecl = ParamDecl::createSelf(SourceLoc(), structDecl, /*static*/false, /*inout*/true); // Construct the set of parameters from the list of members. @@ -2799,9 +2803,9 @@ namespace { } ParameterList *getNonSelfParamList( - const clang::FunctionDecl *decl, Optional selfIdx, - ArrayRef argNames, bool allowNSUIntegerAsInt, - bool isAccessor) { + DeclContext *dc, const clang::FunctionDecl *decl, + Optional selfIdx, ArrayRef argNames, + bool allowNSUIntegerAsInt, bool isAccessor) { if (bool(selfIdx)) { assert(((decl->getNumParams() == argNames.size() + 1) || isAccessor) && (*selfIdx < decl->getNumParams()) && "where's self?"); @@ -2815,7 +2819,7 @@ namespace { continue; nonSelfParams.push_back(decl->getParamDecl(i)); } - return Impl.importFunctionParameterList(decl, nonSelfParams, + return Impl.importFunctionParameterList(dc, decl, nonSelfParams, decl->isVariadic(), allowNSUIntegerAsInt, argNames); } @@ -2852,20 +2856,20 @@ namespace { argNames.front(), Impl.SwiftContext.TheEmptyTupleType, dc)); } else { parameterList = Impl.importFunctionParameterList( - decl, {decl->param_begin(), decl->param_end()}, decl->isVariadic(), - allowNSUIntegerAsInt, argNames); + dc, decl, {decl->param_begin(), decl->param_end()}, + decl->isVariadic(), allowNSUIntegerAsInt, argNames); } if (!parameterList) return nullptr; bool selfIsInOut = - !dc->getDeclaredTypeOfContext()->hasReferenceSemantics(); - auto selfParam = ParamDecl::createUnboundSelf(SourceLoc(), dc, /*static=*/false, + !dc->getDeclaredInterfaceType()->hasReferenceSemantics(); + auto selfParam = ParamDecl::createSelf(SourceLoc(), dc, /*static=*/false, /*inout=*/selfIsInOut); OptionalTypeKind initOptionality; auto resultType = Impl.importFunctionReturnType( - decl, decl->getReturnType(), allowNSUIntegerAsInt); + dc, decl, decl->getReturnType(), allowNSUIntegerAsInt); (void)resultType->getAnyOptionalObjectType(initOptionality); auto result = Impl.createDeclWithClangNode( @@ -2927,14 +2931,15 @@ namespace { } bodyParams.push_back(ParameterList::createWithoutLoc( - ParamDecl::createUnboundSelf(SourceLoc(), dc, !selfIdx.hasValue(), + ParamDecl::createSelf(SourceLoc(), dc, !selfIdx.hasValue(), selfIsInOut))); bodyParams.push_back(getNonSelfParamList( - decl, selfIdx, name.getArgumentNames(), allowNSUIntegerAsInt, !name)); + dc, decl, selfIdx, name.getArgumentNames(), allowNSUIntegerAsInt, !name)); auto swiftResultTy = Impl.importFunctionReturnType( - decl, decl->getReturnType(), allowNSUIntegerAsInt); - auto fnType = ParameterList::getFullType(swiftResultTy, bodyParams); + dc, decl, decl->getReturnType(), allowNSUIntegerAsInt); + auto fnType = ParameterList::getFullInterfaceType(swiftResultTy, bodyParams, + dc); auto loc = Impl.importSourceLoc(decl->getLocation()); auto nameLoc = Impl.importSourceLoc(decl->getLocation()); @@ -2949,7 +2954,7 @@ namespace { if (auto proto = dc->getAsProtocolOrProtocolExtensionContext()) { Type interfaceType; std::tie(fnType, interfaceType) = - getProtocolMethodType(proto, fnType->castTo()); + getGenericMethodType(proto, fnType->castTo()); result->setType(fnType); result->setInterfaceType(interfaceType); result->setGenericSignature(proto->getGenericSignature()); @@ -3214,7 +3219,8 @@ namespace { // Import the function type. If we have parameters, make sure their names // get into the resulting function type. ParameterList *bodyParams = nullptr; - Type type = Impl.importFunctionType(decl, + Type type = Impl.importFunctionType(dc, + decl, decl->getReturnType(), { decl->param_begin(), decl->param_size() }, @@ -3644,14 +3650,9 @@ namespace { auto selfVar = ParamDecl::createSelf(SourceLoc(), dc, /*isStatic*/!isInstance); bodyParams.push_back(ParameterList::createWithoutLoc(selfVar)); - Type selfContextType; - if (dc->getAsProtocolOrProtocolExtensionContext()) { - selfContextType = dc->getProtocolSelf()->getArchetype(); - } else { - selfContextType = dc->getDeclaredTypeInContext(); - } + Type selfInterfaceType = dc->getSelfInterfaceType(); if (!isInstance) { - selfContextType = MetatypeType::get(selfContextType); + selfInterfaceType = MetatypeType::get(selfInterfaceType); } SpecialMethodKind kind = SpecialMethodKind::Regular; @@ -3709,7 +3710,7 @@ namespace { // in Swift as DynamicSelf, do so. if (decl->hasRelatedResultType()) { result->setDynamicSelf(true); - resultTy = result->getDynamicSelf(); + resultTy = result->getDynamicSelfInterface(); assert(resultTy && "failed to get dynamic self"); Type dynamicSelfTy = result->getDynamicSelfInterface(); @@ -3728,23 +3729,14 @@ namespace { auto methodTy = type->castTo(); type = FunctionType::get(methodTy->getInput(), resultTy, methodTy->getExtInfo()); - - // Create the interface type of the method. - interfaceType = FunctionType::get(methodTy->getInput(), dynamicSelfTy, - methodTy->getExtInfo()); - interfaceType = FunctionType::get(selfVar->getType(), interfaceType); } // Add the 'self' parameter to the function type. - type = FunctionType::get(selfContextType, type); + type = FunctionType::get(selfInterfaceType, type); - if (auto proto = dyn_cast(dc)) { - std::tie(type, interfaceType) - = getProtocolMethodType(proto, type->castTo()); - } else if (dc->isGenericContext()) { + if (dc->isGenericContext()) { std::tie(type, interfaceType) = getGenericMethodType(dc, type->castTo()); - selfVar->overwriteType(type->castTo()->getInput()); } result->setBodyResultType(resultTy); @@ -3920,9 +3912,9 @@ namespace { } bool redundant; - auto result = importConstructor(objcMethod, dc, implicit, kind, required, - selector, importedName, params, - variadic, redundant); + auto result = importConstructor(objcMethod, dc, implicit, kind, required, + selector, importedName, params, + variadic, redundant); // If this is a Swift 2 stub, mark it as such. if (result && swift3Name) @@ -4044,13 +4036,12 @@ namespace { redundant = false; // Figure out the type of the container. - auto containerTy = dc->getDeclaredTypeInContext(); - assert(containerTy && "Method in non-type context?"); - auto nominalOwner = containerTy->getAnyNominal(); + auto ownerNominal = dc->getAsNominalTypeOrNominalTypeExtensionContext(); + assert(ownerNominal && "Method in non-type context?"); // Find the interface, if we can. const clang::ObjCInterfaceDecl *interface = nullptr; - if (auto classDecl = containerTy->getClassOrBoundGenericClass()) { + if (auto classDecl = dyn_cast(ownerNominal)) { interface = dyn_cast_or_null( classDecl->getClangDecl()); } @@ -4079,8 +4070,8 @@ namespace { // Add the implicit 'self' parameter patterns. SmallVector bodyParams; - auto selfMetaVar = ParamDecl::createUnboundSelf(SourceLoc(), dc, /*static*/true); - auto selfTy = dc->getDeclaredTypeInContext(); + auto selfMetaVar = ParamDecl::createSelf(SourceLoc(), dc, /*static*/true); + auto selfTy = dc->getSelfInterfaceType(); auto selfMetaTy = MetatypeType::get(selfTy); bodyParams.push_back(ParameterList::createWithoutLoc(selfMetaVar)); @@ -4124,7 +4115,7 @@ namespace { // the same name. Type allocParamType = allocType->castTo()->getResult() ->castTo()->getInput(); - for (auto other : nominalOwner->lookupDirect(name)) { + for (auto other : ownerNominal->lookupDirect(name)) { auto ctor = dyn_cast(other); if (!ctor || ctor->isInvalid() || ctor->getAttrs().isUnavailable(Impl.SwiftContext) || @@ -4197,7 +4188,7 @@ namespace { if (known != Impl.Constructors.end()) return known->second; - auto *selfVar = ParamDecl::createUnboundSelf(SourceLoc(), dc); + auto *selfVar = ParamDecl::createSelf(SourceLoc(), dc); // Create the actual constructor. auto result = Impl.createDeclWithClangNode(objcMethod, @@ -4211,23 +4202,12 @@ namespace { // Make the constructor declaration immediately visible in its // class or protocol type. - nominalOwner->makeMemberVisible(result); + ownerNominal->makeMemberVisible(result); addObjCAttribute(result, selector); - // Fix the types when we've imported into a protocol. - if (auto proto = dyn_cast(dc)) { - Type interfaceAllocType; - Type interfaceInitType; - std::tie(allocType, interfaceAllocType) - = getProtocolMethodType(proto, allocType->castTo()); - std::tie(initType, interfaceInitType) - = getProtocolMethodType(proto, initType->castTo()); - - result->setInitializerInterfaceType(interfaceInitType); - result->setInterfaceType(interfaceAllocType); - result->setGenericSignature(dc->getGenericSignatureOfContext()); - } else if (dc->isGenericContext()) { + // Calculate the function type of the result. + if (dc->isGenericContext()) { Type interfaceAllocType; Type interfaceInitType; std::tie(allocType, interfaceAllocType) @@ -4238,7 +4218,6 @@ namespace { result->setInitializerInterfaceType(interfaceInitType); result->setInterfaceType(interfaceAllocType); result->setGenericSignature(dc->getGenericSignatureOfContext()); - selfVar->overwriteType(initType->castTo()->getInput()); } result->setType(allocType); @@ -4322,62 +4301,22 @@ namespace { return cast(pattern)->getDecl(); } - /// Retrieves the type and interface type for a protocol or - /// protocol extension method given the computed type of that - /// method. - std::pair getProtocolMethodType(DeclContext *dc, - AnyFunctionType *fnType) { - Type type = PolymorphicFunctionType::get(fnType->getInput(), - fnType->getResult(), - dc->getGenericParamsOfContext()); - - // Figure out the curried 'self' type for the interface type. It's always - // either the generic parameter type 'Self' or a metatype thereof. - auto selfDecl = dc->getProtocolSelf(); - auto selfTy = selfDecl->getDeclaredType(); - auto interfaceInputTy = selfTy; - auto inputTy = fnType->getInput(); - if (auto tupleTy = inputTy->getAs()) { - if (tupleTy->getNumElements() == 1) - inputTy = tupleTy->getElementType(0); - } - if (inputTy->is()) - interfaceInputTy = MetatypeType::get(interfaceInputTy); - - auto selfArchetype = selfDecl->getArchetype(); - auto interfaceResultTy = fnType->getResult().transform( - [&](Type type) -> Type { - if (type->is() || type->isEqual(selfArchetype)) { - return DynamicSelfType::get(selfTy, Impl.SwiftContext); - } - - return type; - }); - - Type interfaceType = GenericFunctionType::get( - dc->getGenericSignatureOfContext(), - interfaceInputTy, - interfaceResultTy, - AnyFunctionType::ExtInfo()); - return { type, interfaceType }; - } - - /// Retrieves the type and interface type for a generic class or class - /// extension method, given the computed type of that method. std::pair getGenericMethodType(DeclContext *dc, AnyFunctionType *fnType) { - Type inputType = fnType->getInput(); - Type interfaceInputType = - ArchetypeBuilder::mapTypeOutOfContext(dc, inputType); - Type resultType = fnType->getResult(); - Type interfaceResultType = - ArchetypeBuilder::mapTypeOutOfContext(dc, resultType); + assert(!fnType->hasArchetype()); - Type interfaceType = GenericFunctionType::get( - dc->getGenericSignatureOfContext(), interfaceInputType, - interfaceResultType, AnyFunctionType::ExtInfo()); + Type inputType = ArchetypeBuilder::mapTypeIntoContext( + dc, fnType->getInput()); + Type resultType = ArchetypeBuilder::mapTypeIntoContext( + dc, fnType->getResult()); Type type = PolymorphicFunctionType::get(inputType, resultType, dc->getGenericParamsOfContext()); + + Type interfaceType = GenericFunctionType::get( + dc->getGenericSignatureOfContext(), + fnType->getInput(), fnType->getResult(), + AnyFunctionType::ExtInfo()); + return { type, interfaceType }; } @@ -4395,18 +4334,13 @@ namespace { }; // Form the type of the getter. - auto getterType = ParameterList::getFullType(elementTy, getterArgs); + auto getterType = + ParameterList::getFullInterfaceType(elementTy, getterArgs, dc); - // If we're in a protocol, the getter thunk will be polymorphic. Type interfaceType; - if (dc->getAsProtocolOrProtocolExtensionContext()) { - std::tie(getterType, interfaceType) - = getProtocolMethodType(dc, getterType->castTo()); - } else if (dc->isGenericContext()) { + if (dc->isGenericContext()) { std::tie(getterType, interfaceType) = getGenericMethodType(dc, getterType->castTo()); - getterArgs[0]->get(0)->overwriteType( - getterType->castTo()->getInput()); } // Create the getter thunk. @@ -4432,7 +4366,7 @@ namespace { } /// Build a declaration for an Objective-C subscript setter. - FuncDecl *buildSubscriptSetterDecl(const FuncDecl *setter, Type elementTy, + FuncDecl *buildSubscriptSetterDecl(const FuncDecl *setter, Type elementInterfaceTy, DeclContext *dc, ParamDecl *index) { auto &C = Impl.SwiftContext; auto loc = setter->getLoc(); @@ -4448,13 +4382,15 @@ namespace { // 'self' auto selfDecl = ParamDecl::createSelf(SourceLoc(), dc); + auto elementTy = ArchetypeBuilder::mapTypeIntoContext( + dc, elementInterfaceTy); auto paramVarDecl = new (C) ParamDecl(/*isLet=*/false, SourceLoc(), SourceLoc(), Identifier(),loc, valueIndex->get(0)->getName(), elementTy, dc); - - + paramVarDecl->setInterfaceType(elementInterfaceTy); + auto valueIndicesPL = ParameterList::create(C, { paramVarDecl, index @@ -4467,20 +4403,15 @@ namespace { }; // Form the type of the setter. - Type setterType = ParameterList::getFullType(TupleType::getEmpty(C), - setterArgs); + Type setterType = + ParameterList::getFullInterfaceType(TupleType::getEmpty(C), + setterArgs, + dc); - // If we're in a protocol or extension thereof, the setter thunk - // will be polymorphic. Type interfaceType; - if (dc->getAsProtocolOrProtocolExtensionContext()) { - std::tie(setterType, interfaceType) - = getProtocolMethodType(dc, setterType->castTo()); - } else if (dc->isGenericContext()) { + if (dc->isGenericContext()) { std::tie(setterType, interfaceType) = getGenericMethodType(dc, setterType->castTo()); - selfDecl->overwriteType( - setterType->castTo()->getInput()); } // Create the setter thunk. @@ -5746,6 +5677,8 @@ namespace { isInSystemModule(dc), /*isFullyBridgeable*/false); if (superclassType) { + superclassType = + ArchetypeBuilder::mapTypeOutOfContext(result, superclassType); assert(superclassType->is() || superclassType->is()); inheritedTypes.push_back(TypeLoc::withoutLoc(superclassType)); @@ -6945,7 +6878,7 @@ ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc, // 'self' if (dc->isTypeContext()) { - auto *selfDecl = ParamDecl::createUnboundSelf(SourceLoc(), dc, isStatic); + auto *selfDecl = ParamDecl::createSelf(SourceLoc(), dc, isStatic); getterArgs.push_back(ParameterList::createWithoutLoc(selfDecl)); } @@ -6953,7 +6886,7 @@ ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc, getterArgs.push_back(ParameterList::createEmpty(C)); // Form the type of the getter. - auto getterType = ParameterList::getFullType(type, getterArgs); + auto getterType = ParameterList::getFullInterfaceType(type, getterArgs, dc); // Create the getter function declaration. auto func = diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index 1b82159c01d2f..14a45b7e5a640 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -1415,6 +1415,7 @@ static OptionalTypeKind getParamOptionality( } Type ClangImporter::Implementation::importFunctionReturnType( + DeclContext *dc, const clang::FunctionDecl *clangDecl, clang::QualType resultType, bool allowNSUIntegerAsInt) { // CF function results can be managed if they are audited or @@ -1434,14 +1435,20 @@ Type ClangImporter::Implementation::importFunctionReturnType( } // Import the result type. - return importType(resultType, (isAuditedResult ? ImportTypeKind::AuditedResult - : ImportTypeKind::Result), - allowNSUIntegerAsInt, - /*isFullyBridgeable*/ true, OptionalityOfReturn); + auto type = importType(resultType, + (isAuditedResult ? ImportTypeKind::AuditedResult + : ImportTypeKind::Result), + allowNSUIntegerAsInt, + /*isFullyBridgeable*/ true, OptionalityOfReturn); + if (!type) + return type; + + return ArchetypeBuilder::mapTypeOutOfContext(dc, type); } Type ClangImporter::Implementation:: -importFunctionType(const clang::FunctionDecl *clangDecl, +importFunctionType(DeclContext *dc, + const clang::FunctionDecl *clangDecl, clang::QualType resultType, ArrayRef params, bool isVariadic, bool isNoReturn, @@ -1452,12 +1459,12 @@ importFunctionType(const clang::FunctionDecl *clangDecl, shouldAllowNSUIntegerAsInt(isFromSystemModule, clangDecl); auto swiftResultTy = - importFunctionReturnType(clangDecl, resultType, allowNSUIntegerAsInt); + importFunctionReturnType(dc, clangDecl, resultType, allowNSUIntegerAsInt); if (!swiftResultTy) return Type(); ArrayRef argNames = name.getArgumentNames(); - parameterList = importFunctionParameterList(clangDecl, params, isVariadic, + parameterList = importFunctionParameterList(dc, clangDecl, params, isVariadic, allowNSUIntegerAsInt, argNames); if (!parameterList) return Type(); @@ -1471,7 +1478,7 @@ importFunctionType(const clang::FunctionDecl *clangDecl, } ParameterList *ClangImporter::Implementation::importFunctionParameterList( - const clang::FunctionDecl *clangDecl, + DeclContext *dc, const clang::FunctionDecl *clangDecl, ArrayRef params, bool isVariadic, bool allowNSUIntegerAsInt, ArrayRef argNames) { // Import the parameters. @@ -1523,17 +1530,19 @@ ParameterList *ClangImporter::Implementation::importFunctionParameterList( // It doesn't actually matter which DeclContext we use, so just use the // imported header unit. - auto bodyVar = createDeclWithClangNode( + auto paramInfo = createDeclWithClangNode( param, /*IsLet*/ true, SourceLoc(), SourceLoc(), name, importSourceLoc(param->getLocation()), bodyName, swiftParamTy, ImportedHeaderUnit); + paramInfo->setInterfaceType( + ArchetypeBuilder::mapTypeOutOfContext(dc, swiftParamTy)); if (addNoEscapeAttr) - bodyVar->getAttrs().add(new (SwiftContext) + paramInfo->getAttrs().add(new (SwiftContext) NoEscapeAttr(/*IsImplicit=*/false)); - parameters.push_back(bodyVar); + parameters.push_back(paramInfo); ++index; } @@ -2117,14 +2126,20 @@ Type ClangImporter::Implementation::importMethodType( } } + // The member was defined in 'origDC', but is being imported into 'dc'. + // 'dc' must be a subclass or a type conforming to protocol. DeclContext *origDC = importDeclContextOf(clangDecl, clangDecl->getDeclContext()); assert(origDC); auto mapTypeIntoContext = [&](Type type) -> Type { if (dc != origDC) { + // Replace origDC's archetypes with interface types. type = ArchetypeBuilder::mapTypeOutOfContext(origDC, type); + // Get the substitutions that we need to access a member of + // 'origDC' on 'dc', and apply them to the interface type + // to produce the final substituted type. type = dc->getDeclaredTypeInContext()->getTypeOfMember( - dc->getParentModule(), type, origDC); + dc->getParentModule(), type, origDC); } return type; }; @@ -2302,21 +2317,23 @@ Type ClangImporter::Implementation::importMethodType( // It doesn't actually matter which DeclContext we use, so just use the // imported header unit. - auto bodyVar + swiftParamTy = mapTypeIntoContext(swiftParamTy); + + // Set up the parameter info. + auto paramInfo = createDeclWithClangNode(param, /*IsLet*/ true, - SourceLoc(), SourceLoc(), name, - importSourceLoc(param->getLocation()), - bodyName, mapTypeIntoContext(swiftParamTy), - ImportedHeaderUnit); + SourceLoc(), SourceLoc(), name, + importSourceLoc(param->getLocation()), + bodyName, swiftParamTy, + ImportedHeaderUnit); + paramInfo->setInterfaceType( + ArchetypeBuilder::mapTypeOutOfContext(dc, swiftParamTy)); if (addNoEscapeAttr) { - bodyVar->getAttrs().add( + paramInfo->getAttrs().add( new (SwiftContext) NoEscapeAttr(/*IsImplicit=*/false)); } - // Set up the parameter info. - auto paramInfo = bodyVar; - // Determine whether we have a default argument. if (kind == SpecialMethodKind::Regular || kind == SpecialMethodKind::Constructor) { @@ -2375,10 +2392,13 @@ Type ClangImporter::Implementation::importMethodType( // Mark that the function type throws. extInfo = extInfo.withThrows(true); } - + + swiftResultTy = ArchetypeBuilder::mapTypeOutOfContext(dc, swiftResultTy); + // Form the function type. - return FunctionType::get((*bodyParams)->getType(SwiftContext), - swiftResultTy, extInfo); + return FunctionType::get( + (*bodyParams)->getInterfaceType(const_cast(dc)), + swiftResultTy, extInfo); } diff --git a/lib/ClangImporter/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h index df83b7df66b68..d2aac1e3c3e00 100644 --- a/lib/ClangImporter/ImporterImpl.h +++ b/lib/ClangImporter/ImporterImpl.h @@ -1238,7 +1238,8 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation /// /// \returns the imported function type, or null if the type cannot be /// imported. - Type importFunctionType(const clang::FunctionDecl *clangDecl, + Type importFunctionType(DeclContext *dc, + const clang::FunctionDecl *clangDecl, clang::QualType resultType, ArrayRef params, bool isVariadic, bool isNoReturn, @@ -1257,7 +1258,8 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation /// /// \returns the imported function return type, or null if the type cannot be /// imported. - Type importFunctionReturnType(const clang::FunctionDecl *clangDecl, + Type importFunctionReturnType(DeclContext *dc, + const clang::FunctionDecl *clangDecl, clang::QualType resultType, bool allowNSUIntegerAsInt); @@ -1273,7 +1275,8 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation /// /// \returns The imported parameter list on success, or null on failure ParameterList * - importFunctionParameterList(const clang::FunctionDecl *clangDecl, + importFunctionParameterList(DeclContext *dc, + const clang::FunctionDecl *clangDecl, ArrayRef params, bool isVariadic, bool allowNSUIntegerAsInt, ArrayRef argNames); diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp index c0e79b7a14491..124c0e5df7961 100644 --- a/lib/SIL/SILVerifier.cpp +++ b/lib/SIL/SILVerifier.cpp @@ -1720,12 +1720,19 @@ class SILVerifier : public SILVerifierBase { // Get the expected type of a dynamic method reference. SILType getDynamicMethodType(SILType selfType, SILDeclRef method) { auto &C = F.getASTContext(); - + // The type of the dynamic method must match the usual type of the method, // but with the more opaque Self type. - auto methodTy = F.getModule().Types.getConstantType(method) - .castTo(); - + auto constantInfo = F.getModule().Types.getConstantInfo(method); + auto methodTy = constantInfo.SILFnType; + + // Map interface types to archetypes. + if (auto *params = constantInfo.ContextGenericParams) + methodTy = methodTy->substGenericArgs(F.getModule(), M, + params->getForwardingSubstitutions(C)); + assert(!methodTy->isPolymorphic()); + + // Replace Self parameter with type of 'self' at the call site. auto params = methodTy->getParameters(); SmallVector dynParams(params.begin(), params.end() - 1); @@ -1756,10 +1763,7 @@ class SILVerifier : public SILVerifierBase { dynResults, methodTy->getOptionalErrorResult(), F.getASTContext()); - auto boundFnTy = ArchetypeBuilder::mapTypeIntoContext( - method.getDecl()->getDeclContext(), fnTy) - ->getCanonicalType(); - return SILType::getPrimitiveObjectType(boundFnTy); + return SILType::getPrimitiveObjectType(fnTy); } void checkDynamicMethodInst(DynamicMethodInst *EMI) { diff --git a/lib/SIL/TypeLowering.cpp b/lib/SIL/TypeLowering.cpp index a2f8c62ce5939..2d089c2fabff9 100644 --- a/lib/SIL/TypeLowering.cpp +++ b/lib/SIL/TypeLowering.cpp @@ -1817,6 +1817,8 @@ static Type replaceDynamicSelfWithSelf(Type t) { /// Replace any DynamicSelf types with their underlying Self type. static CanType replaceDynamicSelfWithSelf(CanType t) { + if (!t->hasDynamicSelfType()) + return t; return replaceDynamicSelfWithSelf(Type(t))->getCanonicalType(); } diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index b2a6844adc133..dc135869ae26b 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -89,7 +89,7 @@ static Type getExistentialArchetype(SILValue existential) { CanType ty = existential->getType().getSwiftRValueType(); if (ty->is()) return ty; - return cast(ty)->getDecl()->getProtocolSelf()->getArchetype(); + return cast(ty)->getDecl()->getSelfTypeInContext(); } /// Retrieve the type to use for a method found via dynamic lookup. diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp index 20f2cb8d7caf9..1b7f6a0f2d30b 100644 --- a/lib/SILGen/SILGenBridging.cpp +++ b/lib/SILGen/SILGenBridging.cpp @@ -353,8 +353,8 @@ ManagedValue SILGenFunction::emitFuncToBlock(SILLocation loc, // thunks, which is what we are in spirit. auto thunk = SGM.getOrCreateReabstractionThunk(F.getContextGenericParams(), invokeTy, - fnInterfaceTy, - blockInterfaceTy, + fnTy, + blockTy, F.isFragile()); // Build it if necessary. @@ -772,7 +772,7 @@ static SILFunctionType *emitObjCThunkArguments(SILGenFunction &gen, // Emit the indirect result arguments, if any. // FIXME: we're just assuming that these match up exactly? for (auto indirectResult : objcFnTy->getIndirectResults()) { - SILType argTy = gen.F.mapTypeIntoContext(indirectResult.getSILType()); + SILType argTy = indirectResult.getSILType(); auto arg = new (gen.F.getModule()) SILArgument(gen.F.begin(), argTy); args.push_back(arg); } @@ -783,7 +783,7 @@ static SILFunctionType *emitObjCThunkArguments(SILGenFunction &gen, assert(inputs.size() == nativeInputs.size() + unsigned(foreignError.hasValue())); for (unsigned i = 0, e = inputs.size(); i < e; ++i) { - SILType argTy = gen.F.mapTypeIntoContext(inputs[i].getSILType()); + SILType argTy = inputs[i].getSILType(); SILValue arg = new(gen.F.getModule()) SILArgument(gen.F.begin(), argTy); // If this parameter is the foreign error slot, pull it out. @@ -832,8 +832,7 @@ static SILFunctionType *emitObjCThunkArguments(SILGenFunction &gen, Scope scope(gen.Cleanups, CleanupLocation::get(loc)); assert(bridgedArgs.size() == nativeInputs.size()); for (unsigned i = 0, size = bridgedArgs.size(); i < size; ++i) { - SILType argTy = gen.F.mapTypeIntoContext( - swiftFnTy->getParameters()[i].getSILType()); + SILType argTy = swiftFnTy->getParameters()[i].getSILType(); ManagedValue native = gen.emitBridgedToNativeValue(loc, bridgedArgs[i], @@ -869,8 +868,7 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) { auto nativeInfo = getConstantInfo(native); auto swiftResultTy = F.mapTypeIntoContext(nativeInfo.SILFnType->getSILResult()); - auto objcResultTy = - F.mapTypeIntoContext(objcFnTy->getSILResult()); + auto objcResultTy = objcFnTy->getSILResult(); // Call the native entry point. SILValue nativeFn = emitGlobalFunctionRef(loc, native, nativeInfo); diff --git a/lib/SILGen/SILGenDecl.cpp b/lib/SILGen/SILGenDecl.cpp index 23a3bfe008b94..1348c8ae86203 100644 --- a/lib/SILGen/SILGenDecl.cpp +++ b/lib/SILGen/SILGenDecl.cpp @@ -1839,7 +1839,7 @@ SILGenModule::emitProtocolWitness(ProtocolConformance *conformance, // For default implementations, Self is the protocol archetype. } else { auto *proto = cast(requirement.getDecl()->getDeclContext()); - selfType = proto->getProtocolSelf()->getArchetype(); + selfType = proto->getSelfTypeInContext(); } } diff --git a/lib/SILGen/SILGenMaterializeForSet.cpp b/lib/SILGen/SILGenMaterializeForSet.cpp index 33f9f14c42a6d..0f8cfac436db7 100644 --- a/lib/SILGen/SILGenMaterializeForSet.cpp +++ b/lib/SILGen/SILGenMaterializeForSet.cpp @@ -168,8 +168,8 @@ struct MaterializeForSetEmitter { selfType = conformance->getType(); } else { auto *proto = cast(requirement->getDeclContext()); - selfInterfaceType = proto->getProtocolSelf()->getDeclaredType(); - selfType = proto->getProtocolSelf()->getArchetype(); + selfInterfaceType = proto->getSelfInterfaceType(); + selfType = proto->getSelfTypeInContext(); } MaterializeForSetEmitter emitter(SGM, linkage, witness, witnessSubs, @@ -205,16 +205,9 @@ struct MaterializeForSetEmitter { forConcreteImplementation(SILGenModule &SGM, FuncDecl *witness, ArrayRef witnessSubs) { - Type selfInterfaceType, selfType; - auto *dc = witness->getDeclContext(); - if (auto *proto = dc->getAsProtocolOrProtocolExtensionContext()) { - selfInterfaceType = proto->getProtocolSelf()->getDeclaredType(); - selfType = ArchetypeBuilder::mapTypeIntoContext(dc, selfInterfaceType); - } else { - selfInterfaceType = dc->getDeclaredInterfaceType(); - selfType = dc->getDeclaredTypeInContext(); - } + Type selfInterfaceType = dc->getSelfInterfaceType(); + Type selfType = dc->getSelfTypeInContext(); SILDeclRef constant(witness); auto constantInfo = SGM.Types.getConstantInfo(constant); diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index 4a37a585eed8a..83827c9445078 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -67,7 +67,7 @@ static ParamDecl *buildArgument(SourceLoc loc, DeclContext *DC, } static ParamDecl *buildLetArgument(SourceLoc loc, DeclContext *DC, - StringRef name, Type type) { + StringRef name, Type type) { return buildArgument(loc, DC, name, type, /*isLet*/ true); } @@ -182,8 +182,8 @@ static FuncDecl *createSetterPrototype(AbstractStorageDecl *storage, // Add a "(value : T, indices...)" argument list. auto storageType = getTypeOfStorage(storage, TC); valueDecl = buildLetArgument(storage->getLoc(), - storage->getDeclContext(), "value", - storageType); + storage->getDeclContext(), "value", + storageType); params.push_back(buildIndexForwardingParamList(storage, valueDecl)); Type setterRetTy = TupleType::getEmpty(TC.Context); @@ -2060,15 +2060,17 @@ swift::createDesignatedInitOverride(TypeChecker &tc, return nullptr; // Lookup will sometimes give us initializers that are from the ancestors of - // our immediate superclass. So, from the superclass constructor, we look - // one level up to the enclosing type context which will either be a class + // our immediate superclass. So, from the superclass constructor, we look + // one level up to the enclosing type context which will either be a class // or an extension. We can use the type declared in that context to check // if it's our immediate superclass and give up if we didn't. - // + // // FIXME: Remove this when lookup of initializers becomes restricted to our // immediate superclass. - Type superclassTyInCtor = superclassCtor->getDeclContext()->getDeclaredTypeInContext(); + Type superclassTyInCtor = superclassCtor->getDeclContext()->getDeclaredTypeOfContext(); Type superclassTy = classDecl->getSuperclass(); + Type superclassTyInContext = ArchetypeBuilder::mapTypeIntoContext( + classDecl, superclassTy); NominalTypeDecl *superclassDecl = superclassTy->getAnyNominal(); if (superclassTyInCtor->getAnyNominal() != superclassDecl) { return nullptr; @@ -2093,7 +2095,7 @@ swift::createDesignatedInitOverride(TypeChecker &tc, if (superclassDecl->isGenericContext()) { if (auto *superclassSig = superclassDecl->getGenericSignatureOfContext()) { auto *moduleDecl = classDecl->getParentModule(); - auto subs = superclassTy->gatherAllSubstitutions( + auto subs = superclassTyInContext->gatherAllSubstitutions( moduleDecl, nullptr, nullptr); auto subsMap = superclassSig->getSubstitutionMap(subs); @@ -2103,12 +2105,14 @@ swift::createDesignatedInitOverride(TypeChecker &tc, auto paramTy = ArchetypeBuilder::mapTypeOutOfContext( superclassDecl, decl->getType()); - // Apply the superclass substitutions to produce an interface - // type in terms of the class generic signature. + // Apply the superclass substitutions to produce a contextual + // type in terms of the derived class archetypes. auto paramSubstTy = paramTy.subst(moduleDecl, subsMap, SubstOptions()); + decl->overwriteType(paramSubstTy); - // Map it to a contextual type in terms of the class's archetypes. - decl->overwriteType(ArchetypeBuilder::mapTypeIntoContext( + // Map it to an interface type in terms of the derived class + // generic signature. + decl->setInterfaceType(ArchetypeBuilder::mapTypeOutOfContext( classDecl, paramSubstTy)); } } diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 4e01df46dfb9a..e530d658f7dfe 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -1016,7 +1016,7 @@ void ConstraintSystem::openGeneric( // skip. if (skipProtocolSelfConstraint && protoDecl == outerDC->getAsProtocolOrProtocolExtensionContext() && - (protoDecl->getProtocolSelf()->getDeclaredType()->getCanonicalType() == + (protoDecl->getSelfInterfaceType()->getCanonicalType() == req.getFirstType()->getCanonicalType())) { break; } @@ -1218,8 +1218,8 @@ ConstraintSystem::getTypeOfMemberReference( if (outerDC->getAsProtocolOrProtocolExtensionContext()) { // Retrieve the type variable for 'Self'. - selfTy = replacements[outerDC->getProtocolSelf()->getDeclaredType() - ->getCanonicalType()]; + selfTy = replacements[outerDC->getSelfInterfaceType() + ->getCanonicalType()]; } else { // Open the nominal type. selfTy = openType(nominal->getDeclaredInterfaceType(), locator, diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp index 12b897d71096e..9a6a1560f8eab 100644 --- a/lib/Sema/DerivedConformanceRawRepresentable.cpp +++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp @@ -141,8 +141,9 @@ static VarDecl *deriveRawRepresentable_raw(TypeChecker &tc, PatternBindingDecl *pbDecl; std::tie(propDecl, pbDecl) = declareDerivedReadOnlyProperty(tc, parentDecl, enumDecl, - C.Id_rawValue, rawType, + C.Id_rawValue, rawInterfaceType, + rawType, getterDecl); auto dc = cast(parentDecl); diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index cb6547d1ab1dc..5be1dfaf0f765 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -372,9 +372,8 @@ void TypeChecker::checkInheritanceClause(Decl *decl, continue; // Retrieve the interface type for this inherited type. - if (DC->isGenericContext() && DC->isTypeContext()) { + if (inheritedTy->hasArchetype()) inheritedTy = ArchetypeBuilder::mapTypeOutOfContext(DC, inheritedTy); - } // Check whether we inherited from the same type twice. CanType inheritedCanTy = inheritedTy->getCanonicalType(); @@ -4075,7 +4074,8 @@ class DeclChecker : public DeclVisitor { return false; } - // 'Self' is only a dynamic self on class methods. + // 'Self' is only a dynamic self on class methods and + // protocol requirements. auto declaredType = dc->getDeclaredTypeOfContext(); if (declaredType->is()) return false; diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp index e55b24e593b6b..1835c60aeb3fa 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -587,15 +587,8 @@ void TypeChecker::configureInterfaceType(AbstractFunctionDecl *func) { } else if (auto ctor = dyn_cast(func)) { auto *dc = ctor->getDeclContext(); - // FIXME: shouldn't this just be - // ctor->getDeclContext()->getDeclaredInterfaceType()? - if (dc->getAsProtocolOrProtocolExtensionContext()) { - funcTy = dc->getProtocolSelf()->getDeclaredType(); - } else { - funcTy = dc->getAsNominalTypeOrNominalTypeExtensionContext() - ->getDeclaredInterfaceType(); - } - + funcTy = dc->getSelfInterfaceType(); + // Adjust result type for failability. if (ctor->getFailability() != OTK_None) funcTy = OptionalType::get(ctor->getFailability(), funcTy); @@ -633,14 +626,7 @@ void TypeChecker::configureInterfaceType(AbstractFunctionDecl *func) { initArgTy = func->computeInterfaceSelfType(/*isInitializingCtor=*/true); } } else { - argTy = paramLists[e - i - 1]->getType(Context); - - // For an implicit declaration, our argument type will be in terms of - // archetypes rather than dependent types. Replace the - // archetypes with their corresponding dependent types. - if (func->isImplicit()) { - argTy = ArchetypeBuilder::mapTypeOutOfContext(func, argTy); - } + argTy = paramLists[e - i - 1]->getInterfaceType(func); if (initFuncTy) initArgTy = argTy; @@ -648,9 +634,6 @@ void TypeChecker::configureInterfaceType(AbstractFunctionDecl *func) { auto info = applyFunctionTypeAttributes(func, i); - // FIXME: We shouldn't even get here if the function isn't locally generic - // to begin with, but fixing that requires a lot of reengineering for local - // definitions in generic contexts. if (sig && i == e-1) { funcTy = GenericFunctionType::get(sig, argTy, funcTy, info); if (initFuncTy) @@ -663,9 +646,12 @@ void TypeChecker::configureInterfaceType(AbstractFunctionDecl *func) { } // Record the interface type. + assert(!funcTy->hasArchetype()); func->setInterfaceType(funcTy); - if (initFuncTy) + if (initFuncTy) { + assert(!initFuncTy->hasArchetype()); cast(func)->setInitializerInterfaceType(initFuncTy); + } if (func->getGenericParams()) { // Collect all generic params referenced in parameter types, diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index 9a114a3ba16fa..bcb36ae280ff7 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -925,7 +925,7 @@ matchWitness(TypeChecker &tc, // the required type and the witness type. cs.emplace(tc, dc, ConstraintSystemOptions()); - Type selfIfaceTy = proto->getProtocolSelf()->getDeclaredType(); + Type selfIfaceTy = proto->getSelfInterfaceType(); Type selfTy; // For a concrete conformance, use the conforming type as the @@ -1889,17 +1889,6 @@ void ConformanceChecker::recordTypeWitness(AssociatedTypeDecl *assocType, TypeDecl *typeDecl, DeclContext *fromDC, bool performRedeclarationCheck) { - // If the declaration context from which the type witness was determined - // differs from that of the conformance, adjust the type so that it is - // based on the declaration context of the conformance. - if (fromDC != DC && DC->getGenericSignatureOfContext() && - fromDC->getGenericSignatureOfContext() && !isa(fromDC)) { - // Map the type to an interface type. - type = ArchetypeBuilder::mapTypeOutOfContext(fromDC, type); - - // Map the type into the conformance's context. - type = Adoptee->getTypeOfMember(DC->getParentModule(), type, fromDC); - } // If we already recoded this type witness, there's nothing to do. if (Conformance->hasTypeWitness(assocType)) { @@ -2882,7 +2871,7 @@ void ConformanceChecker::resolveTypeWitnesses() { // Create a set of type substitutions for all known associated type. // FIXME: Base this on dependent types rather than archetypes? TypeSubstitutionMap substitutions; - substitutions[Proto->getProtocolSelf()->getArchetype()] = Adoptee; + substitutions[Proto->getSelfTypeInContext().getPointer()] = Adoptee; for (auto member : Proto->getMembers()) { if (auto assocType = dyn_cast(member)) { if (Conformance->hasTypeWitness(assocType)) { diff --git a/lib/Sema/TypeCheckREPL.cpp b/lib/Sema/TypeCheckREPL.cpp index 36dd0093ef4df..9cbc8a8b20437 100644 --- a/lib/Sema/TypeCheckREPL.cpp +++ b/lib/Sema/TypeCheckREPL.cpp @@ -239,7 +239,8 @@ void REPLChecker::generatePrintOfExpression(StringRef NameStr, Expr *E) { new (Context) ClosureExpr(params, SourceLoc(), SourceLoc(), SourceLoc(), TypeLoc(), discriminator, newTopLevel); - CE->setType(ParameterList::getFullType(TupleType::getEmpty(Context), params)); + CE->setType(ParameterList::getFullInterfaceType( + TupleType::getEmpty(Context), params, newTopLevel)); // Convert the pattern to a string we can print. llvm::SmallString<16> PrefixString; diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 85b58f3eacf99..758d088a324a9 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -333,7 +333,8 @@ Type TypeChecker::resolveTypeInContext( // - Nested type: associated type // - Nested type's context: protocol or protocol extension // - if (assocType && fromProto == nullptr) { + if (!fromProto && + ownerNominal->getAsProtocolOrProtocolExtensionContext()) { ProtocolConformance *conformance = nullptr; // If the conformance check failed, the associated type is for a @@ -344,7 +345,12 @@ Type TypeChecker::resolveTypeInContext( parentDC, ConformanceCheckFlags::Used, &conformance) && conformance) { - return conformance->getTypeWitness(assocType, this).getReplacement(); + if (assocType) { + return conformance->getTypeWitness(assocType, this).getReplacement(); + } + + return substMemberTypeWithBase(parentDC->getParentModule(), typeDecl, + fromType, /*isTypeReference=*/true); } } @@ -370,14 +376,11 @@ Type TypeChecker::resolveTypeInContext( // instead of the existential type. assert(fromType->is()); - auto protoSelf = parentDC->getProtocolSelf(); - if (protoSelf == nullptr) + auto selfType = parentDC->getSelfInterfaceType(); + if (!selfType) return ErrorType::get(Context); - - auto selfType = protoSelf - ->getDeclaredType() - ->castTo(); - fromType = resolver->resolveGenericTypeParamType(selfType); + fromType = resolver->resolveGenericTypeParamType( + selfType->castTo()); if (assocType) { // Odd special case, ask Doug to explain it over pizza one day diff --git a/test/decl/inherit/initializer.swift b/test/decl/inherit/initializer.swift index 9f22eb4778d08..9c95968b7b809 100644 --- a/test/decl/inherit/initializer.swift +++ b/test/decl/inherit/initializer.swift @@ -142,3 +142,11 @@ class SuperVariadic { class SubVariadic : SuperVariadic { } // expected-warning 4{{synthesizing a variadic inherited initializer for subclass 'SubVariadic' is unsupported}} +// Don't crash with invalid nesting of class in generic function + +func testClassInGenericFunc(t: T) { + class A { init(t: T) {} } // expected-error {{type 'A' cannot be nested in generic function 'testClassInGenericFunc'}} + class B : A {} // expected-error {{type 'B' cannot be nested in generic function 'testClassInGenericFunc'}} + + _ = B(t: t) +} diff --git a/test/decl/typealias/protocol.swift b/test/decl/typealias/protocol.swift index 1c3204c912fed..98c6be03af5ba 100644 --- a/test/decl/typealias/protocol.swift +++ b/test/decl/typealias/protocol.swift @@ -152,3 +152,22 @@ struct T5 : P5 { var v7: T5.T2 // OK } +// Unqualified lookup finds typealiases in protocol extensions, though +protocol P6 { + associatedtype A +} + +extension P6 { + typealias Y = A +} + +struct S6 : P6 { + typealias A = Int + + // FIXME + func inTypeContext(y: Y) // expected-error {{use of undeclared type 'Y'}} + + func inExpressionContext() { + _ = Y.self + } +}