Skip to content

Commit

Permalink
Commit DaveA's API changes to 'print', along with the compiler change…
Browse files Browse the repository at this point in the history
…s necessary to support them.

There's still work left to do. In terms of next steps, there's still rdar://problem/22126141, which covers removing the 'workaround' overloads for print (that prevent bogus overload resolution failures), as well as providing a decent diagnostic when users invoke print with 'appendNewline'.

Swift SVN r30976
  • Loading branch information
jopamer committed Aug 4, 2015
1 parent c5bc10a commit 828eb68
Show file tree
Hide file tree
Showing 73 changed files with 498 additions and 1,546 deletions.
3 changes: 3 additions & 0 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,9 @@ class alignas(1 << TypeAlignInBits) TypeBase {

/// Whether this is the AnyObject type.
bool isAnyObject();

/// Whether this is an empty existential composition ("{}").
bool isEmptyExistentialComposition();

void dump() const LLVM_ATTRIBUTE_USED;
void dump(raw_ostream &os, unsigned indent = 0) const;
Expand Down
11 changes: 11 additions & 0 deletions lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,17 @@ bool TypeBase::isAnyObject() {
return false;
}

bool TypeBase::isEmptyExistentialComposition() {
if (auto emtType = ExistentialMetatypeType::get(this)) {
if (auto pcType = emtType->getInstanceType()->
getAs<ProtocolCompositionType>()) {
return pcType->getProtocols().empty();
}
}

return false;
}

static Type getStrippedType(const ASTContext &context, Type type,
bool stripLabels, bool stripDefaultArgs) {
return type.transform([&](Type type) -> Type {
Expand Down
10 changes: 4 additions & 6 deletions lib/Sema/CSRanking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ void ConstraintSystem::increaseScore(ScoreKind kind) {
case SK_ScalarPointerConversion:
log << "scalar-to-pointer conversion";
break;
case SK_EmptyExistentialConversion:
log << "empty-existential conversion";
break;
}
log << ")\n";
}
Expand Down Expand Up @@ -441,12 +444,7 @@ static bool hasEmptyExistenialParameterMismatch(ValueDecl *decl1,
break;

if (t2->isAnyExistentialType() && !t1->isAnyExistentialType()) {
if (auto emtType = ExistentialMetatypeType::get(t2)) {
if (auto pcType = emtType->getInstanceType()->
getAs<ProtocolCompositionType>()) {
return pcType->getProtocols().empty();
}
}
return t2->isEmptyExistentialComposition();
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions lib/Sema/CSSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1372,6 +1372,12 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind,
}

assignFixedType(typeVar1, type2);

// For symmetry with overload resolution, penalize conversions to empty
// existentials.
if (type2->isEmptyExistentialComposition())
increaseScore(ScoreKind::SK_EmptyExistentialConversion);

return SolutionKind::Solved;
}

Expand Down
4 changes: 3 additions & 1 deletion lib/Sema/ConstraintSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -746,8 +746,10 @@ enum ScoreKind {
SK_ScalarPointerConversion,
/// A conversion from an array to a pointer of matching element type.
SK_ArrayPointerConversion,
/// A conversion to an empty existential type ('Any' or '{}').
SK_EmptyExistentialConversion,

SK_LastScoreKind = SK_ArrayPointerConversion,
SK_LastScoreKind = SK_EmptyExistentialConversion,
};

/// The number of score kinds.
Expand Down
12 changes: 6 additions & 6 deletions stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,8 @@ public func expectationFailure(
stackTrace: SourceLocStack) {
_anyExpectFailed = true
stackTrace.print()
print(reason, appendNewline: reason != "")
print(message, appendNewline: message != "")
print(reason, terminator: reason == "" ? "" : "\n")
print(message, terminator: message == "" ? "" : "\n")
}

public func expectEqual<T>(
Expand Down Expand Up @@ -378,7 +378,7 @@ public func expectCrashLater() {
print("\(_stdlibUnittestStreamPrefix);expectCrash;\(_anyExpectFailed)")

var stderr = _Stderr()
print("\(_stdlibUnittestStreamPrefix);expectCrash", &stderr)
print("\(_stdlibUnittestStreamPrefix);expectCrash", toStream: &stderr)

_seenExpectCrash = true
}
Expand Down Expand Up @@ -449,7 +449,7 @@ func _childProcess() {
print("\(_stdlibUnittestStreamPrefix);end;\(_anyExpectFailed)")

var stderr = _Stderr()
print("\(_stdlibUnittestStreamPrefix);end", &stderr)
print("\(_stdlibUnittestStreamPrefix);end", toStream: &stderr)

if !testSuite._testByName(testName).canReuseChildProcessAfterTest {
return
Expand Down Expand Up @@ -501,11 +501,11 @@ struct _ParentProcess {
_spawnChild()
}

print("\(testSuite.name);\(testName)", &_childStdin)
print("\(testSuite.name);\(testName)", toStream: &_childStdin)

let currentTest = testSuite._testByName(testName)
if let stdinText = currentTest.stdinText {
print(stdinText, &_childStdin, appendNewline: false)
print(stdinText, terminator: "", toStream: &_childStdin)
}
if currentTest.stdinEndsWithEOF {
_childStdin.close()
Expand Down
4 changes: 2 additions & 2 deletions stdlib/public/core/Arrays.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -703,9 +703,9 @@ extension ${Self} : CustomStringConvertible, CustomDebugStringConvertible {
result += ", "
}
if isDebug {
debugPrint(item, &result, appendNewline: false)
debugPrint(item, terminator: "", toStream: &result)
} else {
print(item, &result, appendNewline: false)
print(item, terminator: "", toStream: &result)
}
}
result += "]"
Expand Down
10 changes: 5 additions & 5 deletions stdlib/public/core/HashedCollections.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,7 @@ extension Set: CustomStringConvertible, CustomDebugStringConvertible {
} else {
result += ", "
}
debugPrint(member, &result, appendNewline: false)
debugPrint(member, terminator: "", toStream: &result)
}
result += isDebug ? "])" : "]"
return result
Expand Down Expand Up @@ -1281,15 +1281,15 @@ extension Dictionary : CustomStringConvertible, CustomDebugStringConvertible {
result += ", "
}
if isDebug {
debugPrint(k, &result, appendNewline: false)
debugPrint(k, terminator: "", toStream: &result)
} else {
print(k, &result, appendNewline: false)
print(k, terminator: "", toStream: &result)
}
result += ": "
if isDebug {
debugPrint(v, &result, appendNewline: false)
debugPrint(v, terminator: "", toStream: &result)
} else {
print(v, &result, appendNewline: false)
print(v, terminator: "", toStream: &result)
}
}
result += "]"
Expand Down
4 changes: 2 additions & 2 deletions stdlib/public/core/Mirror.swift
Original file line number Diff line number Diff line change
Expand Up @@ -773,7 +773,7 @@ extension String {
/// - SeeAlso: `String.init<T>(reflecting: T)`
public init<T>(_ instance: T) {
self.init()
print(instance, &self, appendNewline: false)
print(instance, terminator: "", toStream: &self)
}

/// Initialize `self` with a detailed textual representation of
Expand All @@ -794,7 +794,7 @@ extension String {
/// - SeeAlso: `String.init<T>(T)`
public init<T>(reflecting subject: T) {
self.init()
debugPrint(subject, &self, appendNewline: false)
debugPrint(subject, terminator: "", toStream: &self)
}
}

Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/core/Optional.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ extension Optional : CustomDebugStringConvertible {
switch self {
case .Some(let value):
var result = "Optional("
debugPrint(value, &result, appendNewline: false)
debugPrint(value, terminator: "", toStream: &result)
result += ")"
return result
case .None:
Expand Down
168 changes: 6 additions & 162 deletions stdlib/public/core/OutputStream.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ internal func _adHocPrint<T, TargetStream : OutputStreamType>(
}
let (_, elementMirror) = mirror[i]
let elt = elementMirror.value
debugPrint(elt, &target, appendNewline: false)
debugPrint(elt, terminator: "", toStream: &target)
}
target.write(")")

Expand All @@ -121,9 +121,9 @@ internal func _adHocPrint<T, TargetStream : OutputStreamType>(
target.write(", ")
}
let (label, elementMirror) = mirror[i]
print(label, &target, appendNewline: false)
print(label, terminator: "", toStream: &target)
target.write(": ")
debugPrint(elementMirror.value, &target, appendNewline: false)
debugPrint(elementMirror.value, terminator: "", toStream: &target)
}
target.write(")")

Expand All @@ -145,18 +145,18 @@ internal func _adHocPrint<T, TargetStream : OutputStreamType>(
}
let (_, payload) = mirror[0]
if payload is _TupleMirror {
debugPrint(payload.value, &target, appendNewline: false)
debugPrint(payload.value, terminator: "", toStream: &target)
return
}
target.write("(")
debugPrint(payload.value, &target, appendNewline: false)
debugPrint(payload.value, terminator: "", toStream: &target)
target.write(")")

case is _MetatypeMirror:
printTypeName(mirror.value as! Any.Type)

default:
print(mirror.summary, &target, appendNewline: false)
print(mirror.summary, terminator: "", toStream: &target)
}
}

Expand Down Expand Up @@ -331,162 +331,6 @@ public func toDebugString<T>(x: T) -> String {
fatalError("unavailable function can't be called")
}

//===----------------------------------------------------------------------===//
// print()
//===----------------------------------------------------------------------===//

/// Writes the textual representation of `value`, and an optional newline,
/// into the stream `target`.
///
/// The textual representation is obtained from the `value` using its protocol
/// conformances, in the following order of preference: `Streamable`,
/// `CustomStringConvertible`, `CustomDebugStringConvertible`. If none of
/// these conformances are found, a default text representation is constructed
/// in an implementation-defined way, based on the type kind and structure.
///
/// Do not overload this function for your type. Instead, adopt one of the
/// protocols mentioned above.
///
/// - parameter appendNewline: Iff `true` (the default), write a trailing
/// newline.
@inline(never)
@_semantics("stdlib_binary_only")
public func print<T, TargetStream : OutputStreamType>(
value: T, inout _ target: TargetStream, appendNewline: Bool
) {
target._lock()
_print_unlocked(value, &target)
if appendNewline {
target.write("\n")
}
target._unlock()
}

@inline(never)
@_semantics("stdlib_binary_only")
public func print<T, TargetStream : OutputStreamType>(
value: T, inout _ target: TargetStream
) {
// FIXME: The PlaygroundTransform/print.swift test currently depends
// on maintaining this overload in lieu of using a default argument.
print(value, &target, appendNewline: true)
}

/// Writes the textual representation of `value`, and an optional newline,
/// into the standard output.
///
/// The textual representation is obtained from the `value` using its protocol
/// conformances, in the following order of preference: `Streamable`,
/// `CustomStringConvertible`, `CustomDebugStringConvertible`. If none of
/// these conformances are found, a default text representation is constructed
/// in an implementation-defined way, based on the type kind and structure.
///
/// Do not overload this function for your type. Instead, adopt one of the
/// protocols mentioned above.
///
/// - parameter appendNewline: Iff `true` (the default), write a trailing
/// newline.
@inline(never)
@_semantics("stdlib_binary_only")
public func print<T>(value: T, appendNewline: Bool) {
if let hook = _playgroundPrintHook {
var output = _TeeStream(left: "", right: _Stdout())
print(value, &output, appendNewline: appendNewline)
hook(output.left)
}
else {
var output = _Stdout()
print(value, &output, appendNewline: appendNewline)
}
}

@inline(never)
@_semantics("stdlib_binary_only")
public func print<T>(value: T) {
// FIXME: the PlaygroundTransform/array_did_set.swift test currently
// on maintaining this overload in lieu of using a default argument.
print(value, appendNewline: true)
}

//===----------------------------------------------------------------------===//
// debugPrint()
//===----------------------------------------------------------------------===//

/// Writes the textual representation of `value` most suitable for debugging,
/// and an optional newline, into the stream `target`.
///
/// The textual representation is obtained from the `value` using its protocol
/// conformances, in the following order of preference:
/// `CustomDebugStringConvertible`, `CustomStringConvertible`, `Streamable`.
/// If none of these conformances are found, a default text representation is
/// constructed in an implementation-defined way, based on the type kind and
/// structure.
///
/// Do not overload this function for your type. Instead, adopt one of the
/// protocols mentioned above.
///
/// - parameter appendNewline: Iff `true` (the default), write a trailing
/// newline.
@inline(never)
@_semantics("stdlib_binary_only")
public func debugPrint<T, TargetStream : OutputStreamType>(
value: T, inout _ target: TargetStream, appendNewline: Bool
) {
target._lock()
_debugPrint_unlocked(value, &target)
if appendNewline {
target.write("\n")
}
target._unlock()
}

@inline(never)
@_semantics("stdlib_binary_only")
public func debugPrint<T, TargetStream : OutputStreamType>(
value: T, inout _ target: TargetStream
) {
// FIXME: The PlaygroundTransform/print.swift test currently depends
// on maintaining this overload in lieu of using a default argument.
debugPrint(value, &target, appendNewline: true)
}

/// Writes the textual representation of `value` most suitable for debugging,
/// and an optional newline, into the standard output.
///
/// The textual representation is obtained from the `value` using its protocol
/// conformances, in the following order of preference:
/// `CustomDebugStringConvertible`, `CustomStringConvertible`, `Streamable`.
/// If none of these conformances are found, a default text representation is
/// constructed in an implementation-defined way, based on the type kind and
/// structure.
///
/// Do not overload this function for your type. Instead, adopt one of the
/// protocols mentioned above.
///
/// - parameter appendNewline: Iff `true` (the default), write a trailing
/// newline.
@inline(never)
@_semantics("stdlib_binary_only")
public func debugPrint<T>(value: T, appendNewline: Bool) {
if let hook = _playgroundPrintHook {
var output = _TeeStream(left: "", right: _Stdout())
debugPrint(value, &output, appendNewline: appendNewline)
hook(output.left)
}
else {
var output = _Stdout()
debugPrint(value, &output, appendNewline: appendNewline)
}
}

@inline(never)
@_semantics("stdlib_binary_only")
public func debugPrint<T>(value: T) {
// FIXME: The PlaygroundTransform/print.swift test currently depends
// on maintaining this overload in lieu of using a default argument.
debugPrint(value, appendNewline: true)
}

/// A hook for playgrounds to print through.
public var _playgroundPrintHook : ((String)->Void)? = {_ in () }

Expand Down
Loading

0 comments on commit 828eb68

Please sign in to comment.