diff options
Diffstat (limited to 'crates/test_utils/src')
-rw-r--r-- | crates/test_utils/src/fixture.rs | 194 | ||||
-rw-r--r-- | crates/test_utils/src/lib.rs | 55 | ||||
-rw-r--r-- | crates/test_utils/src/minicore.rs | 549 |
3 files changed, 778 insertions, 20 deletions
diff --git a/crates/test_utils/src/fixture.rs b/crates/test_utils/src/fixture.rs index d0bddf7d8..44656267f 100644 --- a/crates/test_utils/src/fixture.rs +++ b/crates/test_utils/src/fixture.rs | |||
@@ -77,6 +77,11 @@ pub struct Fixture { | |||
77 | pub introduce_new_source_root: bool, | 77 | pub introduce_new_source_root: bool, |
78 | } | 78 | } |
79 | 79 | ||
80 | pub struct MiniCore { | ||
81 | activated_flags: Vec<String>, | ||
82 | valid_flags: Vec<String>, | ||
83 | } | ||
84 | |||
80 | impl Fixture { | 85 | impl Fixture { |
81 | /// Parses text which looks like this: | 86 | /// Parses text which looks like this: |
82 | /// | 87 | /// |
@@ -86,12 +91,28 @@ impl Fixture { | |||
86 | /// line 2 | 91 | /// line 2 |
87 | /// //- other meta | 92 | /// //- other meta |
88 | /// ``` | 93 | /// ``` |
89 | pub fn parse(ra_fixture: &str) -> Vec<Fixture> { | 94 | /// |
95 | /// Fixture can also start with a minicore declaration: | ||
96 | /// | ||
97 | /// ``` | ||
98 | /// //- minicore: sized | ||
99 | /// ``` | ||
100 | /// | ||
101 | /// That will include a subset of `libcore` into the fixture, see | ||
102 | /// `minicore.rs` for what's available. | ||
103 | pub fn parse(ra_fixture: &str) -> (Option<MiniCore>, Vec<Fixture>) { | ||
90 | let fixture = trim_indent(ra_fixture); | 104 | let fixture = trim_indent(ra_fixture); |
91 | 105 | let mut fixture = fixture.as_str(); | |
106 | let mut mini_core = None; | ||
92 | let mut res: Vec<Fixture> = Vec::new(); | 107 | let mut res: Vec<Fixture> = Vec::new(); |
93 | 108 | ||
94 | let default = if ra_fixture.contains("//-") { None } else { Some("//- /main.rs") }; | 109 | if fixture.starts_with("//- minicore:") { |
110 | let first_line = fixture.split_inclusive('\n').next().unwrap(); | ||
111 | mini_core = Some(MiniCore::parse(first_line)); | ||
112 | fixture = &fixture[first_line.len()..]; | ||
113 | } | ||
114 | |||
115 | let default = if fixture.contains("//-") { None } else { Some("//- /main.rs") }; | ||
95 | 116 | ||
96 | for (ix, line) in default.into_iter().chain(fixture.split_inclusive('\n')).enumerate() { | 117 | for (ix, line) in default.into_iter().chain(fixture.split_inclusive('\n')).enumerate() { |
97 | if line.contains("//-") { | 118 | if line.contains("//-") { |
@@ -108,12 +129,22 @@ impl Fixture { | |||
108 | if line.starts_with("//-") { | 129 | if line.starts_with("//-") { |
109 | let meta = Fixture::parse_meta_line(line); | 130 | let meta = Fixture::parse_meta_line(line); |
110 | res.push(meta) | 131 | res.push(meta) |
111 | } else if let Some(entry) = res.last_mut() { | 132 | } else { |
112 | entry.text.push_str(line); | 133 | if line.starts_with("// ") |
134 | && line.contains(':') | ||
135 | && !line.contains("::") | ||
136 | && line.chars().all(|it| !it.is_uppercase()) | ||
137 | { | ||
138 | panic!("looks like invalid metadata line: {:?}", line) | ||
139 | } | ||
140 | |||
141 | if let Some(entry) = res.last_mut() { | ||
142 | entry.text.push_str(line); | ||
143 | } | ||
113 | } | 144 | } |
114 | } | 145 | } |
115 | 146 | ||
116 | res | 147 | (mini_core, res) |
117 | } | 148 | } |
118 | 149 | ||
119 | //- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo | 150 | //- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo |
@@ -123,7 +154,7 @@ impl Fixture { | |||
123 | let components = meta.split_ascii_whitespace().collect::<Vec<_>>(); | 154 | let components = meta.split_ascii_whitespace().collect::<Vec<_>>(); |
124 | 155 | ||
125 | let path = components[0].to_string(); | 156 | let path = components[0].to_string(); |
126 | assert!(path.starts_with('/')); | 157 | assert!(path.starts_with('/'), "fixture path does not start with `/`: {:?}", path); |
127 | 158 | ||
128 | let mut krate = None; | 159 | let mut krate = None; |
129 | let mut deps = Vec::new(); | 160 | let mut deps = Vec::new(); |
@@ -133,7 +164,9 @@ impl Fixture { | |||
133 | let mut env = FxHashMap::default(); | 164 | let mut env = FxHashMap::default(); |
134 | let mut introduce_new_source_root = false; | 165 | let mut introduce_new_source_root = false; |
135 | for component in components[1..].iter() { | 166 | for component in components[1..].iter() { |
136 | let (key, value) = component.split_once(':').unwrap(); | 167 | let (key, value) = component |
168 | .split_once(':') | ||
169 | .unwrap_or_else(|| panic!("invalid meta line: {:?}", meta)); | ||
137 | match key { | 170 | match key { |
138 | "crate" => krate = Some(value.to_string()), | 171 | "crate" => krate = Some(value.to_string()), |
139 | "deps" => deps = value.split(',').map(|it| it.to_string()).collect(), | 172 | "deps" => deps = value.split(',').map(|it| it.to_string()).collect(), |
@@ -172,6 +205,139 @@ impl Fixture { | |||
172 | } | 205 | } |
173 | } | 206 | } |
174 | 207 | ||
208 | impl MiniCore { | ||
209 | fn has_flag(&self, flag: &str) -> bool { | ||
210 | self.activated_flags.iter().any(|it| it == flag) | ||
211 | } | ||
212 | |||
213 | #[track_caller] | ||
214 | fn assert_valid_flag(&self, flag: &str) { | ||
215 | if !self.valid_flags.iter().any(|it| it == flag) { | ||
216 | panic!("invalid flag: {:?}, valid flags: {:?}", flag, self.valid_flags); | ||
217 | } | ||
218 | } | ||
219 | |||
220 | fn parse(line: &str) -> MiniCore { | ||
221 | let mut res = MiniCore { activated_flags: Vec::new(), valid_flags: Vec::new() }; | ||
222 | |||
223 | let line = line.strip_prefix("//- minicore:").unwrap().trim(); | ||
224 | for entry in line.split(", ") { | ||
225 | if res.has_flag(entry) { | ||
226 | panic!("duplicate minicore flag: {:?}", entry) | ||
227 | } | ||
228 | res.activated_flags.push(entry.to_string()) | ||
229 | } | ||
230 | |||
231 | res | ||
232 | } | ||
233 | |||
234 | /// Strips parts of minicore.rs which are flagged by inactive flags. | ||
235 | /// | ||
236 | /// This is probably over-engineered to support flags dependencies. | ||
237 | pub fn source_code(mut self) -> String { | ||
238 | let mut buf = String::new(); | ||
239 | let raw_mini_core = include_str!("./minicore.rs"); | ||
240 | let mut lines = raw_mini_core.split_inclusive('\n'); | ||
241 | |||
242 | let mut parsing_flags = false; | ||
243 | let mut implications = Vec::new(); | ||
244 | |||
245 | // Parse `//!` preamble and extract flags and dependencies. | ||
246 | for line in lines.by_ref() { | ||
247 | let line = match line.strip_prefix("//!") { | ||
248 | Some(it) => it, | ||
249 | None => { | ||
250 | assert!(line.trim().is_empty()); | ||
251 | break; | ||
252 | } | ||
253 | }; | ||
254 | |||
255 | if parsing_flags { | ||
256 | let (flag, deps) = line.split_once(':').unwrap(); | ||
257 | let flag = flag.trim(); | ||
258 | self.valid_flags.push(flag.to_string()); | ||
259 | for dep in deps.split(", ") { | ||
260 | let dep = dep.trim(); | ||
261 | if !dep.is_empty() { | ||
262 | self.assert_valid_flag(dep); | ||
263 | implications.push((flag, dep)); | ||
264 | } | ||
265 | } | ||
266 | } | ||
267 | |||
268 | if line.contains("Available flags:") { | ||
269 | parsing_flags = true; | ||
270 | } | ||
271 | } | ||
272 | |||
273 | for flag in &self.activated_flags { | ||
274 | self.assert_valid_flag(flag); | ||
275 | } | ||
276 | |||
277 | // Fixed point loop to compute transitive closure of flags. | ||
278 | loop { | ||
279 | let mut changed = false; | ||
280 | for &(u, v) in implications.iter() { | ||
281 | if self.has_flag(u) && !self.has_flag(v) { | ||
282 | self.activated_flags.push(v.to_string()); | ||
283 | changed = true; | ||
284 | } | ||
285 | } | ||
286 | if !changed { | ||
287 | break; | ||
288 | } | ||
289 | } | ||
290 | |||
291 | let mut active_regions = Vec::new(); | ||
292 | let mut seen_regions = Vec::new(); | ||
293 | for line in lines { | ||
294 | let trimmed = line.trim(); | ||
295 | if let Some(region) = trimmed.strip_prefix("// region:") { | ||
296 | active_regions.push(region); | ||
297 | continue; | ||
298 | } | ||
299 | if let Some(region) = trimmed.strip_prefix("// endregion:") { | ||
300 | let prev = active_regions.pop().unwrap(); | ||
301 | assert_eq!(prev, region); | ||
302 | continue; | ||
303 | } | ||
304 | |||
305 | let mut line_region = false; | ||
306 | if let Some(idx) = trimmed.find("// :") { | ||
307 | line_region = true; | ||
308 | active_regions.push(&trimmed[idx + "// :".len()..]); | ||
309 | } | ||
310 | |||
311 | let mut keep = true; | ||
312 | for ®ion in &active_regions { | ||
313 | assert!( | ||
314 | !region.starts_with(' '), | ||
315 | "region marker starts with a space: {:?}", | ||
316 | region | ||
317 | ); | ||
318 | self.assert_valid_flag(region); | ||
319 | seen_regions.push(region); | ||
320 | keep &= self.has_flag(region); | ||
321 | } | ||
322 | |||
323 | if keep { | ||
324 | buf.push_str(line) | ||
325 | } | ||
326 | if line_region { | ||
327 | active_regions.pop().unwrap(); | ||
328 | } | ||
329 | } | ||
330 | |||
331 | for flag in &self.valid_flags { | ||
332 | if !seen_regions.iter().any(|it| it == flag) { | ||
333 | panic!("unused minicore flag: {:?}", flag); | ||
334 | } | ||
335 | } | ||
336 | format!("{}", buf); | ||
337 | buf | ||
338 | } | ||
339 | } | ||
340 | |||
175 | #[test] | 341 | #[test] |
176 | #[should_panic] | 342 | #[should_panic] |
177 | fn parse_fixture_checks_further_indented_metadata() { | 343 | fn parse_fixture_checks_further_indented_metadata() { |
@@ -189,12 +355,14 @@ fn parse_fixture_checks_further_indented_metadata() { | |||
189 | 355 | ||
190 | #[test] | 356 | #[test] |
191 | fn parse_fixture_gets_full_meta() { | 357 | fn parse_fixture_gets_full_meta() { |
192 | let parsed = Fixture::parse( | 358 | let (mini_core, parsed) = Fixture::parse( |
193 | r" | 359 | r#" |
194 | //- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b,atom env:OUTDIR=path/to,OTHER=foo | 360 | //- minicore: coerce_unsized |
195 | mod m; | 361 | //- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b,atom env:OUTDIR=path/to,OTHER=foo |
196 | ", | 362 | mod m; |
363 | "#, | ||
197 | ); | 364 | ); |
365 | assert_eq!(mini_core.unwrap().activated_flags, vec!["coerce_unsized".to_string()]); | ||
198 | assert_eq!(1, parsed.len()); | 366 | assert_eq!(1, parsed.len()); |
199 | 367 | ||
200 | let meta = &parsed[0]; | 368 | let meta = &parsed[0]; |
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs index b2fe25f82..d9c22c180 100644 --- a/crates/test_utils/src/lib.rs +++ b/crates/test_utils/src/lib.rs | |||
@@ -11,6 +11,7 @@ mod fixture; | |||
11 | mod assert_linear; | 11 | mod assert_linear; |
12 | 12 | ||
13 | use std::{ | 13 | use std::{ |
14 | collections::BTreeMap, | ||
14 | convert::{TryFrom, TryInto}, | 15 | convert::{TryFrom, TryInto}, |
15 | env, fs, | 16 | env, fs, |
16 | path::{Path, PathBuf}, | 17 | path::{Path, PathBuf}, |
@@ -23,7 +24,10 @@ use text_size::{TextRange, TextSize}; | |||
23 | pub use dissimilar::diff as __diff; | 24 | pub use dissimilar::diff as __diff; |
24 | pub use rustc_hash::FxHashMap; | 25 | pub use rustc_hash::FxHashMap; |
25 | 26 | ||
26 | pub use crate::{assert_linear::AssertLinear, fixture::Fixture}; | 27 | pub use crate::{ |
28 | assert_linear::AssertLinear, | ||
29 | fixture::{Fixture, MiniCore}, | ||
30 | }; | ||
27 | 31 | ||
28 | pub const CURSOR_MARKER: &str = "$0"; | 32 | pub const CURSOR_MARKER: &str = "$0"; |
29 | pub const ESCAPED_CURSOR_MARKER: &str = "\\$0"; | 33 | pub const ESCAPED_CURSOR_MARKER: &str = "\\$0"; |
@@ -202,14 +206,25 @@ pub fn add_cursor(text: &str, offset: TextSize) -> String { | |||
202 | /// | 206 | /// |
203 | /// // ^^^ first line | 207 | /// // ^^^ first line |
204 | /// // | second line | 208 | /// // | second line |
209 | /// | ||
210 | /// Annotations point to the last line that actually was long enough for the | ||
211 | /// range, not counting annotations themselves. So overlapping annotations are | ||
212 | /// possible: | ||
213 | /// ```no_run | ||
214 | /// // stuff other stuff | ||
215 | /// // ^^ 'st' | ||
216 | /// // ^^^^^ 'stuff' | ||
217 | /// // ^^^^^^^^^^^ 'other stuff' | ||
218 | /// ``` | ||
205 | pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> { | 219 | pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> { |
206 | let mut res = Vec::new(); | 220 | let mut res = Vec::new(); |
207 | let mut prev_line_start: Option<TextSize> = Some(0.into()); | 221 | // map from line length to beginning of last line that had that length |
222 | let mut line_start_map = BTreeMap::new(); | ||
208 | let mut line_start: TextSize = 0.into(); | 223 | let mut line_start: TextSize = 0.into(); |
209 | let mut prev_line_annotations: Vec<(TextSize, usize)> = Vec::new(); | 224 | let mut prev_line_annotations: Vec<(TextSize, usize)> = Vec::new(); |
210 | for line in text.split_inclusive('\n') { | 225 | for line in text.split_inclusive('\n') { |
211 | let mut this_line_annotations = Vec::new(); | 226 | let mut this_line_annotations = Vec::new(); |
212 | if let Some(idx) = line.find("//") { | 227 | let line_length = if let Some(idx) = line.find("//") { |
213 | let annotation_offset = TextSize::of(&line[..idx + "//".len()]); | 228 | let annotation_offset = TextSize::of(&line[..idx + "//".len()]); |
214 | for annotation in extract_line_annotations(&line[idx + "//".len()..]) { | 229 | for annotation in extract_line_annotations(&line[idx + "//".len()..]) { |
215 | match annotation { | 230 | match annotation { |
@@ -219,7 +234,9 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> { | |||
219 | let range = if file { | 234 | let range = if file { |
220 | TextRange::up_to(TextSize::of(text)) | 235 | TextRange::up_to(TextSize::of(text)) |
221 | } else { | 236 | } else { |
222 | range + prev_line_start.unwrap() | 237 | let line_start = line_start_map.range(range.end()..).next().unwrap(); |
238 | |||
239 | range + line_start.1 | ||
223 | }; | 240 | }; |
224 | res.push((range, content)) | 241 | res.push((range, content)) |
225 | } | 242 | } |
@@ -235,9 +252,14 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> { | |||
235 | } | 252 | } |
236 | } | 253 | } |
237 | } | 254 | } |
238 | } | 255 | idx.try_into().unwrap() |
256 | } else { | ||
257 | TextSize::of(line) | ||
258 | }; | ||
259 | |||
260 | line_start_map = line_start_map.split_off(&line_length); | ||
261 | line_start_map.insert(line_length, line_start); | ||
239 | 262 | ||
240 | prev_line_start = Some(line_start); | ||
241 | line_start += TextSize::of(line); | 263 | line_start += TextSize::of(line); |
242 | 264 | ||
243 | prev_line_annotations = this_line_annotations; | 265 | prev_line_annotations = this_line_annotations; |
@@ -293,7 +315,7 @@ fn extract_line_annotations(mut line: &str) -> Vec<LineAnnotation> { | |||
293 | } | 315 | } |
294 | 316 | ||
295 | #[test] | 317 | #[test] |
296 | fn test_extract_annotations() { | 318 | fn test_extract_annotations_1() { |
297 | let text = stdx::trim_indent( | 319 | let text = stdx::trim_indent( |
298 | r#" | 320 | r#" |
299 | fn main() { | 321 | fn main() { |
@@ -318,6 +340,25 @@ fn main() { | |||
318 | assert_eq!(res[3].0.len(), 115); | 340 | assert_eq!(res[3].0.len(), 115); |
319 | } | 341 | } |
320 | 342 | ||
343 | #[test] | ||
344 | fn test_extract_annotations_2() { | ||
345 | let text = stdx::trim_indent( | ||
346 | r#" | ||
347 | fn main() { | ||
348 | (x, y); | ||
349 | //^ a | ||
350 | // ^ b | ||
351 | //^^^^^^^^ c | ||
352 | }"#, | ||
353 | ); | ||
354 | let res = extract_annotations(&text) | ||
355 | .into_iter() | ||
356 | .map(|(range, ann)| (&text[range], ann)) | ||
357 | .collect::<Vec<_>>(); | ||
358 | |||
359 | assert_eq!(res, [("x", "a".into()), ("y", "b".into()), ("(x, y)", "c".into())]); | ||
360 | } | ||
361 | |||
321 | /// Returns `false` if slow tests should not run, otherwise returns `true` and | 362 | /// Returns `false` if slow tests should not run, otherwise returns `true` and |
322 | /// also creates a file at `./target/.slow_tests_cookie` which serves as a flag | 363 | /// also creates a file at `./target/.slow_tests_cookie` which serves as a flag |
323 | /// that slow tests did run. | 364 | /// that slow tests did run. |
diff --git a/crates/test_utils/src/minicore.rs b/crates/test_utils/src/minicore.rs new file mode 100644 index 000000000..ce6ad8541 --- /dev/null +++ b/crates/test_utils/src/minicore.rs | |||
@@ -0,0 +1,549 @@ | |||
1 | //! This is a fixture we use for tests that need lang items. | ||
2 | //! | ||
3 | //! We want to include the minimal subset of core for each test, so this file | ||
4 | //! supports "conditional compilation". Tests use the following syntax to include minicore: | ||
5 | //! | ||
6 | //! //- minicore: flag1, flag2 | ||
7 | //! | ||
8 | //! We then strip all the code marked with other flags. | ||
9 | //! | ||
10 | //! Available flags: | ||
11 | //! sized: | ||
12 | //! unsize: sized | ||
13 | //! coerce_unsized: unsize | ||
14 | //! slice: | ||
15 | //! range: | ||
16 | //! deref: sized | ||
17 | //! deref_mut: deref | ||
18 | //! index: sized | ||
19 | //! fn: | ||
20 | //! pin: | ||
21 | //! future: pin | ||
22 | //! option: | ||
23 | //! result: | ||
24 | //! iterator: option | ||
25 | //! iterators: iterator, fn | ||
26 | //! default: sized | ||
27 | //! clone: sized | ||
28 | //! copy: clone | ||
29 | //! from: sized | ||
30 | //! eq: sized | ||
31 | //! ord: eq, option | ||
32 | //! derive: | ||
33 | |||
34 | pub mod marker { | ||
35 | // region:sized | ||
36 | #[lang = "sized"] | ||
37 | #[fundamental] | ||
38 | #[rustc_specialization_trait] | ||
39 | pub trait Sized {} | ||
40 | // endregion:sized | ||
41 | |||
42 | // region:unsize | ||
43 | #[lang = "unsize"] | ||
44 | pub trait Unsize<T: ?Sized> {} | ||
45 | // endregion:unsize | ||
46 | |||
47 | // region:copy | ||
48 | #[lang = "copy"] | ||
49 | pub trait Copy: Clone {} | ||
50 | // region:derive | ||
51 | #[rustc_builtin_macro] | ||
52 | pub macro Copy($item:item) {} | ||
53 | // endregion:derive | ||
54 | |||
55 | mod copy_impls { | ||
56 | use super::Copy; | ||
57 | |||
58 | macro_rules! impl_copy { | ||
59 | ($($t:ty)*) => { | ||
60 | $( | ||
61 | impl Copy for $t {} | ||
62 | )* | ||
63 | } | ||
64 | } | ||
65 | |||
66 | impl_copy! { | ||
67 | usize u8 u16 u32 u64 u128 | ||
68 | isize i8 i16 i32 i64 i128 | ||
69 | f32 f64 | ||
70 | bool char | ||
71 | } | ||
72 | |||
73 | impl<T: ?Sized> Copy for *const T {} | ||
74 | impl<T: ?Sized> Copy for *mut T {} | ||
75 | impl<T: ?Sized> Copy for &T {} | ||
76 | } | ||
77 | // endregion:copy | ||
78 | } | ||
79 | |||
80 | // region:default | ||
81 | pub mod default { | ||
82 | pub trait Default: Sized { | ||
83 | fn default() -> Self; | ||
84 | } | ||
85 | } | ||
86 | // endregion:default | ||
87 | |||
88 | // region:clone | ||
89 | pub mod clone { | ||
90 | #[lang = "clone"] | ||
91 | pub trait Clone: Sized { | ||
92 | fn clone(&self) -> Self; | ||
93 | } | ||
94 | // region:derive | ||
95 | #[rustc_builtin_macro] | ||
96 | pub macro Clone($item:item) {} | ||
97 | // endregion:derive | ||
98 | } | ||
99 | // endregion:clone | ||
100 | |||
101 | // region:from | ||
102 | pub mod convert { | ||
103 | pub trait From<T>: Sized { | ||
104 | fn from(_: T) -> Self; | ||
105 | } | ||
106 | pub trait Into<T>: Sized { | ||
107 | fn into(self) -> T; | ||
108 | } | ||
109 | |||
110 | impl<T, U> Into<U> for T | ||
111 | where | ||
112 | U: From<T>, | ||
113 | { | ||
114 | fn into(self) -> U { | ||
115 | U::from(self) | ||
116 | } | ||
117 | } | ||
118 | |||
119 | impl<T> From<T> for T { | ||
120 | fn from(t: T) -> T { | ||
121 | t | ||
122 | } | ||
123 | } | ||
124 | } | ||
125 | // endregion:from | ||
126 | |||
127 | pub mod ops { | ||
128 | // region:coerce_unsized | ||
129 | mod unsize { | ||
130 | use crate::marker::Unsize; | ||
131 | |||
132 | #[lang = "coerce_unsized"] | ||
133 | pub trait CoerceUnsized<T: ?Sized> {} | ||
134 | |||
135 | impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {} | ||
136 | impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {} | ||
137 | impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {} | ||
138 | impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {} | ||
139 | |||
140 | impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} | ||
141 | impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a T {} | ||
142 | |||
143 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} | ||
144 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *mut T {} | ||
145 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {} | ||
146 | } | ||
147 | pub use self::unsize::CoerceUnsized; | ||
148 | // endregion:coerce_unsized | ||
149 | |||
150 | // region:deref | ||
151 | mod deref { | ||
152 | #[lang = "deref"] | ||
153 | pub trait Deref { | ||
154 | #[lang = "deref_target"] | ||
155 | type Target: ?Sized; | ||
156 | fn deref(&self) -> &Self::Target; | ||
157 | } | ||
158 | // region:deref_mut | ||
159 | #[lang = "deref_mut"] | ||
160 | pub trait DerefMut: Deref { | ||
161 | fn deref_mut(&mut self) -> &mut Self::Target; | ||
162 | } | ||
163 | // endregion:deref_mut | ||
164 | } | ||
165 | pub use self::deref::{ | ||
166 | Deref, | ||
167 | DerefMut, // :deref_mut | ||
168 | }; | ||
169 | // endregion:deref | ||
170 | |||
171 | // region:index | ||
172 | mod index { | ||
173 | #[lang = "index"] | ||
174 | pub trait Index<Idx: ?Sized> { | ||
175 | type Output: ?Sized; | ||
176 | fn index(&self, index: Idx) -> &Self::Output; | ||
177 | } | ||
178 | #[lang = "index_mut"] | ||
179 | pub trait IndexMut<Idx: ?Sized>: Index<Idx> { | ||
180 | fn index_mut(&mut self, index: Idx) -> &mut Self::Output; | ||
181 | } | ||
182 | |||
183 | // region:slice | ||
184 | impl<T, I> Index<I> for [T] | ||
185 | where | ||
186 | I: SliceIndex<[T]>, | ||
187 | { | ||
188 | type Output = I::Output; | ||
189 | fn index(&self, index: I) -> &I::Output { | ||
190 | loop {} | ||
191 | } | ||
192 | } | ||
193 | impl<T, I> IndexMut<I> for [T] | ||
194 | where | ||
195 | I: SliceIndex<[T]>, | ||
196 | { | ||
197 | fn index_mut(&mut self, index: I) -> &mut I::Output { | ||
198 | loop {} | ||
199 | } | ||
200 | } | ||
201 | |||
202 | pub unsafe trait SliceIndex<T: ?Sized> { | ||
203 | type Output: ?Sized; | ||
204 | } | ||
205 | unsafe impl<T> SliceIndex<[T]> for usize { | ||
206 | type Output = T; | ||
207 | } | ||
208 | // endregion:slice | ||
209 | } | ||
210 | pub use self::index::{Index, IndexMut}; | ||
211 | // endregion:index | ||
212 | |||
213 | // region:range | ||
214 | mod range { | ||
215 | #[lang = "RangeFull"] | ||
216 | pub struct RangeFull; | ||
217 | |||
218 | #[lang = "Range"] | ||
219 | pub struct Range<Idx> { | ||
220 | pub start: Idx, | ||
221 | pub end: Idx, | ||
222 | } | ||
223 | |||
224 | #[lang = "RangeFrom"] | ||
225 | pub struct RangeFrom<Idx> { | ||
226 | pub start: Idx, | ||
227 | } | ||
228 | |||
229 | #[lang = "RangeTo"] | ||
230 | pub struct RangeTo<Idx> { | ||
231 | pub end: Idx, | ||
232 | } | ||
233 | |||
234 | #[lang = "RangeInclusive"] | ||
235 | pub struct RangeInclusive<Idx> { | ||
236 | pub(crate) start: Idx, | ||
237 | pub(crate) end: Idx, | ||
238 | pub(crate) exhausted: bool, | ||
239 | } | ||
240 | |||
241 | #[lang = "RangeToInclusive"] | ||
242 | pub struct RangeToInclusive<Idx> { | ||
243 | pub end: Idx, | ||
244 | } | ||
245 | } | ||
246 | pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; | ||
247 | pub use self::range::{RangeInclusive, RangeToInclusive}; | ||
248 | // endregion:range | ||
249 | |||
250 | // region:fn | ||
251 | mod function { | ||
252 | #[lang = "fn"] | ||
253 | #[fundamental] | ||
254 | pub trait Fn<Args>: FnMut<Args> {} | ||
255 | |||
256 | #[lang = "fn_mut"] | ||
257 | #[fundamental] | ||
258 | pub trait FnMut<Args>: FnOnce<Args> {} | ||
259 | |||
260 | #[lang = "fn_once"] | ||
261 | #[fundamental] | ||
262 | pub trait FnOnce<Args> { | ||
263 | #[lang = "fn_once_output"] | ||
264 | type Output; | ||
265 | } | ||
266 | } | ||
267 | pub use self::function::{Fn, FnMut, FnOnce}; | ||
268 | // endregion:fn | ||
269 | } | ||
270 | |||
271 | // region:eq | ||
272 | pub mod cmp { | ||
273 | #[lang = "eq"] | ||
274 | pub trait PartialEq<Rhs: ?Sized = Self> { | ||
275 | fn eq(&self, other: &Rhs) -> bool; | ||
276 | } | ||
277 | |||
278 | pub trait Eq: PartialEq<Self> {} | ||
279 | |||
280 | // region:derive | ||
281 | #[rustc_builtin_macro] | ||
282 | pub macro PartialEq($item:item) {} | ||
283 | #[rustc_builtin_macro] | ||
284 | pub macro Eq($item:item) {} | ||
285 | // endregion:derive | ||
286 | |||
287 | // region:ord | ||
288 | #[lang = "partial_ord"] | ||
289 | pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> { | ||
290 | fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>; | ||
291 | } | ||
292 | |||
293 | pub trait Ord: Eq + PartialOrd<Self> { | ||
294 | fn cmp(&self, other: &Self) -> Ordering; | ||
295 | } | ||
296 | |||
297 | pub enum Ordering { | ||
298 | Less = -1, | ||
299 | Equal = 0, | ||
300 | Greater = 1, | ||
301 | } | ||
302 | |||
303 | // region:derive | ||
304 | #[rustc_builtin_macro] | ||
305 | pub macro PartialOrd($item:item) {} | ||
306 | #[rustc_builtin_macro] | ||
307 | pub macro Ord($item:item) {} | ||
308 | // endregion:derive | ||
309 | |||
310 | // endregion:ord | ||
311 | } | ||
312 | // endregion:eq | ||
313 | |||
314 | // region:slice | ||
315 | pub mod slice { | ||
316 | #[lang = "slice"] | ||
317 | impl<T> [T] { | ||
318 | pub fn len(&self) -> usize { | ||
319 | loop {} | ||
320 | } | ||
321 | } | ||
322 | } | ||
323 | // endregion:slice | ||
324 | |||
325 | // region:option | ||
326 | pub mod option { | ||
327 | pub enum Option<T> { | ||
328 | #[lang = "None"] | ||
329 | None, | ||
330 | #[lang = "Some"] | ||
331 | Some(T), | ||
332 | } | ||
333 | } | ||
334 | // endregion:option | ||
335 | |||
336 | // region:result | ||
337 | pub mod result { | ||
338 | pub enum Result<T, E> { | ||
339 | #[lang = "Ok"] | ||
340 | Ok(T), | ||
341 | #[lang = "Err"] | ||
342 | Err(E), | ||
343 | } | ||
344 | } | ||
345 | // endregion:result | ||
346 | |||
347 | // region:pin | ||
348 | pub mod pin { | ||
349 | #[lang = "pin"] | ||
350 | #[fundamental] | ||
351 | pub struct Pin<P> { | ||
352 | pointer: P, | ||
353 | } | ||
354 | } | ||
355 | // endregion:pin | ||
356 | |||
357 | // region:future | ||
358 | pub mod future { | ||
359 | use crate::{ | ||
360 | pin::Pin, | ||
361 | task::{Context, Poll}, | ||
362 | }; | ||
363 | |||
364 | #[lang = "future_trait"] | ||
365 | pub trait Future { | ||
366 | type Output; | ||
367 | #[lang = "poll"] | ||
368 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>; | ||
369 | } | ||
370 | } | ||
371 | pub mod task { | ||
372 | pub enum Poll<T> { | ||
373 | #[lang = "Ready"] | ||
374 | Ready(T), | ||
375 | #[lang = "Pending"] | ||
376 | Pending, | ||
377 | } | ||
378 | |||
379 | pub struct Context<'a> { | ||
380 | waker: &'a (), | ||
381 | } | ||
382 | } | ||
383 | // endregion:future | ||
384 | |||
385 | // region:iterator | ||
386 | pub mod iter { | ||
387 | // region:iterators | ||
388 | mod adapters { | ||
389 | pub struct Take<I> { | ||
390 | iter: I, | ||
391 | n: usize, | ||
392 | } | ||
393 | impl<I> Iterator for Take<I> | ||
394 | where | ||
395 | I: Iterator, | ||
396 | { | ||
397 | type Item = <I as Iterator>::Item; | ||
398 | |||
399 | fn next(&mut self) -> Option<<I as Iterator>::Item> { | ||
400 | loop {} | ||
401 | } | ||
402 | } | ||
403 | |||
404 | pub struct FilterMap<I, F> { | ||
405 | iter: I, | ||
406 | f: F, | ||
407 | } | ||
408 | impl<B, I: Iterator, F> Iterator for FilterMap<I, F> | ||
409 | where | ||
410 | F: FnMut(I::Item) -> Option<B>, | ||
411 | { | ||
412 | type Item = B; | ||
413 | |||
414 | #[inline] | ||
415 | fn next(&mut self) -> Option<B> { | ||
416 | loop {} | ||
417 | } | ||
418 | } | ||
419 | } | ||
420 | pub use self::adapters::Take; | ||
421 | |||
422 | mod sources { | ||
423 | mod repeat { | ||
424 | pub fn repeat<T>(elt: T) -> Repeat<T> { | ||
425 | loop {} | ||
426 | } | ||
427 | |||
428 | pub struct Repeat<A> { | ||
429 | element: A, | ||
430 | } | ||
431 | |||
432 | impl<A> Iterator for Repeat<A> { | ||
433 | type Item = A; | ||
434 | |||
435 | fn next(&mut self) -> Option<A> { | ||
436 | loop {} | ||
437 | } | ||
438 | } | ||
439 | } | ||
440 | pub use self::repeat::{repeat, Repeat}; | ||
441 | } | ||
442 | pub use self::sources::{repeat, Repeat}; | ||
443 | // endregion:iterators | ||
444 | |||
445 | mod traits { | ||
446 | mod iterator { | ||
447 | use super::super::Take; | ||
448 | |||
449 | pub trait Iterator { | ||
450 | type Item; | ||
451 | #[lang = "next"] | ||
452 | fn next(&mut self) -> Option<Self::Item>; | ||
453 | fn nth(&mut self, n: usize) -> Option<Self::Item> { | ||
454 | loop {} | ||
455 | } | ||
456 | fn by_ref(&mut self) -> &mut Self | ||
457 | where | ||
458 | Self: Sized, | ||
459 | { | ||
460 | self | ||
461 | } | ||
462 | // region:iterators | ||
463 | fn take(self, n: usize) -> crate::iter::Take<Self> { | ||
464 | loop {} | ||
465 | } | ||
466 | fn filter_map<B, F>(self, f: F) -> crate::iter::FilterMap<Self, F> | ||
467 | where | ||
468 | Self: Sized, | ||
469 | F: FnMut(Self::Item) -> Option<B>, | ||
470 | { | ||
471 | loop {} | ||
472 | } | ||
473 | // endregion:iterators | ||
474 | } | ||
475 | impl<I: Iterator + ?Sized> Iterator for &mut I { | ||
476 | type Item = I::Item; | ||
477 | fn next(&mut self) -> Option<I::Item> { | ||
478 | (**self).next() | ||
479 | } | ||
480 | } | ||
481 | } | ||
482 | pub use self::iterator::Iterator; | ||
483 | |||
484 | mod collect { | ||
485 | pub trait IntoIterator { | ||
486 | type Item; | ||
487 | type IntoIter: Iterator<Item = Self::Item>; | ||
488 | #[lang = "into_iter"] | ||
489 | fn into_iter(self) -> Self::IntoIter; | ||
490 | } | ||
491 | impl<I: Iterator> IntoIterator for I { | ||
492 | type Item = I::Item; | ||
493 | type IntoIter = I; | ||
494 | fn into_iter(self) -> I { | ||
495 | self | ||
496 | } | ||
497 | } | ||
498 | } | ||
499 | pub use self::collect::IntoIterator; | ||
500 | } | ||
501 | pub use self::traits::{IntoIterator, Iterator}; | ||
502 | } | ||
503 | // endregion:iterator | ||
504 | |||
505 | // region:derive | ||
506 | mod macros { | ||
507 | pub(crate) mod builtin { | ||
508 | #[rustc_builtin_macro] | ||
509 | pub macro derive($item:item) { | ||
510 | /* compiler built-in */ | ||
511 | } | ||
512 | } | ||
513 | } | ||
514 | // endregion:derive | ||
515 | |||
516 | pub mod prelude { | ||
517 | pub mod v1 { | ||
518 | pub use crate::{ | ||
519 | clone::Clone, // :clone | ||
520 | cmp::{Eq, PartialEq}, // :eq | ||
521 | cmp::{Ord, PartialOrd}, // :ord | ||
522 | convert::{From, Into}, // :from | ||
523 | default::Default, // :default | ||
524 | iter::{IntoIterator, Iterator}, // :iterator | ||
525 | macros::builtin::derive, // :derive | ||
526 | marker::Copy, // :copy | ||
527 | marker::Sized, // :sized | ||
528 | ops::{Fn, FnMut, FnOnce}, // :fn | ||
529 | option::Option::{self, None, Some}, // :option | ||
530 | result::Result::{self, Err, Ok}, // :result | ||
531 | }; | ||
532 | } | ||
533 | |||
534 | pub mod rust_2015 { | ||
535 | pub use super::v1::*; | ||
536 | } | ||
537 | |||
538 | pub mod rust_2018 { | ||
539 | pub use super::v1::*; | ||
540 | } | ||
541 | |||
542 | pub mod rust_2021 { | ||
543 | pub use super::v1::*; | ||
544 | } | ||
545 | } | ||
546 | |||
547 | #[prelude_import] | ||
548 | #[allow(unused)] | ||
549 | use prelude::v1::*; | ||