Skip to content

Commit dd51311

Browse files
committed
Improve reporting of HackC unit compilation errors
hackc_compile() calls into Rust via hackc::compile_unit_from_text(). This may return a Rust error that cxxbridge then throws as a C++ exception extending `std::exception`, causing cryptic errors. For example, after D80369513 / facebook@587ab58, trying to run the below Hack file: ```hack <<__EntryPoint>> function foo(): void { $bar = @file_get_contents('foo.txt'); } ``` returns in an error like: ``` (non-standard exception "N4rust10cxxbridge15ErrorE" was thrown) ``` So, catch and return exceptions during unit compilation. This produces a more friendly error for the above file: ``` Fatal error: Unhandled Emitter error: Unrecoverable: Unexpected Silence operator '@' in /home/mszabo/at.hack on line -1 ```
1 parent 35d16dc commit dd51311

1 file changed

Lines changed: 27 additions & 21 deletions

File tree

hphp/runtime/vm/unit-parser.cpp

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "hphp/runtime/vm/unit-parser.h"
1818

1919
#include <memory>
20+
#include <stdexcept>
2021
#include <string>
2122

2223
#include <folly/compression/Zstd.h>
@@ -117,29 +118,34 @@ CompilerResult hackc_compile(
117118
}
118119
}
119120

120-
rust::Box<hackc::UnitWrapper> unit_wrapped = [&] {
121-
tracing::Block _{
122-
"hackc_translator",
123-
[&] {
124-
return tracing::Props{}
125-
.add("filename", filename ? filename : "")
126-
.add("code_size", code.size());
127-
}
128-
};
129-
return hackc::compile_unit_from_text(
130-
native_env,
131-
{(const uint8_t*)code.data(), code.size()}
132-
);
133-
}();
121+
try {
122+
rust::Box<hackc::UnitWrapper> unit_wrapped = [&] {
123+
tracing::Block _{
124+
"hackc_translator",
125+
[&] {
126+
return tracing::Props{}
127+
.add("filename", filename ? filename : "")
128+
.add("code_size", code.size());
129+
}
130+
};
131+
return hackc::compile_unit_from_text(
132+
native_env,
133+
{(const uint8_t*)code.data(), code.size()}
134+
);
135+
}();
134136

135-
auto const bcSha1 = SHA1(hash_unit(*unit_wrapped));
136-
const hackc::hhbc::Unit* unit = hackCUnitRaw(unit_wrapped);
137+
auto const bcSha1 = SHA1(hash_unit(*unit_wrapped));
138+
const hackc::hhbc::Unit* unit = hackCUnitRaw(unit_wrapped);
137139

138-
auto hackCResult = unitEmitterFromHackCUnitHandleErrors(
139-
*unit, filename, sha1, bcSha1, extension,
140-
internal_error, mode, options.packageInfo()
141-
);
142-
return hackCResult;
140+
auto hackCResult = unitEmitterFromHackCUnitHandleErrors(
141+
*unit, filename, sha1, bcSha1, extension,
142+
internal_error, mode, options.packageInfo()
143+
);
144+
return hackCResult;
145+
} catch (const std::exception& ex) {
146+
// Report Rust errors from compile_unit_from_text().
147+
return ex.what();
148+
}
143149
}
144150

145151
/// A simple UnitCompiler that invokes hackc in-process.

0 commit comments

Comments
 (0)