ensure import resolution is done according to local bindings
Might it be from a module that has multiple path fragments or one that is aliased. Signed-off-by: KtorZ <matthias.benkort@gmail.com>
This commit is contained in:
parent
983902fca8
commit
2adc1fab66
|
@ -2296,7 +2296,7 @@ fn use_imported_type_as_namespace_for_patterns() {
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let result = check_with_deps(
|
let result = check_with_deps(
|
||||||
dbg!(parse(source_code)),
|
parse(source_code),
|
||||||
vec![(parse_as(dependency, "cardano/address"))],
|
vec![(parse_as(dependency, "cardano/address"))],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2443,6 +2443,52 @@ fn use_type_as_nested_namespace_for_constructors() {
|
||||||
assert!(matches!(result, Ok(..)), "{result:#?}");
|
assert!(matches!(result, Ok(..)), "{result:#?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn use_type_as_nested_namespace_for_constructors_from_multi_level_module() {
|
||||||
|
let dependency = r#"
|
||||||
|
pub type Foo {
|
||||||
|
I(Int)
|
||||||
|
B(Bool)
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let source_code = r#"
|
||||||
|
use foo/bar
|
||||||
|
|
||||||
|
test my_test() {
|
||||||
|
trace bar.Foo.I(42)
|
||||||
|
Void
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let result = check_with_deps(parse(source_code), vec![(parse_as(dependency, "foo/bar"))]);
|
||||||
|
|
||||||
|
assert!(matches!(result, Ok(..)), "{result:#?}");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn use_type_as_nested_namespace_for_constructors_from_module_alias() {
|
||||||
|
let dependency = r#"
|
||||||
|
pub type Foo {
|
||||||
|
I(Int)
|
||||||
|
B(Bool)
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let source_code = r#"
|
||||||
|
use foo as bar
|
||||||
|
|
||||||
|
test my_test() {
|
||||||
|
trace bar.Foo.I(42)
|
||||||
|
Void
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let result = check_with_deps(parse(source_code), vec![(parse_as(dependency, "foo"))]);
|
||||||
|
|
||||||
|
assert!(matches!(result, Ok(..)), "{result:#?}");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn use_type_as_namespace_unknown_constructor() {
|
fn use_type_as_namespace_unknown_constructor() {
|
||||||
let dependency = r#"
|
let dependency = r#"
|
||||||
|
@ -2626,6 +2672,33 @@ fn use_opaque_type_as_nested_namespace_for_constructors_fails() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn use_non_imported_module_as_namespace() {
|
||||||
|
let dependency = r#"
|
||||||
|
pub type Foo {
|
||||||
|
I(Int)
|
||||||
|
B(Bool)
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let source_code = r#"
|
||||||
|
test my_test() {
|
||||||
|
trace foo.Foo.I(14)
|
||||||
|
Void
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let result = check_with_deps(parse(source_code), vec![(parse_as(dependency, "foo"))]);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
matches!(
|
||||||
|
&result,
|
||||||
|
Err((warnings, Error::UnknownModule { name, .. })) if name == "foo" && warnings.is_empty(),
|
||||||
|
),
|
||||||
|
"{result:#?}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn forbid_importing_or_using_opaque_constructors() {
|
fn forbid_importing_or_using_opaque_constructors() {
|
||||||
let dependency = r#"
|
let dependency = r#"
|
||||||
|
|
|
@ -372,6 +372,31 @@ impl<'a> Environment<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get an imported module's actual name in the current module, from its fully qualified module
|
||||||
|
/// name.
|
||||||
|
#[allow(clippy::result_large_err)]
|
||||||
|
pub fn local_module_name(&self, name: &str, location: Span) -> Result<String, Error> {
|
||||||
|
self.imported_modules
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(k, module)| {
|
||||||
|
if module.1.name == name {
|
||||||
|
Some(k.to_string())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| Error::UnknownModule {
|
||||||
|
location,
|
||||||
|
name: name.to_string(),
|
||||||
|
known_modules: self
|
||||||
|
.importable_modules
|
||||||
|
.keys()
|
||||||
|
.map(|t| t.to_string())
|
||||||
|
.collect(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::result_large_err)]
|
#[allow(clippy::result_large_err)]
|
||||||
pub fn get_fully_qualified_value_constructor(
|
pub fn get_fully_qualified_value_constructor(
|
||||||
&self,
|
&self,
|
||||||
|
@ -379,8 +404,8 @@ impl<'a> Environment<'a> {
|
||||||
(type_name, type_location): (&str, Span),
|
(type_name, type_location): (&str, Span),
|
||||||
(value, value_location): (&str, Span),
|
(value, value_location): (&str, Span),
|
||||||
) -> Result<&ValueConstructor, Error> {
|
) -> Result<&ValueConstructor, Error> {
|
||||||
let (_, module) =
|
let module =
|
||||||
self.imported_modules
|
self.importable_modules
|
||||||
.get(module_name)
|
.get(module_name)
|
||||||
.ok_or_else(|| Error::UnknownModule {
|
.ok_or_else(|| Error::UnknownModule {
|
||||||
location: module_location,
|
location: module_location,
|
||||||
|
|
|
@ -1095,8 +1095,25 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
location: module_location,
|
location: module_location,
|
||||||
} = type_container.as_ref()
|
} = type_container.as_ref()
|
||||||
{
|
{
|
||||||
|
// Lookup the module using the declared name (which may have been rebind with
|
||||||
|
// 'as'), to obtain its _full unambiguous name_.
|
||||||
|
let (_, module) = self
|
||||||
|
.environment
|
||||||
|
.imported_modules
|
||||||
|
.get(module_name)
|
||||||
|
.ok_or_else(|| Error::UnknownModule {
|
||||||
|
location: *module_location,
|
||||||
|
name: module_name.to_string(),
|
||||||
|
known_modules: self
|
||||||
|
.environment
|
||||||
|
.importable_modules
|
||||||
|
.keys()
|
||||||
|
.map(|t| t.to_string())
|
||||||
|
.collect(),
|
||||||
|
})?;
|
||||||
|
|
||||||
return self.infer_inner_type_constructor_access(
|
return self.infer_inner_type_constructor_access(
|
||||||
(module_name, *module_location),
|
(module.name.as_str(), *module_location),
|
||||||
(
|
(
|
||||||
type_name,
|
type_name,
|
||||||
type_location.map(|start, end| (start + module_name.len() + 1, end)),
|
type_location.map(|start, end| (start + module_name.len() + 1, end)),
|
||||||
|
@ -1251,7 +1268,9 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
self.environment.unused_modules.remove(module_name);
|
self.environment.unused_modules.remove(module_name);
|
||||||
|
|
||||||
self.infer_module_access(
|
self.infer_module_access(
|
||||||
module_name,
|
&self
|
||||||
|
.environment
|
||||||
|
.local_module_name(module_name, module_location)?,
|
||||||
label.to_string(),
|
label.to_string(),
|
||||||
&type_location,
|
&type_location,
|
||||||
label_location,
|
label_location,
|
||||||
|
|
Loading…
Reference in New Issue