`Error: request to generate code for .compileTime proc` - compile-time

I have a small helper proc that is supposed to tell me at compile-time whether a type is an object-type or not.
func isObject*[T](val: typedesc[T]): bool {.compileTime.} = T is (object or ref object)
However, when I call this proc with a simple echo to see whether it works, I receive an error:
type A = object
echo isObject(A)
Error: request to generate code for .compileTime proc: isObject
Why is that? It should be perfectly valid to just call this, isObject should just compile to true and in the end what's written there is echo true, why does this cause this cryptic error?

The problem here is that runtime code (The echo call) is trying to work with a compiletime proc.
That is not valid, as the compiler would not replace the function-call with its result, but try to actually call the function at runtime instead. The compiler knows this is invalid behaviour and thus prohibits it by throwing an error, albeit one that isn't that useful.
The only way this can be allowed is if you store the result of the compile-time proc in a compile-time variable, aka a const. These are allowed to be used at runtime.
So the calling code would look more like this instead:
type A = object
const x = isObject(A)
echo x
EDIT:
As Elegantbeef pointed out on nim's discord:
Another alternative is to just do what I thought would happen initially and have that isObject(A) call evaluate fully at compile-time, so that at runtime it goes away and all that's left is it's result, true.
To do so, just use static:
type A = object
echo static(isObject(A))

Related

Luau Error "Recursive type being used with different parameters" when there is no recursion

With Luau 0.550, getting this error: TypeError: Recursive type being used with different parameters on the code below. There's no recursion, and somehow removing setmetatable() fixes the problem (but I need to do it in my integration example).
--!strict
local __: Observable<any> -- recursive type error on this line, but there's no type recursion!
-- false positive happens on any function call, is resolved if I delete the setmetatable function call
local _ = setmetatable({}, {})
export type Observable<K> = any
This is a bug in (at least) 0.550 and prior where any function call between the use of the generic type and the declaration of the generic type triggers this false positive warning. The workaround, for now, is to re-order the type declaration and the use.
--!strict
export type Observable<K> = any -- manually hoisting this line fixes the issue
local __: Observable<any>
local _ = setmetatable({}, {})
If you needed to order these things differently -- for instance, if your generic type declaration used a typeof() on its assignment and therefore needs to be declared post-use -- you are simply out of luck right now. Your best bet is to hoist the declaration and use a less specific type shape (but still avoiding any if possible):
--!strict
type Object = { [string]: unknown }
export type Observable<K> = Object -- loses most safety, workaround for Luau bug
local __: Observable<any>
local _ = someFunctionCall()

Why is Dafny allowing uninitialized return result?

In this method:
datatype Results = Foo | Bar
method test() returns (r:Result)
{
}
Dafny verifies OK and test() returns Foo. Which is technically correct (it does return a value of the correct type) however I was expecting Dafny to complain that the result has not been set by the method itself. What test() is doing is similar to doing:
return;
in a C function that is supposed to return an int.
Is there a way to make Dafny verify that a methods results are always set before the method returns?
The flag you want is /definiteAssignment:2:
/definiteAssignment:<n>
0 - ignores definite-assignment rules; this mode is for testing only--it is
not sound
1 (default) - enforces definite-assignment rules for compiled variables and fields
whose types do not support auto-initialization and for ghost variables
and fields whose type is possibly empty
2 - enforces definite-assignment for all non-yield-parameter
variables and fields, regardless of their types
3 - like 2, but also performs checks in the compiler that no nondeterministic
statements are used; thus, a program that passes at this level 3 is one
that the language guarantees that values seen during execution will be
the same in every run of the program
This is what Dafny says on your code says with that flag:
test.dfy(5,0): Error: out-parameter 'r', which is subject to definite-assignment rules, might be uninitialized at this return point

Nullability mismatch in simple assignment after switching to sound null safety

I switched to sound null safety and started getting runtime error in a simple assignment, that should never happen with sound null safety:
final widgetOnPressed = widget.onPressed;
Error:
type '(LogData) => void' is not a subtype of type '((LogData?) => void)?'
I can repro it for Flutter versions 2.12.0-4.1.pre and 2.13.0-0.0.pre.505.
PR: https://github.com/flutter/devtools/pull/3971
Failing line: https://github.com/flutter/devtools/blob/9fc560ff2e6749459e2ca6a1dc00bf6fb16ed93b/packages/devtools_app/lib/src/shared/table.dart#L1184
To repro, start DevTools at this PR for macos, connect to an app and click the tab 'Logging'. DevTools will show red screen and error in console.
Is it dart bug or the app bug? If it is the app bug, how can I debug it?
It's a bug in your code.
You didn't say which kind of error you got - a compile-time error or a runtime error. I'm guessing runtime error. (Well, you did say to launch it in the debugger, so that is a good hint too.)
The line final widgetOnPressed = widget.onPressed; looks like it can't possibly fail. After all, the type of the local variable is inferred from the expression assigned to it, and the runtime value of that expression will surely be a subtype of the static type because the type system is sound!
Isn't it? ISN'T IT?
It's not, sorry. Dart 2's type system is mostly sound, even more so with null safety, but class generics is covariant, which can still be unsound. It's fairly hard to hit one of the cases where that unsoundness shows its ugly head, but returning a function where the argument type is the class's type variable is one.
Your state class extends State<TableRow<T?>>, so the widget getter returns a TableRow<T?>. The onPressed of that type has type ItemCallback<T?>?, aka, void Function(T?)?.
You create a _TableRowState<LogData>, with its widget which has static type TableRow<LogData?>, but you somehow manage to pass it a TableRow<LogData> instead. That's fine. Class generics are covariant, so all is apparently fine at compile-time.
Then you do final widgetOnPressed = widget.onPressed;.
The static type of widgetOnPressed is void Function(LogData?) here.
The actual runtime type of onPressed is void Function(LogData) because it's from a TableRow<LogData>.
A void Function(LogData) is-not-a void Function(LogData?) because the former cannot be used in all places where the latter can (in particular, it can't be used in a place where it's called with null).
This assignment is potentially unsound, and actually unsound in this case. The compiler knows this and inserts an extra check to ensure that you don't assign a value to the variable which isn't actually valid. That check triggers and throws the error you see.
How do you avoid that?
Don't create a TableRow<LogData> where a TableRow<LogData?> is required.
Or type the variable as:
final ItemCallback<T>? widgetOnPressed = widget.onPressed;
(no ? on the T).
Or rewrite everything to avoid returning a function with a covariant type parameter (from the class) occurring contra-variantly (as an argument type).
Which solution fits you depends on what you want to be able to do.

How does null assertion work in dart and when can I use it?

Can someone simply explain to me how null assertion (!) works and when to use it?
The ! operator can be used after any expression, e!.
That evaluates the expression e to value v, then checks whether v is the null value. If it is null, an error is thrown. If not, then e! also evaluates to v.
The static type of an expression e! is (basically) the static type of e with any trailing ?s remove. So, if e has type int?, the type of e! is int.
You should not use e! unless e can be null (the type of e is potentially nullable).
The ! operator is dynamically checked. It can throw at runtime, and there is no static check which can guarantee that it won't. It's like using a value with type dynamic in that all the responsibility of preventing it from throwing is on the author, the compiler can't help you, and you need good tests to ensure that it won't throw when it's not supposed to.
It's called an assertion because it should never throw in production code.
So, use e! when you know (for some reason not obvious to the compiler, perhaps because of some invariant guaranteeing that the value is not null while something else is true) that e is not null.
Example:
abstract class Box<T extends Object> {
bool hasValue;
T? get value;
}
...
Box<int> box = ...;
if (box.hasValue) {
var value = box.value!;
... use value ...
}
If you are repeatedly using ! on the same expression, do consider whether it's more efficient to read it into a local variable just once.
Also, if (like this Box example) the value being null is equivalent to the other test you just did, maybe just check that directly:
Box<int> box = ...;
var value = box.value;
if (value != null) {
... use value ...
}
This code, with an explicit != null check on a local variable, is statically guaranteed to not throw because the value is null.
The code using ! above relies on the author to maintain whichever invariant allowed them to write the !, and if something changes, the code might just start throwing at runtime. You can't tell whether it's safe just by looking at the code locally.
Use ! sparingly, just like the dynamic type and late declarations, because they're ways to side-step the compiler's static checking and ensure it that "this is going to be fine". That's a great feature when you need it, but it's a risk if you use it unnecessarily.

Using Xcode, Swift, and GRDB, why do I have to unwrap DatabaseQueue? before I can use its methods?

I'm using the GRDB library to integrate SQLite with my iOS application project. I declared a DatabaseQueue object in AppDelegate.swift like so:
var DB : DatabaseQueue!
In the same file, I had provided a function for connecting the above object to a SQLite database which is called when the app starts running. I had been able to use this in one of my controllers without problems (as in, the app doesn't have problems running using the database I connected to it), like so:
var building : Building?
do {
try DB.write { db in
let building = Building.fetchOne(db, "SELECT * FROM Building WHERE number = ?", arguments: [bldgNumber])
}
} catch {
print(error)
}
However, in another controller, the same construct is met with an error,
Value of optional type 'DatabaseQueue?' must be unwrapped to refer to member 'write' of wrapped base type 'DatabaseQueue'
with the only difference (aside from the code, of course) being that there are return statements inside the do-catch block, as the latter is inside a function (tableView for numberOfRowsInSection) that is supposed to return an integer. The erroneous section of code is shown below.
var locsCountInFloor : Int
do {
try DB.write { db in
if currentBuilding!.hasLGF == true {
locsCountInFloor = IndoorLocation.filter(bldg == currentBuilding! && level == floor).fetchCount(db)
} else {
locsCountInFloor = IndoorLocation.filter(bldg == currentBuilding! && level == floor + 1).fetchCount(db)
}
return locsCountInFloor
}
} catch {
return 0
}
Any help would be greatly appreciated!
As is often the case when you have a problem with a generic type in Swift, the error message is not helpful.
Here’s the real problem:
DB.write is generic in its argument and return type. It has a type parameter T. The closure argument’s return type is T, and the write method itself returns T.
The closure you’re passing is more than a single expression. It is a multi-statement closure. Swift does not deduce the type of a multi-statement closure from the statements in the closure. This is just a limitation of the compiler, for practical reasons.
Your program doesn’t specify the type T explicitly or otherwise provide constraints that would let Swift deduce the concrete type.
These characteristics of your program mean Swift doesn’t know concrete type to use for T. So the compiler’s type checker/deducer fails. You would expect to get an error message about this problem. (Possibly an inscrutable message, but presumably at least relevant).
But that’s not what you get, because you declared DB as DatabaseQueue!.
Since DB is an implicitly-unwrapped optional, the type checker handles it specially by (as you might guess) automatically unwrapping it if doing so makes the statement type-check when the statement would otherwise not type-check. In all other ways, the type of DB is just plain DatabaseQueue?, a regular Optional.
In this case, the statement won’t type-check even with automatic unwrapping, because of the error I described above: Swift can’t deduce the concrete type to substitute for T. Since the statement doesn’t type-check either way, Swift doesn’t insert the unwrapping for you. Then it carries on as if DB were declared DatabaseQueue?.
Since DatabaseQueue? doesn’t have a write method (because Optional doesn’t have a write method), the call DB.write is erroneous. So Swift wants to print an error message. But it “helpfully” sees that the wrapped type, DatabaseQueue, does have a write method. And by this point it has completely forgotten that DB was declared implicitly-unwrapped. So it tells you to unwrap DB to get to the write method, even though it would have done that automatically if it hadn’t encountered another error in this statement.
So anyway, you need to tell Swift what type to use for T. I suspect you meant to say this:
var locsCountInFloor: Int
do {
locsCountInFloor = try DB.write { db in
...
Assigning the result of the DB.write call to the outer locsCountInFloor is sufficient to fix the error, because you already explicitly defined the type of locsCountInFloor. From that, Swift can deduce the return type of this call to DB.write, and from that the type of the closure.

Resources