Re: [swift-evolution] Replace Fileprivate with Hidden + Import Hidden

2016-10-17 Thread Rien via swift-evolution

> On 17 Oct 2016, at 19:47, Jonathan Hull  wrote:
> 
> First, let me say, thank you for your feedback.  Just because I am arguing 
> against others' points does not mean that I don’t appreciate those points.
> 
>> On Oct 17, 2016, at 12:37 AM, Rien  wrote:
>> 
>> -1.
>> 
>> If an API designer wants to allow access to a “hidden’ member, he should be 
>> in control of that access.
> This seems to be one of the biggest internal arguments within the swift 
> community.  Who is in control of the use of frameworks?  The author or the 
> user?
> 
> I am trying to plot a middle path here which gives both a fair amount of 
> control.  I think that is part of why this proposal has been so unpopular, it 
> is a compromise between both extremes, and everyone hates a compromise.  
> Someone else just had the opinion that we should make everything public and 
> note in the documentation what should and should not be used.
> 
> And as I said before, API like UIGestureRecognizer's is currently impossible 
> to create solely in Swift.  There is a hole in Swift’s access system which we 
> will have to fix sometime during this phase.  I think a lot of people think 
> that submodules will magically solve all of our problems, (I want them too) 
> but the core issue here will remain (just with a little less frequency), and 
> we will be forced to go back to the drawing board in 6mo to a year. I am 
> hoping to prevent that.
> 
> 
>> The proposed chance simply opens up access completely and leads to API 
>> vulnerability.
> No, it only opens up access to API explicitly marked with ‘hidden’.  That is, 
> the framework author is explicitly saying: This API should only be used for 
> subclassing/extension (but they also realize it can be accessed).  The user 
> of that API has to explicitly acknowledge that intention by writing ‘import 
> hidden’.  API marked private or internal will not be opened beyond it’s scope 
> in any case.
> 
> As I said in another email, a potential further compromise would be to make 
> ‘hidden’ a separate axis, and allow things like ‘internal hidden’, where 
> access can only be opened up within the module.  Would that solve your issues 
> with the proposal?
> 
> I started out closer to your position, wanting more targeted permissions, but 
> I ultimately realized that this would be good enough for real world use.
> 
> 
>> (I am in favour of a “friend” solution, in which the API designer explicitly 
>> allows access to identified members of the API users.)
> But what happens when you need to be a friend and you don’t own the API?  I 
> get the thinking behind friend classes, but it is problematic in practice.

In that case, you don’t get to be a “friend”. Tough cookies. Life isn’t “fair”.
In an exact science like SW development, control must be hierarchical or 
singular. Any deviation, however small, will come back to bite.
Too many API developers have spend too much time to look for “errors” that 
inexperienced or unknowing API users caused because the API was too “open”. The 
API developer may think that “it is clearly documented”… but then again, look 
at stackoverflow…. people don’t read them, and the API developer will be held 
responsible for the error of others… if only in reputation...


>  As another poster mentioned, we basically have friend classes already, just 
> based on location of code.  The core issue I am trying to solve here cannot 
> be solved with more variation of the same, we need a counterpoint to it, and 
> then the two approaches can be mixed to get the desired balance/tradeoffs.

Balances and tradeoffs only get you deeper into the quicksand. Better not to 
tread there. Sometimes you have to say NO.

Rien.

PS: I do understand the lure, buts it’s (IMO) always better to resist.



