Skip to content

Commit 7dc2c70

Browse files
authored
Merge pull request #11874 from rjmccall/accessor-validation-noescape
2 parents b7f744c + 171d45d commit 7dc2c70

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)