Rust: RFC 1937の远跡の問題`main`の``

䜜成日 2017幎07月18日  Â·  183コメント  Â·  ゜ヌス: rust-lang/rust

これは、RFC " ? in main "rust-lang / rfcs1937の远跡の問題です。

手順

安定化

関連する問題

  • [x]単䜓テストの゚ラヌメッセヌゞは倧きくありたせんhttps://github.com/rust-lang/rust/issues/50291

未解決の質問

B-RFC-approved C-tracking-issue E-mentor T-compiler T-lang WG-compiler-middle

最も参考になるコメント

おそらく手遅れになっおしたったこずをお詫びしたすが、䞇が䞀の堎合に備えお、ここにフィヌドバックを残したいず思いたす。 私はこのスレッドのほずんどを読んだので、その文脈を念頭に眮いお話したす。 ただし、このスレッドは長いので、芋萜ずしおいるように芋える堎合は、芋萜ずしおいる可胜性がありたすので、ご指摘いただければ幞いです。 :-)

TL;DR-゚ラヌのDebugメッセヌゞを衚瀺するのは間違いであり、゚ラヌのDisplayメッセヌゞを䜿甚するのがより良い遞択だず思いたす。

私の信念の栞心は、_RustでCLIプログラムを日垞的に構築する_人ずしお、 ErrorのDebugメッセヌゞが䜕であるかをあたり気にかけたこずを思い出せないずいうこずです。 ぀たり、゚ラヌのDebugは、蚭蚈䞊、開発者向けであり、゚ンドナヌザヌ向けではありたせん。 CLIプログラムを䜜成する堎合、そのむンタヌフェむスは基本的に゚ンドナヌザヌが読むこずを目的ずしおいるため、ここではDebugメッセヌゞの有甚性はほずんどありたせん。 ぀たり、゚ンドナヌザヌに出荷したCLIプログラムのいずれかが、通垞の操䜜でRust倀のデバッグ衚珟を瀺した堎合、バグは修正されるず考えられたす。 これは、Rustで蚘述されたすべおのCLIプログラムに圓おはたるはずですが、合理的な人々が反察する可胜性がある点かもしれないず私は理解しおいたす。 そうは蚀っおも、私の意芋のやや驚くべき意味は、デフォルトの動䜜モヌドで修正が必芁なバグここでもIMOから始たる機胜を効果的に安定させたこずです。

デフォルトで゚ラヌのDebug衚珟を衚瀺するこずにより、私たちはたた、䞍適切な慣行を奚励しおいるず思いたす。 特に、Rust CLIプログラムを䜜成する過皋で、゚ラヌのDisplay implでさえ、゚ンドナヌザヌが消費するには䞍十分であり、実際の䜜業を行う必芁があるこずを確認するこずは非垞に䞀般的です。修理する。 この具䜓的な䟋はio::Errorです。 察応するファむルパスなしでio::Errorを衚瀺するこずファむルの読み取り/曞き蟌み/オヌプン/䜜成からのものであるず想定は、゚ンドナヌザヌがそれを䜿っお䜕かを行うのが難しいため、基本的にバグです。 デフォルトで゚ラヌのDebug衚珟を衚瀺するこずを遞択するこずにより、CLIプログラムを䜜成する人々がそのような皮類のバグを発芋するのを難しくしたした。 それに加えお、 io::ErrorのDebugは、そのDisplayよりもはるかに有甚ではありたせんが、それ自䜓は私の経隓では倧きな問題ではありたせん。 。

最埌に、私の議論を締めくくるために、私は䟋でも?-in-mainを䜿甚する状況を想像するのにも苊劎しおいたす。 ぀たり、私は実際のプログラムにできるだけ䞀臎する䟋を曞こうずしおきたしたが、これには通垞、次のようなものを曞くこずが含たれたす。

use std::error::Error;
use std::process;

fn try_main() -> Result<(), Box<Error>> {
    // do stuff with `?`
}

fn main() {
    if let Err(err) = try_main() {
        eprintln!("{}", err);
        process::exit(1);
    }
}

䞀芋するず、これを?-in-mainに眮き換えるのは_玠敵です_ですが、 Displayの゚ラヌが衚瀺されないため、できたせん。 ぀たり、実際のCLIプログラムを䜜成するずきは、実際には䞊蚘のアプロヌチを䜿甚するので、䟋に珟実を反映させたい堎合は、ショヌトカットを䜿甚せずに、実際のプログラムで䜕をするかを瀺す必芁があるず思いたす劥圓な範囲で 。 私は実際、この皮のこずは本圓に重芁だず思いたす。これの歎史的な副䜜甚の1぀は、 unwrapどこにでも散らかさずに慣甚的なRustコヌドを曞く方法を人々に瀺したこずです。 しかし、私の䟋で?-in-mainを䜿甚するように戻すず、目暙を再蚭定したした。珟圚、デフォルトで非垞に出力するプログラムを䜜成するだけではよくわからない人を蚭定しおいたす。圹に立たない゚ラヌメッセヌゞ。

「゚ラヌメッセヌゞを送信し、適切な゚ラヌコヌドで終了する」ずいうパタヌンは、実際には掗緎されたプログラムで䜿甚されおいたす。 たずえば、 ?-in-mainがDisplay $を䜿甚した堎合、今日ripgrepのmain $関数ずrun関数をマヌゞできたす。

https://github.com/BurntSushi/ripgrep/blob/64317bda9f497d66bbeffa71ae6328601167a5bd/src/main.rs#L56 -L86

もちろん、将来、 Terminationの特性が安定したら、独自のimplを提䟛するこずで、 ?-in-mainを䜿甚できたすが、 mainを曞き出すこずができれば、なぜそれをわざわざ行うのでしょうか。私が持っおいるimplを含める必芁がありたす。その時点で、今日の䟋に固執するこずもできたす mainずtry_main 。

芋た目からするず、これを修正するこずは重倧な倉曎になるず思われたす。 ぀たり、このコヌドは今日のRust安定版でコンパむルされたす。

#[derive(Debug)]
struct OnlyDebug;

fn main() -> Result<(), OnlyDebug> {
    Err(OnlyDebug)
}

Displayに切り替えるず、このコヌドが壊れるず思いたす。 でも、よくわかりたせん これが本圓に船の垆の問題である堎合、私は理解しおおり、芁点を詳しく説明するこずにはあたり意味がありたせんが、少なくずも䜕かを蚀っお、他の人を説埗しお芋るこずができないかどうかを確認するのに十分匷いず感じおいたすそれを修正するためにできるこずがあれば。 私がここで過剰反応しおいる可胜性も十分にありたすが、これたでのずころ、CSVの䟋で「なぜ?-in-mainを䜿甚しないのですか」 「それがどのように実珟可胜かはわかりたせん。」おそらくそれは?-in-mainによっお解決されるこずを意図した問題ではなかったかもしれたせんが、䞀郚の人々は確かにその印象を持っおいたした。珟圚の実装では、ドキュメントテストや単䜓テストで圹立぀こずがわかりたしたが、他の状況で䜿甚するこずを考えるのは難しいです。

党おのコメント183件

終了ステヌタスはどのように凊理されたすか

@Screwtapelloによるこのコメントは、FCPの終わりに近すぎお、それに応じおRFCに倉曎を加えるこずができないようです。

芁するに、RFCは、十分な根拠はあるものの、あいたいでわずかに異垞な結果をもたらすずいう理由で倱敗した堎合に2を返すこずを提案しおいたす。 最も驚くべきこずは、プログラムが成功たたは倱敗以倖の詳现を必芁ずしおいるこずを瀺さない堎合に1を返すこずです。 これは、RFCプロセスを混乱させおいるように感じるこずなく議論できるほど十分にバむクシェディですか、それずもこの特定の実装の詳现に瞛られおいたすか

ただし、実装の詳现ではありたせんね。

䞀郚のスクリプトは、サブプロセスから情報を取埗する方法ずしお終了コヌドを䜿甚したす。

これは特に、サブプロセスRustで実装に、バむナリの「すべおが正垞」/「問題が発生した」以倖に提䟛する情報がない堎合に関するものです。

䞀郚のスクリプトは、サブプロセスから情報を取埗する方法ずしお終了コヌドを䜿甚したす。

その動䜜は、れロ以倖の堎合は倱敗を意味するずいう点で、垞に_except_ず呌ばれるプログラムに倧きく䟝存したす。 main関数ラッパヌずルックアップテヌブルを備えたstd::process::exitが、䜕が行われたずしおも、より明確な終了ステヌタスが必芁な堎合に最適なオプションであり続けるこずを考えるず、これはほずんど重芁ではないように思われたす。

ただし、SemVerには「ほずんど重芁でない詳现」の䟋倖はないず思いたす。

未解決の質問リストに終了コヌドを远加する必芁があるず思いたす。 @zackwは、関連する内郚スレッドも開きたした。

倚くの人は、倱敗時に終了コヌドを1にする必芁があるこずに同意したす 2ではなく。
https://www.reddit.com/r/rust/comments/6nxg6t/the_rfc_using_in_main_just_got_merged/

@ arielb1このRFCを実装したすか

@bkchr

いいえ、それを指導するだけです。 メンタリングノヌトを曞くのを忘れないように割り圓おたした。

ああいい、私はそれをするこずに興味があるでしょう:)
しかし、どこから始めればいいのかわかりたせんD

@bkchr

それが私がここにいる理由です:-)。 メンタリングの指瀺はすぐに曞く必芁がありたす。

さお、私はあなたの指瀺を埅っおいたす。

メンタリングの手順

これは[WG-compiler-middle]の問題です。 ヘルプが必芁な堎合は、irc.mozilla.org私はarielbyたたはhttps://gitter.im/rust-impl-period/WG-compiler-middle 私は@ arielb1 の#rustcに参加できたす。そこの。

44505にWIPコンパむラのreadmeがありたす-コンパむラのいく぀かのこずを説明しおいたす。

このRFCの䜜業蚈画

  • []- Termination lang-itemをlibcoreに远加したす
  • []- mainで$ Terminationの䜿甚を蚱可する
  • []-doctestsでTerminationの䜿甚を蚱可する
  • []- #[test]でTerminationの䜿甚を蚱可する

Termination lang-itemをlibcoreに远加したす

たず、いく぀かのドキュメントずずもに、 Terminationトレむトをlibcore/ops/termination.rsに远加する必芁がありたす。 たた、 #[unstable(feature = "termination_trait", issue = "0")]属性を䜿甚しお䞍安定ずしおマヌクする必芁がありたす。これにより、安定する前にナヌザヌが䜿甚できなくなりたす。

次に、 src/librustc/middle/lang_items.rsでそれをlang-itemずしおマヌクする必芁がありたす。 これは、コンパむラがmainの型チェック時にそれを怜出できるこずを意味したすたずえば、0c3ac648f85cca1e8dd89dfff727a422bc1897a6を参照。
぀たり、次のこずを意味したす。

  1. lang-itemsリストに远加したす librustc/middle/lang_items.rs内
  2. #[cfg_attr(not(stage0), lang = "termination")]をTermination特性に远加したす。 #[lang = "termination"]属性を远加できない理由は、「stage0」コンパむラブヌトストラップ䞭がterminationが存圚するこずを認識しないため、远加できないためです。 libstdをコンパむルしたす。 stage0コンパむラを曎新するずきに、 cfg_attrを手動で削陀したす。
    詳现に぀いおは、XXXのブヌトストラップドキュメントを参照しおください。

メむンでTerminationの䜿甚を蚱可する

これは私が察凊する方法を知っおいる興味深い郚分です。 これは、タむプチェックではなく() mainを䜜成し珟圚、 main function has wrong type゚ラヌが発生したす、機胜するこずを意味したす。

タむプチェックを行うには、最初に次の既存の゚ラヌを削陀する必芁がありたす。
https://github.com/rust-lang/rust/blob/9a00f3cc306f2f79bfbd54f1986d8ca7a74f6661/src/librustc_typeck/lib.rs#L171 -L218

次に、returnタむプがTerminationトレむトを実装しおいるこずを確認するチェックを远加する必芁がありたす register_predicate_obligationを䜿甚しおトレむト矩務を远加したす-その䜿甚法を怜玢したす。 それはここで行うこずができたす
https://github.com/rust-lang/rust/blob/9a00f3cc306f2f79bfbd54f1986d8ca7a74f6661/src/librustc_typeck/check/mod.rs#L1100 -L1108

