Skip to content

Commit 9520aff

Browse files
authored
Merge pull request #9765 from slavapestov/pre-check-expression-fixes
Fix various problems with types in expression context
2 parents 02e2bd5 + 0eac6f0 commit 9520aff

23 files changed

+687
-279
lines changed

include/swift/AST/Expr.h

+26-1
Original file line numberDiff line numberDiff line change
@@ -1382,12 +1382,37 @@ class TypeExpr : public Expr {
13821382
static TypeExpr *createImplicitHack(SourceLoc Loc, Type Ty, ASTContext &C);
13831383

13841384

1385-
/// Return a TypeExpr for a TypeDecl and the specified location.
1385+
/// Create a TypeExpr for a TypeDecl at the specified location.
13861386
static TypeExpr *createForDecl(SourceLoc Loc, TypeDecl *D,
13871387
bool isImplicit);
1388+
1389+
/// Create a TypeExpr for a member TypeDecl of the given parent TypeDecl.
1390+
static TypeExpr *createForMemberDecl(SourceLoc ParentNameLoc,
1391+
TypeDecl *Parent,
1392+
SourceLoc NameLoc,
1393+
TypeDecl *Decl);
1394+
1395+
/// Create a TypeExpr for a member TypeDecl of the given parent IdentTypeRepr.
1396+
static TypeExpr *createForMemberDecl(IdentTypeRepr *ParentTR,
1397+
SourceLoc NameLoc,
1398+
TypeDecl *Decl);
1399+
1400+
/// Create a TypeExpr for a generic TypeDecl with the given arguments applied
1401+
/// at the specified location.
13881402
static TypeExpr *createForSpecializedDecl(SourceLoc Loc, TypeDecl *D,
13891403
ArrayRef<TypeRepr*> args,
13901404
SourceRange angleLocs);
1405+
1406+
/// Create a TypeExpr from an IdentTypeRepr with the given arguments applied
1407+
/// at the specified location.
1408+
///
1409+
/// Returns nullptr if the reference cannot be formed, which is a hack due
1410+
/// to limitations in how we model generic typealiases.
1411+
static TypeExpr *createForSpecializedDecl(IdentTypeRepr *ParentTR,
1412+
ArrayRef<TypeRepr*> Args,
1413+
SourceRange AngleLocs,
1414+
ASTContext &C);
1415+
13911416
TypeLoc &getTypeLoc() { return Info; }
13921417
TypeLoc getTypeLoc() const { return Info; }
13931418
TypeRepr *getTypeRepr() const { return Info.getTypeRepr(); }

lib/AST/Expr.cpp

+97-1
Original file line numberDiff line numberDiff line change
@@ -1959,7 +1959,6 @@ Type TypeExpr::getInstanceType(
19591959
}
19601960

19611961

1962-
/// Return a TypeExpr for a simple identifier and the specified location.
19631962
TypeExpr *TypeExpr::createForDecl(SourceLoc Loc, TypeDecl *Decl,
19641963
bool isImplicit) {
19651964
ASTContext &C = Decl->getASTContext();
@@ -1972,6 +1971,52 @@ TypeExpr *TypeExpr::createForDecl(SourceLoc Loc, TypeDecl *Decl,
19721971
return result;
19731972
}
19741973

1974+
TypeExpr *TypeExpr::createForMemberDecl(SourceLoc ParentNameLoc,
1975+
TypeDecl *Parent,
1976+
SourceLoc NameLoc,
1977+
TypeDecl *Decl) {
1978+
ASTContext &C = Decl->getASTContext();
1979+
assert(ParentNameLoc.isValid());
1980+
assert(NameLoc.isValid());
1981+
1982+
// Create a new list of components.
1983+
SmallVector<ComponentIdentTypeRepr *, 2> Components;
1984+
1985+
// The first component is the parent type.
1986+
auto *ParentComp = new (C) SimpleIdentTypeRepr(ParentNameLoc,
1987+
Parent->getName());
1988+
ParentComp->setValue(Parent);
1989+
Components.push_back(ParentComp);
1990+
1991+
// The second component is the member we just found.
1992+
auto *NewComp = new (C) SimpleIdentTypeRepr(NameLoc,
1993+
Decl->getName());
1994+
NewComp->setValue(Decl);
1995+
Components.push_back(NewComp);
1996+
1997+
auto *NewTypeRepr = IdentTypeRepr::create(C, Components);
1998+
return new (C) TypeExpr(TypeLoc(NewTypeRepr, Type()));
1999+
}
2000+
2001+
TypeExpr *TypeExpr::createForMemberDecl(IdentTypeRepr *ParentTR,
2002+
SourceLoc NameLoc,
2003+
TypeDecl *Decl) {
2004+
ASTContext &C = Decl->getASTContext();
2005+
2006+
// Create a new list of components.
2007+
SmallVector<ComponentIdentTypeRepr *, 2> Components;
2008+
for (auto *Component : ParentTR->getComponentRange())
2009+
Components.push_back(Component);
2010+
2011+
// Add a new component for the member we just found.
2012+
auto *NewComp = new (C) SimpleIdentTypeRepr(NameLoc, Decl->getName());
2013+
NewComp->setValue(Decl);
2014+
Components.push_back(NewComp);
2015+
2016+
auto *NewTypeRepr = IdentTypeRepr::create(C, Components);
2017+
return new (C) TypeExpr(TypeLoc(NewTypeRepr, Type()));
2018+
}
2019+
19752020
TypeExpr *TypeExpr::createForSpecializedDecl(SourceLoc Loc, TypeDecl *D,
19762021
ArrayRef<TypeRepr*> args,
19772022
SourceRange AngleLocs) {
@@ -1983,6 +2028,57 @@ TypeExpr *TypeExpr::createForSpecializedDecl(SourceLoc Loc, TypeDecl *D,
19832028
return new (C) TypeExpr(TypeLoc(Repr, Type()));
19842029
}
19852030

2031+
TypeExpr *TypeExpr::createForSpecializedDecl(IdentTypeRepr *ParentTR,
2032+
ArrayRef<TypeRepr*> Args,
2033+
SourceRange AngleLocs,
2034+
ASTContext &C) {
2035+
// Create a new list of components.
2036+
SmallVector<ComponentIdentTypeRepr *, 2> components;
2037+
for (auto *component : ParentTR->getComponentRange()) {
2038+
components.push_back(component);
2039+
}
2040+
2041+
auto *last = components.back();
2042+
components.pop_back();
2043+
2044+
if (isa<SimpleIdentTypeRepr>(last) &&
2045+
last->getBoundDecl()) {
2046+
if (isa<TypeAliasDecl>(last->getBoundDecl())) {
2047+
// If any of our parent types are unbound, bail out and let
2048+
// the constraint solver can infer generic parameters for them.
2049+
//
2050+
// This is because a type like GenericClass.GenericAlias<Int>
2051+
// cannot be represented directly.
2052+
//
2053+
// This also means that [GenericClass.GenericAlias<Int>]()
2054+
// won't parse correctly, whereas if we fully specialize
2055+
// GenericClass, it does.
2056+
//
2057+
// FIXME: Once we can model generic typealiases properly, rip
2058+
// this out.
2059+
for (auto *component : components) {
2060+
auto *componentDecl = dyn_cast_or_null<GenericTypeDecl>(
2061+
component->getBoundDecl());
2062+
2063+
if (isa<SimpleIdentTypeRepr>(component) &&
2064+
componentDecl &&
2065+
componentDecl->isGeneric())
2066+
return nullptr;
2067+
}
2068+
}
2069+
2070+
auto *genericComp = new (C) GenericIdentTypeRepr(
2071+
last->getIdLoc(), last->getIdentifier(),
2072+
Args, AngleLocs);
2073+
genericComp->setValue(last->getBoundDecl());
2074+
components.push_back(genericComp);
2075+
2076+
auto *genericRepr = IdentTypeRepr::create(C, components);
2077+
return new (C) TypeExpr(TypeLoc(genericRepr, Type()));
2078+
}
2079+
2080+
return nullptr;
2081+
}
19862082

19872083
// Create an implicit TypeExpr, with location information even though it
19882084
// shouldn't have one. This is presently used to work around other location

lib/Sema/CSGen.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -1537,7 +1537,7 @@ namespace {
15371537
if (BoundGenericType *bgt
15381538
= meta->getInstanceType()->getAs<BoundGenericType>()) {
15391539
ArrayRef<Type> typeVars = bgt->getGenericArgs();
1540-
ArrayRef<TypeLoc> specializations = expr->getUnresolvedParams();
1540+
MutableArrayRef<TypeLoc> specializations = expr->getUnresolvedParams();
15411541

15421542
// If we have too many generic arguments, complain.
15431543
if (specializations.size() > typeVars.size()) {
@@ -1557,6 +1557,11 @@ namespace {
15571557
// open type.
15581558
auto locator = CS.getConstraintLocator(expr);
15591559
for (size_t i = 0, size = specializations.size(); i < size; ++i) {
1560+
if (tc.validateType(specializations[i], CS.DC,
1561+
(TR_InExpression |
1562+
TR_AllowUnboundGenerics)))
1563+
return Type();
1564+
15601565
CS.addConstraint(ConstraintKind::Equal,
15611566
typeVars[i], specializations[i].getType(),
15621567
locator);

lib/Sema/CSRanking.cpp

+38-24
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,12 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
481481
log << "\n";
482482
}
483483

484+
auto *innerDC1 = decl1->getInnermostDeclContext();
485+
auto *innerDC2 = decl2->getInnermostDeclContext();
486+
487+
auto *outerDC1 = decl1->getDeclContext();
488+
auto *outerDC2 = decl2->getDeclContext();
489+
484490
if (!tc.specializedOverloadComparisonCache.count({decl1, decl2})) {
485491

486492
auto compareSpecializations = [&] () -> bool {
@@ -516,18 +522,16 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
516522
}
517523

518524
// Members of protocol extensions have special overloading rules.
519-
ProtocolDecl *inProtocolExtension1 = decl1->getDeclContext()
525+
ProtocolDecl *inProtocolExtension1 = outerDC1
520526
->getAsProtocolExtensionContext();
521-
ProtocolDecl *inProtocolExtension2 = decl2->getDeclContext()
527+
ProtocolDecl *inProtocolExtension2 = outerDC2
522528
->getAsProtocolExtensionContext();
523529
if (inProtocolExtension1 && inProtocolExtension2) {
524530
// Both members are in protocol extensions.
525531
// Determine whether the 'Self' type from the first protocol extension
526532
// satisfies all of the requirements of the second protocol extension.
527-
DeclContext *dc1 = decl1->getDeclContext();
528-
DeclContext *dc2 = decl2->getDeclContext();
529-
bool better1 = isProtocolExtensionAsSpecializedAs(tc, dc1, dc2);
530-
bool better2 = isProtocolExtensionAsSpecializedAs(tc, dc2, dc1);
533+
bool better1 = isProtocolExtensionAsSpecializedAs(tc, outerDC1, outerDC2);
534+
bool better2 = isProtocolExtensionAsSpecializedAs(tc, outerDC2, outerDC1);
531535
if (better1 != better2) {
532536
return better1;
533537
}
@@ -554,8 +558,8 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
554558
}
555559
} else {
556560
// Add a curried 'self' type.
557-
type1 = addCurriedSelfType(tc.Context, type1, decl1->getDeclContext());
558-
type2 = addCurriedSelfType(tc.Context, type2, decl2->getDeclContext());
561+
type1 = addCurriedSelfType(tc.Context, type1, outerDC1);
562+
type2 = addCurriedSelfType(tc.Context, type2, outerDC2);
559563

560564
// For a subscript declaration, only look at the input type (i.e., the
561565
// indices).
@@ -578,31 +582,44 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
578582
openedType2 = cs.openFunctionType(
579583
funcType, /*numArgumentLabelsToRemove=*/0, locator,
580584
/*replacements=*/unused,
581-
decl2->getInnermostDeclContext(),
582-
decl2->getDeclContext(),
585+
innerDC2,
586+
outerDC2,
583587
/*skipProtocolSelfConstraint=*/false);
584588
} else {
589+
cs.openGeneric(innerDC2,
590+
outerDC2,
591+
innerDC2->getGenericSignatureOfContext(),
592+
/*skipProtocolSelfConstraint=*/false,
593+
locator,
594+
unused);
595+
585596
openedType2 = cs.openType(type2, locator, unused);
586597
}
587598

588599
// Get the type of a reference to the first declaration, swapping in
589600
// archetypes for the dependent types.
590601
OpenedTypeMap replacements;
591-
auto dc1 = decl1->getInnermostDeclContext();
592602
Type openedType1;
593603
if (auto *funcType = type1->getAs<AnyFunctionType>()) {
594604
openedType1 = cs.openFunctionType(
595605
funcType, /*numArgumentLabelsToRemove=*/0, locator,
596606
replacements,
597-
dc1,
598-
decl1->getDeclContext(),
607+
innerDC1,
608+
outerDC1,
599609
/*skipProtocolSelfConstraint=*/false);
600610
} else {
611+
cs.openGeneric(innerDC1,
612+
outerDC1,
613+
innerDC1->getGenericSignatureOfContext(),
614+
/*skipProtocolSelfConstraint=*/false,
615+
locator,
616+
replacements);
617+
601618
openedType1 = cs.openType(type1, locator, replacements);
602619
}
603620

604621
for (const auto &replacement : replacements) {
605-
if (auto mapped = dc1->mapTypeIntoContext(replacement.first)) {
622+
if (auto mapped = innerDC1->mapTypeIntoContext(replacement.first)) {
606623
cs.addConstraint(ConstraintKind::Bind, replacement.second, mapped,
607624
locator);
608625
}
@@ -611,12 +628,12 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
611628
// Extract the self types from the declarations, if they have them.
612629
Type selfTy1;
613630
Type selfTy2;
614-
if (decl1->getDeclContext()->isTypeContext()) {
631+
if (outerDC1->isTypeContext()) {
615632
auto funcTy1 = openedType1->castTo<FunctionType>();
616633
selfTy1 = funcTy1->getInput()->getRValueInstanceType();
617634
openedType1 = funcTy1->getResult();
618635
}
619-
if (decl2->getDeclContext()->isTypeContext()) {
636+
if (outerDC2->isTypeContext()) {
620637
auto funcTy2 = openedType2->castTo<FunctionType>();
621638
selfTy2 = funcTy2->getInput()->getRValueInstanceType();
622639
openedType2 = funcTy2->getResult();
@@ -625,8 +642,7 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
625642
// Determine the relationship between the 'self' types and add the
626643
// appropriate constraints. The constraints themselves never fail, but
627644
// they help deduce type variables that were opened.
628-
switch (computeSelfTypeRelationship(tc, dc, decl1->getDeclContext(),
629-
decl2->getDeclContext())) {
645+
switch (computeSelfTypeRelationship(tc, dc, outerDC1, outerDC2)) {
630646
case SelfTypeRelationship::Unrelated:
631647
// Skip the self types parameter entirely.
632648
break;
@@ -645,15 +661,13 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
645661

646662
case SelfTypeRelationship::ConformsTo:
647663
cs.addConstraint(ConstraintKind::ConformsTo, selfTy1,
648-
cast<ProtocolDecl>(decl2->getDeclContext())
649-
->getDeclaredType(),
664+
cast<ProtocolDecl>(outerDC2)->getDeclaredType(),
650665
locator);
651666
break;
652667

653668
case SelfTypeRelationship::ConformedToBy:
654669
cs.addConstraint(ConstraintKind::ConformsTo, selfTy2,
655-
cast<ProtocolDecl>(decl1->getDeclContext())
656-
->getDeclaredType(),
670+
cast<ProtocolDecl>(outerDC1)->getDeclaredType(),
657671
locator);
658672
break;
659673
}
@@ -675,10 +689,10 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
675689
auto funcTy2 = openedType2->castTo<FunctionType>();
676690
SmallVector<CallArgParam, 4> params1 =
677691
decomposeParamType(funcTy1->getInput(), decl1,
678-
decl1->getDeclContext()->isTypeContext());
692+
outerDC1->isTypeContext());
679693
SmallVector<CallArgParam, 4> params2 =
680694
decomposeParamType(funcTy2->getInput(), decl2,
681-
decl2->getDeclContext()->isTypeContext());
695+
outerDC2->isTypeContext());
682696

683697
unsigned numParams1 = params1.size();
684698
unsigned numParams2 = params2.size();

0 commit comments

Comments
 (0)