> 
> Thanks,
> Jon
> 
> 
>> Rien.
>> 
>> 
>>> On 16 Oct 2016, at 22:34, Jonathan Hull via swift-evolution 
>>>  wrote:
>>> 
>>> I keep wanting a “protected” access level, but I must also admit that there 
>>> was something really elegant about Swift 2’s access scheme (and I think 
>>> most of us feel like the word ‘fileprivate’ feels out of place).  I was 
>>> thinking about how to mesh those two ideas, and I think I may have come up 
>>> with a solution.
>>> 
>>> I propose we replace ‘fileprivate’ with a new ‘hidden’ access level.  
>>> Hidden would work exactly the same way as fileprivate does now, but adds 
>>> the connotation that what is hidden can also be unhidden.  By adding 
>>> ‘import hidden TypeName’ to another file, that file also gains access to 
>>> all of the hidden items of that type (kind of like if it was in the same 
>>> file).
>>> 
>>> #FileA  
>>> import Foundation
>>> 
>>> Struct A {
>>> private var x:Int
>>> hidden var y:Int  //This is just like fileprivate, but can also 
>>> be shared with other files
>>> }
>>> 
>>> extension A {
>>> //y can be accessed here 

Re: [swift-evolution] Replace Fileprivate with Hidden + Import Hidden

2016-10-17 Thread Charles Srstka via swift-evolution
> On Oct 17, 2016, at 12:47 PM, Jonathan Hull via swift-evolution 
>  wrote:
> 
>> On Oct 17, 2016, at 12:37 AM, Rien > > wrote:
>> 
>> -1.
>> 
>> If an API designer wants to allow access to a “hidden’ member, he should be 
>> in control of that access.
> This seems to be one of the biggest internal arguments within the swift 
> community.  Who is in control of the use of frameworks?  The author or the 
> user?

To me, it seems that if the author has control already. If s/he needs to hide 
symbols from outside the framework, the “internal” keyword already exists for 
that.

Charles

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Replace Fileprivate with Hidden + Import Hidden

2016-10-17 Thread Jonathan Hull via swift-evolution
First, let me say, thank you for your feedback.  Just because I am arguing 
against others' points does not mean that I don’t appreciate those points.

> On Oct 17, 2016, at 12:37 AM, Rien  wrote:
> 
> -1.
> 
> If an API designer wants to allow access to a “hidden’ member, he should be 
> in control of that access.
This seems to be one of the biggest internal arguments within the swift 
community.  Who is in control of the use of frameworks?  The author or the user?

I am trying to plot a middle path here which gives both a fair amount of 
control.  I think that is part of why this proposal has been so unpopular, it 
is a compromise between both extremes, and everyone hates a compromise.  
Someone else just had the opinion that we should make everything public and 
note in the documentation what should and should not be used.

And as I said before, API like UIGestureRecognizer's is currently impossible to 
create solely in Swift.  There is a hole in Swift’s access system which we will 
have to fix sometime during this phase.  I think a lot of people think that 
submodules will magically solve all of our problems, (I want them too) but the 
core issue here will remain (just with a little less frequency), and we will be 
forced to go back to the drawing board in 6mo to a year. I am hoping to prevent 
that.


> The proposed chance simply opens up access completely and leads to API 
> vulnerability.
No, it only opens up access to API explicitly marked with ‘hidden’.  That is, 
the framework author is explicitly saying: This API should only be used for 
subclassing/extension (but they also realize it can be accessed).  The user of 
that API has to explicitly acknowledge that intention by writing ‘import 
hidden’.  API marked private or internal will not be opened beyond it’s scope 
in any case.

As I said in another email, a potential further compromise would be to make 
‘hidden’ a separate axis, and allow things like ‘internal hidden’, where access 
can only be opened up within the module.  Would that solve your issues with the 
proposal?

I started out closer to your position, wanting more targeted permissions, but I 
ultimately realized that this would be good enough for real world use.


> (I am in favour of a “friend” solution, in which the API designer explicitly 
> allows access to identified members of the API users.)
But what happens when you need to be a friend and you don’t own the API?  I get 
the thinking behind friend classes, but it is problematic in practice.  As 
another poster mentioned, we basically have friend classes already, just based 
on location of code.  The core issue I am trying to solve here cannot be solved 
with more variation of the same, we need a counterpoint to it, and then the two 
approaches can be mixed to get the desired balance/tradeoffs.

Thanks,
Jon


> Rien.
> 
> 
>> On 16 Oct 2016, at 22:34, Jonathan Hull via swift-evolution 
>>  wrote:
>> 
>> I keep wanting a “protected” access level, but I must also admit that there 
>> was something really elegant about Swift 2’s access scheme (and I think most 
>> of us feel like the word ‘fileprivate’ feels out of place).  I was thinking 
>> about how to mesh those two ideas, and I think I may have come up with a 
>> solution.
>> 
>> I propose we replace ‘fileprivate’ with a new ‘hidden’ access level.  Hidden 
>> would work exactly the same way as fileprivate does now, but adds the 
>> connotation that what is hidden can also be unhidden.  By adding ‘import 
>> hidden TypeName’ to another file, that file also gains access to all of the 
>> hidden items of that type (kind of like if it was in the same file).
>> 
>> #FileA   
>>  import Foundation
>> 
>>  Struct A {
>>  private var x:Int
>>  hidden var y:Int  //This is just like fileprivate, but can also 
>> be shared with other files
>>  }
>> 
>>  extension A {
>>  //y can be accessed here because they are in the same file
>>  }
>> 
>>  
>> #FileB
>>  import Foundation
>>  import hidden A  //This allows the entire file to see A’s hidden 
>> variables
>> 
>>  extension A {
>>  //y can be accessed here because of the ‘import hidden’ 
>> declaration
>>  }
>> 
>> 
>> #FileC
>>  import Foundation
>> 
>>  extension A {
>>  //y can NOT be seen or accessed here because it is hidden
>>  }
>> 
>> 
>> I think this is a fairly elegant solution to our protected dilemma, which 
>> also feels in sync with Swift 2’s file-based scheme.  The key features:
>>  • Extensions no longer need to be piled in the same file if it is 
>> getting too long
>>  • Subclasses can be in their own file, but still have access to the 
>> necessary parts of their superclass
>>  • It communicates the author’s intent that the items are not meant to 
>> be visible to its users, but that it is expected to be used for 
>> extension/subclassing
>>  

Re: [swift-evolution] Replace Fileprivate with Hidden + Import Hidden

2016-10-17 Thread Jonathan Hull via swift-evolution

> On Oct 16, 2016, at 8:19 PM, David Waite  wrote:
> 
> fileprivate (and internal, in a sense) are really in the “friend” camp. 
> Rather than declaring particular types are friends, these require code 
> locality - in the same file in the case of fileprivate, in the same module in 
> the case of internal.
> 
> This does mean that the more stringent you wish to control internals, the 
> more code gets stuffed into a file or module - but could actually be 
> considered a benefit, as depending on internals naturally makes code highly 
> coupled.
> 
> That reason is why I’m not exactly fan of expanding ‘friend’-style 
> permissions further - this could completely disguise the level of effort 
> needed to change ‘hidden’ code in one class.

I think that is a valid point.  There is a tradeoff.  Being able to spread an 
API over more files means that there are more files to change when you need to 
make a change (and there is always a chance that you forget a file).  My 
argument would be that this allows the author to choose the tradeoff for 
themselves in each situation, whereas right now the choice is being made for 
them.  


> I’m against allowing hidden cross-module. If external code is explicitly 
> allowed to depend on ‘hidden’ API, then its still API which would be expected 
> to be stably maintained. Why not just make it public with appropriate caveats?

Yes, I think it would be expected to be stably maintained… but any sort of 
protected-style access is going to be the same, as you need a stable API to 
build subclasses/extensions on.  There are several reasons for encapsulation 
beyond making it easier to update API.  My main reason for wanting this is to 
be able to hide the levers which could get things into an inconsistent state 
internally, while still allowing for the few cases where that access is needed 
for efficient implementation.  Safe by default, with override.

I do suppose, at the expense of a little more complexity, we could make 
‘hidden' a separate axis of control.  That is, you could have ‘public hidden’, 
‘internal hidden’, and ‘private hidden’, with private hidden being exactly the 
same as today’s fileprivate (C# has protected internal, etc… so it isn’t 
unprecedented). That way, an author could choose the tradeoff between 
maintenance burden and extensibility.

Thanks,
Jon


> -DW
> 
>> On Oct 16, 2016, at 2:34 PM, Jonathan Hull via swift-evolution 
>>  wrote:
>> 
>> I keep wanting a “protected” access level, but I must also admit that there 
>> was something really elegant about Swift 2’s access scheme (and I think most 
>> of us feel like the word ‘fileprivate’ feels out of place).  I was thinking 
>> about how to mesh those two ideas, and I think I may have come up with a 
>> solution.
>> 
>> I propose we replace ‘fileprivate’ with a new ‘hidden’ access level.  Hidden 
>> would work exactly the same way as fileprivate does now, but adds the 
>> connotation that what is hidden can also be unhidden.  By adding ‘import 
>> hidden TypeName’ to another file, that file also gains access to all of the 
>> hidden items of that type (kind of like if it was in the same file).
>> 
>> #FileA   
>>  import Foundation
>> 
>>  Struct A {
>>  private var x:Int
>>  hidden var y:Int  //This is just like fileprivate, but can also 
>> be shared with other files
>>  }
>> 
>>  extension A {
>>  //y can be accessed here because they are in the same file
>>  }
>> 
>>  
>> #FileB
>>  import Foundation
>>  import hidden A  //This allows the entire file to see A’s hidden 
>> variables
>> 
>>  extension A {
>>  //y can be accessed here because of the ‘import hidden’ 
>> declaration
>>  }
>> 
>> 
>> #FileC
>>  import Foundation
>> 
>>  extension A {
>>  //y can NOT be seen or accessed here because it is hidden
>>  }
>> 
>> 
>> I think this is a fairly elegant solution to our protected dilemma, which 
>> also feels in sync with Swift 2’s file-based scheme.  The key features:
>>  • Extensions no longer need to be piled in the same file if it is 
>> getting too long
>>  • Subclasses can be in their own file, but still have access to the 
>> necessary parts of their superclass
>>  • It communicates the author’s intent that the items are not meant to 
>> be visible to its users, but that it is expected to be used for 
>> extension/subclassing
>>  • It requires an explicit statement ‘import hidden’ to access the 
>> hidden variables. Safe by default, with override.
>>  • It is not bound by module boundaries  (i.e. you could use it for 
>> subclassing classes from an imported module)
>>  • Roughly the same length as ‘private’ and ‘public’ so various 
>> declarations packed together are much easier to read (fileprivate breaks 
>> reading rhythm)  
>> 
>> Worth a formal proposal?
>> 
>> Thanks,
>> Jon
>> 
>> 
>> 
>> 

Re: [swift-evolution] Replace Fileprivate with Hidden + Import Hidden

2016-10-17 Thread Jay Abbott via swift-evolution
Oops, correction:

@unshelter(self); or
@unshelter(aWotsit)
// Inside a Wotsit or a Wotsit subclass this would work, y becomes
available.

Should be:

@unshelter(aThing)
// Inside a Wotsit or a Wotsit subclass this would work, y becomes
available.


On Mon, 17 Oct 2016 at 13:38 Jay Abbott  wrote:

> I'm not sure of my own opinions on this one as I can see good points on
> both sides. There also seem to be a variety of different discussions with
> similar concerns. So at the risk of confusing things I'm suggesting another
> idea, with the hope/intention of promoting some deeper thought and helping
> us figure out what is needed/wanted.
>
> I will use the word 'sheltered' here, apologies if that is confusing, it
> just means protected/hidden/whatever but without any existing notions of
> what those might mean. It might not be the best word either, I just picked
> it from a list of synonyms for 'protected'.
>
> Class authors can (now) if they want provide their own way to explicitly
> access some private members through a public interface:
>
> public class Thing {
> private var x: Int
> public var shelteredX: Int {
> get { return x }
> set { x = newValue }
> }
> }
>
> But this isn't ideal as it just causes excess boilerplate code and doesn't
> hide it from anyone or suggest they shouldn't normally use it (other than
> the explicit naming). However, perhaps the compiler could help with this
> type of pattern as follows:
>
> public class Thing {
> sheltered var x: Int {
> get { return x } // not sure how this would work - x is also the
> backing ivar so you don't have to declare it twice as _x and x.
> set { x = newValue }
> }
>// accessors provided - internal access to x is direct, sheltered
> access is via accessors
>
> sheltered var y: Int
> // No accessors provided, sheltered access to y is direct
> }
>
> For members with 'sheltered' access:
> * Don't by default allow access to the sheltered members or accessors -
> they are equivalent to private (or maybe fileprivate)
> * Provide a way to expose them in a given scope
> * I think it can be applied to methods too
>
> For example:
> var aThing = Thing()
> aThing.x = 7 // NOT ALLOWED: x is sheltered.
> @unshelter(aThing) // aThing is unsheltered in the remainder of its scope.
> aThing.x = 7 // NOW ALLOWED
>
> One good thing is that this is very explicit where you use it.
>
> Sheltered groups might also be a thing:
>
> Definition:
> sheltered var x: Int
> sheltered var y: Int
> Usage:
> @unshelter(aThing)
> // x is available, y isn't
> @unshelter(aThing)
> // x and y are available
>
> "Subclasses" and "Wotsits" are author-defined identifiers, not keywords.
> This is a bit like friends and protected, but using an honesty system,
> where friends can easily declare themselves as friends by unsheltering all
> the Wotsits group, and subclasses (not enforced) would unshelter the
> Subclasses group. That is, the author's intentions are clear, but other
> classes can abuse it to get access. If the author doesn't want to allow
> abuse, they can do this:
>
> Definition:
> sheltered var x: Int
> sheltered var y: Int
>
> Usage:
> @unshelter(self); or
> @unshelter(anOtherThing)
> // Works inside a Thing subclass, x becomes available. The scope in which
> @unshelter is used must match the type of the shelter group.
>
> @unshelter(self); or
> @unshelter(aWotsit)
> // Inside a Wotsit or a Wotsit subclass this would work, y becomes
> available.
>
> I'm just spitballing here, this isn't fully thought through. Perhaps a
> where clause would be better instead of a type annotation for the shelter
> groups, so you could list multiple types that are allowed to unshelter that
> group. You might be able to abuse it still by putting something in an
> extension of an allowed class, so that may need some further thought.
>
> This is of course more complex that other proposed solutions, I'm just
> trying to combine all the desires people seem to have and see what people
> think - do we want more control and are happy with a bit more complexity?
> or should it be simple and less control? Personally I actually don't have
> much of an opinion on it because I haven't used Swift enough yet to come a
> cropper of such things.
>
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Replace Fileprivate with Hidden + Import Hidden

