Skip to content

Commit 5b71b64

Browse files
committed
---
yaml --- r: 348112 b: refs/heads/master c: 6c252ae h: refs/heads/master
1 parent 88d91f3 commit 5b71b64

File tree

8 files changed

+101
-75
lines changed

8 files changed

+101
-75
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: 51a987870beda8b648c68e295f49d99f4d062c6b
2+
refs/heads/master: 6c252ae22805f62ca0086372de8f2dff58654f3b
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/include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4430,12 +4430,6 @@ ERROR(property_with_wrapper_overrides,none,
44304430
"property %0 with attached wrapper cannot override another property",
44314431
(DeclName))
44324432

4433-
ERROR(property_wrapper_and_normal_init,none,
4434-
"property %0 with attached wrapper cannot initialize both the "
4435-
"wrapper type and the property", (DeclName))
4436-
ERROR(property_wrapper_init_without_initial_value, none,
4437-
"initializing property %0 with wrapper %1 that lacks "
4438-
"an 'init(initialValue:)' initializer", (DeclName, Type))
44394433
NOTE(property_wrapper_direct_init,none,
44404434
"initialize the property wrapper type directly with "
44414435
"'(...') on the attribute", ())

trunk/lib/Sema/CodeSynthesis.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1847,8 +1847,8 @@ PropertyWrapperBackingPropertyInfoRequest::evaluate(Evaluator &evaluator,
18471847
}
18481848

