Skip to content

Commit bc7cb33

Browse files
committed
Fix generic types
add tests get parent init
1 parent e8bc662 commit bc7cb33

File tree

5 files changed

+87
-8
lines changed

5 files changed

+87
-8
lines changed

lib/SILGen/SILGenApply.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3364,8 +3364,7 @@ void DelayedArgument::emitDefaultArgument(SILGenFunction &SGF,
33643364
var->getDeclContext()->getGenericSignatureOfContext();
33653365

33663366
if (genericEnv && typeGenericSig) {
3367-
// Get the substitutions from the constructor's generic env.
3368-
subs = genericEnv->getForwardingSubstitutionMap();
3367+
subs = info.defaultArgsOwner.getSubstitutions();
33693368
}
33703369

33713370
value = SGF.emitApplyOfStoredPropertyInitializer(info.loc,

lib/Sema/CodeSynthesis.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1655,11 +1655,10 @@ static void maybeAddMemberwiseDefaultArg(ParamDecl *arg, VarDecl *var,
16551655
if (!var->getParentPattern()->getSingleVar())
16561656
return;
16571657

1658-
// If we don't have an initializer and we can't assign a default initializer
1659-
// in silgen, then we can't generate a default value. An example of a default
1660-
// initializer would be var x: Int? where the default is nil.
1661-
if (!var->getParentInitializer() &&
1662-
!var->getParentPatternBinding()->isDefaultInitializable())
1658+
// If we don't have an expression initializer or silgen can't assign a default
1659+
// initializer, then we can't generate a default value. An example of where
1660+
// silgen can assign a default is var x: Int? where the default is nil.
1661+
if (!var->getParentPatternBinding()->isDefaultInitializable())
16631662
return;
16641663

16651664
// We can add a default value now.
@@ -1675,6 +1674,14 @@ static void maybeAddMemberwiseDefaultArg(ParamDecl *arg, VarDecl *var,
16751674
// we're going to call the variable's initializer expression.
16761675
arg->setStoredProperty(var);
16771676
arg->setDefaultArgumentKind(DefaultArgumentKind::StoredProperty);
1677+
1678+
// If the type is T? and has no initial value, then set the default arg kind
1679+
// to nil literal. This is useful when we need to print the constructor.
1680+
// Note, this will always be the sugared T? because we don't default init an
1681+
// explicit Optional<T>.
1682+
if (isa<OptionalType>(var->getType().getPointer()) &&
1683+
!var->getParentInitializer())
1684+
arg->setDefaultArgumentKind(DefaultArgumentKind::NilLiteral);
16781685
}
16791686

16801687
/// Create an implicit struct or class constructor.

test/IDE/complete_at_top_level.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,8 @@ func resyncParser7() {}
263263
var topLevelVar2 = FooStruct#^TOP_LEVEL_VAR_INIT_2^#
264264
// TOP_LEVEL_VAR_INIT_2: Begin completions
265265
// TOP_LEVEL_VAR_INIT_2-NEXT: Decl[InstanceMethod]/CurrNominal: .instanceFunc({#(self): FooStruct#})[#(Int) -> Void#]{{; name=.+$}}
266-
// TOP_LEVEL_VAR_INIT_2-NEXT: Decl[Constructor]/CurrNominal: ({#instanceVar: Int#})[#FooStruct#]{{; name=.+$}}
267266
// TOP_LEVEL_VAR_INIT_2-NEXT: Decl[Constructor]/CurrNominal: ()[#FooStruct#]{{; name=.+$}}
267+
// TOP_LEVEL_VAR_INIT_2-NEXT: Decl[Constructor]/CurrNominal: ({#instanceVar: Int#})[#FooStruct#]{{; name=.+$}}
268268
// TOP_LEVEL_VAR_INIT_2-NEXT: Decl[Constructor]/CurrNominal: ()[#FooStruct#]{{; name=.+$}}
269269
// TOP_LEVEL_VAR_INIT_2-NEXT: Keyword[self]/CurrNominal: .self[#FooStruct.Type#]; name=self
270270
// TOP_LEVEL_VAR_INIT_2-NEXT: Keyword/CurrNominal: .Type[#FooStruct.Type#]; name=Type
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// RUN: %target-swift-emit-silgen -primary-file %s | %FileCheck %s
2+
3+
// Currently, this only appears for memberwise initializers.
4+
5+
struct A {
6+
var b: Int = 0
7+
var c: Bool = false
8+
}
9+
10+
// CHECK: function_ref variable initialization expression of A.c
11+
// CHECK-NEXT: [[C1_REF:%.*]] = function_ref @$s27stored_property_default_arg1AV1cSbvpfi : $@convention(thin) () -> Bool
12+
// CHECK-NEXT: [[C1:%.*]] = apply [[C1_REF]]() : $@convention(thin) () -> Bool
13+
// CHECK-NEXT: function_ref A.init(b:c:)
14+
// CHECK-NEXT: [[A1_REF:%.*]] = function_ref @$s27stored_property_default_arg1AV1b1cACSi_SbtcfC : $@convention(method) (Int, Bool, @thin A.Type) -> A
15+
// CHECK-NEXT: {{.*}} = apply [[A1_REF]]({{.*}}, [[C1]], {{.*}}) : $@convention(method) (Int, Bool, @thin A.Type) -> A
16+
17+
let d = A(b: 1)
18+
19+
// CHECK: function_ref variable initialization expression of A.b
20+
// CHECK-NEXT: [[B1_REF:%.*]] = function_ref @$s27stored_property_default_arg1AV1bSivpfi : $@convention(thin) () -> Int
21+
// CHECK-NEXT: [[B1:%.*]] = apply [[B1_REF]]() : $@convention(thin) () -> Int
22+
// CHECK-NEXT: function_ref A.init(b:c:)
23+
// CHECK-NEXT: [[A2_REF:%.*]] = function_ref @$s27stored_property_default_arg1AV1b1cACSi_SbtcfC : $@convention(method) (Int, Bool, @thin A.Type) -> A
24+
// CHECK-NEXT: {{.*}} = apply [[A2_REF]]([[B1]], {{.*}}, {{.*}}) : $@convention(method) (Int, Bool, @thin A.Type) -> A
25+
26+
let e = A(c: true)
27+
28+
struct F<T> {
29+
var g: T
30+
var h: Int = 0
31+
}
32+
33+
// CHECK: function_ref variable initialization expression of F.h
34+
// CHECK-NEXT: [[H1_REF:%.*]] = function_ref @$s27stored_property_default_arg1FV1hSivpfi : $@convention(thin) <τ_0_0> () -> Int
35+
// CHECK-NEXT: [[H1:%.*]] = apply [[H1_REF]]<Int>() : $@convention(thin) <τ_0_0> () -> Int
36+
// CHECK-NEXT: function_ref F.init(g:h:)
37+
// CHECK-NEXT: [[F1_REF:%.*]] = function_ref @$s27stored_property_default_arg1FV1g1hACyxGx_SitcfC : $@convention(method) <τ_0_0> (@in τ_0_0, Int, @thin F<τ_0_0>.Type) -> @out F<τ_0_0>
38+
// CHECK-NEXT: {{.*}} = apply [[F1_REF]]<Int>({{.*}}, {{.*}}, [[H1]], {{.*}}) : $@convention(method) <τ_0_0> (@in τ_0_0, Int, @thin F<τ_0_0>.Type) -> @out F<τ_0_0>
39+
40+
let i = F(g: 128)

test/decl/func/default-values.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,36 @@ func inoutFuncWithDefaultArg4(x: inout Int = &aLiteral) {} // expected-error {{c
135135
func inoutFuncWithDefaultArg5(x: inout Int = &bLiteral) {} // expected-error {{cannot provide default value to inout parameter 'x'}}
136136
func inoutFuncWithDefaultArg6(x: inout Int = #file) {} // expected-error {{cannot provide default value to inout parameter 'x'}}
137137
func inoutFuncWithDefaultArg7(_: inout Int = 1) {} // expected-error {{cannot provide default value to inout parameter '_'}}
138+
139+
// SE-0242 - Test that memberwise constructor generates default values
140+
141+
struct Foo {
142+
var a: Int
143+
var b: Bool = false
144+
let c: (Int, Bool) = (1, true)
145+
let d: Int
146+
var (e, f) = (0, false)
147+
var g: Int?
148+
let h: Bool?
149+
150+
// The generated memberwise should look like the following:
151+
// init(a: Int, b: Bool = false, d: Int, e: Int, f: Bool, g: Int? = nil, h: Bool?)
152+
}
153+
154+
// Here b = false and g = nil
155+
let fooThing1 = Foo(a: 0, d: 1, e: 2, f: false, h: nil) // ok
156+
// Here g = nil
157+
let fooThing2 = Foo(a: 0, b: true, d: 1, e: 2, f: false, h: nil) // ok
158+
// Here b = false
159+
let fooThing3 = Foo(a: 0, d: 1, e: 2, f: false, g: 10, h: nil) // ok
160+
// Use all the parameters
161+
let fooThing4 = Foo(a: 0, b: true, d: 1, e: 2, f: false, g: 10, h: nil) // ok
162+
163+
// Ensure that tuple init is not allowed
164+
// Here b = false and g = nil, but we're checking that e and f don't get a default value
165+
let fooThing5 = Foo(a: 0, d: 1, h: nil) // expected-error {{missing argument for parameter 'e' in call}}
166+
// expected-note@-25 {{'init(a:b:d:e:f:g:h:)' declared here}}
167+
168+
// Here b = false and g = nil, but we're checking that f doesn't get a default value
169+
let fooThing6 = Foo(a: 0, d: 1, e: 2, h: nil) // expected-error {{missing argument for parameter 'f' in call}}
170+
// expected-note@-29 {{'init(a:b:d:e:f:g:h:)' declared here}}

0 commit comments

Comments
 (0)