Skip to content

Fix a bug found by inspection and add some regression tests #8709

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 12, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 3 additions & 24 deletions lib/Sema/CSApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4748,31 +4748,10 @@ Expr *ExprRewriter::coerceExistential(Expr *expr, Type toType,
cs.getType(result)));
}

// If the type we are trying to coerce is a tuple, let's look through
// its elements to see if there are any LValue types present, such requires
// load or address-of operation first before proceeding with erasure.
// Load tuples with lvalue elements.
if (auto tupleType = fromType->getAs<TupleType>()) {
bool coerceToRValue = false;
for (auto element : tupleType->getElements()) {
if (element.getType()->is<LValueType>()) {
coerceToRValue = true;
break;
}
}

// Tuple has one or more LValue types associated with it,
// which requires coercion to RValue, let's perform it here by creating
// new tuple type with LValue(s) stripped off and coercing
// expression to that type, which would do required transformation.
if (coerceToRValue) {
SmallVector<TupleTypeElt, 2> elements;
for (auto &element : tupleType->getElements())
elements.push_back(TupleTypeElt(element.getType()->getRValueType(),
element.getName(),
element.getParameterFlags()));

// New type is guaranteed to be a tuple because source type is one.
auto toTuple = TupleType::get(elements, ctx)->castTo<TupleType>();
if (tupleType->isLValueType()) {
auto toTuple = tupleType->getRValueType()->castTo<TupleType>();
SmallVector<int, 4> sources;
SmallVector<unsigned, 4> variadicArgs;
bool failed = computeTupleShuffle(tupleType, toTuple,
Expand Down
11 changes: 11 additions & 0 deletions test/Constraints/tuple.swift
Original file line number Diff line number Diff line change
Expand Up @@ -202,3 +202,14 @@ func f(a : r25271859<(Float, Int)>) {
}
}

// LValue to rvalue conversions.

func takesRValue(_: (Int, (Int, Int))) {}
func takesAny(_: Any) {}

var x = 0
var y = 0

let _ = (x, (y, 0))
takesRValue((x, (y, 0)))
takesAny((x, (y, 0)))
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
// REQUIRES: asserts

func matched<C: Collection>(atStartOf c: C)
where C.Index#^A^# == Index {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
// REQUIRES: asserts

let bounds: Range#^A^#
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
// REQUIRES: asserts

func searchTest(format: ()->String = { "" }#^A^#) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
// REQUIRES: asserts

func _thread() {
_ = #^A^#
}

func run<InputCollection : Collection, Result>(_: InputCollection) -> Result {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// RUN: %target-swift-ide-test -code-completion -code-completion-token=A1 -source-filename=%s
// RUN: %target-swift-ide-test -code-completion -code-completion-token=B1 -source-filename=%s
// RUN: %target-swift-ide-test -code-completion -code-completion-token=C1 -source-filename=%s

// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A2 -source-filename=%s
// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=B2 -source-filename=%s
// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=C2 -source-filename=%s

// RUN: %target-swift-ide-test -code-completion -code-completion-token=A3 -source-filename=%s
// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=B3 -source-filename=%s
// REQUIRES: asserts

class a1<b#^A1^#> {}
struct a2<b#^B1^#> {}
enum a3<b#^C1^#> {}

class a4<b> where c == b#^A2^# {}
struct a5<b> where c == b#^B2^# {}
enum a6<b> where c == b#^C2^# {}yt

func f1<b#^A3^#> {}
func f2<b>() where c == b#^B3^# {}
12 changes: 12 additions & 0 deletions validation-test/IDE/crashers_2/0006-crazy-associated-types.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
// REQUIRES: asserts

protocol a {
associatedtype b
}
protocol c {
associatedtype d : a
}

struct e<f : c> where f == f.g.b {
#^A^#
11 changes: 11 additions & 0 deletions validation-test/IDE/crashers_2/0007-archetype-not-in-context.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
// REQUIRES: asserts

class D<X, Y>() {}

class C<T> {
func f<U>() -> D<U, T> {}
func g() {
f#^A^#
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
// REQUIRES: asserts

.a != nil #^A^#
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
// REQUIRES: asserts

extension Integer {
#^A^#
extension {
var : Self
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
// REQUIRES: asserts

Integer#^A^#
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
// REQUIRES: asserts

protocol a where #^A^#
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
// REQUIRES: asserts

func a<b>(() -> b) -> b {
a {}#^A^#
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s

extension Integer {
init() {
self = #^A^#
}
}
14 changes: 14 additions & 0 deletions validation-test/IDE/crashers_2_fixed/0014-sr4560.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s

protocol MyDelegate: AnyObject {
func mySweetDelegateFunction()
}

class Foo {
weak var delegate: MyDelegate?

func bar() {
self.delegate.#^A^#
// ^--- type "." here -> crash
}
}