Use ObligationCtxt in main fn return type check

This commit is contained in:
Michael Goulet 2022-07-26 03:18:45 +00:00
parent 6f18f0a9d4
commit da59fa74f0

View File

@ -112,7 +112,6 @@ use rustc_middle::util;
use rustc_session::config::EntryFnType; use rustc_session::config::EntryFnType;
use rustc_span::{symbol::sym, Span, DUMMY_SP}; use rustc_span::{symbol::sym, Span, DUMMY_SP};
use rustc_target::spec::abi::Abi; 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::error_reporting::InferCtxtExt as _;
use rustc_trait_selection::traits::{ use rustc_trait_selection::traits::{
self, ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt as _, self, ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt as _,
@ -303,7 +302,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
} }
let expected_return_type; let expected_return_type;
if let Some(term_id) = tcx.lang_items().termination() { if let Some(term_did) = tcx.lang_items().termination() {
let return_ty = main_fnsig.output(); let return_ty = main_fnsig.output();
let return_ty_span = main_fn_return_type_span(tcx, main_def_id).unwrap_or(main_span); let return_ty_span = main_fn_return_type_span(tcx, main_def_id).unwrap_or(main_span);
if !return_ty.bound_vars().is_empty() { if !return_ty.bound_vars().is_empty() {
@ -314,33 +313,17 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
} }
let return_ty = return_ty.skip_binder(); let return_ty = return_ty.skip_binder();
tcx.infer_ctxt().enter(|infcx| { tcx.infer_ctxt().enter(|infcx| {
// Main should have no WC, so empty param env is OK here.
let param_env = ty::ParamEnv::empty();
let cause = traits::ObligationCause::new( let cause = traits::ObligationCause::new(
return_ty_span, return_ty_span,
main_diagnostics_hir_id, main_diagnostics_hir_id,
ObligationCauseCode::MainFunctionType, ObligationCauseCode::MainFunctionType,
); );
let mut fulfillment_cx = traits::FulfillmentContext::new(); let ocx = traits::ObligationCtxt::new(&infcx);
// normalize any potential projections in the return type, then add let norm_return_ty = ocx.normalize(cause.clone(), param_env, return_ty);
// any possible obligations to the fulfillment context. ocx.register_bound(cause, param_env, norm_return_ty, term_did);
// HACK(ThePuzzlemaker) this feels symptomatic of a problem within let errors = ocx.select_all_or_error();
// 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 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(),
norm_return_ty,
term_id,
cause,
);
let errors = fulfillment_cx.select_all_or_error(&infcx);
if !errors.is_empty() { if !errors.is_empty() {
infcx.report_fulfillment_errors(&errors, None, false); infcx.report_fulfillment_errors(&errors, None, false);
error = true; error = true;