mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 12:18:19 +00:00
Fix package module resolution in inline imports
We were still passing `ModuleIds` from `load` to `can`, but now that imports can appear in any scope, we don't know which package an unqualified module name belongs to from the top level. We now pass `PackageModuleIds` instead and keep a Map of `ModuleName` to `ModuleId` in `Scope`. This also allow us to import multiple modules with the same name from different packages as long as a unique alias is provided.
This commit is contained in:
parent
842a256907
commit
1f347f6ca1
13 changed files with 398 additions and 309 deletions
|
@ -11,7 +11,7 @@ use roc_can::scope::Scope;
|
|||
use roc_collections::all::{ImMap, MutMap, SendSet};
|
||||
use roc_constrain::expr::constrain_expr;
|
||||
use roc_derive::SharedDerivedModule;
|
||||
use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds};
|
||||
use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds, PQModuleName, PackageModuleIds};
|
||||
use roc_parse::parser::{SourceError, SyntaxError};
|
||||
use roc_problem::can::Problem;
|
||||
use roc_region::all::Loc;
|
||||
|
@ -154,10 +154,10 @@ pub fn can_expr_with<'a>(
|
|||
let var = var_store.fresh();
|
||||
let var_index = constraints.push_variable(var);
|
||||
let expected = constraints.push_expected_type(Expected::NoExpectation(var_index));
|
||||
let mut module_ids = ModuleIds::default();
|
||||
let mut module_ids = PackageModuleIds::default();
|
||||
|
||||
// ensure the Test module is accessible in our tests
|
||||
module_ids.get_or_insert(&"Test".into());
|
||||
module_ids.get_or_insert(&PQModuleName::Unqualified("Test".into()));
|
||||
|
||||
// Desugar operators (convert them to Apply calls, taking into account
|
||||
// operator precedence and associativity rules), before doing other canonicalization.
|
||||
|
@ -174,10 +174,15 @@ pub fn can_expr_with<'a>(
|
|||
arena.alloc("TestPath"),
|
||||
);
|
||||
|
||||
let mut scope = Scope::new(home, IdentIds::default(), Default::default());
|
||||
let mut scope = Scope::new(
|
||||
home,
|
||||
"TestPath".into(),
|
||||
IdentIds::default(),
|
||||
Default::default(),
|
||||
);
|
||||
|
||||
let dep_idents = IdentIds::exposed_builtins(0);
|
||||
let mut env = Env::new(arena, home, &dep_idents, &module_ids);
|
||||
let mut env = Env::new(arena, home, &dep_idents, &module_ids, None);
|
||||
let (loc_expr, output) = canonicalize_expr(
|
||||
&mut env,
|
||||
&mut var_store,
|
||||
|
@ -204,7 +209,7 @@ pub fn can_expr_with<'a>(
|
|||
all_ident_ids.insert(home, scope.locals.ident_ids);
|
||||
|
||||
let interns = Interns {
|
||||
module_ids: env.module_ids.clone(),
|
||||
module_ids: env.qualified_module_ids.clone().into_module_ids(),
|
||||
all_ident_ids,
|
||||
};
|
||||
|
||||
|
|
|
@ -4921,19 +4921,21 @@ mod test_reporting {
|
|||
r#"
|
||||
app "dict" imports [ Dict ] provides [main] to "./platform"
|
||||
|
||||
import Dict
|
||||
|
||||
myDict : Dict.Dict Num.I64 Str
|
||||
myDict = Dict.insert (Dict.empty {}) "foo" 42
|
||||
|
||||
main = myDict
|
||||
"#
|
||||
),
|
||||
@r#"
|
||||
@r###"
|
||||
── TYPE MISMATCH in /code/proj/Main.roc ────────────────────────────────────────
|
||||
|
||||
Something is off with the body of the `myDict` definition:
|
||||
|
||||
3│ myDict : Dict.Dict Num.I64 Str
|
||||
4│ myDict = Dict.insert (Dict.empty {}) "foo" 42
|
||||
5│ myDict : Dict.Dict Num.I64 Str
|
||||
6│ myDict = Dict.insert (Dict.empty {}) "foo" 42
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This `insert` call produces:
|
||||
|
@ -4943,7 +4945,7 @@ mod test_reporting {
|
|||
But the type annotation on `myDict` says it should be:
|
||||
|
||||
Dict I64 Str
|
||||
"#
|
||||
"###
|
||||
);
|
||||
|
||||
test_report!(
|
||||
|
@ -10898,7 +10900,9 @@ In roc, functions are always written as a lambda, like{}
|
|||
function_cannot_derive_encoding,
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" imports [Decode.{decoder}] provides [main] to "./platform"
|
||||
app "test" imports [] provides [main] to "./platform"
|
||||
|
||||
import Decode exposing [decoder]
|
||||
|
||||
main =
|
||||
myDecoder : Decoder (a -> a) fmt where fmt implements DecoderFormatting
|
||||
|
@ -10907,12 +10911,12 @@ In roc, functions are always written as a lambda, like{}
|
|||
myDecoder
|
||||
"#
|
||||
),
|
||||
@r"
|
||||
@r###"
|
||||
── TYPE MISMATCH in /code/proj/Main.roc ────────────────────────────────────────
|
||||
|
||||
This expression has a type that does not implement the abilities it's expected to:
|
||||
|
||||
5│ myDecoder = decoder
|
||||
7│ myDecoder = decoder
|
||||
^^^^^^^
|
||||
|
||||
I can't generate an implementation of the `Decoding` ability for
|
||||
|
@ -10920,14 +10924,16 @@ In roc, functions are always written as a lambda, like{}
|
|||
a -> a
|
||||
|
||||
Note: `Decoding` cannot be generated for functions.
|
||||
"
|
||||
"###
|
||||
);
|
||||
|
||||
test_report!(
|
||||
nested_opaque_cannot_derive_encoding,
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" imports [Decode.{decoder}] provides [main] to "./platform"
|
||||
app "test" imports [] provides [main] to "./platform"
|
||||
|
||||
import Decode exposing [decoder]
|
||||
|
||||
A := {}
|
||||
|
||||
|
@ -10938,12 +10944,12 @@ In roc, functions are always written as a lambda, like{}
|
|||
myDecoder
|
||||
"#
|
||||
),
|
||||
@r"
|
||||
@r###"
|
||||
── TYPE MISMATCH in /code/proj/Main.roc ────────────────────────────────────────
|
||||
|
||||
This expression has a type that does not implement the abilities it's expected to:
|
||||
|
||||
7│ myDecoder = decoder
|
||||
9│ myDecoder = decoder
|
||||
^^^^^^^
|
||||
|
||||
I can't generate an implementation of the `Decoding` ability for
|
||||
|
@ -10958,7 +10964,7 @@ In roc, functions are always written as a lambda, like{}
|
|||
|
||||
Tip: `A` does not implement `Decoding`. Consider adding a custom
|
||||
implementation or `implements Decode.Decoding` to the definition of `A`.
|
||||
"
|
||||
"###
|
||||
);
|
||||
|
||||
test_report!(
|
||||
|
@ -11119,7 +11125,9 @@ In roc, functions are always written as a lambda, like{}
|
|||
infer_decoded_record_error_with_function_field,
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" imports [TotallyNotJson] provides [main] to "./platform"
|
||||
app "test" imports [] provides [main] to "./platform"
|
||||
|
||||
import TotallyNotJson
|
||||
|
||||
main =
|
||||
decoded = Str.toUtf8 "{\"first\":\"ab\",\"second\":\"cd\"}" |> Decode.fromBytes TotallyNotJson.json
|
||||
|
@ -11128,12 +11136,12 @@ In roc, functions are always written as a lambda, like{}
|
|||
_ -> "something went wrong"
|
||||
"#
|
||||
),
|
||||
@r"
|
||||
@r###"
|
||||
── TYPE MISMATCH in /code/proj/Main.roc ────────────────────────────────────────
|
||||
|
||||
This expression has a type that does not implement the abilities it's expected to:
|
||||
|
||||
6│ Ok rcd -> rcd.first rcd.second
|
||||
8│ Ok rcd -> rcd.first rcd.second
|
||||
^^^^^^^^^
|
||||
|
||||
I can't generate an implementation of the `Decoding` ability for
|
||||
|
@ -11141,14 +11149,16 @@ In roc, functions are always written as a lambda, like{}
|
|||
* -> *
|
||||
|
||||
Note: `Decoding` cannot be generated for functions.
|
||||
"
|
||||
"###
|
||||
);
|
||||
|
||||
test_report!(
|
||||
record_with_optional_field_types_cannot_derive_decoding,
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" imports [Decode.{decoder}] provides [main] to "./platform"
|
||||
app "test" imports [] provides [main] to "./platform"
|
||||
|
||||
import Decode exposing [decoder]
|
||||
|
||||
main =
|
||||
myDecoder : Decoder {x : Str, y ? Str} fmt where fmt implements DecoderFormatting
|
||||
|
@ -11157,12 +11167,12 @@ In roc, functions are always written as a lambda, like{}
|
|||
myDecoder
|
||||
"#
|
||||
),
|
||||
@r"
|
||||
@r###"
|
||||
── TYPE MISMATCH in /code/proj/Main.roc ────────────────────────────────────────
|
||||
|
||||
This expression has a type that does not implement the abilities it's expected to:
|
||||
|
||||
5│ myDecoder = decoder
|
||||
7│ myDecoder = decoder
|
||||
^^^^^^^
|
||||
|
||||
I can't generate an implementation of the `Decoding` ability for
|
||||
|
@ -11177,7 +11187,7 @@ In roc, functions are always written as a lambda, like{}
|
|||
over records that may or may not contain them at compile time, but are
|
||||
not a concept that extends to runtime!
|
||||
Maybe you wanted to use a `Result`?
|
||||
"
|
||||
"###
|
||||
);
|
||||
|
||||
test_report!(
|
||||
|
@ -11359,21 +11369,23 @@ In roc, functions are always written as a lambda, like{}
|
|||
unused_value_import,
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" imports [List.{ concat }] provides [main] to "./platform"
|
||||
app "test" imports [] provides [main] to "./platform"
|
||||
|
||||
import List exposing [concat]
|
||||
|
||||
main = ""
|
||||
"#
|
||||
),
|
||||
@r#"
|
||||
@r###"
|
||||
── UNUSED IMPORT in /code/proj/Main.roc ────────────────────────────────────────
|
||||
|
||||
`List.concat` is not used in this module.
|
||||
List is imported but not used.
|
||||
|
||||
1│ app "test" imports [List.{ concat }] provides [main] to "./platform"
|
||||
^^^^^^
|
||||
3│ import List exposing [concat]
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Since `List.concat` isn't used, you don't need to import it.
|
||||
"#
|
||||
Since List isn't used, you don't need to import it.
|
||||
"###
|
||||
);
|
||||
|
||||
test_report!(
|
||||
|
@ -11395,7 +11407,9 @@ In roc, functions are always written as a lambda, like{}
|
|||
unnecessary_builtin_type_import,
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" imports [Decode.{ DecodeError }] provides [main, E] to "./platform"
|
||||
app "test" imports [] provides [main, E] to "./platform"
|
||||
|
||||
import Decode exposing [DecodeError]
|
||||
|
||||
E : DecodeError
|
||||
|
||||
|
@ -13664,7 +13678,9 @@ In roc, functions are always written as a lambda, like{}
|
|||
derive_decoding_for_tuple,
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" imports [Decode.{decoder}] provides [main] to "./platform"
|
||||
app "test" imports [] provides [main] to "./platform"
|
||||
|
||||
import Decode exposing [decoder]
|
||||
|
||||
main =
|
||||
myDecoder : Decoder (U32, Str) fmt where fmt implements DecoderFormatting
|
||||
|
@ -13679,7 +13695,9 @@ In roc, functions are always written as a lambda, like{}
|
|||
cannot_decode_tuple_with_non_decode_element,
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" imports [Decode.{decoder}] provides [main] to "./platform"
|
||||
app "test" imports [] provides [main] to "./platform"
|
||||
|
||||
import Decode exposing [decoder]
|
||||
|
||||
main =
|
||||
myDecoder : Decoder (U32, {} -> {}) fmt where fmt implements DecoderFormatting
|
||||
|
@ -13688,12 +13706,12 @@ In roc, functions are always written as a lambda, like{}
|
|||
myDecoder
|
||||
"#
|
||||
),
|
||||
@r"
|
||||
@r###"
|
||||
── TYPE MISMATCH in /code/proj/Main.roc ────────────────────────────────────────
|
||||
|
||||
This expression has a type that does not implement the abilities it's expected to:
|
||||
|
||||
5│ myDecoder = decoder
|
||||
7│ myDecoder = decoder
|
||||
^^^^^^^
|
||||
|
||||
I can't generate an implementation of the `Decoding` ability for
|
||||
|
@ -13701,7 +13719,7 @@ In roc, functions are always written as a lambda, like{}
|
|||
U32, {} -> {}
|
||||
|
||||
Note: `Decoding` cannot be generated for functions.
|
||||
"
|
||||
"###
|
||||
);
|
||||
|
||||
test_no_problem!(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue