The greater prominence of Critiques in Calypso encourages me to try to clean them out. I bumped into a false positive "Temporaries read before written." that I've condensed to the following example. test |x| [ x := nil ] whileNil: [ x ifNil: [ x := 1] ] Now before I log an Issue, is it feasible to be able to recognise this? Perhaps only for common looping idioms? Anyway, the workaround is simple enough... test |x| x := nil. "silence critiques" [ x := nil ] whileNil: [ x ifNil: [ x := 1] ] cheers -ben |
On dim. 15 avr. 2018 at 16:43, Ben Coman <[hidden email]> wrote:
Hi Ben, I do not have an answer regarding the variables written in the blocks, but for false positive you can also just exclude a rule for the scope of the method, class, package and image IIRC. There was a presentation at esug about it. I'm on phone and it's hard to search for the link currently.
Cyril Ferlicot
https://ferlicot.fr |
In reply to this post by Ben Coman
On 04/15/2018 07:42 AM, Ben Coman
wrote:
In this example, the first runtime reference to x is to send it #ifNil:. So technically, x *is* being read before being written, at least if you count sending it a message as "reading" (which seems a reasonable interpretation to me). Probably not a terrible idea to be explicit about initializing to nil, thereby revealing the developer's intent that this variable be nil rather than relying on the default initialization to nil. So I'd lean towards leaving the critique as-is. If a developer knows what they did was safe, they can either ignore the critique, exclude the critique, or put in the explicit initialization to nil. I think I prefer explicit initialization. Regards, -Martin |
2018-04-15 20:40 GMT+02:00 Martin McClure <[hidden email]>:
Maybe critique can be a bit smarter and check that sent message is known by nil.
|
In reply to this post by Ben Coman
> On Apr 15, 2018, at 9:42 AM, Ben Coman <[hidden email]> wrote: > > The greater prominence of Critiques in Calypso > encourages me to try to clean them out. > > I bumped into a false positive "Temporaries read before written." > that I've condensed to the following example. > > test > |x| > [ x := nil ] whileNil: [ x ifNil: [ x := 1] ] > > Now before I log an Issue, is it feasible to be able to recognise this? In general one would need to look at the implementor to know which blocks are always evaluated and in what order. For example, someone could have defined whileNil: as: whileNil: aBlock aBlock value In this case, it isn’t a false positive since the "x := nil” is never executed and the first use of “x” is the “x ifNil: …”. > Perhaps only for common looping idioms? It does look for common looping idioms. It treats the four whileTrue/False messages different than normal messages. It also treats ifTrue:ifFalse:/ifFalse:ifTrue: messages differently. #whileNil: isn’t what I call a common looping idiom as it seems to have been added in 2007 (about 13 years after the read before written tester was written), and has 0 senders in my image. I think a better change would be adding knowledge about and:/or: combined with ifTrue:, whileTrue:, etc. For example, (self someCondition and: [(x := self value) > 0]) ifTrue: [Transcript show: x printString] In this case, x is reported as potentially read before written, but it can’t be. John Brant |
In reply to this post by Martin McClure-2
Hi Martin,
|
In reply to this post by Denis Kudriashov
On 16 April 2018 at 03:07, Denis Kudriashov <[hidden email]> wrote:
> > > > 2018-04-15 20:40 GMT+02:00 Martin McClure <[hidden email]>: >> >> On 04/15/2018 07:42 AM, Ben Coman wrote: >> >> The greater prominence of Critiques in Calypso >> encourages me to try to clean them out. >> >> I bumped into a false positive "Temporaries read before written." >> that I've condensed to the following example. >> >> test >> |x| >> [ x := nil ] whileNil: [ x ifNil: [ x := 1] ] >> >> Now before I log an Issue, is it feasible to be able to recognise this? >> Perhaps only for common looping idioms? >> >> >> In this example, the first runtime reference to x is to send it #ifNil:. So technically, x *is* being read before being written, at least if you count sending it a message as "reading" (which seems a reasonable interpretation to me). > > > Maybe critique can be a bit smarter and check that sent message is known by nil. That sounds like a nice approach. Browsing the messages of Undefined, maybe its worthwhile to restrict this to messages containing the the string "nil", because this shows explicit intent and would cover the most common//useful cases. https://pharo.manuscript.com/f/cases/21704/Critiques-Temporaries-read-before-written-versus-nil-checking-messages cheers -ben |
On 04/15/2018 05:02 PM, Ben Coman wrote:
> On 16 April 2018 at 03:07, Denis Kudriashov <[hidden email]> wrote: >> >> >> >> 2018-04-15 20:40 GMT+02:00 Martin McClure <[hidden email]>: >>> >>> On 04/15/2018 07:42 AM, Ben Coman wrote: >>> >>> The greater prominence of Critiques in Calypso >>> encourages me to try to clean them out. >>> >>> I bumped into a false positive "Temporaries read before written." >>> that I've condensed to the following example. >>> >>> test >>> |x| >>> [ x := nil ] whileNil: [ x ifNil: [ x := 1] ] >>> >>> Now before I log an Issue, is it feasible to be able to recognise this? >>> Perhaps only for common looping idioms? >>> >>> >>> In this example, the first runtime reference to x is to send it #ifNil:. So technically, x *is* being read before being written, at least if you count sending it a message as "reading" (which seems a reasonable interpretation to me). >> >> >> Maybe critique can be a bit smarter and check that sent message is known by nil. > > That sounds like a nice approach. Browsing the messages of Undefined, > maybe its worthwhile to restrict this to messages containing the the > string "nil", because this shows explicit intent and would cover the > most common//useful cases. > https://pharo.manuscript.com/f/cases/21704/Critiques-Temporaries-read-before-written-versus-nil-checking-messages You may break extract method if you change this. I haven't tried, but I think something like this would break -- extract the last line of this method: method | x | x := self someValue. x isNil ifTrue: [Transcript show: 'nil'] You should get something like this: method | x | x := self someValue. self extractedMethod: x extractedMethod: x x isNil ifTrue: [Transcript show: 'nil'] However, if you change what is considered read before written, then you would get something like this: method | x | x := self someValue. self extractedMethod extractedMethod | x | x isNil ifTrue: [Transcript show: 'nil'] John Brant |
Free forum by Nabble | Edit this page |