2016-10-17 Thread Jay Abbott via swift-evolution
I'm not sure of my own opinions on this one as I can see good points on
both sides. There also seem to be a variety of different discussions with
similar concerns. So at the risk of confusing things I'm suggesting another
idea, with the hope/intention of promoting some deeper thought and helping
us figure out what is needed/wanted.

I will use the word 'sheltered' here, apologies if that is confusing, it
just means protected/hidden/whatever but without any existing notions of
what those might mean. It might not be the best word either, I just picked
it from a list of synonyms for 'protected'.

Class authors can (now) if they want provide their own way to explicitly
access some private members through a public interface:

public class Thing {
private var x: Int
public var shelteredX: Int {
get { return x }
set { x = newValue }
}
}

But this isn't ideal as it just causes excess boilerplate code and doesn't
hide it from anyone or suggest they shouldn't normally use it (other than
the explicit naming). However, perhaps the compiler could help with this
type of pattern as follows:

public class Thing {
sheltered var x: Int {
get { return x } // not sure how this would work - x is also the
backing ivar so you don't have to declare it twice as _x and x.
set { x = newValue }
}
   // accessors provided - internal access to x is direct, sheltered access
is via accessors

sheltered var y: Int
// No accessors provided, sheltered access to y is direct
}

For members with 'sheltered' access:
* Don't by default allow access to the sheltered members or accessors -
they are equivalent to private (or maybe fileprivate)
* Provide a way to expose them in a given scope
* I think it can be applied to methods too

For example:
var aThing = Thing()
aThing.x = 7 // NOT ALLOWED: x is sheltered.
@unshelter(aThing) // aThing is unsheltered in the remainder of its scope.
aThing.x = 7 // NOW ALLOWED

One good thing is that this is very explicit where you use it.

Sheltered groups might also be a thing:

Definition:
sheltered var x: Int
sheltered var y: Int
Usage:
@unshelter(aThing)
// x is available, y isn't
@unshelter(aThing)
// x and y are available

"Subclasses" and "Wotsits" are author-defined identifiers, not keywords.
This is a bit like friends and protected, but using an honesty system,
where friends can easily declare themselves as friends by unsheltering all
the Wotsits group, and subclasses (not enforced) would unshelter the
Subclasses group. That is, the author's intentions are clear, but other
classes can abuse it to get access. If the author doesn't want to allow
abuse, they can do this:

Definition:
sheltered var x: Int
sheltered var y: Int

Usage:
@unshelter(self); or
@unshelter(anOtherThing)
// Works inside a Thing subclass, x becomes available. The scope in which
@unshelter is used must match the type of the shelter group.

@unshelter(self); or
@unshelter(aWotsit)
// Inside a Wotsit or a Wotsit subclass this would work, y becomes
available.

I'm just spitballing here, this isn't fully thought through. Perhaps a
where clause would be better instead of a type annotation for the shelter
groups, so you could list multiple types that are allowed to unshelter that
group. You might be able to abuse it still by putting something in an
extension of an allowed class, so that may need some further thought.

This is of course more complex that other proposed solutions, I'm just
trying to combine all the desires people seem to have and see what people
think - do we want more control and are happy with a bit more complexity?
or should it be simple and less control? Personally I actually don't have
much of an opinion on it because I haven't used Swift enough yet to come a
cropper of such things.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Replace Fileprivate with Hidden + Import Hidden

