> On Feb 20, 2017, at 6:54 PM, Michel Fortin <michel.for...@michelf.ca> wrote:
> 
>> 
>> Le 20 févr. 2017 à 18:02, Matthew Johnson <matt...@anandabits.com> a écrit :
>> 
>> 
>>> On Feb 20, 2017, at 4:50 PM, Michel Fortin <michel.for...@michelf.ca> wrote:
>>> 
>>>> Le 20 févr. 2017 à 14:45, Matthew Johnson <matt...@anandabits.com> a écrit 
>>>> :
>>>> 
>>>>> 
>>>>> On Feb 20, 2017, at 1:42 PM, Michel Fortin <michel.for...@michelf.ca> 
>>>>> wrote:
>>>>> 
>>>>>> Le 20 févr. 2017 à 14:23, Charles Srstka <cocoa...@charlessoft.com> a 
>>>>>> écrit :
>>>>>> 
>>>>>> I’m not sure how I feel about that, since it hamstrings the ability to 
>>>>>> improve APIs in a lot of ways without breaking backwards compatibility. 
>>>>>> A quick example off the top of my head would be all the Cocoa APIs that 
>>>>>> started out having ivars representing paths backed by simple getter 
>>>>>> methods, and were later refactored to be URL-based, but with the 
>>>>>> original path properties become computed properties pointing to the 
>>>>>> URL’s “path” property. With this, properties would not be able to be 
>>>>>> refactored in this way unless the library developer had previously 
>>>>>> declared the “path” property as private(set), which is unlikely for a 
>>>>>> property that was not intended to be changed after the class was 
>>>>>> initialized.
>>>>> 
>>>>> Version 1:
>>>>> 
>>>>>   public class A {
>>>>>           public let path: String
>>>>>   }
>>>>> 
>>>>> Version 2:
>>>>> 
>>>>>   public class A {
>>>>>           public pure var path: String { return url.path }
>>>>>           public let path: URL
>>>>>   }
>>>>> 
>>>>> This is assuming `let` is implicitly pure. It probably should not be. Or 
>>>>> at least it should not when crossing module boundaries. Note that 
>>>>> internal to the module it wouldn't violate any contract to allow pure 
>>>>> code access to `let` variables.
>>>>> 
>>>>> Which makes me think of an idea: internal to the module, `pure` could be 
>>>>> inferred for everything. Only the published APIs would require the 
>>>>> annotations, and only if you want `pure` to be part of the API contract. 
>>>>> Attaching `pure` to an internal function could still be useful for your 
>>>>> own reasoning though.
>>>> 
>>>> That’s a very interesting approach that could lighten the syntactic load.  
>>>> We could strategically annotate our code where we want purity verified, 
>>>> but otherwise omit the annotation for members that don’t need to be 
>>>> visible outside the module.  This approach works especially well for 
>>>> closures.  I like it a lot!
>>> 
>>> There is an important limitation to this though: a class method that mutate 
>>> something in the class is never going to be implicitly pure (per the rules 
>>> of purity for instance methods). For that the compiler would have to prove 
>>> the method is only called from unique references, and that'd be a bit weird 
>>> (add a method call somewhere and suddenly the function becomes impure).
>> 
>> That seems totally fine to me.
>> 
>>> 
>>> There's also an issue with diagnostics: say you have func1 that calls func2 
>>> that calls func3. Func1 is `pure`, the other two are pure only implicitly. 
>>> Then you change something in func3, and suddenly func1 complains that it 
>>> can't call impure func2 and you are left wondering why because you haven't 
>>> changed anything in func2. Perhaps the compiler could dig in the call tree 
>>> to find the impure operation and tell you, but that's starting to look like 
>>> the awful diagnostic messages for C++ templates.
>>> 
>>> So now I'm starting to think this idea of inferring purity was perhaps a 
>>> bit reckless.
>> 
>> It all depends on how people use it (that’s why I mentioned strategic 
>> annotations), but yeah it could be ugly.  I wonder if there is a reasonable 
>> way to bound the inference to keep error messages tractable.  For example, 
>> you mentioned inference within a module.  If that’s too broad a scope for 
>> inference, maybe within a file would be ok and annotation would be required 
>> for anything with `internal` or greater visibility.  This would still 
>> address closures which would be cool and outside of crazy large files it 
>> wouldn’t be too bad to track down the meaning of an error.
> 
> If a closure can be inferred pure, then it should be pure. We already infer 
> `throws` and return types for closures, so inferring `pure` is natural. But 
> for functions declared with a full signature, I'm hesitant to allow them to 
> be inferred.
> 
> Now that I think of it, overrides could be another source of problem with 
> inference: add an impure override and the method in the base class can no 
> longer be inferred as pure. So it can't apply to any non-final class property 
> or function.

Yeah, I’m ok with requiring annotation if inference is going to be hairy or 
confusing.

> 
> -- 
> Michel Fortin
> https://michelf.ca <https://michelf.ca/>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to