diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index a726f994bb171..26e20612d2de1 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -2689,7 +2689,8 @@ static VarDecl *synthesizePropertyWrapperProjectionVar( } static void typeCheckSynthesizedWrapperInitializer(VarDecl *wrappedVar, - Expr *&initializer) { + Expr *&initializer, + bool contextualize) { auto *dc = wrappedVar->getInnermostDeclContext(); auto &ctx = wrappedVar->getASTContext(); auto *initContext = new (ctx) PropertyWrapperInitializer( @@ -2705,6 +2706,11 @@ static void typeCheckSynthesizedWrapperInitializer(VarDecl *wrappedVar, initializer = result->getAsExpr(); + // Contextualize the initializer which is a local variable with defaultInit or + // gets an independent initializer. The rest of initializer contextualizing + // will be done in visitPatternBindingDecl. + if (!contextualize) + return; TypeChecker::contextualizeInitializer(initContext, initializer); checkPropertyWrapperActorIsolation(wrappedVar, initializer); TypeChecker::checkInitializerEffects(initContext, initializer); @@ -2979,7 +2985,8 @@ PropertyWrapperInitializerInfoRequest::evaluate(Evaluator &evaluator, && !wrapperInfo.defaultInit) { auto ty = parentPBD->getPattern(patternNumber)->getType(); if (auto defaultInit = TypeChecker::buildDefaultInitializer(ty)) { - typeCheckSynthesizedWrapperInitializer(var, defaultInit); + typeCheckSynthesizedWrapperInitializer(var, defaultInit, + /*contextualize=*/false); parentPBD->setInit(0, defaultInit); parentPBD->setInitializerChecked(0); } @@ -2997,7 +3004,9 @@ PropertyWrapperInitializerInfoRequest::evaluate(Evaluator &evaluator, // FIXME: Record this expression somewhere so that DI can perform the // initialization itself. Expr *defaultInit = nullptr; - typeCheckSynthesizedWrapperInitializer(var, defaultInit); + // Only contextualize local wrapped property, the rest of wrapped + // property will be contextualized in visitPatternBindingDecl. + typeCheckSynthesizedWrapperInitializer(var, defaultInit, dc->isLocalContext()); pbd->setInit(0, defaultInit); pbd->setInitializerChecked(0); @@ -3067,7 +3076,8 @@ PropertyWrapperInitializerInfoRequest::evaluate(Evaluator &evaluator, !var->getName().hasDollarPrefix()) { wrappedValueInit = PropertyWrapperValuePlaceholderExpr::create( ctx, var->getSourceRange(), var->getType(), /*wrappedValue=*/nullptr); - typeCheckSynthesizedWrapperInitializer(var, wrappedValueInit); + typeCheckSynthesizedWrapperInitializer(var, wrappedValueInit, + /*contextualize=*/true); } return PropertyWrapperInitializerInfo(wrappedValueInit, projectedValueInit); diff --git a/test/Concurrency/global_actor_inference.swift b/test/Concurrency/global_actor_inference.swift index d29268a8d06be..9fbe0dc0dfc11 100644 --- a/test/Concurrency/global_actor_inference.swift +++ b/test/Concurrency/global_actor_inference.swift @@ -415,12 +415,13 @@ actor WrapperActorBad2 { struct WrapperWithMainActorDefaultInit { var wrappedValue: Int { fatalError() } - @MainActor init() {} // expected-note {{calls to initializer 'init()' from outside of its actor context are implicitly asynchronous}} + @MainActor init() {} // expected-note 2 {{calls to initializer 'init()' from outside of its actor context are implicitly asynchronous}} } actor ActorWithWrapper { @WrapperOnActor var synced: Int = 0 // expected-note@-1 3{{property declared here}} + @WrapperWithMainActorDefaultInit var property: Int // expected-error {{call to main actor-isolated initializer 'init()' in a synchronous actor-isolated context}} func f() { _ = synced // expected-error{{main actor-isolated property 'synced' can not be referenced on a different actor instance}} _ = $synced // expected-error{{global actor 'SomeGlobalActor'-isolated property '$synced' can not be referenced on a different actor instance}} diff --git a/test/SILGen/property_wrappers.swift b/test/SILGen/property_wrappers.swift index cc76e6378efef..b901d267ea7b8 100644 --- a/test/SILGen/property_wrappers.swift +++ b/test/SILGen/property_wrappers.swift @@ -957,6 +957,34 @@ struct TestAutoclosureComposition { @Once @ObservedObject var model = Model() } +@propertyWrapper +struct SR_15940Foo { + var wrappedValue: Int { 0 } +} + +struct SR_15940_C { + func a() { + @SR_15940Foo var b: Int + } +} + +// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers10SR_15940_CV1ayyF : $@convention(method) (SR_15940_C) -> () { +// CHECK: bb0(%0 : $SR_15940_C): +// CHECK-NEXT: debug_value %0 : $SR_15940_C, let, name "self", argno 1, implicit +// CHECK-NEXT: [[BOX:%.*]] = alloc_box ${ var SR_15940Foo }, var, name "_b" +// CHECK-NEXT: [[LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] : ${ var SR_15940Foo } +// CHECK-NEXT: [[BOXADDR:%.*]] = project_box [[LIFETIME]] : ${ var SR_15940Foo }, 0 +// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin SR_15940Foo.Type +// CHECK-NEXT: // function_ref SR_15940Foo.init() +// CHECK-NEXT: [[DEFAULTVALUE_FN:%.*]] = function_ref @$s17property_wrappers11SR_15940FooVACycfC : $@convention(method) (@thin SR_15940Foo.Type) -> SR_15940Foo +// CHECK-NEXT: [[DEFAULTRESULT:%.*]] = apply [[DEFAULTVALUE_FN]]([[METATYPE]]) : $@convention(method) (@thin SR_15940Foo.Type) -> SR_15940Foo +// CHECK-NEXT: store [[DEFAULTRESULT]] to [trivial] [[BOXADDR]] : $*SR_15940Foo +// CHECK-NEXT: end_borrow [[LIFETIME]] : ${ var SR_15940Foo } +// CHECK-NEXT: destroy_value [[BOX]] : ${ var SR_15940Foo } +// CHECK-NEXT: [[TUPLE:%.*]] = tuple () +// CHECK-NEXT: return [[TUPLE]] : $() +// CHECK-NEXT: } // end sil function '$s17property_wrappers10SR_15940_CV1ayyF + // CHECK-LABEL: sil_vtable ClassUsingWrapper { // CHECK-NEXT: #ClassUsingWrapper.x!getter: (ClassUsingWrapper) -> () -> Int : @$s17property_wrappers17ClassUsingWrapperC1xSivg // ClassUsingWrapper.x.getter // CHECK-NEXT: #ClassUsingWrapper.x!setter: (ClassUsingWrapper) -> (Int) -> () : @$s17property_wrappers17ClassUsingWrapperC1xSivs // ClassUsingWrapper.x.setter diff --git a/test/Sema/property_wrappers.swift b/test/Sema/property_wrappers.swift index dc2bf3fda765f..19cf5bdac0db5 100644 --- a/test/Sema/property_wrappers.swift +++ b/test/Sema/property_wrappers.swift @@ -47,3 +47,37 @@ struct TestInitSubscript { @Wrapper(wrappedValue: Color.allCases[0]) var color: Color } + +@propertyWrapper +public class SR_15940Bar { + private var _value: Value + + public var wrappedValue: Value { + get { _value } + set { + _value = newValue + } + } + + public init(wrappedValue value: @autoclosure @escaping () -> Value) { + self._value = value() + } +} + +// CHECK-LABEL: struct_decl{{.*}}SR_15940_A +struct SR_15940_A { + // CHECK: argument_list implicit labels=wrappedValue: + // CHECK-NEXT: argument label=wrappedValue + // CHECK-NEXT: autoclosure_expr implicit type='() -> Bool?' discriminator=0 captures=( ) escaping + // CHECK: autoclosure_expr implicit type='() -> Bool?' discriminator=1 escaping + @SR_15940Bar var a: Bool? +} + +// CHECK-LABEL: struct_decl{{.*}}SR_15940_B +struct SR_15940_B { + // CHECK: argument_list implicit labels=wrappedValue: + // CHECK-NEXT: argument label=wrappedValue + // CHECK-NEXT: autoclosure_expr implicit type='() -> Bool' location={{.*}}.swift:[[@LINE+2]]:30 range=[{{.+}}] discriminator=0 captures=( ) escaping + // CHECK: autoclosure_expr implicit type='() -> Bool' location={{.*}}.swift:[[@LINE+1]]:30 range=[{{.+}}] discriminator=1 escaping + @SR_15940Bar var b: Bool = false +}