2016-10-17 Thread Rien via swift-evolution
-1.

If an API designer wants to allow access to a “hidden’ member, he should be in 
control of that access.
The proposed chance simply opens up access completely and leads to API 
vulnerability.

(I am in favour of a “friend” solution, in which the API designer explicitly 
allows access to identified members of the API users.)

Rien.


> On 16 Oct 2016, at 22:34, Jonathan Hull via swift-evolution 
>  wrote:
> 
> I keep wanting a “protected” access level, but I must also admit that there 
> was something really elegant about Swift 2’s access scheme (and I think most 
> of us feel like the word ‘fileprivate’ feels out of place).  I was thinking 
> about how to mesh those two ideas, and I think I may have come up with a 
> solution.
> 
> I propose we replace ‘fileprivate’ with a new ‘hidden’ access level.  Hidden 
> would work exactly the same way as fileprivate does now, but adds the 
> connotation that what is hidden can also be unhidden.  By adding ‘import 
> hidden TypeName’ to another file, that file also gains access to all of the 
> hidden items of that type (kind of like if it was in the same file).
> 
> #FileA
>   import Foundation
> 
>   Struct A {
>   private var x:Int
>   hidden var y:Int  //This is just like fileprivate, but can also 
> be shared with other files
>   }
> 
>   extension A {
>   //y can be accessed here because they are in the same file
>   }
> 
>   
> #FileB
>   import Foundation
>   import hidden A  //This allows the entire file to see A’s hidden 
> variables
> 
>   extension A {
>   //y can be accessed here because of the ‘import hidden’ 
> declaration
>   }
> 
> 
> #FileC
>   import Foundation
> 
>   extension A {
>   //y can NOT be seen or accessed here because it is hidden
>   }
> 
> 
> I think this is a fairly elegant solution to our protected dilemma, which 
> also feels in sync with Swift 2’s file-based scheme.  The key features:
>   • Extensions no longer need to be piled in the same file if it is 
> getting too long
>   • Subclasses can be in their own file, but still have access to the 
> necessary parts of their superclass
>   • It communicates the author’s intent that the items are not meant to 
> be visible to its users, but that it is expected to be used for 
> extension/subclassing
>   • It requires an explicit statement ‘import hidden’ to access the 
> hidden variables. Safe by default, with override.
>   • It is not bound by module boundaries  (i.e. you could use it for 
> subclassing classes from an imported module)
>   • Roughly the same length as ‘private’ and ‘public’ so various 
> declarations packed together are much easier to read (fileprivate breaks 
> reading rhythm)  
> 
> Worth a formal proposal?
> 
> Thanks,
> Jon
> 
> 
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Replace Fileprivate with Hidden + Import Hidden

2016-10-16 Thread Jonathan Hull via swift-evolution

> On Oct 16, 2016, at 7:23 PM, Xiaodi Wu  wrote:
> 
> On that last point, I would push back against calling it access inflation. If 
> a member needs to be visible outside the file for whatever reason, it needs 
> to have at least internal visibility. This is not at all "inflated" (implying 
> that it's a workaround) but an explicitly contemplated part of Swift's access 
> scheme.
But what happens when someone needs to make an extension outside of the module? 
 For example, subclassing UIGestureRecognizer.  Should things like setState: 
(which triggers a bunch of side effects and should never be called externally) 
be made public?  The only two options in pure Swift 3 (it only gains it’s 
protected-style import from ObjC) are to make them public or to disallow 
subclassing outside the module (you have to call setState: as part of 
implementing a custom gesture recognizer).


> What you're arguing is that we should be able to expressly enumerate the 
> specific files in which a member is accessible. This is a more granular 
> system, but increased granularity is not in and of itself sufficient 
> justification. After all, if more granularity is better--and this is an 
> argumentum ad absurdum--why not demand that we be able to expressly enumerate 
> the specific types that can access that member? why not the specific methods 
> of those types? why not the specific scope? why not the specific line?
Actually, I am arguing almost the opposite.  I had originally wanted a more 
granular system like 'protected’ from most languages.  This proposal comes from 
a realization that file granularity is most likely good enough for real world 
use cases.

What I am arguing is important:
1) The author’s ability to show which items should generally not be 
accessible/used, but are still provided/required for extension/subclassing 
purposes.
2) Requiring users of these items to acknowledge the author’s intent (by 
requiring ‘import hidden’) before using them
3) Terminology which has the correct connotation for this new behavior


> It's all about what use cases are enabled or not at different points along 
> this spectrum of granularity. So the question is, does your proposed scheme 
> enable additional use cases that `internal` does not?
It allows use of ‘hidden’ variables/functions from other modules.  It also 
allows the author to show their intention that the variable/function is meant 
to be accessed elsewhere if needed for extension (vs. internal which is the 
default)… and it requires the user to acknowledge that intention.


> I'm not convinced that having access to a member at a use site when the 
> declaration itself is totally under your own control, in the same module, is 
> "brittle" is any meaningful sense.
What I mean by brittle is how much a change in one spot will ripple throughout 
your code by requiring other changes.  It becomes a much larger issue when 
multiple people are working on a code base.


Thanks,
Jon

