mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 07:14:46 +00:00
don't add guarded record fields into scope
This commit is contained in:
parent
85e2cf4465
commit
fd7ca5bcc9
8 changed files with 196 additions and 79 deletions
|
@ -1,5 +1,6 @@
|
|||
use crate::report::ReportText::{BinOp, Concat, Module, Region, Value};
|
||||
use bumpalo::Bump;
|
||||
use roc_collections::all::MutSet;
|
||||
use roc_module::ident::TagName;
|
||||
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
||||
use roc_problem::can::PrecedenceProblem::BothNonAssociative;
|
||||
|
@ -130,8 +131,16 @@ pub fn can_problem(filename: PathBuf, problem: Problem) -> Report {
|
|||
shadowing_report(&mut texts, original_region, shadow);
|
||||
}
|
||||
|
||||
_ => {
|
||||
panic!("TODO implement run time error reporting");
|
||||
RuntimeError::LookupNotInScope(loc_name, options) => {
|
||||
texts.push(not_found(
|
||||
loc_name.region,
|
||||
&loc_name.value,
|
||||
"value",
|
||||
options,
|
||||
));
|
||||
}
|
||||
other => {
|
||||
todo!("TODO implement run time error reporting for {:?}", other);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -156,6 +165,53 @@ fn shadowing_report(
|
|||
texts.push(plain_text("Since these variables have the same name, it's easy to use the wrong one on accident. Give one of them a new name."));
|
||||
}
|
||||
|
||||
fn not_found(
|
||||
region: roc_region::all::Region,
|
||||
name: &str,
|
||||
thing: &str,
|
||||
options: MutSet<Box<str>>,
|
||||
) -> ReportText {
|
||||
use crate::type_error::suggest;
|
||||
|
||||
let mut suggestions = suggest::sort(name, options.iter().map(|v| v.as_ref()).collect());
|
||||
suggestions.truncate(4);
|
||||
|
||||
let to_details = |no_suggestion_details, yes_suggestion_details| {
|
||||
if suggestions.is_empty() {
|
||||
no_suggestion_details
|
||||
} else {
|
||||
ReportText::Stack(vec![
|
||||
yes_suggestion_details,
|
||||
ReportText::Indent(
|
||||
4,
|
||||
Box::new(ReportText::Stack(
|
||||
suggestions
|
||||
.into_iter()
|
||||
.map(|v: &str| plain_text(v))
|
||||
.collect(),
|
||||
)),
|
||||
),
|
||||
])
|
||||
}
|
||||
};
|
||||
|
||||
let default_no = ReportText::Concat(vec![
|
||||
plain_text("Is there an "),
|
||||
keyword_text("import"),
|
||||
plain_text(" or "),
|
||||
keyword_text("exposing"),
|
||||
plain_text(" missing up-top?"),
|
||||
]);
|
||||
|
||||
let default_yes = plain_text("these names seem close though:");
|
||||
|
||||
ReportText::Stack(vec![
|
||||
plain_text(&format!("I cannot find a `{}` {}", name, thing)),
|
||||
ReportText::Region(region),
|
||||
to_details(default_no, default_yes),
|
||||
])
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ReportText {
|
||||
/// A value. Render it qualified unless it was defined in the current module.
|
||||
|
|
|
@ -882,6 +882,12 @@ pub mod suggest {
|
|||
}
|
||||
}
|
||||
|
||||
impl ToStr for &str {
|
||||
fn to_str(&self) -> &str {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sort<'a, T>(typo: &'a str, mut options: Vec<T>) -> Vec<T>
|
||||
where
|
||||
T: ToStr,
|
||||
|
|
|
@ -1500,36 +1500,98 @@ mod test_reporting {
|
|||
)
|
||||
}
|
||||
|
||||
// Currently hits a bug where `x` is marked as unused
|
||||
// https://github.com/rtfeldman/roc/issues/304
|
||||
// #[test]
|
||||
// fn pattern_guard_mismatch() {
|
||||
// report_problem_as(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when { foo: 1 } is
|
||||
// { x: True } -> 42
|
||||
// "#
|
||||
// ),
|
||||
// indoc!(
|
||||
// r#"
|
||||
// The 2nd pattern in this `when` does not match the previous ones:
|
||||
//
|
||||
// 3 ┆ {} -> 42
|
||||
// ┆ ^^
|
||||
//
|
||||
// The 2nd pattern is trying to match record values of type:
|
||||
//
|
||||
// {}a
|
||||
//
|
||||
// But all the previous branches match:
|
||||
//
|
||||
// Num a
|
||||
//
|
||||
// "#
|
||||
// ),
|
||||
// )
|
||||
// }
|
||||
#[test]
|
||||
fn pattern_guard_mismatch() {
|
||||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
when { foo: 1 } is
|
||||
{ foo: True } -> 42
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
The 1st pattern in this `when` is causing a mismatch:
|
||||
|
||||
2 ┆ { foo: True } -> 42
|
||||
┆ ^^^^^^^^^^^^^
|
||||
|
||||
The first pattern is trying to match record values of type:
|
||||
|
||||
{ foo : [ True ]a }
|
||||
|
||||
But the expression between `when` and `is` has the type:
|
||||
|
||||
{ foo : Num a }
|
||||
|
||||
"#
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pattern_guard_does_not_bind_label() {
|
||||
// needs some improvement, but the principle works
|
||||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
when { foo: 1 } is
|
||||
{ foo: 2 } -> foo
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
I cannot find a `foo` value
|
||||
|
||||
|
||||
2 ┆ { foo: 2 } -> foo
|
||||
┆ ^^^
|
||||
|
||||
|
||||
these names seem close though:
|
||||
Bool
|
||||
Int
|
||||
Num
|
||||
Map
|
||||
|
||||
|
||||
"#
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pattern_guard_can_be_shadowed_above() {
|
||||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
foo = 3
|
||||
|
||||
when { foo: 1 } is
|
||||
{ foo: 2 } -> foo
|
||||
"#
|
||||
),
|
||||
// should give no error
|
||||
"",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pattern_guard_can_be_shadowed_below() {
|
||||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
when { foo: 1 } is
|
||||
{ foo: 2 } ->
|
||||
foo = 3
|
||||
|
||||
foo
|
||||
"#
|
||||
),
|
||||
// should give no error
|
||||
"",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pattern_or_pattern_mismatch() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue