Skip to content

Fix more problems detected by fuzzing in #4389 #4411

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

Merged
merged 13 commits into from
Apr 30, 2018

Conversation

odersky
Copy link
Contributor

@odersky odersky commented Apr 29, 2018

Fix more problems detected by fuzzing in #4389

}
recur(buf, remaining)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at this point remaining = Thicket(elems) :: remaining1 so isn't this call equivalent to the one in the else branch below?

Copy link
Contributor Author

@odersky odersky Apr 29, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed it is. Scope for simplification, then.

def typedClassDef(cdef: untpd.TypeDef, cls: ClassSymbol)(implicit ctx: Context): Tree = track("typedClassDef") {
if (!cls.info.isInstanceOf[ClassInfo]) {
assert(ctx.reporter.errorsReported)
return cdef.withType(UnspecifiedErrorType)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think ideally we should have a way to recursively set the type of the tree children to maintain the invariant that a typed tree only contains typed trees.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, yes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, that's not so easy. Sometimes, there's simply no way to proceed. And we cannot just assign an ErrorType, because a lot of trees are not typed trees, so we'd have to replace them with something else.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess they could be replaced by ErrorTrees.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact, maybe cdef should just be replaced by an ErrorTree since it's unusable anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, yes. Let's do that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm wait. What do you mean by ErrorTree? We only have errorTree which gives an error type to an existing tree.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, we can replace it with an EmptyTree instead.

odersky added 2 commits April 29, 2018 15:14
`checkedParentType` tests that the underlying class symbol of a type is a class.
So `computeBaseClasses` should assume exactly the same property.
@odersky
Copy link
Contributor Author

odersky commented Apr 29, 2018

Rebased to master

odersky added 6 commits April 29, 2018 15:47
Also: fix a cyclic reference caused by 5252b15
 - Handle the case where Thickets can contain themselves Thickets
 - Make it tail recursive instead of using an outer while loop
In the face of previous errors:

 - Constant#classBound cannot assume all class parents have good types
 - dominator cannot assume that all classes in an OrType inherit from the same parent
These are sometimes detected after they are computed. Need to avoid
a crash in AndType due to an operand that is not a value type.
@@ -3478,7 +3478,7 @@ object Types {
if (selfTypeCache == null)
selfTypeCache = {
val given = cls.givenSelfType
if (!given.exists) appliedRef
if (!given.isValueType) appliedRef
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth explicitly checking that an error happened like other commits in this PR do, e.g.:

if (!given.isValueType) {
  assert(!given.exists || ctx.reporter.errorsReported)
  appliedRef
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The given type might be higher-kinded (in fact that's what it was in the test) but this would be detected only later.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, in that case maybe just add a comment explaining that non-value types self can only happen with erroneous code? Otherwise readers of this code might be puzzled.

/** The result type of `mt`, where all references to parameters of `mt` are
* replaced by either wildcards (if typevarsMissContext) or TypeParamRefs.
*/
def resultTypeApprox(mt: MethodType)(implicit ctx: Context): Type =
if (mt.isResultDependent) {
def replacement(tp: Type) =
if (ctx.mode.is(Mode.TypevarsMissContext)) WildcardType else newDepTypeVar(tp)
if (ctx.mode.is(Mode.TypevarsMissContext) ||
!tp.widenExpr.isValueTypeOrWildcard) WildcardType
Copy link
Member

@smarter smarter Apr 29, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here too, the error recovery case could be more explicit:

if (!tp.widenExpr.isValueTypeOrWildcard) {
  assert(ctx.reporter.errorsReported)
  WildcardType
}
else if (ctx.mode.is(Mode.TypevarsMissContext))
  WildcardType
else ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same response: I am not sure the error would always be detected beforehand.

odersky added 3 commits April 29, 2018 17:17
In the tested case, an unApply ended up with an inserted toplevel apply method,
which confused the follow-on logic. This case is now rejected.
Parent types can be aliases, so .typeSymbol can be wrong.
// A test case is CompilationTests.compileMixed
pcls match {
for (p <- classParents)
p.classSymbol match {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

incorrect indentation.

@odersky
Copy link
Contributor Author

odersky commented Apr 29, 2018

So that's all bugs in #4389, except those that contain a _ in a wrong place.

if (ctx.reporter.errorsReported) ErrorType(msg)
else throw new java.lang.Error(msg)
}
ErrorType(msg).assertingErrorsReported(msg)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong indentation.

@odersky odersky merged commit 75b66c8 into scala:master Apr 30, 2018
@allanrenucci allanrenucci deleted the fix-fuzzing-2 branch April 30, 2018 18:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants