Add wrappers around Builtin.isUnique.

Currently they do nothing but allow stdlib code to use regular (Bool)
types.  However, soon the wrappers for the _native variants will
provide point-of-use sanity checking.

These need to be fully generic to support class protocols and
single-payload enums (not just for optional). It also avoids a massive
amount of overloading for all the reference type variations
(AnyObject, Native, Unknown, Bridge) x 2 for optional versions of
each.

Because the wrapper is generic, type checking had to be deferred until
IRGen. Generating code for the wrapper itself will result in an
IRGen-time type error. They need to be transparent anyway for proper
diagnostics, but also must be internal.

Note that the similar external API type checks ok because it
forces conformance to AnyObject.

The sanity checks are disabled because our current facilities for
unsafe type casting are incomplete and unsound. SILCombine can
remove UnsafeMutablePointer and RawPointer casts by assuming layout
compatibility. IRGen will later discover layout incompatibility and
generate a trap.

I'll send out a proposal for improving the casting situation so we can
get the sanity checks back.

Swift SVN r28057
This commit is contained in:
Andrew Trick
2015-05-01 23:45:44 +00:00
parent 2d872dc7d2
commit 5bc23acf75
9 changed files with 102 additions and 73 deletions

View File

@@ -855,23 +855,10 @@ emitBuiltinMakeMaterializeForSetCallback(SILGenFunction &gen,
return ManagedValue::forUnmanaged(result);
}
static bool requireRefCountedType(SILGenFunction &gen,
SILLocation loc,
Type type) {
auto valueType = type->getOptionalObjectType();
auto objType = valueType ? valueType : type;
if (objType->mayHaveSuperclass()
|| objType->isClassExistentialType()
|| objType->is<BuiltinNativeObjectType>()
|| objType->is<BuiltinBridgeObjectType>()
|| objType->is<BuiltinUnknownObjectType>()) {
return true;
}
gen.SGM.diagnose(loc, diag::invalid_sil_builtin,
"isUnique operand type must be a refcounted object");
return false;
}
// This should only accept as an operand type single-refcounted-pointer types,
// class existentials, or single-payload enums (optional). Type checking must be
// deferred until IRGen so Builtin.isUnique can be called from a transparent
// generic wrapper (we can only type check after specialization).
static ManagedValue emitBuiltinIsUnique(SILGenFunction &gen,
SILLocation loc,
ArrayRef<Substitution> subs,
@@ -880,11 +867,6 @@ static ManagedValue emitBuiltinIsUnique(SILGenFunction &gen,
SGFContext C) {
assert(subs.size() == 1 && "isUnique should have a single substitution");
if (!requireRefCountedType(gen, loc, subs[0].getReplacement())) {
auto Int1Ty = SILType::getBuiltinIntegerType(1, gen.getASTContext());
return ManagedValue::forUnmanaged(SILUndef::get(Int1Ty, gen.SGM.M));
}
assert(args.size() == 1 && "isUnique should have a single argument");
assert((args[0].getType().isAddress() && !args[0].hasCleanup()) &&
"Builtin.isUnique takes an address.");
@@ -901,11 +883,6 @@ emitBuiltinIsUniqueOrPinned(SILGenFunction &gen,
CanFunctionType formalApplyType,
SGFContext C) {
assert(subs.size() == 1 && "isUnique should have a single substitution");
if (!requireRefCountedType(gen, loc, subs[0].getReplacement())) {
auto Int1Ty = SILType::getBuiltinIntegerType(1, gen.getASTContext());
return ManagedValue::forUnmanaged(SILUndef::get(Int1Ty, gen.SGM.M));
}
assert(args.size() == 1 && "isUnique should have a single argument");
assert((args[0].getType().isAddress() && !args[0].hasCleanup()) &&
"Builtin.isUnique takes an address.");