Skip to content

Commit 4a14aae

Browse files
committed
---
yaml --- r: 348618 b: refs/heads/master c: 61e1268 h: refs/heads/master
1 parent 5673409 commit 4a14aae

File tree

13 files changed

+282
-101
lines changed

13 files changed

+282
-101
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 64382c03100dc96eef2747a9f1c828f71240491f
2+
refs/heads/master: 61e126867ca057f74c59fce5e61cadb1c71f5c02
33
refs/heads/master-next: 203b3026584ecad859eb328b2e12490099409cd5
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea

trunk/lib/IDE/Refactoring.cpp

Lines changed: 83 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -2753,78 +2753,107 @@ bool RefactoringActionLocalizeString::performChange() {
27532753
return false;
27542754
}
27552755

2756+
struct MemberwiseParameter {
2757+
Identifier Name;
2758+
Type MemberType;
2759+
Expr *DefaultExpr;
2760+
2761+
MemberwiseParameter(Identifier name, Type type, Expr *initialExpr)
2762+
: Name(name), MemberType(type), DefaultExpr(initialExpr) {}
2763+
};
2764+
27562765
static void generateMemberwiseInit(SourceEditConsumer &EditConsumer,
2757-
SourceManager &SM,
2758-
SmallVectorImpl<std::string>& memberNameVector,
2759-
SmallVectorImpl<std::string>& memberTypeVector,
2760-
SourceLoc targetLocation) {
2761-
2762-
assert(!memberTypeVector.empty());
2763-
assert(memberTypeVector.size() == memberNameVector.size());
2766+
SourceManager &SM,
2767+
ArrayRef<MemberwiseParameter> memberVector,
2768+
SourceLoc targetLocation) {
27642769

2770+
assert(!memberVector.empty());
2771+
27652772
EditConsumer.accept(SM, targetLocation, "\ninternal init(");
2766-
2767-
for (size_t i = 0, n = memberTypeVector.size(); i < n ; i++) {
2768-
EditConsumer.accept(SM, targetLocation, memberNameVector[i] + ": " +
2769-
memberTypeVector[i]);
2770-
2771-
if (i != memberTypeVector.size() - 1) {
2772-
EditConsumer.accept(SM, targetLocation, ", ");
2773+
auto insertMember = [&SM](const MemberwiseParameter &memberData,
2774+
llvm::raw_ostream &OS, bool wantsSeparator) {
2775+
OS << memberData.Name << ": " << memberData.MemberType.getString();
2776+
if (auto *expr = memberData.DefaultExpr) {
2777+
if (isa<NilLiteralExpr>(expr)) {
2778+
OS << " = nil";
2779+
} else if (expr->getSourceRange().isValid()) {
2780+
auto range =
2781+
Lexer::getCharSourceRangeFromSourceRange(
2782+
SM, expr->getSourceRange());
2783+
OS << " = " << SM.extractText(range);
2784+
}
2785+
}
2786+
2787+
if (wantsSeparator) {
2788+
OS << ", ";
27732789
}
2790+
};
2791+
2792+
// Process the initial list of members, inserting commas as appropriate.
2793+
std::string Buffer;
2794+
llvm::raw_string_ostream OS(Buffer);
2795+
for (const auto &memberData : memberVector.drop_back()) {
2796+
insertMember(memberData, OS, /*wantsSeparator*/ true);
27742797
}
2775-
2776-
EditConsumer.accept(SM, targetLocation, ") {\n");
2777-
2778-
for (auto varName: memberNameVector) {
2779-
EditConsumer.accept(SM, targetLocation,
2780-
"self." + varName + " = " + varName + "\n");
2798+
2799+
// Process the last (or perhaps, only) member.
2800+
insertMember(memberVector.back(), OS, /*wantsSeparator*/ false);
2801+
2802+
// Synthesize the body.
2803+
OS << ") {\n";
2804+
for (auto &member : memberVector) {
2805+
// self.<property> = <property>
2806+
OS << "self." << member.Name << " = " << member.Name << "\n";
27812807
}
2782-
2783-
EditConsumer.accept(SM, targetLocation, "}\n");
2808+
OS << "}\n";
2809+
2810+
// Accept the entire edit.
2811+
EditConsumer.accept(SM, targetLocation, OS.str());
27842812
}
2785-
2786-
static SourceLoc collectMembersForInit(ResolvedCursorInfo CursorInfo,
2787-
SmallVectorImpl<std::string>& memberNameVector,
2788-
SmallVectorImpl<std::string>& memberTypeVector) {
2789-
2813+
2814+
static SourceLoc
2815+
collectMembersForInit(ResolvedCursorInfo CursorInfo,
2816+
SmallVectorImpl<MemberwiseParameter> &memberVector) {
2817+
27902818
if (!CursorInfo.ValueD)
27912819
return SourceLoc();
27922820

2793-
ClassDecl *classDecl = dyn_cast<ClassDecl>(CursorInfo.ValueD);
2794-
if (!classDecl || classDecl->getStoredProperties().empty() ||
2821+
NominalTypeDecl *nominalDecl = dyn_cast<NominalTypeDecl>(CursorInfo.ValueD);
2822+
if (!nominalDecl || nominalDecl->getStoredProperties().empty() ||
27952823
CursorInfo.IsRef) {
27962824
return SourceLoc();
27972825
}
2798-
2799-
SourceLoc bracesStart = classDecl->getBraces().Start;
2826+
2827+
SourceLoc bracesStart = nominalDecl->getBraces().Start;
28002828
if (!bracesStart.isValid())
28012829
return SourceLoc();
28022830

28032831
SourceLoc targetLocation = bracesStart.getAdvancedLoc(1);
28042832
if (!targetLocation.isValid())
28052833
return SourceLoc();
2806-
2807-
for (auto varDecl : classDecl->getStoredProperties()) {
2808-
auto parentPatternBinding = varDecl->getParentPatternBinding();
2809-
if (!parentPatternBinding)
2834+
2835+
for (auto varDecl : nominalDecl->getStoredProperties()) {
2836+
auto patternBinding = varDecl->getParentPatternBinding();
2837+
if (!patternBinding)
2838+
continue;
2839+
2840+
if (!varDecl->isMemberwiseInitialized(/*preferDeclaredProperties=*/true)) {
28102841
continue;
2811-
2812-
auto varDeclIndex =
2813-
parentPatternBinding->getPatternEntryIndexForVarDecl(varDecl);
2814-
2815-
if (auto init = varDecl->getParentPatternBinding()->getInit(varDeclIndex)) {
2816-
if (init->getStartLoc().isValid())
2817-
continue;
28182842
}
2819-
2820-
StringRef memberName = varDecl->getName().str();
2821-
memberNameVector.push_back(memberName.str());
2822-
2823-
std::string memberType = varDecl->getType().getString();
2824-
memberTypeVector.push_back(memberType);
2843+
2844+
auto &entry = patternBinding->getPatternEntryForVarDecl(varDecl);
2845+
bool isExplicitlyInitialized =
2846+
entry.isInitialized() && entry.getEqualLoc().isValid();
2847+
Expr *defaultInit = nullptr;
2848+
if (isExplicitlyInitialized || patternBinding->isDefaultInitializable()) {
2849+
defaultInit = varDecl->getParentInitializer();
2850+
}
2851+
2852+
memberVector.emplace_back(varDecl->getName(),
2853+
varDecl->getType(), defaultInit);
28252854
}
28262855

2827-
if (memberNameVector.empty() || memberTypeVector.empty()) {
2856+
if (memberVector.empty()) {
28282857
return SourceLoc();
28292858
}
28302859

@@ -2834,25 +2863,18 @@ static SourceLoc collectMembersForInit(ResolvedCursorInfo CursorInfo,
28342863
bool RefactoringActionMemberwiseInitLocalRefactoring::
28352864
isApplicable(ResolvedCursorInfo Tok, DiagnosticEngine &Diag) {
28362865

2837-
SmallVector<std::string, 8> memberNameVector;
2838-
SmallVector<std::string, 8> memberTypeVector;
2839-
2840-
return collectMembersForInit(Tok, memberNameVector,
2841-
memberTypeVector).isValid();
2866+
SmallVector<MemberwiseParameter, 8> memberVector;
2867+
return collectMembersForInit(Tok, memberVector).isValid();
28422868
}
28432869

28442870
bool RefactoringActionMemberwiseInitLocalRefactoring::performChange() {
28452871

2846-
SmallVector<std::string, 8> memberNameVector;
2847-
SmallVector<std::string, 8> memberTypeVector;
2848-
2849-
SourceLoc targetLocation = collectMembersForInit(CursorInfo, memberNameVector,
2850-
memberTypeVector);
2872+
SmallVector<MemberwiseParameter, 8> memberVector;
2873+
SourceLoc targetLocation = collectMembersForInit(CursorInfo, memberVector);
28512874
if (targetLocation.isInvalid())
28522875
return true;
28532876

2854-
generateMemberwiseInit(EditConsumer, SM, memberNameVector,
2855-
memberTypeVector, targetLocation);
2877+
generateMemberwiseInit(EditConsumer, SM, memberVector, targetLocation);
28562878

28572879
return false;
28582880
}

trunk/lib/Sema/CSFix.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,26 @@ IgnoreContextualType *IgnoreContextualType::create(ConstraintSystem &cs,
759759
IgnoreContextualType(cs, resultTy, specifiedTy, locator);
760760
}
761761

762+
bool IgnoreAssignmentDestinationType::diagnose(Expr *root, bool asNote) const {
763+
auto &cs = getConstraintSystem();
764+
auto *AE = cast<AssignExpr>(getAnchor());
765+
auto CTP = isa<SubscriptExpr>(AE->getDest()) ? CTP_SubscriptAssignSource
766+
: CTP_AssignSource;
767+
768+
ContextualFailure failure(
769+
root, cs, CTP, getFromType(), getToType(),
770+
cs.getConstraintLocator(AE->getSrc(), LocatorPathElt::ContextualType()));
771+
return failure.diagnose(asNote);
772+
}
773+
774+
IgnoreAssignmentDestinationType *
775+
IgnoreAssignmentDestinationType::create(ConstraintSystem &cs, Type sourceTy,
776+
Type destTy,
777+
ConstraintLocator *locator) {
778+
return new (cs.getAllocator())
779+
IgnoreAssignmentDestinationType(cs, sourceTy, destTy, locator);
780+
}
781+
762782
bool AllowInOutConversion::diagnose(Expr *root, bool asNote) const {
763783
auto &cs = getConstraintSystem();
764784
InOutConversionFailure failure(root, cs, getFromType(), getToType(),

trunk/lib/Sema/CSFix.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,6 +1299,23 @@ class IgnoreContextualType : public ContextualMismatch {
12991299
ConstraintLocator *locator);
13001300
};
13011301

1302+
class IgnoreAssignmentDestinationType final : public ContextualMismatch {
1303+
IgnoreAssignmentDestinationType(ConstraintSystem &cs, Type sourceTy,
1304+
Type destTy, ConstraintLocator *locator)
1305+
: ContextualMismatch(cs, sourceTy, destTy, locator) {}
1306+
1307+
public:
1308+
std::string getName() const override {
1309+
return "ignore type of the assignment destination";
1310+
}
1311+
1312+
bool diagnose(Expr *root, bool asNote = false) const override;
1313+
1314+
static IgnoreAssignmentDestinationType *create(ConstraintSystem &cs,
1315+
Type sourceTy, Type destTy,
1316+
ConstraintLocator *locator);
1317+
};
1318+
13021319
/// If this is an argument-to-parameter conversion which is associated with
13031320
/// `inout` parameter, subtyping is not permitted, types have to
13041321
/// be identical.

trunk/lib/Sema/CSSimplify.cpp

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2353,6 +2353,15 @@ bool ConstraintSystem::repairFailures(
23532353
return false;
23542354
};
23552355

2356+
auto hasConversionOrRestriction = [&](ConversionRestrictionKind kind) {
2357+
return llvm::any_of(conversionsOrFixes,
2358+
[kind](const RestrictionOrFix correction) {
2359+
if (auto restriction = correction.getRestriction())
2360+
return restriction == kind;
2361+
return false;
2362+
});
2363+
};
2364+
23562365
if (path.empty()) {
23572366
if (!anchor)
23582367
return false;
@@ -2391,20 +2400,39 @@ bool ConstraintSystem::repairFailures(
23912400

23922401
if (repairViaBridgingCast(*this, lhs, rhs, conversionsOrFixes, locator))
23932402
return true;
2403+
2404+
// If we are trying to assign e.g. `Array<Int>` to `Array<Float>` let's
2405+
// give solver a chance to determine which generic parameters are
2406+
// mismatched and produce a fix for that.
2407+
if (hasConversionOrRestriction(ConversionRestrictionKind::DeepEquality))
2408+
return false;
2409+
2410+
// If the situation has to do with protocol composition types and
2411+
// destination doesn't have one of the conformances e.g. source is
2412+
// `X & Y` but destination is only `Y` or vice versa, there is a
2413+
// tailored "missing conformance" fix for that.
2414+
if (hasConversionOrRestriction(ConversionRestrictionKind::Existential))
2415+
return false;
2416+
2417+
// If this is an attempt to assign something to a value of optional type
2418+
// there is a possiblity that the problem is related to escapiness, so
2419+
// fix has to be delayed.
2420+
if (hasConversionOrRestriction(
2421+
ConversionRestrictionKind::ValueToOptional))
2422+
return false;
2423+
2424+
// If the destination of an assignment is l-value type
2425+
// it leaves only possible reason for failure - a type mismatch.
2426+
if (getType(AE->getDest())->is<LValueType>()) {
2427+
conversionsOrFixes.push_back(IgnoreAssignmentDestinationType::create(
2428+
*this, lhs, rhs, getConstraintLocator(locator)));
2429+
return true;
2430+
}
23942431
}
23952432

23962433
return false;
23972434
}
23982435

2399-
auto hasConversionOrRestriction = [&](ConversionRestrictionKind kind) {
2400-
return llvm::any_of(conversionsOrFixes,
2401-
[kind](const RestrictionOrFix correction) {
2402-
if (auto restriction = correction.getRestriction())
2403-
return restriction == kind;
2404-
return false;
2405-
});
2406-
};
2407-
24082436
auto elt = path.back();
24092437
switch (elt.getKind()) {
24102438
case ConstraintLocator::LValueConversion: {

trunk/test/Constraints/closures.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ func rdar20868864(_ s: String) {
394394
func r22058555() {
395395
var firstChar: UInt8 = 0
396396
"abc".withCString { chars in
397-
firstChar = chars[0] // expected-error {{cannot assign value of type 'Int8' to type 'UInt8'}}
397+
firstChar = chars[0] // expected-error {{cannot assign value of type 'Int8' to type 'UInt8'}} {{17-17=UInt8(}} {{25-25=)}}
398398
}
399399
}
400400

trunk/test/Generics/deduction.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func useIdentity(_ x: Int, y: Float, i32: Int32) {
2222

2323
// Deduction where the result type and input type can get different results
2424
var xx : X, yy : Y
25-
xx = identity(yy) // expected-error{{cannot convert value of type 'Y' to expected argument type 'X'}}
25+
xx = identity(yy) // expected-error{{cannot assign value of type 'Y' to type 'X'}}
2626
xx = identity2(yy) // expected-error{{cannot convert value of type 'Y' to expected argument type 'X'}}
2727
}
2828

trunk/test/ModuleInterface/Inputs/opaque-result-types-client.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ struct YourFoo: Foo {}
1717
func someTypeIsTheSame() {
1818
var a = foo(0)
1919
a = foo(0)
20-
a = foo("") // expected-error{{cannot convert value of type 'String' to expected argument type 'Int'}}
20+
a = foo("") // expected-error{{cannot assign value of type 'some Foo' (result of 'foo') to type 'some Foo' (result of 'foo')}}
2121

2222
var b = foo("")
23-
b = foo(0) // expected-error{{cannot convert value of type 'Int' to expected argument type 'String'}}
23+
b = foo(0) // expected-error{{cannot assign value of type 'some Foo' (result of 'foo') to type 'some Foo' (result of 'foo')}}
2424
b = foo("")
2525

2626
var c = foo(MyFoo())
27-
c = foo(0) // expected-error{{cannot convert value of type 'Int' to expected argument type 'MyFoo'}}
27+
c = foo(0) // expected-error{{cannot assign value of type 'some Foo' (result of 'foo') to type 'some Foo' (result of 'foo')}}
2828
c = foo(MyFoo())
2929
c = foo(YourFoo()) // expected-error{{cannot convert value of type 'YourFoo' to expected argument type 'MyFoo'}}
3030

trunk/test/refactoring/MemberwiseInit/Outputs/class_members/class_members.swift.expected

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)