Remove MonoProblem

This commit is contained in:
Ayaz Hafiz 2022-04-28 14:46:17 -04:00 committed by ayazhafiz
parent c969c7a15e
commit 89757dc31f
9 changed files with 12 additions and 408 deletions

1
Cargo.lock generated
View file

@ -3937,7 +3937,6 @@ dependencies = [
"roc_exhaustive", "roc_exhaustive",
"roc_load", "roc_load",
"roc_module", "roc_module",
"roc_mono",
"roc_parse", "roc_parse",
"roc_problem", "roc_problem",
"roc_region", "roc_region",

View file

@ -24,10 +24,6 @@ pub struct CodeGenTiming {
#[cfg(feature = "llvm")] #[cfg(feature = "llvm")]
const LLVM_VERSION: &str = "12"; const LLVM_VERSION: &str = "12";
// TODO instead of finding exhaustiveness problems in monomorphization, find
// them after type checking (like Elm does) so we can complete the entire
// `roc check` process without needing to monomorphize.
/// Returns the number of problems reported.
pub fn report_problems_monomorphized(loaded: &mut MonomorphizedModule) -> Problems { pub fn report_problems_monomorphized(loaded: &mut MonomorphizedModule) -> Problems {
report_problems_help( report_problems_help(
loaded.total_problems(), loaded.total_problems(),
@ -35,7 +31,6 @@ pub fn report_problems_monomorphized(loaded: &mut MonomorphizedModule) -> Proble
&loaded.interns, &loaded.interns,
&mut loaded.can_problems, &mut loaded.can_problems,
&mut loaded.type_problems, &mut loaded.type_problems,
&mut loaded.mono_problems,
) )
} }
@ -46,7 +41,6 @@ pub fn report_problems_typechecked(loaded: &mut LoadedModule) -> Problems {
&loaded.interns, &loaded.interns,
&mut loaded.can_problems, &mut loaded.can_problems,
&mut loaded.type_problems, &mut loaded.type_problems,
&mut Default::default(),
) )
} }
@ -73,11 +67,9 @@ fn report_problems_help(
interns: &Interns, interns: &Interns,
can_problems: &mut MutMap<ModuleId, Vec<roc_problem::can::Problem>>, can_problems: &mut MutMap<ModuleId, Vec<roc_problem::can::Problem>>,
type_problems: &mut MutMap<ModuleId, Vec<roc_solve::solve::TypeError>>, type_problems: &mut MutMap<ModuleId, Vec<roc_solve::solve::TypeError>>,
mono_problems: &mut MutMap<ModuleId, Vec<roc_mono::ir::MonoProblem>>,
) -> Problems { ) -> Problems {
use roc_reporting::report::{ use roc_reporting::report::{
can_problem, mono_problem, type_problem, Report, RocDocAllocator, Severity::*, can_problem, type_problem, Report, RocDocAllocator, Severity::*, DEFAULT_PALETTE,
DEFAULT_PALETTE,
}; };
let palette = DEFAULT_PALETTE; let palette = DEFAULT_PALETTE;
@ -134,25 +126,6 @@ fn report_problems_help(
} }
} }
} }
let problems = mono_problems.remove(home).unwrap_or_default();
for problem in problems {
let report = mono_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; let problems_reported;

View file

@ -519,7 +519,6 @@ pub struct MonomorphizedModule<'a> {
pub platform_path: Box<str>, pub platform_path: Box<str>,
pub can_problems: MutMap<ModuleId, Vec<roc_problem::can::Problem>>, pub can_problems: MutMap<ModuleId, Vec<roc_problem::can::Problem>>,
pub type_problems: MutMap<ModuleId, Vec<solve::TypeError>>, pub type_problems: MutMap<ModuleId, Vec<solve::TypeError>>,
pub mono_problems: MutMap<ModuleId, Vec<roc_mono::ir::MonoProblem>>,
pub procedures: MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>, pub procedures: MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>,
pub entry_point: EntryPoint<'a>, pub entry_point: EntryPoint<'a>,
pub exposed_to_host: ExposedToHost, pub exposed_to_host: ExposedToHost,
@ -547,10 +546,6 @@ impl<'a> MonomorphizedModule<'a> {
total += problems.len(); total += problems.len();
} }
for problems in self.mono_problems.values() {
total += problems.len();
}
total total
} }
} }
@ -2321,7 +2316,6 @@ fn finish_specialization(
} = state; } = state;
let ModuleCache { let ModuleCache {
mono_problems,
type_problems, type_problems,
can_problems, can_problems,
sources, sources,
@ -2384,7 +2378,6 @@ fn finish_specialization(
Ok(MonomorphizedModule { Ok(MonomorphizedModule {
can_problems, can_problems,
mono_problems,
type_problems, type_problems,
output_path: output_path.unwrap_or(DEFAULT_APP_OUTPUT_PATH).into(), output_path: output_path.unwrap_or(DEFAULT_APP_OUTPUT_PATH).into(),
platform_path, platform_path,

View file

@ -7,7 +7,7 @@ use roc_fmt::annotation::{Newlines, Parens};
use roc_load::{LoadingProblem, MonomorphizedModule}; use roc_load::{LoadingProblem, MonomorphizedModule};
use roc_parse::ast::Expr; use roc_parse::ast::Expr;
use roc_region::all::LineInfo; use roc_region::all::LineInfo;
use roc_reporting::report::{can_problem, mono_problem, type_problem, RocDocAllocator}; use roc_reporting::report::{can_problem, type_problem, RocDocAllocator};
use roc_target::TargetInfo; use roc_target::TargetInfo;
use crate::eval::ToAstProblem; use crate::eval::ToAstProblem;
@ -78,7 +78,6 @@ pub fn compile_to_mono<'a>(
sources, sources,
can_problems, can_problems,
type_problems, type_problems,
mono_problems,
.. ..
} = &mut loaded; } = &mut loaded;
@ -87,9 +86,8 @@ pub fn compile_to_mono<'a>(
for (home, (module_path, src)) in sources.iter() { for (home, (module_path, src)) in sources.iter() {
let can_probs = can_problems.remove(home).unwrap_or_default(); let can_probs = can_problems.remove(home).unwrap_or_default();
let type_probs = type_problems.remove(home).unwrap_or_default(); let type_probs = type_problems.remove(home).unwrap_or_default();
let mono_probs = mono_problems.remove(home).unwrap_or_default();
let error_count = can_probs.len() + type_probs.len() + mono_probs.len(); let error_count = can_probs.len() + type_probs.len();
if error_count == 0 { if error_count == 0 {
continue; continue;
@ -119,15 +117,6 @@ pub fn compile_to_mono<'a>(
lines.push(buf); lines.push(buf);
} }
} }
for problem in mono_probs {
let report = mono_problem(&alloc, &line_info, module_path.clone(), problem);
let mut buf = String::new();
report.render_color_terminal(&mut buf, &alloc, &palette);
lines.push(buf);
}
} }
if !lines.is_empty() { if !lines.is_empty() {

View file

@ -15,7 +15,6 @@ roc_problem = { path = "../compiler/problem" }
roc_types = { path = "../compiler/types" } roc_types = { path = "../compiler/types" }
roc_can = { path = "../compiler/can" } roc_can = { path = "../compiler/can" }
roc_solve = { path = "../compiler/solve" } roc_solve = { path = "../compiler/solve" }
roc_mono = { path = "../compiler/mono" }
ven_pretty = { path = "../vendor/pretty" } ven_pretty = { path = "../vendor/pretty" }
distance = "0.4.0" distance = "0.4.0"
bumpalo = { version = "3.8.0", features = ["collections"] } bumpalo = { version = "3.8.0", features = ["collections"] }

View file

@ -1,4 +1,3 @@
pub mod canonicalize; pub mod canonicalize;
pub mod mono;
pub mod parse; pub mod parse;
pub mod r#type; pub mod r#type;

View file

@ -1,235 +0,0 @@
use crate::report::{Annotation, Report, RocDocAllocator, RocDocBuilder, Severity};
use roc_module::ident::TagName;
use roc_region::all::LineInfo;
use std::path::PathBuf;
use ven_pretty::DocAllocator;
pub fn mono_problem<'b>(
alloc: &'b RocDocAllocator<'b>,
lines: &LineInfo,
filename: PathBuf,
problem: roc_mono::ir::MonoProblem,
) -> Report<'b> {
use roc_exhaustive::Context::*;
use roc_exhaustive::Error::*;
use roc_mono::ir::MonoProblem::*;
match problem {
PatternProblem(Incomplete(region, context, missing)) => match context {
BadArg => {
let doc = alloc.stack([
alloc.reflow("This pattern does not cover all the possibilities:"),
alloc.region(lines.convert_region(region)),
alloc.reflow("Other possibilities include:"),
unhandled_patterns_to_doc_block(alloc, missing),
alloc.concat([
alloc.reflow(
"I would have to crash if I saw one of those! \
So rather than pattern matching in function arguments, put a ",
),
alloc.keyword("when"),
alloc.reflow(" in the function body to account for all possibilities."),
]),
]);
Report {
filename,
title: "UNSAFE PATTERN".to_string(),
doc,
severity: Severity::RuntimeError,
}
}
BadDestruct => {
let doc = alloc.stack([
alloc.reflow("This pattern does not cover all the possibilities:"),
alloc.region(lines.convert_region(region)),
alloc.reflow("Other possibilities include:"),
unhandled_patterns_to_doc_block(alloc, missing),
alloc.concat([
alloc.reflow(
"I would have to crash if I saw one of those! \
You can use a binding to deconstruct a value if there is only ONE possibility. \
Use a "
),
alloc.keyword("when"),
alloc.reflow(" to account for all possibilities."),
]),
]);
Report {
filename,
title: "UNSAFE PATTERN".to_string(),
doc,
severity: Severity::RuntimeError,
}
}
BadCase => {
let doc = alloc.stack([
alloc.concat([
alloc.reflow("This "),
alloc.keyword("when"),
alloc.reflow(" does not cover all the possibilities:"),
]),
alloc.region(lines.convert_region(region)),
alloc.reflow("Other possibilities include:"),
unhandled_patterns_to_doc_block(alloc, missing),
alloc.reflow(
"I would have to crash if I saw one of those! \
Add branches for them!",
),
// alloc.hint().append(alloc.reflow("or use a hole.")),
]);
Report {
filename,
title: "UNSAFE PATTERN".to_string(),
doc,
severity: Severity::RuntimeError,
}
}
},
PatternProblem(Redundant {
overall_region,
branch_region,
index,
}) => {
let doc = alloc.stack([
alloc.concat([
alloc.reflow("The "),
alloc.string(index.ordinal()),
alloc.reflow(" pattern is redundant:"),
]),
alloc.region_with_subregion(
lines.convert_region(overall_region),
lines.convert_region(branch_region),
),
alloc.reflow(
"Any value of this shape will be handled by \
a previous pattern, so this one should be removed.",
),
]);
Report {
filename,
title: "REDUNDANT PATTERN".to_string(),
doc,
severity: Severity::Warning,
}
}
}
}
pub fn unhandled_patterns_to_doc_block<'b>(
alloc: &'b RocDocAllocator<'b>,
patterns: Vec<roc_exhaustive::Pattern>,
) -> RocDocBuilder<'b> {
alloc
.vcat(patterns.into_iter().map(|v| pattern_to_doc(alloc, v)))
.indent(4)
.annotate(Annotation::TypeBlock)
}
fn pattern_to_doc<'b>(
alloc: &'b RocDocAllocator<'b>,
pattern: roc_exhaustive::Pattern,
) -> RocDocBuilder<'b> {
pattern_to_doc_help(alloc, pattern, false)
}
const AFTER_TAG_INDENT: &str = " ";
fn pattern_to_doc_help<'b>(
alloc: &'b RocDocAllocator<'b>,
pattern: roc_exhaustive::Pattern,
in_type_param: bool,
) -> RocDocBuilder<'b> {
use roc_exhaustive::Literal::*;
use roc_exhaustive::Pattern::*;
use roc_exhaustive::{CtorName, RenderAs};
match pattern {
Anything => alloc.text("_"),
Literal(l) => match l {
Int(i) => alloc.text(i.to_string()),
U128(i) => alloc.text(i.to_string()),
Bit(true) => alloc.text("True"),
Bit(false) => alloc.text("False"),
Byte(b) => alloc.text(b.to_string()),
Float(f) => alloc.text(f.to_string()),
Decimal(d) => alloc.text(d.to_string()),
Str(s) => alloc.string(s.into()),
},
Ctor(union, tag_id, args) => {
match union.render_as {
RenderAs::Guard => {
// #Guard <fake-condition-tag> <unexhausted-pattern>
debug_assert!(union.alternatives[tag_id.0 as usize]
.name
.is_tag(&TagName::Tag("#Guard".into())),);
debug_assert!(args.len() == 2);
let tag = pattern_to_doc_help(alloc, args[1].clone(), in_type_param);
alloc.concat([
tag,
alloc.text(AFTER_TAG_INDENT),
alloc.text("(note the lack of an "),
alloc.keyword("if"),
alloc.text(" clause)"),
])
}
RenderAs::Record(field_names) => {
let mut arg_docs = Vec::with_capacity(args.len());
for (label, v) in field_names.into_iter().zip(args.into_iter()) {
match &v {
Anything => {
arg_docs.push(alloc.text(label.to_string()));
}
Literal(_) | Ctor(_, _, _) => {
arg_docs.push(
alloc
.text(label.to_string())
.append(alloc.reflow(": "))
.append(pattern_to_doc_help(alloc, v, false)),
);
}
}
}
alloc
.text("{ ")
.append(alloc.intersperse(arg_docs, alloc.reflow(", ")))
.append(" }")
}
RenderAs::Tag | RenderAs::Opaque => {
let has_args = !args.is_empty();
let arg_docs = args
.into_iter()
.map(|v| pattern_to_doc_help(alloc, v, true));
let ctor = &union.alternatives[tag_id.0 as usize];
let tag_name = match (union.render_as, &ctor.name) {
(RenderAs::Tag, CtorName::Tag(tag)) => alloc.tag_name(tag.clone()),
(RenderAs::Opaque, CtorName::Opaque(opaque)) => {
alloc.wrapped_opaque_name(*opaque)
}
_ => unreachable!(),
};
// We assume the alternatives are sorted. If not, this assert will trigger
debug_assert!(tag_id == ctor.tag_id);
let docs = std::iter::once(tag_name).chain(arg_docs);
if in_type_param && has_args {
alloc
.text("(")
.append(alloc.intersperse(docs, alloc.space()))
.append(")")
} else {
alloc.intersperse(docs, alloc.space())
}
}
}
}
}
}

