Skip to content

Commit 9278fb8

Browse files
committed
[Constraint system] Eliminate TypeCheckExprFlags::ConvertTypeIsOpaqueReturnType
We can compute this information based solely on the SolutionApplicationTarget, so do it.
1 parent 365511c commit 9278fb8

File tree

5 files changed

+67
-49
lines changed

5 files changed

+67
-49
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3970,7 +3970,7 @@ ValueDecl *ConstraintSystem::findResolvedMemberRef(ConstraintLocator *locator) {
39703970
}
39713971

39723972
SolutionApplicationTarget::SolutionApplicationTarget(
3973-
Expr *expr, ContextualTypePurpose contextualPurpose,
3973+
Expr *expr, DeclContext *dc, ContextualTypePurpose contextualPurpose,
39743974
TypeLoc convertType, bool isDiscarded) {
39753975
// Verify that a purpose was specified if a convertType was. Note that it is
39763976
// ok to have a purpose without a convertType (which is used for call
@@ -3991,13 +3991,14 @@ SolutionApplicationTarget::SolutionApplicationTarget(
39913991

39923992
kind = Kind::expression;
39933993
expression.expression = expr;
3994+
expression.dc = dc;
39943995
expression.contextualPurpose = contextualPurpose;
39953996
expression.convertType = convertType;
39963997
expression.isDiscarded = isDiscarded;
39973998
}
39983999

39994000
SolutionApplicationTarget SolutionApplicationTarget::forInitialization(
4000-
Expr *initializer, Type patternType, Pattern *pattern) {
4001+
Expr *initializer, DeclContext *dc, Type patternType, Pattern *pattern) {
40014002
// Determine the contextual type for the initialization.
40024003
TypeLoc contextualType;
40034004
if (!isa<OptionalSomePattern>(pattern) &&
@@ -4016,18 +4017,43 @@ SolutionApplicationTarget SolutionApplicationTarget::forInitialization(
40164017
}
40174018

40184019
SolutionApplicationTarget target(
4019-
initializer, CTP_Initialization, contextualType,
4020+
initializer, dc, CTP_Initialization, contextualType,
40204021
/*isDiscarded=*/false);
40214022
target.expression.pattern = pattern;
40224023
return target;
40234024
}
40244025

4025-
bool SolutionApplicationTarget::contextualTypeIsOnlyAHint(
4026-
bool isOpaqueReturnType) const {
4026+
bool SolutionApplicationTarget::infersOpaqueReturnType() const {
40274027
assert(kind == Kind::expression);
40284028
switch (expression.contextualPurpose) {
40294029
case CTP_Initialization:
4030-
return !isOpaqueReturnType;
4030+
if (Type convertType = expression.convertType.getType()) {
4031+
return convertType->is<OpaqueTypeArchetypeType>();
4032+
}
4033+
return false;
4034+
4035+
case CTP_ReturnStmt:
4036+
case CTP_ReturnSingleExpr:
4037+
if (Type convertType = expression.convertType.getType()) {
4038+
if (auto opaqueType = convertType->getAs<OpaqueTypeArchetypeType>()) {
4039+
auto dc = getDeclContext();
4040+
if (auto func = dyn_cast<AbstractFunctionDecl>(dc)) {
4041+
return opaqueType->getDecl()->isOpaqueReturnTypeOfFunction(func);
4042+
}
4043+
}
4044+
}
4045+
return false;
4046+
4047+
default:
4048+
return false;
4049+
}
4050+
}
4051+
4052+
bool SolutionApplicationTarget::contextualTypeIsOnlyAHint() const {
4053+
assert(kind == Kind::expression);
4054+
switch (expression.contextualPurpose) {
4055+
case CTP_Initialization:
4056+
return !infersOpaqueReturnType();
40314057
case CTP_ForEachStmt:
40324058
return true;
40334059
case CTP_Unused:

lib/Sema/ConstraintSystem.h

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1150,6 +1150,10 @@ class SolutionApplicationTarget {
11501150
/// The expression being type-checked.
11511151
Expr *expression;
11521152

1153+
/// The declaration context in which the expression is being
1154+
/// type-checked.
1155+
DeclContext *dc;
1156+
11531157
/// The purpose of the contextual type.
11541158
ContextualTypePurpose contextualPurpose;
11551159

@@ -1171,14 +1175,15 @@ class SolutionApplicationTarget {
11711175
};
11721176

11731177
public:
1174-
SolutionApplicationTarget(Expr *expr,
1178+
SolutionApplicationTarget(Expr *expr, DeclContext *dc,
11751179
ContextualTypePurpose contextualPurpose,
11761180
Type convertType, bool isDiscarded)
1177-
: SolutionApplicationTarget(expr, contextualPurpose,
1181+
: SolutionApplicationTarget(expr, dc, contextualPurpose,
11781182
TypeLoc::withoutLoc(convertType),
11791183
isDiscarded) { }
11801184

1181-
SolutionApplicationTarget(Expr *expr, ContextualTypePurpose contextualPurpose,
1185+
SolutionApplicationTarget(Expr *expr, DeclContext *dc,
1186+
ContextualTypePurpose contextualPurpose,
11821187
TypeLoc convertType, bool isDiscarded);
11831188

11841189
SolutionApplicationTarget(AnyFunctionRef fn)
@@ -1192,7 +1197,7 @@ class SolutionApplicationTarget {
11921197

11931198
/// Form a target for the initialization of a pattern from an expression.
11941199
static SolutionApplicationTarget forInitialization(
1195-
Expr *initializer, Type patternType, Pattern *pattern);
1200+
Expr *initializer, DeclContext *dc, Type patternType, Pattern *pattern);
11961201

11971202
Expr *getAsExpr() const {
11981203
switch (kind) {
@@ -1204,6 +1209,16 @@ class SolutionApplicationTarget {
12041209
}
12051210
}
12061211

1212+
DeclContext *getDeclContext() const {
1213+
switch (kind) {
1214+
case Kind::expression:
1215+
return expression.dc;
1216+
1217+
case Kind::function:
1218+
return function.function.getAsDeclContext();
1219+
}
1220+
}
1221+
12071222
ContextualTypePurpose getExprContextualTypePurpose() const {
12081223
assert(kind == Kind::expression);
12091224
return expression.contextualPurpose;
@@ -1258,9 +1273,12 @@ class SolutionApplicationTarget {
12581273
expression.contextualPurpose == CTP_Initialization &&
12591274
isa<OptionalSomePattern>(expression.pattern);
12601275
}
1261-
1276+
1277+
/// Whether this context infers an opaque return type.
1278+
bool infersOpaqueReturnType() const;
1279+
12621280
/// Whether the contextual type is only a hint, rather than a type
1263-
bool contextualTypeIsOnlyAHint(bool isOpaqueReturnType) const;
1281+
bool contextualTypeIsOnlyAHint() const;
12641282

12651283
bool isDiscardedExpr() const {
12661284
assert(kind == Kind::expression);

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2066,11 +2066,11 @@ Type TypeChecker::typeCheckExpression(Expr *&expr, DeclContext *dc,
20662066
ExprTypeCheckListener *listener,
20672067
ConstraintSystem *baseCS) {
20682068
SolutionApplicationTarget target(
2069-
expr, convertTypePurpose, convertType,
2069+
expr, dc, convertTypePurpose, convertType,
20702070
options.contains(TypeCheckExprFlags::IsDiscarded));
20712071
bool unresolvedTypeExprs = false;
20722072
auto resultTarget = typeCheckExpression(
2073-
target, dc, unresolvedTypeExprs, options, listener, baseCS);
2073+
target, unresolvedTypeExprs, options, listener, baseCS);
20742074
if (!resultTarget) {
20752075
expr = target.getAsExpr();
20762076
return Type();
@@ -2090,14 +2090,14 @@ Type TypeChecker::typeCheckExpression(Expr *&expr, DeclContext *dc,
20902090
Optional<SolutionApplicationTarget>
20912091
TypeChecker::typeCheckExpression(
20922092
SolutionApplicationTarget &target,
2093-
DeclContext *dc,
20942093
bool &unresolvedTypeExprs,
20952094
TypeCheckExprOptions options,
20962095
ExprTypeCheckListener *listener,
20972096
ConstraintSystem *baseCS) {
20982097
unresolvedTypeExprs = false;
2099-
auto &Context = dc->getASTContext();
21002098
Expr *expr = target.getAsExpr();
2099+
DeclContext *dc = target.getDeclContext();
2100+
auto &Context = dc->getASTContext();
21012101
FrontendStatsTracer StatsTracer(Context.Stats, "typecheck-expr", expr);
21022102
PrettyStackTraceExpr stackTrace(Context, "type-checking", expr);
21032103

@@ -2134,12 +2134,11 @@ TypeChecker::typeCheckExpression(
21342134
cs.setContextualType(
21352135
contextualTypeExpr, convertType,
21362136
target.getExprContextualTypePurpose(),
2137-
options.contains(TypeCheckExprFlags::ConvertTypeIsOpaqueReturnType));
2137+
target.infersOpaqueReturnType());
21382138

21392139
// If the convertType is *only* provided for that hint, then null it out so
21402140
// that we don't later treat it as an actual conversion constraint.
2141-
if (target.contextualTypeIsOnlyAHint(
2142-
options.contains(TypeCheckExprFlags::ConvertTypeIsOpaqueReturnType)))
2141+
if (target.contextualTypeIsOnlyAHint())
21432142
convertType = TypeLoc();
21442143

21452144
// If the client can handle unresolved type variables, leave them in the
@@ -2165,7 +2164,7 @@ TypeChecker::typeCheckExpression(
21652164

21662165
// Attempt to solve the constraint system.
21672166
SolutionApplicationTarget innerTarget(
2168-
expr, target.getExprContextualTypePurpose(), convertTo,
2167+
expr, dc, target.getExprContextualTypePurpose(), convertTo,
21692168
target.isDiscardedExpr());
21702169
auto viable = cs.solve(innerTarget, listener, allowFreeTypeVariables);
21712170
if (!viable) {
@@ -2264,7 +2263,7 @@ getTypeOfExpressionWithoutApplying(Expr *&expr, DeclContext *dc,
22642263
if (needClearType)
22652264
expr->setType(Type());
22662265
SolutionApplicationTarget target(
2267-
expr, CTP_Unused, Type(), /*isDiscarded=*/false);
2266+
expr, dc, CTP_Unused, Type(), /*isDiscarded=*/false);
22682267
auto viable = cs.solve(target, listener, allowFreeTypeVariables);
22692268
if (!viable) {
22702269
recoverOriginalType();
@@ -2345,7 +2344,7 @@ void TypeChecker::getPossibleTypesOfExpressionWithoutApplying(
23452344
expr->setType(Type());
23462345

23472346
SolutionApplicationTarget target(
2348-
expr, CTP_Unused, Type(), /*isDiscarded=*/false);
2347+
expr, dc, CTP_Unused, Type(), /*isDiscarded=*/false);
23492348
if (auto viable = cs.solve(target, listener, allowFreeTypeVariables)) {
23502349
expr = target.getAsExpr();
23512350
for (auto &solution : *viable) {
@@ -2671,9 +2670,9 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
26712670

26722671
// Type-check the initializer.
26732672
auto target = SolutionApplicationTarget::forInitialization(
2674-
initializer, patternType, pattern);
2673+
initializer, DC, patternType, pattern);
26752674
bool unresolvedTypeExprs = false;
2676-
auto resultTarget = typeCheckExpression(target, DC, unresolvedTypeExprs,
2675+
auto resultTarget = typeCheckExpression(target, unresolvedTypeExprs,
26772676
None, &listener);
26782677

26792678
if (resultTarget) {

lib/Sema/TypeCheckStmt.cpp

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -517,23 +517,6 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
517517

518518
TypeCheckExprOptions options = {};
519519

520-
// If the result type is an opaque type, this is an opportunity to resolve
521-
// the underlying type.
522-
auto isOpaqueReturnTypeOfCurrentFunc = [&](OpaqueTypeDecl *opaque) -> bool {
523-
// Closures currently don't support having opaque types.
524-
auto funcDecl = TheFunc->getAbstractFunctionDecl();
525-
if (!funcDecl)
526-
return false;
527-
528-
return opaque->isOpaqueReturnTypeOfFunction(funcDecl);
529-
};
530-
531-
if (auto opaque = ResultTy->getAs<OpaqueTypeArchetypeType>()) {
532-
if (isOpaqueReturnTypeOfCurrentFunc(opaque->getDecl())) {
533-
options |= TypeCheckExprFlags::ConvertTypeIsOpaqueReturnType;
534-
}
535-
}
536-
537520
if (EndTypeCheckLoc.isValid()) {
538521
assert(DiagnosticSuppression::isEnabled(getASTContext().Diags) &&
539522
"Diagnosing and AllowUnresolvedTypeVariables don't seem to mix");

lib/Sema/TypeChecker.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,6 @@ enum class TypeCheckExprFlags {
183183
/// as part of the expression diagnostics, which is attempting to narrow
184184
/// down failure location.
185185
SubExpressionDiagnostics = 0x400,
186-
187-
/// If set, the 'convertType' specified to typeCheckExpression is the opaque
188-
/// return type of the declaration being checked. The archetype should be
189-
/// opened into a type variable to provide context to the expression, and
190-
/// the resulting type will be a candidate for binding the underlying
191-
/// type.
192-
ConvertTypeIsOpaqueReturnType = 0x800,
193186
};
194187

195188
using TypeCheckExprOptions = OptionSet<TypeCheckExprFlags>;
@@ -831,7 +824,6 @@ class TypeChecker final {
831824

832825
static Optional<constraints::SolutionApplicationTarget>
833826
typeCheckExpression(constraints::SolutionApplicationTarget &target,
834-
DeclContext *dc,
835827
bool &unresolvedTypeExprs,
836828
TypeCheckExprOptions options = TypeCheckExprOptions(),
837829
ExprTypeCheckListener *listener = nullptr,

0 commit comments

Comments
 (0)