Merge pull request #2574 from rtfeldman/fix-panic-on-unimported-module

[Bug] Handle unimported modules properly
This commit is contained in:
hafiz 2022-02-26 16:39:22 -05:00 committed by GitHub
commit 1aec997843
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 117 additions and 32 deletions

View file

@ -130,7 +130,9 @@ fn make_apply_symbol(
// it was imported but it doesn't expose this ident.
env.problem(roc_problem::can::Problem::RuntimeError(problem));
Err(Type::Erroneous(Problem::UnrecognizedIdent((*ident).into())))
// A failed import should have already been reported through
// roc_can::env::Env::qualified_lookup's checks
Err(Type::Erroneous(Problem::SolvedTypeError))
}
}
}

View file

@ -124,12 +124,17 @@ impl<'a> Env<'a> {
})
}
},
None => {
panic!(
"Module {} exists, but is not recorded in dep_idents",
module_name
)
}
None => Err(RuntimeError::ModuleNotImported {
module_name,
imported_modules: self
.dep_idents
.keys()
.filter_map(|module_id| self.module_ids.get_name(*module_id))
.map(|module_name| module_name.as_ref().into())
.collect(),
region,
module_exists: true,
}),
}
}
}
@ -141,6 +146,7 @@ impl<'a> Env<'a> {
.map(|string| string.as_ref().into())
.collect(),
region,
module_exists: false,
}),
}
}

View file

@ -171,10 +171,37 @@ pub enum RuntimeError {
region: Region,
exposed_values: Vec<Lowercase>,
},
/// A module was referenced, but hasn't been imported anywhere in the program
///
/// An example would be:
/// ```roc
/// app "hello"
/// packages { pf: "platform" }
/// imports [ pf.Stdout]
/// provides [ main ] to pf
///
/// main : Task.Task {} [] // Task isn't imported!
/// main = Stdout.line "I'm a Roc application!"
/// ```
ModuleNotImported {
/// The name of the module that was referenced
module_name: ModuleName,
/// A list of modules which *have* been imported
imported_modules: MutSet<Box<str>>,
/// Where the problem occurred
region: Region,
/// Whether or not the module exists at all
///
/// This is used to suggest that the user import the module, as opposed to fix a
/// typo in the spelling. For example, if the user typed `Task`, and the platform
/// exposes a `Task` module that hasn't been imported, we can sugguest that they
/// add the import statement.
///
/// On the other hand, if the user typed `Tesk`, they might want to check their
/// spelling.
///
/// If unsure, this should be set to `false`
module_exists: bool,
},
InvalidPrecedence(PrecedenceProblem, Region),
MalformedIdentifier(Box<str>, roc_parse::ident::BadIdent, Region),