about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_typeck/src/lib.rs18
-rw-r--r--src/test/ui/typeck/issue-88609.rs19
2 files changed, 36 insertions, 1 deletions
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;
diff --git a/src/test/ui/typeck/issue-88609.rs b/src/test/ui/typeck/issue-88609.rs
new file mode 100644
index 00000000000..dc459c885fa
--- /dev/null
+++ b/src/test/ui/typeck/issue-88609.rs
@@ -0,0 +1,19 @@
+// Regression test for #88609:
+// The return type for `main` is not normalized while checking if it implements
+// the trait `std::process::Termination`.
+
+// build-pass
+
+trait Same {
+    type Output;
+}
+
+impl<T> Same for T {
+    type Output = T;
+}
+
+type Unit = <() as Same>::Output;
+
+fn main() -> Result<Unit, std::io::Error> {
+    unimplemented!()
+}