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