Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion book/book.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@
title = "Gluon Documentation"
description = "Gluon is a static, type inferred and embeddable language written in Rust"
authors = ["Markus Westerlind"]
multilingual = false
src = "src"
48 changes: 26 additions & 22 deletions check/src/typecheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,9 @@ impl<'a, 'ast> Typecheck<'a, 'ast> {
}
Err(err) => {
returned_type = ModType::wobbly(self.subs.error());
if let Some(exp) = expected_type {
self.unify_span(expr.span, &exp.concrete, returned_type.concrete.clone());
}
self.errors.push(Spanned {
span: expr_check_span(expr),
value: err.into(),
Expand Down Expand Up @@ -1268,7 +1271,7 @@ impl<'a, 'ast> Typecheck<'a, 'ast> {
ModType::wobbly(
typ.as_ref()
.map(|typ| self.translate_arc_type(typ))
.unwrap_or_else(|| self.subs.new_var()),
.unwrap_or_else(|| self.subs.error()),
),
Vec::new(),
)),
Expand Down Expand Up @@ -1672,37 +1675,41 @@ impl<'a, 'ast> Typecheck<'a, 'ast> {
let name = name.value.clone();
// The `types` in the record type should have a type matching the
// `name`
let field_type = record_match_type
.type_field_iter()
.find(|field| field.name.name_eq(&name));
let field_type = match *record_match_type {
// Don't cascade into more errors if the type we are matching is already one
Type::Error => None,
_ => record_match_type
.type_field_iter()
.find(|field| field.name.name_eq(&name))
.or_else(|| {
self.error(
span,
TypeError::UndefinedField(
match_type.concrete.clone(),
name.clone(),
),
);
None
}),
};

let alias;
let alias = match field_type {
match field_type {
Some(field_type) => {
if let Some(meta) = self.implicit_resolver.metadata.remove(&name) {
self.implicit_resolver
.metadata
.insert(field_type.typ.name.clone(), meta);
}
&field_type.typ
self.stack_type(name, &field_type.typ);
}
None => {
self.error(
span,
TypeError::UndefinedField(
match_type.concrete.clone(),
name.clone(),
),
);
// We still define the type so that any uses later on in the program
// won't error on UndefinedType
let hole = self.subs.error();
alias = self.new_alias(name.clone(), Vec::new(), hole);
&alias
let alias = self.new_alias(name.clone(), Vec::new(), hole);
self.stack_type(name, &alias);
}
};

self.stack_type(name, &alias);
}
}

if !missing_fields_from_match_type.is_empty() {
Expand Down Expand Up @@ -1930,7 +1937,6 @@ impl<'a, 'ast> Typecheck<'a, 'ast> {
}
}

let mut types = Vec::new();
for (i, bind) in bindings.iter_mut().enumerate() {
// Functions which are declared as `let f x = ...` are allowed to be self
// recursive
Expand Down Expand Up @@ -2002,8 +2008,6 @@ impl<'a, 'ast> Typecheck<'a, 'ast> {
self.typecheck_let_pattern(&mut bind.name, resolved_type.clone());
debug!("Generalized to {}", bind.resolved_type);
self.finish_pattern(level, &mut bind.name, &resolved_type);
} else {
types.push(typ);
}
}

Expand Down
10 changes: 10 additions & 0 deletions check/tests/fail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -782,3 +782,13 @@ Cons "" Nil
"#,
Unification { .. }
}

test_check_err! {
missing_type_do_not_cascade,
r#"
let { Test } = x
""

"#,
UndefinedVariable { .. }
}
7 changes: 4 additions & 3 deletions check/tests/support/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,10 +475,10 @@ macro_rules! assert_err {
$crate::support::Error::Parser(ref err) => panic!("{}", err),
$crate::support::Error::Check(err) => err.into_errors(),
};
let mut iter = (&errors).into_iter();
let mut iter = errors.iter();
$(
match iter.next() {
Some(&crate::base::pos::Spanned { value: crate::base::error::Help { error: $id, .. }, .. }) => (),
Some(crate::base::pos::Spanned { value: crate::base::error::Help { error: $id, .. }, .. }) => (),
_ => {
if $text.is_empty() {
assert!(
Expand All @@ -498,7 +498,8 @@ macro_rules! assert_err {
}
}
)+
assert!(iter.count() == 0, "Found more errors than expected\n{}", errors);
let remaining: crate::base::error::Errors<_> = iter.cloned().collect();
assert!(remaining.is_empty(), "Found more errors than expected\n{}", crate::support::in_file_error($text, remaining));
}
}
}}
Expand Down
4 changes: 2 additions & 2 deletions scripts/install_mdbook.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ else
TARGET='x86_64-unknown-linux-musl'
fi

MDBOOK_VERSION="mdbook-v0.2.1-${TARGET}"
curl -L "https://github.com/rust-lang-nursery/mdBook/releases/download/v0.2.1/$MDBOOK_VERSION.tar.gz" | tar -xvz
MDBOOK_VERSION="v0.5.4"
curl -L "https://github.com/rust-lang/mdBook/releases/download/${MDBOOK_VERSION}/mdbook-${MDBOOK_VERSION}-${TARGET}.tar.gz" | tar -xvz
chmod +x ./mdbook
mv ./mdbook $HOME/bin/
22 changes: 22 additions & 0 deletions tests/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,25 @@ fn module_imports_provide_a_type_despite_internal_errors() {
"#]]
.assert_eq(&result.unwrap_err().to_string());
}

#[test]
fn missing_module_import_does_not_cascade() {
let _ = ::env_logger::try_init();
let vm = support::make_vm();

let result = vm.run_expr::<f64>(
"test2",
r#"
let { Test } = import! test
1.0
"#,
);
expect![[r#"
error: Could not find module 'test'. Searched `.`, `..`.
┌─ test2:2:24
│
2 │ let { Test } = import! test
│ ^^^^^^^^^^^^

"#]].assert_eq(&result.unwrap_err().to_string());
}