Is there any way to ignore warnings for a single line?

I’m trying to write a deep clone function like so:

let deepClone = (obj: 'a): 'a => %raw(`
  JSON.parse(JSON.stringify(obj))
`); 

let line1 = {"p0": {"x": 5, "y": 10}, "p1": {"x": 20, "y": 30}}
let line2 = deepClone(line1)

The playground gives me the following warning:

[W] Line 1, column 17:
unused variable obj.

The docs about @@warning say that it modifies the enabled warnings for the entire module. Is there any way this could be restricted to a single line?

1 Like

why not just

let deepClone = (_obj: 'a): 'a => %raw(`
  JSON.parse(JSON.stringify(_obj))
`); 

?

1 Like

@flo-pereira’s solution is probably the better one, but generally you can deactivate the warning for as many lines as you want and then activate it again:

@@warning("-27")

let deepClone = (obj: 'a): 'a => %raw(`
  JSON.parse(JSON.stringify(obj))
`); 

@@warning("+27")
3 Likes

you can also just define the whole function in JS:

let deepClone = %raw(`function(obj){
  return JSON.parse(JSON.stringify(obj));
}`); 
1 Like

Thanks for all of the suggestions. I’m going to go with the _obj solution since it avoids having to use @@warning. The %raw(`function(obj){...}`) solution has the unfortunate side-effect that return values are typed as 'a instead of preserve the type of the argument.

1 Like

Alternatively you could use Obj.magic in the middle (to bypass the option return type on stringifyAny) and avoid %raw completely :man_shrugging:

https://rescript-lang.org/try?code=DYUwLgBAJiIA4GFgHsB2IIF4IEMsD5cBafAKQGcA6CtS8sAJwEtUBzJgMwE8BBVLkgHkARgCtKAWxzsAxiQrVytODgbkQAUQAeqANwAofaEjAWIAIxYIAbwBEcAAy2AXDdtaXEAKwAaCLa5PcwcAXz97c087D1cAJgdwwNcAZlCQo3AIU3RYqxh4JDQQAApsiwBKIA

There’s also a->Js.Json.serializeExn->Js.Json.parseExn which avoids magic completely but it’s not a zero cost binding, it calls a wrapper function.

Going off of the example above for disabling a warning for a line, I tried the following:

@@warning("-32")
let foo = 4
@@warning("+32")
let bar = 3

but the warning is not re-enabled. It just stays disabled. It should show a warning for let bar = 3 as unused.

(Warning 32 is “Unused value declaration” - Warning Numbers | ReScript Language Manual)

Is this a bug?

If you have no interface file or if bar is in the interface file then you’ll have no such warning.

Not sure I quite understand.

let foo = 4
let bar = 3

are just in a vanilla .res file. If i have them without the @@warning set, then I get warnings of foo is never used and bar is never used, which is what I would expect. But if I have them as i posted above with the @@warning set, then I get no warnings for either being unused. I would have expected it to give me a warning of bar is never used since i re-enabled the warning?

To answer your original question, yes you can disable a warning for a specific line:

@warning("-27")
let deepClone = (obj: 'a): 'a => %raw(`
  JSON.parse(JSON.stringify(obj))
`); 
2 Likes

Oh, thanks. :+1:
I just checked and the @warning with a single @ doesnt seem to be listed on the Syntax Lookup or the Warning Numbers | ReScript Language Manual page. :thinking:
But yeah that works.

You are right, this one is missing.

But I added it now: Syntax lookup: Add @warning by fhammerschmidt · Pull Request #676 · rescript-association/rescript-lang.org · GitHub

1 Like

Just merged the change. Thanks for bringing this up!

1 Like

if you have it in the toplevel of your .res file without interface file, then those values will be exported and no warning about unused value will be shown, see for example:

module Foo: {
  let baz: int
} = {
  @@warning("-32")
  let foo = 4
  @@warning("+32")
  // bar will raise a warning here
  let bar = 3
  let baz = 5
}

module Foo2 = {
  // no warnings here
  let foo2 = 4
  let bar2 = 3
}
1 Like