mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-02 11:22:19 +00:00
add proper error messages for ingested files
This commit is contained in:
parent
62fcc71be3
commit
e5b88366fe
5 changed files with 86 additions and 25 deletions
|
@ -757,10 +757,21 @@ pub fn build(
|
||||||
roc_run(&arena, opt_level, triple, args, bytes, expect_metadata)
|
roc_run(&arena, opt_level, triple, args, bytes, expect_metadata)
|
||||||
}
|
}
|
||||||
BuildAndRunIfNoErrors => {
|
BuildAndRunIfNoErrors => {
|
||||||
|
if problems.fatally_errored {
|
||||||
|
problems.print_to_stdout(total_time);
|
||||||
|
println!(
|
||||||
|
".\n\nCannot run program due to fatal error…\n\n\x1B[36m{}\x1B[39m",
|
||||||
|
"─".repeat(80)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Return a nonzero exit code due to falta problem
|
||||||
|
return Ok(problems.exit_code());
|
||||||
|
}
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(
|
||||||
problems.errors, 0,
|
problems.errors, 0,
|
||||||
"if there are errors, they should have been returned as an error variant"
|
"if there are non-fatal errors, they should have been returned as an error variant"
|
||||||
);
|
);
|
||||||
|
|
||||||
if problems.warnings > 0 {
|
if problems.warnings > 0 {
|
||||||
problems.print_to_stdout(total_time);
|
problems.print_to_stdout(total_time);
|
||||||
println!(
|
println!(
|
||||||
|
|
|
@ -4186,9 +4186,11 @@ pub fn with_hole<'a>(
|
||||||
Layout::STR,
|
Layout::STR,
|
||||||
hole,
|
hole,
|
||||||
),
|
),
|
||||||
_ => unreachable!(
|
_ => {
|
||||||
"All of these cases should be dealt during solve, generating proper errors"
|
// This will not manifest as a real runtime error and is just returned to have a value here.
|
||||||
),
|
// The actual type error during solve will be fatal.
|
||||||
|
runtime_error(env, "Invalid type for ingested file")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SingleQuote(_, _, character, _) => {
|
SingleQuote(_, _, character, _) => {
|
||||||
|
|
|
@ -1771,7 +1771,7 @@ fn solve(
|
||||||
|
|
||||||
state
|
state
|
||||||
}
|
}
|
||||||
IngestedFile(type_index, _, bytes) => {
|
IngestedFile(type_index, file_path, bytes) => {
|
||||||
let actual = either_type_index_to_var(
|
let actual = either_type_index_to_var(
|
||||||
subs,
|
subs,
|
||||||
rank,
|
rank,
|
||||||
|
@ -1794,34 +1794,37 @@ fn solve(
|
||||||
) {
|
) {
|
||||||
// List U8 always valid.
|
// List U8 always valid.
|
||||||
subs.rollback_to(snapshot);
|
subs.rollback_to(snapshot);
|
||||||
state
|
return state;
|
||||||
} else if let Success { .. } = unify(
|
}
|
||||||
|
subs.rollback_to(snapshot);
|
||||||
|
|
||||||
|
let snapshot = subs.snapshot();
|
||||||
|
// We explicitly match on the last unify to get the type in the case it errors.
|
||||||
|
match unify(
|
||||||
&mut UEnv::new(subs),
|
&mut UEnv::new(subs),
|
||||||
actual,
|
actual,
|
||||||
Variable::STR,
|
Variable::STR,
|
||||||
Mode::EQ,
|
Mode::EQ,
|
||||||
Polarity::OF_VALUE,
|
Polarity::OF_VALUE,
|
||||||
) {
|
) {
|
||||||
// Str only valid if valid utf8.
|
Success { .. } => {
|
||||||
if std::str::from_utf8(bytes).is_err() {
|
// Str only valid if valid utf8.
|
||||||
todo!("add type error due to not being a utf8 string");
|
if let Err(err) = std::str::from_utf8(bytes) {
|
||||||
|
let problem = TypeError::IngestedFileBadUtf8(file_path.clone(), err);
|
||||||
|
problems.push(problem);
|
||||||
|
}
|
||||||
|
|
||||||
|
subs.rollback_to(snapshot);
|
||||||
|
state
|
||||||
}
|
}
|
||||||
|
Failure(_, actual_type, _, _) => {
|
||||||
|
subs.rollback_to(snapshot);
|
||||||
|
|
||||||
subs.rollback_to(snapshot);
|
let problem =
|
||||||
state
|
TypeError::IngestedFileUnsupportedType(file_path.clone(), actual_type);
|
||||||
} else {
|
problems.push(problem);
|
||||||
// Unexpected type.
|
state
|
||||||
todo!("Add type error for unsupported ingested file type");
|
}
|
||||||
// let problem = TypeError::BadExpr(
|
|
||||||
// *region,
|
|
||||||
// Category::Lookup(*symbol),
|
|
||||||
// actual_type,
|
|
||||||
// expectation.replace_ref(expected_type),
|
|
||||||
// );
|
|
||||||
|
|
||||||
// problems.push(problem);
|
|
||||||
// subs.rollback_to(snapshot);
|
|
||||||
// state
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
//! Provides types to describe problems that can occur during solving.
|
//! Provides types to describe problems that can occur during solving.
|
||||||
|
use std::{path::Path, str::Utf8Error};
|
||||||
|
|
||||||
use roc_can::expected::{Expected, PExpected};
|
use roc_can::expected::{Expected, PExpected};
|
||||||
use roc_module::{ident::Lowercase, symbol::Symbol};
|
use roc_module::{ident::Lowercase, symbol::Symbol};
|
||||||
use roc_problem::{can::CycleEntry, Severity};
|
use roc_problem::{can::CycleEntry, Severity};
|
||||||
|
@ -29,6 +31,8 @@ pub enum TypeError {
|
||||||
expected_opaque: Symbol,
|
expected_opaque: Symbol,
|
||||||
found_opaque: Symbol,
|
found_opaque: Symbol,
|
||||||
},
|
},
|
||||||
|
IngestedFileBadUtf8(Box<Path>, Utf8Error),
|
||||||
|
IngestedFileUnsupportedType(Box<Path>, ErrorType),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeError {
|
impl TypeError {
|
||||||
|
@ -48,6 +52,8 @@ impl TypeError {
|
||||||
TypeError::Exhaustive(exhtv) => exhtv.severity(),
|
TypeError::Exhaustive(exhtv) => exhtv.severity(),
|
||||||
TypeError::StructuralSpecialization { .. } => RuntimeError,
|
TypeError::StructuralSpecialization { .. } => RuntimeError,
|
||||||
TypeError::WrongSpecialization { .. } => RuntimeError,
|
TypeError::WrongSpecialization { .. } => RuntimeError,
|
||||||
|
TypeError::IngestedFileBadUtf8(..) => Fatal,
|
||||||
|
TypeError::IngestedFileUnsupportedType(..) => Fatal,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -209,6 +209,45 @@ pub fn type_problem<'b>(
|
||||||
severity,
|
severity,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
IngestedFileBadUtf8(file_path, utf8_err) => {
|
||||||
|
let stack = [
|
||||||
|
alloc.concat([
|
||||||
|
alloc.reflow("Failed to load "),
|
||||||
|
alloc.text(format!("{:?}", file_path)),
|
||||||
|
alloc.reflow(" as Str:"),
|
||||||
|
]),
|
||||||
|
alloc.text(format!("{}", utf8_err)),
|
||||||
|
];
|
||||||
|
Some(Report {
|
||||||
|
title: "INVALID UTF-8".to_string(),
|
||||||
|
filename,
|
||||||
|
doc: alloc.stack(stack),
|
||||||
|
severity,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
IngestedFileUnsupportedType(file_path, typ) => {
|
||||||
|
let stack = [
|
||||||
|
alloc.concat([
|
||||||
|
alloc.text(format!("{:?}", file_path)),
|
||||||
|
alloc.reflow(" is annotated to be a "),
|
||||||
|
alloc.inline_type_block(error_type_to_doc(alloc, typ)),
|
||||||
|
alloc.reflow("."),
|
||||||
|
]),
|
||||||
|
alloc.concat([
|
||||||
|
alloc.reflow("Ingested files can only be of type "),
|
||||||
|
alloc.type_str("List U8"),
|
||||||
|
alloc.reflow(" or "),
|
||||||
|
alloc.type_str("Str"),
|
||||||
|
alloc.reflow("."),
|
||||||
|
]),
|
||||||
|
];
|
||||||
|
Some(Report {
|
||||||
|
title: "INVALID TYPE FOR INGESTED FILE".to_string(),
|
||||||
|
filename,
|
||||||
|
doc: alloc.stack(stack),
|
||||||
|
severity,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue