diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index ece844cf26f..e3ca0ced57f 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -2259,6 +2259,7 @@ GenericTypeParamDecl::GenericTypeParamDecl(DeclContext *dc, Identifier name, auto &ctx = dc->getASTContext(); auto type = new (ctx, AllocationArena::Permanent) GenericTypeParamType(this); setType(MetatypeType::get(type, ctx)); + setInterfaceType(MetatypeType::get(type, ctx)); } SourceRange GenericTypeParamDecl::getSourceRange() const { @@ -4625,26 +4626,54 @@ SourceRange EnumElementDecl::getSourceRange() const { bool EnumElementDecl::computeType() { EnumDecl *ED = getParentEnum(); - Type resultTy = ED->getDeclaredTypeInContext(); + { + Type resultTy = ED->getDeclaredTypeInContext(); + + if (resultTy->hasError()) { + setType(resultTy); + setInterfaceType(resultTy); + return false; + } + + Type argTy = MetatypeType::get(resultTy); + + // The type of the enum element is either (T) -> T or (T) -> ArgType -> T. + if (getArgumentType()) + resultTy = FunctionType::get(getArgumentType(), resultTy); + + if (ED->isGenericContext()) + resultTy = PolymorphicFunctionType::get(argTy, resultTy, + ED->getGenericParamsOfContext()); + else + resultTy = FunctionType::get(argTy, resultTy); - if (resultTy->hasError()) { setType(resultTy); - return false; + } + { + Type resultTy = ED->getDeclaredInterfaceType(); + + if (resultTy->hasError()) { + setInterfaceType(resultTy); + return false; + } + + Type argTy = MetatypeType::get(resultTy); + + // The type of the enum element is either (T) -> T or (T) -> ArgType -> T. + if (auto inputTy = getArgumentType()) + resultTy = FunctionType::get( + ArchetypeBuilder::mapTypeOutOfContext(ED, inputTy), resultTy); + + if (auto *genericSig = ED->getGenericSignatureOfContext()) + resultTy = GenericFunctionType::get(genericSig, argTy, resultTy, + AnyFunctionType::ExtInfo()); + else + resultTy = FunctionType::get(argTy, resultTy); + + // Record the interface type. + setInterfaceType(resultTy); } - Type argTy = MetatypeType::get(resultTy); - - // The type of the enum element is either (T) -> T or (T) -> ArgType -> T. - if (getArgumentType()) - resultTy = FunctionType::get(getArgumentType(), resultTy); - - if (ED->isGenericContext()) - resultTy = PolymorphicFunctionType::get(argTy, resultTy, - ED->getGenericParamsOfContext()); - else - resultTy = FunctionType::get(argTy, resultTy); - - setType(resultTy); return true; } diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index 15b2515ce68..eaf92abaaf4 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -84,6 +84,7 @@ void BuiltinUnit::LookupCache::lookupValue( /*genericparams*/nullptr, const_cast(&M)); TAD->computeType(); + TAD->setInterfaceType(TAD->getType()); TAD->setAccessibility(Accessibility::Public); Entry = TAD; } @@ -346,6 +347,7 @@ ModuleDecl::ModuleDecl(Identifier name, ASTContext &ctx) ctx.addDestructorCleanup(*this); setImplicit(); setType(ModuleType::get(this)); + setInterfaceType(ModuleType::get(this)); setAccessibility(Accessibility::Public); } diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index edb3e229747..227bb64947f 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -126,6 +126,7 @@ createVarWithPattern(ASTContext &cxt, DeclContext *dc, Identifier name, Type ty, /*IsLet*/ isLet, SourceLoc(), name, ty, dc); if (isImplicit) var->setImplicit(); + var->setInterfaceType(ty); var->setAccessibility(Accessibility::Public); var->setSetterAccessibility(setterAccessibility); @@ -1197,6 +1198,7 @@ static void makeStructRawValuedWithBridge( auto computedVar = new (cxt) VarDecl( /*static*/ false, /*IsLet*/ false, SourceLoc(), computedVarName, bridgedType, structDecl); + computedVar->setInterfaceType(bridgedType); computedVar->setImplicit(); computedVar->setAccessibility(Accessibility::Public); computedVar->setSetterAccessibility(Accessibility::Private); @@ -1512,6 +1514,7 @@ static bool addErrorDomain(NominalTypeDecl *swiftDecl, auto errorDomainPropertyDecl = new (C) VarDecl( isStatic, /*isLet=*/false, SourceLoc(), C.Id_nsErrorDomain, stringTy, swiftDecl); + errorDomainPropertyDecl->setInterfaceType(stringTy); errorDomainPropertyDecl->setAccessibility(Accessibility::Public); swiftDecl->addMember(errorDomainPropertyDecl); @@ -1921,6 +1924,7 @@ namespace { underlying->getDeclaredInterfaceType()), /*genericparams*/nullptr, DC); typealias->computeType(); + typealias->setInterfaceType(typealias->getType()); Impl.SpecialTypedefNames[Decl->getCanonicalDecl()] = MappedTypeNameKind::DefineAndUse; @@ -1946,6 +1950,7 @@ namespace { proto->getDeclaredInterfaceType()), /*genericparams*/nullptr, DC); typealias->computeType(); + typealias->setInterfaceType(typealias->getType()); Impl.SpecialTypedefNames[Decl->getCanonicalDecl()] = MappedTypeNameKind::DefineAndUse; @@ -2014,6 +2019,7 @@ namespace { TypeLoc::withoutLoc(SwiftType), /*genericparams*/nullptr, DC); Result->computeType(); + Result->setInterfaceType(Result->getType()); // Make Objective-C's 'id' unavailable. ASTContext &ctx = DC->getASTContext(); @@ -2189,6 +2195,7 @@ namespace { errorWrapper); nsErrorProp->setImplicit(); nsErrorProp->setAccessibility(Accessibility::Public); + nsErrorProp->setInterfaceType(nsErrorType); // Create a pattern binding to describe the variable. Pattern *nsErrorPattern = createTypedNamedPattern(nsErrorProp); @@ -2256,6 +2263,7 @@ namespace { rawValue->setImplicit(); rawValue->setAccessibility(Accessibility::Public); rawValue->setSetterAccessibility(Accessibility::Private); + rawValue->setInterfaceType(underlyingType); // Create a pattern binding to describe the variable. Pattern *varPattern = createTypedNamedPattern(rawValue); @@ -2282,6 +2290,7 @@ namespace { errorWrapper->getDeclaredInterfaceType()), /*genericSignature=*/nullptr, enumDecl); alias->computeType(); + alias->setInterfaceType(alias->getType()); enumDecl->addMember(alias); // Add the 'Code' enum to the error wrapper. @@ -2775,6 +2784,7 @@ namespace { /*static*/ false, /*IsLet*/ false, Impl.importSourceLoc(decl->getLocStart()), name, type, dc); + result->setInterfaceType(type); // If this is a Swift 2 stub, mark is as such. if (swift3Name) @@ -2965,6 +2975,7 @@ namespace { /*static*/ false, /*IsLet*/ false, Impl.importSourceLoc(decl->getLocation()), name, type, dc); + result->setInterfaceType(type); // Handle attributes. if (decl->hasAttr()) @@ -3037,6 +3048,7 @@ namespace { Impl.shouldImportGlobalAsLet(decl->getType()), Impl.importSourceLoc(decl->getLocation()), name, type, dc); + result->setInterfaceType(type); // If imported as member, the member should be final. if (dc->getAsClassOrClassExtensionContext()) @@ -4111,6 +4123,7 @@ namespace { /*genericparams=*/nullptr, dc); typealias->computeType(); + typealias->setInterfaceType(typealias->getType()); return typealias; } @@ -4347,6 +4360,7 @@ Decl *SwiftDeclConverter::importSwift2TypeAlias(const clang::NamedDecl *decl, Impl.importSourceLoc(decl->getLocation()), TypeLoc::withoutLoc(underlyingType), genericParams, dc); alias->computeType(); + alias->setInterfaceType(alias->getType()); alias->setGenericEnvironment(genericEnv); // Record that this is the Swift 2 version of this declaration. @@ -4927,6 +4941,7 @@ SwiftDeclConverter::getImplicitProperty(ImportedName importedName, auto property = Impl.createDeclWithClangNode( getter, Accessibility::Public, isStatic, /*isLet=*/false, SourceLoc(), propertyName, swiftPropertyType, dc); + property->setInterfaceType(swiftPropertyType); // Note that we've formed this property. Impl.FunctionsAsProperties[getter] = property; @@ -7047,6 +7062,8 @@ ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc, VarDecl(isStatic, /*IsLet*/ false, SourceLoc(), name, type, dc); } + var->setInterfaceType(type); + // Form the argument patterns. SmallVector getterArgs; @@ -7148,6 +7165,7 @@ createUnavailableDecl(Identifier name, DeclContext *dc, Type type, auto var = createDeclWithClangNode(ClangN, Accessibility::Public, isStatic, /*IsLet*/ false, SourceLoc(), name, type, dc); + var->setInterfaceType(type); markUnavailable(var, UnavailableMessage); return var; diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 4cc044c4e54..a0dfca3c45c 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -5315,6 +5315,7 @@ ParserStatus Parser::parseDeclSubscript(ParseDeclOptions Flags, if (Invalid) { Subscript->setType(ErrorType::get(Context)); + Subscript->setInterfaceType(ErrorType::get(Context)); Subscript->setInvalid(); } diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp index 0ff08edbd1a..6bd27153158 100644 --- a/lib/Sema/CSDiag.cpp +++ b/lib/Sema/CSDiag.cpp @@ -3199,8 +3199,10 @@ namespace { for (auto patternElt : PatternTypes) patternElt.first->setType(patternElt.second); - for (auto paramDeclElt : ParamDeclTypes) + for (auto paramDeclElt : ParamDeclTypes) { paramDeclElt.first->overwriteType(paramDeclElt.second); + paramDeclElt.first->setInterfaceType(Type()); + } for (auto CSE : CollectionSemanticExprs) CSE.first->setSemanticExpr(CSE.second); diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index 2427e703d07..06fbf21ced5 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -1440,6 +1440,7 @@ void TypeChecker::completePropertyBehaviorAccessors(VarDecl *VD, ArrayRef SelfInterfaceSubs, ArrayRef SelfContextSubs) { auto selfTy = SelfContextSubs[0].getReplacement(); + auto selfIfaceTy = SelfInterfaceSubs[0].getReplacement(); SmallVector bodyStmts; @@ -1469,6 +1470,8 @@ void TypeChecker::completePropertyBehaviorAccessors(VarDecl *VD, SourceLoc(), Context.getIdentifier("tempSelf"), selfTy, fromAccessor); + var->setInterfaceType(selfIfaceTy); + auto varPat = new (Context) NamedPattern(var); auto pbd = PatternBindingDecl::create(Context, SourceLoc(), StaticSpellingKind::None, diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 7c732c07050..2feed54e9f7 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -771,8 +771,11 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value, } // Determine the type of the value, opening up that type if necessary. + bool wantInterfaceType = true; + if (isa(value)) + wantInterfaceType = !value->getDeclContext()->isLocalContext(); Type valueType = TC.getUnopenedTypeOfReference(value, Type(), DC, base, - /*wantInterfaceType=*/true); + wantInterfaceType); // If this is a let-param whose type is a type variable, this is an untyped // closure param that may be bound to an inout type later. References to the diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp index 14b1fc2d5e2..1531f2be812 100644 --- a/lib/Sema/DerivedConformanceEquatableHashable.cpp +++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp @@ -67,6 +67,7 @@ static DeclRefExpr *convertEnumToIndex(SmallVectorImpl &stmts, auto indexVar = new (C) VarDecl(/*static*/false, /*let*/false, SourceLoc(), C.getIdentifier(indexName), intType, funcDecl); + indexVar->setInterfaceType(intType); indexVar->setImplicit(); // generate: var indexVar @@ -445,6 +446,7 @@ deriveHashable_enum_hashValue(TypeChecker &tc, Decl *parentDecl, SourceLoc(), C.Id_hashValue, intType, parentDC); hashValueDecl->setImplicit(); + hashValueDecl->setInterfaceType(intType); hashValueDecl->makeComputed(SourceLoc(), getterDecl, nullptr, nullptr, SourceLoc()); hashValueDecl->setAccessibility(getterDecl->getFormalAccess()); diff --git a/lib/Sema/PlaygroundTransform.cpp b/lib/Sema/PlaygroundTransform.cpp index bd1a84b9f7b..e7662611e43 100644 --- a/lib/Sema/PlaygroundTransform.cpp +++ b/lib/Sema/PlaygroundTransform.cpp @@ -913,6 +913,7 @@ public: MaybeLoadInitExpr->getType(), TypeCheckDC); + VD->setInterfaceType(VD->getType()); VD->setImplicit(); NamedPattern *NP = new (Context) NamedPattern(VD, /*implicit*/true); diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 5f4e96c2c3c..2d5f00a7a96 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -1641,6 +1641,7 @@ void TypeChecker::checkNoEscapeAttr(ParamDecl *PD, NoEscapeAttr *attr) { void TypeChecker::checkOwnershipAttr(VarDecl *var, OwnershipAttr *attr) { Type type = var->getType(); + Type interfaceType = var->getInterfaceType(); // Just stop if we've already processed this declaration. if (type->is()) @@ -1699,7 +1700,10 @@ void TypeChecker::checkOwnershipAttr(VarDecl *var, OwnershipAttr *attr) { } // Change the type to the appropriate reference storage type. - var->overwriteType(ReferenceStorageType::get(type, ownershipKind, Context)); + var->overwriteType(ReferenceStorageType::get( + type, ownershipKind, Context)); + var->setInterfaceType(ReferenceStorageType::get( + interfaceType, ownershipKind, Context)); } Optional> diff --git a/lib/Sema/TypeCheckCaptures.cpp b/lib/Sema/TypeCheckCaptures.cpp index 12263a46dcb..4591fc43cf6 100644 --- a/lib/Sema/TypeCheckCaptures.cpp +++ b/lib/Sema/TypeCheckCaptures.cpp @@ -320,7 +320,9 @@ public: if (!validateForwardCapture(DRE->getDecl())) return { false, DRE }; - bool isInOut = D->hasType() && D->getInterfaceType()->is(); + bool isInOut = (isa(D) && + D->hasType() && + D->getType()->is()); bool isNested = false; if (auto f = AFR.getAbstractFunctionDecl()) isNested = f->getDeclContext()->isLocalContext(); @@ -642,9 +644,11 @@ void TypeChecker::computeCaptures(AnyFunctionRef AFR) { unsigned inoutCount = 0; for (auto C: Captures) { - if (auto type = C.getDecl()->getInterfaceType()) - if (isa(type.getPointer())) - inoutCount++; + if (auto PD = dyn_cast(C.getDecl())) + if (PD->hasType()) + if (auto type = PD->getType()) + if (isa(type.getPointer())) + inoutCount++; } if (inoutCount > 0) { diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 06e55038de6..1c7d0c7ee7d 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -1290,6 +1290,7 @@ void CleanupIllFormedExpressionRAII::doIt(Expr *expr, ASTContext &Context) { if (auto VD = dyn_cast(D)) { if (VD->hasType() && VD->getType()->hasTypeVariable()) { VD->overwriteType(ErrorType::get(context)); + VD->setInterfaceType(ErrorType::get(context)); VD->setInvalid(); } } @@ -1897,6 +1898,7 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer, return; var->overwriteType(ErrorType::get(Context)); + var->setInterfaceType(ErrorType::get(Context)); var->setInvalid(); }); } @@ -2227,6 +2229,7 @@ bool TypeChecker::typeCheckStmtCondition(StmtCondition &cond, DeclContext *dc, if (var->hasType() && !var->getType()->hasError()) return; var->overwriteType(ErrorType::get(Context)); + var->setInterfaceType(ErrorType::get(Context)); var->setInvalid(); }); }; @@ -2280,6 +2283,7 @@ bool TypeChecker::typeCheckExprPattern(ExprPattern *EP, DeclContext *DC, Context.getIdentifier("$match"), rhsType, DC); + matchVar->setInterfaceType(rhsType); matchVar->setImplicit(); EP->setMatchVar(matchVar); diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 32bcefa52b0..d6b8889da36 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -651,6 +651,7 @@ static void checkCircularity(TypeChecker &tc, T *decl, decl->setInvalid(); decl->overwriteType(ErrorType::get(tc.Context)); + decl->setInterfaceType(ErrorType::get(tc.Context)); breakInheritanceCycle(decl); break; } @@ -673,6 +674,7 @@ static void checkCircularity(TypeChecker &tc, T *decl, // Set this declaration as invalid, then break the cycle somehow. decl->setInvalid(); decl->overwriteType(ErrorType::get(tc.Context)); + decl->setInterfaceType(ErrorType::get(tc.Context)); breakInheritanceCycle(decl); break; } @@ -701,6 +703,7 @@ static void setBoundVarsTypeError(Pattern *pattern, ASTContext &ctx) { return; var->overwriteType(ErrorType::get(ctx)); + var->setInterfaceType(ErrorType::get(ctx)); var->setInvalid(); }); } @@ -941,7 +944,9 @@ static void checkRedeclaration(TypeChecker &tc, ValueDecl *current) { const auto markInvalid = [¤t, &tc]() { current->setInvalid(); if (current->hasType()) - current->overwriteType(ErrorType::get(tc.Context)); + current->overwriteType(ErrorType::get(tc.Context)); + if (current->hasInterfaceType()) + current->setInterfaceType(ErrorType::get(tc.Context)); }; // Thwart attempts to override the same declaration more than once. @@ -1099,18 +1104,6 @@ static void validatePatternBindingDecl(TypeChecker &tc, if (binding->getPattern(entryNumber)->hasType()) if (auto var = binding->getSingleVar()) tc.checkTypeModifyingDeclAttributes(var); - - // If we're in a generic type context, provide interface types for all of - // the variables. - { - auto dc = binding->getDeclContext(); - if (dc->isGenericContext() && dc->isTypeContext()) { - binding->getPattern(entryNumber)->forEachVariable([&](VarDecl *var) { - var->setInterfaceType( - ArchetypeBuilder::mapTypeOutOfContext(dc, var->getType())); - }); - } - } } void swift::makeFinal(ASTContext &ctx, ValueDecl *D) { @@ -2958,6 +2951,7 @@ static void checkVarBehavior(VarDecl *decl, TypeChecker &TC) { if (conformance->isInvalid()) { decl->setInvalid(); decl->overwriteType(ErrorType::get(TC.Context)); + decl->setInterfaceType(ErrorType::get(TC.Context)); return; } @@ -3171,6 +3165,7 @@ static void checkVarBehavior(VarDecl *decl, TypeChecker &TC) { if (conformance->isInvalid()) { decl->setInvalid(); decl->overwriteType(ErrorType::get(TC.Context)); + decl->setInterfaceType(ErrorType::get(TC.Context)); return; } @@ -3194,6 +3189,7 @@ static void checkVarBehavior(VarDecl *decl, TypeChecker &TC) { diag::property_behavior_value_decl_here); decl->setInvalid(); decl->overwriteType(ErrorType::get(TC.Context)); + decl->setInterfaceType(ErrorType::get(TC.Context)); return; } @@ -3539,6 +3535,7 @@ public: TC.diagnose(VD->getStartLoc(), diag::var_type_not_materializable, VD->getType()); VD->overwriteType(ErrorType::get(TC.Context)); + VD->setInterfaceType(ErrorType::get(TC.Context)); VD->setInvalid(); } @@ -3567,11 +3564,13 @@ public: TC.diagnose(VD->getLoc(), diag::enum_stored_property); VD->setInvalid(); VD->overwriteType(ErrorType::get(TC.Context)); + VD->setInterfaceType(ErrorType::get(TC.Context)); } else if (isa(VD->getDeclContext()) && !VD->isStatic()) { TC.diagnose(VD->getLoc(), diag::extension_stored_property); VD->setInvalid(); VD->overwriteType(ErrorType::get(TC.Context)); + VD->setInterfaceType(ErrorType::get(TC.Context)); } // We haven't implemented type-level storage in some contexts. @@ -3731,8 +3730,10 @@ public: TC.diagnose(var->getLoc(), diag::observingprop_requires_initializer); PBD->setInvalid(); var->setInvalid(); - if (!var->hasType()) + if (!var->hasType()) { var->setType(ErrorType::get(TC.Context)); + var->setInterfaceType(ErrorType::get(TC.Context)); + } return; } @@ -3744,8 +3745,10 @@ public: var->getCorrectStaticSpelling()); PBD->setInvalid(); var->setInvalid(); - if (!var->hasType()) + if (!var->hasType()) { var->setType(ErrorType::get(TC.Context)); + var->setInterfaceType(ErrorType::get(TC.Context)); + } return; } @@ -3757,8 +3760,10 @@ public: diag::global_requires_initializer, var->isLet()); PBD->setInvalid(); var->setInvalid(); - if (!var->hasType()) + if (!var->hasType()) { var->setType(ErrorType::get(TC.Context)); + var->setInterfaceType(ErrorType::get(TC.Context)); + } return; } }); @@ -3792,6 +3797,7 @@ public: if (isInvalid) { SD->overwriteType(ErrorType::get(TC.Context)); + SD->setInterfaceType(ErrorType::get(TC.Context)); SD->setInvalid(); } else { // Hack to deal with types already getting set during type validation @@ -3800,17 +3806,15 @@ public: return; // Relabel the indices according to the subscript name. - auto indicesType = SD->getIndices()->getType(TC.Context); - SD->setType(FunctionType::get(indicesType, SD->getElementType())); + auto indicesTy = SD->getIndices()->getType(TC.Context); + SD->setType(FunctionType::get(indicesTy, SD->getElementType())); // If we're in a generic context, set the interface type. - if (dc->isGenericContext()) { - auto indicesTy = ArchetypeBuilder::mapTypeOutOfContext( - dc, indicesType); - auto elementTy = ArchetypeBuilder::mapTypeOutOfContext( - dc, SD->getElementType()); - SD->setInterfaceType(FunctionType::get(indicesTy, elementTy)); - } + auto indicesIfaceTy = ArchetypeBuilder::mapTypeOutOfContext( + dc, indicesTy); + auto elementIfaceTy = ArchetypeBuilder::mapTypeOutOfContext( + dc, SD->getElementType()); + SD->setInterfaceType(FunctionType::get(indicesIfaceTy, elementIfaceTy)); } validateAttributes(TC, SD); @@ -3904,8 +3908,16 @@ public: TAD->getDeclContext(), options)) { TAD->setInvalid(); TAD->overwriteType(ErrorType::get(TC.Context)); + TAD->setInterfaceType(ErrorType::get(TC.Context)); TAD->getUnderlyingTypeLoc().setInvalidType(TC.Context); - } else if (TAD->getDeclContext()->isGenericContext()) { + } + + // lldb creates global typealiases containing archetypes + // sometimes... + if (TAD->getType()->getCanonicalType()->hasTypeParameter() || + !TAD->isGenericContext()) + TAD->setInterfaceType(TAD->getType()); + else { TAD->setInterfaceType( ArchetypeBuilder::mapTypeOutOfContext(TAD, TAD->getType())); } @@ -4017,6 +4029,7 @@ public: auto Res = Elements.insert({ EED->getName(), EED }); if (!Res.second) { EED->overwriteType(ErrorType::get(TC.Context)); + EED->setInterfaceType(ErrorType::get(TC.Context)); EED->setInvalid(); if (auto *RawValueExpr = EED->getRawValueExpr()) RawValueExpr->setType(ErrorType::get(TC.Context)); @@ -4712,7 +4725,7 @@ public: // Check the parameters for a reference to 'Self'. bool isProtocol = isa(selfNominal); for (auto param : *FD->getParameterList(1)) { - auto paramType = param->getInterfaceType(); + auto paramType = param->getType(); if (!paramType) break; // Look through 'inout'. @@ -6216,25 +6229,6 @@ public: return false; } - /// Compute the interface type of the given enum element. - void computeEnumElementInterfaceType(EnumElementDecl *elt) { - auto enumDecl = cast(elt->getDeclContext()); - assert(enumDecl->getGenericSignatureOfContext() && "Not a generic enum"); - - // Build the generic function type. - auto funcTy = elt->getType()->castTo(); - auto inputTy = ArchetypeBuilder::mapTypeOutOfContext(enumDecl, - funcTy->getInput()); - auto resultTy = ArchetypeBuilder::mapTypeOutOfContext(enumDecl, - funcTy->getResult()); - auto interfaceTy - = GenericFunctionType::get(enumDecl->getGenericSignatureOfContext(), - inputTy, resultTy, funcTy->getExtInfo()); - - // Record the interface type. - elt->setInterfaceType(interfaceTy); - } - void visitEnumCaseDecl(EnumCaseDecl *ECD) { // The type-checker doesn't care about how these are grouped. } @@ -6250,6 +6244,7 @@ public: if (EED->isBeingTypeChecked()) { TC.diagnose(EED->getLoc(), diag::circular_reference); EED->setType(ErrorType::get(TC.Context)); + EED->setInterfaceType(ErrorType::get(TC.Context)); EED->setInvalid(); return; } @@ -6270,6 +6265,7 @@ public: if (TC.validateType(EED->getArgumentTypeLoc(), EED->getDeclContext(), TR_EnumCase)) { EED->overwriteType(ErrorType::get(TC.Context)); + EED->setInterfaceType(ErrorType::get(TC.Context)); EED->setInvalid(); return; } @@ -6311,18 +6307,12 @@ public: return; } - // Test for type parameters, as opposed to a generic decl context, in - // case the enclosing enum type was illegally declared inside of a generic - // context. (In that case, we'll post a diagnostic while visiting the - // parent enum.) - if (EED->getDeclContext()->getGenericSignatureOfContext()) - computeEnumElementInterfaceType(EED); - // Require the carried type to be materializable. if (EED->getArgumentType() && !EED->getArgumentType()->isMaterializable()) { TC.diagnose(EED->getLoc(), diag::enum_element_not_materializable); EED->overwriteType(ErrorType::get(TC.Context)); + EED->setInterfaceType(ErrorType::get(TC.Context)); EED->setInvalid(); } TC.checkDeclAttributes(EED); @@ -7071,6 +7061,7 @@ void TypeChecker::validateDecl(ValueDecl *D, bool resolveTypeParams) { typeAlias->getUnderlyingTypeLoc().setInvalidType(Context); typeAlias->setInvalid(); typeAlias->overwriteType(ErrorType::get(Context)); + typeAlias->setInterfaceType(ErrorType::get(Context)); } return; } @@ -7231,6 +7222,7 @@ void TypeChecker::validateDecl(ValueDecl *D, bool resolveTypeParams) { } } else { D->setType(ErrorType::get(Context)); + D->setInterfaceType(ErrorType::get(Context)); } } else { // FIXME: This case is hit when code completion occurs in a function @@ -7241,6 +7233,7 @@ void TypeChecker::validateDecl(ValueDecl *D, bool resolveTypeParams) { isa(D->getDeclContext()) || isa(D->getDeclContext())); D->setType(ErrorType::get(Context)); + D->setInterfaceType(ErrorType::get(Context)); } // Make sure the getter and setter have valid types, since they will be @@ -7358,6 +7351,7 @@ void TypeChecker::validateDecl(ValueDecl *D, bool resolveTypeParams) { typeCheckDecl(D, true); } else { D->setType(ErrorType::get(Context)); + D->setInterfaceType(ErrorType::get(Context)); } break; } diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index 9295eaa5a21..b37ace4dffa 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -883,6 +883,7 @@ bool TypeChecker::typeCheckPattern(Pattern *P, DeclContext *dc, if (auto var = named->getDecl()) { var->setInvalid(); var->overwriteType(ErrorType::get(Context)); + var->setInterfaceType(ErrorType::get(Context)); } } return true; @@ -970,6 +971,7 @@ static bool coercePatternViaConditionalDowncast(TypeChecker &tc, pattern->getLoc(), tc.Context.getIdentifier("$match"), type, dc); + matchVar->setInterfaceType(type); matchVar->setHasNonPatternBindingInit(); // Form the cast $match as? T, which produces an optional. @@ -1083,16 +1085,20 @@ bool TypeChecker::coercePatternToType(Pattern *&P, DeclContext *dc, Type type, NamedPattern *NP = cast(P); VarDecl *var = NP->getDecl(); if (var->isInvalid()) - var->overwriteType(ErrorType::get(Context)); + type = ErrorType::get(Context); + var->overwriteType(type); + if (type->hasTypeParameter()) + var->setInterfaceType(type); else - var->overwriteType(type); + var->setInterfaceType(ArchetypeBuilder::mapTypeOutOfContext( + var->getDeclContext(), type)); checkTypeModifyingDeclAttributes(var); if (type->is()) { NP->getDecl()->setLet(false); } if (var->getAttrs().hasAttribute()) - type = getTypeOfRValue(var, true); + type = getTypeOfRValue(var, false); else if (!var->isInvalid()) type = var->getType(); P->setType(type); diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index 9473b1773ce..fba1143d678 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -2256,19 +2256,22 @@ void ConformanceChecker::recordTypeWitness(AssociatedTypeDecl *assocType, /*genericparams*/nullptr, DC); aliasDecl->computeType(); - aliasDecl->setImplicit(); - if (type->hasError()) { - aliasDecl->setInvalid(); - // If we're recording a failed type witness, keep the sugar around for - // code completion. - type = aliasDecl->getDeclaredType(); - } else if (type->hasArchetype()) { - Type metaType = MetatypeType::get(type); + // Strip off sugar from the interface type if it is dependent. + // FIXME: Without this, the stdlib doesn't compile because + // 'typealias _Buffer' is insufficiently accessible. + if (type->hasArchetype()) { + auto metaType = MetatypeType::get(type); aliasDecl->setInterfaceType( ArchetypeBuilder::mapTypeOutOfContext(DC, metaType)); + } else { + aliasDecl->setInterfaceType(aliasDecl->getType()); } - + + aliasDecl->setImplicit(); + if (type->hasError()) + aliasDecl->setInvalid(); + // Inject the typealias into the nominal decl that conforms to the protocol. if (auto nominal = DC->getAsNominalTypeOrNominalTypeExtensionContext()) { TC.computeAccessibility(nominal); diff --git a/lib/Sema/TypeCheckREPL.cpp b/lib/Sema/TypeCheckREPL.cpp index 1c88af11cc6..4dd84cd107d 100644 --- a/lib/Sema/TypeCheckREPL.cpp +++ b/lib/Sema/TypeCheckREPL.cpp @@ -312,6 +312,7 @@ void REPLChecker::processREPLTopLevelExpr(Expr *E) { VarDecl *vd = new (Context) VarDecl(/*static*/ false, /*IsLet*/true, E->getStartLoc(), name, E->getType(), &SF); + vd->setInterfaceType(E->getType()); SF.Decls.push_back(vd); // Create a PatternBindingDecl to bind the expression into the decl. @@ -384,6 +385,7 @@ void REPLChecker::processREPLTopLevelPatternBinding(PatternBindingDecl *PBD) { VarDecl *vd = new (Context) VarDecl(/*static*/ false, /*IsLet*/true, PBD->getStartLoc(), name, pattern->getType(), &SF); + vd->setInterfaceType(pattern->getType()); SF.Decls.push_back(vd); diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index 20ce7f1fda7..f155440058e 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -664,6 +664,7 @@ public: generator = new (TC.Context) VarDecl(/*static*/ false, /*IsLet*/ false, S->getInLoc(), TC.Context.getIdentifier(name), generatorTy, DC); + generator->setInterfaceType(generatorTy); generator->setImplicit(); // Create a pattern binding to initialize the generator. @@ -877,6 +878,7 @@ public: // as invalid to silence follow-on errors. pattern->forEachVariable([&](VarDecl *VD) { VD->overwriteType(ErrorType::get(TC.Context)); + VD->setInterfaceType(ErrorType::get(TC.Context)); VD->setInvalid(); }); } @@ -897,8 +899,11 @@ public: TC.diagnose(VD->getLoc(), diag::type_mismatch_multiple_pattern_list, VD->getType(), expected->getType()); VD->overwriteType(ErrorType::get(TC.Context)); + VD->setInterfaceType(ErrorType::get(TC.Context)); VD->setInvalid(); + expected->overwriteType(ErrorType::get(TC.Context)); + expected->setInterfaceType(ErrorType::get(TC.Context)); expected->setInvalid(); } return; @@ -995,9 +1000,10 @@ bool TypeChecker::typeCheckCatchPattern(CatchStmt *S, DeclContext *DC) { // before we type-check the guard. (This will probably kill // most of the type-checking, but maybe not.) pattern->forEachVariable([&](VarDecl *var) { - var->overwriteType(ErrorType::get(Context)); - var->setInvalid(); - }); + var->overwriteType(ErrorType::get(Context)); + var->setInterfaceType(ErrorType::get(Context)); + var->setInvalid(); + }); } S->setErrorPattern(pattern); diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 6ab4afa4d1f..789389281b4 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -2521,7 +2521,12 @@ void Serializer::writeDecl(const Decl *D) { verifyAttrSerializable(param); auto contextID = addDeclContextRef(param->getDeclContext()); - Type type = param->hasType() ? param->getType() : nullptr; + Type type = (param->hasType() + ? param->getType() + : Type()); + Type interfaceType = (param->hasInterfaceType() + ? param->getInterfaceType() + : Type()); unsigned abbrCode = DeclTypeAbbrCodes[ParamLayout::Code]; ParamLayout::emitRecord(Out, ScratchRecord, abbrCode, @@ -2530,7 +2535,7 @@ void Serializer::writeDecl(const Decl *D) { contextID, param->isLet(), addTypeRef(type), - addTypeRef(param->getInterfaceType())); + addTypeRef(interfaceType)); break; } diff --git a/test/expr/closure/trailing.swift b/test/expr/closure/trailing.swift index df25183ba84..2c75893c389 100644 --- a/test/expr/closure/trailing.swift +++ b/test/expr/closure/trailing.swift @@ -84,7 +84,7 @@ func labeledArgumentAndTrailingClosure() { // Trailing closure binds to last parameter, always. takeTwoFuncsWithDefaults { "Hello, " + $0 } - takeTwoFuncsWithDefaults { $0 + 1 } // expected-error {{cannot convert value of type '(_) -> Int' to expected argument type '((String) -> String)?'}} + takeTwoFuncsWithDefaults { $0 + 1 } // expected-error {{cannot convert value of type '(Int) -> Int' to expected argument type '((String) -> String)?'}} takeTwoFuncsWithDefaults(f1: {$0 + 1 }) } diff --git a/validation-test/IDE/crashers/087-swift-declcontext-getparentmodule.swift b/validation-test/IDE/crashers/087-swift-declcontext-getparentmodule.swift deleted file mode 100644 index 648947ee253..00000000000 --- a/validation-test/IDE/crashers/087-swift-declcontext-getparentmodule.swift +++ /dev/null @@ -1,3 +0,0 @@ -// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s -// REQUIRES: asserts -struct c{class a=var f{let c:a{enum e#^A^# \ No newline at end of file diff --git a/validation-test/IDE/crashers_fixed/087-swift-declcontext-getparentmodule.swift b/validation-test/IDE/crashers_fixed/087-swift-declcontext-getparentmodule.swift new file mode 100644 index 00000000000..eac7aa1f9a2 --- /dev/null +++ b/validation-test/IDE/crashers_fixed/087-swift-declcontext-getparentmodule.swift @@ -0,0 +1,3 @@ +// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s +// REQUIRES: asserts +struct c{class a=var f{let c:a{enum e#^A^# diff --git a/validation-test/compiler_crashers/28382-swift-archetypebuilder-maptypeoutofcontext.swift b/validation-test/compiler_crashers_fixed/28382-swift-archetypebuilder-maptypeoutofcontext.swift similarity index 88% rename from validation-test/compiler_crashers/28382-swift-archetypebuilder-maptypeoutofcontext.swift rename to validation-test/compiler_crashers_fixed/28382-swift-archetypebuilder-maptypeoutofcontext.swift index 31539e53c37..c582cac29a9 100644 --- a/validation-test/compiler_crashers/28382-swift-archetypebuilder-maptypeoutofcontext.swift +++ b/validation-test/compiler_crashers_fixed/28382-swift-archetypebuilder-maptypeoutofcontext.swift @@ -5,7 +5,7 @@ // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// RUN: not --crash %target-swift-frontend %s -typecheck +// RUN: not %target-swift-frontend %s -typecheck // REQUIRES: asserts var b{{ }