18491849
// Get the property wrapper information.
1850-
if (!var->allAttachedPropertyWrappersHaveInitialValueInit()) {
1851-
assert(!originalInitialValue);
1850+
if (!var->allAttachedPropertyWrappersHaveInitialValueInit() &&
1851+
!originalInitialValue) {
18521852
return PropertyWrapperBackingPropertyInfo(
18531853
backingVar, storageVar, nullptr, nullptr, nullptr);
18541854
}
@@ -1859,9 +1859,10 @@ PropertyWrapperBackingPropertyInfoRequest::evaluate(Evaluator &evaluator,
18591859
new (ctx) OpaqueValueExpr(var->getLoc(), var->getType(),
18601860
/*isPlaceholder=*/true);
18611861
Expr *initializer = buildPropertyWrapperInitialValueCall(
1862-
var, storageType, origValue);
1863-
typeCheckSynthesizedWrapperInitializer(pbd, backingVar, parentPBD,
1864-
initializer);
1862+
var, storageType, origValue,
1863+
/*ignoreAttributeArgs=*/!originalInitialValue);
1864+
typeCheckSynthesizedWrapperInitializer(
1865+
pbd, backingVar, parentPBD, initializer);
18651866

18661867
return PropertyWrapperBackingPropertyInfo(
18671868
backingVar, storageVar, originalInitialValue, initializer, origValue);

trunk/lib/Sema/TypeCheckConstraints.cpp

Lines changed: 11 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2709,7 +2709,16 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
27092709
// call.
27102710
auto &ctx = singleVar->getASTContext();
27112711
auto outermostWrapperAttr = wrapperAttrs.front();
2712-
if (auto outermostArg = outermostWrapperAttr->getArg()) {
2712+
if (initializer) {
2713+
// Form init(initialValue:) call(s).
2714+
Expr *wrappedInitializer =
2715+
buildPropertyWrapperInitialValueCall(
2716+
singleVar, Type(), initializer, /*ignoreAttributeArgs=*/false);
2717+
if (!wrappedInitializer)
2718+
return;
2719+
2720+
initializer = wrappedInitializer;
2721+
} else if (auto outermostArg = outermostWrapperAttr->getArg()) {
27132722
Type outermostWrapperType =
27142723
singleVar->getAttachedPropertyWrapperType(0);
27152724
if (!outermostWrapperType)
@@ -2718,63 +2727,14 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
27182727
auto typeExpr = TypeExpr::createImplicitHack(
27192728
outermostWrapperAttr->getTypeLoc().getLoc(),
27202729
outermostWrapperType, ctx);
2721-
if (initializer) {
2722-
singleVar->diagnose(diag::property_wrapper_and_normal_init,
2723-
singleVar->getFullName())
2724-
.highlight(outermostWrapperAttr->getRange())
2725-
.highlight(initializer->getSourceRange());
2726-
}
2727-
27282730
initializer = CallExpr::create(
27292731
ctx, typeExpr, outermostArg,
27302732
outermostWrapperAttr->getArgumentLabels(),
27312733
outermostWrapperAttr->getArgumentLabelLocs(),
27322734
/*hasTrailingClosure=*/false,
27332735
/*implicit=*/false);
2734-
} else if (singleVar->allAttachedPropertyWrappersHaveInitialValueInit()) {
2735-
// FIXME: we want to use the initialValueInits we found.
2736-
assert(initializer);
2737-
2738-
// Form init(initialValue:) call(s).
2739-
Expr *wrappedInitializer =
2740-
buildPropertyWrapperInitialValueCall(singleVar, Type(),
2741-
initializer);
2742-
if (!wrappedInitializer)
2743-
return;
2744-
2745-
initializer = wrappedInitializer;
27462736
} else {
2747-
// Find the property wrapper that does not have an initialValue
2748-
// initializer and diagnose it.
2749-
for (unsigned i : indices(wrapperAttrs)) {
2750-
auto wrapperTypeInfo =
2751-
singleVar->getAttachedPropertyWrapperTypeInfo(i);
2752-
if (wrapperTypeInfo.initialValueInit)
2753-
continue;
2754-
2755-
Type wrapperType = singleVar->getAttachedPropertyWrapperType(i);
2756-
if (!wrapperType)
2757-
return;
2758-
2759-
auto wrapperNominal = wrapperType->getAnyNominal();
2760-
if (!wrapperNominal)
2761-
return;
2762-
2763-
CustomAttr *wrapperAttr = wrapperAttrs[i];
2764-
singleVar->diagnose(diag::property_wrapper_init_without_initial_value,
2765-
singleVar->getFullName(), wrapperType)
2766-
.highlight(initializer->getSourceRange());
2767-
ctx.Diags.diagnose(wrapperAttr->getLocation(),
2768-
diag::property_wrapper_direct_init)
2769-
.fixItInsertAfter(initializer->getSourceRange().End,
2770-
"(<# initializer args #>)");
2771-
wrapperNominal->diagnose(diag::kind_declname_declared_here,
2772-
wrapperNominal->getDescriptiveKind(),
2773-
wrapperNominal->getFullName());
2774-
return;
2775-
}
2776-
2777-
llvm_unreachable("All wrappers had init(initialValue:)?");
2737+
llvm_unreachable("No initializer anywhere?");
27782738
}
27792739
wrapperAttrs[0]->setSemanticInit(initializer);
27802740

trunk/lib/Sema/TypeCheckPropertyWrapper.cpp

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,8 @@ PropertyWrapperTypeInfoRequest::evaluate(
261261
return PropertyWrapperTypeInfo();
262262
}
263263

264-
valueVar->diagnose(diag::property_wrapper_value);
264+
valueVar->diagnose(diag::property_wrapper_value)
265+
.fixItReplace(valueVar->getNameLoc(), "wrappedValue");
265266
}
266267

267268
PropertyWrapperTypeInfo result;
@@ -560,7 +561,8 @@ Type swift::computeWrappedValueType(VarDecl *var, Type backingStorageType,
560561
}
561562

562563
Expr *swift::buildPropertyWrapperInitialValueCall(
563-
VarDecl *var, Type backingStorageType, Expr *value) {
564+
VarDecl *var, Type backingStorageType, Expr *value,
565+
bool ignoreAttributeArgs) {
564566
// From the innermost wrapper type out, form init(initialValue:) calls.
565567
ASTContext &ctx = var->getASTContext();
566568
auto wrapperAttrs = var->getAttachedPropertyWrappers();
@@ -575,8 +577,39 @@ Expr *swift::buildPropertyWrapperInitialValueCall(
575577
auto typeExpr = TypeExpr::createImplicitHack(
576578
wrapperAttrs[i]->getTypeLoc().getLoc(),
577579
wrapperType, ctx);
580+
581+
// If there were no arguments provided for the attribute at this level,
582+
// call `init(initialValue:)` directly.
583+
auto attr = wrapperAttrs[i];
584+
if (!attr->getArg() || ignoreAttributeArgs) {
585+
initializer = CallExpr::createImplicit(
586+
ctx, typeExpr, {initializer}, {ctx.Id_initialValue});
587+
continue;
588+
}
589+
590+
// Splice `initialValue:` into the argument list.
591+
SmallVector<Expr *, 4> elements;
592+
SmallVector<Identifier, 4> elementNames;
593+
SmallVector<SourceLoc, 4> elementLocs;
594+
elements.push_back(initializer);
595+
elementNames.push_back(ctx.Id_initialValue);
596+
elementLocs.push_back(SourceLoc());
597+
598+
if (auto tuple = dyn_cast<TupleExpr>(attr->getArg())) {
599+
for (unsigned i : range(tuple->getNumElements())) {
600+
elements.push_back(tuple->getElement(i));
601+
elementNames.push_back(tuple->getElementName(i));
602+
elementLocs.push_back(tuple->getElementNameLoc(i));
603+
}
604+
} else {
605+
auto paren = cast<ParenExpr>(attr->getArg());
606+
elements.push_back(paren->getSubExpr());
607+
elementNames.push_back(Identifier());
608+
elementLocs.push_back(SourceLoc());
609+
}
610+
578611
initializer = CallExpr::createImplicit(
579-
ctx, typeExpr, {initializer}, {ctx.Id_initialValue});
612+
ctx, typeExpr, elements, elementNames);
580613
}
581614

582615
return initializer;

trunk/lib/Sema/TypeChecker.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2163,7 +2163,8 @@ Type computeWrappedValueType(VarDecl *var, Type backingStorageType,
21632163
/// \c value as the original value.
21642164
Expr *buildPropertyWrapperInitialValueCall(VarDecl *var,
21652165
Type backingStorageType,
2166-
Expr *value);
2166+
Expr *value,
2167+
bool ignoreAttributeArgs);
21672168

21682169
/// Whether an overriding declaration requires the 'override' keyword.
21692170
enum class OverrideRequiresKeyword {

trunk/test/decl/var/property_wrapper_aliases.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ struct Wrapper<T> {
2626

2727
@propertyWrapper
2828
struct OldValue<T> {
29-
var value: T // expected-warning{{property wrapper's `value` property should be renamed to 'wrappedValue'; use of 'value' is deprecated}}
29+
var value: T // expected-warning{{property wrapper's `value` property should be renamed to 'wrappedValue'; use of 'value' is deprecated}}{{7-12=wrappedValue}}
3030
}
3131

3232
struct TestOldValue {

trunk/test/decl/var/property_wrappers.swift

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,9 @@ struct BadCombinations {
193193
}
194194

195195
struct MultipleWrappers {
196-
@Wrapper(wrappedValue: 17) // expected-error{{cannot convert value of type 'Wrapper<Int>' to specified type 'Int'}}
197-
@WrapperWithInitialValue
198-
var x: Int = 17 // expected-error{{property 'x' with attached wrapper cannot initialize both the wrapper type and the property}}
196+
@Wrapper(wrappedValue: 17)
197+
@WrapperWithInitialValue // expected-error{{extra argument 'initialValue' in call}}
198+
var x: Int = 17
199199

200200
@WrapperWithInitialValue // expected-error 2{{property wrapper can only apply to a single variable}}
201201
var (y, z) = (1, 2)
@@ -213,7 +213,7 @@ struct Initialization {
213213
var x2: Double
214214

215215
@Wrapper(wrappedValue: 17)
216-
var x3 = 42 // expected-error{{property 'x3' with attached wrapper cannot initialize both the wrapper type and the property}}
216+
var x3 = 42 // expected-error{{extra argument 'initialValue' in call}}
217217

218218
@Wrapper(wrappedValue: 17)
219219
var x4
@@ -232,6 +232,44 @@ struct Initialization {
232232
}
233233
}
234234

235+
@propertyWrapper
236+
struct Clamping<V: Comparable> {
237+
var value: V
238+
let min: V
239+
let max: V
240+
241+
init(initialValue: V, min: V, max: V) {
242+
value = initialValue
243+
self.min = min
244+
self.max = max
245+
assert(value >= min && value <= max)
246+
}
247+
248+
var wrappedValue: V {
249+
get { return value }
250+
set {
251+
if newValue < min {
252+
value = min
253+
} else if newValue > max {
254+
value = max
255+
} else {
256+
value = newValue
257+
}
258+
}
259+
}
260+
}
261+
262+
struct Color {
263+
@Clamping(min: 0, max: 255) var red: Int = 127
264+
@Clamping(min: 0, max: 255) var green: Int = 127
265+
@Clamping(min: 0, max: 255) var blue: Int = 127
266+
@Clamping(min: 0, max: 255) var alpha: Int = 255
267+
}
268+
269+
func testColor() {
270+
_ = Color(green: 17)
271+
}
272+
235273
// ---------------------------------------------------------------------------
236274
// Wrapper type formation
237275
// ---------------------------------------------------------------------------
@@ -732,14 +770,13 @@ struct UsesExplicitClosures {
732770
struct PD<Value> {
733771
var wrappedValue: Value
734772

735-
init<A>(initialValue: Value, a: A) { // expected-note{{'init(initialValue:a:)' declared here}}
773+
init<A>(initialValue: Value, a: A) {
736774
self.wrappedValue = initialValue
737775
}
738776
}
739777

740778
struct TestPD {
741-
@PD(a: "foo") var foo: Int = 42 // expected-error{{property 'foo' with attached wrapper cannot initialize both the wrapper type and the property}}
742-
// expected-error@-1{{missing argument for parameter 'initialValue' in call}}
779+
@PD(a: "foo") var foo: Int = 42
743780
}
744781

745782
protocol P { }

0 commit comments

Comments
 (0)