Использование необъявленного типа или модуля `std` при использовании в отдельном модуле

rust

11289 просмотра

1 ответ

У меня есть следующий код:

pub mod a {
    #[test]
    pub fn test() {
        println!("{:?}", std::fs::remove_file("Somefilehere"));
    }
}

Я получаю ошибки, когда я компилирую это:

error[E0433]: failed to resolve. Use of undeclared type or module `std`
 --> src/main.rs:4:24
  |
4 |         println!("{}", std::fs::remove_file("Somefilehere"));
  |                        ^^^ Use of undeclared type or module `std`

Тем не менее, удаление внутреннего модуля и компиляция кода, который он содержит, работает нормально:

#[test]
pub fn test() {
    println!("{:?}", std::fs::remove_file("Somefilehere"));
}

Что мне здесь не хватает? Я получаю те же ошибки, если модуль находится в отдельном файле:

main.rs

pub mod a;

a.rs

#[test]
pub fn test() {
    println!("{:?}", std::fs::remove_file("Somefilehere"));
}
Автор: luke Источник Размещён: 12.11.2019 09:26

Ответы (1)


39 плюса

Решение

По умолчанию компилятор вставляет extern crate std;в начало корня ящика (корень ящика - это файл, который вы передаете rustc). Этот оператор добавляет имя stdк корневому пространству имен ящика и связывает его с модулем, который содержит общедоступное содержимое stdящика.

Однако в дочерних модулях stdне добавляется автоматически в пространство имен модуля. Вот почему компилятор не может разрешить std(или все, что начинается с std::) в модуле.

Есть много способов это исправить. Во-первых, вы можете добавить use std;модуль, чтобы имя stdв этом модуле ссылалось на корень std. Обратите внимание, что в useоператорах путь обрабатывается как абсолютный (или «относительно корневого пространства имен ящика»), тогда как везде другие пути рассматриваются как относящиеся к текущему пространству имен (будь то модуль, функция и т. Д.).

pub mod a {
    use std;

    #[test]
    pub fn test() {
        println!("{:?}", std::fs::remove_file("Somefilehere"));
    }
}

Вы также можете использовать useоператор для импорта более конкретных элементов. Например, вы можете написать use std::fs::remove_file;. Это позволяет вам не вводить весь путь remove_fileи просто использовать имя remove_fileнепосредственно в этом модуле:

pub mod a {
    use std::fs::remove_file;

    #[test]
    pub fn test() {
        println!("{:?}", remove_file("Somefilehere")));
    }
}

Наконец, вы можете полностью отказаться от использования use, добавив префикс пути, ::чтобы попросить компилятор разрешить путь из корневого пространства имен ящика (то есть превратить путь в абсолютный путь).

pub mod a {
    #[test]
    pub fn test() {
        println!("{:?}", ::std::fs::remove_file("Somefilehere"));
    }
}

Рекомендуемая практика - импортировать типы (структуры, перечисления и т. Д.) Напрямую (например use std::rc::Rc;, затем использовать путь Rc), но использовать функции через импорт их родительского модуля (например use std::io::fs;, затем использовать путь fs::remove_file).

pub mod a {
    use std::fs;

    #[test]
    pub fn test() {
        println!("{:?}", fs::remove_file("Somefilehere"));
    }
}

Примечание: Вы также можете написать self::в начале пути, чтобы сделать его относительно текущего модуля. Это чаще используется в useвыражениях, так как другие пути уже являются относительными (хотя они относительно текущего пространства имен , тогда self::как всегда относительно содержащего модуля ).

Автор: Renato Zannon Размещён: 02.05.2014 06:57
Вопросы из категории :
32x32