Repository: typst/typst
File: crates/typst/src/eval/import.rs (Rust)

Code before:
                        };

                        if path.peek().is_some() {
                            // Nested import, as this is not the last component.
                            // This must be a submodule.
                            if matches!(value, Value::Func(function) if function.scope().is_none())
                            {
                                errors.push(error!(
                                    component.span(),
                                    "cannot import from user-defined functions"
                                ));
                                break;
                            } else if !matches!(
                                value,
                                Value::Func(_) | Value::Module(_) | Value::Type(_)
                            ) {
                                errors.push(error!(
                                    component.span(),
                                    "expected module, function, or type, found {}",
                                    value.ty()
                                ));
                                break;
                            }

                            // Walk into the submodule.
                            scope = value.scope().unwrap();
                        } else {
                            // Now that we have the scope of the innermost submodule
                            // in the import path, we may extract the desired item from
                            // it.

                            // Warn on `import ...: x as x`
                            if let ast::ImportItem::Renamed(renamed_item) = &item {
                                if renamed_item.original_name().as_str()
                                    == renamed_item.new_name().as_str()
                                {
                                    vm.engine.tracer.warn(warning!(
                                        renamed_item.new_name().span(),
                                        "unnecessary import rename to same name",
                                    ));
                                }
                            }

                            vm.define(item.bound_name(), value.clone());
                        }
                    }
                }
                if !errors.is_empty() {
                    return Err(errors);
                }
            }

Review comment (suggestion):
Rather than unwrapping here after checking the type, I think it would be better to do this first and if it is none inspect the type to produce the correct error message.

Code after:
                        };

                        if path.peek().is_some() {
                            // Nested import, as this is not the last component.
                            // This must be a submodule.
                            let Some(submodule) = value.scope() else {
                                let error = if matches!(value, Value::Func(function) if function.scope().is_none())
                                {
                                    error!(
                                        component.span(),
                                        "cannot import from user-defined functions"
                                    )
                                } else if !matches!(
                                    value,
                                    Value::Func(_) | Value::Module(_) | Value::Type(_)
                                ) {
                                    error!(
                                        component.span(),
                                        "expected module, function, or type, found {}",
                                        value.ty()
                                    )
                                } else {
                                    panic!("unexpected nested import failure")
                                };
                                errors.push(error);
                                break;
                            };

                            // Walk into the submodule.
                            scope = submodule;
                        } else {
                            // Now that we have the scope of the innermost submodule
                            // in the import path, we may extract the desired item from
                            // it.

                            // Warn on `import ...: x as x`
                            if let ast::ImportItem::Renamed(renamed_item) = &item {
                                if renamed_item.original_name().as_str()
                                    == renamed_item.new_name().as_str()
                                {
                                    vm.engine.tracer.warn(warning!(
                                        renamed_item.new_name().span(),
                                        "unnecessary import rename to same name",
                                    ));
                                }
                            }

                            vm.define(item.bound_name(), value.clone());
                        }
                    }
                }