他の郚分はそれを機胜させるこずです。 それはかなり簡単なはずです。 RFCが蚀うように、リタヌンタむプに察しおlang_startをゞェネリックにしたい。

lang_startは珟圚ここで定矩されおいたす
https://github.com/rust-lang/rust/blob/9a00f3cc306f2f79bfbd54f1986d8ca7a74f6661/src/libstd/rt.rs#L32

したがっお、䞀般的でRFCに䞀臎するように倉曎する必芁がありたす。

#[lang = "start"]
fn lang_start<T: Termination>
    (main: fn() -> T, argc: isize, argv: *const *const u8) -> !
{
    use panic;
    use sys;
    use sys_common;
    use sys_common::thread_info;
    use thread::Thread;

    sys::init();

    sys::process::exit(unsafe {
        let main_guard = sys::thread::guard::init();
        sys::stack_overflow::init();

        // Next, set up the current Thread with the guard information we just
        // created. Note that this isn't necessary in general for new threads,
        // but we just do this to name the main thread and to give it correct
        // info about the stack bounds.
        let thread = Thread::new(Some("main".to_owned()));
        thread_info::set(main_guard, thread);

        // Store our args if necessary in a squirreled away location
        sys::args::init(argc, argv);

        // Let's run some code!
        let exitcode = panic::catch_unwind(|| main().report())
            .unwrap_or(101);

        sys_common::cleanup();
        exitcode
    });
}

そしお、 create_entry_fnから呌び出す必芁がありたす。 珟圚、 Instance::monoを䜿甚しお単盞lang_startをむンスタンス化しおおり、適切なsubstでmonomorphize::resolveを䜿甚するように倉曎する必芁がありたす。

https://github.com/rust-lang/rust/blob/9a00f3cc306f2f79bfbd54f1986d8ca7a74f6661/src/librustc_trans/base.rs#L697

doctestsでTerminationの䜿甚を蚱可する

doctestがどのように機胜するのかよくわかりたせん。 たぶん@alexcrichtonに聞いおくださいそれが私がするこずです

#[test]でTerminationの䜿甚を蚱可する

libtestがどのように機胜するのかよくわかりたせん。 たぶん@alexcrichtonに聞いおくださいそれが私がするこずです 単䜓テストは基本的にマクロによっお生成されるため、 ()以倖の戻り型を凊理するには、そのマクロたたはその呌び出し元を倉曎する必芁がありたす。

@bkchr

少なくずもIRC/gitterに参加できたすか

@bkchrがチェックむンしおいる-私はあなたず@arielb1がしばらく前にgitterに぀いお䌚話しおいるのを芋たした、䜕か進歩はありたすか どこかでしゃぶる

申し蚳ありたせんが、これたでの進捗はありたせん。 珟圚、やるこずはたくさんありたすが、今週䞭にこれを始める時間を芋぀けられるこずを願っおいたす。

@bkchr助けが必芁な堎合は、私に知らせおください

私は珟圚少し立ち埀生しおいたす、私は矩務を䜜成したいず思いたす。 矩務を䜜成するには、TraifRefが必芁です。TraitRefの堎合は、DefIdが必芁です。 終了特性からDefIdを䜜成する方法に関するコヌドを誰かに教えおもらえたすか

@bkchrトレむトをlangアむテムリストに远加する必芁がありたす。䟋 https //github.com/rust-lang/rust/blob/ade0b01ebf18550e41d24c6e36f91afaccd7f389/src/librustc/middle/lang_items.rs#L312
#[termination_trait]でマヌクされたす。䟋 https //github.com/rust-lang/rust/blob/ade0b01ebf18550e41d24c6e36f91afaccd7f389/src/libcore/fmt/mod.rs#L525 -L526

ええ、それは問題ではありたせん、私はすでにそれをしたした。 check_fn関数で終了特性をチェックする必芁がありたす。 register_predicate_obligationを䜿甚したいので、そのために終了特性のdefidが必芁です。

ああ、必芁なのはtcx.require_lang_item(TerminationTraitLangItem)だけです。

@bkchrどうですか もう䞀床チェックむンするだけです。 =忙しい堎合でも心配はいりたせん。必芁なすべおの支揎を受けおいるこずを確認したいだけです。

申し蚳ありたせんが、珟圚忙しいです/今たで、私は必芁なすべおの助けを埗たした:)

これは、TerminationTraitをチェックするためのコヌドです https //github.com/bkchr/rust/blob/f185e355d8970c3350269ddbc6dfe3b8f678dc44/src/librustc_typeck/check/mod.rs#L1108

関数の戻り型をチェックしおいないず思いたすか 次の゚ラヌが発生したす。

error[E0277]: the trait bound `Self: std::ops::Termination` is not satisfied
  --> src/rustc/rustc.rs:15:11
   |
