Skip to content

Commit ab594dd

Browse files
authored
Merge pull request #38503 from hamishknight/another-one-bites-the-subst
2 parents 6e29c02 + d4c25f5 commit ab594dd

13 files changed

+101
-44
lines changed

include/swift/AST/Types.h

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,10 +1116,22 @@ class alignas(1 << TypeAlignInBits) TypeBase {
11161116
TypeSubstitutionMap getMemberSubstitutions(const ValueDecl *member,
11171117
GenericEnvironment *genericEnv=nullptr);
11181118

1119+
/// Retrieve the type of the given property as seen through the given base
1120+
/// type, substituting generic arguments where necessary. This is the same as
1121+
/// the more general overload of \c TypeBase::getTypeOfMember, but defaults to
1122+
/// the property's interface type for the \c memberType.
1123+
///
1124+
/// \param module The module in which the substitution occurs.
1125+
///
1126+
/// \param member The property whose type we are substituting.
1127+
///
1128+
/// \returns The resulting property type.
1129+
Type getTypeOfMember(ModuleDecl *module, const VarDecl *member);
1130+
11191131
/// Retrieve the type of the given member as seen through the given base
11201132
/// type, substituting generic arguments where necessary.
11211133
///
1122-
/// This routine allows one to take a concrete type (the "this" type) and
1134+
/// This routine allows one to take a concrete type (the "self" type) and
11231135
/// and a member of that type (or one of its superclasses), then determine
11241136
/// what type an access to that member through the base type will have.
11251137
/// For example, given:
@@ -1130,20 +1142,23 @@ class alignas(1 << TypeAlignInBits) TypeBase {
11301142
/// }
11311143
/// \endcode
11321144
///
1133-
/// Given the type \c Vector<Int> and the member \c add, the resulting type
1134-
/// of the member will be \c (self : Vector<Int>) -> (value : Int) -> ().
1145+
/// Given the type \c Vector<Int>, the member \c add, and its method interface
1146+
/// type (value: T) -> Void the resulting type will be (value: Int) -> Void.
11351147
///
11361148
/// \param module The module in which the substitution occurs.
11371149
///
11381150
/// \param member The member whose type we are substituting.
11391151
///
1140-
/// \param memberType The type of the member, in which archetypes will be
1141-
/// replaced by the generic arguments provided by the base type. If null,
1142-
/// the member's type will be used.
1152+
/// \param memberType The type of the member in which generic parameters will
1153+
/// be replaced by the generic arguments provided by the base type. Note this
1154+
/// must not be a GenericFunctionType. For a method, either strip the self
1155+
/// parameter and generic signature using e.g \c getMethodInterfaceType, or
1156+
/// use \c substGenericArgs if you want to substitute types for any of the
1157+
/// method's generic parameters.
11431158
///
1144-
/// \returns the resulting member type.
1159+
/// \returns The resulting member type.
11451160
Type getTypeOfMember(ModuleDecl *module, const ValueDecl *member,
1146-
Type memberType = Type());
1161+
Type memberType);
11471162

11481163
/// Get the type of a superclass member as seen from the subclass,
11491164
/// substituting generic parameters, dynamic Self return, and the

include/swift/SIL/AbstractionPattern.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -794,8 +794,7 @@ class AbstractionPattern {
794794
/// Note that, for most purposes, you should lower a field's type against its
795795
/// *unsubstituted* interface type.
796796
AbstractionPattern
797-
unsafeGetSubstFieldType(ValueDecl *member,
798-
CanType origMemberType = CanType()) const;
797+
unsafeGetSubstFieldType(ValueDecl *member, CanType origMemberType) const;
799798

800799
private:
801800
/// Return an abstraction pattern for the curried type of an

lib/AST/Type.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4312,8 +4312,16 @@ SubstitutionMap TypeBase::getMemberSubstitutionMap(
43124312
LookUpConformanceInModule(module));
43134313
}
43144314

4315+
Type TypeBase::getTypeOfMember(ModuleDecl *module, const VarDecl *member) {
4316+
return getTypeOfMember(module, member, member->getInterfaceType());
4317+
}
4318+
43154319
Type TypeBase::getTypeOfMember(ModuleDecl *module, const ValueDecl *member,
43164320
Type memberType) {
4321+
assert(memberType);
4322+
assert(!memberType->is<GenericFunctionType>() &&
4323+
"Generic function types are not supported");
4324+
43174325
if (is<ErrorType>())
43184326
return ErrorType::get(getASTContext());
43194327

@@ -4322,12 +4330,6 @@ Type TypeBase::getTypeOfMember(ModuleDecl *module, const ValueDecl *member,
43224330
return objectTy->getTypeOfMember(module, member, memberType);
43234331
}
43244332

4325-
// If no member type was provided, use the member's type.
4326-
if (!memberType)
4327-
memberType = member->getInterfaceType();
4328-
4329-
assert(memberType);
4330-
43314333
// Perform the substitution.
43324334
auto substitutions = getMemberSubstitutionMap(module, member);
43334335
return memberType.subst(substitutions);

lib/IDE/ConformingMethodList.cpp

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -129,22 +129,20 @@ void ConformingMethodListCallbacks::getMatchingMethods(
129129
/// Returns true if \p VD is a instance method whose return type conforms
130130
/// to the requested protocols.
131131
bool isMatchingMethod(ValueDecl *VD) {
132-
if (!isa<FuncDecl>(VD))
132+
auto *FD = dyn_cast<FuncDecl>(VD);
133+
if (!FD)
133134
return false;
134-
if (VD->isStatic() || VD->isOperator())
135+
if (FD->isStatic() || FD->isOperator())
135136
return false;
136137

137-
auto declTy = T->getTypeOfMember(CurModule, VD);
138-
if (declTy->is<ErrorType>())
138+
auto resultTy = T->getTypeOfMember(CurModule, FD,
139+
FD->getResultInterfaceType());
140+
if (resultTy->is<ErrorType>())
139141
return false;
140142

141-
// Strip '(Self.Type) ->' and parameters.
142-
declTy = declTy->castTo<AnyFunctionType>()->getResult();
143-
declTy = declTy->castTo<AnyFunctionType>()->getResult();
144-
145143
// The return type conforms to any of the requested protocols.
146144
for (auto Proto : ExpectedTypes) {
147-
if (CurModule->conformsToProtocol(declTy, Proto))
145+
if (CurModule->conformsToProtocol(resultTy, Proto))
148146
return true;
149147
}
150148

lib/IDE/TypeContextInfo.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,11 +143,13 @@ void ContextInfoCallbacks::getImplicitMembers(
143143
return true;
144144

145145
// Static properties which is convertible to 'Self'.
146-
if (isa<VarDecl>(VD) && VD->isStatic()) {
147-
auto declTy = T->getTypeOfMember(CurModule, VD);
148-
if (declTy->isEqual(T) ||
149-
swift::isConvertibleTo(declTy, T, /*openArchetypes=*/true, *DC))
150-
return true;
146+
if (auto *Var = dyn_cast<VarDecl>(VD)) {
147+
if (Var->isStatic()) {
148+
auto declTy = T->getTypeOfMember(CurModule, Var);
149+
if (declTy->isEqual(T) ||
150+
swift::isConvertibleTo(declTy, T, /*openArchetypes=*/true, *DC))
151+
return true;
152+
}
151153
}
152154

153155
return false;

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -918,8 +918,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
918918
SmallVector<llvm::Metadata *, 16> Elements;
919919
unsigned OffsetInBits = 0;
920920
for (VarDecl *VD : Decl->getStoredProperties()) {
921-
auto memberTy =
922-
BaseTy->getTypeOfMember(IGM.getSwiftModule(), VD, nullptr);
921+
auto memberTy = BaseTy->getTypeOfMember(IGM.getSwiftModule(), VD);
923922

924923
if (auto DbgTy = CompletedDebugTypeInfo::getFromTypeInfo(
925924
VD->getInterfaceType(),

lib/SIL/IR/AbstractionPattern.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,13 +1135,12 @@ AbstractionPattern
11351135
AbstractionPattern::unsafeGetSubstFieldType(ValueDecl *member,
11361136
CanType origMemberInterfaceType)
11371137
const {
1138+
assert(origMemberInterfaceType);
11381139
if (isTypeParameterOrOpaqueArchetype()) {
11391140
// Fall back to the generic abstraction pattern for the member.
11401141
auto sig = member->getDeclContext()->getGenericSignatureOfContext();
1141-
CanType memberTy = origMemberInterfaceType
1142-
? origMemberInterfaceType
1143-
: member->getInterfaceType()->getCanonicalType(sig);
1144-
return AbstractionPattern(sig.getCanonicalSignature(), memberTy);
1142+
return AbstractionPattern(sig.getCanonicalSignature(),
1143+
origMemberInterfaceType);
11451144
}
11461145

11471146
switch (getKind()) {

lib/SIL/IR/SILType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ SILType SILType::getFieldType(VarDecl *field, TypeConverter &TC,
165165
substFieldTy = origFieldTy.getType();
166166
} else {
167167
substFieldTy =
168-
getASTType()->getTypeOfMember(&TC.M, field, nullptr)->getCanonicalType();
168+
getASTType()->getTypeOfMember(&TC.M, field)->getCanonicalType();
169169
}
170170

171171
auto loweredTy =

lib/SIL/IR/TypeLowering.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1768,7 +1768,10 @@ namespace {
17681768
// field type against the declaration's interface type as we normally
17691769
// would, we use the substituted field type in order to accurately
17701770
// preserve the properties of the aggregate.
1771-
auto origFieldType = origType.unsafeGetSubstFieldType(field);
1771+
auto sig = field->getDeclContext()->getGenericSignatureOfContext();
1772+
auto interfaceTy = field->getInterfaceType()->getCanonicalType(sig);
1773+
auto origFieldType = origType.unsafeGetSubstFieldType(field,
1774+
interfaceTy);
17721775

17731776
properties.addSubobject(classifyType(origFieldType, substFieldType,
17741777
TC, Expansion));

lib/Sema/ConstraintSystem.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -998,8 +998,11 @@ ConstraintSystem::getPropertyWrapperInformation(
998998
if (!decl->hasAttachedPropertyWrapper())
999999
return None;
10001000

1001-
return std::make_pair(decl,
1002-
decl->getPropertyWrapperBackingPropertyType());
1001+
auto backingTy = decl->getPropertyWrapperBackingPropertyType();
1002+
if (!backingTy)
1003+
return None;
1004+
1005+
return std::make_pair(decl, backingTy);
10031006
});
10041007
}
10051008

lib/Sema/TypeCheckSwitchStmt.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -844,11 +844,10 @@ namespace {
844844

845845
// .e(a: X, b: X) -> (a: X, b: X)
846846
// .f((a: X, b: X)) -> ((a: X, b: X)
847-
auto eedTy = tp->getCanonicalType()->getTypeOfMember(
848-
E->getModuleContext(), eed,
849-
eed->getArgumentInterfaceType());
850847
SmallVector<Space, 4> constElemSpaces;
851-
if (eedTy) {
848+
if (auto payloadTy = eed->getArgumentInterfaceType()) {
849+
auto eedTy = tp->getCanonicalType()->getTypeOfMember(
850+
E->getModuleContext(), eed, payloadTy);
852851
if (auto *TTy = eedTy->getAs<TupleType>()) {
853852
Space::getTupleTypeSpaces(eedTy, TTy, constElemSpaces);
854853
} else if (auto *TTy =
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: %target-swift-ide-test -conforming-methods -source-filename %s -code-completion-token=CM1 -module-name MyModule -conforming-methods-expected-types '$s8MyModule6TargetPD' | %FileCheck %s -check-prefix=SI
2+
// RUN: %target-swift-ide-test -conforming-methods -source-filename %s -code-completion-token=CM2 -module-name MyModule -conforming-methods-expected-types '$s8MyModule6TargetPD' | %FileCheck %s -check-prefix=SF
3+
4+
protocol Target {}
5+
struct Concrete : Target {}
6+
7+
struct S<T> {
8+
func returnsAnything<U>() -> U { fatalError() }
9+
}
10+
11+
extension S where T == Int {
12+
func returnsConcrete<U>(_ x: U) -> Concrete { fatalError() }
13+
}
14+
15+
func test(si: S<Int>, sf: S<Float>) {
16+
si.#^CM1^#
17+
// SI: -----BEGIN CONFORMING METHOD LIST-----
18+
// SI-NEXT: - TypeName: S<Int>
19+
// SI-NEXT: - Members:
20+
// SI-NEXT: - Name: returnsConcrete(_:)
21+
// SI-NEXT: TypeName: Concrete
22+
// SI-NEXT: -----END CONFORMING METHOD LIST-----
23+
24+
sf.#^CM2^#
25+
// SF: -----BEGIN CONFORMING METHOD LIST-----
26+
// SF-NEXT: - TypeName: S<Float>
27+
// SF-NEXT: - Members: []
28+
// SF-NEXT: -----END CONFORMING METHOD LIST-----
29+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %target-swift-ide-test -conforming-methods -source-filename %s -code-completion-token=CC
2+
3+
protocol MyView {}
4+
5+
extension MyView {
6+
func foo<Content>() -> Content? {
7+
return nil#^CC^#
8+
}
9+
}

0 commit comments

Comments
 (0)