mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 19:58:18 +00:00
Merge pull request #4661 from roc-lang/roc-test-dev
`test` has `dev` behavior, and `dev` does not exit if there are warnings
This commit is contained in:
commit
c61c42bff7
22 changed files with 341 additions and 194 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -3880,6 +3880,7 @@ dependencies = [
|
|||
"roc_collections",
|
||||
"roc_error_macros",
|
||||
"roc_module",
|
||||
"roc_problem",
|
||||
"roc_region",
|
||||
]
|
||||
|
||||
|
@ -4247,6 +4248,7 @@ dependencies = [
|
|||
"roc_mono",
|
||||
"roc_packaging",
|
||||
"roc_parse",
|
||||
"roc_problem",
|
||||
"roc_region",
|
||||
"roc_reporting",
|
||||
"roc_std",
|
||||
|
|
|
@ -359,8 +359,9 @@ pub fn test(_matches: &ArgMatches, _triple: Triple) -> io::Result<i32> {
|
|||
|
||||
#[cfg(not(windows))]
|
||||
pub fn test(matches: &ArgMatches, triple: Triple) -> io::Result<i32> {
|
||||
use roc_build::program::report_problems_monomorphized;
|
||||
use roc_gen_llvm::llvm::build::LlvmBackendMode;
|
||||
use roc_load::{ExecutionMode, LoadConfig};
|
||||
use roc_load::{ExecutionMode, LoadConfig, LoadMonomorphizedError};
|
||||
use roc_packaging::cache;
|
||||
use roc_target::TargetInfo;
|
||||
|
||||
|
@ -425,18 +426,26 @@ pub fn test(matches: &ArgMatches, triple: Triple) -> io::Result<i32> {
|
|||
threading,
|
||||
exec_mode: ExecutionMode::Test,
|
||||
};
|
||||
let loaded = roc_load::load_and_monomorphize(
|
||||
let load_result = roc_load::load_and_monomorphize(
|
||||
arena,
|
||||
path.to_path_buf(),
|
||||
subs_by_module,
|
||||
RocCacheDir::Persistent(cache::roc_cache_dir().as_path()),
|
||||
load_config,
|
||||
)
|
||||
.unwrap();
|
||||
);
|
||||
|
||||
let mut loaded = match load_result {
|
||||
Ok(loaded) => loaded,
|
||||
Err(LoadMonomorphizedError::LoadingProblem(problem)) => {
|
||||
return handle_loading_problem(problem);
|
||||
}
|
||||
Err(LoadMonomorphizedError::ErrorModule(module)) => {
|
||||
return handle_error_module(module, start_time.elapsed(), filename, false);
|
||||
}
|
||||
};
|
||||
let problems = report_problems_monomorphized(&mut loaded);
|
||||
|
||||
let mut loaded = loaded;
|
||||
let mut expectations = std::mem::take(&mut loaded.expectations);
|
||||
let loaded = loaded;
|
||||
|
||||
let interns = loaded.interns.clone();
|
||||
|
||||
|
@ -449,6 +458,19 @@ pub fn test(matches: &ArgMatches, triple: Triple) -> io::Result<i32> {
|
|||
)
|
||||
.unwrap();
|
||||
|
||||
// Print warnings before running tests.
|
||||
{
|
||||
debug_assert_eq!(
|
||||
problems.errors, 0,
|
||||
"if there were errors, we would have already exited."
|
||||
);
|
||||
if problems.warnings > 0 {
|
||||
print_problems(problems, start_time.elapsed());
|
||||
println!(".\n\nRunning tests…\n\n\x1B[36m{}\x1B[39m", "─".repeat(80));
|
||||
}
|
||||
}
|
||||
|
||||
// Run the tests.
|
||||
let arena = &bumpalo::Bump::new();
|
||||
let interns = arena.alloc(interns);
|
||||
|
||||
|
@ -733,35 +755,51 @@ pub fn build(
|
|||
}
|
||||
}
|
||||
}
|
||||
Err(BuildFileError::ErrorModule {
|
||||
mut module,
|
||||
total_time,
|
||||
}) => {
|
||||
debug_assert!(module.total_problems() > 0);
|
||||
|
||||
let problems = roc_build::program::report_problems_typechecked(&mut module);
|
||||
|
||||
print_problems(problems, total_time);
|
||||
|
||||
print!(".\n\nYou can run the program anyway with \x1B[32mroc run");
|
||||
|
||||
// If you're running "main.roc" then you can just do `roc run`
|
||||
// to re-run the program.
|
||||
if filename != DEFAULT_ROC_FILENAME {
|
||||
print!(" {}", &filename.to_string_lossy());
|
||||
}
|
||||
|
||||
println!("\x1B[39m");
|
||||
|
||||
Ok(problems.exit_code())
|
||||
Err(BuildFileError::ErrorModule { module, total_time }) => {
|
||||
handle_error_module(module, total_time, filename, true)
|
||||
}
|
||||
Err(BuildFileError::LoadingProblem(LoadingProblem::FormattedReport(report))) => {
|
||||
print!("{}", report);
|
||||
Err(BuildFileError::LoadingProblem(problem)) => handle_loading_problem(problem),
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_error_module(
|
||||
mut module: roc_load::LoadedModule,
|
||||
total_time: std::time::Duration,
|
||||
filename: &OsStr,
|
||||
print_run_anyway_hint: bool,
|
||||
) -> io::Result<i32> {
|
||||
debug_assert!(module.total_problems() > 0);
|
||||
|
||||
let problems = roc_build::program::report_problems_typechecked(&mut module);
|
||||
|
||||
print_problems(problems, total_time);
|
||||
|
||||
if print_run_anyway_hint {
|
||||
// If you're running "main.roc" then you can just do `roc run`
|
||||
// to re-run the program.
|
||||
print!(".\n\nYou can run the program anyway with \x1B[32mroc run");
|
||||
|
||||
if filename != DEFAULT_ROC_FILENAME {
|
||||
print!(" {}", &filename.to_string_lossy());
|
||||
}
|
||||
|
||||
println!("\x1B[39m");
|
||||
}
|
||||
|
||||
Ok(problems.exit_code())
|
||||
}
|
||||
|
||||
fn handle_loading_problem(problem: LoadingProblem) -> io::Result<i32> {
|
||||
match problem {
|
||||
LoadingProblem::FormattedReport(report) => {
|
||||
print!("{}", report);
|
||||
Ok(1)
|
||||
}
|
||||
Err(other) => {
|
||||
panic!("build_file failed with error:\n{:?}", other);
|
||||
_ => {
|
||||
// TODO: tighten up the types here, we should always end up with a
|
||||
// formatted report from load.
|
||||
print!("Failed with error: {:?}", problem);
|
||||
Ok(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,3 +11,4 @@ roc_collections = { path = "../collections" }
|
|||
roc_region = { path = "../region" }
|
||||
roc_module = { path = "../module" }
|
||||
roc_error_macros = { path = "../../error_macros" }
|
||||
roc_problem = { path = "../problem" }
|
||||
|
|
|
@ -7,6 +7,7 @@ use roc_module::{
|
|||
ident::{Lowercase, TagIdIntType, TagName},
|
||||
symbol::Symbol,
|
||||
};
|
||||
use roc_problem::Severity;
|
||||
use roc_region::all::Region;
|
||||
|
||||
use self::Pattern::*;
|
||||
|
@ -149,6 +150,17 @@ pub enum Error {
|
|||
},
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub fn severity(&self) -> Severity {
|
||||
use Severity::*;
|
||||
match self {
|
||||
Error::Incomplete(..) => RuntimeError,
|
||||
Error::Redundant { .. } => Warning,
|
||||
Error::Unmatchable { .. } => Warning,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum Context {
|
||||
BadArg,
|
||||
|
|
|
@ -101,14 +101,14 @@ pub fn load_and_monomorphize_from_str<'a>(
|
|||
exposed_types: ExposedByModule,
|
||||
roc_cache_dir: RocCacheDir<'_>,
|
||||
load_config: LoadConfig,
|
||||
) -> Result<MonomorphizedModule<'a>, LoadingProblem<'a>> {
|
||||
) -> Result<MonomorphizedModule<'a>, LoadMonomorphizedError<'a>> {
|
||||
use LoadResult::*;
|
||||
|
||||
let load_start = LoadStart::from_str(arena, filename, src, roc_cache_dir, src_dir)?;
|
||||
|
||||
match load(arena, load_start, exposed_types, roc_cache_dir, load_config)? {
|
||||
Monomorphized(module) => Ok(module),
|
||||
TypeChecked(_) => unreachable!(""),
|
||||
TypeChecked(module) => Err(LoadMonomorphizedError::ErrorModule(module)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ use roc_parse::header::{HeaderFor, ModuleNameEnum, PackageName};
|
|||
use roc_parse::ident::UppercaseIdent;
|
||||
use roc_parse::module::module_defs;
|
||||
use roc_parse::parser::{FileError, Parser, SourceError, SyntaxError};
|
||||
use roc_problem::Severity;
|
||||
use roc_region::all::{LineInfo, Loc, Region};
|
||||
use roc_reporting::report::{Annotation, Palette, RenderTarget};
|
||||
use roc_solve::module::{extract_module_owned_implementations, Solved, SolvedModule};
|
||||
|
@ -97,20 +98,28 @@ pub struct LoadConfig {
|
|||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum ExecutionMode {
|
||||
Test,
|
||||
Check,
|
||||
Executable,
|
||||
/// Like [`ExecutionMode::Executable`], but stops in the presence of type errors.
|
||||
ExecutableIfCheck,
|
||||
/// Test is like [`ExecutionMode::ExecutableIfCheck`], but rather than producing a proper
|
||||
/// executable, run tests.
|
||||
Test,
|
||||
}
|
||||
|
||||
impl ExecutionMode {
|
||||
fn goal_phase(&self) -> Phase {
|
||||
match self {
|
||||
ExecutionMode::Test | ExecutionMode::Executable => Phase::MakeSpecializations,
|
||||
ExecutionMode::Check | ExecutionMode::ExecutableIfCheck => Phase::SolveTypes,
|
||||
ExecutionMode::Executable => Phase::MakeSpecializations,
|
||||
ExecutionMode::Check | ExecutionMode::ExecutableIfCheck | ExecutionMode::Test => {
|
||||
Phase::SolveTypes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn build_if_checks(&self) -> bool {
|
||||
matches!(self, Self::ExecutableIfCheck | Self::Test)
|
||||
}
|
||||
}
|
||||
|
||||
/// Struct storing various intermediate stages by their ModuleId
|
||||
|
@ -141,18 +150,22 @@ struct ModuleCache<'a> {
|
|||
}
|
||||
|
||||
impl<'a> ModuleCache<'a> {
|
||||
pub fn total_problems(&self) -> usize {
|
||||
let mut total = 0;
|
||||
fn has_can_errors(&self) -> bool {
|
||||
self.can_problems
|
||||
.values()
|
||||
.flatten()
|
||||
.any(|problem| problem.severity() == Severity::RuntimeError)
|
||||
}
|
||||
|
||||
for problems in self.can_problems.values() {
|
||||
total += problems.len();
|
||||
}
|
||||
fn has_type_errors(&self) -> bool {
|
||||
self.type_problems
|
||||
.values()
|
||||
.flatten()
|
||||
.any(|problem| problem.severity() == Severity::RuntimeError)
|
||||
}
|
||||
|
||||
for problems in self.type_problems.values() {
|
||||
total += problems.len();
|
||||
}
|
||||
|
||||
total
|
||||
pub fn has_errors(&self) -> bool {
|
||||
self.has_can_errors() || self.has_type_errors()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2615,7 +2628,7 @@ fn update<'a>(
|
|||
let finish_type_checking = is_host_exposed &&
|
||||
(state.goal_phase() == Phase::SolveTypes)
|
||||
// If we're running in check-and-then-build mode, only exit now there are errors.
|
||||
&& (!matches!(state.exec_mode, ExecutionMode::ExecutableIfCheck) || state.module_cache.total_problems() > 0);
|
||||
&& (!state.exec_mode.build_if_checks() || state.module_cache.has_errors());
|
||||
|
||||
if finish_type_checking {
|
||||
debug_assert!(work.is_empty());
|
||||
|
@ -2623,7 +2636,7 @@ fn update<'a>(
|
|||
|
||||
state.timings.insert(module_id, module_timing);
|
||||
|
||||
if matches!(state.exec_mode, ExecutionMode::ExecutableIfCheck) {
|
||||
if state.exec_mode.build_if_checks() {
|
||||
// We there may outstanding modules in the typecheked cache whose ident IDs
|
||||
// aren't registered; transfer all of their idents over to the state, since
|
||||
// we're now done and ready to report errors.
|
||||
|
@ -2677,9 +2690,7 @@ fn update<'a>(
|
|||
},
|
||||
);
|
||||
|
||||
if state.goal_phase() > Phase::SolveTypes
|
||||
|| matches!(state.exec_mode, ExecutionMode::ExecutableIfCheck)
|
||||
{
|
||||
if state.goal_phase() > Phase::SolveTypes || state.exec_mode.build_if_checks() {
|
||||
let layout_cache = state.layout_caches.pop().unwrap_or_else(|| {
|
||||
LayoutCache::new(state.layout_interner.fork(), state.target_info)
|
||||
});
|
||||
|
@ -2703,17 +2714,12 @@ fn update<'a>(
|
|||
state.timings.insert(module_id, module_timing);
|
||||
}
|
||||
|
||||
let work = if is_host_exposed
|
||||
&& matches!(state.exec_mode, ExecutionMode::ExecutableIfCheck)
|
||||
{
|
||||
let work = if is_host_exposed && state.exec_mode.build_if_checks() {
|
||||
debug_assert!(
|
||||
work.is_empty(),
|
||||
"work left over after host exposed is checked"
|
||||
);
|
||||
|
||||
// Update the goal phase to target full codegen.
|
||||
state.exec_mode = ExecutionMode::Executable;
|
||||
|
||||
// Load the find + make specializations portion of the dependency graph.
|
||||
state
|
||||
.dependencies
|
||||
|
@ -2785,7 +2791,10 @@ fn update<'a>(
|
|||
layout_cache,
|
||||
..
|
||||
} => {
|
||||
debug_assert!(state.goal_phase() == Phase::MakeSpecializations);
|
||||
debug_assert!(
|
||||
state.goal_phase() == Phase::MakeSpecializations
|
||||
|| state.exec_mode.build_if_checks()
|
||||
);
|
||||
|
||||
log!("made specializations for {:?}", module_id);
|
||||
|
||||
|
@ -5987,7 +5996,7 @@ fn run_task<'a>(
|
|||
}
|
||||
|
||||
fn to_file_problem_report(filename: &Path, error: io::ErrorKind) -> String {
|
||||
use roc_reporting::report::{Report, RocDocAllocator, Severity, DEFAULT_PALETTE};
|
||||
use roc_reporting::report::{Report, RocDocAllocator, DEFAULT_PALETTE};
|
||||
use ven_pretty::DocAllocator;
|
||||
|
||||
let src_lines: Vec<&str> = Vec::new();
|
||||
|
@ -6074,7 +6083,7 @@ fn to_import_cycle_report(
|
|||
filename: PathBuf,
|
||||
render: RenderTarget,
|
||||
) -> String {
|
||||
use roc_reporting::report::{Report, RocDocAllocator, Severity, DEFAULT_PALETTE};
|
||||
use roc_reporting::report::{Report, RocDocAllocator, DEFAULT_PALETTE};
|
||||
use ven_pretty::DocAllocator;
|
||||
|
||||
// import_cycle looks like CycleModule, Import1, ..., ImportN, CycleModule
|
||||
|
@ -6134,7 +6143,7 @@ fn to_incorrect_module_name_report<'a>(
|
|||
src: &'a [u8],
|
||||
render: RenderTarget,
|
||||
) -> String {
|
||||
use roc_reporting::report::{Report, RocDocAllocator, Severity, DEFAULT_PALETTE};
|
||||
use roc_reporting::report::{Report, RocDocAllocator, DEFAULT_PALETTE};
|
||||
use ven_pretty::DocAllocator;
|
||||
|
||||
let IncorrectModuleName {
|
||||
|
@ -6220,7 +6229,7 @@ fn to_parse_problem_report<'a>(
|
|||
}
|
||||
|
||||
fn to_missing_platform_report(module_id: ModuleId, other: PlatformPath) -> String {
|
||||
use roc_reporting::report::{Report, RocDocAllocator, Severity, DEFAULT_PALETTE};
|
||||
use roc_reporting::report::{Report, RocDocAllocator, DEFAULT_PALETTE};
|
||||
use ven_pretty::DocAllocator;
|
||||
use PlatformPath::*;
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@ use roc_parse::pattern::PatternType;
|
|||
use roc_region::all::{Loc, Region};
|
||||
use roc_types::types::AliasKind;
|
||||
|
||||
use crate::Severity;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct CycleEntry {
|
||||
pub symbol: Symbol,
|
||||
|
@ -205,6 +207,71 @@ pub enum Problem {
|
|||
}
|
||||
|
||||
impl Problem {
|
||||
pub fn severity(&self) -> Severity {
|
||||
use Severity::{RuntimeError, Warning};
|
||||
|
||||
match self {
|
||||
Problem::UnusedDef(_, _) => Warning,
|
||||
Problem::UnusedImport(_, _) => Warning,
|
||||
Problem::UnusedModuleImport(_, _) => Warning,
|
||||
Problem::ExposedButNotDefined(_) => RuntimeError,
|
||||
Problem::UnknownGeneratesWith(_) => RuntimeError,
|
||||
Problem::UnusedArgument(_, _, _, _) => Warning,
|
||||
Problem::UnusedBranchDef(_, _) => Warning,
|
||||
Problem::PrecedenceProblem(_) => RuntimeError,
|
||||
Problem::UnsupportedPattern(_, _) => RuntimeError,
|
||||
Problem::Shadowing { .. } => RuntimeError,
|
||||
Problem::CyclicAlias(..) => RuntimeError,
|
||||
Problem::BadRecursion(_) => RuntimeError,
|
||||
Problem::PhantomTypeArgument { .. } => Warning,
|
||||
Problem::UnboundTypeVariable { .. } => RuntimeError,
|
||||
Problem::DuplicateRecordFieldValue { .. } => Warning,
|
||||
Problem::DuplicateRecordFieldType { .. } => RuntimeError,
|
||||
Problem::InvalidOptionalValue { .. } => RuntimeError,
|
||||
Problem::DuplicateTag { .. } => RuntimeError,
|
||||
Problem::RuntimeError(_) => RuntimeError,
|
||||
Problem::SignatureDefMismatch { .. } => RuntimeError,
|
||||
Problem::InvalidAliasRigid { .. } => RuntimeError,
|
||||
Problem::InvalidInterpolation(_) => RuntimeError,
|
||||
Problem::InvalidHexadecimal(_) => RuntimeError,
|
||||
Problem::InvalidUnicodeCodePt(_) => RuntimeError,
|
||||
Problem::NestedDatatype { .. } => RuntimeError,
|
||||
Problem::InvalidExtensionType { .. } => RuntimeError,
|
||||
Problem::AbilityHasTypeVariables { .. } => RuntimeError,
|
||||
Problem::HasClauseIsNotAbility { .. } => RuntimeError,
|
||||
Problem::IllegalHasClause { .. } => RuntimeError,
|
||||
Problem::DuplicateHasAbility { .. } => Warning,
|
||||
Problem::AbilityMemberMissingHasClause { .. } => RuntimeError,
|
||||
Problem::AbilityMemberMultipleBoundVars { .. } => RuntimeError,
|
||||
Problem::AbilityNotOnToplevel { .. } => RuntimeError, // Ideally, could be compiled
|
||||
Problem::AbilityUsedAsType(_, _, _) => RuntimeError,
|
||||
Problem::NestedSpecialization(_, _) => RuntimeError, // Ideally, could be compiled
|
||||
Problem::IllegalDerivedAbility(_) => RuntimeError,
|
||||
Problem::ImplementationNotFound { .. } => RuntimeError,
|
||||
Problem::NotAnAbilityMember { .. } => RuntimeError,
|
||||
Problem::OptionalAbilityImpl { .. } => RuntimeError,
|
||||
Problem::QualifiedAbilityImpl { .. } => RuntimeError,
|
||||
Problem::AbilityImplNotIdent { .. } => RuntimeError,
|
||||
Problem::DuplicateImpl { .. } => Warning, // First impl is used at runtime
|
||||
Problem::NotAnAbility(_) => Warning,
|
||||
Problem::ImplementsNonRequired { .. } => Warning,
|
||||
Problem::DoesNotImplementAbility { .. } => RuntimeError,
|
||||
Problem::NotBoundInAllPatterns { .. } => RuntimeError,
|
||||
Problem::NoIdentifiersIntroduced(_) => Warning,
|
||||
Problem::OverloadedSpecialization { .. } => Warning, // Ideally, will compile
|
||||
Problem::UnnecessaryOutputWildcard { .. } => Warning,
|
||||
// TODO: sometimes this can just be a warning, e.g. if you have [1, .., .., 2] but we
|
||||
// don't catch that yet.
|
||||
Problem::MultipleListRestPattern { .. } => RuntimeError,
|
||||
Problem::BadTypeArguments { .. } => RuntimeError,
|
||||
// TODO: this can be a warning instead if we recover the program by
|
||||
// injecting a crash message
|
||||
Problem::UnappliedCrash { .. } => RuntimeError,
|
||||
Problem::OverAppliedCrash { .. } => RuntimeError,
|
||||
Problem::DefsOnlyUsedInRecursion(_, _) => Warning,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a Region value from the Problem, if possible.
|
||||
/// Some problems have more than one region; in those cases,
|
||||
/// this tries to pick the one that's closest to the original
|
||||
|
|
|
@ -3,3 +3,15 @@
|
|||
// See github.com/roc-lang/roc/issues/800 for discussion of the large_enum_variant check.
|
||||
#![allow(clippy::large_enum_variant)]
|
||||
pub mod can;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Severity {
|
||||
/// This will cause a runtime error if some code get srun
|
||||
/// (e.g. type mismatch, naming error)
|
||||
RuntimeError,
|
||||
|
||||
/// This will never cause the code to misbehave,
|
||||
/// but should be cleaned up
|
||||
/// (e.g. unused def, unused import)
|
||||
Warning,
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Provides types to describe problems that can occur during solving.
|
||||
use roc_can::expected::{Expected, PExpected};
|
||||
use roc_module::{ident::Lowercase, symbol::Symbol};
|
||||
use roc_problem::can::CycleEntry;
|
||||
use roc_problem::{can::CycleEntry, Severity};
|
||||
use roc_region::all::Region;
|
||||
|
||||
use roc_types::types::{Category, ErrorType, PatternCategory};
|
||||
|
@ -31,6 +31,27 @@ pub enum TypeError {
|
|||
},
|
||||
}
|
||||
|
||||
impl TypeError {
|
||||
pub fn severity(&self) -> Severity {
|
||||
use Severity::*;
|
||||
match self {
|
||||
TypeError::BadExpr(..) => RuntimeError,
|
||||
TypeError::BadPattern(..) => RuntimeError,
|
||||
TypeError::CircularType(..) => RuntimeError,
|
||||
TypeError::CircularDef(_) => RuntimeError,
|
||||
TypeError::UnexposedLookup(_) => RuntimeError,
|
||||
TypeError::UnfulfilledAbility(_) => RuntimeError,
|
||||
TypeError::BadExprMissingAbility(_, _, _, _) => RuntimeError,
|
||||
TypeError::BadPatternMissingAbility(_, _, _, _) => RuntimeError,
|
||||
// NB: if bidirectional exhaustiveness checking is implemented, the other direction
|
||||
// is also not a runtime error.
|
||||
TypeError::Exhaustive(exhtv) => exhtv.severity(),
|
||||
TypeError::StructuralSpecialization { .. } => RuntimeError,
|
||||
TypeError::WrongSpecialization { .. } => RuntimeError,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone)]
|
||||
pub enum Unfulfilled {
|
||||
/// No claimed implementation of an ability for an opaque type.
|
||||
|
|
|
@ -7,7 +7,7 @@ use roc_build::link::llvm_module_to_dylib;
|
|||
use roc_collections::all::MutSet;
|
||||
use roc_gen_llvm::llvm::externs::add_default_roc_externs;
|
||||
use roc_gen_llvm::{llvm::build::LlvmBackendMode, run_roc::RocCallResult};
|
||||
use roc_load::{EntryPoint, ExecutionMode, LoadConfig, Threading};
|
||||
use roc_load::{EntryPoint, ExecutionMode, LoadConfig, LoadMonomorphizedError, Threading};
|
||||
use roc_mono::ir::{CrashTag, OptLevel};
|
||||
use roc_packaging::cache::RocCacheDir;
|
||||
use roc_region::all::LineInfo;
|
||||
|
@ -87,7 +87,9 @@ fn create_llvm_module<'a>(
|
|||
|
||||
let mut loaded = match loaded {
|
||||
Ok(x) => x,
|
||||
Err(roc_load::LoadingProblem::FormattedReport(report)) => {
|
||||
Err(LoadMonomorphizedError::LoadingProblem(roc_load::LoadingProblem::FormattedReport(
|
||||
report,
|
||||
))) => {
|
||||
println!("{}", report);
|
||||
panic!();
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ const EXPANDED_STACK_SIZE: usize = 8 * 1024 * 1024;
|
|||
use roc_collections::all::MutMap;
|
||||
use roc_load::ExecutionMode;
|
||||
use roc_load::LoadConfig;
|
||||
use roc_load::LoadMonomorphizedError;
|
||||
use roc_load::Threading;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::ir::Proc;
|
||||
|
@ -113,7 +114,9 @@ fn compiles_to_ir(test_name: &str, src: &str) {
|
|||
|
||||
let mut loaded = match loaded {
|
||||
Ok(x) => x,
|
||||
Err(roc_load::LoadingProblem::FormattedReport(report)) => {
|
||||
Err(LoadMonomorphizedError::LoadingProblem(roc_load::LoadingProblem::FormattedReport(
|
||||
report,
|
||||
))) => {
|
||||
println!("{}", report);
|
||||
panic!();
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ roc_load = {path = "../compiler/load"}
|
|||
roc_module = {path = "../compiler/module"}
|
||||
roc_mono = {path = "../compiler/mono"}
|
||||
roc_parse = {path = "../compiler/parse"}
|
||||
roc_problem = {path = "../compiler/problem"}
|
||||
roc_region = {path = "../compiler/region"}
|
||||
roc_packaging = {path = "../packaging"}
|
||||
roc_reporting = {path = "../reporting"}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use bumpalo::Bump;
|
||||
use roc_load::{ExecutionMode, LoadConfig, Threading};
|
||||
use roc_load::{ExecutionMode, LoadConfig, LoadMonomorphizedError, Threading};
|
||||
use roc_packaging::cache::{self, RocCacheDir};
|
||||
use roc_reporting::report::{Palette, Severity};
|
||||
use roc_problem::Severity;
|
||||
use roc_reporting::report::Palette;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use roc_fmt::annotation::Formattable;
|
||||
|
@ -72,7 +73,13 @@ pub fn compile_to_mono<'a, 'i, I: Iterator<Item = &'i str>>(
|
|||
|
||||
let mut loaded = match loaded {
|
||||
Ok(v) => v,
|
||||
Err(LoadingProblem::FormattedReport(report)) => {
|
||||
Err(LoadMonomorphizedError::ErrorModule(m)) => {
|
||||
todo!(
|
||||
"error while loading module: {:?}",
|
||||
(m.can_problems, m.type_problems)
|
||||
);
|
||||
}
|
||||
Err(LoadMonomorphizedError::LoadingProblem(LoadingProblem::FormattedReport(report))) => {
|
||||
return (
|
||||
None,
|
||||
Problems {
|
||||
|
|
|
@ -87,7 +87,7 @@ mod test {
|
|||
use indoc::indoc;
|
||||
use pretty_assertions::assert_eq;
|
||||
use roc_gen_llvm::{llvm::build::LlvmBackendMode, run_roc::RocCallResult, run_roc_dylib};
|
||||
use roc_load::{ExecutionMode, LoadConfig, Threading};
|
||||
use roc_load::{ExecutionMode, LoadConfig, LoadMonomorphizedError, Threading};
|
||||
use roc_packaging::cache::RocCacheDir;
|
||||
use roc_reporting::report::{RenderTarget, DEFAULT_PALETTE};
|
||||
use target_lexicon::Triple;
|
||||
|
@ -119,7 +119,7 @@ mod test {
|
|||
threading: Threading::Single,
|
||||
exec_mode: ExecutionMode::Test,
|
||||
};
|
||||
let loaded = roc_load::load_and_monomorphize_from_str(
|
||||
let loaded = match roc_load::load_and_monomorphize_from_str(
|
||||
arena,
|
||||
filename,
|
||||
source,
|
||||
|
@ -127,8 +127,13 @@ mod test {
|
|||
Default::default(),
|
||||
RocCacheDir::Disallowed,
|
||||
load_config,
|
||||
)
|
||||
.unwrap();
|
||||
) {
|
||||
Ok(m) => m,
|
||||
Err(LoadMonomorphizedError::ErrorModule(m)) => {
|
||||
panic!("{:?}", (m.can_problems, m.type_problems))
|
||||
}
|
||||
Err(e) => panic!("{e:?}"),
|
||||
};
|
||||
|
||||
let mut loaded = loaded;
|
||||
let mut expectations = std::mem::take(&mut loaded.expectations);
|
||||
|
@ -442,8 +447,8 @@ mod test {
|
|||
main = 0
|
||||
|
||||
expect
|
||||
vec1 = { x: 1.0f64, y: 2.0f64 }
|
||||
vec2 = { x: 4.0f64, y: 8.0f64 }
|
||||
vec1 = { x: 1u8, y: 2u8 }
|
||||
vec2 = { x: 4u8, y: 8u8 }
|
||||
|
||||
vec1 == vec2
|
||||
"#
|
||||
|
@ -453,17 +458,17 @@ mod test {
|
|||
This expectation failed:
|
||||
|
||||
5│> expect
|
||||
6│> vec1 = { x: 1.0f64, y: 2.0f64 }
|
||||
7│> vec2 = { x: 4.0f64, y: 8.0f64 }
|
||||
6│> vec1 = { x: 1u8, y: 2u8 }
|
||||
7│> vec2 = { x: 4u8, y: 8u8 }
|
||||
8│>
|
||||
9│> vec1 == vec2
|
||||
|
||||
When it failed, these variables had these values:
|
||||
|
||||
vec1 : { x : F64, y : F64 }
|
||||
vec1 : { x : U8, y : U8 }
|
||||
vec1 = { x: 1, y: 2 }
|
||||
|
||||
vec2 : { x : F64, y : F64 }
|
||||
vec2 : { x : U8, y : U8 }
|
||||
vec2 = { x: 4, y: 8 }
|
||||
"#
|
||||
),
|
||||
|
|
|
@ -29,9 +29,8 @@ pub fn report_problems(
|
|||
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,
|
||||
};
|
||||
use crate::report::{can_problem, type_problem, Report, RocDocAllocator, DEFAULT_PALETTE};
|
||||
use roc_problem::Severity::*;
|
||||
let palette = DEFAULT_PALETTE;
|
||||
|
||||
// This will often over-allocate total memory, but it means we definitely
|
||||
|
|
|
@ -6,12 +6,13 @@ use roc_problem::can::{
|
|||
BadPattern, CycleEntry, ExtensionTypeKind, FloatErrorKind, IntErrorKind, Problem, RuntimeError,
|
||||
ShadowKind,
|
||||
};
|
||||
use roc_problem::Severity;
|
||||
use roc_region::all::{LineColumn, LineColumnRegion, LineInfo, Loc, Region};
|
||||
use roc_types::types::AliasKind;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::error::r#type::suggest;
|
||||
use crate::report::{Annotation, Report, RocDocAllocator, RocDocBuilder, Severity};
|
||||
use crate::report::{Annotation, Report, RocDocAllocator, RocDocBuilder};
|
||||
use ven_pretty::DocAllocator;
|
||||
|
||||
const SYNTAX_PROBLEM: &str = "SYNTAX PROBLEM";
|
||||
|
@ -67,7 +68,7 @@ pub fn can_problem<'b>(
|
|||
) -> Report<'b> {
|
||||
let doc;
|
||||
let title;
|
||||
let severity;
|
||||
let severity = problem.severity();
|
||||
|
||||
match problem {
|
||||
Problem::UnusedDef(symbol, region) => {
|
||||
|
@ -86,7 +87,6 @@ pub fn can_problem<'b>(
|
|||
]);
|
||||
|
||||
title = UNUSED_DEF.to_string();
|
||||
severity = Severity::Warning;
|
||||
}
|
||||
Problem::UnusedImport(symbol, region) => {
|
||||
doc = alloc.stack([
|
||||
|
@ -103,7 +103,6 @@ pub fn can_problem<'b>(
|
|||
]);
|
||||
|
||||
title = UNUSED_IMPORT.to_string();
|
||||
severity = Severity::Warning;
|
||||
}
|
||||
Problem::UnusedModuleImport(module_id, region) => {
|
||||
doc = alloc.stack([
|
||||
|
@ -121,7 +120,6 @@ pub fn can_problem<'b>(
|
|||
]);
|
||||
|
||||
title = UNUSED_IMPORT.to_string();
|
||||
severity = Severity::Warning;
|
||||
}
|
||||
Problem::DefsOnlyUsedInRecursion(1, region) => {
|
||||
doc = alloc.stack([
|
||||
|
@ -133,7 +131,6 @@ pub fn can_problem<'b>(
|
|||
]);
|
||||
|
||||
title = "DEFINITION ONLY USED IN RECURSION".to_string();
|
||||
severity = Severity::Warning;
|
||||
}
|
||||
Problem::DefsOnlyUsedInRecursion(n, region) => {
|
||||
doc = alloc.stack([
|
||||
|
@ -149,7 +146,6 @@ pub fn can_problem<'b>(
|
|||
]);
|
||||
|
||||
title = "DEFINITIONs ONLY USED IN RECURSION".to_string();
|
||||
severity = Severity::Warning;
|
||||
}
|
||||
Problem::ExposedButNotDefined(symbol) => {
|
||||
doc = alloc.stack([
|
||||
|
@ -165,7 +161,6 @@ pub fn can_problem<'b>(
|
|||
]);
|
||||
|
||||
title = MISSING_DEFINITION.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::UnknownGeneratesWith(loc_ident) => {
|
||||
doc = alloc.stack([
|
||||
|
@ -180,7 +175,6 @@ pub fn can_problem<'b>(
|
|||
]);
|
||||
|
||||
title = UNKNOWN_GENERATES_WITH.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::UnusedArgument(closure_symbol, is_anonymous, argument_symbol, region) => {
|
||||
let line = "\". Adding an underscore at the start of a variable name is a way of saying that the variable is not used.";
|
||||
|
@ -215,7 +209,6 @@ pub fn can_problem<'b>(
|
|||
]);
|
||||
|
||||
title = UNUSED_ARG.to_string();
|
||||
severity = Severity::Warning;
|
||||
}
|
||||
Problem::UnusedBranchDef(symbol, region) => {
|
||||
doc = alloc.stack([
|
||||
|
@ -236,7 +229,6 @@ pub fn can_problem<'b>(
|
|||
]);
|
||||
|
||||
title = UNUSED_DEF.to_string();
|
||||
severity = Severity::Warning;
|
||||
}
|
||||
Problem::PrecedenceProblem(BothNonAssociative(region, left_bin_op, right_bin_op)) => {
|
||||
doc = alloc.stack([
|
||||
|
@ -265,7 +257,6 @@ pub fn can_problem<'b>(
|
|||
]);
|
||||
|
||||
title = SYNTAX_PROBLEM.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::UnsupportedPattern(BadPattern::Unsupported(pattern_type), region) => {
|
||||
use roc_parse::pattern::PatternType::*;
|
||||
|
@ -296,7 +287,6 @@ pub fn can_problem<'b>(
|
|||
]);
|
||||
|
||||
title = SYNTAX_PROBLEM.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::Shadowing {
|
||||
original_region,
|
||||
|
@ -308,7 +298,6 @@ pub fn can_problem<'b>(
|
|||
|
||||
doc = res_doc;
|
||||
title = res_title.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::CyclicAlias(symbol, region, others, alias_kind) => {
|
||||
let answer = crate::error::r#type::cyclic_alias(
|
||||
|
@ -317,7 +306,6 @@ pub fn can_problem<'b>(
|
|||
|
||||
doc = answer.0;
|
||||
title = answer.1;
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::PhantomTypeArgument {
|
||||
typ: alias,
|
||||
|
@ -345,7 +333,6 @@ pub fn can_problem<'b>(
|
|||
]);
|
||||
|
||||
title = UNUSED_ALIAS_PARAM.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::UnboundTypeVariable {
|
||||
typ: alias,
|
||||
|
@ -382,12 +369,10 @@ pub fn can_problem<'b>(
|
|||
doc = alloc.stack(stack);
|
||||
|
||||
title = UNBOUND_TYPE_VARIABLE.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::BadRecursion(entries) => {
|
||||
doc = to_circular_def_doc(alloc, lines, &entries);
|
||||
title = CIRCULAR_DEF.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::DuplicateRecordFieldValue {
|
||||
field_name,
|
||||
|
@ -422,7 +407,6 @@ pub fn can_problem<'b>(
|
|||
]);
|
||||
|
||||
title = DUPLICATE_FIELD_NAME.to_string();
|
||||
severity = Severity::Warning;
|
||||
}
|
||||
Problem::InvalidOptionalValue {
|
||||
field_name,
|
||||
|
@ -471,7 +455,6 @@ pub fn can_problem<'b>(
|
|||
]);
|
||||
|
||||
title = DUPLICATE_FIELD_NAME.to_string();
|
||||
severity = Severity::Warning;
|
||||
}
|
||||
Problem::DuplicateTag {
|
||||
tag_name,
|
||||
|
@ -506,7 +489,6 @@ pub fn can_problem<'b>(
|
|||
]);
|
||||
|
||||
title = DUPLICATE_TAG_NAME.to_string();
|
||||
severity = Severity::Warning;
|
||||
}
|
||||
Problem::SignatureDefMismatch {
|
||||
ref annotation_pattern,
|
||||
|
@ -523,7 +505,6 @@ pub fn can_problem<'b>(
|
|||
]);
|
||||
|
||||
title = NAMING_PROBLEM.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::InvalidAliasRigid {
|
||||
alias_name: type_name,
|
||||
|
@ -546,7 +527,6 @@ pub fn can_problem<'b>(
|
|||
]);
|
||||
|
||||
title = SYNTAX_PROBLEM.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::InvalidHexadecimal(region) => {
|
||||
doc = alloc.stack([
|
||||
|
@ -563,7 +543,6 @@ pub fn can_problem<'b>(
|
|||
]);
|
||||
|
||||
title = INVALID_UNICODE.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::InvalidUnicodeCodePt(region) => {
|
||||
doc = alloc.stack([
|
||||
|
@ -573,7 +552,6 @@ pub fn can_problem<'b>(
|
|||
]);
|
||||
|
||||
title = INVALID_UNICODE.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::InvalidInterpolation(region) => {
|
||||
doc = alloc.stack([
|
||||
|
@ -590,14 +568,12 @@ pub fn can_problem<'b>(
|
|||
]);
|
||||
|
||||
title = SYNTAX_PROBLEM.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::RuntimeError(runtime_error) => {
|
||||
let answer = pretty_runtime_error(alloc, lines, runtime_error);
|
||||
|
||||
doc = answer.0;
|
||||
title = answer.1.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::NestedDatatype {
|
||||
alias,
|
||||
|
@ -625,7 +601,6 @@ pub fn can_problem<'b>(
|
|||
]);
|
||||
|
||||
title = NESTED_DATATYPE.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
|
||||
Problem::InvalidExtensionType { region, kind } => {
|
||||
|
@ -653,7 +628,6 @@ pub fn can_problem<'b>(
|
|||
]);
|
||||
|
||||
title = INVALID_EXTENSION_TYPE.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
|
||||
Problem::AbilityHasTypeVariables {
|
||||
|
@ -672,7 +646,6 @@ pub fn can_problem<'b>(
|
|||
),
|
||||
]);
|
||||
title = ABILITY_HAS_TYPE_VARIABLES.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
|
||||
Problem::HasClauseIsNotAbility {
|
||||
|
@ -683,7 +656,6 @@ pub fn can_problem<'b>(
|
|||
alloc.region(lines.convert_region(clause_region)),
|
||||
]);
|
||||
title = HAS_CLAUSE_IS_NOT_AN_ABILITY.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
|
||||
Problem::IllegalHasClause { region } => {
|
||||
|
@ -702,7 +674,6 @@ pub fn can_problem<'b>(
|
|||
]),
|
||||
]);
|
||||
title = ILLEGAL_HAS_CLAUSE.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
|
||||
Problem::DuplicateHasAbility { ability, region } => {
|
||||
|
@ -720,7 +691,6 @@ pub fn can_problem<'b>(
|
|||
]),
|
||||
]);
|
||||
title = "DUPLICATE BOUND ABILITY".to_string();
|
||||
severity = Severity::Warning;
|
||||
}
|
||||
|
||||
Problem::AbilityMemberMissingHasClause {
|
||||
|
@ -755,7 +725,6 @@ pub fn can_problem<'b>(
|
|||
.reflow("Otherwise, the function does not need to be part of the ability!")]),
|
||||
]);
|
||||
title = ABILITY_MEMBER_MISSING_HAS_CLAUSE.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
|
||||
Problem::AbilityMemberMultipleBoundVars {
|
||||
|
@ -783,7 +752,6 @@ pub fn can_problem<'b>(
|
|||
])
|
||||
]);
|
||||
title = ABILITY_MEMBER_BINDS_MULTIPLE_VARIABLES.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
|
||||
Problem::AbilityNotOnToplevel { region } => {
|
||||
|
@ -795,7 +763,6 @@ pub fn can_problem<'b>(
|
|||
alloc.reflow("Abilities can only be defined on the top-level of a Roc module."),
|
||||
]);
|
||||
title = ABILITY_NOT_ON_TOPLEVEL.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
|
||||
Problem::AbilityUsedAsType(suggested_var_name, ability, region) => {
|
||||
|
@ -823,7 +790,6 @@ pub fn can_problem<'b>(
|
|||
])),
|
||||
]);
|
||||
title = ABILITY_USED_AS_TYPE.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::NestedSpecialization(member, region) => {
|
||||
doc = alloc.stack([
|
||||
|
@ -836,7 +802,6 @@ pub fn can_problem<'b>(
|
|||
alloc.reflow("Specializations can only be defined on the top-level of a module."),
|
||||
]);
|
||||
title = SPECIALIZATION_NOT_ON_TOPLEVEL.to_string();
|
||||
severity = Severity::Warning;
|
||||
}
|
||||
Problem::IllegalDerivedAbility(region) => {
|
||||
doc = alloc.stack([
|
||||
|
@ -848,7 +813,6 @@ pub fn can_problem<'b>(
|
|||
.append(list_builtin_abilities(alloc)),
|
||||
]);
|
||||
title = ILLEGAL_DERIVE.to_string();
|
||||
severity = Severity::Warning;
|
||||
}
|
||||
Problem::NotAnAbility(region) => {
|
||||
doc = alloc.stack([
|
||||
|
@ -857,7 +821,6 @@ pub fn can_problem<'b>(
|
|||
alloc.reflow("Only abilities can be implemented."),
|
||||
]);
|
||||
title = NOT_AN_ABILITY.to_string();
|
||||
severity = Severity::Warning;
|
||||
}
|
||||
Problem::NotAnAbilityMember {
|
||||
ability,
|
||||
|
@ -872,7 +835,6 @@ pub fn can_problem<'b>(
|
|||
alloc.reflow("Only implementations for members an ability has can be specified in this location.")
|
||||
]);
|
||||
title = NOT_AN_ABILITY_MEMBER.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::ImplementationNotFound { member, region } => {
|
||||
let member_str = member.as_str(alloc.interns);
|
||||
|
@ -884,7 +846,6 @@ pub fn can_problem<'b>(
|
|||
alloc.tip().append(alloc.concat([alloc.reflow("consider adding a value of name "), alloc.symbol_unqualified(member), alloc.reflow(" in this scope, or using another variable that implements this ability member, like "), alloc.type_str(&format!("{{ {}: my{} }}", member_str, member_str))]))
|
||||
]);
|
||||
title = IMPLEMENTATION_NOT_FOUND.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::OptionalAbilityImpl { ability, region } => {
|
||||
let hint = if ability.is_builtin() {
|
||||
|
@ -903,7 +864,6 @@ pub fn can_problem<'b>(
|
|||
hint,
|
||||
]);
|
||||
title = OPTIONAL_ABILITY_IMPLEMENTATION.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::QualifiedAbilityImpl { region } => {
|
||||
doc = alloc.stack([
|
||||
|
@ -914,7 +874,6 @@ pub fn can_problem<'b>(
|
|||
),
|
||||
]);
|
||||
title = QUALIFIED_ABILITY_IMPLEMENTATION.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::AbilityImplNotIdent { region } => {
|
||||
doc = alloc.stack([
|
||||
|
@ -926,7 +885,6 @@ pub fn can_problem<'b>(
|
|||
alloc.tip().append(alloc.reflow("consider defining this expression as a variable."))
|
||||
]);
|
||||
title = ABILITY_IMPLEMENTATION_NOT_IDENTIFIER.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::DuplicateImpl {
|
||||
original,
|
||||
|
@ -941,7 +899,6 @@ pub fn can_problem<'b>(
|
|||
.reflow("Only one custom implementation can be defined for an ability member."),
|
||||
]);
|
||||
title = DUPLICATE_IMPLEMENTATION.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::ImplementsNonRequired {
|
||||
region,
|
||||
|
@ -966,7 +923,6 @@ pub fn can_problem<'b>(
|
|||
),
|
||||
]);
|
||||
title = UNNECESSARY_IMPLEMENTATIONS.to_string();
|
||||
severity = Severity::Warning;
|
||||
}
|
||||
Problem::DoesNotImplementAbility {
|
||||
region,
|
||||
|
@ -991,7 +947,6 @@ pub fn can_problem<'b>(
|
|||
),
|
||||
]);
|
||||
title = INCOMPLETE_ABILITY_IMPLEMENTATION.to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::NotBoundInAllPatterns {
|
||||
unbound_symbol,
|
||||
|
@ -1012,7 +967,6 @@ pub fn can_problem<'b>(
|
|||
]),
|
||||
]);
|
||||
title = "NAME NOT BOUND IN ALL PATTERNS".to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::NoIdentifiersIntroduced(region) => {
|
||||
doc = alloc.stack([
|
||||
|
@ -1021,7 +975,6 @@ pub fn can_problem<'b>(
|
|||
alloc.reflow("If you don't need to use the value on the right-hand-side of this assignment, consider removing the assignment. Since Roc is purely functional, assignments that don't introduce variables cannot affect a program's behavior!"),
|
||||
]);
|
||||
title = "UNNECESSARY DEFINITION".to_string();
|
||||
severity = Severity::Warning;
|
||||
}
|
||||
Problem::OverloadedSpecialization {
|
||||
ability_member,
|
||||
|
@ -1041,7 +994,6 @@ pub fn can_problem<'b>(
|
|||
alloc.reflow("Ability specializations can only provide implementations for one opaque type, since all opaque types are different!"),
|
||||
]);
|
||||
title = "OVERLOADED SPECIALIZATION".to_string();
|
||||
severity = Severity::Warning;
|
||||
}
|
||||
Problem::UnnecessaryOutputWildcard { region } => {
|
||||
doc = alloc.stack([
|
||||
|
@ -1061,7 +1013,6 @@ pub fn can_problem<'b>(
|
|||
alloc.reflow("You can safely remove this to make the code more concise without changing what it means."),
|
||||
]);
|
||||
title = "UNNECESSARY WILDCARD".to_string();
|
||||
severity = Severity::Warning;
|
||||
}
|
||||
Problem::MultipleListRestPattern { region } => {
|
||||
doc = alloc.stack([
|
||||
|
@ -1074,7 +1025,6 @@ pub fn can_problem<'b>(
|
|||
]),
|
||||
]);
|
||||
title = "MULTIPLE LIST REST PATTERNS".to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::BadTypeArguments {
|
||||
symbol,
|
||||
|
@ -1114,7 +1064,6 @@ pub fn can_problem<'b>(
|
|||
} else {
|
||||
"TOO FEW TYPE ARGUMENTS".to_string()
|
||||
};
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::UnappliedCrash { region } => {
|
||||
doc = alloc.stack([
|
||||
|
@ -1128,7 +1077,6 @@ pub fn can_problem<'b>(
|
|||
])
|
||||
]);
|
||||
title = "UNAPPLIED CRASH".to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
Problem::OverAppliedCrash { region } => {
|
||||
doc = alloc.stack([
|
||||
|
@ -1144,7 +1092,6 @@ pub fn can_problem<'b>(
|
|||
]),
|
||||
]);
|
||||
title = "OVERAPPLIED CRASH".to_string();
|
||||
severity = Severity::RuntimeError;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::path::PathBuf;
|
|||
use bumpalo::Bump;
|
||||
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
||||
use roc_parse::ast::Expr;
|
||||
use roc_problem::Severity;
|
||||
use roc_region::all::{LineColumnRegion, LineInfo, Region};
|
||||
use roc_types::{
|
||||
subs::{Subs, Variable},
|
||||
|
@ -154,7 +155,7 @@ impl<'a> Renderer<'a> {
|
|||
title: "EXPECT FAILED".into(),
|
||||
doc,
|
||||
filename: self.filename.clone(),
|
||||
severity: crate::report::Severity::RuntimeError,
|
||||
severity: Severity::RuntimeError,
|
||||
};
|
||||
|
||||
let mut buf = String::new();
|
||||
|
@ -225,7 +226,7 @@ impl<'a> Renderer<'a> {
|
|||
title: "EXPECT PANICKED".into(),
|
||||
doc,
|
||||
filename: self.filename.clone(),
|
||||
severity: crate::report::Severity::RuntimeError,
|
||||
severity: Severity::RuntimeError,
|
||||
};
|
||||
|
||||
let mut buf = String::new();
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use roc_parse::parser::{ENumber, FileError, PList, SyntaxError};
|
||||
use roc_problem::Severity;
|
||||
use roc_region::all::{LineColumn, LineColumnRegion, LineInfo, Position, Region};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::report::{Report, RocDocAllocator, RocDocBuilder, Severity};
|
||||
use crate::report::{Report, RocDocAllocator, RocDocBuilder};
|
||||
use ven_pretty::DocAllocator;
|
||||
|
||||
pub fn parse_problem<'a>(
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
use crate::error::canonicalize::{to_circular_def_doc, CIRCULAR_DEF};
|
||||
use crate::report::{Annotation, Report, RocDocAllocator, RocDocBuilder, Severity};
|
||||
use crate::report::{Annotation, Report, RocDocAllocator, RocDocBuilder};
|
||||
use roc_can::expected::{Expected, PExpected};
|
||||
use roc_collections::all::{HumanIndex, MutSet, SendMap};
|
||||
use roc_collections::VecMap;
|
||||
|
@ -8,6 +10,7 @@ use roc_exhaustive::{CtorName, ListArity};
|
|||
use roc_module::called_via::{BinOp, CalledVia};
|
||||
use roc_module::ident::{IdentStr, Lowercase, TagName};
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_problem::Severity;
|
||||
use roc_region::all::{LineInfo, Region};
|
||||
use roc_solve_problem::{
|
||||
NotDerivableContext, NotDerivableDecode, NotDerivableEq, TypeError, UnderivableReason,
|
||||
|
@ -38,26 +41,30 @@ pub fn type_problem<'b>(
|
|||
) -> Option<Report<'b>> {
|
||||
use TypeError::*;
|
||||
|
||||
fn report(title: String, doc: RocDocBuilder<'_>, filename: PathBuf) -> Option<Report<'_>> {
|
||||
Some(Report {
|
||||
title,
|
||||
filename,
|
||||
doc,
|
||||
severity: Severity::RuntimeError,
|
||||
})
|
||||
}
|
||||
let severity = problem.severity();
|
||||
|
||||
let report =
|
||||
move |title: String, doc: RocDocBuilder<'b>, filename: PathBuf| -> Option<Report<'b>> {
|
||||
Some(Report {
|
||||
title,
|
||||
filename,
|
||||
doc,
|
||||
severity,
|
||||
})
|
||||
};
|
||||
|
||||
match problem {
|
||||
BadExpr(region, category, found, expected) => Some(to_expr_report(
|
||||
alloc, lines, filename, region, category, found, expected,
|
||||
alloc, lines, filename, severity, region, category, found, expected,
|
||||
)),
|
||||
BadPattern(region, category, found, expected) => Some(to_pattern_report(
|
||||
alloc, lines, filename, region, category, found, expected,
|
||||
alloc, lines, filename, severity, region, category, found, expected,
|
||||
)),
|
||||
CircularType(region, symbol, overall_type) => Some(to_circular_report(
|
||||
alloc,
|
||||
lines,
|
||||
filename,
|
||||
severity,
|
||||
region,
|
||||
symbol,
|
||||
overall_type,
|
||||
|
@ -103,7 +110,7 @@ pub fn type_problem<'b>(
|
|||
title: "TYPE MISMATCH".to_string(),
|
||||
filename,
|
||||
doc: alloc.stack(stack),
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
};
|
||||
Some(report)
|
||||
}
|
||||
|
@ -125,7 +132,7 @@ pub fn type_problem<'b>(
|
|||
title: "TYPE MISMATCH".to_string(),
|
||||
filename,
|
||||
doc: alloc.stack(stack),
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
};
|
||||
Some(report)
|
||||
}
|
||||
|
@ -133,7 +140,6 @@ pub fn type_problem<'b>(
|
|||
CircularDef(entries) => {
|
||||
let doc = to_circular_def_doc(alloc, lines, &entries);
|
||||
let title = CIRCULAR_DEF.to_string();
|
||||
let severity = Severity::RuntimeError;
|
||||
|
||||
Some(Report {
|
||||
title,
|
||||
|
@ -169,7 +175,7 @@ pub fn type_problem<'b>(
|
|||
title: "ILLEGAL SPECIALIZATION".to_string(),
|
||||
filename,
|
||||
doc: alloc.stack(stack),
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
})
|
||||
}
|
||||
WrongSpecialization {
|
||||
|
@ -198,7 +204,7 @@ pub fn type_problem<'b>(
|
|||
title: "WRONG SPECIALIZATION TYPE".to_string(),
|
||||
filename,
|
||||
doc: alloc.stack(stack),
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -451,11 +457,11 @@ pub fn cyclic_alias<'b>(
|
|||
(doc, "CYCLIC ALIAS".to_string())
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn report_mismatch<'b>(
|
||||
alloc: &'b RocDocAllocator<'b>,
|
||||
lines: &LineInfo,
|
||||
filename: PathBuf,
|
||||
severity: Severity,
|
||||
category: &Category,
|
||||
found: ErrorType,
|
||||
expected_type: ErrorType,
|
||||
|
@ -492,15 +498,15 @@ fn report_mismatch<'b>(
|
|||
title: "TYPE MISMATCH".to_string(),
|
||||
filename,
|
||||
doc: alloc.stack(lines),
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn report_bad_type<'b>(
|
||||
alloc: &'b RocDocAllocator<'b>,
|
||||
lines: &LineInfo,
|
||||
filename: PathBuf,
|
||||
severity: Severity,
|
||||
category: &Category,
|
||||
found: ErrorType,
|
||||
expected_type: ErrorType,
|
||||
|
@ -535,7 +541,7 @@ fn report_bad_type<'b>(
|
|||
title: "TYPE MISMATCH".to_string(),
|
||||
filename,
|
||||
doc: alloc.stack(lines),
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -563,6 +569,7 @@ fn to_expr_report<'b>(
|
|||
alloc: &'b RocDocAllocator<'b>,
|
||||
lines: &LineInfo,
|
||||
filename: PathBuf,
|
||||
severity: Severity,
|
||||
expr_region: roc_region::all::Region,
|
||||
category: Category,
|
||||
found: ErrorType,
|
||||
|
@ -590,6 +597,7 @@ fn to_expr_report<'b>(
|
|||
alloc,
|
||||
lines,
|
||||
filename,
|
||||
severity,
|
||||
opt_sym,
|
||||
".",
|
||||
field,
|
||||
|
@ -620,7 +628,7 @@ fn to_expr_report<'b>(
|
|||
alloc.region(lines.convert_region(expr_region)),
|
||||
comparison,
|
||||
]),
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
}
|
||||
}
|
||||
Expected::FromAnnotation(name, _arity, annotation_source, expected_type) => {
|
||||
|
@ -743,7 +751,7 @@ fn to_expr_report<'b>(
|
|||
},
|
||||
comparison,
|
||||
]),
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
}
|
||||
}
|
||||
Expected::ForReason(reason, expected_type, region) => match reason {
|
||||
|
@ -760,6 +768,7 @@ fn to_expr_report<'b>(
|
|||
alloc,
|
||||
lines,
|
||||
filename,
|
||||
severity,
|
||||
&category,
|
||||
found,
|
||||
expected_type,
|
||||
|
@ -799,6 +808,7 @@ fn to_expr_report<'b>(
|
|||
alloc,
|
||||
lines,
|
||||
filename,
|
||||
severity,
|
||||
&category,
|
||||
found,
|
||||
expected_type,
|
||||
|
@ -837,6 +847,7 @@ fn to_expr_report<'b>(
|
|||
alloc,
|
||||
lines,
|
||||
filename,
|
||||
severity,
|
||||
&category,
|
||||
found,
|
||||
expected_type,
|
||||
|
@ -865,6 +876,7 @@ fn to_expr_report<'b>(
|
|||
alloc,
|
||||
lines,
|
||||
filename,
|
||||
severity,
|
||||
&category,
|
||||
found,
|
||||
expected_type,
|
||||
|
@ -899,6 +911,7 @@ fn to_expr_report<'b>(
|
|||
alloc,
|
||||
lines,
|
||||
filename,
|
||||
severity,
|
||||
&category,
|
||||
found,
|
||||
expected_type,
|
||||
|
@ -924,6 +937,7 @@ fn to_expr_report<'b>(
|
|||
alloc,
|
||||
lines,
|
||||
filename,
|
||||
severity,
|
||||
&category,
|
||||
found,
|
||||
expected_type,
|
||||
|
@ -963,6 +977,7 @@ fn to_expr_report<'b>(
|
|||
alloc,
|
||||
lines,
|
||||
filename,
|
||||
severity,
|
||||
&category,
|
||||
found,
|
||||
expected_type,
|
||||
|
@ -978,6 +993,7 @@ fn to_expr_report<'b>(
|
|||
alloc,
|
||||
lines,
|
||||
filename,
|
||||
severity,
|
||||
&category,
|
||||
found,
|
||||
expected_type,
|
||||
|
@ -1013,6 +1029,7 @@ fn to_expr_report<'b>(
|
|||
alloc,
|
||||
lines,
|
||||
filename,
|
||||
severity,
|
||||
&category,
|
||||
found,
|
||||
expected_type,
|
||||
|
@ -1031,6 +1048,7 @@ fn to_expr_report<'b>(
|
|||
alloc,
|
||||
lines,
|
||||
filename,
|
||||
severity,
|
||||
Some(symbol),
|
||||
"",
|
||||
field,
|
||||
|
@ -1045,6 +1063,7 @@ fn to_expr_report<'b>(
|
|||
alloc,
|
||||
lines,
|
||||
filename,
|
||||
severity,
|
||||
&category,
|
||||
found,
|
||||
expected_type,
|
||||
|
@ -1087,7 +1106,7 @@ fn to_expr_report<'b>(
|
|||
filename,
|
||||
title: "TOO MANY ARGS".to_string(),
|
||||
doc: alloc.stack(lines),
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
}
|
||||
}
|
||||
n => {
|
||||
|
@ -1122,7 +1141,7 @@ fn to_expr_report<'b>(
|
|||
filename,
|
||||
title: "TOO MANY ARGS".to_string(),
|
||||
doc: alloc.stack(lines),
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
}
|
||||
} else {
|
||||
let lines = vec![
|
||||
|
@ -1149,7 +1168,7 @@ fn to_expr_report<'b>(
|
|||
filename,
|
||||
title: "TOO FEW ARGS".to_string(),
|
||||
doc: alloc.stack(lines),
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1166,6 +1185,7 @@ fn to_expr_report<'b>(
|
|||
alloc,
|
||||
lines,
|
||||
filename,
|
||||
severity,
|
||||
&category,
|
||||
found,
|
||||
expected_type,
|
||||
|
@ -1190,6 +1210,7 @@ fn to_expr_report<'b>(
|
|||
alloc,
|
||||
lines,
|
||||
filename,
|
||||
severity,
|
||||
&category,
|
||||
found,
|
||||
expected_type,
|
||||
|
@ -1241,6 +1262,7 @@ fn to_expr_report<'b>(
|
|||
alloc,
|
||||
lines,
|
||||
filename,
|
||||
severity,
|
||||
&category,
|
||||
found,
|
||||
expected_type,
|
||||
|
@ -1281,6 +1303,7 @@ fn to_expr_report<'b>(
|
|||
alloc,
|
||||
lines,
|
||||
filename,
|
||||
severity,
|
||||
&category,
|
||||
found,
|
||||
expected_type,
|
||||
|
@ -1334,7 +1357,7 @@ fn to_expr_report<'b>(
|
|||
title: "TYPE MISMATCH".to_string(),
|
||||
filename,
|
||||
doc: alloc.stack(lines),
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1371,7 +1394,7 @@ fn to_expr_report<'b>(
|
|||
filename,
|
||||
title: "TYPE MISMATCH".to_string(),
|
||||
doc,
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1407,7 +1430,7 @@ fn to_expr_report<'b>(
|
|||
filename,
|
||||
title: "TYPE MISMATCH".to_string(),
|
||||
doc: alloc.stack(lines),
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1756,6 +1779,7 @@ fn to_pattern_report<'b>(
|
|||
alloc: &'b RocDocAllocator<'b>,
|
||||
lines: &LineInfo,
|
||||
filename: PathBuf,
|
||||
severity: Severity,
|
||||
expr_region: roc_region::all::Region,
|
||||
category: PatternCategory,
|
||||
found: ErrorType,
|
||||
|
@ -1782,7 +1806,7 @@ fn to_pattern_report<'b>(
|
|||
filename,
|
||||
title: "TYPE MISMATCH".to_string(),
|
||||
doc,
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1825,7 +1849,7 @@ fn to_pattern_report<'b>(
|
|||
filename,
|
||||
title: "TYPE MISMATCH".to_string(),
|
||||
doc,
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
}
|
||||
}
|
||||
PReason::WhenMatch { index, sub_pattern } => {
|
||||
|
@ -1905,7 +1929,7 @@ fn to_pattern_report<'b>(
|
|||
filename,
|
||||
title: "TYPE MISMATCH".to_string(),
|
||||
doc,
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
}
|
||||
}
|
||||
PReason::ListElem => {
|
||||
|
@ -1932,7 +1956,7 @@ fn to_pattern_report<'b>(
|
|||
filename,
|
||||
title: "TYPE MISMATCH".to_string(),
|
||||
doc,
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
}
|
||||
}
|
||||
PReason::TagArg { .. } | PReason::PatternGuard => {
|
||||
|
@ -2007,6 +2031,7 @@ fn to_circular_report<'b>(
|
|||
alloc: &'b RocDocAllocator<'b>,
|
||||
lines: &LineInfo,
|
||||
filename: PathBuf,
|
||||
severity: Severity,
|
||||
region: roc_region::all::Region,
|
||||
symbol: Symbol,
|
||||
overall_type: ErrorType,
|
||||
|
@ -2031,7 +2056,7 @@ fn to_circular_report<'b>(
|
|||
]),
|
||||
])
|
||||
},
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4077,11 +4102,11 @@ fn type_problem_to_pretty<'b>(
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn report_record_field_typo<'b>(
|
||||
alloc: &'b RocDocAllocator<'b>,
|
||||
lines: &LineInfo,
|
||||
filename: PathBuf,
|
||||
severity: Severity,
|
||||
opt_sym: Option<Symbol>,
|
||||
field_prefix: &str,
|
||||
field: &Lowercase,
|
||||
|
@ -4163,7 +4188,7 @@ fn report_record_field_typo<'b>(
|
|||
filename,
|
||||
title: "TYPE MISMATCH".to_string(),
|
||||
doc,
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4176,6 +4201,8 @@ fn exhaustive_problem<'a>(
|
|||
use roc_exhaustive::Context::*;
|
||||
use roc_exhaustive::Error::*;
|
||||
|
||||
let severity = problem.severity();
|
||||
|
||||
match problem {
|
||||
Incomplete(region, context, missing) => match context {
|
||||
BadArg => {
|
||||
|
@ -4198,7 +4225,7 @@ fn exhaustive_problem<'a>(
|
|||
filename,
|
||||
title: "UNSAFE PATTERN".to_string(),
|
||||
doc,
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
}
|
||||
}
|
||||
BadDestruct => {
|
||||
|
@ -4222,7 +4249,7 @@ fn exhaustive_problem<'a>(
|
|||
filename,
|
||||
title: "UNSAFE PATTERN".to_string(),
|
||||
doc,
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
}
|
||||
}
|
||||
BadCase => {
|
||||
|
@ -4246,7 +4273,7 @@ fn exhaustive_problem<'a>(
|
|||
filename,
|
||||
title: "UNSAFE PATTERN".to_string(),
|
||||
doc,
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -4275,7 +4302,7 @@ fn exhaustive_problem<'a>(
|
|||
filename,
|
||||
title: "REDUNDANT PATTERN".to_string(),
|
||||
doc,
|
||||
severity: Severity::Warning,
|
||||
severity,
|
||||
}
|
||||
}
|
||||
Unmatchable {
|
||||
|
@ -4303,7 +4330,7 @@ fn exhaustive_problem<'a>(
|
|||
filename,
|
||||
title: "UNMATCHABLE PATTERN".to_string(),
|
||||
doc,
|
||||
severity: Severity::Warning,
|
||||
severity,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use roc_module::ident::Ident;
|
||||
use roc_module::ident::{Lowercase, ModuleName, TagName, Uppercase};
|
||||
use roc_module::symbol::{Interns, ModuleId, PQModuleName, PackageQualified, Symbol};
|
||||
use roc_problem::Severity;
|
||||
use roc_region::all::LineColumnRegion;
|
||||
use std::fmt;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
@ -99,18 +100,6 @@ pub fn pretty_header_with_path(title: &str, path: &Path) -> String {
|
|||
header
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Severity {
|
||||
/// This will cause a runtime error if some code get srun
|
||||
/// (e.g. type mismatch, naming error)
|
||||
RuntimeError,
|
||||
|
||||
/// This will never cause the code to misbehave,
|
||||
/// but should be cleaned up
|
||||
/// (e.g. unused def, unused import)
|
||||
Warning,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum RenderTarget {
|
||||
ColorTerminal,
|
||||
|
|
|
@ -19,9 +19,10 @@ mod test_reporting {
|
|||
use roc_parse::module::parse_header;
|
||||
use roc_parse::state::State;
|
||||
use roc_parse::test_helpers::parse_expr_with;
|
||||
use roc_problem::Severity;
|
||||
use roc_region::all::LineInfo;
|
||||
use roc_reporting::report::{
|
||||
can_problem, parse_problem, type_problem, RenderTarget, Report, Severity, ANSI_STYLE_CODES,
|
||||
can_problem, parse_problem, type_problem, RenderTarget, Report, ANSI_STYLE_CODES,
|
||||
DEFAULT_PALETTE,
|
||||
};
|
||||
use roc_reporting::report::{RocDocAllocator, RocDocBuilder};
|
||||
|
|
|
@ -5,6 +5,8 @@ app "env"
|
|||
|
||||
main : Task {} []
|
||||
main =
|
||||
f = ""
|
||||
|
||||
task =
|
||||
Env.decode "EDITOR"
|
||||
|> Task.await (\editor -> Stdout.line "Your favorite editor is \(editor)!")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue