-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use initialization checker for soundness #11716
Conversation
-- Warning: tests/init/neg/i11572.scala:8:6 ------------------------------------ 8 | val t: Bounded = new Bounded { | ^ | Access non-initialized value t. Calling trace: | -> } [ i11572.scala:11 ] | -> override type T >: t.T <: t.T [ i11572.scala:10 ] 1 warning found
@@ -12,8 +12,8 @@ import core.Contexts._ | |||
import Potentials._ | |||
|
|||
object Effects { | |||
type Effects = Set[Effect] | |||
val empty: Effects = Set.empty | |||
type Effects = Vector[Effect] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the change from Set to Vector related to checking TypeDef
s, or is it an orthogonal improvement?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's orthogonal. Set is bad for concatenation, and we can afford to have duplicate entries in summaries.
We get types like the following in effpi: effpi.examples.demo.audit.types.Pay#replyTo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think I fully understand what effectsOfType
does, but the rest looks OK!
@@ -213,6 +214,19 @@ object Summarization { | |||
else summary | |||
} | |||
|
|||
private def effectsOfType(tp: Type, source: Tree)(implicit env: Env): Effects = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this function calculating the effects of constructing an instance of type tp
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's calculating field access effects in types. In Scala we can have types like p.f.T
, here we summarize the effects for p.f
.
@olhotak Could you also have a look at the changes? |
var summary = Summary.empty | ||
val traverser = new TypeTraverser { | ||
def traverse(tp: Type): Unit = tp match { | ||
case TermRef(_: SingletonType, _) => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we restrict to SingletonType here as a prefix of the TermRef?
What could the prefix be other than a SingletonType and why is it OK to skip those cases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the community build, the project effpi (which use compiler plugin for session protocol checking) generates types like the following:
effpi.examples.demo.audit.types.Pay#replyTo
The type looks dubious, but the compiler seems to be fine with it. For such a type, our code will simply recur on the prefix effpi.examples.demo.audit.types.Pay
and look for term selections recursively.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still confused.
That type is a TypeRef, right? And we recurse on its prefix below in case _ => traverseChildren(tp)
, right? What would go wrong if this case was just case _: TermRef =>
instead of the pattern with the SingletonType
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't make it clear: it's a display problem, it's a TermRef where the prefix is a TypeRef.
If we only have _: TermRef
, we will need to do more error-handling in analyze(tp)
to avoid crash: currently it's pretty strict about what types it may get.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, sorry, yes, this makes sense now.
Then I just wonder why the restriction is for the prefix to be a SingletonType
rather than the prefix being something like TermRef | NoPrefix
. Can a SingletonType
be more things than that and are those things that we want?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the prefix can also be ThisType
, which is usually what we care about. If the prefix is NoPrefix
, the variable is a local variable --- the analysis currently enforces that all local variables are hot.
I have another question above about TermRef/SingletonType. We should check the various pieces of code in the comments of #50, scala/bug#9633, #4042, #4031, #5854. I think you have some of these already but there seem to be a lot of examples there: there are probably more that should be added as test cases. Otherwise LGTM. |
I added some more tests. I didn't include tests that use |
Good point. I will ask @noti0na1 to look at which of the above examples are fixed by |
Use initialization checker for soundness
Fix #5854, #4042 and part of #11572