diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-01-14 09:07:15 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2021-01-14 09:07:15 +0000 |
commit | 39167b97d8a62adadecc9b67caac65ec556768cf (patch) | |
tree | f3a1c700b36ddc26bb9d189de3d03c84a93e9251 /crates | |
parent | 6835f2e37c8331ef54d4839a31df195d7dbbeee8 (diff) | |
parent | 3d6480bc3103f7238b1b0e020518e8aa72af3156 (diff) |
Merge #7260
7260: Render Fn* trait objects and impl types as rust does r=matklad a=Veykril
Also fixes raw ptr impl types being rendered ambiguously with multiple predicates.
This moves out the `FamousDefs::Fixture` into its own file as well, cause I figured it is big enough to get its own file at this point + we also get highlighting this way when editing it.
Fixes #3012
Co-authored-by: Lukas Wirth <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir_ty/src/display.rs | 100 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/display_source_code.rs | 15 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/traits.rs | 8 | ||||
-rw-r--r-- | crates/ide/src/inlay_hints.rs | 37 | ||||
-rw-r--r-- | crates/ide_db/src/helpers.rs | 89 | ||||
-rw-r--r-- | crates/ide_db/src/helpers/famous_defs_fixture.rs | 120 |
6 files changed, 252 insertions, 117 deletions
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index e9e949c47..d2f1b4014 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -1,14 +1,15 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use std::fmt; | 3 | use std::{borrow::Cow, fmt}; |
4 | 4 | ||
5 | use crate::{ | 5 | use crate::{ |
6 | db::HirDatabase, utils::generics, ApplicationTy, CallableDefId, FnSig, GenericPredicate, | 6 | db::HirDatabase, utils::generics, ApplicationTy, CallableDefId, FnSig, GenericPredicate, |
7 | Lifetime, Obligation, OpaqueTyId, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | 7 | Lifetime, Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, |
8 | }; | 8 | }; |
9 | use arrayvec::ArrayVec; | ||
9 | use hir_def::{ | 10 | use hir_def::{ |
10 | find_path, generics::TypeParamProvenance, item_scope::ItemInNs, AdtId, AssocContainerId, | 11 | db::DefDatabase, find_path, generics::TypeParamProvenance, item_scope::ItemInNs, AdtId, |
11 | Lookup, ModuleId, | 12 | AssocContainerId, HasModule, Lookup, ModuleId, TraitId, |
12 | }; | 13 | }; |
13 | use hir_expand::name::Name; | 14 | use hir_expand::name::Name; |
14 | 15 | ||
@@ -257,25 +258,45 @@ impl HirDisplay for ApplicationTy { | |||
257 | t.hir_fmt(f)?; | 258 | t.hir_fmt(f)?; |
258 | write!(f, "; _]")?; | 259 | write!(f, "; _]")?; |
259 | } | 260 | } |
260 | TypeCtor::RawPtr(m) => { | 261 | TypeCtor::RawPtr(m) | TypeCtor::Ref(m) => { |
261 | let t = self.parameters.as_single(); | 262 | let t = self.parameters.as_single(); |
263 | let ty_display = | ||
264 | t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); | ||
262 | 265 | ||
263 | write!(f, "*{}", m.as_keyword_for_ptr())?; | 266 | if matches!(self.ctor, TypeCtor::RawPtr(_)) { |
264 | if matches!(t, Ty::Dyn(predicates) if predicates.len() > 1) { | 267 | write!(f, "*{}", m.as_keyword_for_ptr())?; |
265 | write!(f, "(")?; | ||
266 | t.hir_fmt(f)?; | ||
267 | write!(f, ")")?; | ||
268 | } else { | 268 | } else { |
269 | t.hir_fmt(f)?; | 269 | write!(f, "&{}", m.as_keyword_for_ref())?; |
270 | } | ||
271 | |||
272 | let datas; | ||
273 | let predicates = match t { | ||
274 | Ty::Dyn(predicates) if predicates.len() > 1 => { | ||
275 | Cow::Borrowed(predicates.as_ref()) | ||
276 | } | ||
277 | &Ty::Opaque(OpaqueTy { | ||
278 | opaque_ty_id: OpaqueTyId::ReturnTypeImplTrait(func, idx), | ||
279 | ref parameters, | ||
280 | }) => { | ||
281 | datas = | ||
282 | f.db.return_type_impl_traits(func).expect("impl trait id without data"); | ||
283 | let data = (*datas) | ||
284 | .as_ref() | ||
285 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); | ||
286 | let bounds = data.subst(parameters); | ||
287 | Cow::Owned(bounds.value) | ||
288 | } | ||
289 | _ => Cow::Borrowed(&[][..]), | ||
290 | }; | ||
291 | |||
292 | if let [GenericPredicate::Implemented(trait_ref), _] = predicates.as_ref() { | ||
293 | let trait_ = trait_ref.trait_; | ||
294 | if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_) { | ||
295 | return write!(f, "{}", ty_display); | ||
296 | } | ||
270 | } | 297 | } |
271 | } | ||
272 | TypeCtor::Ref(m) => { | ||
273 | let t = self.parameters.as_single(); | ||
274 | let ty_display = | ||
275 | t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); | ||
276 | 298 | ||
277 | write!(f, "&{}", m.as_keyword_for_ref())?; | 299 | if predicates.len() > 1 { |
278 | if matches!(t, Ty::Dyn(predicates) if predicates.len() > 1) { | ||
279 | write!(f, "(")?; | 300 | write!(f, "(")?; |
280 | write!(f, "{}", ty_display)?; | 301 | write!(f, "{}", ty_display)?; |
281 | write!(f, ")")?; | 302 | write!(f, ")")?; |
@@ -595,6 +616,17 @@ impl HirDisplay for FnSig { | |||
595 | } | 616 | } |
596 | } | 617 | } |
597 | 618 | ||
619 | fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = TraitId> { | ||
620 | let krate = trait_.lookup(db).container.module(db).krate; | ||
621 | let fn_traits = [ | ||
622 | db.lang_item(krate, "fn".into()), | ||
623 | db.lang_item(krate, "fn_mut".into()), | ||
624 | db.lang_item(krate, "fn_once".into()), | ||
625 | ]; | ||
626 | // FIXME: Replace ArrayVec when into_iter is a thing on arrays | ||
627 | ArrayVec::from(fn_traits).into_iter().flatten().flat_map(|it| it.as_trait()) | ||
628 | } | ||
629 | |||
598 | pub fn write_bounds_like_dyn_trait( | 630 | pub fn write_bounds_like_dyn_trait( |
599 | predicates: &[GenericPredicate], | 631 | predicates: &[GenericPredicate], |
600 | f: &mut HirFormatter, | 632 | f: &mut HirFormatter, |
@@ -607,10 +639,15 @@ pub fn write_bounds_like_dyn_trait( | |||
607 | // predicate for that trait). | 639 | // predicate for that trait). |
608 | let mut first = true; | 640 | let mut first = true; |
609 | let mut angle_open = false; | 641 | let mut angle_open = false; |
642 | let mut is_fn_trait = false; | ||
610 | for p in predicates.iter() { | 643 | for p in predicates.iter() { |
611 | match p { | 644 | match p { |
612 | GenericPredicate::Implemented(trait_ref) => { | 645 | GenericPredicate::Implemented(trait_ref) => { |
613 | if angle_open { | 646 | let trait_ = trait_ref.trait_; |
647 | if !is_fn_trait { | ||
648 | is_fn_trait = fn_traits(f.db.upcast(), trait_).any(|it| it == trait_); | ||
649 | } | ||
650 | if !is_fn_trait && angle_open { | ||
614 | write!(f, ">")?; | 651 | write!(f, ">")?; |
615 | angle_open = false; | 652 | angle_open = false; |
616 | } | 653 | } |
@@ -620,14 +657,27 @@ pub fn write_bounds_like_dyn_trait( | |||
620 | // We assume that the self type is $0 (i.e. the | 657 | // We assume that the self type is $0 (i.e. the |
621 | // existential) here, which is the only thing that's | 658 | // existential) here, which is the only thing that's |
622 | // possible in actual Rust, and hence don't print it | 659 | // possible in actual Rust, and hence don't print it |
623 | write!(f, "{}", f.db.trait_data(trait_ref.trait_).name)?; | 660 | write!(f, "{}", f.db.trait_data(trait_).name)?; |
624 | if trait_ref.substs.len() > 1 { | 661 | if let [_, params @ ..] = &*trait_ref.substs.0 { |
625 | write!(f, "<")?; | 662 | if is_fn_trait { |
626 | f.write_joined(&trait_ref.substs[1..], ", ")?; | 663 | if let Some(args) = params.first().and_then(|it| it.as_tuple()) { |
627 | // there might be assoc type bindings, so we leave the angle brackets open | 664 | write!(f, "(")?; |
628 | angle_open = true; | 665 | f.write_joined(&*args.0, ", ")?; |
666 | write!(f, ")")?; | ||
667 | } | ||
668 | } else if !params.is_empty() { | ||
669 | write!(f, "<")?; | ||
670 | f.write_joined(params, ", ")?; | ||
671 | // there might be assoc type bindings, so we leave the angle brackets open | ||
672 | angle_open = true; | ||
673 | } | ||
629 | } | 674 | } |
630 | } | 675 | } |
676 | GenericPredicate::Projection(projection_pred) if is_fn_trait => { | ||
677 | is_fn_trait = false; | ||
678 | write!(f, " -> ")?; | ||
679 | projection_pred.ty.hir_fmt(f)?; | ||
680 | } | ||
631 | GenericPredicate::Projection(projection_pred) => { | 681 | GenericPredicate::Projection(projection_pred) => { |
632 | // in types in actual Rust, these will always come | 682 | // in types in actual Rust, these will always come |
633 | // after the corresponding Implemented predicate | 683 | // after the corresponding Implemented predicate |
diff --git a/crates/hir_ty/src/tests/display_source_code.rs b/crates/hir_ty/src/tests/display_source_code.rs index b502135d8..3d29021aa 100644 --- a/crates/hir_ty/src/tests/display_source_code.rs +++ b/crates/hir_ty/src/tests/display_source_code.rs | |||
@@ -39,3 +39,18 @@ fn main() { | |||
39 | "#, | 39 | "#, |
40 | ); | 40 | ); |
41 | } | 41 | } |
42 | |||
43 | #[test] | ||
44 | fn render_raw_ptr_impl_ty() { | ||
45 | check_types_source_code( | ||
46 | r#" | ||
47 | trait Sized {} | ||
48 | trait Unpin {} | ||
49 | fn foo() -> *const (impl Unpin + Sized) { loop {} } | ||
50 | fn main() { | ||
51 | let foo = foo(); | ||
52 | foo; | ||
53 | } //^ *const (impl Unpin + Sized) | ||
54 | "#, | ||
55 | ); | ||
56 | } | ||
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index 41d097519..e5a3f95a6 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs | |||
@@ -3038,16 +3038,16 @@ fn infer_box_fn_arg() { | |||
3038 | 406..417 '&self.inner': &*mut T | 3038 | 406..417 '&self.inner': &*mut T |
3039 | 407..411 'self': &Box<T> | 3039 | 407..411 'self': &Box<T> |
3040 | 407..417 'self.inner': *mut T | 3040 | 407..417 'self.inner': *mut T |
3041 | 478..575 '{ ...(&s) }': FnOnce::Output<dyn FnOnce<(&Option<i32>,)>, (&Option<i32>,)> | 3041 | 478..575 '{ ...(&s) }': FnOnce::Output<dyn FnOnce(&Option<i32>), (&Option<i32>,)> |
3042 | 488..489 's': Option<i32> | 3042 | 488..489 's': Option<i32> |
3043 | 492..504 'Option::None': Option<i32> | 3043 | 492..504 'Option::None': Option<i32> |
3044 | 514..515 'f': Box<dyn FnOnce<(&Option<i32>,)>> | 3044 | 514..515 'f': Box<dyn FnOnce(&Option<i32>)> |
3045 | 549..562 'box (|ps| {})': Box<|{unknown}| -> ()> | 3045 | 549..562 'box (|ps| {})': Box<|{unknown}| -> ()> |
3046 | 554..561 '|ps| {}': |{unknown}| -> () | 3046 | 554..561 '|ps| {}': |{unknown}| -> () |
3047 | 555..557 'ps': {unknown} | 3047 | 555..557 'ps': {unknown} |
3048 | 559..561 '{}': () | 3048 | 559..561 '{}': () |
3049 | 568..569 'f': Box<dyn FnOnce<(&Option<i32>,)>> | 3049 | 568..569 'f': Box<dyn FnOnce(&Option<i32>)> |
3050 | 568..573 'f(&s)': FnOnce::Output<dyn FnOnce<(&Option<i32>,)>, (&Option<i32>,)> | 3050 | 568..573 'f(&s)': FnOnce::Output<dyn FnOnce(&Option<i32>), (&Option<i32>,)> |
3051 | 570..572 '&s': &Option<i32> | 3051 | 570..572 '&s': &Option<i32> |
3052 | 571..572 's': Option<i32> | 3052 | 571..572 's': Option<i32> |
3053 | "#]], | 3053 | "#]], |
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index 3e9a65d9c..a2039fcc7 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs | |||
@@ -1401,4 +1401,41 @@ fn main() { | |||
1401 | "#, | 1401 | "#, |
1402 | ) | 1402 | ) |
1403 | } | 1403 | } |
1404 | |||
1405 | #[test] | ||
1406 | fn fn_hints() { | ||
1407 | check( | ||
1408 | r#" | ||
1409 | trait Sized {} | ||
1410 | |||
1411 | fn foo() -> impl Fn() { loop {} } | ||
1412 | fn foo1() -> impl Fn(f64) { loop {} } | ||
1413 | fn foo2() -> impl Fn(f64, f64) { loop {} } | ||
1414 | fn foo3() -> impl Fn(f64, f64) -> u32 { loop {} } | ||
1415 | fn foo4() -> &'static dyn Fn(f64, f64) -> u32 { loop {} } | ||
1416 | fn foo5() -> &'static dyn Fn(&'static dyn Fn(f64, f64) -> u32, f64) -> u32 { loop {} } | ||
1417 | fn foo6() -> impl Fn(f64, f64) -> u32 + Sized { loop {} } | ||
1418 | fn foo7() -> *const (impl Fn(f64, f64) -> u32 + Sized) { loop {} } | ||
1419 | |||
1420 | fn main() { | ||
1421 | let foo = foo(); | ||
1422 | // ^^^ impl Fn() | ||
1423 | let foo = foo1(); | ||
1424 | // ^^^ impl Fn(f64) | ||
1425 | let foo = foo2(); | ||
1426 | // ^^^ impl Fn(f64, f64) | ||
1427 | let foo = foo3(); | ||
1428 | // ^^^ impl Fn(f64, f64) -> u32 | ||
1429 | let foo = foo4(); | ||
1430 | // ^^^ &dyn Fn(f64, f64) -> u32 | ||
1431 | let foo = foo5(); | ||
1432 | // ^^^ &dyn Fn(&dyn Fn(f64, f64) -> u32, f64) -> u32 | ||
1433 | let foo = foo6(); | ||
1434 | // ^^^ impl Fn(f64, f64) -> u32 + Sized | ||
1435 | let foo = foo7(); | ||
1436 | // ^^^ *const (impl Fn(f64, f64) -> u32 + Sized) | ||
1437 | } | ||
1438 | "#, | ||
1439 | ) | ||
1440 | } | ||
1404 | } | 1441 | } |
diff --git a/crates/ide_db/src/helpers.rs b/crates/ide_db/src/helpers.rs index e3e5670f1..c6763ae36 100644 --- a/crates/ide_db/src/helpers.rs +++ b/crates/ide_db/src/helpers.rs | |||
@@ -38,94 +38,7 @@ pub struct FamousDefs<'a, 'b>(pub &'a Semantics<'b, RootDatabase>, pub Option<Cr | |||
38 | 38 | ||
39 | #[allow(non_snake_case)] | 39 | #[allow(non_snake_case)] |
40 | impl FamousDefs<'_, '_> { | 40 | impl FamousDefs<'_, '_> { |
41 | pub const FIXTURE: &'static str = r#"//- /libcore.rs crate:core | 41 | pub const FIXTURE: &'static str = include_str!("helpers/famous_defs_fixture.rs"); |
42 | pub mod convert { | ||
43 | pub trait From<T> { | ||
44 | fn from(t: T) -> Self; | ||
45 | } | ||
46 | } | ||
47 | |||
48 | pub mod default { | ||
49 | pub trait Default { | ||
50 | fn default() -> Self; | ||
51 | } | ||
52 | } | ||
53 | |||
54 | pub mod iter { | ||
55 | pub use self::traits::{collect::IntoIterator, iterator::Iterator}; | ||
56 | mod traits { | ||
57 | pub(crate) mod iterator { | ||
58 | use crate::option::Option; | ||
59 | pub trait Iterator { | ||
60 | type Item; | ||
61 | fn next(&mut self) -> Option<Self::Item>; | ||
62 | fn by_ref(&mut self) -> &mut Self { | ||
63 | self | ||
64 | } | ||
65 | fn take(self, n: usize) -> crate::iter::Take<Self> { | ||
66 | crate::iter::Take { inner: self } | ||
67 | } | ||
68 | } | ||
69 | |||
70 | impl<I: Iterator> Iterator for &mut I { | ||
71 | type Item = I::Item; | ||
72 | fn next(&mut self) -> Option<I::Item> { | ||
73 | (**self).next() | ||
74 | } | ||
75 | } | ||
76 | } | ||
77 | pub(crate) mod collect { | ||
78 | pub trait IntoIterator { | ||
79 | type Item; | ||
80 | } | ||
81 | } | ||
82 | } | ||
83 | |||
84 | pub use self::sources::*; | ||
85 | pub(crate) mod sources { | ||
86 | use super::Iterator; | ||
87 | use crate::option::Option::{self, *}; | ||
88 | pub struct Repeat<A> { | ||
89 | element: A, | ||
90 | } | ||
91 | |||
92 | pub fn repeat<T>(elt: T) -> Repeat<T> { | ||
93 | Repeat { element: elt } | ||
94 | } | ||
95 | |||
96 | impl<A> Iterator for Repeat<A> { | ||
97 | type Item = A; | ||
98 | |||
99 | fn next(&mut self) -> Option<A> { | ||
100 | None | ||
101 | } | ||
102 | } | ||
103 | } | ||
104 | |||
105 | pub use self::adapters::*; | ||
106 | pub(crate) mod adapters { | ||
107 | use super::Iterator; | ||
108 | use crate::option::Option::{self, *}; | ||
109 | pub struct Take<I> { pub(crate) inner: I } | ||
110 | impl<I> Iterator for Take<I> where I: Iterator { | ||
111 | type Item = <I as Iterator>::Item; | ||
112 | fn next(&mut self) -> Option<<I as Iterator>::Item> { | ||
113 | None | ||
114 | } | ||
115 | } | ||
116 | } | ||
117 | } | ||
118 | |||
119 | pub mod option { | ||
120 | pub enum Option<T> { None, Some(T)} | ||
121 | } | ||
122 | |||
123 | pub mod prelude { | ||
124 | pub use crate::{convert::From, iter::{IntoIterator, Iterator}, option::Option::{self, *}, default::Default}; | ||
125 | } | ||
126 | #[prelude_import] | ||
127 | pub use prelude::*; | ||
128 | "#; | ||
129 | 42 | ||
130 | pub fn core(&self) -> Option<Crate> { | 43 | pub fn core(&self) -> Option<Crate> { |
131 | self.find_crate("core") | 44 | self.find_crate("core") |
diff --git a/crates/ide_db/src/helpers/famous_defs_fixture.rs b/crates/ide_db/src/helpers/famous_defs_fixture.rs new file mode 100644 index 000000000..5e88de64d --- /dev/null +++ b/crates/ide_db/src/helpers/famous_defs_fixture.rs | |||
@@ -0,0 +1,120 @@ | |||
1 | //- /libcore.rs crate:core | ||
2 | //! Signatures of traits, types and functions from the core lib for use in tests. | ||
3 | pub mod convert { | ||
4 | pub trait From<T> { | ||
5 | fn from(t: T) -> Self; | ||
6 | } | ||
7 | } | ||
8 | |||
9 | pub mod default { | ||
10 | pub trait Default { | ||
11 | fn default() -> Self; | ||
12 | } | ||
13 | } | ||
14 | |||
15 | pub mod iter { | ||
16 | pub use self::traits::{collect::IntoIterator, iterator::Iterator}; | ||
17 | mod traits { | ||
18 | pub(crate) mod iterator { | ||
19 | use crate::option::Option; | ||
20 | pub trait Iterator { | ||
21 | type Item; | ||
22 | fn next(&mut self) -> Option<Self::Item>; | ||
23 | fn by_ref(&mut self) -> &mut Self { | ||
24 | self | ||
25 | } | ||
26 | fn take(self, n: usize) -> crate::iter::Take<Self> { | ||
27 | crate::iter::Take { inner: self } | ||
28 | } | ||
29 | } | ||
30 | |||
31 | impl<I: Iterator> Iterator for &mut I { | ||
32 | type Item = I::Item; | ||
33 | fn next(&mut self) -> Option<I::Item> { | ||
34 | (**self).next() | ||
35 | } | ||
36 | } | ||
37 | } | ||
38 | pub(crate) mod collect { | ||
39 | pub trait IntoIterator { | ||
40 | type Item; | ||
41 | } | ||
42 | } | ||
43 | } | ||
44 | |||
45 | pub use self::sources::*; | ||
46 | pub(crate) mod sources { | ||
47 | use super::Iterator; | ||
48 | use crate::option::Option::{self, *}; | ||
49 | pub struct Repeat<A> { | ||
50 | element: A, | ||
51 | } | ||
52 | |||
53 | pub fn repeat<T>(elt: T) -> Repeat<T> { | ||
54 | Repeat { element: elt } | ||
55 | } | ||
56 | |||
57 | impl<A> Iterator for Repeat<A> { | ||
58 | type Item = A; | ||
59 | |||
60 | fn next(&mut self) -> Option<A> { | ||
61 | None | ||
62 | } | ||
63 | } | ||
64 | } | ||
65 | |||
66 | pub use self::adapters::*; | ||
67 | pub(crate) mod adapters { | ||
68 | use super::Iterator; | ||
69 | use crate::option::Option::{self, *}; | ||
70 | pub struct Take<I> { | ||
71 | pub(crate) inner: I, | ||
72 | } | ||
73 | impl<I> Iterator for Take<I> | ||
74 | where | ||
75 | I: Iterator, | ||
76 | { | ||
77 | type Item = <I as Iterator>::Item; | ||
78 | fn next(&mut self) -> Option<<I as Iterator>::Item> { | ||
79 | None | ||
80 | } | ||
81 | } | ||
82 | } | ||
83 | } | ||
84 | |||
85 | pub mod ops { | ||
86 | #[lang = "fn"] | ||
87 | pub trait Fn<Args>: FnMut<Args> { | ||
88 | extern "rust-call" fn call(&self, args: Args) -> Self::Output; | ||
89 | } | ||
90 | |||
91 | #[lang = "fn_mut"] | ||
92 | pub trait FnMut<Args>: FnOnce<Args> { | ||
93 | extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; | ||
94 | } | ||
95 | #[lang = "fn_once"] | ||
96 | pub trait FnOnce<Args> { | ||
97 | #[lang = "fn_once_output"] | ||
98 | type Output; | ||
99 | extern "rust-call" fn call_once(self, args: Args) -> Self::Output; | ||
100 | } | ||
101 | } | ||
102 | |||
103 | pub mod option { | ||
104 | pub enum Option<T> { | ||
105 | None, | ||
106 | Some(T), | ||
107 | } | ||
108 | } | ||
109 | |||
110 | pub mod prelude { | ||
111 | pub use crate::{ | ||
112 | convert::From, | ||
113 | default::Default, | ||
114 | iter::{IntoIterator, Iterator}, | ||
115 | ops::{Fn, FnMut, FnOnce}, | ||
116 | option::Option::{self, *}, | ||
117 | }; | ||
118 | } | ||
119 | #[prelude_import] | ||
120 | pub use prelude::*; | ||