Skip to content

Commit

Permalink
Ban traits from implementing sealed interfaces
Browse files Browse the repository at this point in the history
Summary: After speaking with dlreeves, we're gonna punt on allowing traits to implement sealed interfaces for now. HHVM should support it, because it models traits differently.

Reviewed By: jamesjwu

Differential Revision: D7863243

fbshipit-source-id: 671dc88120b10d2a75cdff3a632250caa045361f
  • Loading branch information
kmeht authored and hhvm-bot committed May 17, 2018
1 parent 2a5a79c commit 1ae57e6
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 11 deletions.
9 changes: 9 additions & 0 deletions hphp/hack/src/errors/errors.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2547,6 +2547,15 @@ let extend_sealed child_pos parent_pos parent_name parent_kind verb =
parent_pos, "Declaration is here"
]

let trait_implement_sealed child_pos parent_pos parent_name =
let name = (strip_ns parent_name) in
add_list (Typing.err_code Typing.ExtendSealed) [
child_pos, (
"A trait cannot implement sealed interface "^name^
". Use `require implements` instead");
parent_pos, "Declaration is here"
]

let sealed_final pos name =
let name = (strip_ns name) in
add (Typing.err_code Typing.SealedFinal) pos ("Sealed class "^name^" cannot be marked final")
Expand Down
1 change: 1 addition & 0 deletions hphp/hack/src/errors/errors_sig.ml
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ module type S = sig
val sketchy_null_check_primitive : Pos.t -> string option -> [< `Coalesce | `Eq | `Neq ] -> unit
val extend_final : Pos.t -> Pos.t -> string -> unit
val extend_sealed : Pos.t -> Pos.t -> string -> string -> string -> unit
val trait_implement_sealed : Pos.t -> Pos.t -> string -> unit
val sealed_final : Pos.t -> string -> unit
val read_before_write : Pos.t * string -> unit
val interface_final : Pos.t -> unit
Expand Down
31 changes: 20 additions & 11 deletions hphp/hack/src/typing/typing.ml
Original file line number Diff line number Diff line change
Expand Up @@ -6138,19 +6138,28 @@ and check_parent class_def class_type parent_type =

and check_parent_sealed child_type parent_type =
match parent_type.dc_sealed_whitelist with
| None -> ()
| Some whitelist ->
if not (SSet.mem child_type.tc_name whitelist)
then begin
let error = Errors.extend_sealed
child_type.tc_pos parent_type.dc_pos parent_type.dc_name in
match parent_type.dc_kind, child_type.tc_kind with
| Ast.Cabstract, _
| Ast.Cnormal, _ -> error "class" "extend"
| Ast.Cinterface, Ast.Cinterface -> error "interface" "extend"
| Ast.Cinterface, _ -> error "interface" "implement"
| _ -> ()
begin match child_type.tc_kind with
| Ast.Cabstract
| Ast.Cnormal
| Ast.Cinterface ->
if not (SSet.mem child_type.tc_name whitelist)
then begin
let error = Errors.extend_sealed
child_type.tc_pos parent_type.dc_pos parent_type.dc_name in
match parent_type.dc_kind, child_type.tc_kind with
| Ast.Cabstract, _
| Ast.Cnormal, _ -> error "class" "extend"
| Ast.Cinterface, Ast.Cinterface -> error "interface" "extend"
| Ast.Cinterface, _ -> error "interface" "implement"
| _ -> ()
end
| Ast.Ctrait ->
Errors.trait_implement_sealed
child_type.tc_pos parent_type.dc_pos parent_type.dc_name
| Ast.Cenum -> ()
end
| None -> ()

and check_parents_sealed env child_def child_type =
List.iter (child_def.c_extends @ child_def.c_implements) begin function
Expand Down
14 changes: 14 additions & 0 deletions hphp/hack/test/typecheck/sealed/trait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?hh // strict
// Copyright 2004-present Facebook. All Rights Reserved.

<<__Sealed(B::class)>>
interface A {}

trait T implements A {}

final class B {
use T;
}
final class C {
use T;
}
4 changes: 4 additions & 0 deletions hphp/hack/test/typecheck/sealed/trait.php.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
File "trait.php", line 7, characters 7-7:
A trait cannot implement sealed interface A. Use `require implements` instead (Typing[4238])
File "trait.php", line 5, characters 11-11:
Declaration is here
16 changes: 16 additions & 0 deletions hphp/hack/test/typecheck/sealed/trait2.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?hh // strict
// Copyright 2004-present Facebook. All Rights Reserved.

<<__Sealed(B::class)>>
interface A {}

trait T {
require implements A;
}

final class B implements A {
use T;
}
final class C implements A {
use T;
}
4 changes: 4 additions & 0 deletions hphp/hack/test/typecheck/sealed/trait2.php.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
File "trait2.php", line 14, characters 13-13:
You cannot implement sealed interface A (Typing[4238])
File "trait2.php", line 5, characters 11-11:
Declaration is here

0 comments on commit 1ae57e6

Please sign in to comment.