Skip to content

[NFC] Sema: Internalize the use of UnboundGenericType in applyUnboundGenericArguments #32340

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions lib/Sema/CSBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1039,11 +1039,9 @@ bool TypeVarBindingProducer::computeNext() {
// types, that's going to ensure that subtype relationship is
// always preserved.
auto *BGT = type->castTo<BoundGenericType>();
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));
}
Expand Down
25 changes: 10 additions & 15 deletions lib/Sema/ConstraintSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -655,25 +655,19 @@ Optional<std::pair<unsigned, Expr *>> 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<GenericTypeParamType>(pair.first));
Expand All @@ -686,7 +680,7 @@ ConstraintSystem::openUnboundGenericType(UnboundGenericType *unbound,

// Map the generic parameters to their corresponding type variables.
llvm::SmallVector<Type, 2> arguments;
for (auto gp : unboundDecl->getInnermostGenericParamTypes()) {
for (auto gp : decl->getInnermostGenericParamTypes()) {
auto found = replacements.find(
cast<GenericTypeParamType>(gp->getCanonicalType()));
assert(found != replacements.end() &&
Expand All @@ -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,
Expand Down Expand Up @@ -791,7 +785,8 @@ Type ConstraintSystem::openUnboundGenericTypes(

type = type.transform([&](Type type) -> Type {
if (auto unbound = type->getAs<UnboundGenericType>()) {
return openUnboundGenericType(unbound, locator);
return openUnboundGenericType(unbound->getDecl(), unbound->getParent(),
locator);
}

return type;
Expand Down
10 changes: 4 additions & 6 deletions lib/Sema/ConstraintSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
55 changes: 25 additions & 30 deletions lib/Sema/TypeCheckType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<GenericTypeDecl>(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(),
Expand Down Expand Up @@ -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);
}

Expand All @@ -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)) {
Expand All @@ -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<Type> genericArgs) {
Type TypeChecker::applyUnboundGenericArguments(GenericTypeDecl *decl,
Type parentTy, SourceLoc loc,
TypeResolution resolution,
ArrayRef<Type> genericArgs) {
assert(genericArgs.size() == decl->getGenericParams()->size() &&
"invalid arguments, use applyGenericArguments for diagnostic emitting");

Expand All @@ -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<NominalTypeDecl>(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();
Expand Down Expand Up @@ -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:
Expand All @@ -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;
Expand Down Expand Up @@ -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<UnboundGenericType>();
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);
}
Expand Down
20 changes: 10 additions & 10 deletions lib/Sema/TypeChecker.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<Type> genericArgs);

/// Substitute the given base type into the type of the given nested type,
Expand Down