Rollup merge of #88706 - ThePuzzlemaker:issue-88609, r=jackh726
Normalize associated type projections when checking return type 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.
This commit is contained in:
commit
960e49e89b
2 changed files with 40 additions and 1 deletions
|
@ -107,6 +107,7 @@ 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 _,
|
||||||
|
@ -328,7 +329,26 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
|
||||||
ObligationCauseCode::MainFunctionType,
|
ObligationCauseCode::MainFunctionType,
|
||||||
);
|
);
|
||||||
let mut fulfillment_cx = traits::FulfillmentContext::new();
|
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 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,
|
||||||
|
);
|
||||||
if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) {
|
if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) {
|
||||||
infcx.report_fulfillment_errors(&err, None, false);
|
infcx.report_fulfillment_errors(&err, None, false);
|
||||||
error = true;
|
error = true;
|
||||||
|
|
19
src/test/ui/typeck/issue-88609.rs
Normal file
19
src/test/ui/typeck/issue-88609.rs
Normal file
|
@ -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!()
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue