summaryrefslogtreecommitdiff
path: root/src/reflect
Commit message (Collapse)AuthorAgeFilesLines
* Flesh out copyMemberDef methods with copyModuleDef.Paul Phillips2013-05-101-0/+15
|
* Merge pull request #2462 from magarciaEPFL/backendish9Paul Phillips2013-05-101-0/+2
|\ | | | | SI-6863 root cause fixed using factory of scala.runtime.*Ref
| * SI-6863 root cause fixed using factory of scala.runtime.*RefMiguel Garcia2013-04-271-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This commit does away with an error-prone division of labor between UnCurry and LambdaLift, a division of labor by which UnCurry had to anticipate under which circumstances LambdaLift creates a scala.runtime.*Ref whose initial value is given by a an expression including a Try in non-statement position. That sounds complicated, and it is. The solution so far (fixing SI-6863) is replaced by a simpler approach, at the cost of forward binary comptability with pre-2.11 releases, this time fixing the root cause of SI-6863. From now on, a s.r.*Ref is instantiated via invocation of a static factory method in the s.r.*Ref class in question. Unlike the code that was emitted so far (which involved NEW refclass, DUP, expr, INVOKESPECIAL refclass.<init>) the "expr" doesn't appear on the operand stack on top of the *Ref value being initialized. In other words, the *Ref initialization is in statement position provided "expr" is.
* | Merge pull request #2493 from paulp/pr/null-hardeningPaul Phillips2013-05-071-1/+2
|\ \ | | | | | | Hardening against nulls for deserialization.
| * | Hardening against nulls for deserialization.Paul Phillips2013-05-031-1/+2
| | | | | | | | | | | | | | | | | | When one attempts to populate data structures via deserialization, nulls tend to show up in unlikely or "impossible" places. Now there are a few fewer.
* | | Absolutized paths involving the scala package.Paul Phillips2013-05-03138-166/+305
|/ / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Confusing, now-it-happens now-it-doesn't mysteries lurk in the darkness. When scala packages are declared like this: package scala.collection.mutable Then paths relative to scala can easily be broken via the unlucky presence of an empty (or nonempty) directory. Example: // a.scala package scala.foo class Bar { new util.Random } % scalac ./a.scala % mkdir util % scalac ./a.scala ./a.scala:4: error: type Random is not a member of package util new util.Random ^ one error found There are two ways to play defense against this: - don't use relative paths; okay sometimes, less so others - don't "opt out" of the scala package This commit mostly pursues the latter, with occasional doses of the former. I created a scratch directory containing these empty directories: actors annotation ant api asm beans cmd collection compat concurrent control convert docutil dtd duration event factory forkjoin generic hashing immutable impl include internal io logging macros man1 matching math meta model mutable nsc parallel parsing partest persistent process pull ref reflect reify remote runtime scalap scheduler script swing sys text threadpool tools transform unchecked util xml I stopped when I could compile the main src directories even with all those empties on my classpath.
* | Merge pull request #2483 from adriaanm/merge-2.10.xPaul Phillips2013-05-021-1/+15
|\ \ | | | | | | Merge 2.10.x
| * \ Merge 2.10.x into masterAdriaan Moors2013-05-021-1/+15
| |\ \ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Conflicts: bincompat-forward.whitelist.conf src/compiler/scala/tools/nsc/matching/Patterns.scala src/compiler/scala/tools/nsc/transform/patmat/Logic.scala src/compiler/scala/tools/nsc/typechecker/Infer.scala src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala test/files/neg/t5663-badwarneq.check
| | * | SI-6675 Avoid spurious warning about pattern bind arity.Jason Zaugg2013-04-211-1/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In 692372ce, we added a warning (under -Xlint) when binding a `TupleN` in to a single pattern binder, which wasn't allowed before 2.10.0, and more often than not represents a bug. However, that warning overstretched, and warned even when using a Tuple Pattern to bind to the elements of such a value. This commit checks for this case, and avoids the spurious warnings. A new test case is added for this case to go with the existing test for SI-6675: $ ./tools/partest-ack 6675 % tests-with-matching-paths ... 3 % tests-with-matching-code ... 2 # 3 tests to run. test/partest --show-diff --show-log \ test/files/neg/t6675-old-patmat.scala \ test/files/neg/t6675.scala \ test/files/pos/t6675.scala \ "" Testing individual files testing: [...]/files/pos/t6675.scala [ OK ] Testing individual files testing: [...]/files/neg/t6675-old-patmat.scala [ OK ] testing: [...]/files/neg/t6675.scala [ OK ] All of 3 tests were successful (elapsed time: 00:00:03)
* | | | Route -explaintypes through reporter.Paul Phillips2013-04-293-4/+5
| |_|/ |/| | | | | | | | | | | | | | Sick of seeing Console printlns during partest runs. You should not print anything to Console.{out,err} if it's ever going to happen outside developerland.
* | | Merge pull request #2457 from paulp/pr/late-method-reduxJason Zaugg2013-04-261-6/+27
|\ \ \ | | | | | | | | Documented lateMETHOD flag.
| * | | Documented lateMETHOD flag.Paul Phillips2013-04-261-6/+27
| |/ / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A baby step toward its eventual elimination. WANTED, DEAD OR ALIVE For Heinous Crimes Against Efficiency and Scrutability lateDEFERRED lateFINAL lateINTERFACE lateMODULE notPROTECTED notPRIVATE notOVERRIDE lateMETHOD ON THE RUN lateMETHOD
* | | Merge pull request #2445 from magarciaEPFL/backendish3Paul Phillips2013-04-261-0/+2
|\ \ \ | | | | | | | | improvements, constructors phase (2nd attempt)
| * | | deprecation cycle for definitions.NPEConstructorMiguel Garcia2013-04-271-0/+3
| | | |
| * | | for null outer pointer, NPE via throw nullMiguel Garcia2013-04-241-1/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | As per the JVM spec, the athrow instruction throws a NullPointerException upon finding null on stack top. This commit takes advantage of that feature, to emit more compact code. The constructor of an inner class that receives an outer value first checks that value for nullness, depending on which NPE may be thrown. The code now emitted to achieve the above looks like: 0: aload_1 1: ifnonnull 6 4: aconst_null 5: athrow 6: ...
* | | | Merge pull request #2447 from paulp/pr/bynamePaul Phillips2013-04-261-0/+4
|\ \ \ \ | | | | | | | | | | Created utility function for dropping by-name-ness.
| * | | | Created utility function for dropping by-name-ness.Paul Phillips2013-04-251-0/+4
| | | | | | | | | | | | | | | | | | | | And applied it in three locations.
* | | | | Merge pull request #2452 from magarciaEPFL/backendish5Paul Phillips2013-04-261-8/+15
|\ \ \ \ \ | |_|_|/ / |/| | | | cleanup of old stuff from the GenJVM era
| * | | | role played by magic constant in ScalaSigBytesMiguel Garcia2013-04-261-0/+10
| | | | |
| * | | | removing remnants from the GenJVM eraMiguel Garcia2013-04-251-8/+5
| | | | |
* | | | | Merge pull request #2430 from paulp/issue/4365Adriaan Moors2013-04-261-8/+32
|\ \ \ \ \ | |/ / / / |/| | | | SI-4365 nondeterministic failure in asSeenFrom
| * | | | SI-4365 nondeterministic failure in asSeenFromPaul Phillips2013-04-221-8/+32
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Under some order-dependent conditions (if source files arrive in one order it happens, in the other order it does not) more than one set of type parameters are created for a given class. Previously this would lead to a crash in asSeenFrom when a type parameter had to be matched up with a type application. Now when that situation arises I compare them by name and log a dev warning if it hits. This does not risk anything undesirable happening because the wayward type parameter's owner is always the right class; it's only the class type parameters which don't include the wayward one. Since in a given type parameter list names are unique, we have enough information to salvage the search.
* | | | | Merge pull request #2436 from paulp/pr/lub-productionPaul Phillips2013-04-253-8/+39
|\ \ \ \ \ | |_|/ / / |/| | | | Minor overhaul of lub-producing typer methods.
| * | | | Minor overhaul of lub-producing typer methods.Paul Phillips2013-04-231-8/+31
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | There were a number of inefficiencies and unnecessary indirections in these methods. I beat them into better shape. Some highlights: - eliminated ptOrLub and similar. We must do something to suppress peoples' urge to tack a Boolean onto another method: these methods returned (Type, Boolean) and in addition to being horribly inefficient, it's vastly harder to follow the logic. Anything which can be written with a Boolean parameter or multi-value return can probably be written without the Boolean parameter and/or the multi-value return. - eliminated all the vars in the lub producing methods. Again, it's just a lot easier to understand code when I don't have to keep scanning up and down to see where and how previously declared names are being changed midstream. - added "sameWeakLubAsLub", which is the bit of information which was being tacked onto ptOrLub. This lets them all find out in advance whether the lub result implies further tree adaptation is necessary.
| * | | | Added orElse to Type.Paul Phillips2013-04-232-0/+8
| | | | | | | | | | | | | | | | | | | | | | | | | Tree and Symbol each have the analogous method, so consistency calls along with utility for putting it on Type.
* | | | | Merge branch 'master' into pr/warning-cleanupPaul Phillips2013-04-243-3/+15
|\ \ \ \ \ | | |_|/ / | |/| | | | | | | | | | | | | Conflicts: src/compiler/scala/tools/nsc/typechecker/Contexts.scala
| * | | | Merge pull request #2393 from retronym/ticket/7345-2Paul Phillips2013-04-243-3/+15
| |\ \ \ \ | | |/ / / | |/| | | SI-7345 Refactoring Contexts
| | * | | Merge remote-tracking branch 'origin/master' into ticket/7345-2Jason Zaugg2013-04-215-102/+80
| | |\ \ \ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Conflicts: src/compiler/scala/tools/nsc/typechecker/Contexts.scala src/compiler/scala/tools/nsc/typechecker/Typers.scala
| | * | | | SI-7345 Drive by refactoring of pattern matching for `arg: _*`.Jason Zaugg2013-04-212-2/+14
| | | | | |
| | * | | | SI-7345 Represent the boolean modes in Context in ContextMode.Jason Zaugg2013-04-211-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | - This is a value class in the same spirit of Mode. - Code that temporarily changes mode can be simplified by saving and restoring this one field.
* | | | | | Eliminated the accumulated feature warnings.Paul Phillips2013-04-236-6/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | No, this isn't busywork, how dare you suggest such a thing. I intend my tombstone to say HERE LIES EXTEMPORE, WHO ELIMINATED A LOT OF SIP-18 WARNINGS REST IN PEACE
* | | | | | Eliminate a pile of -Xlint warnings.Paul Phillips2013-04-236-17/+16
|/ / / / / | | | | | | | | | | | | | | | | | | | | | | | | | Some unused private code, unused imports, and points where an extra pair of parentheses is necessary for scalac to have confidence in our intentions.
* | | | | Merge pull request #2417 from paulp/pr/empty-type-boundsJason Zaugg2013-04-231-1/+8
|\ \ \ \ \ | |_|_|/ / |/| | | | Simplify type bounds.
| * | | | Simplify type bounds.Paul Phillips2013-04-201-1/+8
| | |/ / | |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | I started out looking to limit the noise from empty type bounds, i.e. the endless repetition of class A[T >: _root_.scala.Nothing <: _root_.scala.Any] This led me to be reminded of all the unnecessary and in fact damaging overreaches which are performed during parsing. Why should a type parameter for which no bounds are specified be immediately encoded with this giant tree: TypeBounds( Select(Select(Ident(nme.ROOTPKG), tpnme.scala_), tpnme.Nothing), Select(Select(Ident(nme.ROOTPKG), tpnme.scala_), tpnme.Any) ) ...which must then be manually recognized as empty type bounds? Truly, this is madness. - It deftly eliminates the possibility of recognizing whether the user wrote "class A[T]" or "class A[T >: Nothing]" or "class A[T <: Any]" or specified both bounds. The fact that these work out the same internally does not imply the information should be exterminated even before parsing completes. - It burdens everyone who must recognize type bounds trees, such as this author - It is far less efficient than the obvious encoding - It offers literally no advantage whatsoever Encode empty type bounds as TypeBounds(EmptyTree, EmptyTree) What could be simpler.
* | | | Merge pull request #2398 from huitseeker/silence_scaladoc_betterJason Zaugg2013-04-212-4/+4
|\ \ \ \ | | | | | | | | | | Change unrecognized scaladoc comments to C-style
| * | | | Change unrecognized scaladoc comments to C-styleFrançois Garillot2013-04-162-4/+4
| | |/ / | |/| |
* | | | SI-7324 jvm not cool with 255+ parametersPaul Phillips2013-04-211-1/+0
| |/ / |/| | | | | | | | Fail those monster methods rather than generating bad bytecode.
* | | Merge pull request #2380 from paulp/pr/reifier-ast-testAdriaan Moors2013-04-151-12/+36
|\ \ \ | | | | | | | | Reifier -> AST Node test.
| * | | Reifier -> AST Node test.Paul Phillips2013-04-091-12/+36
| | | | | | | | | | | | | | | | | | | | | | | | | | | | It's a Node-by-Node tour of the reifier's abilities and occasional foibles. That is one spectacularly attractive checkfile.
* | | | Merge pull request #2368 from retronym/ticket/7335Adriaan Moors2013-04-152-23/+20
|\ \ \ \ | | | | | | | | | | SI-7335 Simpler bootstrapping the standard library
| * | | | SI-7335 Remove special case for import of Predef._ in Predef.scalaJason Zaugg2013-04-131-19/+3
| | | | | | | | | | | | | | | | | | | | | | | | | Perhaps this once was problematic, but in our modern age we can bootstrap perfectly well with this import.
| * | | | SI-7335 Add logging for a now-impossible* case in Symbol#exists.Jason Zaugg2013-04-081-3/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * Impossible (to the best of my knowledge) because LowPriorityImplicits is now defined in Predef.scala. Were I more sure, we could trip an assertion here, rather than the devWarning.
| * | | | SI-7335 Don't import Predef._ in Predef.scalaJason Zaugg2013-04-081-7/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The check for this was foiled by the introduction of DeprecatedPredef in c26a8db0. This didn't cause any harm, but in any case this commit restores the intended state of affairs. The change is visible only through logging; no test case is included. qbin/scalac -Ydebug -Ylog:all src/library/scala/Predef.scala -Ystop-after:typer 2>&1 | grep -i "Omitted import of Predef" [log namer] Omitted import of Predef._ for Predef.scala [log typer] Omitted import of Predef._ for Predef.scala A redundant override of `firstDefinesClassOrObject` is also removed. Maybe we can remove the special case altogether?
* | | | | Merge remote-tracking branch 'origin/2.10.x' into ↵Jason Zaugg2013-04-153-67/+24
|\ \ \ \ \ | |_|_|/ / |/| | | / | | |_|/ | |/| | | | | | | | | | | | | | | | | | | | | | | | | | merge/v2.10.1-235-g4525e92-to-master Conflicts: bincompat-backward.whitelist.conf bincompat-forward.whitelist.conf src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala src/compiler/scala/tools/nsc/typechecker/Typers.scala src/reflect/scala/reflect/internal/Types.scala
| * | | Merge pull request #2367 from vigdorchik/si-6387-revertAdriaan Moors2013-04-091-24/+11
| |\ \ \ | | | | | | | | | | Revert "SI-6387 Clones accessor before name expansion"
| | * | | Revert "SI-6387 Clones accessor before name expansion"Eugene Vigdorchik2013-04-081-24/+11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This reverts commit 4e10b2c833fa846c68b81e94a08d867e7de656aa. Add 6387 test to pending and 7341 to up-to-date.
| * | | | Merge pull request #2354 from adriaanm/ticket-7289Adriaan Moors2013-04-091-7/+10
| |\ \ \ \ | | | | | | | | | | | | SI-7289 Less strict type application for TypeVar.
| | * | | | SI-7289 Less strict type application for TypeVar.Adriaan Moors2013-04-081-7/+10
| | |/ / / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When a type constructor variable is applied to the wrong number of arguments, return a new type variable whose instance is `ErrorType`. Dissection of the reported test case by @retronym: Define the first implicit: scala> trait Schtroumpf[T] defined trait Schtroumpf scala> implicit def schtroumpf[T, U <: Coll[T], Coll[X] <: Traversable[X]] | (implicit minorSchtroumpf: Schtroumpf[T]): Schtroumpf[U] = ??? schtroumpf: [T, U <: Coll[T], Coll[X] <: Traversable[X]](implicit minorSchtroumpf: Schtroumpf[T])Schtroumpf[U] Call it explicitly => kind error during type inference reported. scala> schtroumpf(null): Schtroumpf[Int] <console>:10: error: inferred kinds of the type arguments (Nothing,Int,Int) do not conform to the expected kinds of the type parameters (type T,type U,type Coll). Int's type parameters do not match type Coll's expected parameters: class Int has no type parameters, but type Coll has one schtroumpf(null): Schtroumpf[Int] ^ <console>:10: error: type mismatch; found : Schtroumpf[U] required: Schtroumpf[Int] schtroumpf(null): Schtroumpf[Int] ^ Add another implicit, and let implicit search weigh them up. scala> implicitly[Schtroumpf[Int]] <console>:10: error: diverging implicit expansion for type Schtroumpf[Int] starting with method schtroumpf implicitly[Schtroumpf[Int]] ^ scala> implicit val qoo = new Schtroumpf[Int]{} qoo: Schtroumpf[Int] = $anon$1@c1b9b03 scala> implicitly[Schtroumpf[Int]] <crash> Implicit search compares the two in-scope implicits in `isStrictlyMoreSpecific`, which constructs an existential type: type ET = Schtroumpf[U] forSome { type T; type U <: Coll[T]; type Coll[_] <: Traversable[_] } A subsequent subtype check `ET <:< Schtroumpf[Int]` gets to `withTypeVars`, which replaces the quantified types with type variables, checks conformance of that substitued underlying type against `Schtroumpf[Int]`, and then tries to solve the collected type constraints. The type var trace looks like: [ create] ?T ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]] ) [ create] ?U ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]] ) [ create] ?Coll ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]] ) [ setInst] Nothing ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]], T=Nothing ) [ setInst] scala.collection.immutable.Nil.type( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]], U=scala.collection.immutable.Nil.type ) [ setInst] =?scala.collection.immutable.Nil.type( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]], Coll==?scala.collection.immutable.Nil.type ) [ create] ?T ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]] ) [ setInst] Int ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]], T=Int ) [ create] ?T ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]] ) [ create] ?U ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]] ) [ create] ?Coll ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]] ) [ setInst] Nothing ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]], T=Nothing ) [ setInst] Int ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]], U=Int ) [ setInst] =?Int ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]], Coll==?Int ) The problematic part is when `?Int` (the type var originated from `U`) is registered as a lower bound for `Coll`. That happens in `solveOne`: for (tparam2 <- tparams) tparam2.info.bounds.hi.dealias match { case TypeRef(_, `tparam`, _) => log(s"$tvar addLoBound $tparam2.tpeHK.instantiateTypeParams($tparams, $tvars)") tvar addLoBound tparam2.tpeHK.instantiateTypeParams(tparams, tvars) case _ => }
| * | | | Merge pull request #2349 from scalamacros/ticket/6937Adriaan Moors2013-04-091-36/+2
| |\ \ \ \ | | |/ / / | |/| | | SI-6937 core type tags are no longer referentially unique
| | * | | SI-6937 core type tags are no longer referentially uniqueEugene Burmako2013-04-031-36/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Type tag factory used to evaluate the provided type creator in the context of the initial mirror in order to maintain referential equality of instances of standard tags. Unfortunately this evaluation might fail if the mirror provided doesn't contain the classes being referred to. Therefore I think we should avoid evaluating type creators there. Note that failure of evaluation doesn't mean that there's something bad going on. When one creates a type tag, the correct mirror / classloader to interpret that tag in might be unknown (like it happens here). This is okay, and this is exactly what the 2.10.0-M4 refactoring has addressed. Something like `res2.typeTag[A].in(currentMirror)` should be okay.