diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp index b159a8494c566..9b6891c7452e2 100644 --- a/lib/Sema/CSBindings.cpp +++ b/lib/Sema/CSBindings.cpp @@ -1039,11 +1039,9 @@ bool TypeVarBindingProducer::computeNext() { // types, that's going to ensure that subtype relationship is // always preserved. auto *BGT = type->castTo(); - auto UGT = UnboundGenericType::get(BGT->getDecl(), BGT->getParent(), - BGT->getASTContext()); - auto dstLocator = TypeVar->getImpl().getLocator(); - auto newType = CS.openUnboundGenericType(UGT, dstLocator) + auto newType = CS.openUnboundGenericType(BGT->getDecl(), BGT->getParent(), + dstLocator) ->reconstituteSugar(/*recursive=*/false); addNewBinding(binding.withType(newType)); } diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 7b28796ae60b1..e4f8310ed326d 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -655,25 +655,19 @@ Optional> ConstraintSystem::getExprDepthAndParent( return None; } -Type -ConstraintSystem::openUnboundGenericType(UnboundGenericType *unbound, - ConstraintLocatorBuilder locator) { - auto unboundDecl = unbound->getDecl(); - auto parentTy = unbound->getParent(); +Type ConstraintSystem::openUnboundGenericType( + GenericTypeDecl *decl, Type parentTy, ConstraintLocatorBuilder locator) { if (parentTy) { parentTy = openUnboundGenericTypes(parentTy, locator); - unbound = UnboundGenericType::get(unboundDecl, parentTy, - getASTContext()); } // Open up the generic type. OpenedTypeMap replacements; - openGeneric(unboundDecl->getDeclContext(), unboundDecl->getGenericSignature(), - locator, replacements); + openGeneric(decl->getDeclContext(), decl->getGenericSignature(), locator, + replacements); if (parentTy) { - auto subs = parentTy->getContextSubstitutions( - unboundDecl->getDeclContext()); + auto subs = parentTy->getContextSubstitutions(decl->getDeclContext()); for (auto pair : subs) { auto found = replacements.find( cast(pair.first)); @@ -686,7 +680,7 @@ ConstraintSystem::openUnboundGenericType(UnboundGenericType *unbound, // Map the generic parameters to their corresponding type variables. llvm::SmallVector arguments; - for (auto gp : unboundDecl->getInnermostGenericParamTypes()) { + for (auto gp : decl->getInnermostGenericParamTypes()) { auto found = replacements.find( cast(gp->getCanonicalType())); assert(found != replacements.end() && @@ -699,8 +693,8 @@ ConstraintSystem::openUnboundGenericType(UnboundGenericType *unbound, // handle generic TypeAliases elsewhere, this can just become a // call to BoundGenericType::get(). return TypeChecker::applyUnboundGenericArguments( - unbound, unboundDecl, SourceLoc(), - TypeResolution::forContextual(DC, None), arguments); + decl, parentTy, SourceLoc(), TypeResolution::forContextual(DC, None), + arguments); } static void checkNestedTypeConstraints(ConstraintSystem &cs, Type type, @@ -791,7 +785,8 @@ Type ConstraintSystem::openUnboundGenericTypes( type = type.transform([&](Type type) -> Type { if (auto unbound = type->getAs()) { - return openUnboundGenericType(unbound, locator); + return openUnboundGenericType(unbound->getDecl(), unbound->getParent(), + locator); } return type; diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index 4c93b2ef74571..080f06cd2348a 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -3403,14 +3403,12 @@ class ConstraintSystem { /// Add implicit "load" expressions to the given expression. Expr *addImplicitLoadExpr(Expr *expr); - /// "Open" the given unbound type by introducing fresh type - /// variables for generic parameters and constructing a bound generic - /// type from these type variables. - /// - /// \param unbound The type to open. + /// "Open" the unbound generic type represented by the given declaration and + /// parent type by introducing fresh type variables for generic parameters + /// and constructing a bound generic type from these type variables. /// /// \returns The opened type. - Type openUnboundGenericType(UnboundGenericType *unbound, + Type openUnboundGenericType(GenericTypeDecl *decl, Type parentTy, ConstraintLocatorBuilder locator); /// "Open" the given type by replacing any occurrences of unbound diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 33097e7450936..6c6a1006cb0d5 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -725,9 +725,8 @@ static Type applyGenericArguments(Type type, TypeResolution resolution, // Make sure we have the right number of generic arguments. // FIXME: If we have fewer arguments than we need, that might be okay, if // we're allowed to deduce the remaining arguments from context. - auto genericDecl = cast(decl); auto genericArgs = generic->getGenericArgs(); - auto genericParams = genericDecl->getGenericParams(); + auto genericParams = decl->getGenericParams(); if (genericParams->size() != genericArgs.size()) { if (!options.contains(TypeResolutionFlags::SilenceErrors)) { diags.diagnose(loc, diag::type_parameter_count_mismatch, decl->getName(), @@ -756,10 +755,10 @@ static Type applyGenericArguments(Type type, TypeResolution resolution, } // FIXME: More principled handling of circularity. - if (!genericDecl->getGenericSignature()) { + if (!decl->getGenericSignature()) { diags.diagnose(loc, diag::recursive_decl_reference, - genericDecl->getDescriptiveKind(), genericDecl->getName()); - genericDecl->diagnose(diag::kind_declared_here, DescriptiveDeclKind::Type); + decl->getDescriptiveKind(), decl->getName()); + decl->diagnose(diag::kind_declared_here, DescriptiveDeclKind::Type); return ErrorType::get(ctx); } @@ -777,9 +776,8 @@ static Type applyGenericArguments(Type type, TypeResolution resolution, args.push_back(substTy); } - auto result = TypeChecker::applyUnboundGenericArguments( - unboundType, genericDecl, loc, - resolution, args); + const auto result = TypeChecker::applyUnboundGenericArguments( + decl, unboundType->getParent(), loc, resolution, args); const auto genericOptions = genericResolution.getOptions(); if (!genericOptions.contains(TypeResolutionFlags::AllowUnavailable)) { @@ -802,10 +800,10 @@ static Type applyGenericArguments(Type type, TypeResolution resolution, } /// Apply generic arguments to the given type. -Type TypeChecker::applyUnboundGenericArguments( - UnboundGenericType *unboundType, GenericTypeDecl *decl, - SourceLoc loc, TypeResolution resolution, - ArrayRef genericArgs) { +Type TypeChecker::applyUnboundGenericArguments(GenericTypeDecl *decl, + Type parentTy, SourceLoc loc, + TypeResolution resolution, + ArrayRef genericArgs) { assert(genericArgs.size() == decl->getGenericParams()->size() && "invalid arguments, use applyGenericArguments for diagnostic emitting"); @@ -826,20 +824,20 @@ Type TypeChecker::applyUnboundGenericArguments( // Get the substitutions for outer generic parameters from the parent // type. - if (auto parentType = unboundType->getParent()) { - if (parentType->hasUnboundGenericType()) { + if (parentTy) { + if (parentTy->hasUnboundGenericType()) { // If we're working with a nominal type declaration, just construct // a bound generic type without checking the generic arguments. if (auto *nominalDecl = dyn_cast(decl)) { - return BoundGenericType::get(nominalDecl, parentType, genericArgs); + return BoundGenericType::get(nominalDecl, parentTy, genericArgs); } assert(!resultType->hasTypeParameter()); return resultType; } - subs = parentType->getContextSubstitutions(decl->getDeclContext()); - skipRequirementsCheck |= parentType->hasTypeVariable(); + subs = parentTy->getContextSubstitutions(decl->getDeclContext()); + skipRequirementsCheck |= parentTy->hasTypeVariable(); } else if (auto genericEnv = decl->getDeclContext()->getGenericEnvironmentOfContext()) { auto genericSig = genericEnv->getGenericSignature(); @@ -876,11 +874,11 @@ Type TypeChecker::applyUnboundGenericArguments( if (!skipRequirementsCheck && resolution.getStage() > TypeResolutionStage::Structural) { - auto result = - checkGenericArguments(dc, loc, noteLoc, unboundType, - genericSig->getGenericParams(), - genericSig->getRequirements(), - QueryTypeSubstitutionMap{subs}); + auto result = checkGenericArguments( + dc, loc, noteLoc, + UnboundGenericType::get(decl, parentTy, dc->getASTContext()), + genericSig->getGenericParams(), genericSig->getRequirements(), + QueryTypeSubstitutionMap{subs}); switch (result) { case RequirementCheckResult::Failure: @@ -903,14 +901,12 @@ Type TypeChecker::applyUnboundGenericArguments( LookUpConformanceInModule(module)); // Form a sugared typealias reference. - Type parentType = unboundType->getParent(); - if (typealias && (!parentType || !parentType->isAnyExistentialType())) { + if (typealias && (!parentTy || !parentTy->isAnyExistentialType())) { auto genericSig = typealias->getGenericSignature(); auto subMap = SubstitutionMap::get(genericSig, QueryTypeSubstitutionMap{subs}, LookUpConformanceInModule(module)); - resultType = TypeAliasType::get(typealias, parentType, - subMap, resultType); + resultType = TypeAliasType::get(typealias, parentTy, subMap, resultType); } return resultType; @@ -3311,17 +3307,16 @@ Type TypeResolver::resolveDictionaryType(DictionaryTypeRepr *repr, return ErrorType::get(Context); } - auto dictDecl = Context.getDictionaryDecl(); + auto *const dictDecl = Context.getDictionaryDecl(); if (!dictDecl) { Context.Diags.diagnose(repr->getBrackets().Start, diag::sugar_type_not_found, 3); return ErrorType::get(Context); } - auto unboundTy = dictDecl->getDeclaredType()->castTo(); - Type args[] = {keyTy, valueTy}; if (!TypeChecker::applyUnboundGenericArguments( - unboundTy, dictDecl, repr->getStartLoc(), resolution, args)) { + dictDecl, nullptr, repr->getStartLoc(), resolution, + {keyTy, valueTy})) { assert(Context.Diags.hadAnyError()); return ErrorType::get(Context); } diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index 7315910400fff..282f2adae235e 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -383,25 +383,25 @@ void checkUnsupportedProtocolType(ASTContext &ctx, Type resolveTypeInContext(TypeDecl *typeDecl, DeclContext *foundDC, TypeResolution resolution, bool isSpecialized); -/// Apply generic arguments to the given type. +/// Apply generic arguments to the unbound generic type represented by the +/// given declaration and parent type. /// -/// This function requires a valid unbound generic type with the correct -/// number of generic arguments given, whereas applyGenericArguments emits -/// diagnostics in those cases. +/// This function requires the correct number of generic arguments, +/// whereas applyGenericArguments emits diagnostics in those cases. /// -/// \param unboundType The unbound generic type to which to apply arguments. -/// \param decl The declaration of the type. +/// \param decl The declaration that the resulting bound generic type +/// shall reference. +/// \param parentTy The parent type. /// \param loc The source location for diagnostic reporting. /// \param resolution The type resolution. -/// \param genericArgs The list of generic arguments to apply to the type. +/// \param genericArgs The list of generic arguments to apply. /// /// \returns A BoundGenericType bound to the given arguments, or null on /// error. /// /// \see applyGenericArguments -Type applyUnboundGenericArguments(UnboundGenericType *unboundType, - GenericTypeDecl *decl, SourceLoc loc, - TypeResolution resolution, +Type applyUnboundGenericArguments(GenericTypeDecl *decl, Type parentTy, + SourceLoc loc, TypeResolution resolution, ArrayRef genericArgs); /// Substitute the given base type into the type of the given nested type,