Skip to content

Commit d5c014b

Browse files
committed
Remove validateDeclForNameLookup
Flush it and the early validation hack now that we can delay computing the underlying interface type on demand and have taught type resolution to honor the structural type of a typealias. This changes the way requirement signatures are spelled as a side effect.
1 parent 5e34169 commit d5c014b

File tree

10 files changed

+21
-298
lines changed

10 files changed

+21
-298
lines changed

lib/Sema/TypeCheckAttr.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -1070,7 +1070,7 @@ bool swift::isValidDynamicCallableMethod(FuncDecl *decl, DeclContext *DC,
10701070
// `ExpressibleByStringLiteral`.
10711071
// `D.Value` and the return type can be arbitrary.
10721072

1073-
TC.validateDeclForNameLookup(decl);
1073+
TC.validateDecl(decl);
10741074
auto paramList = decl->getParameters();
10751075
if (paramList->size() != 1 || paramList->get(0)->isVariadic()) return false;
10761076
auto argType = paramList->get(0)->getType();
@@ -1241,7 +1241,7 @@ visitDynamicMemberLookupAttr(DynamicMemberLookupAttr *attr) {
12411241
auto oneCandidate = candidates.front().getValueDecl();
12421242
candidates.filter([&](LookupResultEntry entry, bool isOuter) -> bool {
12431243
auto cand = cast<SubscriptDecl>(entry.getValueDecl());
1244-
TC.validateDeclForNameLookup(cand);
1244+
TC.validateDecl(cand);
12451245
return isValidDynamicMemberLookupSubscript(cand, decl, TC);
12461246
});
12471247

@@ -1264,7 +1264,7 @@ visitDynamicMemberLookupAttr(DynamicMemberLookupAttr *attr) {
12641264
// Validate the candidates while ignoring the label.
12651265
newCandidates.filter([&](const LookupResultEntry entry, bool isOuter) {
12661266
auto cand = cast<SubscriptDecl>(entry.getValueDecl());
1267-
TC.validateDeclForNameLookup(cand);
1267+
TC.validateDecl(cand);
12681268
return isValidDynamicMemberLookupSubscript(cand, decl, TC,
12691269
/*ignoreLabel*/ true);
12701270
});

lib/Sema/TypeCheckDecl.cpp

+5-281
Original file line numberDiff line numberDiff line change
@@ -3861,34 +3861,6 @@ void TypeChecker::validateDecl(ValueDecl *D) {
38613861
(void)proto->getGenericSignature();
38623862
proto->setSignatureIsValidated();
38633863

3864-
// See the comment in validateDeclForNameLookup(); we may have validated
3865-
// the alias before we built the protocol's generic environment.
3866-
//
3867-
// FIXME: Hopefully this can all go away with the ITC.
3868-
for (auto member : proto->getMembers()) {
3869-
if (auto *aliasDecl = dyn_cast<TypeAliasDecl>(member)) {
3870-
if (!aliasDecl->isGeneric()) {
3871-
// FIXME: Force creation of the protocol's generic environment now.
3872-
(void) proto->getGenericEnvironment();
3873-
3874-
// The generic environment didn't exist until now, we may have
3875-
// unresolved types we will need to deal with, and need to record the
3876-
// appropriate substitutions for that environment. Wipe out the types
3877-
// and validate them again.
3878-
aliasDecl->getUnderlyingTypeLoc().setType(Type());
3879-
aliasDecl->setInterfaceType(Type());
3880-
3881-
// Check generic parameters, if needed.
3882-
if (aliasDecl->hasValidationStarted()) {
3883-
validateTypealiasType(*this, aliasDecl);
3884-
} else {
3885-
DeclValidationRAII IBV(aliasDecl);
3886-
validateTypealiasType(*this, aliasDecl);
3887-
}
3888-
}
3889-
}
3890-
}
3891-
38923864
break;
38933865
}
38943866

@@ -4209,90 +4181,6 @@ void TypeChecker::validateDecl(ValueDecl *D) {
42094181
assert(D->hasValidSignature());
42104182
}
42114183

4212-
void TypeChecker::validateDeclForNameLookup(ValueDecl *D) {
4213-
// Validate the context.
4214-
auto dc = D->getDeclContext();
4215-
if (auto nominal = dyn_cast<NominalTypeDecl>(dc)) {
4216-
validateDeclForNameLookup(nominal);
4217-
if (!nominal->hasInterfaceType())
4218-
return;
4219-
} else if (auto ext = dyn_cast<ExtensionDecl>(dc)) {
4220-
validateExtension(ext);
4221-
if (!ext->hasValidSignature())
4222-
return;
4223-
}
4224-
4225-
switch (D->getKind()) {
4226-
case DeclKind::Protocol: {
4227-
auto proto = cast<ProtocolDecl>(D);
4228-
if (proto->hasInterfaceType())
4229-
return;
4230-
proto->computeType();
4231-
4232-
break;
4233-
}
4234-
case DeclKind::AssociatedType: {
4235-
auto assocType = cast<AssociatedTypeDecl>(D);
4236-
if (assocType->hasInterfaceType())
4237-
return;
4238-
assocType->computeType();
4239-
break;
4240-
}
4241-
case DeclKind::TypeAlias: {
4242-
auto typealias = cast<TypeAliasDecl>(D);
4243-
if (typealias->getUnderlyingTypeLoc().getType())
4244-
return;
4245-
4246-
// Perform earlier validation of typealiases in protocols.
4247-
if (isa<ProtocolDecl>(dc)) {
4248-
if (!typealias->getGenericParams()) {
4249-
if (typealias->isBeingValidated()) return;
4250-
4251-
auto helper = [&] {
4252-
TypeResolutionOptions options(
4253-
(typealias->getGenericParams() ?
4254-
TypeResolverContext::GenericTypeAliasDecl :
4255-
TypeResolverContext::TypeAliasDecl));
4256-
auto &underlyingTL = typealias->getUnderlyingTypeLoc();
4257-
if (underlyingTL.isNull() ||
4258-
TypeChecker::validateType(Context,
4259-
underlyingTL,
4260-
TypeResolution::forStructural(typealias),
4261-
options)) {
4262-
typealias->setInvalid();
4263-
underlyingTL.setInvalidType(Context);
4264-
}
4265-
4266-
typealias->setUnderlyingType(underlyingTL.getType());
4267-
4268-
// Note that this doesn't set the generic environment of the alias yet,
4269-
// because we haven't built one for the protocol.
4270-
//
4271-
// See how validateDecl() sets the generic environment on alias members
4272-
// explicitly.
4273-
//
4274-
// FIXME: Hopefully this can all go away with the ITC.
4275-
};
4276-
4277-
if (typealias->hasValidationStarted()) {
4278-
helper();
4279-
} else {
4280-
DeclValidationRAII IBV(typealias);
4281-
helper();
4282-
}
4283-
4284-
return;
4285-
}
4286-
}
4287-
LLVM_FALLTHROUGH;
4288-
}
4289-
4290-
default:
4291-
validateDecl(D);
4292-
break;
4293-
}
4294-
}
4295-
42964184
llvm::Expected<DeclRange>
42974185
EmittedMembersRequest::evaluate(Evaluator &evaluator,
42984186
ClassDecl *CD) const {
@@ -4333,35 +4221,11 @@ EmittedMembersRequest::evaluate(Evaluator &evaluator,
43334221
return CD->getMembers();
43344222
}
43354223

4336-
<<<<<<< HEAD
4337-
bool TypeChecker::isPassThroughTypealias(TypeAliasDecl *typealias) {
4224+
bool TypeChecker::isPassThroughTypealias(TypeAliasDecl *typealias,
4225+
Type underlyingType,
4226+
NominalTypeDecl *nominal) {
43384227
// Pass-through only makes sense when the typealias refers to a nominal
43394228
// type.
4340-
Type underlyingType = typealias->getUnderlyingTypeLoc().getType();
4341-
auto nominal = underlyingType->getAnyNominal();
4342-
=======
4343-
/// Determine whether this is a "pass-through" typealias, which has the
4344-
/// same type parameters as the nominal type it references and specializes
4345-
/// the underlying nominal type with exactly those type parameters.
4346-
/// For example, the following typealias \c GX is a pass-through typealias:
4347-
///
4348-
/// \code
4349-
/// struct X<T, U> { }
4350-
/// typealias GX<A, B> = X<A, B>
4351-
/// \endcode
4352-
///
4353-
/// whereas \c GX2 and \c GX3 are not pass-through because \c GX2 has
4354-
/// different type parameters and \c GX3 doesn't pass its type parameters
4355-
/// directly through.
4356-
///
4357-
/// \code
4358-
/// typealias GX2<A> = X<A, A>
4359-
/// typealias GX3<A, B> = X<B, A>
4360-
/// \endcode
4361-
static bool isPassThroughTypealias(TypeAliasDecl *typealias,
4362-
Type underlyingType,
4363-
NominalTypeDecl *nominal) {
4364-
>>>>>>> Separate computing interface types and underlying types
43654229
if (!nominal) return false;
43664230

43674231
// Check that the nominal type and the typealias are either both generic
@@ -4410,138 +4274,6 @@ static bool isPassThroughTypealias(TypeAliasDecl *typealias,
44104274
});
44114275
}
44124276

4413-
<<<<<<< HEAD
4414-
=======
4415-
/// Form the interface type of an extension from the raw type and the
4416-
/// extension's list of generic parameters.
4417-
static Type formExtensionInterfaceType(
4418-
TypeChecker &tc, ExtensionDecl *ext,
4419-
Type type,
4420-
GenericParamList *genericParams,
4421-
SmallVectorImpl<Requirement> &sameTypeReqs,
4422-
bool &mustInferRequirements) {
4423-
if (type->is<ErrorType>())
4424-
return type;
4425-
4426-
// Find the nominal type declaration and its parent type.
4427-
if (type->is<ProtocolCompositionType>())
4428-
type = type->getCanonicalType();
4429-
4430-
Type parentType = type->getNominalParent();
4431-
GenericTypeDecl *genericDecl = type->getAnyGeneric();
4432-
4433-
// Reconstruct the parent, if there is one.
4434-
if (parentType) {
4435-
// Build the nested extension type.
4436-
auto parentGenericParams = genericDecl->getGenericParams()
4437-
? genericParams->getOuterParameters()
4438-
: genericParams;
4439-
parentType =
4440-
formExtensionInterfaceType(tc, ext, parentType, parentGenericParams,
4441-
sameTypeReqs, mustInferRequirements);
4442-
}
4443-
4444-
// Find the nominal type.
4445-
auto nominal = dyn_cast<NominalTypeDecl>(genericDecl);
4446-
auto typealias = dyn_cast<TypeAliasDecl>(genericDecl);
4447-
if (!nominal) {
4448-
Type underlyingType = typealias->getUnderlyingTypeLoc().getType();
4449-
nominal = underlyingType->getNominalOrBoundGenericNominal();
4450-
}
4451-
4452-
// Form the result.
4453-
Type resultType;
4454-
SmallVector<Type, 2> genericArgs;
4455-
if (!nominal->isGeneric() || isa<ProtocolDecl>(nominal)) {
4456-
resultType = NominalType::get(nominal, parentType,
4457-
nominal->getASTContext());
4458-
} else {
4459-
auto currentBoundType = type->getAs<BoundGenericType>();
4460-
4461-
// Form the bound generic type with the type parameters provided.
4462-
unsigned gpIndex = 0;
4463-
for (auto gp : *genericParams) {
4464-
SWIFT_DEFER { ++gpIndex; };
4465-
4466-
auto gpType = gp->getDeclaredInterfaceType();
4467-
genericArgs.push_back(gpType);
4468-
4469-
if (currentBoundType) {
4470-
sameTypeReqs.emplace_back(RequirementKind::SameType, gpType,
4471-
currentBoundType->getGenericArgs()[gpIndex]);
4472-
}
4473-
}
4474-
4475-
resultType = BoundGenericType::get(nominal, parentType, genericArgs);
4476-
}
4477-
4478-
// If we have a typealias, try to form type sugar.
4479-
if (typealias && isPassThroughTypealias(typealias, typealias->getUnderlyingType(), nominal)) {
4480-
auto typealiasSig = typealias->getGenericSignature();
4481-
SubstitutionMap subMap;
4482-
if (typealiasSig) {
4483-
subMap = typealiasSig->getIdentitySubstitutionMap();
4484-
4485-
mustInferRequirements = true;
4486-
}
4487-
4488-
resultType = TypeAliasType::get(typealias, parentType, subMap,
4489-
resultType);
4490-
}
4491-
4492-
return resultType;
4493-
}
4494-
4495-
/// Retrieve the generic parameter depth of the extended type.
4496-
static unsigned getExtendedTypeGenericDepth(ExtensionDecl *ext) {
4497-
auto nominal = ext->getSelfNominalTypeDecl();
4498-
if (!nominal) return static_cast<unsigned>(-1);
4499-
4500-
auto sig = nominal->getGenericSignatureOfContext();
4501-
if (!sig) return static_cast<unsigned>(-1);
4502-
4503-
return sig->getGenericParams().back()->getDepth();
4504-
}
4505-
4506-
/// Check the generic parameters of an extension, recursively handling all of
4507-
/// the parameter lists within the extension.
4508-
static GenericSignature *
4509-
checkExtensionGenericParams(TypeChecker &tc, ExtensionDecl *ext,
4510-
GenericParamList *genericParams) {
4511-
assert(!ext->getGenericEnvironment());
4512-
4513-
// Form the interface type of the extension.
4514-
bool mustInferRequirements = false;
4515-
SmallVector<Requirement, 2> sameTypeReqs;
4516-
Type extInterfaceType =
4517-
formExtensionInterfaceType(tc, ext, ext->getExtendedType(),
4518-
genericParams, sameTypeReqs,
4519-
mustInferRequirements);
4520-
4521-
assert(genericParams && "Missing generic parameters?");
4522-
4523-
auto cannotReuseNominalSignature = [&]() -> bool {
4524-
const auto finalDepth = genericParams->getParams().back()->getDepth();
4525-
return mustInferRequirements
4526-
|| !sameTypeReqs.empty()
4527-
|| ext->getTrailingWhereClause()
4528-
|| (getExtendedTypeGenericDepth(ext) != finalDepth);
4529-
};
4530-
4531-
// Re-use the signature of the type being extended by default.
4532-
if (cannotReuseNominalSignature()) {
4533-
return TypeChecker::checkGenericSignature(
4534-
genericParams, ext,
4535-
/*parent signature*/ nullptr,
4536-
/*allowConcreteGenericParams=*/true,
4537-
sameTypeReqs,
4538-
{TypeLoc{nullptr, extInterfaceType}});
4539-
}
4540-
4541-
return ext->getSelfNominalTypeDecl()->getGenericSignatureOfContext();
4542-
}
4543-
4544-
>>>>>>> Separate computing interface types and underlying types
45454277
static bool isNonGenericTypeAliasType(Type type) {
45464278
// A non-generic typealias can extend a specialized type.
45474279
if (auto *aliasType = dyn_cast<TypeAliasType>(type.getPointer()))
@@ -4574,28 +4306,20 @@ ExtendedTypeRequest::evaluate(Evaluator &eval, ExtensionDecl *ext) const {
45744306
// Hack to allow extending a generic typealias.
45754307
if (auto *unboundGeneric = extendedType->getAs<UnboundGenericType>()) {
45764308
if (auto *aliasDecl = dyn_cast<TypeAliasDecl>(unboundGeneric->getDecl())) {
4577-
<<<<<<< HEAD
4578-
auto extendedNominal = aliasDecl->getDeclaredInterfaceType()->getAnyNominal();
4579-
if (extendedNominal)
4580-
return TypeChecker::isPassThroughTypealias(aliasDecl)
4581-
? extendedType
4582-
: extendedNominal->getDeclaredType();
4583-
=======
45844309
// Nested Hack to break cycles if this is called before validation has
45854310
// finished.
45864311
if (aliasDecl->hasInterfaceType()) {
45874312
auto extendedNominal = aliasDecl->getDeclaredInterfaceType()->getAnyNominal();
45884313
if (extendedNominal)
4589-
return isPassThroughTypealias(aliasDecl, aliasDecl->getUnderlyingType(), extendedNominal)
4314+
return TypeChecker::isPassThroughTypealias(aliasDecl, aliasDecl->getUnderlyingType(), extendedNominal)
45904315
? extendedType
45914316
: extendedNominal->getDeclaredType();
45924317
} else {
45934318
if (auto ty = aliasDecl->getStructuralType()->getAs<NominalOrBoundGenericNominalType>())
4594-
return isPassThroughTypealias(aliasDecl, ty, ty->getDecl())
4319+
return TypeChecker::isPassThroughTypealias(aliasDecl, ty, ty->getDecl())
45954320
? extendedType
45964321
: ty->getDecl()->getDeclaredType();
45974322
}
4598-
>>>>>>> Separate computing interface types and underlying types
45994323
}
46004324
}
46014325

lib/Sema/TypeCheckGeneric.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ static Type formExtensionInterfaceType(
525525
auto nominal = dyn_cast<NominalTypeDecl>(genericDecl);
526526
auto typealias = dyn_cast<TypeAliasDecl>(genericDecl);
527527
if (!nominal) {
528-
Type underlyingType = typealias->getUnderlyingTypeLoc().getType();
528+
Type underlyingType = typealias->getUnderlyingType();
529529
nominal = underlyingType->getNominalOrBoundGenericNominal();
530530
}
531531

@@ -556,7 +556,7 @@ static Type formExtensionInterfaceType(
556556
}
557557

558558
// If we have a typealias, try to form type sugar.
559-
if (typealias && TypeChecker::isPassThroughTypealias(typealias)) {
559+
if (typealias && TypeChecker::isPassThroughTypealias(typealias, typealias->getUnderlyingType(), nominal)) {
560560
auto typealiasSig = typealias->getGenericSignature();
561561
SubstitutionMap subMap;
562562
if (typealiasSig) {

lib/Sema/TypeCheckPattern.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1497,7 +1497,7 @@ bool TypeChecker::coercePatternToType(Pattern *&P, TypeResolution resolution,
14971497
}
14981498

14991499
// If there is a subpattern, push the enum element type down onto it.
1500-
validateDeclForNameLookup(elt);
1500+
validateDecl(elt);
15011501
if (EEP->hasSubPattern()) {
15021502
Pattern *sub = EEP->getSubPattern();
15031503
if (!elt->hasAssociatedValues()) {

0 commit comments

Comments
 (0)