> On Mon, Oct 17, 2016 at 09:51 Jonathan Hull via swift-evolution 
> > wrote:
> To put it more forcefully, I believe that ‘fileprivate’ currently suffers 
> from the same problem that singletons do.  That is, the main reason to make 
> something ‘fileprivate’ instead of ‘private’ is to allow some sort of 
> extension.  It is highly unlikely that the point you were required to expose 
> for that extension will not also be needed by other extensions.  Both 
> ‘internal’ and submodules would extend the boundaries of the problem from the 
> file boundary to the module/submodule boundary… but the underlying problem 
> still persists.
> 
> If it is the module designer’s intent to limit extension, then fine, but it 
> also often forces a design to be much more brittle and fragile than it needs 
> to be.  One of two things happens: extension becomes impossible or there is 
> access inflation, giving inappropriate levels of access (usually combined 
> with a note in the documentation saying not to use it).
> 
> Thanks,
> Jon
> 
> 
> 
>> On Oct 16, 2016, at 3:28 PM, T.J. Usiyan > > wrote:
>> 
> 
>> I don't like this at all and it comes down to  "what is hidden can also be 
>> unhidden". This, to me, feels like it would create more confusion than it 
>> would address. Why not just use `internal` for `hidden` items?  If we're ok 
>> with modifying import statements, why not simply have a command that imports 
>> `fileprivate` stuff? (not advocating for this).
>> 
>> I think that submodules would have really helped with this issue and it is 
>> unfortunate that we couldn't get them in for swift 3. 
>> 
>> On Sun, Oct 16, 2016 at 4:34 PM, Jonathan Hull via swift-evolution 
>> > wrote:
>> I keep wanting a “protected” access level, but I must also admit that there 
>> was something really elegant about Swift 2’s 

Re: [swift-evolution] Replace Fileprivate with Hidden + Import Hidden

2016-10-16 Thread Jonathan Hull via swift-evolution
To put it more forcefully, I believe that ‘fileprivate’ currently suffers from 
the same problem that singletons do.  That is, the main reason to make 
something ‘fileprivate’ instead of ‘private’ is to allow some sort of 
extension.  It is highly unlikely that the point you were required to expose 
for that extension will not also be needed by other extensions.  Both 
‘internal’ and submodules would extend the boundaries of the problem from the 
file boundary to the module/submodule boundary… but the underlying problem 
still persists.

If it is the module designer’s intent to limit extension, then fine, but it 
also often forces a design to be much more brittle and fragile than it needs to 
be.  One of two things happens: extension becomes impossible or there is access 
inflation, giving inappropriate levels of access (usually combined with a note 
in the documentation saying not to use it).

Thanks,
Jon


> On Oct 16, 2016, at 3:28 PM, T.J. Usiyan  wrote:
> 
> I don't like this at all and it comes down to  "what is hidden can also be 
> unhidden". This, to me, feels like it would create more confusion than it 
> would address. Why not just use `internal` for `hidden` items?  If we're ok 
> with modifying import statements, why not simply have a command that imports 
> `fileprivate` stuff? (not advocating for this).
> 
> I think that submodules would have really helped with this issue and it is 
> unfortunate that we couldn't get them in for swift 3. 
> 
> On Sun, Oct 16, 2016 at 4:34 PM, Jonathan Hull via swift-evolution 
> > wrote:
> I keep wanting a “protected” access level, but I must also admit that there 
> was something really elegant about Swift 2’s access scheme (and I think most 
> of us feel like the word ‘fileprivate’ feels out of place).  I was thinking 
> about how to mesh those two ideas, and I think I may have come up with a 
> solution.
> 
> I propose we replace ‘fileprivate’ with a new ‘hidden’ access level.  Hidden 
> would work exactly the same way as fileprivate does now, but adds the 
> connotation that what is hidden can also be unhidden.  By adding ‘import 
> hidden TypeName’ to another file, that file also gains access to all of the 
> hidden items of that type (kind of like if it was in the same file).
> 
> #FileA
> import Foundation
> 
> Struct A {
> private var x:Int
> hidden var y:Int  //This is just like fileprivate, but can 
> also be shared with other files
> }
> 
> extension A {
> //y can be accessed here because they are in the same file
> }
> 
> 
> #FileB
> import Foundation
> import hidden A  //This allows the entire file to see A’s hidden 
> variables
> 
> extension A {
> //y can be accessed here because of the ‘import hidden’ 
> declaration
> }
> 
> 
> #FileC
> import Foundation
> 
> extension A {
> //y can NOT be seen or accessed here because it is hidden
> }
> 
> 
> I think this is a fairly elegant solution to our protected dilemma, which 
> also feels in sync with Swift 2’s file-based scheme.  The key features:
> • Extensions no longer need to be piled in the same file if it is 
> getting too long
> • Subclasses can be in their own file, but still have access to the 
> necessary parts of their superclass
> • It communicates the author’s intent that the items are not meant to 
> be visible to its users, but that it is expected to be used for 
> extension/subclassing
> • It requires an explicit statement ‘import hidden’ to access the 
> hidden variables. Safe by default, with override.
> • It is not bound by module boundaries  (i.e. you could use it for 
> subclassing classes from an imported module)
> • Roughly the same length as ‘private’ and ‘public’ so various 
> declarations packed together are much easier to read (fileprivate breaks 
> reading rhythm)
> 
> Worth a formal proposal?
> 
> Thanks,
> Jon
> 
> 
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org 
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> 
> 

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Replace Fileprivate with Hidden + Import Hidden

2016-10-16 Thread Xiaodi Wu via swift-evolution
No need to rename fileprivate; it's irrelevant to your use case and is
resurrecting a bikeshedding discussion that really needs to be put to rest.

