diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs index a6dae521db884..4c72f5a654e1d 100644 --- a/compiler/rustc_hir_analysis/src/check/entry.rs +++ b/compiler/rustc_hir_analysis/src/check/entry.rs @@ -7,22 +7,23 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::span_bug; use rustc_middle::ty::{self, TyCtxt, TypingMode}; use rustc_session::config::EntryFnType; -use rustc_span::Span; use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; +use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; +use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; use super::check_function_signature; use crate::errors; -pub(crate) fn check_for_entry_fn(tcx: TyCtxt<'_>) { +pub(crate) fn check_for_entry_fn(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { match tcx.entry_fn(()) { Some((def_id, EntryFnType::Main { .. })) => check_main_fn_ty(tcx, def_id), - _ => {} + _ => Ok(()), } } -fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { +fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) -> Result<(), ErrorGuaranteed> { let main_fnsig = tcx.fn_sig(main_def_id).instantiate_identity(); let main_span = tcx.def_span(main_def_id); @@ -87,20 +88,20 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { } } - let mut error = false; let main_diagnostics_def_id = main_fn_diagnostics_def_id(tcx, main_def_id, main_span); let main_asyncness = tcx.asyncness(main_def_id); if main_asyncness.is_async() { let asyncness_span = main_fn_asyncness_span(tcx, main_def_id); - tcx.dcx() - .emit_err(errors::MainFunctionAsync { span: main_span, asyncness: asyncness_span }); - error = true; + return Err(tcx + .dcx() + .emit_err(errors::MainFunctionAsync { span: main_span, asyncness: asyncness_span })); } if let Some(attr_span) = find_attr!(tcx, main_def_id, TrackCaller(span) => *span) { - tcx.dcx().emit_err(errors::TrackCallerOnMain { span: attr_span, annotated: main_span }); - error = true; + return Err(tcx + .dcx() + .emit_err(errors::TrackCallerOnMain { span: attr_span, annotated: main_span })); } if !tcx.codegen_fn_attrs(main_def_id).target_features.is_empty() @@ -108,12 +109,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { && !tcx.sess.target.is_like_wasm && !tcx.sess.opts.actually_rustdoc { - tcx.dcx().emit_err(errors::TargetFeatureOnMain { main: main_span }); - error = true; - } - - if error { - return; + return Err(tcx.dcx().emit_err(errors::TargetFeatureOnMain { main: main_span })); } // Main should have no WC, so empty param env is OK here. @@ -123,8 +119,9 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { let return_ty = main_fnsig.output(); let return_ty_span = main_fn_return_type_span(tcx, main_def_id).unwrap_or(main_span); let Some(return_ty) = return_ty.no_bound_vars() else { - tcx.dcx().emit_err(errors::MainFunctionReturnTypeGeneric { span: return_ty_span }); - return; + return Err(tcx + .dcx() + .emit_err(errors::MainFunctionReturnTypeGeneric { span: return_ty_span })); }; let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let cause = traits::ObligationCause::new( @@ -137,8 +134,16 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { ocx.register_bound(cause, param_env, norm_return_ty, term_did); let errors = ocx.evaluate_obligations_error_on_ambiguity(); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(errors); - error = true; + return Err(infcx.err_ctxt().report_fulfillment_errors(errors)); + } + + let region_errors = + infcx.resolve_regions(main_diagnostics_def_id, param_env, ty::List::empty()); + + if !region_errors.is_empty() { + return Err(infcx + .err_ctxt() + .report_region_errors(main_diagnostics_def_id, ®ion_errors)); } // now we can take the return type of the given main function expected_return_type = norm_return_ty; @@ -147,10 +152,6 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { expected_return_type = tcx.types.unit; } - if error { - return; - } - let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig( [], expected_return_type, @@ -159,7 +160,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { ExternAbi::Rust, )); - if check_function_signature( + check_function_signature( tcx, ObligationCause::new( main_span, @@ -168,26 +169,24 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { ), main_def_id, expected_sig, - ) - .is_err() - { - return; - } + )?; let main_fn_generics = tcx.generics_of(main_def_id); let main_fn_predicates = tcx.predicates_of(main_def_id); if main_fn_generics.count() != 0 || !main_fnsig.bound_vars().is_empty() { let generics_param_span = main_fn_generics_params_span(tcx, main_def_id); - tcx.dcx().emit_err(errors::MainFunctionGenericParameters { + return Err(tcx.dcx().emit_err(errors::MainFunctionGenericParameters { span: generics_param_span.unwrap_or(main_span), label_span: generics_param_span, - }); + })); } else if !main_fn_predicates.predicates.is_empty() { // generics may bring in implicit predicates, so we skip this check if generics is present. let generics_where_clauses_span = main_fn_where_clauses_span(tcx, main_def_id); - tcx.dcx().emit_err(errors::WhereClauseOnMain { + return Err(tcx.dcx().emit_err(errors::WhereClauseOnMain { span: generics_where_clauses_span.unwrap_or(main_span), generics_span: generics_where_clauses_span, - }); + })); } + + Ok(()) } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 5656c4566d9ff..734154238b1f7 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -2350,7 +2350,8 @@ pub(super) fn check_type_wf(tcx: TyCtxt<'_>, (): ()) -> Result<(), ErrorGuarante })) .and(items.par_nested_bodies(|item| tcx.ensure_result().check_well_formed(item))) .and(items.par_opaques(|item| tcx.ensure_result().check_well_formed(item))); - super::entry::check_for_entry_fn(tcx); + + super::entry::check_for_entry_fn(tcx)?; res } diff --git a/tests/ui/typeck/main-termination-lifetime-issue-148421.rs b/tests/ui/typeck/main-termination-lifetime-issue-148421.rs new file mode 100644 index 0000000000000..2c11de2883fd2 --- /dev/null +++ b/tests/ui/typeck/main-termination-lifetime-issue-148421.rs @@ -0,0 +1,15 @@ +// check-fail + +use std::process::ExitCode; +use std::process::Termination; + +trait IsStatic {} +impl<'a: 'static> IsStatic for &'a () {} + +struct Thing; + +impl Termination for Thing where for<'a> &'a (): IsStatic { + fn report(self) -> ExitCode { panic!() } +} + +fn main() -> Thing { Thing } //~ ERROR implementation of `IsStatic` is not general enough diff --git a/tests/ui/typeck/main-termination-lifetime-issue-148421.stderr b/tests/ui/typeck/main-termination-lifetime-issue-148421.stderr new file mode 100644 index 0000000000000..3d46e3df5f4a8 --- /dev/null +++ b/tests/ui/typeck/main-termination-lifetime-issue-148421.stderr @@ -0,0 +1,11 @@ +error: implementation of `IsStatic` is not general enough + --> $DIR/main-termination-lifetime-issue-148421.rs:15:14 + | +LL | fn main() -> Thing { Thing } + | ^^^^^ implementation of `IsStatic` is not general enough + | + = note: `IsStatic` would have to be implemented for the type `&'0 ()`, for any lifetime `'0`... + = note: ...but `IsStatic` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1` + +error: aborting due to 1 previous error +