@@ -71,21 +71,32 @@ object Access {
7171
7272 def (x : Permissions ) & (y : Permissions ): Permissions = x | y
7373 def (x : PermissionChoice ) | (y : PermissionChoice ): PermissionChoice = x | y
74- def (x : Permissions ).is(y : Permissions ) = (x & y ) == y
75- def (x : Permissions ).isOneOf(y : PermissionChoice ) = (x & y ) != 0
74+ def (granted : Permissions ).is(required : Permissions ) = (granted & required ) == required
75+ def (granted : Permissions ).isOneOf(required : PermissionChoice ) = (granted & required ) != 0
7676
7777 val NoPermission : Permission = 0
78- val ReadOnly : Permission = 1
79- val WriteOnly : Permission = 2
80- val ReadWrite : Permissions = ReadOnly & WriteOnly
81- val ReadOrWrite : PermissionChoice = ReadOnly | WriteOnly
78+ val Read : Permission = 1
79+ val Write : Permission = 2
80+ val ReadWrite : Permissions = Read | Write
81+ val ReadOrWrite : PermissionChoice = Read | Write
8282}
8383```
8484The ` Access ` object defines three opaque types:
8585
8686 - ` Permission ` , representing a single permission,
87- - ` Permissions ` , representing a conjunction (logical "and") of permissions,
88- - ` PermissionChoice ` , representing a disjunction (logical "or") of permissions.
87+ - ` Permissions ` , representing a set of permissions with the meaning "all of these permissions granted",
88+ - ` PermissionChoice ` , representing a set of permissions with the meaning "at least one of these permissions granted".
89+
90+ Outside the ` Access ` object, values of type ` Permissions ` may be combined using the ` & ` operator,
91+ where ` x & y ` means "all permissions in ` x ` * and* in ` y ` granted".
92+ Values of type ` PermissionChoice ` may be combined using the ` | ` operator,
93+ where ` x | y ` means "a permission in ` x ` * or* in ` y ` granted".
94+
95+ Note that inside the ` Access ` object, the ` & ` and ` | ` operators always resolve to the corresponding methods of ` Int ` ,
96+ because members always take precedence over extension methods.
97+ Because of that, the ` | ` extension method in ` Access ` does not cause infinite recursion.
98+ Also, the definition of ` ReadWrite ` must use ` | ` ,
99+ even though an equivalent definition outside ` Access ` would use ` & ` .
89100
90101All three opaque types have the same underlying representation type ` Int ` . The
91102` Permission ` type has an upper bound ` Permissions & PermissionChoice ` . This makes
@@ -97,13 +108,21 @@ object User {
97108
98109 case class Item (rights : Permissions )
99110
100- val x = Item (ReadOnly ) // OK, since Permission <: Permissions
111+ val roItem = Item (Read ) // OK, since Permission <: Permissions
112+ val rwItem = Item (ReadWrite )
113+ val noItem = Item (NoPermission )
114+
115+ assert( roItem.rights.is(ReadWrite ) == false )
116+ assert( roItem.rights.isOneOf(ReadOrWrite ) == true )
117+
118+ assert( rwItem.rights.is(ReadWrite ) == true )
119+ assert( rwItem.rights.isOneOf(ReadOrWrite ) == true )
101120
102- assert( x .rights.is(ReadWrite ) == false )
103- assert( x .rights.isOneOf(ReadOrWrite ) == true )
121+ assert( noItem .rights.is(ReadWrite ) == false )
122+ assert( noItem .rights.isOneOf(ReadOrWrite ) == false )
104123}
105124```
106- On the other hand, the call ` x .rights.isOneOf(ReadWrite)` would give a type error
125+ On the other hand, the call ` roItem .rights.isOneOf(ReadWrite)` would give a type error
107126since ` Permissions ` and ` PermissionChoice ` are different, unrelated types outside ` Access ` .
108127
109128[ More details] ( opaques-details.md )
0 commit comments