The proposal is essentially for something like @testable for fileprivate
members. Sounds fine to me.
On Mon, Oct 17, 2016 at 09:35 Jonathan Hull via swift-evolution <
swift-evolution@swift.org> wrote:

> On Oct 16, 2016, at 3:28 PM, T.J. Usiyan  wrote:
>
> I don't like this at all and it comes down to  "what is hidden can also
> be unhidden". This, to me, feels like it would create more confusion than
> it would address.
>
> I don’t think it would cause confusion. Other languages have things like
> protected, which is currently a glaring hole in Swift’s access control.
> This addresses that without any of the complexity of friend classes, etc….
>
>
> Why not just use `internal` for `hidden` items?
>
> Because there is an important aspect of communicating the author’s intent.
>
> I think it is important to be able to mark things which are not meant to
> be public (and internal is essentially public in the main module), but may
> be required by extensions/subclasses. With internal, it would be easy to
> accidentally create tightly coupled structures.  With ‘hidden', it requires
> intentional annotation (via the ‘include hidden’ statement) to gain access,
> so more thought will be given to the coupling.
>
> Also, internal would prevent extensions/subclasses outside the defining
> module.  With ‘hidden’ you have an author approved way of extending a type
> (even from another module).  I can’t actually think of a single use of
> ‘fileprivate’ where my intent/need was something other than allowing
> extensions. Unfortunately, with the current model those files can get quite
> a bit bigger than is ideal from an organizational standpoint.
>
>
> If we're ok with modifying import statements, why not simply have a
> command that imports `fileprivate` stuff? (not advocating for this).
>
> From a technical perspective, that is essentially what I am proposing, but
> terminology matters.  The word fileprivate was chosen to convey that the
> associated item was private to scope of the file. With this, we need to
> convey a slightly different intent because, while it does open access at
> file granularity, it is no longer private to the scope of that single file,
> and the name would be misleading.
>
> It doesn’t need to be the word ‘hidden’ necessarily, but it should be
> something with the correct connotation for the new behavior.
>
>
> I think that submodules would have really helped with this issue and it is
> unfortunate that we couldn't get them in for swift 3.
>
> I also want submodules, but they won’t fully solve the protected problem
> above.  They would allow you to group KNOWN subclasses and extensions into
> a single submodule.  But they would also prevent further extensions and
> subclasses from being made by the consumer of that module.  If that is what
> you want, then submodules are the answer, but there are also lots of cases
> where an author wants to allow careful subclassing outside of the original
> module.
>
> A good example of this is UIGestureRecognizer, which separates its
> protected items into a different include.  It hides all of the dangerous
> properties/methods in that separate file, and 98% of the time you don’t
> need it.  However, if you want to create your own gesture recognizer, you
> can’t really do it without those dangerous methods… thus you include the
> file.  With the submodule approach, you would either be unable to create
> your own gesture recognizer subclasses or the dangerous methods would be
> made available inappropriately.
>
>
> Thanks,
> Jon
>
>
> On Sun, Oct 16, 2016 at 4:34 PM, Jonathan Hull via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> I keep wanting a “protected” access level, but I must also admit that
> there was something really elegant about Swift 2’s access scheme (and I
> think most of us feel like the word ‘fileprivate’ feels out of place).  I
> was thinking about how to mesh those two ideas, and I think I may have come
> up with a solution.
>
> I propose we replace ‘fileprivate’ with a new ‘hidden’ access level.
> Hidden would work exactly the same way as fileprivate does now, but adds
> the connotation that what is hidden can also be unhidden.  By adding
> ‘import hidden TypeName’ to another file, that file also gains access to
> all of the hidden items of that type (kind of like if it was in the same
> file).
>
> #FileA
> import Foundation
>
> Struct A {
> private var x:Int
> hidden var y:Int  //This is just like fileprivate, but can
> also be shared with other files
> }
>
> extension A {
> //y can be accessed here because they are in the same file
> }
>
>
> #FileB
> import Foundation
> import hidden A  //This allows the entire file to see A’s hidden
> variables
>
> 

Re: [swift-evolution] Replace Fileprivate with Hidden + Import Hidden

2016-10-16 Thread Jonathan Hull via swift-evolution

> On Oct 16, 2016, at 3:28 PM, T.J. Usiyan  wrote:
> 
> I don't like this at all and it comes down to  "what is hidden can also be 
> unhidden". This, to me, feels like it would create more confusion than it 
> would address.
I don’t think it would cause confusion. Other languages have things like 
protected, which is currently a glaring hole in Swift’s access control. This 
addresses that without any of the complexity of friend classes, etc….


> Why not just use `internal` for `hidden` items? 
Because there is an important aspect of communicating the author’s intent. 

I think it is important to be able to mark things which are not meant to be 
public (and internal is essentially public in the main module), but may be 
required by extensions/subclasses. With internal, it would be easy to 
accidentally create tightly coupled structures.  With ‘hidden', it requires 
intentional annotation (via the ‘include hidden’ statement) to gain access, so 
more thought will be given to the coupling.

Also, internal would prevent extensions/subclasses outside the defining module. 
 With ‘hidden’ you have an author approved way of extending a type (even from 
another module).  I can’t actually think of a single use of ‘fileprivate’ where 
my intent/need was something other than allowing extensions. Unfortunately, 
with the current model those files can get quite a bit bigger than is ideal 
from an organizational standpoint.