View file

@ -7,7 +7,6 @@ use std::path::{Path, PathBuf};
use ven_pretty::{BoxAllocator, DocAllocator, DocBuilder, Render, RenderAnnotated}; use ven_pretty::{BoxAllocator, DocAllocator, DocBuilder, Render, RenderAnnotated};
pub use crate::error::canonicalize::can_problem; pub use crate::error::canonicalize::can_problem;
pub use crate::error::mono::mono_problem;
pub use crate::error::parse::parse_problem; pub use crate::error::parse::parse_problem;
pub use crate::error::r#type::type_problem; pub use crate::error::r#type::type_problem;

View file

@ -12,16 +12,12 @@ mod test_reporting {
use bumpalo::Bump; use bumpalo::Bump;
use indoc::indoc; use indoc::indoc;
use roc_can::abilities::AbilitiesStore; use roc_can::abilities::AbilitiesStore;
use roc_can::def::Declaration;
use roc_can::pattern::Pattern;
use roc_load::{self, LoadedModule, LoadingProblem}; use roc_load::{self, LoadedModule, LoadingProblem};
use roc_module::symbol::{Interns, ModuleId}; use roc_module::symbol::{Interns, ModuleId};
use roc_mono::ir::{Procs, Stmt, UpdateModeIds};
use roc_mono::layout::LayoutCache;
use roc_region::all::LineInfo; use roc_region::all::LineInfo;
use roc_reporting::report::{ use roc_reporting::report::{
can_problem, mono_problem, parse_problem, type_problem, RenderTarget, Report, Severity, can_problem, parse_problem, type_problem, RenderTarget, Report, Severity, ANSI_STYLE_CODES,
ANSI_STYLE_CODES, DEFAULT_PALETTE, DEFAULT_PALETTE,
}; };
use roc_reporting::report::{RocDocAllocator, RocDocBuilder}; use roc_reporting::report::{RocDocAllocator, RocDocBuilder};
use roc_solve::solve; use roc_solve::solve;
@ -114,7 +110,6 @@ mod test_reporting {
String, String,
Vec<solve::TypeError>, Vec<solve::TypeError>,
Vec<roc_problem::can::Problem>, Vec<roc_problem::can::Problem>,
Vec<roc_mono::ir::MonoProblem>,
ModuleId, ModuleId,
Interns, Interns,
), ),
@ -128,8 +123,6 @@ mod test_reporting {
interns, interns,
mut solved, mut solved,
exposed_to_host, exposed_to_host,
mut declarations_by_id,
abilities_store,
.. ..
} = result?; } = result?;
@ -142,65 +135,7 @@ mod test_reporting {
name_all_type_vars(*var, subs); name_all_type_vars(*var, subs);
} }
let mut mono_problems = Vec::new(); Ok((module_src, type_problems, can_problems, home, interns))
// MONO
if type_problems.is_empty() && can_problems.is_empty() {
let arena = Bump::new();
assert!(exposed_to_host.len() == 1);
let (sym, _var) = exposed_to_host.into_iter().next().unwrap();
let home_decls = declarations_by_id.remove(&home).unwrap();
let (loc_expr, var) = home_decls
.into_iter()
.find_map(|decl| match decl {
Declaration::Declare(def) => match def.loc_pattern.value {
Pattern::Identifier(s) if s == sym => Some((def.loc_expr, def.expr_var)),
_ => None,
},
_ => None,
})
.expect("No expression to monomorphize found!");
// Compile and add all the Procs before adding main
let mut procs = Procs::new_in(&arena);
let mut ident_ids = interns.all_ident_ids.get(&home).unwrap().clone();
let mut update_mode_ids = UpdateModeIds::new();
// Populate Procs and Subs, and get the low-level Expr from the canonical Expr
let target_info = roc_target::TargetInfo::default_x86_64();
let mut layout_cache = LayoutCache::new(target_info);
let mut mono_env = roc_mono::ir::Env {
arena: &arena,
subs,
problems: &mut mono_problems,
home,
ident_ids: &mut ident_ids,
update_mode_ids: &mut update_mode_ids,
target_info,
// call_specialization_counter=0 is reserved
call_specialization_counter: 1,
abilities_store: &abilities_store,
};
let _mono_expr = Stmt::new(
&mut mono_env,
loc_expr.value,
var,
&mut procs,
&mut layout_cache,
);
}
Ok((
module_src,
type_problems,
can_problems,
mono_problems,
home,
interns,
))
} }
fn list_reports_new<F>(subdir: &str, arena: &Bump, src: &str, finalize_render: F) -> String fn list_reports_new<F>(subdir: &str, arena: &Bump, src: &str, finalize_render: F) -> String
@ -215,7 +150,7 @@ mod test_reporting {
match infer_expr_help_new(subdir, arena, src) { match infer_expr_help_new(subdir, arena, src) {
Err(LoadingProblem::FormattedReport(fail)) => fail, Err(LoadingProblem::FormattedReport(fail)) => fail,
Ok((module_src, type_problems, can_problems, mono_problems, home, interns)) => { Ok((module_src, type_problems, can_problems, home, interns)) => {
let lines = LineInfo::new(&module_src); let lines = LineInfo::new(&module_src);
let src_lines: Vec<&str> = module_src.split('\n').collect(); let src_lines: Vec<&str> = module_src.split('\n').collect();
let mut reports = Vec::new(); let mut reports = Vec::new();
@ -235,11 +170,6 @@ mod test_reporting {
} }
} }
for problem in mono_problems {
let report = mono_problem(&alloc, &lines, filename.clone(), problem.clone());
reports.push(report);
}
let has_reports = !reports.is_empty(); let has_reports = !reports.is_empty();
let doc = alloc let doc = alloc
@ -267,14 +197,13 @@ mod test_reporting {
( (
Vec<solve::TypeError>, Vec<solve::TypeError>,
Vec<roc_problem::can::Problem>, Vec<roc_problem::can::Problem>,
Vec<roc_mono::ir::MonoProblem>,
ModuleId, ModuleId,
Interns, Interns,
), ),
ParseErrOut<'a>, ParseErrOut<'a>,
> { > {
let CanExprOut { let CanExprOut {
loc_expr, loc_expr: _,
output, output,
var_store, var_store,
var, var,
@ -315,43 +244,7 @@ mod test_reporting {
name_all_type_vars(var, &mut subs); name_all_type_vars(var, &mut subs);
let mut mono_problems = Vec::new(); Ok((unify_problems, can_problems, home, interns))
// MONO
if unify_problems.is_empty() && can_problems.is_empty() {
let arena = Bump::new();
// Compile and add all the Procs before adding main
let mut procs = Procs::new_in(&arena);
let mut ident_ids = interns.all_ident_ids.get(&home).unwrap().clone();
let mut update_mode_ids = UpdateModeIds::new();
// Populate Procs and Subs, and get the low-level Expr from the canonical Expr
let target_info = roc_target::TargetInfo::default_x86_64();
let mut layout_cache = LayoutCache::new(target_info);
let mut mono_env = roc_mono::ir::Env {
arena: &arena,
subs: &mut subs,
problems: &mut mono_problems,
home,
ident_ids: &mut ident_ids,
update_mode_ids: &mut update_mode_ids,
target_info,
// call_specialization_counter=0 is reserved
call_specialization_counter: 1,
abilities_store: &abilities_store,
};
let _mono_expr = Stmt::new(
&mut mono_env,
loc_expr.value,
var,
&mut procs,
&mut layout_cache,
);
}
Ok((unify_problems, can_problems, mono_problems, home, interns))
} }
fn list_reports<F>(arena: &Bump, src: &str, buf: &mut String, callback: F) fn list_reports<F>(arena: &Bump, src: &str, buf: &mut String, callback: F)
@ -380,7 +273,7 @@ mod test_reporting {
callback(doc.pretty(&alloc).append(alloc.line()), buf) callback(doc.pretty(&alloc).append(alloc.line()), buf)
} }
Ok((type_problems, can_problems, mono_problems, home, interns)) => { Ok((type_problems, can_problems, home, interns)) => {
let mut reports = Vec::new(); let mut reports = Vec::new();
let alloc = RocDocAllocator::new(&src_lines, home, &interns); let alloc = RocDocAllocator::new(&src_lines, home, &interns);
@ -398,11 +291,6 @@ mod test_reporting {
} }
} }
for problem in mono_problems {
let report = mono_problem(&alloc, &lines, filename.clone(), problem.clone());
reports.push(report);
}
let has_reports = !reports.is_empty(); let has_reports = !reports.is_empty();
let doc = alloc let doc = alloc
@ -922,7 +810,7 @@ mod test_reporting {
); );
let arena = Bump::new(); let arena = Bump::new();
let (_type_problems, _can_problems, _mono_problems, home, interns) = let (_type_problems, _can_problems, home, interns) =
infer_expr_help(&arena, src).expect("parse error"); infer_expr_help(&arena, src).expect("parse error");
let mut buf = String::new(); let mut buf = String::new();
@ -953,7 +841,7 @@ mod test_reporting {
); );
let arena = Bump::new(); let arena = Bump::new();
let (_type_problems, _can_problems, _mono_problems, home, mut interns) = let (_type_problems, _can_problems, home, mut interns) =
infer_expr_help(&arena, src).expect("parse error"); infer_expr_help(&arena, src).expect("parse error");
let mut buf = String::new(); let mut buf = String::new();