当前位置:网站首页>[rust submission] review impl trail and dyn trail in rust
[rust submission] review impl trail and dyn trail in rust
2022-06-25 03:52:00 【51CTO】
PrivateRookie -- author
origin
Everything must be changed from the end of the year to the special period , I read a few poems at home , I suddenly want to write a poem that can be browsed and recited TUI Procedure starts . I chose Cursive This Rust TUI library . There is such a function in the implementation , It will return a component according to different parameters ( Such as Button, TextView etc. ). stay Cursive in , Each component implements View This trait, Initially, this function will only return a certain component , So the function signature can be written like this
As development progresses , This function needs to return Button, TextView One of the components such as , I subconsciously wrote something like this
unfortunately Rust The compiler always smacks in the face , Rust The compiler reports an error as follows
--> src\main.rs:19:16
|
13 | fn some_fn(param1: i32, param2: i32) -> impl View {
| --------- expected because this return type...
...
16 | return Button {};
| --------- ...is found to be `Button` here
...
19 | return TextView {};
| ^^^^^^^^^^^ expected struct `Button`, found struct `TextView`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
From the compiler error information, we can see that the return value of the function is impl View But it comes from if The branch inference return value type is Button No longer accept else Branch returns TextView. This is related to Rust requirement if else The return value types of the two branches are the same . Can you make the function return multiple types ? Rust The reason why a function cannot return multiple types is because Rust In need in The compile time determines the memory size occupied by the return value , Obviously, different types of return values have different memory sizes . In that case , Pack the return value , Returns a fat pointer , In this way, the size of our return value can be determined , Maybe it will be OK . Try changing the function to the following form :
Now the code has been compiled , But if Rust 2018, You will find that the compiler will throw a warning :
The compiler tells us to use trait object Do not use dyn The form of has been abandoned , And it also reminds us to put Box<View> Change to Box<dyn View>, Follow the compiler's prompts to modify the code , Now the code no warning, no error, perfect .
but impl Trait and Box<dyn Trait> Is there any difference except that multiple return value types are allowed ? trait object What is it again? ? Why? Box<Trait> The return value of form will be discarded and new dyn Key words? ?
Buried pit
impl Trait and dyn Trait stay Rust They are called static distribution and dynamic distribution respectively . In the first edition of Rust Book Explain distribution in this way (dispatch)
When code involves polymorphism, there needs to be a mechanism to determine which specific version is actually run. This is called ‘dispatch’. There are two major forms of dispatch: static dispatch and dynamic dispatch. While Rust favors static dispatch, it also supports dynamic dispatch through a mechanism called ‘trait objects’.
That is, when the code involves polymorphism , Some mechanism is needed to determine the actual call type . Rust Of Trait It can be seen as some collection with pass through feature types , Take the above code for example , When we write code, we don't care about specific types , However, it must be determined at compile time or run time Button still TextView. Static distribution , Just like static typed languages " static state " The word , The specific call type is determined at compile time . Rust The compiler will use singleton (Monomorphization) Expand generic functions .
hypothesis Foo and Bar It's all done Noop characteristic , Rust Will function
Begin to
( For principle explanation only , There is no guarantee that the compilation will expand the function name in this way ).
By monometalization , The compiler eliminates generics , And no performance loss , This is also Rust The form advocated , The disadvantage is that too many expansions may cause the volume of the secondary system file generated by compilation to be too large , You may need to refactor the code .
Static distribution has high performance , But at the beginning of the article, another shortcoming is also reflected , That is, functions cannot return multiple types , therefore Rust Also support passing trait object Realize dynamic distribution . since Trait Is a collection of types with certain characteristics , Then we can put Trait Also as a certain type , But it is " In the abstract ", It's like OOP Abstract class or base class in , Cannot instantiate directly .
Rust Of trait object Used with c++ Allied vtable Realization , trait object contain 1 Points to the actual type data The pointer , And an implementation that points to the actual type trait Functional vtable, This enables dynamic distribution . A more detailed introduction can be found in
Exploring Dynamic Dispatch in Rustalschwalm.com
notice . since trait object The size can be determined during implementation , Then why not fn x() -> Trait In the form of ? although trait object The size can be determined in the implementation , But logically , because Trait Represents a collection of types , Its size cannot be determined . allow fn x() -> Trait It will lead to semantic disharmony . that fn x() -> &Trait Well ? Certainly. ! However, in this scenario, all references are created in the function and then return the value , Obviously, the life cycle needs to be added :
I don't like to add additional lifecycle descriptions , You must be the same . So we can use the Box Smart pointers avoid annoying life cycle descriptions . thus Box<Trait> At last . So here comes the question , Why does the compiler prompt Box<Trait> Will be abandoned , Specially introduced dyn Key words? ? The answer can be in RFC-2113 Find .
RFC-2113 The introduction of dyn Why , That is, semantic fuzziness , It's confusing , The reason is that there is no dyn Give Way Trait and trait objects It looks exactly the same , RFC List 3 An example shows .
First example , Add the code you see below , Do you know what the author wants to do ?
Do you understand ? To tell the truth, I can't understand : ) PASS
Second example , impl MyTrait {} Is the correct grammar , But it makes people think that this will be in Trait Add default implementation on , Extension method or other Trait Some of their own operations . In fact, this is trait object Add method on .
As explained in the following code , Trait The correct way to define the default implementation is to define Trait When you specify , Instead of impl Trait {} In the block .
Bar In the realization of Foo You can go through b.default_impl call , No additional implementation is required , but b.trait_object No way. , because trait_object The method is Foo Of trait object The method on the .
If it is Rust 2018 The compiler should also display a warning , Tell us that we should use impl dyn Foo {}
The third example is based on function type and function trait Contrast , The only difference between the two is whether the initial letter is capitalized (Fn Representative function trait object, fn Is the function type ), It is inevitable to confuse the two .
More detailed instructions can be moved
RFC-2113github.com
.
summary
impl trait and dyn trait The difference is that static distribution is different from dynamic distribution , Static distribution performance good , However, extensive use may cause binary file expansion ; Dynamic distribution to trait object The concept of is realized through virtual tables , There will be some runtime overhead . Because of trait object And Trait Without introducing dyn It often leads to semantic confusion , therefore Rust Specially introduce dyn keyword , stay Rust 2018 Has been stabilized in .
quote
The following are the references for this article
impl Trait for returning complex types with easedoc.rust-lang.org
impl trait Community Tracking github.com
rust-lang/rfcsgithub.com
Traits and Trait Objects in Rustjoshleeb.comDynamic vs. Static Dispatchlukasatkinson.deExploring Dynamic Dispatch in Rustalschwalm.com
PS: The picture above shows Lupu Bridge , My favorite bridge in Shanghai , Not one of them. ~
边栏推荐
- AI越进化越跟人类大脑像!Meta找到了机器的“前额叶皮层”,AI学者和神经科学家都惊了...
- When people look at the industrial Internet from the Internet like thinking and perspective, they have actually fallen into a dead end
- Is it safe to open an account online? Online and other answers
- 服乔布斯不服库克,苹果传奇设计团队解散内幕曝光
- Two common OEE monitoring methods for equipment utilization
- How to play well in the PMP Exam?
- Solution to the problem that Linux crontab timed operation Oracle does not execute (crontab environment variable problem)
- How to choose a securities company when opening an account with a compass? Which is safer
- Sun Wu plays Warcraft? There is a picture and a truth
- 签到功能完成03《ivx低代码签到系统制作》
猜你喜欢

协作+安全+存储,云盒子助力深圳爱德泰重构数据中心

About sizeof() and strlen in array

Redis related-03

Sleep more, you can lose weight. According to the latest research from the University of Chicago, sleeping more than 1 hour a day is equivalent to eating less than one fried chicken leg

AI越进化越跟人类大脑像!Meta找到了机器的“前额叶皮层”,AI学者和神经科学家都惊了...

腾讯开源项目「应龙」成Apache顶级项目:前身长期服务微信支付,能hold住百万亿级数据流处理...

北大换新校长!中国科学院院士龚旗煌接任,15岁考上北大物理系

后台页制作01《ivx低代码签到系统制作》

The era of copilot free is over! The official version is 67 yuan / month, and the student party and the defenders of popular open source projects can prostitute for nothing

Google founder brin's second marriage broke up: it was revealed that he had filed for divorce from his Chinese wife in January, and his current fortune is $631.4 billion
随机推荐
Perfect shuffle problem
马斯克被诉传销索赔2580亿美元,台积电公布2nm制程,中科院发现月壤中含有羟基形式的水,今日更多大新闻在此...
俄罗斯AIRI研究院等 | SEMA:利用深度迁移学习进行抗原B细胞构象表征预测
Disassembly of Weima prospectus: the electric competition has ended and the intelligent qualifying has just begun
Create SQLite table with shell script and add SQL statement -- General
多睡觉,能减肥,芝加哥大学最新研究:每天多睡1小时,等于少吃一根炸鸡腿...
Sorting of poor cattle (winter vacation daily question 40)
在线股票开户安全吗?
用指南针开户如何选择证券公司?哪一个是更安全的
2点睡10点起不算熬夜?除非你每天都能执行
China's SkyEye found suspicious signals of extraterrestrial civilization. Musk said that the Starship began its orbital test flight in July. Netinfo office: app should not force users to agree to proc
用CPU方案打破内存墙?学PayPal堆傲腾扩容量,漏查欺诈交易量可降至1/30
Mobile mall project operation
Preparedstatement principle of preventing SQL injection
签到功能完成03《ivx低代码签到系统制作》
Void* pointer
香蕉为什么能做随机数生成器?因为,它是水果界的“辐射之王”
Configuration source code
redis
跨境电商新手如何防止店铺关联?用什么工具好?