Skip to content

Commit d8bef6e

Browse files
authored
Merge pull request swiftlang#33385 from apple/revert-33227-unbound-thinout-1
Revert "Sema: Make type resolution for EnumElementPattern less eager"
2 parents 457b999 + a3340e8 commit d8bef6e

File tree

6 files changed

+98
-87
lines changed

6 files changed

+98
-87
lines changed

include/swift/AST/NameLookup.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -512,14 +512,6 @@ void recordLookupOfTopLevelName(DeclContext *topLevelContext, DeclName name,
512512

513513
} // end namespace namelookup
514514

515-
/// Retrieve the set of nominal type declarations that are directly
516-
/// referenced in the given \c typeRepr, looking through typealiases.
517-
///
518-
/// \param dc The \c DeclContext from which to perform lookup.
519-
TinyPtrVector<NominalTypeDecl *>
520-
getDirectlyReferencedNominalTypeDecls(ASTContext &ctx, TypeRepr *typeRepr,
521-
DeclContext *dc, bool &anyObject);
522-
523515
/// Retrieve the set of nominal type declarations that are directly
524516
/// "inherited" by the given declaration at a particular position in the
525517
/// list of "inherited" types.

lib/AST/NameLookup.cpp

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -861,13 +861,18 @@ SelfBounds SelfBoundsFromWhereClauseRequest::evaluate(
861861
continue;
862862

863863
// Resolve the right-hand side.
864-
if (auto *const typeRepr = req.getConstraintRepr()) {
865-
const auto rhsNominals = getDirectlyReferencedNominalTypeDecls(
866-
ctx, typeRepr, lookupDC, result.anyObject);
867-
868-
result.decls.insert(result.decls.end(), rhsNominals.begin(),
869-
rhsNominals.end());
864+
DirectlyReferencedTypeDecls rhsDecls;
865+
if (auto typeRepr = req.getConstraintRepr()) {
866+
rhsDecls = directReferencesForTypeRepr(evaluator, ctx, typeRepr, lookupDC);
870867
}
868+
869+
SmallVector<ModuleDecl *, 2> modulesFound;
870+
auto rhsNominals = resolveTypeDeclsToNominal(evaluator, ctx, rhsDecls,
871+
modulesFound,
872+
result.anyObject);
873+
result.decls.insert(result.decls.end(),
874+
rhsNominals.begin(),
875+
rhsNominals.end());
871876
}
872877

873878
return result;
@@ -2134,17 +2139,6 @@ static DirectlyReferencedTypeDecls directReferencesForType(Type type) {
21342139
return { };
21352140
}
21362141

2137-
TinyPtrVector<NominalTypeDecl *> swift::getDirectlyReferencedNominalTypeDecls(
2138-
ASTContext &ctx, TypeRepr *typeRepr, DeclContext *dc, bool &anyObject) {
2139-
const auto referenced =
2140-
directReferencesForTypeRepr(ctx.evaluator, ctx, typeRepr, dc);
2141-
2142-
// Resolve those type declarations to nominal type declarations.
2143-
SmallVector<ModuleDecl *, 2> modulesFound;
2144-
return resolveTypeDeclsToNominal(ctx.evaluator, ctx, referenced, modulesFound,
2145-
anyObject);
2146-
}
2147-
21482142
DirectlyReferencedTypeDecls InheritedDeclsReferencedRequest::evaluate(
21492143
Evaluator &evaluator,
21502144
llvm::PointerUnion<const TypeDecl *, const ExtensionDecl *> decl,
@@ -2266,10 +2260,16 @@ ExtendedNominalRequest::evaluate(Evaluator &evaluator,
22662260
// We must've seen 'extension { ... }' during parsing.
22672261
return nullptr;
22682262

2263+
ASTContext &ctx = ext->getASTContext();
2264+
DirectlyReferencedTypeDecls referenced =
2265+
directReferencesForTypeRepr(evaluator, ctx, typeRepr, ext->getParent());
2266+
22692267
// Resolve those type declarations to nominal type declarations.
2268+
SmallVector<ModuleDecl *, 2> modulesFound;
22702269
bool anyObject = false;
2271-
const auto nominalTypes = getDirectlyReferencedNominalTypeDecls(
2272-
ext->getASTContext(), typeRepr, ext->getParent(), anyObject);
2270+
auto nominalTypes
2271+
= resolveTypeDeclsToNominal(evaluator, ctx, referenced, modulesFound,
2272+
anyObject);
22732273

22742274
// If there is more than 1 element, we will emit a warning or an error
22752275
// elsewhere, so don't handle that case here.

lib/Sema/CSGen.cpp

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2491,23 +2491,31 @@ namespace {
24912491
if (enumPattern->getParentType() || enumPattern->getParentTypeRepr()) {
24922492
// Resolve the parent type.
24932493
Type parentType = [&]() -> Type {
2494-
if (const auto resolvedTy = enumPattern->getParentType()) {
2495-
assert(resolvedTy->hasUnboundGenericType() == false &&
2496-
"A pre-resolved type must be fully bound");
2497-
return resolvedTy;
2494+
if (auto preTy = enumPattern->getParentType()) {
2495+
return preTy;
24982496
}
24992497
return resolveTypeReferenceInExpression(
25002498
enumPattern->getParentTypeRepr(),
2501-
TypeResolverContext::InExpression,
2502-
OpenUnboundGenericType(
2503-
CS, CS.getConstraintLocator(
2504-
locator, {LocatorPathElt::PatternMatch(pattern),
2505-
ConstraintLocator::ParentType})));
2499+
TypeResolverContext::InExpression, [](auto unboundTy) {
2500+
// FIXME: We ought to pass an OpenUnboundGenericType object
2501+
// rather than calling CS.openUnboundGenericType below, but
2502+
// sometimes the parent type is resolved eagerly in
2503+
// ResolvePattern::visitUnresolvedDotExpr, letting unbound
2504+
// generics escape.
2505+
return unboundTy;
2506+
});
25062507
}();
25072508

25082509
if (!parentType)
25092510
return Type();
25102511

2512+
parentType = CS.openUnboundGenericTypes(
2513+
parentType, CS.getConstraintLocator(
2514+
locator, {LocatorPathElt::PatternMatch(pattern),
2515+
ConstraintLocator::ParentType}));
2516+
2517+
assert(parentType);
2518+
25112519
// Perform member lookup into the parent's metatype.
25122520
Type parentMetaType = MetatypeType::get(parentType);
25132521
CS.addValueMemberConstraint(

lib/Sema/TypeCheckPattern.cpp

Lines changed: 41 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -467,26 +467,31 @@ class ResolvePattern : public ASTVisitor<ResolvePattern,
467467
if (!ExprToIdentTypeRepr(components, Context).visit(ude->getBase()))
468468
return nullptr;
469469

470-
auto *const repr = IdentTypeRepr::create(Context, components);
470+
const auto options =
471+
TypeResolutionOptions(None) | TypeResolutionFlags::SilenceErrors;
471472

472-
// See first if the repr unambiguously references an enum declaration.
473-
bool anyObject = false;
474-
const auto &referencedDecls =
475-
getDirectlyReferencedNominalTypeDecls(Context, repr, DC, anyObject);
476-
if (referencedDecls.size() != 1)
477-
return nullptr;
473+
auto *repr = IdentTypeRepr::create(Context, components);
478474

479-
auto *const enumDecl = dyn_cast<EnumDecl>(referencedDecls.front());
475+
// See if the repr resolves to a type.
476+
const auto resolution =
477+
TypeResolution::forContextual(DC, options, [](auto unboundTy) {
478+
// FIXME: Don't let unbound generic types escape type resolution.
479+
// For now, just return the unbound generic type.
480+
return unboundTy;
481+
});
482+
const auto ty = resolution.resolveType(repr);
483+
auto *enumDecl = dyn_cast_or_null<EnumDecl>(ty->getAnyNominal());
480484
if (!enumDecl)
481485
return nullptr;
482486

483-
EnumElementDecl *referencedElement =
484-
lookupEnumMemberElement(DC, enumDecl->getDeclaredInterfaceType(),
485-
ude->getName(), ude->getLoc());
487+
EnumElementDecl *referencedElement
488+
= lookupEnumMemberElement(DC, ty, ude->getName(), ude->getLoc());
486489
if (!referencedElement)
487490
return nullptr;
488491

489-
auto *const base = new (Context) TypeExpr(repr);
492+
auto *base =
493+
TypeExpr::createForMemberDecl(repr, ude->getNameLoc(), enumDecl);
494+
base->setType(MetatypeType::get(ty));
490495
return new (Context)
491496
EnumElementPattern(base, ude->getDotLoc(), ude->getNameLoc(),
492497
ude->getName(), referencedElement, nullptr);
@@ -564,31 +569,37 @@ class ResolvePattern : public ASTVisitor<ResolvePattern,
564569
baseTE = TypeExpr::createImplicit(enumDecl->getDeclaredTypeInContext(),
565570
Context);
566571
} else {
572+
const auto options =
573+
TypeResolutionOptions(None) | TypeResolutionFlags::SilenceErrors;
574+
567575
// Otherwise, see whether we had an enum type as the penultimate
568576
// component, and look up an element inside it.
569-
auto *const prefixRepr = IdentTypeRepr::create(Context, components);
570-
571-
// See first if the repr unambiguously references an enum declaration.
572-
bool anyObject = false;
573-
const auto &referencedDecls = getDirectlyReferencedNominalTypeDecls(
574-
Context, prefixRepr, DC, anyObject);
575-
if (referencedDecls.size() != 1)
576-
return nullptr;
577-
578-
auto *const enumDecl = dyn_cast<EnumDecl>(referencedDecls.front());
577+
auto *prefixRepr = IdentTypeRepr::create(Context, components);
578+
579+
// See first if the entire repr resolves to a type.
580+
const Type enumTy =
581+
TypeResolution::forContextual(DC, options, [](auto unboundTy) {
582+
// FIXME: Don't let unbound generic types escape type resolution.
583+
// For now, just return the unbound generic type.
584+
return unboundTy;
585+
}).resolveType(prefixRepr);
586+
auto *enumDecl = dyn_cast_or_null<EnumDecl>(enumTy->getAnyNominal());
579587
if (!enumDecl)
580588
return nullptr;
581589

582-
referencedElement = lookupEnumMemberElement(
583-
DC, enumDecl->getDeclaredInterfaceType(), tailComponent->getNameRef(),
584-
tailComponent->getLoc());
590+
referencedElement
591+
= lookupEnumMemberElement(DC, enumTy,
592+
tailComponent->getNameRef(),
593+
tailComponent->getLoc());
585594
if (!referencedElement)
586595
return nullptr;
587596

588-
baseTE = new (Context) TypeExpr(prefixRepr);
597+
baseTE = TypeExpr::createForMemberDecl(
598+
prefixRepr, tailComponent->getNameLoc(), enumDecl);
599+
baseTE->setType(MetatypeType::get(enumTy));
589600
}
590601

591-
assert(baseTE && "Didn't initialize base expression?");
602+
assert(baseTE && baseTE->getType() && "Didn't initialize base expression?");
592603
assert(!isa<GenericIdentTypeRepr>(tailComponent) &&
593604
"should be handled above");
594605

@@ -1426,25 +1437,11 @@ Pattern *TypeChecker::coercePatternToType(ContextualPattern pattern,
14261437

14271438
enumTy = type;
14281439
} else {
1429-
// Validate the parent type if we haven't done so yet.
1430-
if (EEP->getParentType().isNull()) {
1431-
const auto resolution =
1432-
TypeResolution::forContextual(dc, options, [](auto unboundTy) {
1433-
// FIXME: Don't let unbound generic types escape type resolution.
1434-
// For now, just return the unbound generic type.
1435-
return unboundTy;
1436-
});
1437-
const auto ty = resolution.resolveType(EEP->getParentTypeRepr());
1438-
EEP->setParentType(ty);
1439-
1440-
if (ty->hasError()) {
1441-
return nullptr;
1442-
}
1443-
}
1444-
14451440
// Check if the explicitly-written enum type matches the type we're
14461441
// coercing to.
1447-
const Type parentTy = EEP->getParentType();
1442+
assert(!EEP->getParentType().isNull()
1443+
&& "enum with resolved element doesn't specify parent type?!");
1444+
auto parentTy = EEP->getParentType();
14481445
// If the type matches exactly, use it.
14491446
if (parentTy->isEqual(type)) {
14501447
enumTy = type;

test/Constraints/enum_cases.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,21 @@ func rdar_49159472() {
153153
func baz(e: E) {}
154154
}
155155
}
156+
157+
struct EnumElementPatternFromContextualType<T> {
158+
enum E {
159+
case plain
160+
case payload(T)
161+
}
162+
163+
func foo(x: Any) where T == EnumElementPatternFromContextualType<Bool>.E {
164+
switch x {
165+
case T.plain: // Ok
166+
break
167+
case T.payload(true): // Ok
168+
break
169+
default:
170+
break
171+
}
172+
}
173+
}

test/Constraints/patterns.swift

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -339,14 +339,10 @@ func rdar32241441() {
339339

340340
// SR-6100
341341
struct One<Two> { // expected-note{{'Two' declared as parameter to type 'One'}}
342-
public enum E: Error {
343-
// if you remove associated value, everything works
344-
case SomeError(String)
345-
346-
static func foo(error: Error) {
347-
if case SomeError = error {}
342+
public enum E: Error {
343+
// if you remove associated value, everything works
344+
case SomeError(String)
348345
}
349-
}
350346
}
351347

352348
func testOne() {

0 commit comments

Comments
 (0)