From 7c154bf76386213cb721a46e2bfa8fd75243a6c2 Mon Sep 17 00:00:00 2001 From: Paul Lietar Date: Thu, 6 Apr 2017 03:13:44 +0200 Subject: [PATCH 1/2] Do not allow capability subtyping when checking constraint subtyping. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The compiler currently allows contravariant constraint for type arguments. When doing so it allows capability subtyping. In other words, it allows the following, where `X` is a type variable, `λ` a capability and `DS` is a type name. ``` λ' ≤ λ ---------------------------------------- fun m[X: DS λ]() ≤ fun m[X: DS λ']() ``` This is however unsound, as shown in the example below. Bar's `alias` method is able to create an `X^` from a `X!`, since `X` is a tag. However, Foo's `alias` method is callable with an iso argument. As a result, this can be used to duplicate an iso reference, as shown in `Main` ```pony trait Foo fun alias[X: Any iso](x: X!) : X^ class Bar is Foo fun alias[X: Any tag](x: X!) : X^ => x class Baz actor Main new create(env: Env) => let foo : Foo = Bar let x : Baz iso = Baz let x' : Baz iso = foo.alias[Baz iso](x) ``` Instead, when checking constraint subtyping, the compiler should not allow capabilities to be subtyped. This is similar to how type arguments are checked to be within the constraint. --- src/libponyc/type/subtype.c | 2 +- test/libponyc/badpony.cc | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/libponyc/type/subtype.c b/src/libponyc/type/subtype.c index a7e56ed5ef..d2159cf538 100644 --- a/src/libponyc/type/subtype.c +++ b/src/libponyc/type/subtype.c @@ -303,7 +303,7 @@ static bool is_reified_fun_sub_fun(ast_t* sub, ast_t* super, ast_t* sub_constraint = ast_childidx(sub_typeparam, 1); ast_t* super_constraint = ast_childidx(super_typeparam, 1); - if(!is_x_sub_x(super_constraint, sub_constraint, CHECK_CAP_SUB, errorf, + if(!is_x_sub_x(super_constraint, sub_constraint, CHECK_CAP_EQ, errorf, opt)) { if(errorf != NULL) diff --git a/test/libponyc/badpony.cc b/test/libponyc/badpony.cc index bcc6119dca..8f7f932980 100644 --- a/test/libponyc/badpony.cc +++ b/test/libponyc/badpony.cc @@ -426,3 +426,16 @@ TEST_F(BadPonyTest, AnnotatedIfClause) TEST_COMPILE(src); } + +TEST_F(BadPonyTest, CapSubtypeInConstrainSubtyping) +{ + // From PR #1816 + const char* src = + "trait T\n" + " fun alias[X: Any iso](x: X!) : X^\n" + "class C is T\n" + " fun alias[X: Any tag](x: X!) : X^ => x\n"; + + TEST_ERRORS_1(src, + "type parameter constraint Any tag is not a supertype of Any iso"); +} From 657141e2df8ef747d105f9c79931610a4eb45ccd Mon Sep 17 00:00:00 2001 From: Paul Lietar Date: Fri, 7 Apr 2017 10:28:44 +0200 Subject: [PATCH 2/2] Fix expected error message in CapSubtypeInConstrainSubtyping test --- test/libponyc/badpony.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/libponyc/badpony.cc b/test/libponyc/badpony.cc index 8f7f932980..a524c24165 100644 --- a/test/libponyc/badpony.cc +++ b/test/libponyc/badpony.cc @@ -432,10 +432,10 @@ TEST_F(BadPonyTest, CapSubtypeInConstrainSubtyping) // From PR #1816 const char* src = "trait T\n" - " fun alias[X: Any iso](x: X!) : X^\n" + " fun alias[X: Any iso](x: X!): X^\n" "class C is T\n" - " fun alias[X: Any tag](x: X!) : X^ => x\n"; + " fun alias[X: Any tag](x: X!): X^ => x\n"; TEST_ERRORS_1(src, - "type parameter constraint Any tag is not a supertype of Any iso"); + "type does not implement its provides list"); }