From 734209ed73507e214e49ef5cb7988af8901e74c7 Mon Sep 17 00:00:00 2001 From: ThePuzzlemaker Date: Mon, 6 Sep 2021 16:11:28 -0500 Subject: Normalize assoc types when checking ret ty of main This fixes #88609. Previously, the return type of `fn main()` would not have any associated type projections within normalized before checking if it implements the standard library trait `std::process::Termination`. This commit appears to fix it. This feels vaguely symptomatic of a problem in the underlying trait solving engine, but I am not sure how I would solve that. I am unsure why the example in #88609 with `assert_impl_termination` and `fn foo()` work, but simply `fn main()` doesn't. The way that I solved this is also probably not the best way to do this, so please let me know if there is a better way to do this. I have added a build-pass regression test for this issue. --- compiler/rustc_typeck/src/lib.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'compiler') diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index 749f681e92e..e5d5ca3362b 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -109,6 +109,7 @@ use rustc_middle::util; use rustc_session::config::EntryFnType; use rustc_span::{symbol::sym, Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use rustc_trait_selection::traits::{ self, ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt as _, @@ -328,7 +329,22 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { ObligationCauseCode::MainFunctionType, ); let mut fulfillment_cx = traits::FulfillmentContext::new(); - fulfillment_cx.register_bound(&infcx, ty::ParamEnv::empty(), return_ty, term_id, cause); + // normalize any potential projections in the return type, then add + // any possible obligations to the fulfillment context. + // HACK(ThePuzzlemaker) this feels symptomatic of a problem within + // checking trait fulfillment, not this here. I'm not sure why it + // works in the example in `fn test()` given in #88609? This also + // probably isn't the best way to do this. + let normalized = infcx.partially_normalize_associated_types_in( + cause.clone(), + ty::ParamEnv::empty(), + return_ty, + ); + let new_ty = normalized.value; + for obligation in normalized.obligations { + fulfillment_cx.register_predicate_obligation(&infcx, obligation); + } + fulfillment_cx.register_bound(&infcx, ty::ParamEnv::empty(), new_ty, term_id, cause); if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { infcx.report_fulfillment_errors(&err, None, false); error = true; -- cgit 1.4.1-3-g733a5 From 33a28254f21c792cb0bda5427e66efa91b87dd4d Mon Sep 17 00:00:00 2001 From: ThePuzzlemaker Date: Mon, 6 Sep 2021 23:58:26 -0500 Subject: Clean up the fix a bit Use register_predicate_obligations rather than a for loop, since I didn't see that before. Also destructure in the `let` rather than projecting the fields individually --- compiler/rustc_typeck/src/lib.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'compiler') diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index e5d5ca3362b..e2cbaa47272 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -335,16 +335,20 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { // checking trait fulfillment, not this here. I'm not sure why it // works in the example in `fn test()` given in #88609? This also // probably isn't the best way to do this. - let normalized = infcx.partially_normalize_associated_types_in( - cause.clone(), + let InferOk { value: norm_return_ty, obligations } = infcx + .partially_normalize_associated_types_in( + cause.clone(), + ty::ParamEnv::empty(), + return_ty, + ); + fulfillment_cx.register_predicate_obligations(&infcx, obligations); + fulfillment_cx.register_bound( + &infcx, ty::ParamEnv::empty(), - return_ty, + norm_return_ty, + term_id, + cause, ); - let new_ty = normalized.value; - for obligation in normalized.obligations { - fulfillment_cx.register_predicate_obligation(&infcx, obligation); - } - fulfillment_cx.register_bound(&infcx, ty::ParamEnv::empty(), new_ty, term_id, cause); if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { infcx.report_fulfillment_errors(&err, None, false); error = true; -- cgit 1.4.1-3-g733a5