Skip to content

Commit 171d45d

Browse files
committed
Move more of the signature validation of accessors into Sema.
Use this to remove the last bit of the hack to suppres noescape on setter arguments. Add a more comprehensive test of noescape's interaction with accessors.
1 parent fec25a5 commit 171d45d

File tree

9 files changed

+329
-120
lines changed

9 files changed

+329
-120
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3060,6 +3060,9 @@ ERROR(sugar_type_not_found,none,
30603060
"broken standard library: cannot find "
30613061
"%select{Array|Optional|ImplicitlyUnwrappedOptional|Dictionary|"
30623062
"Error}0 type", (unsigned))
3063+
ERROR(pointer_type_not_found,none,
3064+
"broken standard library: cannot find "
3065+
"%select{UnsafePointer|UnsafeMutablePointer}0 type", (unsigned))
30633066
ERROR(optional_intrinsics_not_found,none,
30643067
"broken standard library: cannot find intrinsic operations on "
30653068
"Optional<T>", ())

lib/AST/ASTVerifier.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2193,11 +2193,10 @@ class Verifier : public ASTWalker {
21932193
if (!var->getDeclContext()->contextHasLazyGenericEnvironment()) {
21942194
paramType = var->getDeclContext()->mapTypeIntoContext(paramType);
21952195
if (!paramType->isEqual(typeForAccessors)) {
2196-
Out << "property and setter param have mismatched types: '";
2197-
typeForAccessors.print(Out);
2198-
Out << "' vs. '";
2199-
paramType.print(Out);
2200-
Out << "'\n";
2196+
Out << "property and setter param have mismatched types:\n";
2197+
typeForAccessors.dump(Out, 2);
2198+
Out << "vs.\n";
2199+
paramType.dump(Out, 2);
22012200
abort();
22022201
}
22032202
}

lib/Parse/ParseDecl.cpp

Lines changed: 85 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -3347,8 +3347,32 @@ static FuncDecl *createAccessorFunc(SourceLoc DeclLoc, ParameterList *param,
33473347
}
33483348

33493349
if (Indices) {
3350-
Indices = Indices->clone(P->Context, ParameterList::Implicit);
3351-
ValueArgElements.append(Indices->begin(), Indices->end());
3350+
// Create parameter declarations corresponding to each of the
3351+
// parameter declarations from the subscript declaration.
3352+
for (ParamDecl *storageParam : *Indices) {
3353+
// Clone the parameter. Do not clone the parameter type;
3354+
// this will be filled in by the type-checker.
3355+
auto accessorParam =
3356+
new (P->Context) ParamDecl(storageParam->getSpecifier(),
3357+
storageParam->getSpecifierLoc(),
3358+
storageParam->getArgumentNameLoc(),
3359+
storageParam->getArgumentName(),
3360+
storageParam->getNameLoc(),
3361+
storageParam->getName(),
3362+
Type(),
3363+
P->CurDeclContext);
3364+
accessorParam->setVariadic(storageParam->isVariadic());
3365+
3366+
// The cloned parameter is implicit.
3367+
accessorParam->setImplicit();
3368+
3369+
// It has no default arguments; these will be always be taken
3370+
// from the subscript declaration.
3371+
accessorParam->setDefaultArgumentKind(DefaultArgumentKind::None);
3372+
3373+
ValueArgElements.push_back(accessorParam);
3374+
}
3375+
33523376
if (StartLoc.isInvalid()) {
33533377
StartLoc = Indices->getStartLoc();
33543378
EndLoc = Indices->getEndLoc();
@@ -3370,82 +3394,9 @@ static FuncDecl *createAccessorFunc(SourceLoc DeclLoc, ParameterList *param,
33703394
// Add the "(value)" and subscript indices parameter clause.
33713395
Params.push_back(ValueArg);
33723396

3397+
// The typechecker will always fill this in.
33733398
TypeLoc ReturnType;
33743399

3375-
// Getters return the value type.
3376-
if (Kind == AccessorKind::IsGetter) {
3377-
ReturnType = ElementTy.clone(P->Context);
3378-
3379-
// Addressors return Unsafe{,Mutable}Pointer<T>, plus sometimes an
3380-
// owner or pinned owner.
3381-
} else if (Kind == AccessorKind::IsAddressor ||
3382-
Kind == AccessorKind::IsMutableAddressor) {
3383-
3384-
// If we don't have a declared type, we will diagnose later,
3385-
// so skip this to avoid crashing.
3386-
if (ElementTy.getTypeRepr()) {
3387-
// Construct "Unsafe{,Mutable}Pointer<T>".
3388-
3389-
TypeRepr *args[] = { ElementTy.clone(P->Context).getTypeRepr() };
3390-
3391-
// FIXME: the fact that this could resolve in the local scope is dumb.
3392-
bool isMutable = (Kind == AccessorKind::IsMutableAddressor);
3393-
Identifier name = P->Context.getIdentifier(
3394-
isMutable ? "UnsafeMutablePointer" : "UnsafePointer");
3395-
3396-
TypeRepr *resultType =
3397-
new (P->Context) GenericIdentTypeRepr(SourceLoc(), name,
3398-
P->Context.AllocateCopy(args),
3399-
SourceRange());
3400-
3401-
auto makeKnownType = [&](Type type) -> TypeRepr* {
3402-
return new (P->Context) FixedTypeRepr(type, SourceLoc());
3403-
};
3404-
auto makePairType = [&](TypeRepr *fst, TypeRepr *snd) -> TypeRepr* {
3405-
return TupleTypeRepr::create(P->Context, {fst, snd}, SourceRange());
3406-
};
3407-
3408-
switch (addressorKind) {
3409-
case AddressorKind::NotAddressor:
3410-
llvm_unreachable("not an addressor!");
3411-
3412-
// For unsafe addressors, that's all we've got.
3413-
case AddressorKind::Unsafe:
3414-
break;
3415-
3416-
// For non-native owning addressors, the return type is actually
3417-
// (Unsafe{,Mutable}Pointer<T>, Builtin.UnknownObject)
3418-
case AddressorKind::Owning:
3419-
resultType = makePairType(resultType,
3420-
makeKnownType(P->Context.TheUnknownObjectType));
3421-
break;
3422-
3423-
// For native owning addressors, the return type is actually
3424-
// (Unsafe{,Mutable}Pointer<T>, Builtin.NativeObject)
3425-
case AddressorKind::NativeOwning:
3426-
resultType = makePairType(resultType,
3427-
makeKnownType(P->Context.TheNativeObjectType));
3428-
break;
3429-
3430-
// For native pinning addressors, the return type is actually
3431-
// (Unsafe{,Mutable}Pointer<T>, Builtin.NativeObject?)
3432-
case AddressorKind::NativePinning: {
3433-
auto optNativePtr = new (P->Context) OptionalTypeRepr(
3434-
makeKnownType(P->Context.TheNativeObjectType),
3435-
SourceLoc());
3436-
resultType = makePairType(resultType, optNativePtr);
3437-
break;
3438-
}
3439-
}
3440-
3441-
ReturnType = resultType;
3442-
}
3443-
3444-
// Everything else returns ().
3445-
} else {
3446-
ReturnType = TypeLoc::withoutLoc(TupleType::getEmpty(P->Context));
3447-
}
3448-
34493400
// Start the function.
34503401
auto *D = FuncDecl::create(P->Context, StaticLoc, StaticSpellingKind::None,
34513402
/*FIXME FuncLoc=*/DeclLoc, Identifier(),
@@ -3489,8 +3440,7 @@ static FuncDecl *createAccessorFunc(SourceLoc DeclLoc, ParameterList *param,
34893440

34903441
static ParamDecl *
34913442
createSetterAccessorArgument(SourceLoc nameLoc, Identifier name,
3492-
TypeLoc elementTy, AccessorKind accessorKind,
3493-
Parser &P) {
3443+
AccessorKind accessorKind, Parser &P) {
34943444
// Add the parameter. If no name was specified, the name defaults to
34953445
// 'value'.
34963446
bool isNameImplicit = name.empty();
@@ -3507,8 +3457,6 @@ createSetterAccessorArgument(SourceLoc nameLoc, Identifier name,
35073457
if (isNameImplicit)
35083458
result->setImplicit();
35093459

3510-
result->getTypeLoc() = elementTy.clone(P.Context);
3511-
35123460
// AST Walker shouldn't go into the type recursively.
35133461
result->setIsTypeLocImplicit(true);
35143462
return result;
@@ -3518,7 +3466,7 @@ createSetterAccessorArgument(SourceLoc nameLoc, Identifier name,
35183466
/// parameter list to represent the spelled argument or return null if none is
35193467
/// present.
35203468
static ParameterList *
3521-
parseOptionalAccessorArgument(SourceLoc SpecifierLoc, TypeLoc ElementTy,
3469+
parseOptionalAccessorArgument(SourceLoc SpecifierLoc,
35223470
Parser &P, AccessorKind Kind) {
35233471
// 'set' and 'willSet' have a (value) parameter, 'didSet' takes an (oldValue)
35243472
// parameter and 'get' and always takes a () parameter.
@@ -3556,7 +3504,7 @@ parseOptionalAccessorArgument(SourceLoc SpecifierLoc, TypeLoc ElementTy,
35563504
}
35573505

35583506
if (Name.empty()) NameLoc = SpecifierLoc;
3559-
auto param = createSetterAccessorArgument(NameLoc, Name, ElementTy, Kind, P);
3507+
auto param = createSetterAccessorArgument(NameLoc, Name, Kind, P);
35603508
return ParameterList::create(P.Context, StartLoc, param, EndLoc);
35613509
}
35623510

@@ -3779,7 +3727,7 @@ bool Parser::parseGetSetImpl(ParseDeclOptions Flags,
37793727
diagnose(Loc, diag::protocol_setter_name);
37803728

37813729
auto *ValueNameParams
3782-
= parseOptionalAccessorArgument(Loc, ElementTy, *this, Kind);
3730+
= parseOptionalAccessorArgument(Loc, *this, Kind);
37833731

37843732
// Set up a function declaration.
37853733
TheDecl = createAccessorFunc(Loc, ValueNameParams,
@@ -3905,7 +3853,7 @@ bool Parser::parseGetSetImpl(ParseDeclOptions Flags,
39053853
//
39063854
// set-name ::= '(' identifier ')'
39073855
auto *ValueNamePattern =
3908-
parseOptionalAccessorArgument(Loc, ElementTy, *this, Kind);
3856+
parseOptionalAccessorArgument(Loc, *this, Kind);
39093857

39103858
SourceLoc LBLoc = isImplicitGet ? VarLBLoc : Tok.getLoc();
39113859
// FIXME: Use outer '{' loc if isImplicitGet.
@@ -4033,6 +3981,54 @@ void Parser::parseAccessorBodyDelayed(AbstractFunctionDecl *AFD) {
40333981
AFD->setBody(Body);
40343982
}
40353983

3984+
static void fillInAccessorTypeErrors(Parser &P, FuncDecl *accessor,
3985+
AccessorKind kind) {
3986+
if (!accessor) return;
3987+
3988+
// Fill in the parameter types.
3989+
for (auto paramList : accessor->getParameterLists()) {
3990+
for (auto param : *paramList) {
3991+
if (param->getTypeLoc().isNull()) {
3992+
param->getTypeLoc().setType(P.Context.TheErrorType, true);
3993+
}
3994+
}
3995+
}
3996+
3997+
// Fill in the result type.
3998+
switch (kind) {
3999+
case AccessorKind::NotAccessor:
4000+
case AccessorKind::IsMaterializeForSet:
4001+
llvm_unreachable("should never be seen here");
4002+
4003+
// These have non-trivial returns, so fill in error.
4004+
case AccessorKind::IsGetter:
4005+
case AccessorKind::IsAddressor:
4006+
case AccessorKind::IsMutableAddressor:
4007+
accessor->getBodyResultTypeLoc().setType(P.Context.TheErrorType, true);
4008+
return;
4009+
4010+
// These return void.
4011+
case AccessorKind::IsSetter:
4012+
case AccessorKind::IsWillSet:
4013+
case AccessorKind::IsDidSet:
4014+
return;
4015+
}
4016+
llvm_unreachable("bad kind");
4017+
}
4018+
4019+
/// We weren't able to tie the given accessors to a storage declaration.
4020+
/// Fill in various slots with type errors.
4021+
static void fillInAccessorTypeErrors(Parser &P,
4022+
Parser::ParsedAccessors &accessors) {
4023+
fillInAccessorTypeErrors(P, accessors.Get, AccessorKind::IsGetter);
4024+
fillInAccessorTypeErrors(P, accessors.Set, AccessorKind::IsSetter);
4025+
fillInAccessorTypeErrors(P, accessors.Addressor, AccessorKind::IsAddressor);
4026+
fillInAccessorTypeErrors(P, accessors.MutableAddressor,
4027+
AccessorKind::IsMutableAddressor);
4028+
fillInAccessorTypeErrors(P, accessors.WillSet, AccessorKind::IsWillSet);
4029+
fillInAccessorTypeErrors(P, accessors.DidSet, AccessorKind::IsDidSet);
4030+
}
4031+
40364032
/// \brief Parse the brace-enclosed getter and setter for a variable.
40374033
VarDecl *Parser::parseDeclVarGetSet(Pattern *pattern,
40384034
ParseDeclOptions Flags,
@@ -4076,8 +4072,10 @@ VarDecl *Parser::parseDeclVarGetSet(Pattern *pattern,
40764072
Invalid = true;
40774073

40784074
// If we have an invalid case, bail out now.
4079-
if (!PrimaryVar)
4075+
if (!PrimaryVar) {
4076+
fillInAccessorTypeErrors(*this, accessors);
40804077
return nullptr;
4078+
}
40814079

40824080
if (!TyLoc.hasLocation()) {
40834081
if (accessors.Get || accessors.Set || accessors.Addressor ||
@@ -4258,7 +4256,7 @@ void Parser::ParsedAccessors::record(Parser &P, AbstractStorageDecl *storage,
42584256
auto argFunc = (WillSet ? WillSet : DidSet);
42594257
auto argLoc = argFunc->getParameterLists().back()->getStartLoc();
42604258

4261-
auto argument = createSetterAccessorArgument(argLoc, Identifier(),elementTy,
4259+
auto argument = createSetterAccessorArgument(argLoc, Identifier(),
42624260
AccessorKind::IsSetter, P);
42634261
auto argList = ParameterList::create(P.Context, argument);
42644262
Set = createImplicitAccessor(AccessorKind::IsSetter,
@@ -4281,7 +4279,7 @@ void Parser::ParsedAccessors::record(Parser &P, AbstractStorageDecl *storage,
42814279
assert(Get && !Set);
42824280
auto argument =
42834281
createSetterAccessorArgument(MutableAddressor->getLoc(), Identifier(),
4284-
elementTy, AccessorKind::IsSetter, P);
4282+
AccessorKind::IsSetter, P);
42854283
auto argList = ParameterList::create(P.Context, argument);
42864284
Set = createImplicitAccessor(AccessorKind::IsSetter,
42874285
AddressorKind::NotAddressor, argList);

lib/Sema/TypeCheckDecl.cpp

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5194,6 +5194,15 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
51945194
if (auto storage = FD->getAccessorStorageDecl()) {
51955195
TC.validateDecl(storage);
51965196

5197+
// Note that it's important for correctness that we're filling in
5198+
// empty TypeLocs, because otherwise revertGenericFuncSignature might
5199+
// erase the types we set, causing them to be re-validated in a later
5200+
// pass. That later validation might be incorrect even if the TypeLocs
5201+
// are a clone of the type locs from which we derived the value type,
5202+
// because the rules for interpreting types in parameter contexts
5203+
// are sometimes different from the rules elsewhere; for example,
5204+
// function types default to non-escaping.
5205+
51975206
auto valueParams = FD->getParameterList(FD->getParent()->isTypeContext());
51985207

51995208
// Determine the value type.
@@ -5228,10 +5237,13 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
52285237
case AccessorKind::NotAccessor:
52295238
llvm_unreachable("not an accessor");
52305239

5240+
// For getters, set the result type to the value type.
52315241
case AccessorKind::IsGetter:
52325242
FD->getBodyResultTypeLoc().setType(valueIfaceTy, true);
52335243
break;
52345244

5245+
// For setters and observers, set the old/new value parameter's type
5246+
// to the value type.
52355247
case AccessorKind::IsDidSet:
52365248
case AccessorKind::IsWillSet:
52375249
case AccessorKind::IsSetter: {
@@ -5242,10 +5254,16 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
52425254
break;
52435255
}
52445256

5245-
// These don't mention the value types directly.
5246-
case AccessorKind::IsMaterializeForSet:
5257+
// Addressor result types can get complicated because of the owner.
52475258
case AccessorKind::IsAddressor:
52485259
case AccessorKind::IsMutableAddressor:
5260+
if (Type resultType = buildAddressorResultType(FD, valueIfaceTy)) {
5261+
FD->getBodyResultTypeLoc().setType(resultType, true);
5262+
}
5263+
break;
5264+
5265+
// These don't mention the value types directly.
5266+
case AccessorKind::IsMaterializeForSet:
52495267
break;
52505268
}
52515269
}
@@ -5418,6 +5436,61 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
54185436
}
54195437
}
54205438

5439+
Type buildAddressorResultType(FuncDecl *addressor, Type valueType) {
5440+
assert(addressor->getAccessorKind() == AccessorKind::IsAddressor ||
5441+
addressor->getAccessorKind() == AccessorKind::IsMutableAddressor);
5442+
5443+
Type pointerType =
5444+
(addressor->getAccessorKind() == AccessorKind::IsAddressor)
5445+
? TC.getUnsafePointerType(addressor->getLoc(), valueType)
5446+
: TC.getUnsafeMutablePointerType(addressor->getLoc(), valueType);
5447+
if (!pointerType) return Type();
5448+
5449+
switch (addressor->getAddressorKind()) {
5450+
case AddressorKind::NotAddressor:
5451+
llvm_unreachable("addressor without addressor kind");
5452+
5453+
// For unsafe addressors, it's just the pointer type.
5454+
case AddressorKind::Unsafe:
5455+
return pointerType;
5456+
5457+
// For non-native owning addressors, the return type is actually
5458+
// (Unsafe{,Mutable}Pointer<T>, Builtin.UnknownObject)
5459+
case AddressorKind::Owning: {
5460+
TupleTypeElt elts[] = {
5461+
pointerType,
5462+
TC.Context.TheUnknownObjectType
5463+
};
5464+
return TupleType::get(elts, TC.Context);
5465+
}
5466+
5467+
// For native owning addressors, the return type is actually
5468+
// (Unsafe{,Mutable}Pointer<T>, Builtin.NativeObject)
5469+
case AddressorKind::NativeOwning: {
5470+
TupleTypeElt elts[] = {
5471+
pointerType,
5472+
TC.Context.TheNativeObjectType
5473+
};
5474+
return TupleType::get(elts, TC.Context);
5475+
}
5476+
5477+
// For native pinning addressors, the return type is actually
5478+
// (Unsafe{,Mutable}Pointer<T>, Builtin.NativeObject?)
5479+
case AddressorKind::NativePinning: {
5480+
Type pinTokenType =
5481+
TC.getOptionalType(addressor->getLoc(), TC.Context.TheNativeObjectType);
5482+
if (!pinTokenType) return Type();
5483+
5484+
TupleTypeElt elts[] = {
5485+
pointerType,
5486+
pinTokenType
5487+
};
5488+
return TupleType::get(elts, TC.Context);
5489+
}
5490+
}
5491+
llvm_unreachable("bad addressor kind");
5492+
}
5493+
54215494
void visitModuleDecl(ModuleDecl *) { }
54225495

54235496
/// Perform basic checking to determine whether a declaration can override a

0 commit comments

Comments
 (0)