Skip to content

[Sema] SR-15940: Assert crash in TypeCheckStmt.cpp #58956

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 3 commits into from
Jul 8, 2022
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
18 changes: 14 additions & 4 deletions lib/Sema/TypeCheckStorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After this return statement, the function also checks actor isolation and initializer effects. Do we have tests to make sure the cases where contextualize is false still perform actor isolation and effects checking? We might also want to call the parameter something else since it skips more than contextualizing closures.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good question. @hank121314 You can comment out the logic in visitPatternBinding and see if we get any test failures from that related to property wrappers.

if (!contextualize)
return;
TypeChecker::contextualizeInitializer(initContext, initializer);
checkPropertyWrapperActorIsolation(wrappedVar, initializer);
TypeChecker::checkInitializerEffects(initContext, initializer);
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);

Expand Down Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion test/Concurrency/global_actor_inference.swift
Original file line number Diff line number Diff line change
Expand Up @@ -415,12 +415,13 @@ actor WrapperActorBad2<Wrapped: Sendable> {
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}}
Expand Down
28 changes: 28 additions & 0 deletions test/SILGen/property_wrappers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
34 changes: 34 additions & 0 deletions test/Sema/property_wrappers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,37 @@ struct TestInitSubscript {
@Wrapper(wrappedValue: Color.allCases[0])
var color: Color
}

@propertyWrapper
public class SR_15940Bar<Value> {
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=(<opaque_value> ) 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=(<opaque_value> ) escaping
// CHECK: autoclosure_expr implicit type='() -> Bool' location={{.*}}.swift:[[@LINE+1]]:30 range=[{{.+}}] discriminator=1 escaping
@SR_15940Bar var b: Bool = false
}