Skip to content

Commit 197bcc2

Browse files
authored
Merge pull request #84345 from hamishknight/time-and-place
A few fixes for placeholder types in interface types
2 parents e419d30 + aa9aa58 commit 197bcc2

25 files changed

+244
-53
lines changed

include/swift/AST/Decl.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7101,6 +7101,14 @@ class ParamDecl : public VarDecl {
71017101
Identifier parameterName, Expr *defaultValue,
71027102
DefaultArgumentInitializer *defaultValueInitContext, DeclContext *dc);
71037103

7104+
SourceLoc getLocFromSource() const {
7105+
// If we have a name loc, use it, otherwise fallback to the start loc for
7106+
// e.g enum elements without parameter names.
7107+
if (auto nameLoc = getNameLoc())
7108+
return nameLoc;
7109+
return getStartLoc();
7110+
}
7111+
71047112
/// Retrieve the argument (API) name for this function parameter.
71057113
Identifier getArgumentName() const {
71067114
return ArgumentNameAndFlags.getPointer();

include/swift/AST/TypeMatcher.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,12 @@ class TypeMatcher {
117117
#define SINGLETON_TYPE(SHORT_ID, ID) TRIVIAL_CASE(ID##Type)
118118
#include "swift/AST/TypeNodes.def"
119119

120+
bool visitPlaceholderType(CanPlaceholderType firstType, Type secondType,
121+
Type sugaredFirstType) {
122+
// Placeholder types never match.
123+
return mismatch(firstType.getPointer(), secondType, sugaredFirstType);
124+
}
125+
120126
bool visitUnresolvedType(CanUnresolvedType firstType, Type secondType,
121127
Type sugaredFirstType) {
122128
// Unresolved types never match.

include/swift/Sema/CSFix.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,9 @@ enum class FixKind : uint8_t {
362362
/// resolved.
363363
SpecifyTypeForPlaceholder,
364364

365+
/// Ignore an invalid placeholder in a decl's interface type.
366+
IgnoreInvalidPlaceholderInDeclRef,
367+
365368
/// Allow Swift -> C pointer conversion in an argument position
366369
/// of a Swift function.
367370
AllowSwiftToCPointerConversion,
@@ -3191,6 +3194,30 @@ class SpecifyTypeForPlaceholder final : public ConstraintFix {
31913194
}
31923195
};
31933196

3197+
class IgnoreInvalidPlaceholderInDeclRef final : public ConstraintFix {
3198+
IgnoreInvalidPlaceholderInDeclRef(ConstraintSystem &cs,
3199+
ConstraintLocator *locator)
3200+
: ConstraintFix(cs, FixKind::IgnoreInvalidPlaceholderInDeclRef, locator) {}
3201+
3202+
public:
3203+
std::string getName() const override {
3204+
return "ignore invalid placeholder in decl ref";
3205+
}
3206+
3207+
bool diagnose(const Solution &solution, bool asNote = false) const override;
3208+
3209+
bool diagnoseForAmbiguity(CommonFixesArray commonFixes) const override {
3210+
return diagnose(*commonFixes.front().first);
3211+
}
3212+
3213+
static IgnoreInvalidPlaceholderInDeclRef *create(ConstraintSystem &cs,
3214+
ConstraintLocator *locator);
3215+
3216+
static bool classof(const ConstraintFix *fix) {
3217+
return fix->getKind() == FixKind::IgnoreInvalidPlaceholderInDeclRef;
3218+
}
3219+
};
3220+
31943221
class AllowRefToInvalidDecl final : public ConstraintFix {
31953222
AllowRefToInvalidDecl(ConstraintSystem &cs, ConstraintLocator *locator)
31963223
: ConstraintFix(cs, FixKind::AllowRefToInvalidDecl, locator) {}

lib/AST/ASTContext.cpp

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4686,6 +4686,8 @@ isAnyFunctionTypeCanonical(ArrayRef<AnyFunctionType::Param> params,
46864686
// For now, generic function types cannot be dependent (in fact,
46874687
// they erase dependence) or contain type variables, and they're
46884688
// always materializable.
4689+
// FIXME: This doesn't seem great, we should consider changing it to be opt-out
4690+
// rather than opt-in.
46894691
static RecursiveTypeProperties
46904692
getGenericFunctionRecursiveProperties(ArrayRef<AnyFunctionType::Param> params,
46914693
Type result, Type globalActor,
@@ -4694,34 +4696,25 @@ getGenericFunctionRecursiveProperties(ArrayRef<AnyFunctionType::Param> params,
46944696
"revisit this if you add new recursive type properties");
46954697
RecursiveTypeProperties properties;
46964698

4697-
for (auto param : params) {
4698-
if (param.getPlainType()->getRecursiveProperties().hasError())
4699-
properties |= RecursiveTypeProperties::HasError;
4700-
if (param.getPlainType()->getRecursiveProperties().isUnsafe())
4701-
properties |= RecursiveTypeProperties::IsUnsafe;
4702-
}
4699+
using Prop = RecursiveTypeProperties::Property;
4700+
auto mask = (unsigned)Prop::HasError | Prop::IsUnsafe | Prop::HasPlaceholder;
4701+
4702+
auto unionBits = [&](Type ty) {
4703+
if (!ty)
4704+
return;
4705+
auto bits = ty->getRecursiveProperties().getBits();
4706+
properties |= Prop(bits & mask);
4707+
};
4708+
4709+
for (auto param : params)
4710+
unionBits(param.getPlainType());
47034711

47044712
if (result->getRecursiveProperties().hasDynamicSelf())
47054713
properties |= RecursiveTypeProperties::HasDynamicSelf;
4706-
if (result->getRecursiveProperties().hasError())
4707-
properties |= RecursiveTypeProperties::HasError;
4708-
if (result->getRecursiveProperties().isUnsafe())
4709-
properties |= RecursiveTypeProperties::IsUnsafe;
4710-
4711-
if (globalActor) {
4712-
if (globalActor->getRecursiveProperties().hasError())
4713-
properties |= RecursiveTypeProperties::HasError;
4714-
if (globalActor->getRecursiveProperties().isUnsafe())
4715-
properties |= RecursiveTypeProperties::IsUnsafe;
4716-
}
4717-
4718-
if (thrownError) {
4719-
if (thrownError->getRecursiveProperties().hasError())
4720-
properties |= RecursiveTypeProperties::HasError;
4721-
if (thrownError->getRecursiveProperties().isUnsafe())
4722-
properties |= RecursiveTypeProperties::IsUnsafe;
4723-
}
47244714

4715+
unionBits(result);
4716+
unionBits(globalActor);
4717+
unionBits(thrownError);
47254718
return properties;
47264719
}
47274720

lib/Sema/AssociatedTypeInference.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2317,9 +2317,9 @@ AssociatedTypeInference::getPotentialTypeWitnessesByMatchingTypes(ValueDecl *req
23172317
/// Deduce associated types from dependent member types in the witness.
23182318
bool mismatch(DependentMemberType *firstDepMember,
23192319
TypeBase *secondType, Type sugaredFirstType) {
2320-
// If the second type is an error, don't look at it further, but proceed
2321-
// to find other matches.
2322-
if (secondType->hasError())
2320+
// If the second type is an error or placeholder, don't look at it
2321+
// further, but proceed to find other matches.
2322+
if (secondType->hasError() || secondType->hasPlaceholder())
23232323
return true;
23242324

23252325
// If the second type is a generic parameter of the witness, the match

lib/Sema/CSFix.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2264,6 +2264,20 @@ SpecifyTypeForPlaceholder::create(ConstraintSystem &cs,
22642264
return new (cs.getAllocator()) SpecifyTypeForPlaceholder(cs, locator);
22652265
}
22662266

2267+
IgnoreInvalidPlaceholderInDeclRef *
2268+
IgnoreInvalidPlaceholderInDeclRef::create(ConstraintSystem &cs, ConstraintLocator *locator) {
2269+
return new (cs.getAllocator()) IgnoreInvalidPlaceholderInDeclRef(cs, locator);
2270+
}
2271+
2272+
bool
2273+
IgnoreInvalidPlaceholderInDeclRef::diagnose(const Solution &solution,
2274+
bool asNote) const {
2275+
// These are diagnosed separately. Unfortunately we can't enforce that a
2276+
// diagnostic has already been emitted since their diagnosis depends on e.g
2277+
// type-checking a function body for a placeholder result of a function.
2278+
return true;
2279+
}
2280+
22672281
bool AllowRefToInvalidDecl::diagnose(const Solution &solution,
22682282
bool asNote) const {
22692283
ReferenceToInvalidDeclaration failure(solution, getLocator());

lib/Sema/CSGen.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2542,8 +2542,11 @@ namespace {
25422542
Type thrownErrorTy = [&] {
25432543
// Explicitly-specified thrown type.
25442544
if (closure->getExplicitThrownTypeRepr()) {
2545-
if (Type explicitType = closure->getExplicitThrownType())
2546-
return explicitType;
2545+
if (Type explicitType = closure->getExplicitThrownType()) {
2546+
// The thrown type may have errors, open as placeholders if needed.
2547+
return CS.replaceInferableTypesWithTypeVars(explicitType,
2548+
thrownErrorLocator);
2549+
}
25472550
}
25482551

25492552
// Explicitly-specified 'throws' without a type is untyped throws.

lib/Sema/CSSimplify.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16109,6 +16109,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
1610916109
case FixKind::AllowValueExpansionWithoutPackReferences:
1611016110
case FixKind::IgnoreInvalidPatternInExpr:
1611116111
case FixKind::IgnoreInvalidPlaceholder:
16112+
case FixKind::IgnoreInvalidPlaceholderInDeclRef:
1611216113
case FixKind::IgnoreOutOfPlaceThenStmt:
1611316114
case FixKind::IgnoreMissingEachKeyword:
1611416115
case FixKind::AllowInlineArrayLiteralCountMismatch:

lib/Sema/TypeCheckDecl.cpp

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2121,10 +2121,17 @@ ResultTypeRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const {
21212121
if (decl->preconcurrency())
21222122
options |= TypeResolutionFlags::Preconcurrency;
21232123

2124+
// Placeholders are only currently allowed for FuncDecls with bodies, which
2125+
// we diagnose in ReturnTypePlaceholderReplacer.
2126+
HandlePlaceholderTypeReprFn placeholderOpener;
2127+
if (auto *FD = dyn_cast<FuncDecl>(decl)) {
2128+
if (FD->hasBody() && !FD->isBodySkipped())
2129+
placeholderOpener = PlaceholderType::get;
2130+
}
21242131
auto *const dc = decl->getInnermostDeclContext();
21252132
return TypeResolution::forInterface(dc, options,
21262133
/*unboundTyOpener*/ nullptr,
2127-
PlaceholderType::get,
2134+
placeholderOpener,
21282135
/*packElementOpener*/ nullptr)
21292136
.resolveType(resultTyRepr);
21302137
}
@@ -2310,9 +2317,17 @@ static Type validateParameterType(ParamDecl *decl) {
23102317
: TypeResolverContext::FunctionInput);
23112318
options |= TypeResolutionFlags::Direct;
23122319

2320+
// We allow placeholders in parameter types to improve recovery since if a
2321+
// default argument is present we can suggest the inferred type. Avoid doing
2322+
// this for protocol requirements though since those can't ever have default
2323+
// arguments anyway.
2324+
HandlePlaceholderTypeReprFn placeholderOpener;
2325+
if (!isa<ProtocolDecl>(dc->getParent()))
2326+
placeholderOpener = PlaceholderType::get;
2327+
23132328
const auto resolution =
23142329
TypeResolution::forInterface(dc, options, unboundTyOpener,
2315-
PlaceholderType::get,
2330+
placeholderOpener,
23162331
/*packElementOpener*/ nullptr);
23172332

23182333
if (isa<VarargTypeRepr>(nestedRepr)) {
@@ -3026,9 +3041,11 @@ bool TypeChecker::isPassThroughTypealias(TypeAliasDecl *typealias,
30263041

30273042
Type
30283043
ExtendedTypeRequest::evaluate(Evaluator &eval, ExtensionDecl *ext) const {
3029-
auto error = [&ext]() {
3044+
auto &ctx = ext->getASTContext();
3045+
3046+
auto error = [&]() {
30303047
ext->setInvalid();
3031-
return ErrorType::get(ext->getASTContext());
3048+
return ErrorType::get(ctx);
30323049
};
30333050

30343051
// If we didn't parse a type, fill in an error type and bail out.
@@ -3052,6 +3069,15 @@ ExtendedTypeRequest::evaluate(Evaluator &eval, ExtensionDecl *ext) const {
30523069
if (extendedType->hasError())
30533070
return error();
30543071

3072+
auto &diags = ctx.Diags;
3073+
3074+
// Cannot extend types who contain placeholders.
3075+
if (extendedType->hasPlaceholder()) {
3076+
diags.diagnose(ext->getLoc(), diag::extension_placeholder)
3077+
.highlight(extendedRepr->getSourceRange());
3078+
return error();
3079+
}
3080+
30553081
// Hack to allow extending a generic typealias.
30563082
if (auto *unboundGeneric = extendedType->getAs<UnboundGenericType>()) {
30573083
if (auto *aliasDecl = dyn_cast<TypeAliasDecl>(unboundGeneric->getDecl())) {
@@ -3069,8 +3095,6 @@ ExtendedTypeRequest::evaluate(Evaluator &eval, ExtensionDecl *ext) const {
30693095
}
30703096
}
30713097

3072-
auto &diags = ext->getASTContext().Diags;
3073-
30743098
// Cannot extend a metatype.
30753099
if (extendedType->is<AnyMetatypeType>()) {
30763100
diags.diagnose(ext->getLoc(), diag::extension_metatype, extendedType)
@@ -3087,13 +3111,6 @@ ExtendedTypeRequest::evaluate(Evaluator &eval, ExtensionDecl *ext) const {
30873111
return error();
30883112
}
30893113

3090-
// Cannot extend types who contain placeholders.
3091-
if (extendedType->hasPlaceholder()) {
3092-
diags.diagnose(ext->getLoc(), diag::extension_placeholder)
3093-
.highlight(extendedRepr->getSourceRange());
3094-
return error();
3095-
}
3096-
30973114
return extendedType;
30983115
}
30993116

lib/Sema/TypeCheckType.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6999,7 +6999,7 @@ Type ExplicitCaughtTypeRequest::evaluate(
69996999

70007000
return TypeResolution::forInterface(func, options,
70017001
/*unboundTyOpener*/ nullptr,
7002-
PlaceholderType::get,
7002+
/*placeholderOpener*/ nullptr,
70037003
/*packElementOpener*/ nullptr)
70047004
.resolveType(thrownTypeRepr);
70057005
}
@@ -7011,7 +7011,7 @@ Type ExplicitCaughtTypeRequest::evaluate(
70117011
return TypeResolution::resolveContextualType(
70127012
thrownTypeRepr, closure,
70137013
TypeResolutionOptions(TypeResolverContext::None),
7014-
/*unboundTyOpener*/ nullptr, PlaceholderType::get,
7014+
/*unboundTyOpener*/ nullptr, /*placeholderOpener*/ nullptr,
70157015
/*packElementOpener*/ nullptr);
70167016
}
70177017

@@ -7045,7 +7045,7 @@ Type ExplicitCaughtTypeRequest::evaluate(
70457045
return TypeResolution::resolveContextualType(
70467046
typeRepr, doCatch->getDeclContext(),
70477047
TypeResolutionOptions(TypeResolverContext::None),
7048-
/*unboundTyOpener*/ nullptr, PlaceholderType::get,
7048+
/*unboundTyOpener*/ nullptr, /*placeholderOpener*/ nullptr,
70497049
/*packElementOpener*/ nullptr);
70507050
}
70517051

0 commit comments

Comments
 (0)