diff options
Diffstat (limited to 'crates/test_utils')
-rw-r--r-- | crates/test_utils/src/fixture.rs | 192 | ||||
-rw-r--r-- | crates/test_utils/src/lib.rs | 52 | ||||
-rw-r--r-- | crates/test_utils/src/minicore.rs | 234 |
3 files changed, 456 insertions, 22 deletions
diff --git a/crates/test_utils/src/fixture.rs b/crates/test_utils/src/fixture.rs index d0bddf7d8..005a5c092 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 |
@@ -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 ac5a9509d..d55bae62a 100644 --- a/crates/test_utils/src/lib.rs +++ b/crates/test_utils/src/lib.rs | |||
@@ -23,7 +23,10 @@ use text_size::{TextRange, TextSize}; | |||
23 | pub use dissimilar::diff as __diff; | 23 | pub use dissimilar::diff as __diff; |
24 | pub use rustc_hash::FxHashMap; | 24 | pub use rustc_hash::FxHashMap; |
25 | 25 | ||
26 | pub use crate::{assert_linear::AssertLinear, fixture::Fixture}; | 26 | pub use crate::{ |
27 | assert_linear::AssertLinear, | ||
28 | fixture::{Fixture, MiniCore}, | ||
29 | }; | ||
27 | 30 | ||
28 | pub const CURSOR_MARKER: &str = "$0"; | 31 | pub const CURSOR_MARKER: &str = "$0"; |
29 | pub const ESCAPED_CURSOR_MARKER: &str = "\\$0"; | 32 | pub const ESCAPED_CURSOR_MARKER: &str = "\\$0"; |
@@ -190,10 +193,21 @@ pub fn add_cursor(text: &str, offset: TextSize) -> String { | |||
190 | res | 193 | res |
191 | } | 194 | } |
192 | 195 | ||
193 | /// Extracts `//^ some text` annotations | 196 | /// Extracts `//^^^ some text` annotations. |
197 | /// | ||
198 | /// A run of `^^^` can be arbitrary long and points to the corresponding range | ||
199 | /// in the line above. | ||
200 | /// | ||
201 | /// The `// ^file text` syntax can be used to attach `text` to the entirety of | ||
202 | /// the file. | ||
203 | /// | ||
204 | /// Multiline string values are supported: | ||
205 | /// | ||
206 | /// // ^^^ first line | ||
207 | /// // | second line | ||
194 | pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> { | 208 | pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> { |
195 | let mut res = Vec::new(); | 209 | let mut res = Vec::new(); |
196 | let mut prev_line_start: Option<TextSize> = None; | 210 | let mut prev_line_start: Option<TextSize> = Some(0.into()); |
197 | let mut line_start: TextSize = 0.into(); | 211 | let mut line_start: TextSize = 0.into(); |
198 | let mut prev_line_annotations: Vec<(TextSize, usize)> = Vec::new(); | 212 | let mut prev_line_annotations: Vec<(TextSize, usize)> = Vec::new(); |
199 | for line in text.split_inclusive('\n') { | 213 | for line in text.split_inclusive('\n') { |
@@ -202,10 +216,15 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> { | |||
202 | let annotation_offset = TextSize::of(&line[..idx + "//".len()]); | 216 | let annotation_offset = TextSize::of(&line[..idx + "//".len()]); |
203 | for annotation in extract_line_annotations(&line[idx + "//".len()..]) { | 217 | for annotation in extract_line_annotations(&line[idx + "//".len()..]) { |
204 | match annotation { | 218 | match annotation { |
205 | LineAnnotation::Annotation { mut range, content } => { | 219 | LineAnnotation::Annotation { mut range, content, file } => { |
206 | range += annotation_offset; | 220 | range += annotation_offset; |
207 | this_line_annotations.push((range.end(), res.len())); | 221 | this_line_annotations.push((range.end(), res.len())); |
208 | res.push((range + prev_line_start.unwrap(), content)) | 222 | let range = if file { |
223 | TextRange::up_to(TextSize::of(text)) | ||
224 | } else { | ||
225 | range + prev_line_start.unwrap() | ||
226 | }; | ||
227 | res.push((range, content)) | ||
209 | } | 228 | } |
210 | LineAnnotation::Continuation { mut offset, content } => { | 229 | LineAnnotation::Continuation { mut offset, content } => { |
211 | offset += annotation_offset; | 230 | offset += annotation_offset; |
@@ -226,11 +245,12 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> { | |||
226 | 245 | ||
227 | prev_line_annotations = this_line_annotations; | 246 | prev_line_annotations = this_line_annotations; |
228 | } | 247 | } |
248 | |||
229 | res | 249 | res |
230 | } | 250 | } |
231 | 251 | ||
232 | enum LineAnnotation { | 252 | enum LineAnnotation { |
233 | Annotation { range: TextRange, content: String }, | 253 | Annotation { range: TextRange, content: String, file: bool }, |
234 | Continuation { offset: TextSize, content: String }, | 254 | Continuation { offset: TextSize, content: String }, |
235 | } | 255 | } |
236 | 256 | ||
@@ -251,12 +271,20 @@ fn extract_line_annotations(mut line: &str) -> Vec<LineAnnotation> { | |||
251 | } | 271 | } |
252 | let range = TextRange::at(offset, len.try_into().unwrap()); | 272 | let range = TextRange::at(offset, len.try_into().unwrap()); |
253 | let next = line[len..].find(marker).map_or(line.len(), |it| it + len); | 273 | let next = line[len..].find(marker).map_or(line.len(), |it| it + len); |
254 | let content = line[len..][..next - len].trim().to_string(); | 274 | let mut content = &line[len..][..next - len]; |
275 | |||
276 | let mut file = false; | ||
277 | if !continuation && content.starts_with("file") { | ||
278 | file = true; | ||
279 | content = &content["file".len()..] | ||
280 | } | ||
281 | |||
282 | let content = content.trim().to_string(); | ||
255 | 283 | ||
256 | let annotation = if continuation { | 284 | let annotation = if continuation { |
257 | LineAnnotation::Continuation { offset: range.end(), content } | 285 | LineAnnotation::Continuation { offset: range.end(), content } |
258 | } else { | 286 | } else { |
259 | LineAnnotation::Annotation { range, content } | 287 | LineAnnotation::Annotation { range, content, file } |
260 | }; | 288 | }; |
261 | res.push(annotation); | 289 | res.push(annotation); |
262 | 290 | ||
@@ -277,16 +305,20 @@ fn main() { | |||
277 | zoo + 1 | 305 | zoo + 1 |
278 | } //^^^ type: | 306 | } //^^^ type: |
279 | // | i32 | 307 | // | i32 |
308 | |||
309 | // ^file | ||
280 | "#, | 310 | "#, |
281 | ); | 311 | ); |
282 | let res = extract_annotations(&text) | 312 | let res = extract_annotations(&text) |
283 | .into_iter() | 313 | .into_iter() |
284 | .map(|(range, ann)| (&text[range], ann)) | 314 | .map(|(range, ann)| (&text[range], ann)) |
285 | .collect::<Vec<_>>(); | 315 | .collect::<Vec<_>>(); |
316 | |||
286 | assert_eq!( | 317 | assert_eq!( |
287 | res, | 318 | res[..3], |
288 | vec![("x", "def".into()), ("y", "def".into()), ("zoo", "type:\ni32\n".into()),] | 319 | [("x", "def".into()), ("y", "def".into()), ("zoo", "type:\ni32\n".into())] |
289 | ); | 320 | ); |
321 | assert_eq!(res[3].0.len(), 115); | ||
290 | } | 322 | } |
291 | 323 | ||
292 | /// Returns `false` if slow tests should not run, otherwise returns `true` and | 324 | /// Returns `false` if slow tests should not run, otherwise returns `true` and |
diff --git a/crates/test_utils/src/minicore.rs b/crates/test_utils/src/minicore.rs new file mode 100644 index 000000000..e04ca58d2 --- /dev/null +++ b/crates/test_utils/src/minicore.rs | |||
@@ -0,0 +1,234 @@ | |||
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 | //! fn: | ||
19 | //! pin: | ||
20 | //! future: pin | ||
21 | //! option: | ||
22 | //! result: | ||
23 | |||
24 | pub mod marker { | ||
25 | // region:sized | ||
26 | #[lang = "sized"] | ||
27 | #[fundamental] | ||
28 | #[rustc_specialization_trait] | ||
29 | pub trait Sized {} | ||
30 | // endregion:sized | ||
31 | |||
32 | // region:unsize | ||
33 | #[lang = "unsize"] | ||
34 | pub trait Unsize<T: ?Sized> {} | ||
35 | // endregion:unsize | ||
36 | } | ||
37 | |||
38 | pub mod ops { | ||
39 | // region:coerce_unsized | ||
40 | mod unsize { | ||
41 | use crate::marker::Unsize; | ||
42 | |||
43 | #[lang = "coerce_unsized"] | ||
44 | pub trait CoerceUnsized<T: ?Sized> {} | ||
45 | |||
46 | impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {} | ||
47 | impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {} | ||
48 | impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {} | ||
49 | impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {} | ||
50 | |||
51 | impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} | ||
52 | impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a T {} | ||
53 | |||
54 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} | ||
55 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *mut T {} | ||
56 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {} | ||
57 | } | ||
58 | pub use self::unsize::CoerceUnsized; | ||
59 | // endregion:coerce_unsized | ||
60 | |||
61 | // region:deref | ||
62 | mod deref { | ||
63 | #[lang = "deref"] | ||
64 | pub trait Deref { | ||
65 | #[lang = "deref_target"] | ||
66 | type Target: ?Sized; | ||
67 | fn deref(&self) -> &Self::Target; | ||
68 | } | ||
69 | // region:deref_mut | ||
70 | #[lang = "deref_mut"] | ||
71 | pub trait DerefMut: Deref { | ||
72 | fn deref_mut(&mut self) -> &mut Self::Target; | ||
73 | } | ||
74 | // endregion:deref_mut | ||
75 | } | ||
76 | pub use self::deref::Deref; | ||
77 | pub use self::deref::DerefMut; //:deref_mut | ||
78 | // endregion:deref | ||
79 | |||
80 | // region:range | ||
81 | mod range { | ||
82 | #[lang = "RangeFull"] | ||
83 | pub struct RangeFull; | ||
84 | |||
85 | #[lang = "Range"] | ||
86 | pub struct Range<Idx> { | ||
87 | pub start: Idx, | ||
88 | pub end: Idx, | ||
89 | } | ||
90 | |||
91 | #[lang = "RangeFrom"] | ||
92 | pub struct RangeFrom<Idx> { | ||
93 | pub start: Idx, | ||
94 | } | ||
95 | |||
96 | #[lang = "RangeTo"] | ||
97 | pub struct RangeTo<Idx> { | ||
98 | pub end: Idx, | ||
99 | } | ||
100 | |||
101 | #[lang = "RangeInclusive"] | ||
102 | pub struct RangeInclusive<Idx> { | ||
103 | pub(crate) start: Idx, | ||
104 | pub(crate) end: Idx, | ||
105 | pub(crate) exhausted: bool, | ||
106 | } | ||
107 | |||
108 | #[lang = "RangeToInclusive"] | ||
109 | pub struct RangeToInclusive<Idx> { | ||
110 | pub end: Idx, | ||
111 | } | ||
112 | } | ||
113 | pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; | ||
114 | pub use self::range::{RangeInclusive, RangeToInclusive}; | ||
115 | // endregion:range | ||
116 | |||
117 | // region:fn | ||
118 | mod function { | ||
119 | #[lang = "fn"] | ||
120 | #[fundamental] | ||
121 | pub trait Fn<Args>: FnMut<Args> {} | ||
122 | |||
123 | #[lang = "fn_mut"] | ||
124 | #[fundamental] | ||
125 | pub trait FnMut<Args>: FnOnce<Args> {} | ||
126 | |||
127 | #[lang = "fn_once"] | ||
128 | #[fundamental] | ||
129 | pub trait FnOnce<Args> { | ||
130 | #[lang = "fn_once_output"] | ||
131 | type Output; | ||
132 | } | ||
133 | } | ||
134 | pub use self::function::{Fn, FnMut, FnOnce}; | ||
135 | // endregion:fn | ||
136 | } | ||
137 | |||
138 | // region:slice | ||
139 | pub mod slice { | ||
140 | #[lang = "slice"] | ||
141 | impl<T> [T] { | ||
142 | pub fn len(&self) -> usize { | ||
143 | loop {} | ||
144 | } | ||
145 | } | ||
146 | } | ||
147 | // endregion:slice | ||
148 | |||
149 | // region:option | ||
150 | pub mod option { | ||
151 | pub enum Option<T> { | ||
152 | #[lang = "None"] | ||
153 | None, | ||
154 | #[lang = "Some"] | ||
155 | Some(T), | ||
156 | } | ||
157 | } | ||
158 | // endregion:option | ||
159 | |||
160 | // region:result | ||
161 | pub mod result { | ||
162 | pub enum Result<T, E> { | ||
163 | #[lang = "Ok"] | ||
164 | Ok(T), | ||
165 | #[lang = "Err"] | ||
166 | Err(E), | ||
167 | } | ||
168 | } | ||
169 | // endregion:result | ||
170 | |||
171 | // region:pin | ||
172 | pub mod pin { | ||
173 | #[lang = "pin"] | ||
174 | #[fundamental] | ||
175 | pub struct Pin<P> { | ||
176 | pointer: P, | ||
177 | } | ||
178 | } | ||
179 | // endregion:pin | ||
180 | |||
181 | // region:future | ||
182 | pub mod future { | ||
183 | use crate::{ | ||
184 | pin::Pin, | ||
185 | task::{Context, Poll}, | ||
186 | }; | ||
187 | |||
188 | #[lang = "future_trait"] | ||
189 | pub trait Future { | ||
190 | type Output; | ||
191 | #[lang = "poll"] | ||
192 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>; | ||
193 | } | ||
194 | } | ||
195 | pub mod task { | ||
196 | pub enum Poll<T> { | ||
197 | #[lang = "Ready"] | ||
198 | Ready(T), | ||
199 | #[lang = "Pending"] | ||
200 | Pending, | ||
201 | } | ||
202 | |||
203 | pub struct Context<'a> { | ||
204 | waker: &'a (), | ||
205 | } | ||
206 | } | ||
207 | // endregion:future | ||
208 | |||
209 | pub mod prelude { | ||
210 | pub mod v1 { | ||
211 | pub use crate::{ | ||
212 | marker::Sized, // :sized | ||
213 | ops::{Fn, FnMut, FnOnce}, // :fn | ||
214 | option::Option::{self, None, Some}, // :option | ||
215 | result::Result::{self, Err, Ok}, // :result | ||
216 | }; | ||
217 | } | ||
218 | |||
219 | pub mod rust_2015 { | ||
220 | pub use super::v1::*; | ||
221 | } | ||
222 | |||
223 | pub mod rust_2018 { | ||
224 | pub use super::v1::*; | ||
225 | } | ||
226 | |||
227 | pub mod rust_2021 { | ||
228 | pub use super::v1::*; | ||
229 | } | ||
230 | } | ||
231 | |||
232 | #[prelude_import] | ||
233 | #[allow(unused)] | ||
234 | use prelude::v1::*; | ||