mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
AST: Assign interface types to ParamDecls
First, ensure all ParamDecls that are synthesized from scratch are given both a contextual type and an interface type. For ParamDecls written in source, add a new recordParamType() method to GenericTypeResolver. This calls setType() or setInterfaceType() as appropriate. Interestingly enough a handful of diagnostics in the test suite have improved. I'm not sure why, but I'll take it. The ParamDecl::createUnboundSelf() method is now only used in the parser, and no longer sets the type of the self parameter to the unbound generic type. This was wrong anyway, since the type was always being overwritten. This allows us to remove DeclContext::getSelfTypeOfContext(). Also, ensure that FuncDecl::getBodyResultTypeLoc() always has an interface type for synthesized declarations, eliminating a mapTypeOutOfContext() call when computing the function interface type in configureInterfaceType(). Finally, clean up the logic for resolving the DynamicSelfType. We now get the interface or contextual type of 'Self' via the resolver, instead of always getting the contextual type and patching it up inside configureInterfaceType().
This commit is contained in:
@@ -54,37 +54,51 @@ static VarDecl *getFirstParamDecl(FuncDecl *fn) {
|
||||
|
||||
|
||||
static ParamDecl *buildArgument(SourceLoc loc, DeclContext *DC,
|
||||
StringRef name, Type type, bool isLet) {
|
||||
StringRef name,
|
||||
Type type,
|
||||
Type interfaceType,
|
||||
bool isLet) {
|
||||
auto &context = DC->getASTContext();
|
||||
auto *param = new (context) ParamDecl(isLet, SourceLoc(), SourceLoc(),
|
||||
Identifier(), loc,
|
||||
context.getIdentifier(name),Type(), DC);
|
||||
context.getIdentifier(name),
|
||||
type, DC);
|
||||
param->setImplicit();
|
||||
param->getTypeLoc().setType(type);
|
||||
param->setInterfaceType(interfaceType);
|
||||
return param;
|
||||
}
|
||||
|
||||
static ParamDecl *buildLetArgument(SourceLoc loc, DeclContext *DC,
|
||||
StringRef name, Type type) {
|
||||
return buildArgument(loc, DC, name, type, /*isLet*/ true);
|
||||
StringRef name,
|
||||
Type type,
|
||||
Type interfaceType) {
|
||||
return buildArgument(loc, DC, name, type, interfaceType, /*isLet*/ true);
|
||||
}
|
||||
|
||||
static ParamDecl *buildInOutArgument(SourceLoc loc, DeclContext *DC,
|
||||
StringRef name, Type type) {
|
||||
return buildArgument(loc, DC, name, InOutType::get(type), /*isLet*/ false);
|
||||
StringRef name,
|
||||
Type type,
|
||||
Type interfaceType) {
|
||||
return buildArgument(
|
||||
loc, DC, name,
|
||||
InOutType::get(type),
|
||||
InOutType::get(interfaceType),
|
||||
/*isLet*/ false);
|
||||
}
|
||||
|
||||
static Type getTypeOfStorage(AbstractStorageDecl *storage,
|
||||
TypeChecker &TC) {
|
||||
if (auto var = dyn_cast<VarDecl>(storage)) {
|
||||
return TC.getTypeOfRValue(var, /*want interface type*/ false);
|
||||
} else {
|
||||
// None of the transformations done by getTypeOfRValue are
|
||||
// necessary for subscripts.
|
||||
auto subscript = cast<SubscriptDecl>(storage);
|
||||
return ArchetypeBuilder::mapTypeIntoContext(
|
||||
storage->getDeclContext(), subscript->getElementInterfaceType());
|
||||
}
|
||||
TypeChecker &TC,
|
||||
bool wantInterfaceType) {
|
||||
if (auto var = dyn_cast<VarDecl>(storage))
|
||||
return TC.getTypeOfRValue(var, wantInterfaceType);
|
||||
|
||||
// None of the transformations done by getTypeOfRValue are
|
||||
// necessary for subscripts.
|
||||
auto subscript = cast<SubscriptDecl>(storage);
|
||||
auto type = subscript->getElementInterfaceType();
|
||||
if (!wantInterfaceType)
|
||||
type = storage->getDeclContext()->mapTypeIntoContext(type);
|
||||
return type;
|
||||
}
|
||||
|
||||
/// Build a parameter list which can forward the formal index parameters of a
|
||||
@@ -127,7 +141,7 @@ static FuncDecl *createGetterPrototype(AbstractStorageDecl *storage,
|
||||
|
||||
// The implicit 'self' argument if in a type context.
|
||||
if (storage->getDeclContext()->isTypeContext())
|
||||
getterParams.push_back(ParameterList::createUnboundSelf(loc,
|
||||
getterParams.push_back(ParameterList::createSelf(loc,
|
||||
storage->getDeclContext(),
|
||||
/*isStatic*/false));
|
||||
|
||||
@@ -140,13 +154,13 @@ static FuncDecl *createGetterPrototype(AbstractStorageDecl *storage,
|
||||
staticLoc = var->getLoc();
|
||||
}
|
||||
|
||||
auto storageType = getTypeOfStorage(storage, TC);
|
||||
auto storageInterfaceType = getTypeOfStorage(storage, TC, true);
|
||||
|
||||
auto getter = FuncDecl::create(
|
||||
TC.Context, staticLoc, StaticSpellingKind::None, loc, Identifier(), loc,
|
||||
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
|
||||
/*AccessorKeywordLoc=*/SourceLoc(), /*GenericParams=*/nullptr,
|
||||
getterParams, TypeLoc::withoutLoc(storageType),
|
||||
getterParams, TypeLoc::withoutLoc(storageInterfaceType),
|
||||
storage->getDeclContext());
|
||||
getter->setImplicit();
|
||||
|
||||
@@ -171,18 +185,24 @@ static FuncDecl *createSetterPrototype(AbstractStorageDecl *storage,
|
||||
// Create the parameter list for the setter.
|
||||
SmallVector<ParameterList*, 2> params;
|
||||
|
||||
bool isStatic = storage->isStatic();
|
||||
bool isMutating = !storage->isSetterNonMutating();
|
||||
|
||||
// The implicit 'self' argument if in a type context.
|
||||
if (storage->getDeclContext()->isTypeContext()) {
|
||||
params.push_back(ParameterList::createUnboundSelf(loc,
|
||||
params.push_back(ParameterList::createSelf(loc,
|
||||
storage->getDeclContext(),
|
||||
/*isStatic*/false));
|
||||
/*isStatic*/isStatic,
|
||||
/*isInOut*/isMutating));
|
||||
}
|
||||
|
||||
// Add a "(value : T, indices...)" argument list.
|
||||
auto storageType = getTypeOfStorage(storage, TC);
|
||||
auto storageType = getTypeOfStorage(storage, TC, false);
|
||||
auto storageInterfaceType = getTypeOfStorage(storage, TC, true);
|
||||
valueDecl = buildLetArgument(storage->getLoc(),
|
||||
storage->getDeclContext(), "value",
|
||||
storageType);
|
||||
storageType,
|
||||
storageInterfaceType);
|
||||
params.push_back(buildIndexForwardingParamList(storage, valueDecl));
|
||||
|
||||
Type setterRetTy = TupleType::getEmpty(TC.Context);
|
||||
@@ -194,16 +214,16 @@ static FuncDecl *createSetterPrototype(AbstractStorageDecl *storage,
|
||||
storage->getDeclContext());
|
||||
setter->setImplicit();
|
||||
|
||||
if (!storage->isSetterNonMutating())
|
||||
if (isMutating)
|
||||
setter->setMutating();
|
||||
|
||||
if (isStatic)
|
||||
setter->setStatic();
|
||||
|
||||
// If the var is marked final, then so is the getter.
|
||||
if (storage->isFinal())
|
||||
makeFinal(TC.Context, setter);
|
||||
|
||||
if (storage->isStatic())
|
||||
setter->setStatic();
|
||||
|
||||
return setter;
|
||||
}
|
||||
|
||||
@@ -239,14 +259,18 @@ static FuncDecl *createMaterializeForSetPrototype(AbstractStorageDecl *storage,
|
||||
// - The implicit 'self' argument if in a type context.
|
||||
auto DC = storage->getDeclContext();
|
||||
if (DC->isTypeContext())
|
||||
params.push_back(ParameterList::createUnboundSelf(loc, DC, /*isStatic*/false));
|
||||
params.push_back(ParameterList::createSelf(loc, DC, /*isStatic*/false));
|
||||
|
||||
// - The buffer parameter, (buffer: Builtin.RawPointer,
|
||||
// inout storage: Builtin.UnsafeValueBuffer,
|
||||
// indices...).
|
||||
ParamDecl *bufferElements[] = {
|
||||
buildLetArgument(loc, DC, "buffer", ctx.TheRawPointerType),
|
||||
buildInOutArgument(loc, DC, "callbackStorage", ctx.TheUnsafeValueBufferType)
|
||||
buildLetArgument(loc, DC, "buffer",
|
||||
ctx.TheRawPointerType,
|
||||
ctx.TheRawPointerType),
|
||||
buildInOutArgument(loc, DC, "callbackStorage",
|
||||
ctx.TheUnsafeValueBufferType,
|
||||
ctx.TheUnsafeValueBufferType)
|
||||
};
|
||||
params.push_back(buildIndexForwardingParamList(storage, bufferElements));
|
||||
|
||||
@@ -1307,10 +1331,8 @@ void TypeChecker::completePropertyBehaviorParameter(VarDecl *VD,
|
||||
assert(SubstInterfaceTy && "storage type substitution failed?!");
|
||||
|
||||
auto contextMap = sig->getSubstitutionMap(SelfContextSubs);
|
||||
auto SubstContextTy = ParameterTy.subst(contextMap, SubstOptions());
|
||||
assert(SubstContextTy && "storage type substitution failed?!");
|
||||
|
||||
auto SubstBodyResultTy = SubstContextTy->castTo<AnyFunctionType>()
|
||||
auto SubstBodyResultTy = SubstInterfaceTy->castTo<AnyFunctionType>()
|
||||
->getResult();
|
||||
|
||||
// Add the Self type back to the interface and context types.
|
||||
@@ -1921,20 +1943,24 @@ ConstructorDecl *swift::createImplicitConstructor(TypeChecker &tc,
|
||||
|
||||
accessLevel = std::min(accessLevel, var->getFormalAccess());
|
||||
|
||||
auto varType = tc.getTypeOfRValue(var);
|
||||
auto varType = tc.getTypeOfRValue(var, false);
|
||||
auto varInterfaceType = tc.getTypeOfRValue(var, true);
|
||||
|
||||
// If var is a lazy property, its value is provided for the underlying
|
||||
// storage. We thus take an optional of the properties type. We only
|
||||
// need to do this because the implicit constructor is added before all
|
||||
// the properties are type checked. Perhaps init() synth should be moved
|
||||
// later.
|
||||
if (var->getAttrs().hasAttribute<LazyAttr>())
|
||||
if (var->getAttrs().hasAttribute<LazyAttr>()) {
|
||||
varType = OptionalType::get(varType);
|
||||
varInterfaceType = OptionalType::get(varInterfaceType);
|
||||
}
|
||||
|
||||
// Create the parameter.
|
||||
auto *arg = new (context) ParamDecl(/*IsLet*/true, SourceLoc(),
|
||||
Loc, var->getName(),
|
||||
Loc, var->getName(), varType, decl);
|
||||
arg->setInterfaceType(varInterfaceType);
|
||||
arg->setImplicit();
|
||||
|
||||
params.push_back(arg);
|
||||
@@ -1945,7 +1971,7 @@ ConstructorDecl *swift::createImplicitConstructor(TypeChecker &tc,
|
||||
|
||||
// Create the constructor.
|
||||
DeclName name(context, context.Id_init, paramList);
|
||||
auto *selfParam = ParamDecl::createUnboundSelf(Loc, decl,
|
||||
auto *selfParam = ParamDecl::createSelf(Loc, decl,
|
||||
/*static*/false, /*inout*/true);
|
||||
auto *ctor =
|
||||
new (context) ConstructorDecl(name, Loc,
|
||||
@@ -2045,7 +2071,7 @@ swift::createDesignatedInitOverride(TypeChecker &tc,
|
||||
auto &ctx = tc.Context;
|
||||
|
||||
// Create the 'self' declaration and patterns.
|
||||
auto *selfDecl = ParamDecl::createUnboundSelf(SourceLoc(), classDecl);
|
||||
auto *selfDecl = ParamDecl::createSelf(SourceLoc(), classDecl);
|
||||
|
||||
// Create the initializer parameter patterns.
|
||||
OptionSet<ParameterList::CloneFlags> options = ParameterList::Implicit;
|
||||
@@ -2106,9 +2132,6 @@ swift::createDesignatedInitOverride(TypeChecker &tc,
|
||||
// constructor.
|
||||
AvailabilityInference::applyInferredAvailableAttrs(ctor, superclassCtor, ctx);
|
||||
|
||||
// Configure 'self'.
|
||||
configureImplicitSelf(tc, ctor);
|
||||
|
||||
// Set the interface type of the initializer.
|
||||
ctor->setGenericEnvironment(classDecl->getGenericEnvironmentOfContext());
|
||||
tc.configureInterfaceType(ctor, ctor->getGenericSignature());
|
||||
@@ -2186,7 +2209,7 @@ void TypeChecker::addImplicitDestructor(ClassDecl *CD) {
|
||||
if (CD->hasDestructor() || CD->isInvalid())
|
||||
return;
|
||||
|
||||
auto *selfDecl = ParamDecl::createUnboundSelf(CD->getLoc(), CD);
|
||||
auto *selfDecl = ParamDecl::createSelf(CD->getLoc(), CD);
|
||||
|
||||
auto *DD = new (Context) DestructorDecl(Context.Id_deinit, CD->getLoc(),
|
||||
selfDecl, CD);
|
||||
|
||||
Reference in New Issue
Block a user