Skip to content

Commit 18adb53

Browse files
committed
Sema: Tighten up name lookup routines to not look through metatypes/lvalues/etc
Previously all of the following would strip off varying amounts of MetatypeType, LValueType, InOutType, DynamicSelfType, etc: - ConstraintSystem::performMemberLookup() - ConstraintSystem::lookupMember() - TypeChecker::lookupMember() - DeclContext::lookupQualified() - Type::getContextSubstitutions() The problem is that the higher level methods that took a lookup type would call the lower level methods, and post-process the result using the given lookup type. Since different levels of sugar were stripped, it made the code hard to reason about and opened up edge cases, eg if a DynamicSelfType or InOutType appears where we didn't expect it. Since filtering out static/instance and mutating/nonmutating members is done at higher levels, there's no reason for these name lookup operations to accept anything other than nominal types, existentials and archetypes. Make this so with assertions, and deal with the fallout.
1 parent 584f47d commit 18adb53

19 files changed

+152
-159
lines changed

include/swift/AST/Types.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -648,9 +648,17 @@ class alignas(1 << TypeAlignInBits) TypeBase {
648648
/// with a class type.
649649
bool mayHaveSuperclass();
650650

651-
/// \brief Determine whether this type may have nested types, which holds for
652-
/// nominal types, existentials and archetypes.
653-
bool mayHaveMemberTypes() {
651+
/// \brief Determine whether this type can be used as a base type for AST
652+
/// name lookup, which is the case for nominal types, protocol compositions
653+
/// and archetypes.
654+
///
655+
/// Generally, the static vs instanec and mutating vs nonmutating distinction
656+
/// is handled elsewhere, so metatypes, lvalue types and inout types are not
657+
/// allowed here.
658+
///
659+
/// Similarly, tuples formally have members, but this does not go through
660+
/// name lookup.
661+
bool mayHaveMembers() {
654662
return (is<ArchetypeType>() ||
655663
is<ModuleType>() ||
656664
isExistentialType() ||

lib/AST/ASTPrinter.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ struct SynthesizedExtensionAnalyzer::Implementation {
224224
// the extension to the interface types of the base type's
225225
// declaration.
226226
TypeSubstitutionMap subMap;
227-
if (!BaseType->isAnyExistentialType())
227+
if (!BaseType->isExistentialType())
228228
subMap = BaseType->getContextSubstitutions(Ext);
229229
auto *M = DC->getParentModule();
230230

@@ -453,7 +453,9 @@ void PrintOptions::clearSynthesizedExtension() {
453453
}
454454

455455
TypeTransformContext::TypeTransformContext(Type T)
456-
: BaseType(T.getPointer()) {}
456+
: BaseType(T.getPointer()) {
457+
assert(T->mayHaveMembers());
458+
}
457459

458460
TypeTransformContext::TypeTransformContext(NominalTypeDecl *NTD)
459461
: BaseType(NTD->getDeclaredTypeInContext().getPointer()), Nominal(NTD) {}
@@ -984,8 +986,9 @@ class PrintAST : public ASTVisitor<PrintAST> {
984986
Type OldType = CurrentType;
985987
if (CurrentType && (Old != nullptr || Options.PrintAsMember)) {
986988
if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
987-
CurrentType = CurrentType->getTypeOfMember(
988-
Options.CurrentModule, NTD, nullptr);
989+
CurrentType = NTD->getDeclaredInterfaceType().subst(
990+
Options.CurrentModule,
991+
CurrentType->getContextSubstitutions(NTD->getDeclContext()));
989992
}
990993
}
991994

@@ -1259,7 +1262,7 @@ void PrintAST::printSingleDepthOfGenericSignature(
12591262
ModuleDecl *M = nullptr;
12601263

12611264
if (CurrentType) {
1262-
if (!CurrentType->isAnyExistentialType()) {
1265+
if (!CurrentType->isExistentialType()) {
12631266
auto *DC = Current->getInnermostDeclContext()->getInnermostTypeContext();
12641267
subMap = CurrentType->getContextSubstitutions(DC);
12651268
M = DC->getParentModule();

lib/AST/NameLookup.cpp

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,17 +1316,6 @@ bool DeclContext::lookupQualified(Type type,
13161316
}
13171317
};
13181318

1319-
// Look through lvalue and inout types.
1320-
type = type->getLValueOrInOutObjectType();
1321-
1322-
// Look through metatypes.
1323-
if (auto metaTy = type->getAs<AnyMetatypeType>())
1324-
type = metaTy->getInstanceType();
1325-
1326-
// Look through DynamicSelf.
1327-
if (auto dynamicSelf = type->getAs<DynamicSelfType>())
1328-
type = dynamicSelf->getSelfType();
1329-
13301319
// Look for module references.
13311320
if (auto moduleTy = type->getAs<ModuleType>()) {
13321321
Module *module = moduleTy->getModule();
@@ -1438,6 +1427,8 @@ bool DeclContext::lookupQualified(Type type,
14381427
}
14391428
}
14401429
}
1430+
} else {
1431+
llvm_unreachable("Bad type for qualified lookup");
14411432
}
14421433

14431434
// Allow filtering of the visible declarations based on various

lib/AST/Type.cpp

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3099,23 +3099,15 @@ Type TypeBase::getSuperclassForDecl(const ClassDecl *baseClass,
30993099
}
31003100

31013101
TypeSubstitutionMap TypeBase::getContextSubstitutions(const DeclContext *dc) {
3102+
assert(dc->isTypeContext());
3103+
Type baseTy(this);
31023104

3103-
// Ignore lvalues in the base type.
3104-
Type baseTy(getRValueType());
3105-
3106-
// Look through the metatype; it has no bearing on the result.
3107-
if (auto metaBase = baseTy->getAs<AnyMetatypeType>()) {
3108-
baseTy = metaBase->getInstanceType()->getRValueType();
3109-
}
3105+
assert(!baseTy->isLValueType() && !baseTy->is<AnyMetatypeType>());
31103106

31113107
// The resulting set of substitutions. Always use this to ensure we
31123108
// don't miss out on NRVO anywhere.
31133109
TypeSubstitutionMap substitutions;
31143110

3115-
// Look through non-type contexts.
3116-
while (!dc->isTypeContext())
3117-
dc = dc->getParent();
3118-
31193111
// If the member is part of a protocol or extension thereof, we need
31203112
// to substitute in the type of Self.
31213113
if (dc->getAsProtocolOrProtocolExtensionContext()) {
@@ -3127,19 +3119,24 @@ TypeSubstitutionMap TypeBase::getContextSubstitutions(const DeclContext *dc) {
31273119
return substitutions;
31283120
}
31293121

3122+
// If we found a member of a concrete type from a protocol extension,
3123+
// get the superclass out of the archetype.
3124+
if (auto *archetypeTy = baseTy->getAs<ArchetypeType>())
3125+
baseTy = archetypeTy->getSuperclass();
3126+
31303127
// Extract the lazy resolver.
31313128
LazyResolver *resolver = dc->getASTContext().getLazyResolver();
31323129

31333130
// Find the superclass type with the context matching that of the member.
31343131
//
31353132
// FIXME: Do this in the caller?
3136-
if (baseTy->getAnyNominal()) {
3137-
auto *ownerNominal = dc->getAsNominalTypeOrNominalTypeExtensionContext();
3138-
if (auto *ownerClass = dyn_cast<ClassDecl>(ownerNominal))
3139-
baseTy = baseTy->getSuperclassForDecl(ownerClass, resolver);
3133+
assert(baseTy->getAnyNominal());
31403134

3141-
assert(ownerNominal == baseTy->getAnyNominal());
3142-
}
3135+
auto *ownerNominal = dc->getAsNominalTypeOrNominalTypeExtensionContext();
3136+
if (auto *ownerClass = dyn_cast<ClassDecl>(ownerNominal))
3137+
baseTy = baseTy->getSuperclassForDecl(ownerClass, resolver);
3138+
3139+
assert(ownerNominal == baseTy->getAnyNominal());
31433140

31443141
// If the base type isn't specialized, there's nothing to substitute.
31453142
if (!baseTy->isSpecialized())
@@ -3177,8 +3174,7 @@ TypeSubstitutionMap TypeBase::getContextSubstitutions(const DeclContext *dc) {
31773174
continue;
31783175
}
31793176

3180-
// We're done.
3181-
break;
3177+
llvm_unreachable("Bad base type");
31823178
}
31833179

31843180
return substitutions;

lib/IDE/CodeCompletion.cpp

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1975,8 +1975,13 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
19751975
Type ContextTy = VD->getDeclContext()->getDeclaredInterfaceType();
19761976
if (ContextTy) {
19771977
// Look through lvalue types and metatypes
1978-
Type MaybeNominalType = (*ExprType)->getRValueType()
1979-
->getRValueInstanceType();
1978+
Type MaybeNominalType = (*ExprType)->getRValueType();
1979+
1980+
if (auto Metatype = MaybeNominalType->getAs<MetatypeType>())
1981+
MaybeNominalType = Metatype->getInstanceType();
1982+
1983+
if (auto SelfType = MaybeNominalType->getAs<DynamicSelfType>())
1984+
MaybeNominalType = SelfType->getSelfType();
19801985

19811986
// For optional protocol requirements and dynamic dispatch,
19821987
// strip off optionality from the base type, but only if
@@ -1989,6 +1994,12 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
19891994
if (MaybeNominalType->isAnyObject())
19901995
return T;
19911996

1997+
// FIXME: Sometimes ExprType is the type of the member here,
1998+
// and not the type of the base. That is inconsistent and
1999+
// should be cleaned up.
2000+
if (!MaybeNominalType->mayHaveMembers())
2001+
return T;
2002+
19922003
// For everything else, substitute in the base type.
19932004
auto Subs = MaybeNominalType->getMemberSubstitutions(VD);
19942005

@@ -2865,23 +2876,24 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
28652876

28662877
if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
28672878
addNominalTypeRef(NTD, Reason);
2868-
addConstructorCallsForType(NTD->getInterfaceType(), NTD->getName(),
2869-
Reason);
2879+
addConstructorCallsForType(NTD->getDeclaredInterfaceType(),
2880+
NTD->getName(), Reason);
28702881
return;
28712882
}
28722883

28732884
if (auto *TAD = dyn_cast<TypeAliasDecl>(D)) {
28742885
addTypeAliasRef(TAD, Reason);
28752886
auto type = TAD->mapTypeIntoContext(TAD->getUnderlyingTypeLoc().getType());
2876-
addConstructorCallsForType(type, TAD->getName(), Reason);
2887+
if (type->mayHaveMembers())
2888+
addConstructorCallsForType(type, TAD->getName(), Reason);
28772889
return;
28782890
}
28792891

28802892
if (auto *GP = dyn_cast<GenericTypeParamDecl>(D)) {
28812893
addGenericTypeParamRef(GP, Reason);
28822894
for (auto *protocol : GP->getConformingProtocols())
2883-
addConstructorCallsForType(protocol->getInterfaceType(), GP->getName(),
2884-
Reason);
2895+
addConstructorCallsForType(protocol->getDeclaredInterfaceType(),
2896+
GP->getName(), Reason);
28852897
return;
28862898
}
28872899

@@ -2934,23 +2946,24 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
29342946

29352947
if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
29362948
addNominalTypeRef(NTD, Reason);
2937-
addConstructorCallsForType(NTD->getInterfaceType(), NTD->getName(),
2938-
Reason);
2949+
addConstructorCallsForType(NTD->getDeclaredInterfaceType(),
2950+
NTD->getName(), Reason);
29392951
return;
29402952
}
29412953

29422954
if (auto *TAD = dyn_cast<TypeAliasDecl>(D)) {
29432955
addTypeAliasRef(TAD, Reason);
29442956
auto type = TAD->mapTypeIntoContext(TAD->getDeclaredInterfaceType());
2945-
addConstructorCallsForType(type, TAD->getName(), Reason);
2957+
if (type->mayHaveMembers())
2958+
addConstructorCallsForType(type, TAD->getName(), Reason);
29462959
return;
29472960
}
29482961

29492962
if (auto *GP = dyn_cast<GenericTypeParamDecl>(D)) {
29502963
addGenericTypeParamRef(GP, Reason);
29512964
for (auto *protocol : GP->getConformingProtocols())
2952-
addConstructorCallsForType(protocol->getInterfaceType(), GP->getName(),
2953-
Reason);
2965+
addConstructorCallsForType(protocol->getDeclaredInterfaceType(),
2966+
GP->getName(), Reason);
29542967
return;
29552968
}
29562969

lib/SILGen/SILGenMaterializeForSet.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,8 @@ struct MaterializeForSetEmitter {
385385
/// Given part of the witness's interface type, produce its
386386
/// substitution according to the witness substitutions.
387387
CanType getSubstWitnessInterfaceType(CanType type) {
388-
auto subs = SubstSelfType->getMemberSubstitutions(WitnessStorage);
388+
auto subs = SubstSelfType->getRValueInstanceType()
389+
->getMemberSubstitutions(WitnessStorage);
389390
return type.subst(SGM.SwiftModule, subs)->getCanonicalType();
390391
}
391392

lib/Sema/CSDiag.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1606,6 +1606,9 @@ void CalleeCandidateInfo::collectCalleeCandidates(Expr *fn,
16061606

16071607
// Compute a new substituted type if we have a base type to apply.
16081608
if (baseType && C.level == 1 && C.getDecl()) {
1609+
baseType = baseType
1610+
->getLValueOrInOutObjectType()
1611+
->getRValueInstanceType();
16091612
C.entityType = baseType->getTypeOfMember(CS->DC->getParentModule(),
16101613
C.getDecl(), nullptr);
16111614
C.substituted = true;
@@ -1793,22 +1796,18 @@ CalleeCandidateInfo::CalleeCandidateInfo(Type baseType,
17931796
//
17941797
if (baseType) {
17951798
auto substType = replaceTypeVariablesWithUnresolved(baseType);
1799+
if (substType)
1800+
substType = substType
1801+
->getLValueOrInOutObjectType()
1802+
->getRValueInstanceType();
17961803

17971804
// If this is a DeclViaUnwrappingOptional, then we're actually looking
17981805
// through an optional to get the member, and baseType is an Optional or
17991806
// Metatype<Optional>.
18001807
if (cand.getKind() == OverloadChoiceKind::DeclViaUnwrappedOptional) {
1801-
bool isMeta = false;
1802-
if (auto MTT = substType->getAs<MetatypeType>()) {
1803-
isMeta = true;
1804-
substType = MTT->getInstanceType();
1805-
}
1806-
18071808
// Look through optional or IUO to get the underlying type the decl was
18081809
// found in.
18091810
substType = substType->getAnyOptionalObjectType();
1810-
if (isMeta && substType)
1811-
substType = MetatypeType::get(substType);
18121811
} else if (cand.getKind() != OverloadChoiceKind::Decl) {
18131812
// Otherwise, if it is a remapping we can't handle, don't try to compute
18141813
// a substitution.
@@ -2330,8 +2329,8 @@ bool FailureDiagnosis::diagnoseGeneralMemberFailure(Constraint *constraint) {
23302329
anchor = typeCheckArbitrarySubExprIndependently(anchor, TCC_AllowLValue);
23312330
if (!anchor) return true;
23322331

2333-
auto baseTy = anchor->getType();
2334-
auto baseObjTy = baseTy->getRValueType();
2332+
auto baseTy = anchor->getType()->getLValueOrInOutObjectType();
2333+
auto baseObjTy = baseTy;
23352334

23362335
// If the base type is an IUO, look through it. Odds are, the code is not
23372336
// trying to find a member of it.
@@ -3105,7 +3104,7 @@ bool FailureDiagnosis::diagnoseGeneralConversionFailure(Constraint *constraint){
31053104
// contain a member var 'boolValue', now does not convert to Bool. This block
31063105
// tries to add a specific diagnosis/fixit to explicitly invoke 'boolValue'.
31073106
if (toType->isBool() &&
3108-
fromType->mayHaveMemberTypes()) {
3107+
fromType->mayHaveMembers()) {
31093108
auto LookupResult = CS->TC.lookupMember(CS->DC, fromType,
31103109
DeclName(CS->TC.Context.getIdentifier("boolValue")));
31113110
if (!LookupResult.empty()) {

lib/Sema/CSSimplify.cpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2644,9 +2644,6 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName,
26442644
return result;
26452645
}
26462646

2647-
if (instanceTy->isTypeParameter())
2648-
return MemberLookupResult();
2649-
26502647
// Okay, start building up the result list.
26512648
MemberLookupResult result;
26522649
result.OverallResult = MemberLookupResult::HasResults;
@@ -2676,7 +2673,12 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName,
26762673
result.ViableCandidates.push_back(OverloadChoice(baseTy, fieldIdx));
26772674
return result;
26782675
}
2679-
2676+
2677+
if (auto *selfTy = instanceTy->getAs<DynamicSelfType>())
2678+
instanceTy = selfTy->getSelfType();
2679+
2680+
if (!instanceTy->mayHaveMembers())
2681+
return result;
26802682

26812683
// If we have a simple name, determine whether there are argument
26822684
// labels we can use to restrict the set of lookup results.
@@ -2741,7 +2743,7 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName,
27412743
// extensions cannot yet define designated initializers.
27422744
lookupOptions -= NameLookupFlags::PerformConformanceCheck;
27432745

2744-
LookupResult ctors = TC.lookupConstructors(DC, baseObjTy, lookupOptions);
2746+
LookupResult ctors = TC.lookupConstructors(DC, instanceTy, lookupOptions);
27452747
if (!ctors)
27462748
return result; // No result.
27472749

@@ -2831,7 +2833,7 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName,
28312833
}
28322834

28332835
// Look for members within the base.
2834-
LookupResult &lookup = lookupMember(baseObjTy, memberName);
2836+
LookupResult &lookup = lookupMember(instanceTy, memberName);
28352837

28362838
// The set of directly accessible types, which is only used when
28372839
// we're performing dynamic lookup into an existential type.
@@ -3017,10 +3019,11 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName,
30173019
if (result.ViableCandidates.empty() && isMetatype &&
30183020
constraintKind == ConstraintKind::UnresolvedValueMember) {
30193021
if (auto objectType = instanceTy->getAnyOptionalObjectType()) {
3020-
LookupResult &optionalLookup = lookupMember(MetatypeType::get(objectType),
3021-
memberName);
3022-
for (auto result : optionalLookup)
3023-
addChoice(result, /*bridged*/false, /*isUnwrappedOptional=*/true);
3022+
if (objectType->mayHaveMembers()) {
3023+
LookupResult &optionalLookup = lookupMember(objectType, memberName);
3024+
for (auto result : optionalLookup)
3025+
addChoice(result, /*bridged*/false, /*isUnwrappedOptional=*/true);
3026+
}
30243027
}
30253028
}
30263029

@@ -3045,7 +3048,7 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName,
30453048
// This is only used for diagnostics, so always use KnownPrivate.
30463049
lookupOptions |= NameLookupFlags::KnownPrivate;
30473050

3048-
auto lookup = TC.lookupMember(DC, baseObjTy->getCanonicalType(),
3051+
auto lookup = TC.lookupMember(DC, instanceTy,
30493052
memberName, lookupOptions);
30503053
for (auto cand : lookup) {
30513054
// If the result is invalid, skip it.

0 commit comments

Comments
 (0)