Skip to content

Commit 7eb09a1

Browse files
authored
Merge pull request #6055 from slavapestov/param-decl-interface-types
AST: Assign interface types to ParamDecls
2 parents 3e88368 + 6f49557 commit 7eb09a1

38 files changed

+487
-529
lines changed

include/swift/AST/Decl.h

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4319,9 +4319,7 @@ class ParamDecl : public VarDecl {
43194319
/// For a generic context, this also gives the parameter an unbound generic
43204320
/// type with the expectation that type-checking will fill in the context
43214321
/// generic parameters.
4322-
static ParamDecl *createUnboundSelf(SourceLoc loc, DeclContext *DC,
4323-
bool isStatic = false,
4324-
bool isInOut = false);
4322+
static ParamDecl *createUnboundSelf(SourceLoc loc, DeclContext *DC);
43254323

43264324
/// Create an implicit 'self' decl for a method in the specified decl context.
43274325
/// If 'static' is true, then this is self for a static method in the type.
@@ -4723,12 +4721,6 @@ class AbstractFunctionDecl : public ValueDecl, public DeclContext {
47234721
return getParameterLists()[i];
47244722
}
47254723

4726-
/// \brief If this is a method in a type or extension thereof, compute
4727-
/// and return the type to be used for the 'self' argument of the type, or an
4728-
/// empty Type() if no 'self' argument should exist. This can
4729-
/// only be used after name binding has resolved types.
4730-
Type computeSelfType();
4731-
47324724
/// \brief If this is a method in a type or extension thereof, compute
47334725
/// and return the type to be used for the 'self' argument of the interface
47344726
/// type, or an empty Type() if no 'self' argument should exist. This can
@@ -4737,7 +4729,12 @@ class AbstractFunctionDecl : public ValueDecl, public DeclContext {
47374729
/// \param isInitializingCtor Specifies whether we're computing the 'self'
47384730
/// type of an initializing constructor, which accepts an instance 'self'
47394731
/// rather than a metatype 'self'.
4740-
Type computeInterfaceSelfType(bool isInitializingCtor);
4732+
///
4733+
/// \param wantDynamicSelf Specifies whether the 'self' type should be
4734+
/// wrapped in a DynamicSelfType, which is the case for the 'self' parameter
4735+
/// type inside a class method returning 'Self'.
4736+
Type computeInterfaceSelfType(bool isInitializingCtor=false,
4737+
bool wantDynamicSelf=false);
47414738

47424739
/// \brief This method returns the implicit 'self' decl.
47434740
///

include/swift/AST/DeclContext.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -289,12 +289,6 @@ class alignas(1 << DeclContextAlignInBits) DeclContext {
289289
/// - Non-type contexts return a null type.
290290
Type getDeclaredInterfaceType() const;
291291

292-
/// Get the type of `self` in this context.
293-
///
294-
/// - Protocol types return the `Self` archetype.
295-
/// - Everything else falls back on getDeclaredTypeOfContext().
296-
Type getSelfTypeOfContext() const;
297-
298292
/// Get the type of `self` in this context.
299293
///
300294
/// - Protocol types return the `Self` archetype.

include/swift/AST/ParameterList.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,7 @@ class alignas(ParamDecl *) ParameterList final :
7373
/// DeclContext that needs to be set correctly. This is automatically handled
7474
/// when a function is created with this as part of its argument list.
7575
///
76-
static ParameterList *createUnboundSelf(SourceLoc loc, DeclContext *DC,
77-
bool isStaticMethod = false,
78-
bool isInOut = false);
76+
static ParameterList *createUnboundSelf(SourceLoc loc, DeclContext *DC);
7977

8078
/// Create an implicit 'self' decl for a method in the specified decl context.
8179
/// If 'static' is true, then this is self for a static method in the type.

lib/AST/ASTDumper.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -756,13 +756,19 @@ namespace {
756756
if (!P->getArgumentName().empty())
757757
OS << " apiName=" << P->getArgumentName();
758758

759-
OS << " type=";
760759
if (P->hasType()) {
760+
OS << " type=";
761761
OS << '\'';
762762
P->getType().print(OS);
763763
OS << '\'';
764-
} else
765-
OS << "<null type>";
764+
}
765+
766+
if (P->hasInterfaceType()) {
767+
OS << " interface type=";
768+
OS << '\'';
769+
P->getInterfaceType().print(OS);
770+
OS << '\'';
771+
}
766772

767773
if (!P->isLet())
768774
OS << " mutable";

lib/AST/ASTMangler.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1382,13 +1382,7 @@ Type ASTMangler::getDeclTypeForMangling(const ValueDecl *decl,
13821382
if (!decl->hasInterfaceType())
13831383
return ErrorType::get(C)->getCanonicalType();
13841384

1385-
// FIXME: Interface types for ParamDecls
13861385
Type type = decl->getInterfaceType();
1387-
if (type->hasArchetype()) {
1388-
assert(isa<ParamDecl>(decl));
1389-
type = ArchetypeBuilder::mapTypeOutOfContext(
1390-
decl->getDeclContext(), type);
1391-
}
13921386

13931387
initialParamDepth = 0;
13941388
CanGenericSignature sig;

lib/AST/ASTVerifier.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ struct ASTNodeBase {};
414414

415415
// Check for type variables that escaped the type checker.
416416
if (type->hasTypeVariable()) {
417-
Out << "a type variable escaped the type checker";
417+
Out << "a type variable escaped the type checker\n";
418418
abort();
419419
}
420420

lib/AST/Decl.cpp

Lines changed: 38 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1645,33 +1645,27 @@ ValueDecl::getSatisfiedProtocolRequirements(bool Sorted) const {
16451645
}
16461646

16471647
bool ValueDecl::hasInterfaceType() const {
1648-
// getInterfaceType() returns the contextual type for ParamDecls which
1649-
// don't have an explicit interface type.
1650-
if (auto *PD = dyn_cast<ParamDecl>(this))
1651-
return PD->hasType();
1652-
16531648
return !!InterfaceTy;
16541649
}
16551650

16561651
Type ValueDecl::getInterfaceType() const {
1657-
if (InterfaceTy)
1658-
return InterfaceTy;
1659-
1660-
// FIXME: ParamDecls are funky and don't always have an interface type
1661-
if (auto *PD = dyn_cast<ParamDecl>(this))
1662-
return PD->getType();
1663-
1664-
llvm_unreachable("no interface type was set");
1652+
assert(InterfaceTy && "No interface type was set");
1653+
return InterfaceTy;
16651654
}
16661655

16671656
void ValueDecl::setInterfaceType(Type type) {
1668-
assert((type.isNull() || !type->hasTypeVariable()) &&
1669-
"Type variable in interface type");
1670-
16711657
// lldb creates global typealiases with archetypes in them.
16721658
// FIXME: Add an isDebugAlias() flag, like isDebugVar().
1673-
if (!isa<TypeAliasDecl>(this)) {
1674-
assert((type.isNull() || !type->hasArchetype()) &&
1659+
//
1660+
// Also, ParamDecls in closure contexts can have type variables
1661+
// archetype in them during constraint generation.
1662+
if (!type.isNull() &&
1663+
!isa<TypeAliasDecl>(this) &&
1664+
!(isa<ParamDecl>(this) &&
1665+
isa<AbstractClosureExpr>(getDeclContext()))) {
1666+
assert(!type->hasArchetype() &&
1667+
"Archetype in interface type");
1668+
assert(!type->hasTypeVariable() &&
16751669
"Archetype in interface type");
16761670
}
16771671

@@ -2174,8 +2168,7 @@ Type AbstractTypeParamDecl::getSuperclass() const {
21742168
if (!dc->isValidGenericContext())
21752169
return nullptr;
21762170

2177-
auto contextTy = ArchetypeBuilder::mapTypeIntoContext(
2178-
dc, getDeclaredInterfaceType());
2171+
auto contextTy = dc->mapTypeIntoContext(getDeclaredInterfaceType());
21792172
if (auto *archetype = contextTy->getAs<ArchetypeType>())
21802173
return archetype->getSuperclass();
21812174

@@ -2189,8 +2182,7 @@ AbstractTypeParamDecl::getConformingProtocols() const {
21892182
if (!dc->isValidGenericContext())
21902183
return nullptr;
21912184

2192-
auto contextTy = ArchetypeBuilder::mapTypeIntoContext(
2193-
dc, getDeclaredInterfaceType());
2185+
auto contextTy = dc->mapTypeIntoContext(getDeclaredInterfaceType());
21942186
if (auto *archetype = contextTy->getAs<ArchetypeType>())
21952187
return archetype->getConformsTo();
21962188

@@ -3667,6 +3659,8 @@ ParamDecl::ParamDecl(ParamDecl *PD)
36673659
IsTypeLocImplicit(PD->IsTypeLocImplicit),
36683660
defaultArgumentKind(PD->defaultArgumentKind) {
36693661
typeLoc = PD->getTypeLoc();
3662+
if (PD->hasInterfaceType())
3663+
setInterfaceType(PD->getInterfaceType());
36703664
}
36713665

36723666

@@ -3697,22 +3691,6 @@ Type DeclContext::getSelfInterfaceType() const {
36973691
return getDeclaredInterfaceType();
36983692
}
36993693

3700-
/// \brief Retrieve the type of 'self' for the given context.
3701-
Type DeclContext::getSelfTypeOfContext() const {
3702-
// For a protocol or extension thereof, the type is 'Self'.
3703-
if (auto *proto = getAsProtocolOrProtocolExtensionContext()) {
3704-
auto *genericEnv = proto->getGenericEnvironment();
3705-
3706-
// In the parser, generic parameters won't be wired up yet, just give up on
3707-
// producing a type.
3708-
if (genericEnv == nullptr)
3709-
return Type();
3710-
3711-
return genericEnv->mapTypeIntoContext(getProtocolSelfType());
3712-
}
3713-
return getDeclaredTypeOfContext();
3714-
}
3715-
37163694
/// Create an implicit 'self' decl for a method in the specified decl context.
37173695
/// If 'static' is true, then this is self for a static method in the type.
37183696
///
@@ -3722,24 +3700,10 @@ Type DeclContext::getSelfTypeOfContext() const {
37223700
/// For a generic context, this also gives the parameter an unbound generic
37233701
/// type with the expectation that type-checking will fill in the context
37243702
/// generic parameters.
3725-
ParamDecl *ParamDecl::createUnboundSelf(SourceLoc loc, DeclContext *DC,
3726-
bool isStaticMethod, bool isInOut) {
3703+
ParamDecl *ParamDecl::createUnboundSelf(SourceLoc loc, DeclContext *DC) {
37273704
ASTContext &C = DC->getASTContext();
3728-
auto selfType = DC->getSelfTypeOfContext();
3729-
3730-
// If we have a valid selfType (i.e. we're not in the parser before we
3731-
// know such things, or we're nested inside an invalid extension),
3732-
// configure it.
3733-
if (selfType && !selfType->hasError()) {
3734-
if (isStaticMethod)
3735-
selfType = MetatypeType::get(selfType);
3736-
3737-
if (isInOut)
3738-
selfType = InOutType::get(selfType);
3739-
}
3740-
3741-
auto *selfDecl = new (C) ParamDecl(/*IsLet*/!isInOut, SourceLoc(),SourceLoc(),
3742-
Identifier(), loc, C.Id_self, selfType,DC);
3705+
auto *selfDecl = new (C) ParamDecl(/*IsLet*/true, SourceLoc(), SourceLoc(),
3706+
Identifier(), loc, C.Id_self, Type(), DC);
37433707
selfDecl->setImplicit();
37443708
return selfDecl;
37453709
}
@@ -3758,21 +3722,16 @@ ParamDecl *ParamDecl::createSelf(SourceLoc loc, DeclContext *DC,
37583722
ASTContext &C = DC->getASTContext();
37593723
auto selfType = DC->getSelfTypeInContext();
37603724
auto selfInterfaceType = DC->getSelfInterfaceType();
3725+
assert(selfType && selfInterfaceType);
37613726

3762-
assert(!!selfType == !!selfInterfaceType);
3763-
3764-
// If we have a selfType (i.e. we're not in the parser before we know such
3765-
// things, configure it.
3766-
if (selfType && selfInterfaceType) {
3767-
if (isStaticMethod) {
3768-
selfType = MetatypeType::get(selfType);
3769-
selfInterfaceType = MetatypeType::get(selfInterfaceType);
3770-
}
3727+
if (isStaticMethod) {
3728+
selfType = MetatypeType::get(selfType);
3729+
selfInterfaceType = MetatypeType::get(selfInterfaceType);
3730+
}
37713731

3772-
if (isInOut) {
3773-
selfType = InOutType::get(selfType);
3774-
selfInterfaceType = InOutType::get(selfInterfaceType);
3775-
}
3732+
if (isInOut) {
3733+
selfType = InOutType::get(selfType);
3734+
selfInterfaceType = InOutType::get(selfInterfaceType);
37763735
}
37773736

37783737
auto *selfDecl = new (C) ParamDecl(/*IsLet*/!isInOut, SourceLoc(),SourceLoc(),
@@ -3947,39 +3906,31 @@ SourceRange SubscriptDecl::getSourceRange() const {
39473906
return { getSubscriptLoc(), ElementTy.getSourceRange().End };
39483907
}
39493908

3950-
static Type getSelfTypeForContainer(AbstractFunctionDecl *theMethod,
3951-
bool isInitializingCtor,
3952-
bool wantInterfaceType) {
3953-
auto *dc = theMethod->getDeclContext();
3909+
Type AbstractFunctionDecl::computeInterfaceSelfType(bool isInitializingCtor,
3910+
bool wantDynamicSelf) {
3911+
auto *dc = getDeclContext();
39543912
auto &Ctx = dc->getASTContext();
39553913

39563914
// Determine the type of the container.
3957-
auto containerTy = wantInterfaceType ? dc->getDeclaredInterfaceType()
3958-
: dc->getDeclaredTypeInContext();
3915+
auto containerTy = dc->getDeclaredInterfaceType();
39593916
if (!containerTy || containerTy->hasError())
39603917
return ErrorType::get(Ctx);
39613918

39623919
// Determine the type of 'self' inside the container.
3963-
auto selfTy = wantInterfaceType ? dc->getSelfInterfaceType()
3964-
: dc->getSelfTypeInContext();
3920+
auto selfTy = dc->getSelfInterfaceType();
39653921
if (!selfTy || selfTy->hasError())
39663922
return ErrorType::get(Ctx);
39673923

39683924
bool isStatic = false;
39693925
bool isMutating = false;
3970-
Type selfTypeOverride;
3971-
3972-
if (auto *FD = dyn_cast<FuncDecl>(theMethod)) {
3926+
3927+
if (auto *FD = dyn_cast<FuncDecl>(this)) {
39733928
isStatic = FD->isStatic();
39743929
isMutating = FD->isMutating();
39753930

3976-
// The non-interface type of a method that returns DynamicSelf
3977-
// uses DynamicSelf for the type of 'self', which is important
3978-
// when type checking the body of the function.
3979-
if (!wantInterfaceType && FD->hasDynamicSelf()) {
3931+
if (wantDynamicSelf && FD->hasDynamicSelf())
39803932
selfTy = DynamicSelfType::get(selfTy, Ctx);
3981-
}
3982-
} else if (isa<ConstructorDecl>(theMethod)) {
3933+
} else if (isa<ConstructorDecl>(this)) {
39833934
if (isInitializingCtor) {
39843935
// initializing constructors of value types always have an implicitly
39853936
// inout self.
@@ -3988,7 +3939,7 @@ static Type getSelfTypeForContainer(AbstractFunctionDecl *theMethod,
39883939
// allocating constructors have metatype 'self'.
39893940
isStatic = true;
39903941
}
3991-
} else if (isa<DestructorDecl>(theMethod)) {
3942+
} else if (isa<DestructorDecl>(this)) {
39923943
// destructors of value types always have an implicitly inout self.
39933944
isMutating = true;
39943945
}
@@ -4064,14 +4015,6 @@ void AbstractFunctionDecl::setGenericParams(GenericParamList *GP) {
40644015
}
40654016

40664017

4067-
Type AbstractFunctionDecl::computeSelfType() {
4068-
return getSelfTypeForContainer(this, true, false);
4069-
}
4070-
4071-
Type AbstractFunctionDecl::computeInterfaceSelfType(bool isInitializingCtor) {
4072-
return getSelfTypeForContainer(this, isInitializingCtor, true);
4073-
}
4074-
40754018
/// \brief This method returns the implicit 'self' decl.
40764019
///
40774020
/// Note that some functions don't have an implicit 'self' decl, for example,
@@ -4561,8 +4504,7 @@ bool EnumElementDecl::computeType() {
45614504

45624505
// The type of the enum element is either (T) -> T or (T) -> ArgType -> T.
45634506
if (auto inputTy = getArgumentType()) {
4564-
resultTy = FunctionType::get(
4565-
ArchetypeBuilder::mapTypeOutOfContext(ED, inputTy), resultTy);
4507+
resultTy = FunctionType::get(ED->mapTypeOutOfContext(inputTy), resultTy);
45664508
}
45674509

45684510
if (auto *genericSig = ED->getGenericSignatureOfContext())

lib/AST/Mangle.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -489,13 +489,7 @@ Type Mangler::getDeclTypeForMangling(const ValueDecl *decl,
489489
if (!decl->hasInterfaceType())
490490
return ErrorType::get(C);
491491

492-
// FIXME: Interface types for ParamDecls
493492
Type type = decl->getInterfaceType();
494-
if (type->hasArchetype()) {
495-
assert(isa<ParamDecl>(decl));
496-
type = ArchetypeBuilder::mapTypeOutOfContext(
497-
decl->getDeclContext(), type);
498-
}
499493

500494
initialParamDepth = 0;
501495
CanGenericSignature sig;

lib/AST/Parameter.cpp

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,8 @@ ParameterList::create(const ASTContext &C, SourceLoc LParenLoc,
5050
/// type with the expectation that type-checking will fill in the context
5151
/// generic parameters.
5252
ParameterList *ParameterList::createUnboundSelf(SourceLoc loc,
53-
DeclContext *DC,
54-
bool isStaticMethod,
55-
bool isInOut) {
56-
auto *PD = ParamDecl::createUnboundSelf(loc, DC, isStaticMethod, isInOut);
53+
DeclContext *DC) {
54+
auto *PD = ParamDecl::createUnboundSelf(loc, DC);
5755
return create(DC->getASTContext(), PD);
5856
}
5957

@@ -141,17 +139,7 @@ Type ParameterList::getInterfaceType(DeclContext *DC) const {
141139
SmallVector<TupleTypeElt, 8> argumentInfo;
142140

143141
for (auto P : *this) {
144-
assert(P->hasType());
145-
146-
Type type;
147-
// FIXME: Awful predicate because hasInterfaceType() now always
148-
// returns true on ParamDecls.
149-
if (!P->getInterfaceType()->hasArchetype())
150-
type = P->getInterfaceType();
151-
else if (!P->getTypeLoc().hasLocation())
152-
type = ArchetypeBuilder::mapTypeOutOfContext(DC, P->getType());
153-
else
154-
type = P->getType();
142+
auto type = P->getInterfaceType();
155143
assert(!type->hasArchetype());
156144

157145
argumentInfo.emplace_back(

0 commit comments

Comments
 (0)