> If we're ok with modifying import statements, why not simply have a command 
> that imports `fileprivate` stuff? (not advocating for this).
>From a technical perspective, that is essentially what I am proposing, but 
>terminology matters.  The word fileprivate was chosen to convey that the 
>associated item was private to scope of the file. With this, we need to convey 
>a slightly different intent because, while it does open access at file 
>granularity, it is no longer private to the scope of that single file, and the 
>name would be misleading.

It doesn’t need to be the word ‘hidden’ necessarily, but it should be something 
with the correct connotation for the new behavior.


> I think that submodules would have really helped with this issue and it is 
> unfortunate that we couldn't get them in for swift 3. 
I also want submodules, but they won’t fully solve the protected problem above. 
 They would allow you to group KNOWN subclasses and extensions into a single 
submodule.  But they would also prevent further extensions and subclasses from 
being made by the consumer of that module.  If that is what you want, then 
submodules are the answer, but there are also lots of cases where an author 
wants to allow careful subclassing outside of the original module.  

A good example of this is UIGestureRecognizer, which separates its protected 
items into a different include.  It hides all of the dangerous 
properties/methods in that separate file, and 98% of the time you don’t need 
it.  However, if you want to create your own gesture recognizer, you can’t 
really do it without those dangerous methods… thus you include the file.  With 
the submodule approach, you would either be unable to create your own gesture 
recognizer subclasses or the dangerous methods would be made available 
inappropriately.


Thanks,
Jon


> On Sun, Oct 16, 2016 at 4:34 PM, Jonathan Hull via swift-evolution 
> > wrote:
> I keep wanting a “protected” access level, but I must also admit that there 
> was something really elegant about Swift 2’s access scheme (and I think most 
> of us feel like the word ‘fileprivate’ feels out of place).  I was thinking 
> about how to mesh those two ideas, and I think I may have come up with a 
> solution.
> 
> I propose we replace ‘fileprivate’ with a new ‘hidden’ access level.  Hidden 
> would work exactly the same way as fileprivate does now, but adds the 
> connotation that what is hidden can also be unhidden.  By adding ‘import 
> hidden TypeName’ to another file, that file also gains access to all of the 
> hidden items of that type (kind of like if it was in the same file).
> 
> #FileA
> import Foundation
> 
> Struct A {
> private var x:Int
> hidden var y:Int  //This is just like fileprivate, but can 
> also be shared with other files
> }
> 
> extension A {
> //y can be accessed here because they are in the same file
> }
> 
> 
> #FileB
> import Foundation
> import hidden A  //This allows the entire file to see A’s hidden 
> variables
> 
> extension A {
> //y can be accessed here because of the ‘import hidden’ 
> declaration
> }
> 
> 
> #FileC
> import Foundation
> 
> extension A {
> //y can NOT be seen or accessed here because it is hidden
> }
> 
> 
> I think this is a fairly elegant solution to our protected dilemma, which 
> 

Re: [swift-evolution] Replace Fileprivate with Hidden + Import Hidden

2016-10-16 Thread T.J. Usiyan via swift-evolution
I don't like this at all and it comes down to  "what is hidden can also be
unhidden". This, to me, feels like it would create more confusion than it
would address. Why not just use `internal` for `hidden` items?  If we're ok
with modifying import statements, why not simply have a command that
imports `fileprivate` stuff? (not advocating for this).

I think that submodules would have really helped with this issue and it is
unfortunate that we couldn't get them in for swift 3.

On Sun, Oct 16, 2016 at 4:34 PM, Jonathan Hull via swift-evolution <
swift-evolution@swift.org> wrote:

> I keep wanting a “protected” access level, but I must also admit that
> there was something really elegant about Swift 2’s access scheme (and I
> think most of us feel like the word ‘fileprivate’ feels out of place).  I
> was thinking about how to mesh those two ideas, and I think I may have come
> up with a solution.
>
> I propose we replace ‘fileprivate’ with a new ‘hidden’ access level.
> Hidden would work exactly the same way as fileprivate does now, but adds
> the connotation that what is hidden can also be unhidden.  By adding
> ‘import hidden TypeName’ to another file, that file also gains access to
> all of the hidden items of that type (kind of like if it was in the same
> file).
>
> #FileA
> import Foundation
>
> Struct A {
> private var x:Int
> hidden var y:Int  //This is just like fileprivate, but can
> also be shared with other files
> }
>
> extension A {
> //y can be accessed here because they are in the same file
> }
>
>
> #FileB
> import Foundation
> import hidden A  //This allows the entire file to see A’s hidden
> variables
>
> extension A {
> //y can be accessed here because of the ‘import hidden’
> declaration
> }
>
>
> #FileC
> import Foundation
>
> extension A {
> //y can NOT be seen or accessed here because it is hidden
> }
>
>
> I think this is a fairly elegant solution to our protected dilemma, which
> also feels in sync with Swift 2’s file-based scheme.  The key features:
> • Extensions no longer need to be piled in the same file if it is
> getting too long
> • Subclasses can be in their own file, but still have access to
> the necessary parts of their superclass
> • It communicates the author’s intent that the items are not meant
> to be visible to its users, but that it is expected to be used for
> extension/subclassing
> • It requires an explicit statement ‘import hidden’ to access the
> hidden variables. Safe by default, with override.
> • It is not bound by module boundaries  (i.e. you could use it for
> subclassing classes from an imported module)
> • Roughly the same length as ‘private’ and ‘public’ so various
> declarations packed together are much easier to read (fileprivate breaks
> reading rhythm)
>
> Worth a formal proposal?
>
> Thanks,
> Jon
>
>
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution