mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Provide an alternative to requesting if an expression has inout type
To remove some callers of 'is<InOutType>' after Sema, start using what will soon be a structural invariant - the only expressions that can possibly have 'inout' type are semantically InOut expressions.
This commit is contained in:
@@ -4385,10 +4385,7 @@ public:
|
|||||||
|
|
||||||
/// Get the type of the variable within its context. If the context is generic,
|
/// Get the type of the variable within its context. If the context is generic,
|
||||||
/// this will use archetypes.
|
/// this will use archetypes.
|
||||||
Type getType() const {
|
Type getType() const;
|
||||||
assert(!typeInContext.isNull() && "no contextual type set yet");
|
|
||||||
return typeInContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the type of the variable within its context.
|
/// Set the type of the variable within its context.
|
||||||
void setType(Type t);
|
void setType(Type t);
|
||||||
@@ -4577,7 +4574,7 @@ public:
|
|||||||
ParameterTypeFlags getParameterFlags() const;
|
ParameterTypeFlags getParameterFlags() const;
|
||||||
|
|
||||||
SourceLoc getSpecifierLoc() const { return SpecifierLoc; }
|
SourceLoc getSpecifierLoc() const { return SpecifierLoc; }
|
||||||
|
|
||||||
bool isTypeLocImplicit() const { return IsTypeLocImplicit; }
|
bool isTypeLocImplicit() const { return IsTypeLocImplicit; }
|
||||||
void setIsTypeLocImplicit(bool val) { IsTypeLocImplicit = val; }
|
void setIsTypeLocImplicit(bool val) { IsTypeLocImplicit = val; }
|
||||||
|
|
||||||
|
|||||||
@@ -592,6 +592,15 @@ public:
|
|||||||
/// a base class.
|
/// a base class.
|
||||||
bool isSuperExpr() const;
|
bool isSuperExpr() const;
|
||||||
|
|
||||||
|
/// Returns whether the semantically meaningful content of this expression is
|
||||||
|
/// an inout expression.
|
||||||
|
///
|
||||||
|
/// FIXME(Remove InOutType): This should eventually sub-in for
|
||||||
|
/// 'E->getType()->is<InOutType>()' in all cases.
|
||||||
|
bool isSemanticallyInOutExpr() const {
|
||||||
|
return getSemanticsProvidingExpr()->getKind() == ExprKind::InOut;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns false if this expression needs to be wrapped in parens when
|
/// Returns false if this expression needs to be wrapped in parens when
|
||||||
/// used inside of a any postfix expression, true otherwise.
|
/// used inside of a any postfix expression, true otherwise.
|
||||||
///
|
///
|
||||||
@@ -3241,10 +3250,8 @@ class InOutExpr : public Expr {
|
|||||||
SourceLoc OperLoc;
|
SourceLoc OperLoc;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
InOutExpr(SourceLoc operLoc, Expr *subExpr, Type type,
|
InOutExpr(SourceLoc operLoc, Expr *subExpr, Type baseType,
|
||||||
bool isImplicit = false)
|
bool isImplicit = false);
|
||||||
: Expr(ExprKind::InOut, isImplicit, type),
|
|
||||||
SubExpr(subExpr), OperLoc(operLoc) {}
|
|
||||||
|
|
||||||
SourceLoc getStartLoc() const { return OperLoc; }
|
SourceLoc getStartLoc() const { return OperLoc; }
|
||||||
SourceLoc getEndLoc() const { return SubExpr->getEndLoc(); }
|
SourceLoc getEndLoc() const { return SubExpr->getEndLoc(); }
|
||||||
|
|||||||
@@ -946,14 +946,12 @@ FuncDecl *ASTContext::getArrayAppendElementDecl() const {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
if (ParamLists[0]->size() != 1)
|
if (ParamLists[0]->size() != 1)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
if (!ParamLists[0]->get(0)->isInOut())
|
||||||
InOutType *SelfInOutTy =
|
|
||||||
ParamLists[0]->get(0)->getInterfaceType()->getAs<InOutType>();
|
|
||||||
if (!SelfInOutTy)
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
auto SelfInOutTy = ParamLists[0]->get(0)->getInterfaceType();
|
||||||
BoundGenericStructType *SelfGenericStructTy =
|
BoundGenericStructType *SelfGenericStructTy =
|
||||||
SelfInOutTy->getObjectType()->getAs<BoundGenericStructType>();
|
SelfInOutTy->getInOutObjectType()->getAs<BoundGenericStructType>();
|
||||||
if (!SelfGenericStructTy)
|
if (!SelfGenericStructTy)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (SelfGenericStructTy->getDecl() != getArrayDecl())
|
if (SelfGenericStructTy->getDecl() != getArrayDecl())
|
||||||
@@ -997,14 +995,12 @@ FuncDecl *ASTContext::getArrayReserveCapacityDecl() const {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
if (ParamLists[0]->size() != 1)
|
if (ParamLists[0]->size() != 1)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
if (!ParamLists[0]->get(0)->isInOut())
|
||||||
InOutType *SelfInOutTy =
|
|
||||||
ParamLists[0]->get(0)->getInterfaceType()->getAs<InOutType>();
|
|
||||||
if (!SelfInOutTy)
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
auto SelfInOutTy = ParamLists[0]->get(0)->getInterfaceType();
|
||||||
BoundGenericStructType *SelfGenericStructTy =
|
BoundGenericStructType *SelfGenericStructTy =
|
||||||
SelfInOutTy->getObjectType()->getAs<BoundGenericStructType>();
|
SelfInOutTy->getInOutObjectType()->getAs<BoundGenericStructType>();
|
||||||
if (!SelfGenericStructTy)
|
if (!SelfGenericStructTy)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (SelfGenericStructTy->getDecl() != getArrayDecl())
|
if (SelfGenericStructTy->getDecl() != getArrayDecl())
|
||||||
@@ -2665,13 +2661,18 @@ BuiltinVectorType *BuiltinVectorType::get(const ASTContext &context,
|
|||||||
|
|
||||||
ParenType *ParenType::get(const ASTContext &C, Type underlying,
|
ParenType *ParenType::get(const ASTContext &C, Type underlying,
|
||||||
ParameterTypeFlags fl) {
|
ParameterTypeFlags fl) {
|
||||||
auto flags = fl.withInOut(underlying->is<InOutType>());
|
if (fl.isInOut())
|
||||||
|
assert(!underlying->is<InOutType>() && "caller did not pass a base type");
|
||||||
|
if (underlying->is<InOutType>())
|
||||||
|
assert(fl.isInOut() && "caller did not set flags correctly");
|
||||||
|
|
||||||
auto properties = underlying->getRecursiveProperties();
|
auto properties = underlying->getRecursiveProperties();
|
||||||
auto arena = getArena(properties);
|
auto arena = getArena(properties);
|
||||||
ParenType *&Result =
|
ParenType *&Result =
|
||||||
C.Impl.getArena(arena).ParenTypes[{underlying, flags.toRaw()}];
|
C.Impl.getArena(arena).ParenTypes[{underlying, fl.toRaw()}];
|
||||||
if (Result == nullptr) {
|
if (Result == nullptr) {
|
||||||
Result = new (C, arena) ParenType(underlying, properties, flags);
|
Result = new (C, arena) ParenType(underlying,
|
||||||
|
properties, fl);
|
||||||
}
|
}
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
@@ -2693,7 +2694,7 @@ void TupleType::Profile(llvm::FoldingSetNodeID &ID,
|
|||||||
/// getTupleType - Return the uniqued tuple type with the specified elements.
|
/// getTupleType - Return the uniqued tuple type with the specified elements.
|
||||||
Type TupleType::get(ArrayRef<TupleTypeElt> Fields, const ASTContext &C) {
|
Type TupleType::get(ArrayRef<TupleTypeElt> Fields, const ASTContext &C) {
|
||||||
if (Fields.size() == 1 && !Fields[0].isVararg() && !Fields[0].hasName())
|
if (Fields.size() == 1 && !Fields[0].isVararg() && !Fields[0].hasName())
|
||||||
return ParenType::get(C, Fields[0].getType(),
|
return ParenType::get(C, Fields[0].getRawType(),
|
||||||
Fields[0].getParameterFlags());
|
Fields[0].getParameterFlags());
|
||||||
|
|
||||||
RecursiveTypeProperties properties;
|
RecursiveTypeProperties properties;
|
||||||
@@ -2703,7 +2704,7 @@ Type TupleType::get(ArrayRef<TupleTypeElt> Fields, const ASTContext &C) {
|
|||||||
if (!eltTy) continue;
|
if (!eltTy) continue;
|
||||||
|
|
||||||
properties |= eltTy->getRecursiveProperties();
|
properties |= eltTy->getRecursiveProperties();
|
||||||
hasInOut |= eltTy->is<InOutType>();
|
hasInOut |= Elt.getParameterFlags().isInOut();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto arena = getArena(properties);
|
auto arena = getArena(properties);
|
||||||
@@ -2740,10 +2741,38 @@ Type TupleType::get(ArrayRef<TupleTypeElt> Fields, const ASTContext &C) {
|
|||||||
|
|
||||||
TupleTypeElt::TupleTypeElt(Type ty, Identifier name,
|
TupleTypeElt::TupleTypeElt(Type ty, Identifier name,
|
||||||
ParameterTypeFlags fl)
|
ParameterTypeFlags fl)
|
||||||
: Name(name), ElementType(ty), Flags(fl.withInOut(ty->is<InOutType>())) {
|
: Name(name), ElementType(ty), Flags(fl) {
|
||||||
// FIXME: Re-enable this assertion and hunt down the callers that aren't
|
if (fl.isInOut())
|
||||||
// setting parameter bits correctly.
|
assert(!ty->is<InOutType>() && "caller did not pass a base type");
|
||||||
// assert((ty->is<InOutType>() && fl.isInOut()) && "caller did not set flags");
|
if (ty->is<InOutType>())
|
||||||
|
assert(fl.isInOut() && "caller did not set flags correctly");
|
||||||
|
}
|
||||||
|
|
||||||
|
Type TupleTypeElt::getType() const {
|
||||||
|
if (Flags.isInOut()) return InOutType::get(ElementType);
|
||||||
|
return ElementType;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnyFunctionType::Param::Param(const TupleTypeElt &tte)
|
||||||
|
: Ty(tte.isVararg() ? tte.getVarargBaseTy() : tte.getRawType()),
|
||||||
|
Label(tte.getName()), Flags(tte.getParameterFlags()) {
|
||||||
|
assert(getType()->is<InOutType>() == Flags.isInOut());
|
||||||
|
}
|
||||||
|
|
||||||
|
AnyFunctionType::Param::Param(Type t, Identifier l, ParameterTypeFlags f)
|
||||||
|
: Ty(t), Label(l), Flags(f) {
|
||||||
|
if (f.isInOut())
|
||||||
|
assert(!t->is<InOutType>() && "caller did not pass a base type");
|
||||||
|
if (!t.isNull() && t->is<InOutType>())
|
||||||
|
assert(f.isInOut() && "caller did not set flags correctly");
|
||||||
|
}
|
||||||
|
|
||||||
|
Type AnyFunctionType::Param::getType() const {
|
||||||
|
if (Flags.isInOut()) return InOutType::get(Ty);
|
||||||
|
// FIXME: Callers are inconsistenly setting this flag and retrieving this
|
||||||
|
// type with and without the Array Slice type.
|
||||||
|
// if (Flags.isVariadic()) return ArraySliceType::get(Ty);
|
||||||
|
return Ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnboundGenericType::Profile(llvm::FoldingSetNodeID &ID,
|
void UnboundGenericType::Profile(llvm::FoldingSetNodeID &ID,
|
||||||
@@ -3176,13 +3205,18 @@ void AnyFunctionType::decomposeInput(
|
|||||||
}
|
}
|
||||||
|
|
||||||
case TypeKind::Paren: {
|
case TypeKind::Paren: {
|
||||||
auto ty = cast<ParenType>(type.getPointer())->getUnderlyingType();
|
auto pty = cast<ParenType>(type.getPointer());
|
||||||
result.push_back(AnyFunctionType::Param(ty));
|
result.push_back(AnyFunctionType::Param(pty->getUnderlyingType()->getInOutObjectType(),
|
||||||
|
Identifier(),
|
||||||
|
pty->getParameterFlags()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
result.push_back(AnyFunctionType::Param(type));
|
// assert(type->is<InOutType>() && "Found naked inout type");
|
||||||
|
result.push_back(AnyFunctionType::Param(type->getInOutObjectType(),
|
||||||
|
Identifier(),
|
||||||
|
ParameterTypeFlags::fromParameterType(type, false)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3191,7 +3225,7 @@ Type AnyFunctionType::composeInput(ASTContext &ctx, ArrayRef<Param> params,
|
|||||||
bool canonicalVararg) {
|
bool canonicalVararg) {
|
||||||
SmallVector<TupleTypeElt, 4> elements;
|
SmallVector<TupleTypeElt, 4> elements;
|
||||||
for (const auto ¶m : params) {
|
for (const auto ¶m : params) {
|
||||||
Type eltType = param.getType();
|
Type eltType = param.getRawType();
|
||||||
if (param.isVariadic()) {
|
if (param.isVariadic()) {
|
||||||
if (canonicalVararg)
|
if (canonicalVararg)
|
||||||
eltType = BoundGenericType::get(ctx.getArrayDecl(), Type(), {eltType});
|
eltType = BoundGenericType::get(ctx.getArrayDecl(), Type(), {eltType});
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ ManagedValue ArgumentSource::getAsSingleValue(SILGenFunction &SGF,
|
|||||||
}
|
}
|
||||||
case Kind::Expr: {
|
case Kind::Expr: {
|
||||||
auto e = std::move(*this).asKnownExpr();
|
auto e = std::move(*this).asKnownExpr();
|
||||||
if (e->getType()->is<InOutType>()) {
|
if (e->isSemanticallyInOutExpr()) {
|
||||||
return SGF.emitAddressOfLValue(e, SGF.emitLValue(e, AccessKind::ReadWrite),
|
return SGF.emitAddressOfLValue(e, SGF.emitLValue(e, AccessKind::ReadWrite),
|
||||||
AccessKind::ReadWrite);
|
AccessKind::ReadWrite);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ public:
|
|||||||
case Kind::Invalid: llvm_unreachable("argument source is invalid");
|
case Kind::Invalid: llvm_unreachable("argument source is invalid");
|
||||||
case Kind::RValue: return false;
|
case Kind::RValue: return false;
|
||||||
case Kind::LValue: return true;
|
case Kind::LValue: return true;
|
||||||
case Kind::Expr: return asKnownExpr()->getType()->is<InOutType>();
|
case Kind::Expr: return asKnownExpr()->isSemanticallyInOutExpr();
|
||||||
case Kind::Tuple: return false;
|
case Kind::Tuple: return false;
|
||||||
}
|
}
|
||||||
llvm_unreachable("bad kind");
|
llvm_unreachable("bad kind");
|
||||||
|
|||||||
Reference in New Issue
Block a user