mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Report builtins type errors during load building as appropriate
This commit is contained in:
parent
a90d9d465d
commit
03e6d6d7e0
5 changed files with 142 additions and 123 deletions
|
@ -6,6 +6,7 @@ use roc_load::{EntryPoint, ExpectMetadata, LoadedModule, MonomorphizedModule};
|
||||||
use roc_module::symbol::{Interns, ModuleId};
|
use roc_module::symbol::{Interns, ModuleId};
|
||||||
use roc_mono::ir::OptLevel;
|
use roc_mono::ir::OptLevel;
|
||||||
use roc_region::all::LineInfo;
|
use roc_region::all::LineInfo;
|
||||||
|
use roc_reporting::cli::report_problems;
|
||||||
use roc_solve_problem::TypeError;
|
use roc_solve_problem::TypeError;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
@ -21,7 +22,7 @@ pub struct CodeGenTiming {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn report_problems_monomorphized(loaded: &mut MonomorphizedModule) -> Problems {
|
pub fn report_problems_monomorphized(loaded: &mut MonomorphizedModule) -> Problems {
|
||||||
report_problems_help(
|
report_problems(
|
||||||
loaded.total_problems(),
|
loaded.total_problems(),
|
||||||
&loaded.sources,
|
&loaded.sources,
|
||||||
&loaded.interns,
|
&loaded.interns,
|
||||||
|
@ -31,7 +32,7 @@ pub fn report_problems_monomorphized(loaded: &mut MonomorphizedModule) -> Proble
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn report_problems_typechecked(loaded: &mut LoadedModule) -> Problems {
|
pub fn report_problems_typechecked(loaded: &mut LoadedModule) -> Problems {
|
||||||
report_problems_help(
|
report_problems(
|
||||||
loaded.total_problems(),
|
loaded.total_problems(),
|
||||||
&loaded.sources,
|
&loaded.sources,
|
||||||
&loaded.interns,
|
&loaded.interns,
|
||||||
|
@ -40,123 +41,6 @@ pub fn report_problems_typechecked(loaded: &mut LoadedModule) -> Problems {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
|
|
||||||
pub struct Problems {
|
|
||||||
pub errors: usize,
|
|
||||||
pub warnings: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Problems {
|
|
||||||
pub fn exit_code(&self) -> i32 {
|
|
||||||
// 0 means no problems, 1 means errors, 2 means warnings
|
|
||||||
if self.errors > 0 {
|
|
||||||
1
|
|
||||||
} else {
|
|
||||||
self.warnings.min(1) as i32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn report_problems_help(
|
|
||||||
total_problems: usize,
|
|
||||||
sources: &MutMap<ModuleId, (PathBuf, Box<str>)>,
|
|
||||||
interns: &Interns,
|
|
||||||
can_problems: &mut MutMap<ModuleId, Vec<roc_problem::can::Problem>>,
|
|
||||||
type_problems: &mut MutMap<ModuleId, Vec<TypeError>>,
|
|
||||||
) -> Problems {
|
|
||||||
use roc_reporting::report::{
|
|
||||||
can_problem, type_problem, Report, RocDocAllocator, Severity::*, DEFAULT_PALETTE,
|
|
||||||
};
|
|
||||||
let palette = DEFAULT_PALETTE;
|
|
||||||
|
|
||||||
// This will often over-allocate total memory, but it means we definitely
|
|
||||||
// never need to re-allocate either the warnings or the errors vec!
|
|
||||||
let mut warnings = Vec::with_capacity(total_problems);
|
|
||||||
let mut errors = Vec::with_capacity(total_problems);
|
|
||||||
|
|
||||||
for (home, (module_path, src)) in sources.iter() {
|
|
||||||
let mut src_lines: Vec<&str> = Vec::new();
|
|
||||||
|
|
||||||
src_lines.extend(src.split('\n'));
|
|
||||||
|
|
||||||
let lines = LineInfo::new(&src_lines.join("\n"));
|
|
||||||
|
|
||||||
// Report parsing and canonicalization problems
|
|
||||||
let alloc = RocDocAllocator::new(&src_lines, *home, interns);
|
|
||||||
|
|
||||||
let problems = can_problems.remove(home).unwrap_or_default();
|
|
||||||
|
|
||||||
for problem in problems.into_iter() {
|
|
||||||
let report = can_problem(&alloc, &lines, module_path.clone(), problem);
|
|
||||||
let severity = report.severity;
|
|
||||||
let mut buf = String::new();
|
|
||||||
|
|
||||||
report.render_color_terminal(&mut buf, &alloc, &palette);
|
|
||||||
|
|
||||||
match severity {
|
|
||||||
Warning => {
|
|
||||||
warnings.push(buf);
|
|
||||||
}
|
|
||||||
RuntimeError => {
|
|
||||||
errors.push(buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let problems = type_problems.remove(home).unwrap_or_default();
|
|
||||||
|
|
||||||
for problem in problems {
|
|
||||||
if let Some(report) = type_problem(&alloc, &lines, module_path.clone(), problem) {
|
|
||||||
let severity = report.severity;
|
|
||||||
let mut buf = String::new();
|
|
||||||
|
|
||||||
report.render_color_terminal(&mut buf, &alloc, &palette);
|
|
||||||
|
|
||||||
match severity {
|
|
||||||
Warning => {
|
|
||||||
warnings.push(buf);
|
|
||||||
}
|
|
||||||
RuntimeError => {
|
|
||||||
errors.push(buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let problems_reported;
|
|
||||||
|
|
||||||
// Only print warnings if there are no errors
|
|
||||||
if errors.is_empty() {
|
|
||||||
problems_reported = warnings.len();
|
|
||||||
|
|
||||||
for warning in warnings.iter() {
|
|
||||||
println!("\n{}\n", warning);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
problems_reported = errors.len();
|
|
||||||
|
|
||||||
for error in errors.iter() {
|
|
||||||
println!("\n{}\n", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we printed any problems, print a horizontal rule at the end,
|
|
||||||
// and then clear any ANSI escape codes (e.g. colors) we've used.
|
|
||||||
//
|
|
||||||
// The horizontal rule is nice when running the program right after
|
|
||||||
// compiling it, as it lets you clearly see where the compiler
|
|
||||||
// errors/warnings end and the program output begins.
|
|
||||||
if problems_reported > 0 {
|
|
||||||
println!("{}\u{001B}[0m\n", Report::horizontal_rule(&palette));
|
|
||||||
}
|
|
||||||
|
|
||||||
Problems {
|
|
||||||
errors: errors.len(),
|
|
||||||
warnings: warnings.len(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum CodeObject {
|
pub enum CodeObject {
|
||||||
MemoryBuffer(MemoryBuffer),
|
MemoryBuffer(MemoryBuffer),
|
||||||
Vector(Vec<u8>),
|
Vector(Vec<u8>),
|
||||||
|
|
|
@ -72,6 +72,7 @@ fn write_types_for_module_dummy(output_path: &Path) {
|
||||||
fn write_types_for_module_real(module_id: ModuleId, filename: &str, output_path: &Path) {
|
fn write_types_for_module_real(module_id: ModuleId, filename: &str, output_path: &Path) {
|
||||||
use roc_can::module::TypeState;
|
use roc_can::module::TypeState;
|
||||||
use roc_load_internal::file::{LoadingProblem, Threading};
|
use roc_load_internal::file::{LoadingProblem, Threading};
|
||||||
|
use roc_reporting::cli::report_problems;
|
||||||
|
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let src_dir = PathBuf::from(".");
|
let src_dir = PathBuf::from(".");
|
||||||
|
@ -90,7 +91,7 @@ fn write_types_for_module_real(module_id: ModuleId, filename: &str, output_path:
|
||||||
Threading::AllAvailable,
|
Threading::AllAvailable,
|
||||||
);
|
);
|
||||||
|
|
||||||
let module = match res_module {
|
let mut module = match res_module {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(LoadingProblem::FormattedReport(report)) => {
|
Err(LoadingProblem::FormattedReport(report)) => {
|
||||||
panic!("{}", report);
|
panic!("{}", report);
|
||||||
|
@ -100,8 +101,16 @@ fn write_types_for_module_real(module_id: ModuleId, filename: &str, output_path:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if module.total_problems() > 0 {
|
let problems = report_problems(
|
||||||
panic!("Problems were found! Refusing to build cached subs.\nTry building with {}=1 to see them.", ROC_SKIP_SUBS_CACHE);
|
module.total_problems(),
|
||||||
|
&module.sources,
|
||||||
|
&module.interns,
|
||||||
|
&mut module.can_problems,
|
||||||
|
&mut module.type_problems,
|
||||||
|
);
|
||||||
|
|
||||||
|
if problems.errors + problems.warnings > 0 {
|
||||||
|
panic!("Problems were found! Refusing to build cached subs.");
|
||||||
}
|
}
|
||||||
|
|
||||||
let subs = module.solved.into_inner();
|
let subs = module.solved.into_inner();
|
||||||
|
|
|
@ -133,7 +133,9 @@ fn find_names_needed(
|
||||||
}
|
}
|
||||||
_ => panic!(
|
_ => panic!(
|
||||||
"unfixable recursive type in roc_types::pretty_print {:?} {:?} {:?}",
|
"unfixable recursive type in roc_types::pretty_print {:?} {:?} {:?}",
|
||||||
recursive, variable, content
|
recursive,
|
||||||
|
variable,
|
||||||
|
subs.dbg(recursive)
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
123
crates/reporting/src/cli.rs
Normal file
123
crates/reporting/src/cli.rs
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use roc_collections::MutMap;
|
||||||
|
use roc_module::symbol::{Interns, ModuleId};
|
||||||
|
use roc_region::all::LineInfo;
|
||||||
|
use roc_solve_problem::TypeError;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
|
||||||
|
pub struct Problems {
|
||||||
|
pub errors: usize,
|
||||||
|
pub warnings: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Problems {
|
||||||
|
pub fn exit_code(&self) -> i32 {
|
||||||
|
// 0 means no problems, 1 means errors, 2 means warnings
|
||||||
|
if self.errors > 0 {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
self.warnings.min(1) as i32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn report_problems(
|
||||||
|
total_problems: usize,
|
||||||
|
sources: &MutMap<ModuleId, (PathBuf, Box<str>)>,
|
||||||
|
interns: &Interns,
|
||||||
|
can_problems: &mut MutMap<ModuleId, Vec<roc_problem::can::Problem>>,
|
||||||
|
type_problems: &mut MutMap<ModuleId, Vec<TypeError>>,
|
||||||
|
) -> Problems {
|
||||||
|
use crate::report::{
|
||||||
|
can_problem, type_problem, Report, RocDocAllocator, Severity::*, DEFAULT_PALETTE,
|
||||||
|
};
|
||||||
|
let palette = DEFAULT_PALETTE;
|
||||||
|
|
||||||
|
// This will often over-allocate total memory, but it means we definitely
|
||||||
|
// never need to re-allocate either the warnings or the errors vec!
|
||||||
|
let mut warnings = Vec::with_capacity(total_problems);
|
||||||
|
let mut errors = Vec::with_capacity(total_problems);
|
||||||
|
|
||||||
|
for (home, (module_path, src)) in sources.iter() {
|
||||||
|
let mut src_lines: Vec<&str> = Vec::new();
|
||||||
|
|
||||||
|
src_lines.extend(src.split('\n'));
|
||||||
|
|
||||||
|
let lines = LineInfo::new(&src_lines.join("\n"));
|
||||||
|
|
||||||
|
// Report parsing and canonicalization problems
|
||||||
|
let alloc = RocDocAllocator::new(&src_lines, *home, interns);
|
||||||
|
|
||||||
|
let problems = can_problems.remove(home).unwrap_or_default();
|
||||||
|
|
||||||
|
for problem in problems.into_iter() {
|
||||||
|
let report = can_problem(&alloc, &lines, module_path.clone(), problem);
|
||||||
|
let severity = report.severity;
|
||||||
|
let mut buf = String::new();
|
||||||
|
|
||||||
|
report.render_color_terminal(&mut buf, &alloc, &palette);
|
||||||
|
|
||||||
|
match severity {
|
||||||
|
Warning => {
|
||||||
|
warnings.push(buf);
|
||||||
|
}
|
||||||
|
RuntimeError => {
|
||||||
|
errors.push(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let problems = type_problems.remove(home).unwrap_or_default();
|
||||||
|
|
||||||
|
for problem in problems {
|
||||||
|
if let Some(report) = type_problem(&alloc, &lines, module_path.clone(), problem) {
|
||||||
|
let severity = report.severity;
|
||||||
|
let mut buf = String::new();
|
||||||
|
|
||||||
|
report.render_color_terminal(&mut buf, &alloc, &palette);
|
||||||
|
|
||||||
|
match severity {
|
||||||
|
Warning => {
|
||||||
|
warnings.push(buf);
|
||||||
|
}
|
||||||
|
RuntimeError => {
|
||||||
|
errors.push(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let problems_reported;
|
||||||
|
|
||||||
|
// Only print warnings if there are no errors
|
||||||
|
if errors.is_empty() {
|
||||||
|
problems_reported = warnings.len();
|
||||||
|
|
||||||
|
for warning in warnings.iter() {
|
||||||
|
println!("\n{}\n", warning);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
problems_reported = errors.len();
|
||||||
|
|
||||||
|
for error in errors.iter() {
|
||||||
|
println!("\n{}\n", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we printed any problems, print a horizontal rule at the end,
|
||||||
|
// and then clear any ANSI escape codes (e.g. colors) we've used.
|
||||||
|
//
|
||||||
|
// The horizontal rule is nice when running the program right after
|
||||||
|
// compiling it, as it lets you clearly see where the compiler
|
||||||
|
// errors/warnings end and the program output begins.
|
||||||
|
if problems_reported > 0 {
|
||||||
|
println!("{}\u{001B}[0m\n", Report::horizontal_rule(&palette));
|
||||||
|
}
|
||||||
|
|
||||||
|
Problems {
|
||||||
|
errors: errors.len(),
|
||||||
|
warnings: warnings.len(),
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,5 +3,6 @@
|
||||||
// See github.com/roc-lang/roc/issues/800 for discussion of the large_enum_variant check.
|
// See github.com/roc-lang/roc/issues/800 for discussion of the large_enum_variant check.
|
||||||
#![allow(clippy::large_enum_variant)]
|
#![allow(clippy::large_enum_variant)]
|
||||||
|
|
||||||
|
pub mod cli;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod report;
|
pub mod report;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue