Skip to content

Commit f4e2b53

Browse files
authored
Merge pull request #9787 from slavapestov/pre-check-expression-preliminaries
A few fixes for preCheckExpression(), and a cleanup
2 parents 2b92530 + 54d709a commit f4e2b53

File tree

10 files changed

+58
-41
lines changed

10 files changed

+58
-41
lines changed

include/swift/AST/TypeAlignments.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ namespace swift {
4747
class Substitution;
4848
class TypeVariableType;
4949
class TypeBase;
50+
class TypeDecl;
5051
class ValueDecl;
5152

5253
/// We frequently use three tag bits on all of these types.
@@ -87,6 +88,7 @@ LLVM_DECLARE_TYPE_ALIGNMENT(swift::AssociatedTypeDecl, swift::DeclAlignInBits)
8788
LLVM_DECLARE_TYPE_ALIGNMENT(swift::GenericTypeParamDecl, swift::DeclAlignInBits)
8889
LLVM_DECLARE_TYPE_ALIGNMENT(swift::OperatorDecl, swift::DeclAlignInBits)
8990
LLVM_DECLARE_TYPE_ALIGNMENT(swift::ProtocolDecl, swift::DeclAlignInBits)
91+
LLVM_DECLARE_TYPE_ALIGNMENT(swift::TypeDecl, swift::DeclAlignInBits)
9092
LLVM_DECLARE_TYPE_ALIGNMENT(swift::ValueDecl, swift::DeclAlignInBits)
9193
LLVM_DECLARE_TYPE_ALIGNMENT(swift::ExtensionDecl, swift::DeclAlignInBits)
9294

include/swift/AST/TypeRepr.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ namespace swift {
3333
class DeclContext;
3434
class GenericEnvironment;
3535
class IdentTypeRepr;
36-
class ValueDecl;
36+
class TypeDecl;
3737

3838
enum class TypeReprKind : uint8_t {
3939
#define TYPEREPR(ID, PARENT) ID,
@@ -243,7 +243,7 @@ class ComponentIdentTypeRepr : public IdentTypeRepr {
243243
///
244244
/// The initial parsed representation is always an identifier, and
245245
/// name binding will resolve this to a specific declaration.
246-
llvm::PointerUnion<Identifier, ValueDecl *> IdOrDecl;
246+
llvm::PointerUnion<Identifier, TypeDecl *> IdOrDecl;
247247

248248
protected:
249249
ComponentIdentTypeRepr(TypeReprKind K, SourceLoc Loc, Identifier Id)
@@ -258,11 +258,11 @@ class ComponentIdentTypeRepr : public IdentTypeRepr {
258258
void overwriteIdentifier(Identifier newId) { IdOrDecl = newId; }
259259

260260
/// Return true if this has been name-bound already.
261-
bool isBound() const { return IdOrDecl.is<ValueDecl *>(); }
261+
bool isBound() const { return IdOrDecl.is<TypeDecl *>(); }
262262

263-
ValueDecl *getBoundDecl() const { return IdOrDecl.dyn_cast<ValueDecl*>(); }
263+
TypeDecl *getBoundDecl() const { return IdOrDecl.dyn_cast<TypeDecl*>(); }
264264

265-
void setValue(ValueDecl *VD) { IdOrDecl = VD; }
265+
void setValue(TypeDecl *TD) { IdOrDecl = TD; }
266266

267267
static bool classof(const TypeRepr *T) {
268268
return T->getKind() == TypeReprKind::SimpleIdent ||

lib/AST/TypeRepr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ Identifier ComponentIdentTypeRepr::getIdentifier() const {
7777
if (IdOrDecl.is<Identifier>())
7878
return IdOrDecl.get<Identifier>();
7979

80-
return IdOrDecl.get<ValueDecl *>()->getName();
80+
return IdOrDecl.get<TypeDecl *>()->getName();
8181
}
8282

8383
static void printTypeRepr(const TypeRepr *TyR, ASTPrinter &Printer,

lib/Parse/ParseSIL.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -775,8 +775,8 @@ namespace {
775775
auto *T = dyn_cast_or_null<IdentTypeRepr>(Ty);
776776
auto Comp = T->getComponentRange().front();
777777
if (auto Entry = P.lookupInScope(Comp->getIdentifier()))
778-
if (isa<TypeDecl>(Entry)) {
779-
Comp->setValue(Entry);
778+
if (auto *TD = dyn_cast<TypeDecl>(Entry)) {
779+
Comp->setValue(TD);
780780
return false;
781781
}
782782
return true;

lib/Parse/ParseType.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -581,8 +581,8 @@ ParserResult<TypeRepr> Parser::parseTypeIdentifier() {
581581
// Lookup element #0 through our current scope chains in case it is some
582582
// thing local (this returns null if nothing is found).
583583
if (auto Entry = lookupInScope(ComponentsR[0]->getIdentifier()))
584-
if (isa<TypeDecl>(Entry))
585-
ComponentsR[0]->setValue(Entry);
584+
if (auto *TD = dyn_cast<TypeDecl>(Entry))
585+
ComponentsR[0]->setValue(TD);
586586

587587
ITR = IdentTypeRepr::create(Context, ComponentsR);
588588
}
@@ -1136,9 +1136,13 @@ static bool isGenericTypeDisambiguatingToken(Parser &P) {
11361136
case tok::exclaim_postfix:
11371137
case tok::question_postfix:
11381138
return true;
1139-
1140-
case tok::oper_binary_unspaced:
1139+
11411140
case tok::oper_binary_spaced:
1141+
if (tok.getText() == "&")
1142+
return true;
1143+
1144+
LLVM_FALLTHROUGH;
1145+
case tok::oper_binary_unspaced:
11421146
case tok::oper_postfix:
11431147
// These might be '?' or '!' type modifiers.
11441148
return P.isOptionalToken(tok) || P.isImplicitlyUnwrappedOptionalToken(tok);

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1324,7 +1324,8 @@ TypeExpr *PreCheckExpression::simplifyTypeExpr(Expr *E) {
13241324
return nullptr;
13251325
else
13261326
return nullptr;
1327-
}
1327+
} else
1328+
return nullptr;
13281329

13291330
// Add the rhs which is just a TypeExpr
13301331
auto *rhs = dyn_cast<TypeExpr>(binaryExpr->getArg()->getElement(1));

lib/Sema/TypeCheckType.cpp

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,9 +1137,7 @@ resolveTopLevelIdentTypeComponent(TypeChecker &TC, DeclContext *DC,
11371137

11381138
// If the component has already been bound to a declaration, handle
11391139
// that now.
1140-
if (ValueDecl *VD = comp->getBoundDecl()) {
1141-
auto *typeDecl = cast<TypeDecl>(VD);
1142-
1140+
if (auto *typeDecl = comp->getBoundDecl()) {
11431141
// Resolve the type declaration within this context.
11441142
return resolveTypeDecl(TC, typeDecl, comp->getIdLoc(), DC,
11451143
dyn_cast<GenericIdentTypeRepr>(comp), options,
@@ -1328,9 +1326,7 @@ static Type resolveNestedIdentTypeComponent(
13281326
}
13291327

13301328
// Phase 2: If a declaration has already been bound, use it.
1331-
if (ValueDecl *decl = comp->getBoundDecl()) {
1332-
auto *typeDecl = cast<TypeDecl>(decl);
1333-
1329+
if (auto *typeDecl = comp->getBoundDecl()) {
13341330
// Otherwise, simply substitute the parent type into the member.
13351331
auto memberType = TC.substMemberTypeWithBase(DC->getParentModule(),
13361332
typeDecl, parentTy);
@@ -1428,7 +1424,7 @@ static Type resolveNestedIdentTypeComponent(
14281424
}
14291425

14301426
memberType = ty;
1431-
member = cast_or_null<TypeDecl>(comp->getBoundDecl());
1427+
member = comp->getBoundDecl();
14321428
} else {
14331429
memberType = memberTypes.back().second;
14341430
member = memberTypes.back().first;
@@ -1530,7 +1526,7 @@ static bool diagnoseAvailability(IdentTypeRepr *IdType,
15301526
bool AllowPotentiallyUnavailableProtocol) {
15311527
auto componentRange = IdType->getComponentRange();
15321528
for (auto comp : componentRange) {
1533-
if (auto typeDecl = dyn_cast_or_null<TypeDecl>(comp->getBoundDecl())) {
1529+
if (auto *typeDecl = comp->getBoundDecl()) {
15341530
// In Swift 3, components other than the last one were not properly
15351531
// checked for availability.
15361532
// FIXME: We should try to downgrade these errors to warnings, not just
@@ -4053,13 +4049,13 @@ class UnsupportedProtocolVisitor
40534049
return;
40544050

40554051
auto comp = T->getComponentRange().back();
4056-
if (auto proto = dyn_cast_or_null<ProtocolDecl>(comp->getBoundDecl())) {
4052+
if (auto *proto = dyn_cast_or_null<ProtocolDecl>(comp->getBoundDecl())) {
40574053
if (!proto->existentialTypeSupported(&TC)) {
40584054
TC.diagnose(comp->getIdLoc(), diag::unsupported_existential_type,
40594055
proto->getName());
40604056
T->setInvalid();
40614057
}
4062-
} else if (auto alias = dyn_cast_or_null<TypeAliasDecl>(comp->getBoundDecl())) {
4058+
} else if (auto *alias = dyn_cast_or_null<TypeAliasDecl>(comp->getBoundDecl())) {
40634059
if (!alias->hasInterfaceType())
40644060
return;
40654061
auto type = Type(alias->getDeclaredInterfaceType()->getDesugaredType());

test/Interpreter/subclass_existentials.swift

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -141,28 +141,25 @@ protocol Q : class {}
141141

142142
var SubclassExistentialsTestSuite = TestSuite("SubclassExistentials")
143143

144-
// Note: we write ((A) & B) if A is generic to work around a limitation
145-
// in preCheckExpression().
146-
147144
SubclassExistentialsTestSuite.test("Metadata instantiation") {
148-
expectTrue(((Base<String>) & Base<String>).self == Base<String>.self)
149-
expectTrue(((Base<String>) & Any).self == Base<String>.self)
145+
expectTrue((Base<String> & Base<String>).self == Base<String>.self)
146+
expectTrue((Base<String> & Any).self == Base<String>.self)
150147

151-
expectTrue(((Base<Int>) & Q).self == (Q & Base<Int>).self)
148+
expectTrue((Base<Int> & Q).self == (Q & Base<Int>).self)
152149

153-
expectTrue(((Base<Int>) & P & Q).self == (P & (Base<Int>) & Q).self)
154-
expectTrue((P & Q & (Base<Int>)).self == (Q & (Base<Int>) & P).self)
150+
expectTrue((Base<Int> & P & Q).self == (P & Base<Int> & Q).self)
151+
expectTrue((P & Q & Base<Int>).self == (Q & Base<Int> & P).self)
155152

156153
expectTrue((P & Q).self == (P & Q & AnyObject).self)
157154
expectTrue((P & Q).self == (Q & P & AnyObject).self)
158-
expectTrue(((Base<Int>) & Q).self == (Q & (Base<Int>) & AnyObject).self)
155+
expectTrue((Base<Int> & Q).self == (Q & Base<Int> & AnyObject).self)
159156

160157
expectFalse((R & AnyObject).self == R.self)
161158
}
162159

163160
SubclassExistentialsTestSuite.test("Metadata to string") {
164-
expectEqual("Base<Int> & P", String(describing: ((Base<Int>) & P).self))
165-
expectEqual("Base<Int> & P & Q", String(describing: ((Base<Int>) & P & Q).self))
161+
expectEqual("Base<Int> & P", String(describing: (Base<Int> & P).self))
162+
expectEqual("Base<Int> & P & Q", String(describing: (Base<Int> & P & Q).self))
166163
}
167164

168165
SubclassExistentialsTestSuite.test("Call instance methods") {
@@ -360,31 +357,31 @@ func cast<T, U>(_ t: T, to: U.Type) -> U? {
360357
SubclassExistentialsTestSuite.test("Dynamic downcast to subclass existential") {
361358
do {
362359
let baseInt: Base<Int> = Derived(x: 123, y: 321)
363-
let derived = cast(baseInt, to: ((Base<Int>) & P).self)
360+
let derived = cast(baseInt, to: (Base<Int> & P).self)
364361

365362
expectEqual(123, derived!.x)
366363
expectEqual(321, derived!.y)
367364
}
368365

369366
do {
370367
let p: P = Derived(x: 123, y: 321)
371-
let result = cast(p, to: ((Base<Int>) & P).self)
368+
let result = cast(p, to: (Base<Int> & P).self)
372369

373370
expectEqual(123, result!.x)
374371
expectEqual(321, result!.y)
375372
}
376373

377374
do {
378375
let r: R = Derived(x: 123, y: 321)
379-
let result = cast(r, to: ((Base<Int>) & P).self)
376+
let result = cast(r, to: (Base<Int> & P).self)
380377

381378
expectEqual(123, result!.x)
382379
expectEqual(321, result!.y)
383380
}
384381

385382
do {
386383
let baseInt: Base<Int> = Derived(x: 123, y: 321)
387-
let result = cast(baseInt, to: ((Base<Int>) & P).self)
384+
let result = cast(baseInt, to: (Base<Int> & P).self)
388385

389386
expectEqual(123, result!.x)
390387
expectEqual(321, result!.y)
@@ -445,19 +442,19 @@ SubclassExistentialsTestSuite.test("Failing dynamic downcast to subclass existen
445442
do {
446443
let baseInt: Base<Int> = Base<Int>(x: 123, y: 321)
447444

448-
expectNil(cast(baseInt, to: ((Base<Int>) & P).self))
445+
expectNil(cast(baseInt, to: (Base<Int> & P).self))
449446
}
450447

451448
do {
452449
let r: R = Base<Int>(x: 123, y: 321)
453450

454-
expectNil(cast(r, to: ((Base<Int>) & P).self))
451+
expectNil(cast(r, to: (Base<Int> & P).self))
455452
}
456453

457454
do {
458455
let conformsToP = ConformsToP(protocolInit: ())
459456

460-
expectNil(cast(conformsToP, to: ((Base<Int>) & P).self))
457+
expectNil(cast(conformsToP, to: (Base<Int> & P).self))
461458
}
462459
}
463460

test/type/protocol_composition.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,13 @@ struct S05<T> where T : P5? & P6 {} // expected-error {{inheritance from non-nam
163163
struct S3124<T: protocol<P1, P3>> {} // expected-warning {{'protocol<...>' composition syntax is deprecated; join the protocols using '&'}} {{17-34=P1 & P3>}}
164164
func f3124_1<U where U: protocol<P1, P3>>(x: U) {} // expected-warning {{'protocol<...>' composition syntax is deprecated; join the protocols using '&'}} {{25-42=P1 & P3>}} // expected-error {{'where' clause}}
165165
func f3124_2<U : protocol<P1>>(x: U) {} // expected-warning {{'protocol<...>' composition syntax is deprecated and not needed here}} {{18-31=P1>}}
166+
167+
// Make sure we correctly form compositions in expression context
168+
func takesP1AndP2(_: [AnyObject & P1 & P2]) {}
169+
170+
takesP1AndP2([AnyObject & P1 & P2]())
171+
// takesP1AndP2([Swift.AnyObject & P1 & P2]()) // FIXME
172+
// takesP1AndP2([AnyObject & protocol_composition.P1 & P2]()) // FIXME
173+
// takesP1AndP2([AnyObject & P1 & protocol_composition.P2]()) // FIXME
174+
takesP1AndP2([DoesNotExist & P1 & P2]()) // expected-error {{use of unresolved identifier 'DoesNotExist'}}
175+
takesP1AndP2([Swift.DoesNotExist & P1 & P2]()) // expected-error {{module 'Swift' has no member named 'DoesNotExist'}}

test/type/subclass_composition.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,3 +531,10 @@ func staticMembers(
531531
_ = m2.instanceProtocolMember // expected-error {{instance member 'instanceProtocolMember' cannot be used on type 'ClassWithStaticMember & ProtocolWithStaticMember'}}
532532
_ = m2.instanceClassMember // expected-error {{instance member 'instanceClassMember' cannot be used on type 'ClassWithStaticMember & ProtocolWithStaticMember'}}
533533
}
534+
535+
// Make sure we correctly form subclass existentials in expression context.
536+
func takesBaseIntAndPArray(_: [Base<Int> & P2]) {}
537+
538+
func passesBaseIntAndPArray() {
539+
takesBaseIntAndPArray([Base<Int> & P2]())
540+
}

0 commit comments

Comments
 (0)