This is similar to my question in How can I resolve sorbet error: "Use of undeclared variable"?, but for constants.
I am experimenting with adding sorbet type information to my gem, pdf-reader. I don't want sorbet to be a runtime dependency for the gem, so all type annotations are in an external file in the rbi/ directory. I also can't extend T::Sig in my classes, and I can't use T.let in my code.
I'd like to enable typed: strict in some files, but doing so flags that constants don't have type annotations:
$ be srb tc
./lib/pdf/reader/buffer.rb:41: Constants must have type annotations with T.let when specifying # typed: strict https://srb.help/7027
41 | TOKEN_WHITESPACE=[0x00, 0x09, 0x0A, 0x0C, 0x0D, 0x20]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Autocorrect: Use `-a` to autocorrect
./lib/pdf/reader/buffer.rb:41: Replace with T.let([0x00, 0x09, 0x0A, 0x0C, 0x0D, 0x20], T::Array[Integer])
41 | TOKEN_WHITESPACE=[0x00, 0x09, 0x0A, 0x0C, 0x0D, 0x20]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
./lib/pdf/reader/buffer.rb:42: Constants must have type annotations with T.let when specifying # typed: strict https://srb.help/7027
42 | TOKEN_DELIMITER=[0x25, 0x3C, 0x3E, 0x28, 0x5B, 0x7B, 0x29, 0x5D, 0x7D, 0x2F]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Autocorrect: Use `-a` to autocorrect
./lib/pdf/reader/buffer.rb:42: Replace with T.let([0x25, 0x3C, 0x3E, 0x28, 0x5B, 0x7B, 0x29, 0x5D, 0x7D, 0x2F], T::Array[Integer])
42 | TOKEN_DELIMITER=[0x25, 0x3C, 0x3E, 0x28, 0x5B, 0x7B, 0x29, 0x5D, 0x7D, 0x2F]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
./lib/pdf/reader/buffer.rb:55: Constants must have type annotations with T.let when specifying # typed: strict https://srb.help/7027
55 | WHITE_SPACE = [LF, CR, ' ']
^^^^^^^^^^^^^
Autocorrect: Use `-a` to autocorrect
./lib/pdf/reader/buffer.rb:55: Replace with T.let([LF, CR, ' '], T::Array[String])
55 | WHITE_SPACE = [LF, CR, ' ']
^^^^^^^^^^^^^
Errors: 3
The proposed fix is to use T.let(). However I can't do that because it requires a runtime dependency on sorbet.
I tried using T.let() in my RBI file, similar to how we solved the instance variable issue in the linked question. However, that seems to have no effect for this error:
diff --git a/rbi/pdf-reader.rbi b/rbi/pdf-reader.rbi
index 113f183..f392b0a 100644
--- a/rbi/pdf-reader.rbi
+++ b/rbi/pdf-reader.rbi
@@ -81,7 +81,7 @@ module PDF
CR = "\r"
LF = "\n"
CRLF = "\r\n"
- WHITE_SPACE = [LF, CR, ' ']
+ WHITE_SPACE = T.let(T.unsafe(nil), T::Array[String])
TRAILING_BYTECOUNT = 5000
sig { returns(Integer) }
Extra Research
Interestingly, if I change the T.let() in the RBI file to something obviously wrong like:
diff --git a/rbi/pdf-reader.rbi b/rbi/pdf-reader.rbi
index 113f183..251d80d 100644
--- a/rbi/pdf-reader.rbi
+++ b/rbi/pdf-reader.rbi
@@ -81,7 +81,7 @@ module PDF
CR = "\r"
LF = "\n"
CRLF = "\r\n"
- WHITE_SPACE = [LF, CR, ' ']
+ WHITE_SPACE = T.let(T.unsafe(nil), T::Array[Integer])
TRAILING_BYTECOUNT = 5000
sig { returns(Integer) }
Then I get a type error:
$ srb tc
./lib/pdf/reader/buffer.rb:55: Expected T::Array[Integer] but found T::Array[String] for field https://srb.help/7013
55 | WHITE_SPACE = [LF, CR, " "]
^^^^^^^^^^^^^
Expected T::Array[Integer] for field defined here:
./lib/pdf/reader/buffer.rb:55:
55 | WHITE_SPACE = [LF, CR, " "]
^^^^^^^^^^^
Got T::Array[String] originating from:
./lib/pdf/reader/buffer.rb:55:
55 | WHITE_SPACE = [LF, CR, " "]
^^^^^^^^^^^^^
It seems like T.let() for constants in an RBI file isn't ignored, but it's not enough to satisfy the strict requirement for the type of constants to be defined.