mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-16 17:58:16 +00:00
Merge #9097
9097: feat: Implement per-edition preludes r=jonas-schievink a=jonas-schievink
Part of https://github.com/rust-analyzer/rust-analyzer/issues/9056
Our previous implementation was incorrect (presumably because of the misleading comment in libstd [here](a7890c7952/library/std/src/lib.rs (L339-L343)
)). `#[prelude_import]` does not define the prelude, it can only override the implicit prelude for the current crate.
This PR fixes that, which also makes the prelude imports in `rustc_span` work. Closes https://github.com/rust-analyzer/rust-analyzer/issues/8815.
bors r+
Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
This commit is contained in:
commit
4f63e79eb3
12 changed files with 318 additions and 141 deletions
|
@ -682,9 +682,11 @@ pub struct S;
|
|||
//- /main.rs crate:main deps:std
|
||||
$0
|
||||
//- /std.rs crate:std
|
||||
pub mod prelude { pub struct S; }
|
||||
#[prelude_import]
|
||||
pub use prelude::*;
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
pub struct S;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
"S",
|
||||
"S",
|
||||
|
@ -700,11 +702,11 @@ pub use prelude::*;
|
|||
$0
|
||||
//- /std.rs crate:std
|
||||
pub mod prelude {
|
||||
pub enum Option<T> { Some(T), None }
|
||||
pub use Option::*;
|
||||
pub mod rust_2018 {
|
||||
pub enum Option<T> { Some(T), None }
|
||||
pub use Option::*;
|
||||
}
|
||||
}
|
||||
#[prelude_import]
|
||||
pub use prelude::*;
|
||||
"#;
|
||||
check_found_path(code, "None", "None", "None", "None");
|
||||
check_found_path(code, "Some", "Some", "Some", "Some");
|
||||
|
@ -1080,11 +1082,11 @@ fn f() {
|
|||
}
|
||||
//- /std.rs crate:std
|
||||
pub mod prelude {
|
||||
pub enum Option { None }
|
||||
pub use Option::*;
|
||||
pub mod rust_2018 {
|
||||
pub enum Option { None }
|
||||
pub use Option::*;
|
||||
}
|
||||
}
|
||||
#[prelude_import]
|
||||
pub use prelude::*;
|
||||
"#,
|
||||
"None",
|
||||
"None",
|
||||
|
|
|
@ -5,13 +5,13 @@
|
|||
|
||||
use std::iter;
|
||||
|
||||
use base_db::{CrateId, FileId, ProcMacroId};
|
||||
use base_db::{CrateId, Edition, FileId, ProcMacroId};
|
||||
use cfg::{CfgExpr, CfgOptions};
|
||||
use hir_expand::{
|
||||
ast_id_map::FileAstId,
|
||||
builtin_derive::find_builtin_derive,
|
||||
builtin_macro::find_builtin_macro,
|
||||
name::{AsName, Name},
|
||||
name::{name, AsName, Name},
|
||||
proc_macro::ProcMacroExpander,
|
||||
FragmentKind, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
|
||||
};
|
||||
|
@ -67,14 +67,6 @@ pub(super) fn collect_defs(
|
|||
def_map
|
||||
.extern_prelude
|
||||
.insert(dep.as_name(), dep_def_map.module_id(dep_def_map.root).into());
|
||||
|
||||
// look for the prelude
|
||||
// If the dependency defines a prelude, we overwrite an already defined
|
||||
// prelude. This is necessary to import the "std" prelude if a crate
|
||||
// depends on both "core" and "std".
|
||||
if dep_def_map.prelude.is_some() {
|
||||
def_map.prelude = dep_def_map.prelude;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -283,6 +275,8 @@ impl DefCollector<'_> {
|
|||
|
||||
let attrs = item_tree.top_level_attrs(self.db, self.def_map.krate);
|
||||
if attrs.cfg().map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false)) {
|
||||
self.inject_prelude(&attrs);
|
||||
|
||||
// Process other crate-level attributes.
|
||||
for attr in &*attrs {
|
||||
let attr_name = match attr.path.as_ident() {
|
||||
|
@ -460,6 +454,58 @@ impl DefCollector<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn inject_prelude(&mut self, crate_attrs: &Attrs) {
|
||||
// See compiler/rustc_builtin_macros/src/standard_library_imports.rs
|
||||
|
||||
if crate_attrs.by_key("no_core").exists() {
|
||||
// libcore does not get a prelude.
|
||||
return;
|
||||
}
|
||||
|
||||
let krate = if crate_attrs.by_key("no_std").exists() {
|
||||
name![core]
|
||||
} else {
|
||||
let std = name![std];
|
||||
if self.def_map.extern_prelude().any(|(name, _)| *name == std) {
|
||||
std
|
||||
} else {
|
||||
// If `std` does not exist for some reason, fall back to core. This mostly helps
|
||||
// keep r-a's own tests minimal.
|
||||
name![core]
|
||||
}
|
||||
};
|
||||
|
||||
let edition = match self.def_map.edition {
|
||||
Edition::Edition2015 => name![rust_2015],
|
||||
Edition::Edition2018 => name![rust_2018],
|
||||
Edition::Edition2021 => name![rust_2021],
|
||||
};
|
||||
|
||||
let path_kind = if self.def_map.edition == Edition::Edition2015 {
|
||||
PathKind::Plain
|
||||
} else {
|
||||
PathKind::Abs
|
||||
};
|
||||
let path =
|
||||
ModPath::from_segments(path_kind, [krate, name![prelude], edition].iter().cloned());
|
||||
|
||||
let (per_ns, _) =
|
||||
self.def_map.resolve_path(self.db, self.def_map.root, &path, BuiltinShadowMode::Other);
|
||||
|
||||
match &per_ns.types {
|
||||
Some((ModuleDefId::ModuleId(m), _)) => {
|
||||
self.def_map.prelude = Some(*m);
|
||||
}
|
||||
_ => {
|
||||
log::error!(
|
||||
"could not resolve prelude path `{}` to module (resolved to {:?})",
|
||||
path,
|
||||
per_ns.types
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a definition of procedural macro `name` to the root module.
|
||||
///
|
||||
/// # Notes on procedural macro resolution
|
||||
|
@ -718,6 +764,8 @@ impl DefCollector<'_> {
|
|||
match def.take_types() {
|
||||
Some(ModuleDefId::ModuleId(m)) => {
|
||||
if import.is_prelude {
|
||||
// Note: This dodgily overrides the injected prelude. The rustc
|
||||
// implementation seems to work the same though.
|
||||
cov_mark::hit!(std_prelude);
|
||||
self.def_map.prelude = Some(m);
|
||||
} else if m.krate != self.def_map.krate {
|
||||
|
|
|
@ -246,15 +246,16 @@ fn std_prelude() {
|
|||
check(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:test_crate
|
||||
#[prelude_import]
|
||||
use ::test_crate::prelude::*;
|
||||
|
||||
use Foo::*;
|
||||
|
||||
//- /lib.rs crate:test_crate
|
||||
mod prelude;
|
||||
#[prelude_import]
|
||||
use prelude::*;
|
||||
pub mod prelude;
|
||||
|
||||
//- /prelude.rs
|
||||
pub enum Foo { Bar, Baz };
|
||||
pub enum Foo { Bar, Baz }
|
||||
"#,
|
||||
expect![[r#"
|
||||
crate
|
||||
|
@ -466,6 +467,74 @@ pub struct Bar;
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_std_prelude() {
|
||||
check(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:core,std
|
||||
#![cfg_attr(not(never), no_std)]
|
||||
use Rust;
|
||||
|
||||
//- /core.rs crate:core
|
||||
pub mod prelude {
|
||||
pud mod rust_2018 {
|
||||
pub struct Rust;
|
||||
}
|
||||
}
|
||||
//- /std.rs crate:std deps:core
|
||||
pub mod prelude {
|
||||
pud mod rust_2018 {
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
crate
|
||||
Rust: t v
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn edition_specific_preludes() {
|
||||
// We can't test the 2015 prelude here since you can't reexport its contents with 2015's
|
||||
// absolute paths.
|
||||
|
||||
check(
|
||||
r#"
|
||||
//- /main.rs edition:2018 crate:main deps:std
|
||||
use Rust2018;
|
||||
|
||||
//- /std.rs crate:std
|
||||
pub mod prelude {
|
||||
pud mod rust_2018 {
|
||||
pub struct Rust2018;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
crate
|
||||
Rust2018: t v
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
//- /main.rs edition:2021 crate:main deps:std
|
||||
use Rust2021;
|
||||
|
||||
//- /std.rs crate:std
|
||||
pub mod prelude {
|
||||
pud mod rust_2021 {
|
||||
pub struct Rust2021;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
crate
|
||||
Rust2021: t v
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn std_prelude_takes_precedence_above_core_prelude() {
|
||||
check(
|
||||
|
@ -474,18 +543,18 @@ fn std_prelude_takes_precedence_above_core_prelude() {
|
|||
use {Foo, Bar};
|
||||
|
||||
//- /std.rs crate:std deps:core
|
||||
#[prelude_import]
|
||||
pub use self::prelude::*;
|
||||
mod prelude {
|
||||
pub struct Foo;
|
||||
pub use core::prelude::Bar;
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
pub struct Foo;
|
||||
pub use core::prelude::rust_2018::Bar;
|
||||
}
|
||||
}
|
||||
|
||||
//- /core.rs crate:core
|
||||
#[prelude_import]
|
||||
pub use self::prelude::*;
|
||||
mod prelude {
|
||||
pub struct Bar;
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
pub struct Bar;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
|
@ -504,15 +573,15 @@ fn cfg_not_test() {
|
|||
use {Foo, Bar, Baz};
|
||||
|
||||
//- /lib.rs crate:std
|
||||
#[prelude_import]
|
||||
pub use self::prelude::*;
|
||||
mod prelude {
|
||||
#[cfg(test)]
|
||||
pub struct Foo;
|
||||
#[cfg(not(test))]
|
||||
pub struct Bar;
|
||||
#[cfg(all(not(any()), feature = "foo", feature = "bar", opt = "42"))]
|
||||
pub struct Baz;
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
#[cfg(test)]
|
||||
pub struct Foo;
|
||||
#[cfg(not(test))]
|
||||
pub struct Bar;
|
||||
#[cfg(all(not(any()), feature = "foo", feature = "bar", opt = "42"))]
|
||||
pub struct Baz;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
|
@ -532,15 +601,15 @@ fn cfg_test() {
|
|||
use {Foo, Bar, Baz};
|
||||
|
||||
//- /lib.rs crate:std cfg:test,feature=foo,feature=bar,opt=42
|
||||
#[prelude_import]
|
||||
pub use self::prelude::*;
|
||||
mod prelude {
|
||||
#[cfg(test)]
|
||||
pub struct Foo;
|
||||
#[cfg(not(test))]
|
||||
pub struct Bar;
|
||||
#[cfg(all(not(any()), feature = "foo", feature = "bar", opt = "42"))]
|
||||
pub struct Baz;
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
#[cfg(test)]
|
||||
pub struct Foo;
|
||||
#[cfg(not(test))]
|
||||
pub struct Bar;
|
||||
#[cfg(all(not(any()), feature = "foo", feature = "bar", opt = "42"))]
|
||||
pub struct Baz;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
|
|
|
@ -264,7 +264,7 @@ fn prelude_is_macro_use() {
|
|||
cov_mark::check!(prelude_is_macro_use);
|
||||
check(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:foo
|
||||
//- /main.rs crate:main deps:std
|
||||
structs!(Foo);
|
||||
structs_priv!(Bar);
|
||||
structs_outside!(Out);
|
||||
|
@ -276,21 +276,20 @@ mod bar;
|
|||
structs!(Baz);
|
||||
crate::structs!(MacroNotResolved3);
|
||||
|
||||
//- /lib.rs crate:foo
|
||||
#[prelude_import]
|
||||
use self::prelude::*;
|
||||
|
||||
mod prelude {
|
||||
#[macro_export]
|
||||
macro_rules! structs {
|
||||
($i:ident) => { struct $i; }
|
||||
}
|
||||
|
||||
mod priv_mod {
|
||||
//- /lib.rs crate:std
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
#[macro_export]
|
||||
macro_rules! structs_priv {
|
||||
macro_rules! structs {
|
||||
($i:ident) => { struct $i; }
|
||||
}
|
||||
|
||||
mod priv_mod {
|
||||
#[macro_export]
|
||||
macro_rules! structs_priv {
|
||||
($i:ident) => { struct $i; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -617,12 +616,11 @@ fn macro_dollar_crate_is_correct_in_indirect_deps() {
|
|||
foo!();
|
||||
|
||||
//- /std.rs crate:std deps:core
|
||||
#[prelude_import]
|
||||
use self::prelude::*;
|
||||
|
||||
pub use core::foo;
|
||||
|
||||
mod prelude {}
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {}
|
||||
}
|
||||
|
||||
#[macro_use]
|
||||
mod std_macros;
|
||||
|
|
|
@ -176,6 +176,10 @@ pub mod known {
|
|||
result,
|
||||
boxed,
|
||||
option,
|
||||
prelude,
|
||||
rust_2015,
|
||||
rust_2018,
|
||||
rust_2021,
|
||||
// Components of known path (type name)
|
||||
Iterator,
|
||||
IntoIterator,
|
||||
|
|
|
@ -982,14 +982,18 @@ fn test() {
|
|||
} //^ S
|
||||
|
||||
//- /lib.rs crate:core
|
||||
#[prelude_import]
|
||||
use clone::*;
|
||||
mod clone {
|
||||
trait Clone {
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
#[rustc_builtin_macro]
|
||||
pub macro Clone {}
|
||||
pub use crate::clone::Clone;
|
||||
}
|
||||
}
|
||||
|
||||
pub mod clone {
|
||||
pub trait Clone {
|
||||
fn clone(&self) -> Self;
|
||||
}
|
||||
#[rustc_builtin_macro]
|
||||
macro Clone {}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
@ -1001,14 +1005,22 @@ fn infer_derive_clone_in_core() {
|
|||
r#"
|
||||
//- /lib.rs crate:core
|
||||
#[prelude_import]
|
||||
use clone::*;
|
||||
mod clone {
|
||||
trait Clone {
|
||||
use prelude::rust_2018::*;
|
||||
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
#[rustc_builtin_macro]
|
||||
pub macro Clone {}
|
||||
pub use crate::clone::Clone;
|
||||
}
|
||||
}
|
||||
|
||||
pub mod clone {
|
||||
pub trait Clone {
|
||||
fn clone(&self) -> Self;
|
||||
}
|
||||
#[rustc_builtin_macro]
|
||||
macro Clone {}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct S;
|
||||
|
||||
|
@ -1037,14 +1049,18 @@ fn test() {
|
|||
}
|
||||
|
||||
//- /lib.rs crate:core
|
||||
#[prelude_import]
|
||||
use clone::*;
|
||||
mod clone {
|
||||
trait Clone {
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
#[rustc_builtin_macro]
|
||||
pub macro Clone {}
|
||||
pub use crate::clone::Clone;
|
||||
}
|
||||
}
|
||||
|
||||
pub mod clone {
|
||||
pub trait Clone {
|
||||
fn clone(&self) -> Self;
|
||||
}
|
||||
#[rustc_builtin_macro]
|
||||
macro Clone {}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
|
|
@ -796,7 +796,7 @@ fn test() {
|
|||
fn method_resolution_trait_from_prelude() {
|
||||
check_types(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:other_crate
|
||||
//- /main.rs crate:main deps:core
|
||||
struct S;
|
||||
impl Clone for S {}
|
||||
|
||||
|
@ -805,12 +805,12 @@ fn test() {
|
|||
//^ S
|
||||
}
|
||||
|
||||
//- /lib.rs crate:other_crate
|
||||
#[prelude_import] use foo::*;
|
||||
|
||||
mod foo {
|
||||
trait Clone {
|
||||
fn clone(&self) -> Self;
|
||||
//- /lib.rs crate:core
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
pub trait Clone {
|
||||
fn clone(&self) -> Self;
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
|
|
|
@ -426,11 +426,12 @@ fn test() {
|
|||
|
||||
//- /std.rs crate:std
|
||||
#[prelude_import]
|
||||
use prelude::*;
|
||||
|
||||
use self::prelude::rust_2018::*;
|
||||
pub mod prelude {
|
||||
pub use crate::iter::Iterator;
|
||||
pub use crate::option::Option;
|
||||
pub mod rust_2018 {
|
||||
pub use crate::iter::Iterator;
|
||||
pub use crate::option::Option;
|
||||
}
|
||||
}
|
||||
|
||||
pub mod iter {
|
||||
|
|
|
@ -2712,3 +2712,23 @@ fn main() {
|
|||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn prelude_2015() {
|
||||
check_types(
|
||||
r#"
|
||||
//- /main.rs edition:2015 crate:main deps:core
|
||||
fn f() {
|
||||
Rust;
|
||||
//^ Rust
|
||||
}
|
||||
|
||||
//- /core.rs crate:core
|
||||
pub mod prelude {
|
||||
pub mod rust_2015 {
|
||||
pub struct Rust;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -20,11 +20,12 @@ fn test() {
|
|||
} //^ u64
|
||||
|
||||
//- /core.rs crate:core
|
||||
#[prelude_import] use future::*;
|
||||
mod future {
|
||||
#[lang = "future_trait"]
|
||||
trait Future {
|
||||
type Output;
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
#[lang = "future_trait"]
|
||||
pub trait Future {
|
||||
type Output;
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
|
@ -136,17 +137,15 @@ fn test() {
|
|||
} //^ i32
|
||||
|
||||
//- /core.rs crate:core
|
||||
#[prelude_import] use ops::*;
|
||||
mod ops {
|
||||
trait Try {
|
||||
pub mod ops {
|
||||
pub trait Try {
|
||||
type Ok;
|
||||
type Error;
|
||||
}
|
||||
}
|
||||
|
||||
#[prelude_import] use result::*;
|
||||
mod result {
|
||||
enum Result<O, E> {
|
||||
pub mod result {
|
||||
pub enum Result<O, E> {
|
||||
Ok(O),
|
||||
Err(E)
|
||||
}
|
||||
|
@ -156,6 +155,12 @@ mod result {
|
|||
type Error = E;
|
||||
}
|
||||
}
|
||||
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
pub use crate::{result::*, ops::*};
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
@ -190,8 +195,7 @@ mov convert {
|
|||
impl<T> From<T> for T {}
|
||||
}
|
||||
|
||||
#[prelude_import] use result::*;
|
||||
mod result {
|
||||
pub mod result {
|
||||
use crate::convert::From;
|
||||
use crate::ops::{Try, FromResidual};
|
||||
|
||||
|
@ -208,6 +212,12 @@ mod result {
|
|||
|
||||
impl<T, E, F: From<E>> FromResidual<Result<Infallible, E>> for Result<T, F> {}
|
||||
}
|
||||
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
pub use crate::result::*;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
@ -217,6 +227,7 @@ fn infer_for_loop() {
|
|||
check_types(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:core,alloc
|
||||
#![no_std]
|
||||
use alloc::collections::Vec;
|
||||
|
||||
fn test() {
|
||||
|
@ -228,14 +239,19 @@ fn test() {
|
|||
}
|
||||
|
||||
//- /core.rs crate:core
|
||||
#[prelude_import] use iter::*;
|
||||
mod iter {
|
||||
trait IntoIterator {
|
||||
pub mod iter {
|
||||
pub trait IntoIterator {
|
||||
type Item;
|
||||
}
|
||||
}
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
pub use crate::iter::*;
|
||||
}
|
||||
}
|
||||
|
||||
//- /alloc.rs crate:alloc deps:core
|
||||
#![no_std]
|
||||
mod collections {
|
||||
struct Vec<T> {}
|
||||
impl<T> Vec<T> {
|
||||
|
|
|
@ -385,10 +385,11 @@ fn foo() {
|
|||
fn foo() { let x: $0 }
|
||||
|
||||
//- /std/lib.rs crate:std
|
||||
#[prelude_import]
|
||||
use prelude::*;
|
||||
|
||||
mod prelude { struct Option; }
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
pub struct Option;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
fn foo() fn()
|
||||
|
@ -406,12 +407,10 @@ mod prelude { struct Option; }
|
|||
fn f() {$0}
|
||||
|
||||
//- /std/lib.rs crate:std
|
||||
#[prelude_import]
|
||||
pub use prelude::*;
|
||||
|
||||
#[macro_use]
|
||||
mod prelude {
|
||||
pub use crate::concat;
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
pub use crate::concat;
|
||||
}
|
||||
}
|
||||
|
||||
mod macros {
|
||||
|
@ -436,16 +435,18 @@ mod macros {
|
|||
fn foo() { let x: $0 }
|
||||
|
||||
//- /core/lib.rs crate:core
|
||||
#[prelude_import]
|
||||
use prelude::*;
|
||||
|
||||
mod prelude { struct Option; }
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
pub struct Option;
|
||||
}
|
||||
}
|
||||
|
||||
//- /std/lib.rs crate:std deps:core
|
||||
#[prelude_import]
|
||||
use prelude::*;
|
||||
|
||||
mod prelude { struct String; }
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
pub struct String;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
fn foo() fn()
|
||||
|
|
|
@ -128,17 +128,19 @@ pub mod option {
|
|||
}
|
||||
|
||||
pub mod prelude {
|
||||
pub use crate::{
|
||||
cmp::Ord,
|
||||
convert::{From, Into},
|
||||
default::Default,
|
||||
iter::{IntoIterator, Iterator},
|
||||
ops::{Fn, FnMut, FnOnce},
|
||||
option::Option::{self, *},
|
||||
};
|
||||
pub mod rust_2018 {
|
||||
pub use crate::{
|
||||
cmp::Ord,
|
||||
convert::{From, Into},
|
||||
default::Default,
|
||||
iter::{IntoIterator, Iterator},
|
||||
ops::{Fn, FnMut, FnOnce},
|
||||
option::Option::{self, *},
|
||||
};
|
||||
}
|
||||
}
|
||||
#[prelude_import]
|
||||
pub use prelude::*;
|
||||
pub use prelude::rust_2018::*;
|
||||
//- /libstd.rs crate:std deps:core
|
||||
//! Signatures of traits, types and functions from the std lib for use in tests.
|
||||
|
||||
|
@ -148,4 +150,4 @@ mod return_keyword {}
|
|||
/// Docs for prim_str
|
||||
mod prim_str {}
|
||||
|
||||
pub use core::ops;
|
||||
pub use core::ops;
|
||||
|
|
Loading…
Reference in a new issue