Skip to content

Commit 20e1dea

Browse files
author
Benjamin Driscoll
committed
[TypeChecker] Update underlying type mismatch check to handle structural opaque types
1 parent bced7d6 commit 20e1dea

File tree

1 file changed

+13
-23
lines changed

1 file changed

+13
-23
lines changed

lib/Sema/MiscDiagnostics.cpp

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2643,11 +2643,13 @@ class VarDeclUsageChecker : public ASTWalker {
26432643
/// An AST walker that determines the underlying type of an opaque return decl
26442644
/// from its associated function body.
26452645
class OpaqueUnderlyingTypeChecker : public ASTWalker {
2646+
using Candidate = std::pair<Expr *, Type>;
2647+
26462648
ASTContext &Ctx;
26472649
AbstractFunctionDecl *Implementation;
26482650
OpaqueTypeDecl *OpaqueDecl;
26492651
BraceStmt *Body;
2650-
SmallVector<std::pair<Expr*, Type>, 4> Candidates;
2652+
SmallVector<Candidate, 4> Candidates;
26512653

26522654
bool HasInvalidReturn = false;
26532655

@@ -2680,23 +2682,13 @@ class OpaqueUnderlyingTypeChecker : public ASTWalker {
26802682
}
26812683

26822684
// Check whether all of the underlying type candidates match up.
2683-
auto opaqueTypeInContext =
2684-
Implementation->mapTypeIntoContext(OpaqueDecl->getDeclaredInterfaceType());
2685-
Type underlyingType = Candidates.front().second;
2686-
26872685
// TODO [OPAQUE SUPPORT]: multiple opaque types
2688-
bool mismatch = false;
2689-
for (auto otherCandidate : llvm::makeArrayRef(Candidates).slice(1)) {
2690-
// Disregard tautological candidates.
2691-
if (otherCandidate.second->isEqual(opaqueTypeInContext))
2692-
continue;
2693-
2694-
if (!underlyingType->isEqual(otherCandidate.second)) {
2695-
mismatch = true;
2696-
break;
2697-
}
2698-
}
2699-
2686+
Type underlyingType = Candidates.front().second;
2687+
bool mismatch =
2688+
std::any_of(Candidates.begin() + 1, Candidates.end(),
2689+
[&](Candidate &otherCandidate) {
2690+
return !underlyingType->isEqual(otherCandidate.second);
2691+
});
27002692
if (mismatch) {
27012693
Implementation->diagnose(
27022694
diag::opaque_type_mismatched_underlying_type_candidates);
@@ -2710,6 +2702,8 @@ class OpaqueUnderlyingTypeChecker : public ASTWalker {
27102702

27112703
// The underlying type can't be defined recursively
27122704
// in terms of the opaque type itself.
2705+
auto opaqueTypeInContext = Implementation->mapTypeIntoContext(
2706+
OpaqueDecl->getDeclaredInterfaceType());
27132707
auto isSelfReferencing = underlyingType.findIf([&](Type t) -> bool {
27142708
return t->isEqual(opaqueTypeInContext);
27152709
});
@@ -2741,15 +2735,11 @@ class OpaqueUnderlyingTypeChecker : public ASTWalker {
27412735

27422736
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
27432737
if (auto underlyingToOpaque = dyn_cast<UnderlyingToOpaqueExpr>(E)) {
2744-
assert(E->getType()->isEqual(
2745-
Implementation->mapTypeIntoContext(OpaqueDecl->getDeclaredInterfaceType()))
2746-
&& "unexpected opaque type in function body");
2747-
27482738
Candidates.push_back(std::make_pair(underlyingToOpaque->getSubExpr(),
27492739
underlyingToOpaque->getSubExpr()->getType()));
2740+
return {false, E};
27502741
}
2751-
//return std::make_pair(true, E);
2752-
return std::make_pair(false, E);
2742+
return {true, E};
27532743
}
27542744

27552745
std::pair<bool, Stmt *> walkToStmtPre(Stmt *S) override {

0 commit comments

Comments
 (0)