From 108cbc819e5a238bf622c5f15f87578e5e42dd99 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 11 Jun 2020 21:50:02 +0200 Subject: [PATCH 1/5] Have a per-run time budget for import suggestions Keep a budget of import suggestions per run. The first timeout is 10sec. Each successive timeout is the previous timeout reduced by the search time of the previous suggestion search, but at least half the previous timeout. --- .../dotty/tools/dotc/typer/Implicits.scala | 17 +++ .../tools/dotc/typer/ImportSuggestions.scala | 13 +- tests/neg/i9160.scala | 131 ++++++++++++++++++ 3 files changed, 156 insertions(+), 5 deletions(-) create mode 100644 tests/neg/i9160.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 3da72a6c680e..6d929ba3edff 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -481,6 +481,23 @@ trait ImplicitRunInfo: private val EmptyTermRefSet = new TermRefSet(using NoContext) + /** Global timeout to stop looking for further implicit suggestions, in ms. + * This is for the first import suggestion; subsequent suggestions + * get smaller timeouts. + */ + private inline val suggestFirstImplicitsTimeOut = 10000 + + private var importSuggestionBudget: Long = suggestFirstImplicitsTimeOut + + /** The current timeout for import suggestions */ + def nextImportSuggestionTimeout() = importSuggestionBudget + + /** Reduce the import suggestion timeout by `ms`, but make sure that + * the new timeout is at least half the old one. + */ + def reduceImportSuggestionTimeout(ms: Long) = + importSuggestionBudget = (importSuggestionBudget - ms) max (importSuggestionBudget / 2) + private def isExcluded(sym: Symbol) = if migrateTo3 then false else sym.is(Package) || sym.isPackageObject diff --git a/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala b/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala index 117e28f2b9b7..d231bc36d1c0 100644 --- a/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala +++ b/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala @@ -27,9 +27,6 @@ trait ImportSuggestions: /** Timeout to test a single implicit value as a suggestion, in ms */ private inline val testOneImplicitTimeOut = 500 - /** Global timeout to stop looking for further implicit suggestions, in ms */ - private inline val suggestImplicitTimeOut = 10000 - /** A list of TermRefs referring to the roots where suggestions for * imports of givens or extension methods that might fix a type error * are searched. @@ -145,7 +142,11 @@ trait ImportSuggestions: */ private def importSuggestions(pt: Type)(using Context): (List[TermRef], List[TermRef]) = val timer = new Timer() - val deadLine = System.currentTimeMillis() + suggestImplicitTimeOut + val allotted = ctx.run.nextImportSuggestionTimeout() + if allotted <= 1 then return (Nil, Nil) + implicits.println(i"looking for import suggestions, timeout = ${allotted}ms") + val start = System.currentTimeMillis() + val deadLine = start + allotted // Candidates that are already available without explicit import because they // are already provided by the context (imported or inherited) or because they @@ -249,7 +250,9 @@ trait ImportSuggestions: println("caught exception when searching for suggestions") ex.printStackTrace() (Nil, Nil) - finally timer.cancel() + finally + timer.cancel() + ctx.run.reduceImportSuggestionTimeout(System.currentTimeMillis() - start) end importSuggestions /** The `ref` parts of this list of pairs, discarding subsequent elements that diff --git a/tests/neg/i9160.scala b/tests/neg/i9160.scala new file mode 100644 index 000000000000..7a00c89a8f80 --- /dev/null +++ b/tests/neg/i9160.scala @@ -0,0 +1,131 @@ +package foo + +object Test { + type F[T] + val F: F[Int] = ??? + + def f[T](t: T)( + e1: F[T], e2: F[T], e3: F[T], + e4: F[T], e5: F[T], e6: F[T], + e7: F[T], e8: F[T], e9: F[T], + e10: F[T], e11: F[T], e12: F[T], + ) = ??? + f("foo")( + F, F, F, // error // error // error + F, F, F, // error // error // error + F, F, F, // error // error // error + F, F, F, // error // error // error + ) +} + + +object x extends X1 with X2 + +trait X1 extends Implicits +trait X2 extends Implicits + +trait Implicits { + type F[T] + type G[T] + + given g1 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g2 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g3 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g4 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g5 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g6 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g7 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g8 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g9 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g10 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g11 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g12 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g13 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g14 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g15 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g16 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g17 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g18 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g19 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g20 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g21 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g22 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g23 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g24 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g25 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g26 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g27 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g28 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g29 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g30 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g31 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g32 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g33 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g34 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g35 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g36 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g37 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g38 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g39 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g40 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g41 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g42 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g43 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g44 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g45 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g46 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g47 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g48 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g49 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g50 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g51 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g52 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g53 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g54 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g55 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g56 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g57 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g58 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g59 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g60 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g61 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g62 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g63 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g64 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g65 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g66 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g67 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g68 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g69 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g70 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g71 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g72 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g73 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g74 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g75 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g76 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g77 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g78 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g79 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g80 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g81 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g82 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g83 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g84 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g85 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g86 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g87 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g88 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g89 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g90 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g91 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g92 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g93 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g94 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g95 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g96 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g97 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g98 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g99 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? + given g100 [T1: F, T2: F, T3: F, T4: F, T5: F, T6: F, T7: F, T8: F, T9: F, T10: F, T11: F, T12: F, T13: F, T14: F, T15: F, T16: F, T17: F, T18: F, T19: F, T20: F, T21: F, T22: F] as G[Int] = ??? +} \ No newline at end of file From 4dcb7cedf69eb8128797af954e8cc8764c314692 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 11 Jun 2020 23:47:17 +0200 Subject: [PATCH 2/5] Split test into three files That way we escape the problem that implicit timeouts are reduced too much for later tests. --- tests/neg/missing-implicit-2.check | 28 ++++++++++++++++ tests/neg/missing-implicit-2.scala | 6 ++++ tests/neg/missing-implicit-3.check | 25 ++++++++++++++ tests/neg/missing-implicit-3.scala | 8 +++++ tests/neg/missing-implicit.check | 53 ------------------------------ tests/neg/missing-implicit.scala | 12 ------- 6 files changed, 67 insertions(+), 65 deletions(-) create mode 100644 tests/neg/missing-implicit-2.check create mode 100644 tests/neg/missing-implicit-2.scala create mode 100644 tests/neg/missing-implicit-3.check create mode 100644 tests/neg/missing-implicit-3.scala diff --git a/tests/neg/missing-implicit-2.check b/tests/neg/missing-implicit-2.check new file mode 100644 index 000000000000..1cf3c1bcb340 --- /dev/null +++ b/tests/neg/missing-implicit-2.check @@ -0,0 +1,28 @@ +-- Error: tests/neg/missing-implicit-2.scala:4:24 ---------------------------------------------------------------------- +4 |val f = Future[Unit] { } // error + | ^ + | Cannot find an implicit ExecutionContext. You might pass + | an (implicit ec: ExecutionContext) parameter to your method. + | + | The ExecutionContext is used to configure how and on which + | thread pools Futures will run, so the specific ExecutionContext + | that is selected is important. + | + | If your application does not define an ExecutionContext elsewhere, + | consider using Scala's global ExecutionContext by defining + | the following: + | + | implicit val ec: scala.concurrent.ExecutionContext = scala.concurrent.ExecutionContext.global + | + | The following import might fix the problem: + | + | import concurrent.ExecutionContext.Implicits.global + | +-- [E007] Type Mismatch Error: tests/neg/missing-implicit-2.scala:6:25 ------------------------------------------------- +6 |val b: java.lang.Byte = (1: Byte) // error, but no hint + | ^^^^^^^ + | Found: Byte + | Required: Byte² + | + | where: Byte is a class in package scala + | Byte² is a class in package java.lang diff --git a/tests/neg/missing-implicit-2.scala b/tests/neg/missing-implicit-2.scala new file mode 100644 index 000000000000..bec1013dbd29 --- /dev/null +++ b/tests/neg/missing-implicit-2.scala @@ -0,0 +1,6 @@ +import Predef.{byte2Byte => _, _} +import scala.concurrent.Future + +val f = Future[Unit] { } // error + +val b: java.lang.Byte = (1: Byte) // error, but no hint diff --git a/tests/neg/missing-implicit-3.check b/tests/neg/missing-implicit-3.check new file mode 100644 index 000000000000..abb3b083ab6f --- /dev/null +++ b/tests/neg/missing-implicit-3.check @@ -0,0 +1,25 @@ +-- [E007] Type Mismatch Error: tests/neg/missing-implicit-3.scala:6:44 ------------------------------------------------- +6 |val d: scala.concurrent.duration.Duration = (10, DAYS) // error + | ^^^^^^^^^^ + | Found: (Int, java.util.concurrent.TimeUnit) + | Required: concurrent².duration.Duration + | + | where: concurrent is a package in package java.util + | concurrent² is a package in package scala + | + | + | The following import might fix the problem: + | + | import concurrent.duration.pairIntToDuration + | +-- [E008] Not Found Error: tests/neg/missing-implicit-3.scala:8:48 ----------------------------------------------------- +8 |val d2: scala.concurrent.duration.Duration = 10.days // error + | ^^^^^^^ + | value days is not a member of Int, but could be made available as an extension method. + | + | One of the following imports might fix the problem: + | + | import concurrent.duration.DurationInt + | import concurrent.duration.DurationLong + | import concurrent.duration.DurationDouble + | diff --git a/tests/neg/missing-implicit-3.scala b/tests/neg/missing-implicit-3.scala new file mode 100644 index 000000000000..618a33d88101 --- /dev/null +++ b/tests/neg/missing-implicit-3.scala @@ -0,0 +1,8 @@ +import Predef.{byte2Byte => _, _} +import math.Numeric + +val DAYS = scala.concurrent.duration.DAYS + +val d: scala.concurrent.duration.Duration = (10, DAYS) // error + +val d2: scala.concurrent.duration.Duration = 10.days // error diff --git a/tests/neg/missing-implicit.check b/tests/neg/missing-implicit.check index 0d4ad9c1f22e..3ebf54bbf20e 100644 --- a/tests/neg/missing-implicit.check +++ b/tests/neg/missing-implicit.check @@ -17,56 +17,3 @@ | | import math.Numeric.Implicits.infixNumericOps | --- Error: tests/neg/missing-implicit.scala:10:24 ----------------------------------------------------------------------- -10 |val f = Future[Unit] { } // error - | ^ - | Cannot find an implicit ExecutionContext. You might pass - | an (implicit ec: ExecutionContext) parameter to your method. - | - | The ExecutionContext is used to configure how and on which - | thread pools Futures will run, so the specific ExecutionContext - | that is selected is important. - | - | If your application does not define an ExecutionContext elsewhere, - | consider using Scala's global ExecutionContext by defining - | the following: - | - | implicit val ec: scala.concurrent.ExecutionContext = scala.concurrent.ExecutionContext.global - | - | The following import might fix the problem: - | - | import concurrent.ExecutionContext.Implicits.global - | --- [E007] Type Mismatch Error: tests/neg/missing-implicit.scala:12:25 -------------------------------------------------- -12 |val b: java.lang.Byte = (1: Byte) // error, but no hint - | ^^^^^^^ - | Found: Byte - | Required: Byte² - | - | where: Byte is a class in package scala - | Byte² is a class in package java.lang --- [E007] Type Mismatch Error: tests/neg/missing-implicit.scala:16:44 -------------------------------------------------- -16 |val d: scala.concurrent.duration.Duration = (10, DAYS) // error - | ^^^^^^^^^^ - | Found: (Int, java.util.concurrent.TimeUnit) - | Required: concurrent².duration.Duration - | - | where: concurrent is a package in package java.util - | concurrent² is a package in package scala - | - | - | The following import might fix the problem: - | - | import concurrent.duration.pairIntToDuration - | --- [E008] Not Found Error: tests/neg/missing-implicit.scala:18:48 ------------------------------------------------------ -18 |val d2: scala.concurrent.duration.Duration = 10.days // error - | ^^^^^^^ - | value days is not a member of Int, but could be made available as an extension method. - | - | One of the following imports might fix the problem: - | - | import concurrent.duration.DurationInt - | import concurrent.duration.DurationLong - | import concurrent.duration.DurationDouble - | diff --git a/tests/neg/missing-implicit.scala b/tests/neg/missing-implicit.scala index 34d88f0e74eb..2467fb3d8c20 100644 --- a/tests/neg/missing-implicit.scala +++ b/tests/neg/missing-implicit.scala @@ -4,15 +4,3 @@ import math.Numeric def consume[T: Numeric](xs: List[T], limit: T): List[T] = xs match case x :: xs1 if limit > 0 => consume(xs1, limit - x) // error // error case _ => xs - -import scala.concurrent.Future - -val f = Future[Unit] { } // error - -val b: java.lang.Byte = (1: Byte) // error, but no hint - -val DAYS = scala.concurrent.duration.DAYS - -val d: scala.concurrent.duration.Duration = (10, DAYS) // error - -val d2: scala.concurrent.duration.Duration = 10.days // error From 9be30013f1349630d697c2fe91b16ef43e8e17cd Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 12 Jun 2020 00:05:12 +0200 Subject: [PATCH 3/5] Make import suggestions timeout configurable We now expose it as a var, which can be set by IDEs or other tools. --- .../src/dotty/tools/dotc/typer/Implicits.scala | 15 ++++++--------- .../tools/dotc/typer/ImportSuggestions.scala | 6 ++++-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 6d929ba3edff..4ce5056b26c1 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -487,16 +487,13 @@ trait ImplicitRunInfo: */ private inline val suggestFirstImplicitsTimeOut = 10000 - private var importSuggestionBudget: Long = suggestFirstImplicitsTimeOut - - /** The current timeout for import suggestions */ - def nextImportSuggestionTimeout() = importSuggestionBudget - - /** Reduce the import suggestion timeout by `ms`, but make sure that - * the new timeout is at least half the old one. + /** Global default timeout to stop looking for further implicit suggestions, in ms. + * This is usually for the first import suggestion; subsequent suggestions + * may get smaller timeouts. Specifically, the importSuggestions method reduces + * the budget available after it is run by the time it took, but never less + * than to half of the previous budget. */ - def reduceImportSuggestionTimeout(ms: Long) = - importSuggestionBudget = (importSuggestionBudget - ms) max (importSuggestionBudget / 2) + var importSuggestionBudget: Long = 10000 private def isExcluded(sym: Symbol) = if migrateTo3 then false else sym.is(Package) || sym.isPackageObject diff --git a/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala b/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala index d231bc36d1c0..44a14da08b77 100644 --- a/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala +++ b/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala @@ -142,7 +142,7 @@ trait ImportSuggestions: */ private def importSuggestions(pt: Type)(using Context): (List[TermRef], List[TermRef]) = val timer = new Timer() - val allotted = ctx.run.nextImportSuggestionTimeout() + val allotted = ctx.run.importSuggestionBudget if allotted <= 1 then return (Nil, Nil) implicits.println(i"looking for import suggestions, timeout = ${allotted}ms") val start = System.currentTimeMillis() @@ -252,7 +252,9 @@ trait ImportSuggestions: (Nil, Nil) finally timer.cancel() - ctx.run.reduceImportSuggestionTimeout(System.currentTimeMillis() - start) + ctx.run.importSuggestionBudget = + (ctx.run.importSuggestionBudget - (System.currentTimeMillis() - start)) + `max` (ctx.run.importSuggestionBudget / 2) end importSuggestions /** The `ref` parts of this list of pairs, discarding subsequent elements that From 17f4213cefbdc710b80f112f681ee911c830ee1f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 12 Jun 2020 10:16:28 +0200 Subject: [PATCH 4/5] Refine timeout config --- compiler/src/dotty/tools/dotc/Run.scala | 6 ++++++ .../dotty/tools/dotc/config/ScalaSettings.scala | 1 + .../src/dotty/tools/dotc/typer/Implicits.scala | 14 -------------- .../dotty/tools/dotc/typer/ImportSuggestions.scala | 11 ++++++++--- 4 files changed, 15 insertions(+), 17 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/Run.scala b/compiler/src/dotty/tools/dotc/Run.scala index 1a723a79204c..fadc48572585 100644 --- a/compiler/src/dotty/tools/dotc/Run.scala +++ b/compiler/src/dotty/tools/dotc/Run.scala @@ -31,6 +31,12 @@ import scala.util.control.NonFatal /** A compiler run. Exports various methods to compile source files */ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with ConstraintRunInfo { + /** Default timeout to stop looking for further implicit suggestions, in ms. + * This is usually for the first import suggestion; subsequent suggestions + * may get smaller timeouts. @see ImportSuggestions.reduceTimeBudget + */ + var importSuggestionBudget: Int = ictx.settings.XimportSuggestionTimeout.value + /** If this variable is set to `true`, some core typer operations will * return immediately. Currently these early abort operations are * `Typer.typed` and `Implicits.typedImplicit`. diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 6e50df6cbb30..ed97c8b740d8 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -87,6 +87,7 @@ class ScalaSettings extends Settings.SettingGroup { val XfatalWarnings: Setting[Boolean] = BooleanSetting("-Xfatal-warnings", "Fail the compilation if there are any warnings.") val XverifySignatures: Setting[Boolean] = BooleanSetting("-Xverify-signatures", "Verify generic signatures in generated bytecode.") val XignoreScala2Macros: Setting[Boolean] = BooleanSetting("-Xignore-scala2-macros", "Ignore errors when compiling code that calls Scala2 macros, these will fail at runtime.") + val XimportSuggestionTimeout: Setting[Int] = IntSetting("-Ximport-suggestion-timeout", "Timeout (in ms) for searching for import suggestions when errors are reported.", 8000) val XmixinForceForwarders = ChoiceSetting( name = "-Xmixin-force-forwarders", diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 4ce5056b26c1..3da72a6c680e 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -481,20 +481,6 @@ trait ImplicitRunInfo: private val EmptyTermRefSet = new TermRefSet(using NoContext) - /** Global timeout to stop looking for further implicit suggestions, in ms. - * This is for the first import suggestion; subsequent suggestions - * get smaller timeouts. - */ - private inline val suggestFirstImplicitsTimeOut = 10000 - - /** Global default timeout to stop looking for further implicit suggestions, in ms. - * This is usually for the first import suggestion; subsequent suggestions - * may get smaller timeouts. Specifically, the importSuggestions method reduces - * the budget available after it is run by the time it took, but never less - * than to half of the previous budget. - */ - var importSuggestionBudget: Long = 10000 - private def isExcluded(sym: Symbol) = if migrateTo3 then false else sym.is(Package) || sym.isPackageObject diff --git a/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala b/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala index 44a14da08b77..6bcb816b1ce4 100644 --- a/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala +++ b/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala @@ -252,11 +252,16 @@ trait ImportSuggestions: (Nil, Nil) finally timer.cancel() - ctx.run.importSuggestionBudget = - (ctx.run.importSuggestionBudget - (System.currentTimeMillis() - start)) - `max` (ctx.run.importSuggestionBudget / 2) + reduceTimeBudget(((System.currentTimeMillis() - start) min Int.MaxValue).toInt) end importSuggestions + /** Reduce next timeout for import suggestions by the amount of time it took + * for current search, but but never less than to half of the previous budget. + */ + private def reduceTimeBudget(used: Int)(using Context) = + ctx.run.importSuggestionBudget = + (ctx.run.importSuggestionBudget - used) max (ctx.run.importSuggestionBudget / 2) + /** The `ref` parts of this list of pairs, discarding subsequent elements that * have the same String part. Elements are sorted by their String parts. */ From dc96bb61e83058196c6305e0b20493e97d01469d Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 14 Jun 2020 12:41:29 +0200 Subject: [PATCH 5/5] Fix timeout config Avoid referring to config option before it is initialized --- compiler/src/dotty/tools/dotc/Run.scala | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/Run.scala b/compiler/src/dotty/tools/dotc/Run.scala index fadc48572585..b15640ebd9a4 100644 --- a/compiler/src/dotty/tools/dotc/Run.scala +++ b/compiler/src/dotty/tools/dotc/Run.scala @@ -35,7 +35,15 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint * This is usually for the first import suggestion; subsequent suggestions * may get smaller timeouts. @see ImportSuggestions.reduceTimeBudget */ - var importSuggestionBudget: Int = ictx.settings.XimportSuggestionTimeout.value + private var myImportSuggestionBudget: Int = + Int.MinValue // sentinel value; means whatever is set in command line option + + def importSuggestionBudget = + if myImportSuggestionBudget == Int.MinValue then ictx.settings.XimportSuggestionTimeout.value + else myImportSuggestionBudget + + def importSuggestionBudget_=(x: Int) = + myImportSuggestionBudget = x /** If this variable is set to `true`, some core typer operations will * return immediately. Currently these early abort operations are