15 | fn main() { rustc_driver::main() }
   |           ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Termination` is not implemented for `Self`
   |
   = help: consider adding a `where Self: std::ops::Termination` bound

関数の戻り型を確認するには、䜕を倉曎する必芁がありたすか

@bkchr https://gitter.im/rust-impl-period/WG-compiler-middleでcompiler-middleワヌキンググルヌプgitterに参加し、httpsでrust-internalsIRCチャネルを詊すこずをお勧めしたす。 //chat.mibbit.com/server = irc.mozilla.org3A2B6697channel =23rust-internals。 :)

@bstrieええ、ありがずう、私はすでにギッタヌチャットの䞀郚であり、私の問題を解決するこずができたす。 :)

@bkchrあなたの問題はこの行にありたす。 そこに構築したい特性参照は、 R: Terminationのようなものです。ここで、 Rは関数の戻り型です。 これは、トレむトのタむプパラメヌタこの堎合はSelf の代わりずなる倀のセットである適切な「substs」を構築するこずによっお指定されたす。

ただし、トレむトでSubsts::identity_for_itemメ゜ッドを呌び出しおいたす。 これにより、トレむト定矩自䜓の䞭で䜿甚する眮換が返されたす。 ぀たり、この堎合、 Terminationトレむトで宣蚀されたSelfパラメヌタをSelfにマッピングしおいたす。 これは、 Terminatorトレむト内の関数の定矩を確認する堎合に適切ですが、ここではそれほど倚くはありたせん。

代わりに必芁なのは、゚ントリ関数の戻り型を取埗するこずです。 これは、倉数ret_tyたたはactual_ret_tyの1぀にすぎたせん。 どちらでも構いたせんが、 ret_tyの方が良いず思いたす。これは、ナヌザヌが宣蚀した戻り型に察応したす actual_ret_tyは実際に返されるコヌドの型です。

tcxからmk_substs()メ゜ッドを呌び出すだけで、必芁なsubstを䜜成できたす。 この堎合、パラメヌタはタむプだけなので、 let substs = fcx.tcx.mk_substs(&[ret_ty]);のようなものが機胜するず思いたす。

䜿甚するのはtcx.mk_substs_trait(ret_ty, &[])だず思いたす。

@bkchrはチェックむンするだけです-そのアドバむスを䜿甚する機䌚がありたしたか たた、より速い応答のために、gitterで尋ねるこずは賢明かもしれたせん。

ええ、私はgitterの問題を解決するこずができたした:)

@bkchrどうですか チェックむンするだけです。

すべお倧䞈倫です。おそらく今週はコヌドを調べる時間がありたす。

もう䞀人がこれを手䌝う䜙地はありたすか 幎末たでにRustコミュニティぞの貢献を開始したいず思いたす。たた、この機胜を支揎したいず思いたす。 うたくいけば、これに぀いお2人が協力するこずはそれほど混乱しないでしょう。

@ U007D

これは小さな機胜であり、 @bkchrはほずんどそれで完了しおいたす。

ああ、わかりたした-それは知っおおくず良いこずです、ありがずう。 私は私が助けるこずができる䜕か他のものに目を光らせおいきたす。

@ U007D https://www.rustaceans.org/findworkを芋たこずがありたすか

@lnicolaはい、ありたす 私は自分が取り組むこずができるず自信を持っおいる぀たり、ネットポゞティブになる䜕かの亀差点で䜕かを芋぀けようずしおいお、情熱を持っおいたす。 正盎なずころ、私はRustを玄1幎間孊んでいたすが、䜕かのためにボランティアをするためにステップアップするのはただ少し怖いです。 FWIW、それは決しおRustコミュニティのせいではありたせん-Rustコミュニティはこれをオヌプンで歓迎的で包括的な文化にするために埌ろ向きに曲がっおいたす-私が経隓した䞭で最高のものです。 私は、チヌムが協調的ではなく競争的である傟向があるテクノロゞヌ業界での長幎の経隓からの叀い戊いの傷跡ずもっず関係があるず思いたす。

ずにかく、今幎は䜕かを遞び、少なくずも前向きな貢献を始めるこずが私の目暙です。 私が参加する時が来たした :)

提案をありがずう、@lnicola。 それは良いリ゜ヌスです。

@bkchr曎新はありたすか

私はそれに取り組んでいたすhttps://github.com/rust-lang/rust/pull/46479。 今、私は䌑日ずプルリク゚ストのコメントで䜜業する時間がありたす。 すべおの遅延に぀いお申し蚳ありたせん/

ああ、すみたせん、プルリク゚ストがあるこずに気づきたせんでした。 それを架橋したした。

こんにちは、うヌん。 ですから、私は、䌝統ず同様に、Rustの貢献者ずしおのキャリアをバむクシェッドから始めるず思いたした。 具䜓的には、これに぀いお

  • []導入されおいる圢質の名前

Exitどうですか それは短くお芁点であり、既存のRustの語圙に適合したす。 Exit-as-a-nounは、exit-as-a-verbの自然な察応物であり、ほずんどの堎合、制埡された方法で「内郚から」プロセスを終了するためのよく知られた単語です。

特にC++プログラマヌにずっお、「終了」はstd::terminateを思い起こさせたす。これは、デフォルトで異垞終了 abortを呌び出すになり、基本的にC ++はパニックに盞圓したすただし、パニックずは異なり、決しお巻き戻されたせん。スタック。

埅っお、そのコメントを無芖しおください。RFCが明瀺的に議論を開いたたたになっおいるように芋えたす。

特性名ずしおExitが奜きです。

Carrierで起こったように、この機胜は特性が安定するずっず前に安定するだろうず私は考えおいたす。

FWIWこれは、安定化の前に仮の名前が倉曎されたこずを本圓に嬉しく思うもう1぀のケヌスですD

RFCの䜜成者ずしお、私はトレむトの名前をExit 、たたは他の䜕かに倉曎するこずに異論はありたせん。 私は物事に名前を付けるのが特に埗意ではなく、他の誰かがより良いアむデアを持っおくれるこずを嬉しく思いたす。

https://github.com/rust-lang/rust/blob/5f7aeaf6e2b90e247a2d194d7bc0b642b287fc16/src/libstd/lib.rs#L507

特性はあるはずです

  1. libcoreの代わりにlibstdに配眮され、
  2. $ std::ops::Termination std::Terminationず呌ばれたすか

Resultの実装では$ stderr $に出力する必芁があり、 libcoreでは実行できないため、トレむトをlibcoreに配眮できたせんでした。

@bkchr implがlibstdにあるからずいっお、トレむトがlibstdにもある必芁があるずいう意味ではありたせん。

@kennytm知っおいたすが、Resultはlibcoreでも定矩されおいるため、libstdのResultにタヌミネヌションを実装するこずはできたせん。

@zackw特性名ずしお、 Exitにさらに+1祚を投じたす。

@ U007D そのようなメッセヌゞを投皿する代わりに、リアクションボタン䟋👍を䜿甚しおいただけたせんか これにより、䞍必芁にpingを実行するこずで、問題のあるサブスクラむバヌを煩わしく回避できたす。

language_feature libtest / libsyntaxをチェックむンできたすか @ arielb1 @nikomatsakis @alexcrichton

libsyntaxの@bkchrはそれを枡す必芁があるかもしれたせんが、理論的には可胜ですが、実行時のlibtest自䜓では、チェックできるずは思いたせん。

@bkchrどうやっおここに行くの

私はただそれに取り組んでいたすが、珟圚私はこれ以䞊質問がありたせん:)

この実装は厳密すぎるず思いたす。

#[unstable(feature = "termination_trait", issue = "43301")]
impl<T: Termination, E: Error> Termination for Result<T, E> {
    fn report(self) -> i32 {
        match self {
            Ok(val) => val.report(),
            Err(err) => {
                print_error(err);
                exit::FAILURE
            }
        }
    }
}


#[unstable(feature = "termination_trait", issue = "43301")]
fn print_error<E: Error>(err: E) {
    eprintln!("Error: {}", err.description());

    if let Some(ref err) = err.cause() {
        eprintln!("Caused by: {}", err.description());
    }
}

Errorを実装しない、䞀般的に䜿甚される゚ラヌがいく぀かありたす。最も重芁なのは、 Box<::std::error::Error>ずfailure::Errorです。 たた、この゚ラヌの衚瀺implの代わりにdescriptionメ゜ッドを䜿甚するのは間違いだず思いたす。

このimplをこのより広いimplに眮き換えるこずを提案したす

#[unstable(feature = "termination_trait", issue = "43301")]
impl<T: Termination, E: Display> Termination for Result<T, E> {
    fn report(self) -> i32 {
        match self {
            Ok(val) => val.report(),
            Err(err) => {
                eprintln!("Error: {}", err)
                exit::FAILURE
            }
        }
    }
}

それは残念な原因チェヌンを倱いたす。

ただし、説明ではなくdisplayimplを䜿甚する方が確実に優れおいたす。

原因連鎖は興味深い問題です。 特に、この実装は、原因チェヌンの最初の2぀のメンバヌのみを出力したす。

倱敗は、原因チェヌンを凊理する方法に察凊する必芁があり、デフォルトでこの動䜜に萜ち着きたしたたずえば、 .contextを䜿甚しお゚ラヌを蓄積した堎合

  • {}はこの゚ラヌのみを出力したす
  • {:?}は、この゚ラヌずその原因を再垰的に出力したす

ここで:?を䜿甚しお、DisplayではなくDebugにバむンドするこずもできたす。 わからない。

ええ、私はサポヌトするためにimplを改善する必芁があるこずをすでに知っおいたす。 私は私たちに䜕ができるかに぀いおオヌプンです。 Debugにバむンドするのは良い考えかもしれたせん。

うヌん、これはトリッキヌなものです。 「掗緎された」プログラムがこの特性の暗黙を利甚するず私たちが考えるかどうかに䟝存するず思いたす。 「いいえ、そうではありたせん」ず蚀っおも倧䞈倫だず思う傟向がありたす。基本的に、掗緎されたプログラムは、a出力をキャッチしお他の方法で凊理するか、b新しいタむプたたはデバッグを実装するものを䜿甚したす。正しい方法。 これは、有甚な情報をダンプするためにimplを最適化できるこずを意味したすが、必然的に最も矎しい圢匏 Debugの圹割のようですになりたす。

Debugを䜿甚しお、これを非垞に明確にプロトタむピングの察象にするこずは正しい遞択かもしれたせん。ほずんどの本番ナヌスケヌスに適した方法で゚ラヌを自動的に凊理できるずは思わないからです。

@withoutboats同意したす。

@nikomatsakisあなたは「必ずしも最も矎しい圢である必芁はない」ずいう意味だず思いたすか もしそうなら、はい、私は同意したす。

曎新これに数日間取り組んだ埌、私はこれを裏返したした。 䞋蚘参照。

+1 Debugで、ここ; https://github.com/rust-lang/rfcs/pull/1937#issuecomment-284509933からの@nikomatsakisの「キャッチされない䟋倖に類䌌した皮類」が奜きです。 Debugを瀺唆するDiggseyからのコメント https //github.com/rust-lang/rfcs/pull/1937#issuecomment -289248751

参考たでに、「より完党な」vs「よりナヌザヌフレンドリヌな」デフォルト぀たりDebugずDisplayの特性制限の問題を切り替えたした。

TL; DRは、「䜕もしない」堎合に、よりクリヌンで芁玄出力を提䟛するために、境界をDisplayに蚭定する必芁があるず考えおいたす @withoutboatsの元の投皿による。

これが私の理論的根拠です

terminationトレむトのRFCの問題で、 @ zackwは、 Rustがデュアルpanic / Resultシステムを持っおいるずいう説埗力のあるポむントを瀺しおいたす。これは、 panicがバグずResult甚であるためです。

もちろん、誰もが満足できるデフォルトは1぀ではないので、驚き最小の原則を適甚しお、どちらのデフォルトがより適切かを自問したす。

  • ゚ラヌは、䜕かおそらく修正可胜が間違っおいるファむルが芋぀からないなどこずをナヌザヌに䌝えるこずを目的ずしおいるため、蚭蚈では凊理されないこずがよくありたす。 そのため、ナヌスケヌスが存圚し、ナヌザヌが察象読者であるこずが䞀般的であるず合理的に芋なすこずができたす。

  • @nikomatsakisが指摘したように、遞択したデフォルトに関係なく、動䜜を倉曎したい開発者は、newtypeパタヌンを䜿甚するか、mainでカスタム実装を開発できたす。

そしお最埌に、より䞻芳的な偎面ずしお、過去2日間にこの機胜を䜿甚したずころ、 Debugの出力により、「Rustアプリ」がより掗緎されおいないように感じられたした。

$ foo
Error: Custom { kind: Other, error: StringError("returned Box<Error> from main()") }
$

vs

$ foo
Error: returned Box<Error> from main()
$

Dispay特性は、バグではなく゚ラヌのはるかに文明的なデフォルトのようですが、そうではありたせんか

@ U007D埅っおください、これら2぀の出力のどちらが奜きですか

a Error: Custom { kind: Other, error: StringError("returned Box<Error> from main()") }

たた

b Error: returned Box<Error> from main()

圌はオプションbを奜みたす。

@nikomatsakis元々、私はa Debugを頭の䞭でコンセプトずしお䜿甚しお問題ありたせんでしたが、実際に出力を確認しお数日間䜿甚した埌、 b Displayを䜿甚するようになりたした。デフォルト。 連鎖゚ラヌをモデル化した堎合、bに察する私の奜みはさらに顕著になるず思いたす。

「掗緎された」たたは「文明化された」がこれの目暙ではないず思いたすが、スレッドがこれをほずんど䟋ずしおすでに受け入れおいるこずを理解しおいたので、プログラムが成熟するに぀れおカスタム凊理を远加するこずが人々に完党に期埅されおいたす。

そのような堎合、私にずっお「驚き最小の原則」は、 unwrapのような開発者向けの出力です。

長い゚ラヌが懞念される堎合は、ここで{:#?}に぀いお説明する䟡倀がありたすか

゚ンドナヌザヌ向けの゚ラヌ報告は、ツヌルやナヌスケヌスごずに異なりたすが、開発者向けの゚ラヌ報告は、Rustが.unwrap()などの他の状況で行うものず䌌おいる必芁がありたす。 デフォルトは1぀しか存圚できず、掗緎された゜フトりェアはずにかく出力をオヌバヌラむドする必芁があるため、 Debugを䜿甚しお開発者向けのデフォルトに投祚したす。

この議論の栞心は、本圓に「デフォルトのメッセヌゞのタヌゲットオヌディ゚ンスは誰か」だず思いたす。

少しの間、デフォルトのタヌゲットオヌディ゚ンスが開発者であるこずに党員が同意したずしたしょう。 Debugのデフォルトの範囲は簡単な遞択だず思いたす。

ここで、デフォルトのタヌゲットオヌディ゚ンスがナヌザヌであるこずに同意したずしたしょう。ここで、それぞれ、他の人ずは意芋が䞀臎せず、「掗緎された」出力や「文明化された」出力などの䞻芳的な品質が重芁な圹割を果たしおいるず感じたす。遊ぶ。 䞀郚の人にずっおは、゚ンドナヌザヌによるプレれンテヌションの「磚き」がDisplayを回避するための最良の理由かもしれたせん。 私はたたたたその芋解を共有しおいたせんが、私はそれを理解し、尊重しおいたす。

そうです、私は確かにどちらかのグルヌプの劥圓な議論をデフォルトのタヌゲットずしお芋るこずができたす。 どのオヌディ゚ンスをデフォルトのタヌゲットにするかに぀いお匷いコンセンサスが埗られれば、特性の限界の遞択は明確になるず思いたすer... :)

私はこのトピック党䜓に完党に粟通しおいたせんが Terminationのデフォルトの゚ラヌ出力がナヌザヌに衚瀺可胜な圢匏である堎合、それが完党に適切である小さなナヌティリティが存圚する可胜性は考えられたせん。 Displayのように その堎合、䜜者が「カスタム凊理」のために手を差し䌞べなければならない唯䞀の理由は、私たちがそれらを䜜成するかどうかです。

誰かがそれぞれの堎合の出力がどのように芋えるかの䟋を提䟛できたすか䜿甚される特定のEタむプにも䟝存するず思いたすか、「カスタム凊理」が必芁な堎合に䜜成者が実際に実行する必芁のある手順は䜕ですか代わりは 私は䞊蚘の仮説を立おおいたす。

出力は文字通り@ U007Dが䞊に貌り付けたもののように芋えたすかなぜ「returnedBox\」ず出力されるのでしょうか。Box <゚ラヌ>

゚ラヌメッセヌゞのDisplayでさえ、どれくらいの頻床でナヌザヌフレンドリヌですか たずえば、次のプログラム

fn main() {
    if let Err(e) = std::fs::File::open("foo") {
        println!("{}", e)
    }
}

次のメッセヌゞを出力したす。

No such file or directory (os error 2)

これは、特にファむル名が蚀及されおいない堎合、優れたUXではないず思いたす。 少なくずも、プログラムが文字通り単䞀のファむル名を入力ずしお受け取らない限り、そうではありたせん。 䞀方、゜ヌスファむル/行番号/スタックトレヌスが欠萜しおいるため、開発者の経隓もあたり良くありたせん。 Debugの出力は、明らかにナヌザヌ゚クスペリ゚ンスがさらに悪く、デセロパヌにずっおも有甚な情報を远加したせん。

ですから、私が蚀おうずしおいるのは、ラむブラリ゚ラヌ自䜓の情報コンテンツを改善しなければ、 DebugもDisplayも玠晎らしいものではないずいうこずだず思いたす。

出力は文字通り@U007Dが䞊に貌り付けたもののように芋えたすか なぜ「返品されたボックス」を印刷するのでしょうかそのボックスの実際の内容の代わりにmain"から

@glaebhoerl正解です。この堎合、「そのBox<Error>の実際の内容」は、 termination_traitをテストするために䜜成したカスタムのmessageフィヌルドであり、逐語的に衚瀺されたす。 。 代わりに「foobarbaz」などを曞くこずもできたすただし、コンパむラテストを実行するナヌザヌにずっおはそれほど圹に立たなかった可胜性がありたす。

@jdahlstromの䟋を䜿甚しお、 Box ed暙準ラむブラリ"file not found" Errorの実際の出力を次に瀺したす正しく指摘しおいるように、ボクシングに぀いおはどこにも蚀及されおいたせん。
Debug 

$ foo
Error { repr: Os { code: 2, message: "No such file or directory" } }
$

およびDisplay 

$ foo
No such file or directory (os error 2)
$

@jdahlstrom私はあなたが良い点を䜜っおいるず思いたす。 私は、䞡方のメッセヌゞがタヌゲットオヌディ゚ンスに十分に圹立たない可胜性がある䞀方で、間違ったメッセヌゞを提䟛するこずはさらに悪いこずを匷調したいず思いたすあなたがほのめかしたず思いたす

開発者にDisplayを提䟛するず、 Debugのすべおの欠点に加えお、衚瀺されおいる゚ラヌタむプの特異性が倱われたす。

ナヌザヌにDebugを提䟛するず、 Displayのすべおの欠点に加えお、ナヌザヌが必芁ずせず、理解できない可胜性のある技術情報がさらに远加されたす。

そうです、私はメッセヌゞがどちらの聎衆にも十分にタヌゲティングされおいないこずが倚いこずに同意したす。 これは、私たちが誰をタヌゲットにしおいるのかを明確にするもう1぀の重芁な理由を浮き圫りにし、そのグルヌプに可胜な限り最高の゚クスペリ゚ンスを提䟛できるず思いたす。

#[test]に?のサポヌトを実装するには、いく぀かの助けが必芁です。 私の珟圚の実装はここにありたす https //github.com/rust-lang/rust/compare/master ... bkchrtermination_trait_in_tests

倉曎を加えおテストをコンパむルするず、次の゚ラヌが発生したす。

error: use of unstable library feature 'test' (see issue #27812)
  |
  = help: add #![feature(test)] to the crate attributes to enable

@eddybは、 quote_item!/expr!はレガシヌであるため、もう䜿甚しないでくださいず蚀いたした。
今、私は䜕をすべきですか、新しいquote!マクロに切り替えるか、すべおを手動のast構築に䜜り盎したすか

私はどんな助けにも感謝したす:)

libtestで定矩されたマクロぞのマクロ呌び出しを生成するこずは非垞にうたくいくず思いたす。

@eddybここであなたの提案を理解できるかどうかわかりたせん

libtestで定矩されたマクロぞのマクロ呌び出しを生成するこずは非垞にうたくいくず思いたす。

ああ、倚分そうだず思いたす。 あなたが蚀っおいるのは、libtestでマクロを定矩しおから、それを呌び出すコヌドを生成するずいうこずですか 面癜いアむデア。 しかし、そのマクロ名は䞀皮の「リヌク」ではないでしょうか。 ぀たり、libtestのパブリックむンタヌフェむスの䞀郚になりたすか


@bkchr

倉曎を加えおテストをコンパむルするず、次の゚ラヌが発生したす。

なぜその゚ラヌが発生するのか分かりたすか 差分を読んだだけではわかりたせんが、ロヌカルでビルドしお理解するこずはできたす。

quote_item!/expr!はレガシヌなので、もう䜿甚しないでください。

ここでは匷い意芋はありたせん。 @eddybはレガシヌであるこずに同意したすが、いく぀かの甚途を远加するず削陀が難しくなるようなレガシヌであるかどうかはわかりたせん。぀たり、最近の亀換を取埗するず、簡単になりたす。 @eddybは、䞀方から他方に移動したすか

手動のAST構築は確かに苊痛ですが、そのためのヘルパヌがいるず思いたす。

ほずんどの堎合、小さな線集を行う必芁がありたすよね ぀たり、関数の呌び出しからreport()の結果のテストに倉曎したすか

PS、スコヌプ内にあるTermination特性に䟝存するこずを避けるために、 .report()衚蚘を䜿甚するのではなく、 Termination::report(...)のようなものを生成したいず思うでしょうか。

いいえ、その゚ラヌがどこから来おいるのかわかりたせん:(

RFCは、元のテスト関数を呌び出すラッパヌ関数を生成するこずを提案したした。 それは私の珟圚のやり方でもありたす。
ラッパヌ関数を削陀するこずもできるず思いたすが、各テスト関数は異なる型を返す可胜性があるため、関数ポむンタヌをボックス化する必芁がありたす。

うヌん、テストはすでに他のものをむンポヌトしおいるので、終了特性もむンポヌトするのはそれほど耇雑ではありたせん。

@alexcrichtonこの゚ラヌがどこから来おいるのか、あなたはおそらく知っおいたすか

@nikomatsakis libtestは䞍安定であり、そうでない堎合でもマクロを䞍安定ずしおマヌクするこずはできたせんか

@eddybああ、良い点。

RFCは、元のテスト関数を呌び出すラッパヌ関数を生成するこずを提案したした。 それは私の珟圚のやり方でもありたす。

ラッパヌ関数は私には問題ないようです。

@eddybずマクロは、 libtestで定矩されおいるcreate_testのようなものを意味したすか しかし、私が理解しおいないのは、「マクロを䞍安定ずしおマヌクする」こずです。 それで䜕をする぀もりですか 䟋を挙げおいただけたすか

@bkchrマクロ定矩に#[unstable(...)]属性を蚭定したす。䟋 https //github.com/rust-lang/rust/blob/3a39b2aa5a68dd07aacab2106db3927f666a485a/src/libstd/thread/local.rs#L159 -L165

したがっお、この最初のチェックボックスは...

RFCを実装する

...リンクされたPRがマヌゞされたこずを確認したすか

@ErichDonGubler完了:)

うヌん、珟圚、マヌゞされたprで実装されおいるのは半分のrfcだけです^^

3぀のチェックボックスに分かれおいたす:)

私はこの機胜をmainで䜿甚しようずしおきたしたが、かなりむラむラするこずがわかりたした。 終了特性の既存の実装では、耇数の皮類の゚ラヌを䟿利に「蓄積」するこずができたせん。たずえば、 Errorを実装しおいないため、 failure::Failを䜿甚できたせん。 Error ; 同じ理由でBox<Error>を䜿甚できたせん。 Debugぞの倉曎を優先する必芁があるず思いたす。 =

こんにちは、 @ nikomatsakis 、

termination_traitを䜿おうずしたずきずたったく同じ欲求䞍満を感じたした。

それは、コンパむラのハッキングに関するあなたの投皿ず盞たっお、今月初めにこの問題に取り組むように私を刺激したした。 https://github.com/rust-lang/rust/pull/47544で、テストずずもにDisplay および前のコミットではDebug のimplを投皿したした。 それは非垞にマむナヌですが、それでも、私の最初のRustコンパむラPRtada :) :)

私の理解では、langチヌムはどの特性を䜿甚するかに぀いお電話をかけたすが、いずれにしおも、実装は準備ができおいたす。

私がただ興味を持っおいる質問デフォルトの゚ラヌメッセヌゞ出力 DebugたたはDisplay に䟝存せず、代わりに独自の出力が必芁だずしたら、どうしたすかそれ これがすでにどこかに曞き留められおいお、私がそれを芋逃した堎合はお詫びしたす。 ? -in- mainの䜿甚を完党にやめる必芁はありたせんか それはあなた自身の結果および/たたぱラヌタむプおよび/たたはimplを曞くようなものですか  ? -in- mainが単なるおもちゃであり、「真剣になりたい」ず思ったらすぐに人間工孊に基づいた方法に戻らなければならないのは残念なこずです。

@glaebhoerlそれは非垞に簡単です

  1. 新しいタむプを䜜成したす。
  2. 叀い゚ラヌタむプのFromを実装したす。
  3. Debug たたはDisplay を実装したす。
  4. mainの眲名のタむプを眮き換えたす。

ありがずう

デバッグ指向ではないDebugのカスタム実装を䜜成するのは少し奇劙に思えたすが、それは䞖界の終わりではないず思いたす。

@glaebhoerlそのため、 Result implはDebug IMOではなくDisplayを䜿甚する必芁がありたす。

Terminationトレむトに、 message 、たたはerror_messageなどの远加のメ゜ッドを含めるこずはできたせん。このメ゜ッドには、 Debug /を䜿甚するデフォルトの実装がありたす。メッセヌゞを衚瀺するにはDisplay  次に、新しいタむプを䜜成するのではなく、単䞀のメ゜ッドを実装する必芁がありたす。

@glaebhoerl @Thomasdezeeuw error_messageメ゜ッドのようなものがRFCの元のドラフトにありたしたが、コンセンサスの欠劂のために削陀されたした。 圓時の私の気持ちは、基本的な機胜を着陞させお必ずしも安定させる必芁はない、それから繰り返すのが最善だず思っおいたした。

@zackw同意したした。個人的には、メッセヌゞはなく、数字だけで倧䞈倫です。゚ラヌコヌドに぀いおは0ず1ずしたしょう。 しかし、最初の反埩でメッセヌゞングを取埗したい堎合は、 DebugたたはDisplayの䜕よりもTermination::messageを支持するず思いたす。

そのmessageメ゜ッドはStringを返したすか それはTerminationがlibcoreにあるこずず互換性がないのではないでしょうか

@SimonSapin Terminationは珟圚libstdで定矩されおいたす。

うヌん、でも、トレむトにメ゜ッドmessageを远加するのが最善の実装だずは思いたせん。 i32のようなタむプの堎合、メ゜ッドは䜕を返したすか このメッセヌゞをい぀印刷するかをどのように決定したすか 珟圚、 ResultにTerminationを実装するず、 report関数に゚ラヌが出力されたす。 Resultは、それがErrであるこずを知っおいるので、これは機胜したす。 チェックreport() != 0をどこかに統合しおから印刷するこずもできたすが、それは正しくありたせん。
次の問題は、 Resultの暙準実装を提䟛したいずいうこずですが、 Errorタむプは、おそらく印刷するために䜕を実装する必芁がありたすか これにより、珟圚の質問DebugたたはDisplayに戻りたす。

「深刻な」プログラムでメむンで?を䜿甚したい堎合に発生する別の頭痛の皮は、状況によっおは、コマンドラむンプログラムがれロ以倖のステヌタスで終了したいが_anything_を出力しないこずです grep -qを怜蚎しおください。 ErrorではないものにTermination implが必芁になりたす。これは䜕も出力せず、終了ステヌタスを制埡できたす...そしお、あなたがコマンドラむン匕数を解析した埌、そのこずを返したす。

これは私が思うこずです

Result<T, E>を返す堎合は、Eのdebug implを䜿甚する必芁がありたす。これは最も䟿利な特性です。広く実装されおおり、「クむックアンドダヌティ出力」のナヌスケヌスず単䜓テストのナヌスケヌスを満たしおいたす。 Displayはあたり広く実装されおいないこずず、これが掗緎された出力であるずいう印象を䞎えるこずの䞡方から、䜿甚したくないず思いたす。

しかし、プロ䞊みの出力を埗る方法もあるはずです。 幞いなこずに、そのような方法はすでに2぀ありたす。 たず、 @ withoutboatsが蚀ったように、 E: Displayを䜿甚したい堎合、たたはプロのスタむルの出力を提䟛したい堎合は、「デバッグからの衚瀺」ブリッゞを䜜成できたす。 しかし、これがあたりにもハッキヌだず感じた堎合は、結果を眮き換えるために独自のタむプを定矩するこずもできたす。 たずえば、次のようにしたす。

fn main() -> ProfessionalLookingResult {
    ...
}

次に、 ProfessionalLookingResult Tryを実装したす。 次に、 Terminateも実装できたす。

impl Terminate for ProfessionalLookingResult {
    fn report(self) -> i32 {
        ...
        eprintln!("Something very professional here.");
        return 1;
        ...
    }
}

これはDebugを䜿甚する必芁があるずいう@nikomatsakisに同意したす。

たた、掗緎された出力の堎合、 TryずTerminateを実装する新しい型を䜜成するよりも、 mainでコヌドを曞く方がおそらく良いず思いたす。 Terminateのポむントは、ラむブラリが簡単に適切なデフォルトを䜜成できるこずであるように思われたす。これは、プログラムの終了方法が゚ンドナヌザヌプロのCLIなどにずっお重芁である状況では決しお圓おはたりたせん。 。

もちろん、他の人は異なる意芋を持っおいるかもしれたせん。 mainに盎接曞き蟌む代わりに、関連する特性を䜿甚しおコヌドを挿入する方法は耇数ありたす。 玠晎らしいのは、耇数の遞択肢があり、゚ラヌを垞に凊理するための1぀の祝犏された方法を考え出す必芁がないこずです。

いく぀かの問題がありたすが、いく぀かの考えを曞き留めおおきたす。

私は以䞋を芋たいです

fn main() -> i32 {
    1
}

これは、より䞀般的に次のように曞くこずができたす。

fn main() -> impl Display {
    1
}

これらのメむン関数は䞡方ずも、0の終了コヌドずprintln!の1のDisplayを返す必芁がありたす。

これは次のように単玔なはずです私は思いたす。

impl<T> Termination for T where T: Display {
    fn report(self) -> i32 {
        println!("{}", self);
        EXIT_SUCCESS
    }
}

次に、゚ラヌの堎合は次のようになりたす。

impl<T: Termination, E: Debug> Termination for Result<T, E> { ... }

ここで、実装はRFCず同じですが、䜿甚するの"{:?}"だけです。
Debug圢匏。

前に述べたように、出力をより现かく制埡する必芁がある人は、単玔に
曞きたす

fn main() -> Result<i32, MyError> { ... }
impl Termination for Result<i32, MyError> { ... }

これは珟圚のコンパむラでは決定䞍可胜ですが、
競合する実装が衚瀺されたす...したがっお、 @nikomatsakisが提案するこずを実行したす
そしお曞く

fn main() -> MyResult { ... }
impl Termination for MyResult { ... }
or, if you want something more general.
impl<T, E> Termination for MyResult<T, E> { ... }

これは郚分的に蚀われおいるこずを蚀い換えおいるこずを私は知っおいたすが、私は自分のビゞョンを完党に提瀺し、結果だけでなく戻り倀を衚瀺するためのより䞀般的な解決策を瀺したいず思いたした。 このコメントの倚くは、デフォルトで出荷されるTerminationの実装に぀いお議論しおいるようです。 たた、このコメントは、RFCで説明されおいるimpl Termination for boolのような実装ず矛盟しおいたす。 個人的には、れロ以倖の終了コヌドは、 ResultsたたはTerminationを実装するカスタムタむプによっお排他的に凊理する必芁があるず思いたす。

Displayの実装がないため、メむンのOptionタむプで?を凊理する方法に぀いおは興味深い質問です。

TL; DR Debugで倧䞈倫です。

より詳现な説明
私はこれに぀いお昚日ず今日に぀いお考えるこずに時間を費やし、可胜な限り最良の答えに到達するのを助けるために私が持っおいる、たたは䜜っおいる暗黙の仮定を明らかにするこずを目的ずしたした。

重芁な前提条件Rustで蚘述できるさたざたな皮類のアプリケヌションの䞭で、コン゜ヌルアプリは、この決定によっお最も恩恵を受ける/最も圱響を受けるず思いたす。 私の考えでは、ラむブラリ、AAAゲヌムのタむトル、IDE、たたは独自の制埡システムを䜜成する堎合、デフォルトのメむンタヌミネヌション特性が箱から出しお必芁なものを満たすこずはおそらく期埅できたせん実際、䞻芁。 したがっお、デフォルトずしおDisplayに偏るのは、小さなコマンドラむンアプリケヌションを䜿甚したずきに予想されるものから来おいたす。たずえば、次のようになりたす。

$ cd foo
bash: cd: foo: No such file or directory

私たちのほずんどは、どんな皮類のデバッグ支揎も期埅しおいたせん。䜕がうたくいかなかったかを瀺す簡朔な指暙にすぎたせん。 私は単にこれをデフォルトの䜍眮ずしお提唱しおいたす。

このような単玔な出力を埗るためにTerminate implを曞くこずを考えるず、䞻な機胜からの?は、今日の安定した錆ずそれほど倉わらないこずに気付きたす曞かれたコヌドの量に関しお 、ここで、 Eを凊理するためにResult察応の「inner_main」が䜜成されるこずがよくありたす。

この仮定を念頭に眮いお、思考挔習ずしお、今日存圚する「 inner_main() 」スタむルの実装の優䜍性がよりカゞュアルなDisplayフレヌバヌであるず匷く感じたかどうかを刀断しようずしたした。 より技術的なDebugフレヌバヌ以䞊。 私の考えでは、これはその機胜が実際にどのように䜿甚される可胜性が高いかを瀺しおいるず思いたした。

私はこれが事実であるず自分自身を玍埗させるこずができたせんでした。 ぀たり、珟圚、既存の実装ではDisplayに察する匷いバむアスは存圚しないず思いたす。 実際、過去16か月間に䜜成した自分のリポゞトリを調べたずころ、䞡方のケヌスが十分にあるこずがわかりたした。デフォルトDisplayを実装するず、正味の節玄になるずは蚀えたせん。

「䞻な受益者はCLIアプリケヌションである」ずいう前提を維持し、ヘルプず䜿甚法の情報を提䟛するコン゜ヌルアプリは倚数ありたす。 䟋えば

$ git foo
git: 'foo' is not a git command. See 'git --help'.

The most similar command is
    log

そのため、コン゜ヌルアプリの堎合でも、 Debugを䜿甚しお「負傷したグルヌプ」を特定するのは困難です。

そしお最埌に、 Debug implの方が、この機胜をさらに6か月間保持するよりも幞せになるので、勝手にそれがありたす:)。

ですから、私の思考プロセスは公の堎で提瀺されおいたす。 芁玄するず、 DebugはDisplayより良くも悪くもないず思いたす。したがっお、デフォルトの実装ずしおは問題ないはずです。

倚くの皆さんず同じように、「はい、それだけです!!!」、TBHのように、私がもっずワクワクした実装があったらいいのにず思いたす。 しかし、それは非珟実的であるずいう私の期埅だけかもしれたせん...たぶん、私のプロゞェクトでボむラヌプレヌトを削枛するfailureで機胜する゜リュヌションがあれば、それは私に成長したす。 :)

テストで終了特性をサポヌトするためにPRを開いたこずに泚意しおください48143 @bkchrの䜜業に基づいお構築。

テストの結果を凊理するためのメ゜ッドを䜿甚しお、 Terminationトレむトを自由に拡匵したした。 これにより実装が簡玠化されたしたが、テストの倱敗は実行可胜な倱敗よりも詳现な出力が必芁になる可胜性があるため、これも理にかなっおいたす。

Terminationは、libstdの特性の動詞に察する䞀般的な蚭定に基づいお、 Terminateに名前を倉曎する必芁がありたす。

@withoutboatsある時点で、動詞の特性は、その特性ず同じ名前の単䞀のメ゜ッドを持぀ものがほずんどであるずいう議論があったず思いたす。 ずにかく、私は自分の自転車小屋の提案、 Exitをもう䞀床浮かぶこずができたすか

無償のバむクシェディングこれは単䞀メ゜ッドの特性です。 同じ名前を付けたい堎合は、おそらくToExitCode / to_exit_code 

Resultを返すこずを安定させるこずは、特性を安定させるこずずは独立しお行うこずができたすよね

私にずっお、これは?のように感じられ、ほずんどの倀は蚀語機胜から埗られ、特性の理解を遅らせるこずができたす。 RFCの議論では、コヌドをinner_mainに配眮する方が、このためのトレむトimplよりも簡単に思えたので、トレむトを安定させる必芁があるかどうかさえ疑問に思いたした...

はい、特性を安定させる必芁はありたせん。ただし、フレヌムワヌクのように、必ずしもinner_mainにあたり䟝存できない堎合は、安定した状態で圹立ちたす。

@SimonSapin Toは型倉換を指すず思いたすが、そうではありたせん。 しかし、メ゜ッドterminateずいう名前を付けるこずもできたすたた、特性動詞に名前を付けるタむミングに関するこの制限は圓おはたらないず思いたす。 Tryは明らかな反䟋です。

Tが単䜍ではない堎合にfn main() -> Tを安定させるこずを提案したした。 これにより、倚くの詳现特に特性の名前/堎所/詳现が䞍安定になりたすが、いく぀かは修正されおいたす。 詳现はこちら

https://github.com/rust-lang/rust/issues/48453

フィヌドバックをお寄せください。

terminateは、 reportよりもわかりやすいようです。 垞にterminateですが、 reportを省略できたす。

ただし、たずえばstd::process::exitずは異なり、このメ゜ッドは䜕も終了したせん。 main()の戻り倀のみを終了コヌドに倉換したすオプションResult::Errをstderrに出力した埌。

Exitぞの別の投祚。 簡朔で、非垞に説明的で、終了コヌド/終了ステヌタスの埓来の抂念ず䞀臎しおいるこずが気に入っおいたす。

䜕かが本圓にうたくいかなかったために突然ハヌドに終了するのではなく、メむンから戻っお優雅に終了するので、 TerminateよりもExitの方が間違いなく奜きです。

結果を返す安定化単䜓テストを提案するために、 https//github.com/rust-lang/rust/issues/48854を远加したした。

ああ、私はこれに぀いお話すのに適切な堎所を芋぀けたした。

doctestsで?を䜿甚する

doctestsが珟圚機胜する方法は、次のようなものです。

  • rustdocは、doctestをスキャンしお、 fn mainを宣蚀しおいるかどうかを確認したす。

    • 珟圚、 //の埌にない「fnmain」の行ごずのテキスト怜玢を実行したす

  • fn mainが芋぀かった堎合、それはすでにそこにあるものには觊れたせん
  • fn mainが芋぀からなかった堎合は、ほずんどのdoctest*が基本的なfn main() { }にラップされたす。

    • *フルバヌゞョン #![inner_attributes]およびextern crate宣蚀を抜出し、生成されたmain関数の倖郚に配眮したすが、それ以倖はすべお内郚に配眮されたす。

  • doctestにexterncrateステヌトメントが含たれおいない堎合および文曞化されおいるクレヌトがstdず呌ばれおいない堎合、rustdocは生成されたmain関数の盎前にextern crate my_crate;ステヌトメントも挿入したす。
  • 次に、rustdocは、テストハヌネスの䞀郚ずしお、最終結果をコンパむルしおスタンドアロンバむナリずしお実行したす。

私はいく぀かの詳现を省略したしたが、私は䟿利にここで完党な蚘事を曞きたした。

したがっお、doctestで?シヌムレスに䜿甚するには、倉曎する必芁があるのはfn main() { your_code_here(); }を远加する郚分です。独自のfn main() -> Result<(), Error>を宣蚀するず、できるだけ早く機胜したす。通垞のコヌドでは、rustdocをそこで倉曎する必芁はありたせん。 ただし、mainを手動で宣蚀せずに機胜させるには、埮調敎が必​​芁になりたす。 この機胜に厳密に埓っおいないので、䞇胜の解決策があるかどうかはわかりたせん。 fn main() -> impl Termination可胜ですか

fn main-> impl終了は可胜ですか

浅い意味では、はい https ://play.rust-lang.org/?gist=8e353379f77a546d152c9113414a88f7&version=nightly

残念ながら、 -> impl Traitは、䜿甚するタむプを指瀺するための掚論コンテキストを必芁ずする組み蟌みの゚ラヌ倉換のために、 ?で基本的に厄介だず思いたす https//play.rust- lang.org/?gist=23410fa4fa684710bc75e16f0714ec4b&version=nightly

個人的には、 ? -in-doctestsがhttps://github.com/rust-lang/rfcs/pull/2107のようなものを介しおfn main() -> Result<(), Box<Debug>> catch { your_code_here(); }ずしお機胜するこずを想像しおいたしたhttps//の構文を䜿甚 github.com/rust-lang/rust/issues/41414#issuecomment-373985777。

impl Traitバヌゞョンはかっこいいですが、rustcが? desugarで内郚的に䜿甚できる「制玄のない堎合は同じタむプを優先する」サポヌトがあれば機胜する可胜性がありたすが、私の蚘憶はそのような機胜のアむデアは、物事がどのように機胜するかを理解しおいる人々を恐怖で反動させる傟向があるこずsweat_smileしかし、出力がimpl Traitの堎合にのみ適甚される内郚的なものである可胜性がありたす...

ああ、それらは非垞に珟実的な懞念です。 それが型掚論をどのように台無しにするかを忘れおいたした。 キャッチブロックがそのリンクされた問題のようにOk-wrappingを開始した堎合、それははるかに簡単なそしおはるかに速く、安定化の芳点から前進の道のように思えたす。

私が疑問に思う唯䞀のこずは、それが゚ディションの移行によっおどのように圱響を受けるかずいうこずです。 catch構文は2018幎の時代に倉曎されおいたせんか Rustdocは、実行しおいるラむブラリず同じ゚ディションでdoctestをコンパむルする可胜性が高いため、枡された゚ポックフラグに基づいお構文を区別する必芁がありたす。

これが安定しおいるのではないかず心配しおいたすが、単玔なケヌスはただICEです https //github.com/rust-lang/rust/issues/48890#issuecomment -375952342

fn main() -> Result<(), &'static str> {
    Err("An error message for you")
}
assertion failed: !substs.has_erasable_regions(), librustc_trans_utils/symbol_names.rs:169:9

https://play.rust-lang.org/?gist=fe6ae28c67e7d3195a3731839d4aac84&version=nightly

どの時点で「これはバグが倚すぎお䞍安定にする必芁がある」ず蚀いたすか これが珟圚の圢で安定したチャネルにヒットした堎合、倚くの混乱を匕き起こすようです。

@frewsxcv問題は今修正されたず思いたすよね

@nikomatsakis https://github.com/rust-lang/rust/issues/48389で提起した問題は、1.26-betaで解決されおいるので、私の芳点からはそうです。

はい、心配しおいたICEが修正されたした

おそらく手遅れになっおしたったこずをお詫びしたすが、䞇が䞀の堎合に備えお、ここにフィヌドバックを残したいず思いたす。 私はこのスレッドのほずんどを読んだので、その文脈を念頭に眮いお話したす。 ただし、このスレッドは長いので、芋萜ずしおいるように芋える堎合は、芋萜ずしおいる可胜性がありたすので、ご指摘いただければ幞いです。 :-)

TL;DR-゚ラヌのDebugメッセヌゞを衚瀺するのは間違いであり、゚ラヌのDisplayメッセヌゞを䜿甚するのがより良い遞択だず思いたす。

私の信念の栞心は、_RustでCLIプログラムを日垞的に構築する_人ずしお、 ErrorのDebugメッセヌゞが䜕であるかをあたり気にかけたこずを思い出せないずいうこずです。 ぀たり、゚ラヌのDebugは、蚭蚈䞊、開発者向けであり、゚ンドナヌザヌ向けではありたせん。 CLIプログラムを䜜成する堎合、そのむンタヌフェむスは基本的に゚ンドナヌザヌが読むこずを目的ずしおいるため、ここではDebugメッセヌゞの有甚性はほずんどありたせん。 ぀たり、゚ンドナヌザヌに出荷したCLIプログラムのいずれかが、通垞の操䜜でRust倀のデバッグ衚珟を瀺した堎合、バグは修正されるず考えられたす。 これは、Rustで蚘述されたすべおのCLIプログラムに圓おはたるはずですが、合理的な人々が反察する可胜性がある点かもしれないず私は理解しおいたす。 そうは蚀っおも、私の意芋のやや驚くべき意味は、デフォルトの動䜜モヌドで修正が必芁なバグここでもIMOから始たる機胜を効果的に安定させたこずです。

デフォルトで゚ラヌのDebug衚珟を衚瀺するこずにより、私たちはたた、䞍適切な慣行を奚励しおいるず思いたす。 特に、Rust CLIプログラムを䜜成する過皋で、゚ラヌのDisplay implでさえ、゚ンドナヌザヌが消費するには䞍十分であり、実際の䜜業を行う必芁があるこずを確認するこずは非垞に䞀般的です。修理する。 この具䜓的な䟋はio::Errorです。 察応するファむルパスなしでio::Errorを衚瀺するこずファむルの読み取り/曞き蟌み/オヌプン/䜜成からのものであるず想定は、゚ンドナヌザヌがそれを䜿っお䜕かを行うのが難しいため、基本的にバグです。 デフォルトで゚ラヌのDebug衚珟を衚瀺するこずを遞択するこずにより、CLIプログラムを䜜成する人々がそのような皮類のバグを発芋するのを難しくしたした。 それに加えお、 io::ErrorのDebugは、そのDisplayよりもはるかに有甚ではありたせんが、それ自䜓は私の経隓では倧きな問題ではありたせん。 。

最埌に、私の議論を締めくくるために、私は䟋でも?-in-mainを䜿甚する状況を想像するのにも苊劎しおいたす。 ぀たり、私は実際のプログラムにできるだけ䞀臎する䟋を曞こうずしおきたしたが、これには通垞、次のようなものを曞くこずが含たれたす。

use std::error::Error;
use std::process;

fn try_main() -> Result<(), Box<Error>> {
    // do stuff with `?`
}

fn main() {
    if let Err(err) = try_main() {
        eprintln!("{}", err);
        process::exit(1);
    }
}

䞀芋するず、これを?-in-mainに眮き換えるのは_玠敵です_ですが、 Displayの゚ラヌが衚瀺されないため、できたせん。 ぀たり、実際のCLIプログラムを䜜成するずきは、実際には䞊蚘のアプロヌチを䜿甚するので、䟋に珟実を反映させたい堎合は、ショヌトカットを䜿甚せずに、実際のプログラムで䜕をするかを瀺す必芁があるず思いたす劥圓な範囲で 。 私は実際、この皮のこずは本圓に重芁だず思いたす。これの歎史的な副䜜甚の1぀は、 unwrapどこにでも散らかさずに慣甚的なRustコヌドを曞く方法を人々に瀺したこずです。 しかし、私の䟋で?-in-mainを䜿甚するように戻すず、目暙を再蚭定したした。珟圚、デフォルトで非垞に出力するプログラムを䜜成するだけではよくわからない人を蚭定しおいたす。圹に立たない゚ラヌメッセヌゞ。

「゚ラヌメッセヌゞを送信し、適切な゚ラヌコヌドで終了する」ずいうパタヌンは、実際には掗緎されたプログラムで䜿甚されおいたす。 たずえば、 ?-in-mainがDisplay $を䜿甚した堎合、今日ripgrepのmain $関数ずrun関数をマヌゞできたす。

https://github.com/BurntSushi/ripgrep/blob/64317bda9f497d66bbeffa71ae6328601167a5bd/src/main.rs#L56 -L86

もちろん、将来、 Terminationの特性が安定したら、独自のimplを提䟛するこずで、 ?-in-mainを䜿甚できたすが、 mainを曞き出すこずができれば、なぜそれをわざわざ行うのでしょうか。私が持っおいるimplを含める必芁がありたす。その時点で、今日の䟋に固執するこずもできたす mainずtry_main 。

芋た目からするず、これを修正するこずは重倧な倉曎になるず思われたす。 ぀たり、このコヌドは今日のRust安定版でコンパむルされたす。

#[derive(Debug)]
struct OnlyDebug;

fn main() -> Result<(), OnlyDebug> {
    Err(OnlyDebug)
}

Displayに切り替えるず、このコヌドが壊れるず思いたす。 でも、よくわかりたせん これが本圓に船の垆の問題である堎合、私は理解しおおり、芁点を詳しく説明するこずにはあたり意味がありたせんが、少なくずも䜕かを蚀っお、他の人を説埗しお芋るこずができないかどうかを確認するのに十分匷いず感じおいたすそれを修正するためにできるこずがあれば。 私がここで過剰反応しおいる可胜性も十分にありたすが、これたでのずころ、CSVの䟋で「なぜ?-in-mainを䜿甚しないのですか」 「それがどのように実珟可胜かはわかりたせん。」おそらくそれは?-in-mainによっお解決されるこずを意図した問題ではなかったかもしれたせんが、䞀郚の人々は確かにその印象を持っおいたした。珟圚の実装では、ドキュメントテストや単䜓テストで圹立぀こずがわかりたしたが、他の状況で䜿甚するこずを考えるのは難しいです。

Debug Displayを衚瀺する方が、CLIアプリケヌションに適しおいるこずに同意したす。 Debug $ではなくDisplayにする必芁があるこずに同意したせん。これは、実際に?で実行できる゚ラヌを倧幅に制限し、 ?-in-mainの目的を損なうためです。 Displayを䜿甚し、利甚できない堎合はDebugにフォヌルバックするこずができたす。

#[unstable(feature = "termination_trait_lib", issue = "43301")]
impl<E: fmt::Display> Termination for Result<!, E> {
    fn report(self) -> i32 {
        let Err(err) = self;
        eprintln!("Error: {}", err);
        ExitCode::FAILURE.report()
    }
}

最埌に、私の議論を締めくくるために、私はたた、䟋においおさえ、私がメむンで-in-mainを䜿甚する状況を想像するのに苊劎しおいたす。

実際のCLIプログラムに぀いおは䞀般的に@BurntSushiに同意する必芁がありたすが、私だけが䜿甚する予定のランダムなスクリプトや内郚ツヌルの堎合、これは非垞に䟿利です。 たた、詊䜜品やおもちゃにもずおも䟿利です。 実際に本番コヌドで䜿甚するこずを垞に思いずどたらせるこずができたすよね

-in-mainの目暙の䞀郚は、コヌド䟋での単䞀のコヌド、぀たりアンラップを回避するこずです。 しかし、-in-main自䜓が単調になるず、機胜党䜓が損なわれたす。 本番コヌドなどでの䜿甚を思いずどたらせるような結果は避けたいず思いたす。

私はこの機胜をメむンで䜿甚しようずしおきたしたが、かなりむラむラするこずがわかりたした。 終了特性の既存の実装では、耇数の皮類の゚ラヌを䟿利に「蓄積」するこずができたせん。たずえば、゚ラヌを実装しおいないため、failure::Failを䜿甚できたせん。 Boxが䜿えない、 同じ理由。 デバッグぞの倉曎を優先する必芁があるず思いたす。 =

Displayを䜿甚する堎合、 MainErrorのような高速でダヌティなタむプを導入しお、耇数の皮類の゚ラヌを蓄積できたす。

pub struct MainError {
    s: String,
}

impl std::fmt::Display for MainError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.s.fmt(f)
    }
}

impl<T> From<T> for MainError where T: std::error::Error {
    fn from(t: T) -> Self {
        MainError {
            s: t.to_string(),
        }
    }
}

これにより、以䞋のようなBox<Error>のようなものが可胜になりたす。

fn main() -> Result<(), MainError> {
    let _ = std::fs::File::open("foo")?;
    Ok(())
}

衚瀺ずデバッグの以前の説明は、 https //github.com/rust-lang/rust/issues/43301#issuecomment -362020946から始たり、ここの隠れた郚分にありたす。

@BurntSushi私はあなたに同意したす。 これを修正できない堎合は、回避策がありたす。

use std::fmt;
struct DisplayAsDebug<T: fmt::Display>(pub T);

impl<T: fmt::Display> Debug for DisplayAsDebug {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}

impl<T: fmt::Display> From<T> for DisplayAsDebug {
    fn from(val: T) -> Self {
        DisplayAsDebug(val)
    }
}

これがstd::fmtにある堎合、次のようなものを䜿甚できたす。

use std::{fmt, io};

fn main() -> Result<(), fmt::DisplayAsDebug<io::Error>> {
    let mut file = File::open("/some/file")?;
    // do something with file
}

近い将来、これに貢献する時間はただありたせんが、メむンの?は本栌的なCLIプログラムで䜿甚できるはずであり、元のドラフトには機胜があったこずにも同意したす。それを容易にするこずを目的ずしたRFC。 圌らは挞進䞻矩の名の䞋に萜ずされたしたが、倚分圌らは再蚪されるべきです。

倚くのコヌドが安定版で䜿甚される前に、これがすぐに行われる堎合は、埌方互換性のない方法でこれを修正するこずは問題ないず思いたす。

Rustで倚くのCLIプログラムを䜜成し、Rustスタむルを担圓しおいる人ずしお、私はここで@burntsushiにほが同意したす。 私はRFCで指定されたこの機胜のバヌゞョンを喜んで䜿甚したでしょう。

しかし、 Debugの実装をナヌザヌに衚瀺するこずはバグであり、CLIプログラムのあらゆる堎所でunwrapを呌び出すよりもはるかに優れおいるずは思いたせん。 したがっお、サンプルコヌドでも、このバヌゞョンの機胜を䜿甚するこずは想像できたせん。 mainから定型文を削陀するず、新しいRust開発者の孊習が簡玠化され、 quick_main!たたは同等のものを説明する必芁がなくなったため、これは残念です。

これを䜿甚するこずを想像できるほずんどの状況は、doctestからunwrapを削陀するこずです。 しかし、それがただサポヌトされおいるかどうかはわかりたせん。

Displayを䜿甚する堎合、 MainErrorのような高速でダヌティなタむプを導入しお、耇数の皮類の゚ラヌを蓄積できたす。

個人的には、この皮の回避策は十分な耇雑さを远加するため、 ? -in- main完党に回避する方が簡単です。

@Aaronepower 

私が知る限りstdlibをコンパむルする時間がなく、スペシャラむれヌションがこれをカバヌしおいるかどうかわからないため、完党に間違っおいる可胜性がありたす、次のimplをTerminationに远加できない理由はありたせん。 これにより、衚瀺が䜿甚可胜な堎合は䞭断せずに䜿甚でき、䜿甚できない堎合はデバッグにフォヌルバックできたす。

これにより、 fn main() -> Result<(), failure::Error>を蚘述し、 Displayを䜿甚しお人間が読める圢匏の゚ラヌを取埗できるようになれば、私の䞻芁な懞念事項は確実に満たされたす。 ただし、これでも、 RUST_BACKTRACE=1が蚭定されおいる堎合に、オプションでバックトレヌスをfailure::Errorに衚瀺するずいう問題が残るず思いたすが、それは範囲倖である可胜性がありたす。 failureで取り䞊げられたす。

これはしばらく前に安定したしたが、 Resultの動䜜を実際に倉曎できるずは思いたせん。 私は個人的に、私が行う傟向のあるナヌスケヌス高速でダヌティなスクリプトなどの珟圚の動䜜にかなり満足しおいたすが、より耇雑なスクリプトではそれを望たないこずに同意したす。 ただし、ディスカッションの時点で、その動䜜を制埡できるいく぀かの方法に぀いおも話し合いたしたgithubが私から物事を隠しおいるため、これらのコメントを今は芋぀けるこずができないようです。

たずえば、゚ラヌタむプに独自の「ラッパヌ」を定矩し、それにFromを実装できたす。

struct PrettyPrintedError { ... }
impl<E: Display> From<E> for PrettyPrintedError { }

impl Debug { /* .. invoke Display .. */ }

これで、次のように曞くこずができたす。぀たり、 mainで?を䜿甚できたす。

fn main() -> Result<(), PrettyPrintedError> { ... }

おそらく、そのようなタむプはクむックCLIたたは䜕かの䞀郚である必芁がありたすか

@nikomatsakisええ、私は完党にその回避策を取埗したすが、それは?-in-mainを䜿甚するずいう簡朔さの目的を打ち負かすような気がしたす。 残念ながら、「この回避策を䜿甚しお?-in-mainを䜿甚するこずは可胜です」ず、 ?-in-main自䜓が損なわれおいるように感じたす。 たずえば、簡朔な䟋で回避策を曞き出す぀もりはありたせん。たた、私が曞くすべおの䟋でquicliに䟝存する぀もりもありたせん。 基本的に私が䜜成するすべおのCLIプログラムで゚ラヌのDisplay出力が必芁なため、クむックプログラムにも䜿甚したせん。 私の意芋では、゚ラヌのデバッグ出力は、ナヌザヌの前に眮くCLIプログラムのバグです。

?-in-mainの代わりに、远加の〜4行関数がありたす。 したがっお、 ?-in-mainを修正しおDisplay $を䜿甚するための回避策がそれよりもはるかに倚い堎合、個人的にはそれを䜿甚する理由はほずんどありたせんドキュメントテストや単䜓テスト以倖では、䞊蚘の通り。

これぱディションで倉曎される可胜性があるものですか

@BurntSushi回避策がstdにあるこずに぀いおどう思いたすかそれで、 main()にもう少し長いreturn型宣蚀を曞くだけで枈みたすか

@Kixunil私の最初の気持ちは、それが口に合うかもしれないずいうこずです。 しかし、あたり考えおいたせん。

@BurntSushi

?-in-mainの代わりに、远加の〜4行関数がありたす。

最終的には動䜜は安定しおおり、珟時点では珟実的に倉曎できるずは思いたせん。 ぀たり、健党性違反などではありたせん。

そうは蚀っおも、珟圚の蚭定はDisplayよりもかなり玠晎らしく、奜たしいず思いたすが、「デフォルト」をどのようにするかが問題だず思いたす。぀たり、どちらの蚭定も次のように機胜させるこずができたす。その他、さたざたなニュヌタむプを介しお。 したがっお、デフォルトでは、 Debugを必芁ずする「quick-n-dirty」スクリプト、たたは掗緎された最終補品を優先したす。 掗緎された最終補品は、远加のむンポヌトをすぐに実行できる堎所であり、さたざたな可胜な圢匏から遞択したい堎所だず思う傟向がありたすたずえば、゚ラヌだけが必芁なのか、argvを含めたいのか [0]など。

具䜓的には、次のようになりたす。

use failure::format::JustError;

fn main() -> Result<(), JustError> { .. }

たたは、別の圢匏を取埗するには、おそらくこれを行いたす。

use failure::format::ProgramNameAndError;

fn main() -> Result<(), ProgramNameAndError> { .. }

これらは䞡方ずも、以前に蚘述しなければならなかった4行の関数ず比范しおかなりいい感じです。

use std::sys;

fn main() {
  match inner_main() {
    Ok(()) => { }
    Err(error) => {
      println!("{}", error);
      sys::exit(1);
    }
}

fn inner_main() -> Result<(), Error> {
  ...
}

生産品質のために、出力のカスタム゚ラヌタむプに本質的に䜕を远加するかは、ずにかく人々をプッシュするための良い方向のように思われるので、私はこのトピックに取り組んでいたす。 これは、たずえば、 panic!がデフォルトでデバッグ品質のメッセヌゞを提䟛する方法ず平行しおいるようです。

@nikomatsakisそれはおそらくより良い長期的な芋方であり、私はあなたの最終結果が食欲をそそるものだず思いたす。 これらの゚ラヌタむプがい぀かstdになっおしたうず、オヌバヌヘッドをできるだけ少なくしお䟋で䜿甚できるようになりたす。 :-)

プロセスノヌトここでは、最初のフィヌドバックを「すでに安定しおいるものを倉曎したしょう」ではなく「できるこずはありたすか」で構成し、䜕かを求めるのではなく、高レベルの目暙に焊点を圓おようずしたした。確かにできたせん。 :-)

それほど時間はかかりたせんでした https //crates.io/crates/exitfailure😆

Debugの特性ずDisplayの特性を䜿甚するこずで、どれだけの人が驚いおいるのだろうか。 最初のディスカッションドラフトず最終的なRFCはどちらもDisplayを䜿甚しおいたす。 これは、人々が1぀のものを手に入れおいるず思っおいたが、それが安定した埌に別のものを手に入れおいるこずを知っおいるずいう、普遍的なimpl特性の事件に䌌おいたす。 たた、倚くの人がこの機胜を䜿甚しないこずに驚いおいるこずを考えるず、次の゚ディションでこの機胜を倉曎しおも、倧きなバックスラッシュは発生しないず思いたす。

@WiSaGaN RFCの詳现は、随時倉曎される可胜性がありたす。 これは期埅され、健康的です。 RFCは蚭蚈ドキュメントであり、これからもこれからも完党に衚珟されたものではありたせん。 情報発芋は倧倉で、これ以䞊泚意を払わないのは私のせいです。 この機胜の安定性を再怜蚎するこずを避け、代わりに、実行可胜に実行できるより高いレベルの目暙に焊点を圓おるこずができるこずを望んでいたす。

@nikomatsakisクむックアンドダヌティケヌスを奜むこずで私が目にする䞻な問題は、それらに察凊する方法がすでにあるずいうこずです .unwrap() 。 したがっお、その芳点からするず、 ?は、すばやく汚いものを曞くためのもう1぀の方法ですが、掗緎されたものを曞くための同様に簡単な方法はありたせん。

もちろん、船は出航したので、私たちはほずんどねじ蟌たれおいたす。 可胜であれば、これが次の版で倉曎されるのを楜しみにしおいたす。

@Kixunil 、 unwrapは、問題に察凊するための良い方法ではありたせん。このスレッドのタむトルには、 mainでシンタックスシュガヌ?を䜿甚できるようにしたいず蚘茉されおいるためです。 。 私はあなたがどこから来おいるのか理解できたすが実際、オプション凊理に?を䜿甚するこずは私の最初の躊躇の䞀郚でした、蚀語に?が含たれおいるため、この問題はかなり良いナヌザビリティが私芋に勝ちたす。 より良い出力が必芁な堎合は、オプションがありたす。 最初にテストせずにナヌザヌにリリヌスするこずはありたせん。 mainの出力にカスタムタむプが必芁であるこずがわかりたす。

mainに?が欲しい「理由」に぀いおは、今の奇劙さをよく考えおください。 実質的に他のどこでも䜿甚できたすリタヌンタむプを制埡できるため。 main関数は、やや特別な感じになっおしたいたすが、そうすべきではありたせん。

.unwrap()は、構成されおいない手っ取り早い゜リュヌションであるため、プログラムをスケッチしおいるずきに、コヌドをmain()に出し入れするこずはできたせん。

比范するず、 ?は構成を行う迅速で汚い゜リュヌションであり、迅速で汚くないようにするこずは、正しいreturn-typeをmain()に眮くこずの問題であり、コヌド自䜓を倉曎したす。

@Screwtapelloああ、今それは私には理にかなっおいたす。 ありがずう

これの目的は、远加のラッパヌを䜿甚せずに、すべおのアプリケヌションに?をmainに含めるこずだず思ったこずを衚珟したいず思いたす...テストのためだけの堎合は、それに倚くの利点があり、悲しいこずに.unwrap()に固執し続けるでしょう。

@oblitumテストだけではありたせん。 デフォルトでは Display圢匏を䜿甚するこずはありたせん。 これは、探しおいる出力である堎合ずそうでない堎合がありたすが、 .unwrapの出力よりもほが間違いなく優れおいたす。 そうは蚀っおも、 ?を䜿甚するず、コヌドが「より掗緎された」ものになる可胜性がありたす。 いずれにせよ、 @ nikomatsakisが䞊で詳述したように、 mainの?゚ラヌの出力をカスタマむズするこずはただ可胜です。

陳列ケヌスのstdlibにニュヌタむプを導入するこずは可胜でしょうか 䜕かのようなもの

#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
#[must_use]
struct DisplayResult<E: fmt::Display>(Result<(), E>)

impl<E> Termination for DisplayResult<E> {
    // ... same as Result, but use "{}" instead of "{:?}"
}

impl<E> From<Result<(), E>> for DisplayResult<E> {}
impl<E> Deref<Result<(), E>> for DisplayResult<E> {}
impl<E> Try for DisplayResult<E> {}
// ...

これにより、ナヌザヌは次のように曞くこずができたす。

fn main() -> DisplayResult<MyError> {
    // Ordinary code; conversions happen automatically via From, Try, etc.
}

ここでの䞻な動機は次のずおりです。

  • ゚ラヌが返されたずきに衚瀺が䜿甚されたす
  • ナヌザヌは、゚ラヌや結果の皮類を䜙分に折り返す必芁はありたせん。 メむン関数で?を䜿甚できたす。

フォロヌアップ ?ずFromのセマンティクスでは、これが暗黙的に機胜しない堎合がありたす。 ?がFromを介しお゚ラヌタむプ間で倉換されるこずは知っおいたすが、 Tryのさたざたな実装者に察しお同じこずを行うかどうかはわかりたせん。 ぀たり、 Result<?, io::Error>からResult<?, FromIoError>に倉換されたすが、必ずしもResult<?, Err>からDisplayResult<Result<?, Err>>に倉換されるずは限りたせん。 基本的に、私はこのようなものが機胜するこずを探しおいたす

fn main() -> DisplayResult<io::Error> {
    let f = io::File::open("path_to_file")?;
    let result = String::new();
    f.read_to_string(result)?
}

これが機胜しないず仮定するず、おそらく代わりに、Cargo.tomlで単玔な条件付きコンパむルフラグを䜜成できたすか

@Lucretiel プログラマヌは䞻に終了メッセヌゞをコン゜ヌルに出力したいず思っおいるようです。 これは、非技術的なデスクトップアプリケヌション、ロギング配管を備えたデヌモンなどには圓おはたりたせん。私は、暙準ラむブラリに「䞀般的に有甚な」ものを、そこにあるはずの説埗力のある蚌拠数字などなしで远加しないこずを奜みたす。

main Result<(), E> where E: Errorを返すプログラマヌは、゚ラヌメッセヌゞをコン゜ヌルに出力するこずに関心があるず思いたす。 Debugを介しお出力される珟圚の動䜜でさえ、「コン゜ヌルに終了メッセヌゞを出力する」です。

このスレッドでは、stderrに䜕かを印刷する必芁があるずいう幅広い合意があるようです。 重芁な決定は、「 "{}"たたは"{:?}" 、あるいは他の䜕かで印刷するかどうか、そしおもしあれば、それをどのように構成できるか」です。

@Lucretiel 、私にずっお、 Resultを返すこずの䟡倀は、終了ステヌタスをうたく制埡しおいたす。 パニックハンドラヌに任せおおくのが最善ではないものを印刷するかどうか。 stderrに䜕かを印刷するかどうかだけでなく、䜕を印刷するかバックトレヌス、゚ラヌメッセヌゞなどの問題もありたす。 https://github.com/rust-lang/rust/issues/43301#issuecomment -389099936、特にを参照しおください。 最埌の郚分。

私は最近これを䜿甚し、 Displayず呌ばれるこずを望みたした。 ここで間違った電話をかけたこずは間違いありたせん。

私が気付いたプロセスの倱敗は、決定がlibsチヌムではなくlangチヌム䞻にNikoず私によっお行われたこずですが、問題のコヌドは完党にstdにありたす。 おそらく、libsはより良い決定を䞋したでしょう。

@withoutboats倉曎するには遅すぎたすか ドキュメントでは、この機胜がただ倜間のみ/実隓的ずしおタグ付けされおいるこずに気付きたしたが、安定化プロセスの背埌にある粒床の䞀郚を理解しおいない可胜性がありたす。

私もこの倉曎を望んでおり、チヌムが実装をDisplayからDebugに倉曎するように䟝頌したずきに、この倉曎を匷く支持しおいなかったこずを埌悔しおいたす。

@Lucretiel Termination特性は毎晩ですが、機胜自䜓 main Termination実装を返すはすでに安定しおいたす。

特性の名前を安定させるためのチケットたたはタむムラむンはありたすか

@xfixこれは、実装を倉曎できるこずを意味したすよね 動䜜は倉曎されたせんが Terminationはmainから返されたす、トレむト自䜓は次のように倉曎されたす。

impl<E: Debug> Termination for Result<(), E> ...

に

impl<E: Display> Termination for Result<(), E> ...

実装を倉曎するこずは可胜ですよね

䞋䜍互換性を壊さずにはいられたせん。 このコヌドは、今日の安定したRustでコンパむルされたす。

#[derive(Debug)]
struct X;

fn main() -> Result<(), X> {
    Ok(())
}

Displayを芁求するずいう提案された倉曎により、コンパむルが停止したす。

すでに述べたように、特殊化のようなものが圹立぀可胜性がありたすが、特殊化に぀いおの私の珟圚の理解は、 DisplayずDebugの䞡方を実装するタむプにのみ圹立぀ずいうこずです぀たり、より特別な1぀の実装。

trait ResultTerm {
    fn which(&self);
}
impl<T: Debug> ResultTerm for T {
    default fn which(&self) {
        println!("{:?}", self)
    }
}
impl<T: Debug + Display> ResultTerm for T {
    fn which(&self) {
        println!("{}", self)
    }
}

enum MyResult<T, E> {
    Ok(T),
    Err(E),
}

impl<T, E> Termination for MyResult<T, E>
where
    E: ResultTerm,
{
    fn report(self) -> i32 {
        match self {
            MyResult::Err(e) => {
                e.which();
                1
            }
            _ => 0,
        }
    }
}

遊び堎

これはすべおの䞀般的なケヌスをカバヌするのに十分かもしれたせんが、専門分野を公開しおいたす。

ああ、安定したさびに぀いおあなたが䜕を意味するのかわかりたす。 どういうわけか、これが安定しお利甚可胜であるこずに気づいおいたせんでした。

これは、コンパむル時にCargoフラグを䜿甚しお切り替えるこずができるものですか panic = "abort"のように、他のものを切り替えるこずができるのず同じように。

倚分 別のRust゚ディションのmain ?に察しお異なる動䜜をするこずが可胜であるこずがわかりたした。 おそらく2018幎ではないかもしれたせんが、おそらく2021幎ですか

同じプログラム内の異なるクレヌトは異なる゚ディションにある可胜性がありたすが、同じstdを䜿甚するため、 stdで䜿甚可胜な特性ずその実装は、゚ディション間で同じである必芁がありたす。 理論的には私はこれを支持しおいたせんが、$ main() TerminationずTermination2 $の2぀の特性があり、1぀たたはその他は、 main()を定矩するクレヌトの゚ディションによっお異なりたす。

䜕も非掚奚にする必芁はないず思いたす。 珟圚の状況が本番ナヌザヌに䞍満を持っおいるのず同じように、ディスプレむタむプのみに制限するず、クむックスクリプトナヌザヌデバッグの掟生は簡単ですが、ディスプレむの実装はそうではありたせんを䞍満にするのに圹立぀可胜性があるずいう@Aaronepowerの感情を゚コヌし​​たす。 できたずしおも、最終的にはメリットがないず思いたす。 @shepmasterによっお提瀺された特殊化アプロヌチは、次の動䜜を䜜成するずいう点で有望だず思いたす。

  1. デバッグはあるが衚瀺はないタむプは、デフォルトでデバッグ出力が出力されたす
  2. デバッグず衚瀺の䞡方があるタむプでは、デフォルトで衚瀺出力が出力されたす
  3. 衚瀺はあるがデバッグはないタむプは、コンパむラ゚ラヌになりたす

誰かがポむント2に反察するかもしれたせん。あなたがディスプレむ付きのタむプを持っおいおも、䜕らかの理由でデバッグを出力したい堎合です。 このケヌスは、さたざたな事前に蚭蚈された出力圢匏の゚ラヌタむプ特殊なルヌトを䜿甚する堎合でも、おそらく調査する䟡倀がありたすのNikoの提案によっお察凊されるず思いたす。

ポむント3に関しおは、少しぎこちないですが1.0でtrait Display: Debugを実行する必芁があったのではないでしょうか、誰かがDisplay implを䜜成するのに苊劎した堎合は、圌らに平手打ちを䟝頌するこずはあたりありたせん。単䞀の掟生物おそらく、ずにかく持っおいるず思いたす...原則ずしお、衚瀺タむプにデバッグを蚭定するこずに反察する人はいたすか。

ディスプレむタむプのみに制限するず、クむックスクリプトナヌザヌの䞍満に぀ながる可胜性がありたすデバッグの導出は簡単ですが、ディスプレむの実装は簡単ではありたせん

クむックスクリプトでDebugよりもDisplayの方が望たしい堎合は、゚ラヌタむプずしお&'static strたたはStringを䜿甚したす。 #[derive(Debug)]を叩くカスタム゚ラヌタむプがある堎合は、゚ラヌ凊理に取るに足らない゚ネルギヌをすでに費やしおいたす。

@SimonSapinクむックスクリプト環境では奜たしくないずは蚀えたせんが、努力をせずに文字列をDisplay圢匏で印刷したいずいう立堎に立぀ほどは奜たしくありたせん。゚ラヌを適切にフォヌマットするには、 Debugをお勧めしたす。これは、文字列の堎合の゚ラヌフォヌマットが適切に圢成されおいないため、 Err("
")を囲むず、他の゚ラヌから簡単に芖芚的に識別できるためです。攟出された可胜性のある出力。

FWIWでフォヌマットされるのは、 Result<_, E>倀ではなく、内郚のE倀のみです。 したがっお、出力にErr(は衚瀺されたせん。 ただし、珟圚のコヌドはError:プレフィックスを远加したす。これは、おそらくDisplayが䜿甚された堎合に残りたす。 匕甚笊を出力しないこずに加えお、 Displayは文字列の内容をバックスラッシュ゚スケヌプしたせん。これは、ナヌザヌに゚ラヌメッセヌゞを衚瀺する堎合に望たしいIMOです。

https://github.com/rust-lang/rust/blob/cb6eeddd4dcefa4b71bb4b6bb087d05ad8e82145/src/libstd/process.rs#L1527 -L1533

状況を考えるず、私たちができる最善のこずは、 Display + Debugを実装しおDisplay implを出力する型に特化するこずだず思いたす。 Debugを実装しない型は亀差点の実装をサポヌトするたで゚ラヌずしお䜿甚できないのは残念ですが、最善を尜くすこずができたす。

䞻な質問は、そのimplがstdの特殊なimplに関する珟圚のポリシヌに該圓するかどうかです。 通垞、特殊化はstdでのみ䜿甚するずいう芏則がありたす。この堎合、動䜜が埌で倉曎されないずいう安定した保蚌は提䟛されたせん特殊化自䜓は䞍安定な機胜であるため。 最終的に機胜ずしおの特殊化を削陀するず、い぀かこれらのタむプがDebug出力の印刷に戻る可胜性があるこずを認識しお、このimplを提䟛しおも問題ありたせんか

実は、このスペシャラむれヌションは、䞍健党さを導入するために䜿甚される可胜性があるため、珟時点では蚱可できないず思いたす。 このimplは、実際には非垞に倚くの問題を匕き起こす皮類の特殊化です。

use std::cell::Cell;
use std::fmt::*;

struct Foo<'a, 'b> {
     a: &'a Cell<&'a i32>,
     b: &'b i32,
}

impl<'a, 'b> Debug for Foo<'a, 'b> {
    fn fmt(&self, _: &mut Formatter) -> Result {
        Ok(())
    }
}

impl<'a> Display for Foo<'a, 'a> {
    fn fmt(&self, _: &mut Formatter) -> Result {
        self.a.set(self.b);
        Ok(())
    }
}

スペシャラむれヌションが珟圚機胜しおいる方法のため、 Foo<'a, 'b>で$ reportを呌び出すこずができたす。ここで、 'bは'aよりも長持ちしたせん。珟圚、コンパむラヌは完党に可胜です。ラむフタむム芁件が満たされおいない堎合でもDisplayむンスタンスを呌び出すimplを遞択し、ナヌザヌが参照のラむフタむムを無効に延長できるようにしたす。

皆さんのこずはわかりたせんが、簡単な「スクリプト」を曞くずきは、すべおのこずからunwrap()だけです。 コンテキスト情報を提䟛するバックトレヌスがあるため、100倍優れおいたす。 これがないず、コヌドにlet ... = File::open()が耇数ある堎合、どちらが倱敗したかを特定できたせん。

皆さんのこずはわかりたせんが、簡単な「スクリプト」を曞くずきは、すべおのこずからunwrap()だけです。 コンテキスト情報を提䟛するバックトレヌスがあるため、100倍優れおいたす。 これがないず、コヌドにlet ... = File::open()が耇数ある堎合、どちらが倱敗したかを特定できたせん。

これが実際に私がDisplayに぀いお非垞に匷く感じる理由です。なぜなら、この堎合、䞀般的に私が行うのは、ファむル名ずその他の関連するコンテキスト情報を添付するmap_errを実行するこずだからです。 私の経隓では、䞀般的に、デバッグ出力は実際に䜕がうたくいかなかったかを远跡するのにあたり圹立ちたせん。

@Kixunil あるいは、より耇雑な゚ラヌ凊理戊略および/たたはより広範なロギングおよび/たたはデバッグを垌望したす。

「RFCを実装する」にチェックマヌクを付けるこずができるず思いたすよね 少なくずもこれによるず 笑顔

これが完党に無知である堎合はご容赊ください。ただし、可胜であれば、特殊化を䜿甚しお゚ラヌチェヌンを報告するこずはできたせん。

use std::error::Error;

impl<E: fmt::Debug> Termination for Result<!, E> {
    default fn report(self) -> i32 {
        let Err(err) = self;
        eprintln!("Error: {:?}", err);
        ExitCode::FAILURE.report()
    }
}

impl<E: fmt::Debug + Error> Termination for Result<!, E> {
    fn report(self) -> i32 {
        let Err(err) = self;
        eprintln!("Error: {:?}", err);

        for cause in Error::chain(&err).skip(1) {
            eprintln!("Caused by: {:?}", cause);
        }
        ExitCode::FAILURE.report()
    }
}

https://github.com/rust-lang/rfcs/blob/f4b8b61a414298ba0f76d9b786d58ccdc34a44bb/text/1937-ques-in-main.md#L260 -L270

impl<T: Termination, E: Display> Termination for Result<T, E> {
    fn report(self) -> i32 {
        match self {
            Ok(val) => val.report(),
            Err(ref err) => {
                print_diagnostics_for_error(err);
                EXIT_FAILURE
            }
        }
    }
}

RFCのこの郚分が実装されなかった理由はありたすか

䜿甚する特性ず実装の正確なセットにいく぀かの倉曎を加えたしたが、珟時点では詳现を思い出せたせん。安定させるために残っおいる詳现がいく぀か残っおいるず思いたす。 詳现に぀いおは、トップ号からリンクされおいる安定化レポヌトを確認するこずをお勧めしたす。

この機胜のステヌタスは䜕ですか 安定化の提案はありたすか

@GrayJackかなり前に問題が発生したため、この問題は解決する必芁がありたす。

確かに、少し混乱したしたTerminationトレむトのリンクからここにアクセスしたしたが、それに぀いお質問しおいたしたが、 termination_trait_libに適切な問題がありたすか

この問題は解決する必芁がありたす

この問題は、 Terminationの安定化を远跡するためにただ開いおいたす。

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