mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-01 01:23:26 +00:00
Auto merge of #115897 - eduardosm:check-fn-sig, r=compiler-errors
rustc_hir_analysis: add a helper to check function the signature mismatches This function is now used to check `#[panic_handler]`, `start` lang item, `main`, `#[start]` and intrinsic functions. The diagnosis produced are now closer to the ones produced by trait/impl method signature mismatch. This is the first time I do anything with rustc_hir_analysis/rustc_hir_typeck, so comments and suggestions about things I did wrong or that could be improved will be appreciated.
This commit is contained in:
commit
99b63d068b
@ -11,8 +11,8 @@ use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
|
||||
|
||||
use std::ops::Not;
|
||||
|
||||
use super::check_function_signature;
|
||||
use crate::errors;
|
||||
use crate::require_same_types;
|
||||
|
||||
pub(crate) fn check_for_entry_fn(tcx: TyCtxt<'_>) {
|
||||
match tcx.entry_fn(()) {
|
||||
@ -162,33 +162,33 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
|
||||
error = true;
|
||||
}
|
||||
// now we can take the return type of the given main function
|
||||
expected_return_type = main_fnsig.output();
|
||||
expected_return_type = norm_return_ty;
|
||||
} else {
|
||||
// standard () main return type
|
||||
expected_return_type = ty::Binder::dummy(Ty::new_unit(tcx));
|
||||
expected_return_type = tcx.types.unit;
|
||||
}
|
||||
|
||||
if error {
|
||||
return;
|
||||
}
|
||||
|
||||
let se_ty = Ty::new_fn_ptr(
|
||||
tcx,
|
||||
expected_return_type.map_bound(|expected_return_type| {
|
||||
tcx.mk_fn_sig([], expected_return_type, false, hir::Unsafety::Normal, Abi::Rust)
|
||||
}),
|
||||
);
|
||||
let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig(
|
||||
[],
|
||||
expected_return_type,
|
||||
false,
|
||||
hir::Unsafety::Normal,
|
||||
Abi::Rust,
|
||||
));
|
||||
|
||||
require_same_types(
|
||||
check_function_signature(
|
||||
tcx,
|
||||
&ObligationCause::new(
|
||||
ObligationCause::new(
|
||||
main_span,
|
||||
main_diagnostics_def_id,
|
||||
ObligationCauseCode::MainFunctionType,
|
||||
),
|
||||
param_env,
|
||||
se_ty,
|
||||
Ty::new_fn_ptr(tcx, main_fnsig),
|
||||
main_def_id,
|
||||
expected_sig,
|
||||
);
|
||||
}
|
||||
|
||||
@ -247,27 +247,23 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
|
||||
}
|
||||
}
|
||||
|
||||
let se_ty = Ty::new_fn_ptr(
|
||||
tcx,
|
||||
ty::Binder::dummy(tcx.mk_fn_sig(
|
||||
[tcx.types.isize, Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8))],
|
||||
tcx.types.isize,
|
||||
false,
|
||||
hir::Unsafety::Normal,
|
||||
Abi::Rust,
|
||||
)),
|
||||
);
|
||||
let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig(
|
||||
[tcx.types.isize, Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8))],
|
||||
tcx.types.isize,
|
||||
false,
|
||||
hir::Unsafety::Normal,
|
||||
Abi::Rust,
|
||||
));
|
||||
|
||||
require_same_types(
|
||||
check_function_signature(
|
||||
tcx,
|
||||
&ObligationCause::new(
|
||||
ObligationCause::new(
|
||||
start_span,
|
||||
start_def_id,
|
||||
ObligationCauseCode::StartFunctionType,
|
||||
),
|
||||
ty::ParamEnv::empty(), // start should not have any where bounds.
|
||||
se_ty,
|
||||
Ty::new_fn_ptr(tcx, tcx.fn_sig(start_def_id).instantiate_identity()),
|
||||
start_def_id.into(),
|
||||
expected_sig,
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
|
@ -1,11 +1,11 @@
|
||||
//! Type-checking for the rust-intrinsic and platform-intrinsic
|
||||
//! intrinsics that the compiler exposes.
|
||||
|
||||
use crate::check::check_function_signature;
|
||||
use crate::errors::{
|
||||
UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction,
|
||||
WrongNumberOfGenericArgumentsToIntrinsic,
|
||||
};
|
||||
use crate::require_same_types;
|
||||
|
||||
use hir::def_id::DefId;
|
||||
use rustc_errors::{struct_span_err, DiagnosticMessage};
|
||||
@ -53,15 +53,12 @@ fn equate_intrinsic_type<'tcx>(
|
||||
&& gen_count_ok(own_counts.types, n_tps, "type")
|
||||
&& gen_count_ok(own_counts.consts, 0, "const")
|
||||
{
|
||||
let fty = Ty::new_fn_ptr(tcx, sig);
|
||||
let it_def_id = it.owner_id.def_id;
|
||||
let cause = ObligationCause::new(it.span, it_def_id, ObligationCauseCode::IntrinsicType);
|
||||
require_same_types(
|
||||
check_function_signature(
|
||||
tcx,
|
||||
&cause,
|
||||
ty::ParamEnv::empty(), // FIXME: do all intrinsics have an empty param env?
|
||||
Ty::new_fn_ptr(tcx, tcx.fn_sig(it.owner_id).instantiate_identity()),
|
||||
fty,
|
||||
ObligationCause::new(it.span, it_def_id, ObligationCauseCode::IntrinsicType),
|
||||
it_def_id.into(),
|
||||
sig,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -73,23 +73,31 @@ pub mod wfcheck;
|
||||
|
||||
pub use check::check_abi;
|
||||
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use check::check_mod_item_types;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_errors::{pluralize, struct_span_err, Diagnostic, DiagnosticBuilder};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_infer::infer::error_reporting::ObligationCauseExt as _;
|
||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||
use rustc_infer::infer::{self, TyCtxtInferExt as _};
|
||||
use rustc_infer::traits::ObligationCause;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{GenericArgs, GenericArgsRef};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::source_map::DUMMY_SP;
|
||||
use rustc_span::symbol::{kw, Ident};
|
||||
use rustc_span::{self, BytePos, Span, Symbol};
|
||||
use rustc_span::{self, def_id::CRATE_DEF_ID, BytePos, Span, Symbol};
|
||||
use rustc_target::abi::VariantIdx;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;
|
||||
use std::num::NonZeroU32;
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
|
||||
use rustc_trait_selection::traits::ObligationCtxt;
|
||||
|
||||
use crate::errors;
|
||||
use crate::require_c_abi_if_c_variadic;
|
||||
@ -546,3 +554,79 @@ fn bad_non_zero_sized_fields<'tcx>(
|
||||
pub fn potentially_plural_count(count: usize, word: &str) -> String {
|
||||
format!("{} {}{}", count, word, pluralize!(count))
|
||||
}
|
||||
|
||||
pub fn check_function_signature<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
mut cause: ObligationCause<'tcx>,
|
||||
fn_id: DefId,
|
||||
expected_sig: ty::PolyFnSig<'tcx>,
|
||||
) {
|
||||
let local_id = fn_id.as_local().unwrap_or(CRATE_DEF_ID);
|
||||
|
||||
let param_env = ty::ParamEnv::empty();
|
||||
|
||||
let infcx = &tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
|
||||
let actual_sig = tcx.fn_sig(fn_id).instantiate_identity();
|
||||
|
||||
let norm_cause = ObligationCause::misc(cause.span, local_id);
|
||||
let actual_sig = ocx.normalize(&norm_cause, param_env, actual_sig);
|
||||
|
||||
let expected_ty = Ty::new_fn_ptr(tcx, expected_sig);
|
||||
let actual_ty = Ty::new_fn_ptr(tcx, actual_sig);
|
||||
|
||||
match ocx.eq(&cause, param_env, expected_ty, actual_ty) {
|
||||
Ok(()) => {
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
let err_ctxt = infcx.err_ctxt();
|
||||
if fn_id.is_local() {
|
||||
cause.span = extract_span_for_error_reporting(tcx, err, &cause, local_id);
|
||||
}
|
||||
let failure_code = cause.as_failure_code_diag(err, cause.span, vec![]);
|
||||
let mut diag = tcx.sess.create_err(failure_code);
|
||||
err_ctxt.note_type_err(
|
||||
&mut diag,
|
||||
&cause,
|
||||
None,
|
||||
Some(infer::ValuePairs::Sigs(ExpectedFound {
|
||||
expected: tcx.liberate_late_bound_regions(fn_id, expected_sig),
|
||||
found: tcx.liberate_late_bound_regions(fn_id, actual_sig),
|
||||
})),
|
||||
err,
|
||||
false,
|
||||
false,
|
||||
);
|
||||
diag.emit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let outlives_env = OutlivesEnvironment::new(param_env);
|
||||
let _ = ocx.resolve_regions_and_report_errors(local_id, &outlives_env);
|
||||
|
||||
fn extract_span_for_error_reporting<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
err: TypeError<'_>,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
fn_id: LocalDefId,
|
||||
) -> rustc_span::Span {
|
||||
let mut args = {
|
||||
let node = tcx.hir().expect_owner(fn_id);
|
||||
let decl = node.fn_decl().unwrap_or_else(|| bug!("expected fn decl, found {:?}", node));
|
||||
decl.inputs.iter().map(|t| t.span).chain(std::iter::once(decl.output.span()))
|
||||
};
|
||||
|
||||
match err {
|
||||
TypeError::ArgumentMutability(i)
|
||||
| TypeError::ArgumentSorts(ExpectedFound { .. }, i) => args.nth(i).unwrap(),
|
||||
_ => cause.span(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +99,6 @@ use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
|
||||
use rustc_fluent_macro::fluent_messages;
|
||||
use rustc_hir as hir;
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_middle::middle;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
@ -107,8 +106,7 @@ use rustc_middle::util;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::{symbol::sym, Span, DUMMY_SP};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
|
||||
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCtxt};
|
||||
use rustc_trait_selection::traits;
|
||||
|
||||
use astconv::{AstConv, OnlySelfBounds};
|
||||
use bounds::Bounds;
|
||||
@ -151,28 +149,6 @@ fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi
|
||||
tcx.sess.emit_err(errors::VariadicFunctionCompatibleConvention { span, conventions });
|
||||
}
|
||||
|
||||
fn require_same_types<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
) {
|
||||
let infcx = &tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
match ocx.eq(cause, param_env, expected, actual) {
|
||||
Ok(()) => {
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
infcx.err_ctxt().report_mismatched_types(cause, expected, actual, err).emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
collect::provide(providers);
|
||||
coherence::provide(providers);
|
||||
|
@ -83,16 +83,6 @@ hir_typeck_int_to_fat_label_nightly = consider casting this expression to `*cons
|
||||
|
||||
hir_typeck_invalid_callee = expected function, found {$ty}
|
||||
|
||||
hir_typeck_lang_start_expected_sig_note = the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize`
|
||||
hir_typeck_lang_start_incorrect_number_params = incorrect number of parameters for the `start` lang item
|
||||
hir_typeck_lang_start_incorrect_number_params_note_expected_count = the `start` lang item should have four parameters, but found {$found_param_count}
|
||||
|
||||
hir_typeck_lang_start_incorrect_param = parameter {$param_num} of the `start` lang item is incorrect
|
||||
.suggestion = change the type from `{$found_ty}` to `{$expected_ty}`
|
||||
|
||||
hir_typeck_lang_start_incorrect_ret_ty = the return type of the `start` lang item is incorrect
|
||||
.suggestion = change the type from `{$found_ty}` to `{$expected_ty}`
|
||||
|
||||
hir_typeck_lossy_provenance_int2ptr =
|
||||
strict provenance disallows casting integer `{$expr_ty}` to pointer `{$cast_ty}`
|
||||
.suggestion = use `.with_addr()` to adjust a valid pointer in the same allocation, to this address
|
||||
|
@ -1,7 +1,6 @@
|
||||
use std::cell::RefCell;
|
||||
|
||||
use crate::coercion::CoerceMany;
|
||||
use crate::errors::{
|
||||
LangStartIncorrectNumberArgs, LangStartIncorrectParam, LangStartIncorrectRetTy,
|
||||
};
|
||||
use crate::gather_locals::GatherLocalsVisitor;
|
||||
use crate::FnCtxt;
|
||||
use crate::GeneratorTypes;
|
||||
@ -9,14 +8,15 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir_analysis::check::fn_maybe_err;
|
||||
use rustc_hir_analysis::check::{check_function_signature, fn_maybe_err};
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::RegionVariableOrigin;
|
||||
use rustc_middle::ty::{self, Binder, Ty, TyCtxt};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use rustc_trait_selection::traits;
|
||||
use std::cell::RefCell;
|
||||
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
|
||||
|
||||
/// Helper used for fns and closures. Does the grungy work of checking a function
|
||||
/// body and returns the function context used for that purpose, since in the case of a fn item
|
||||
@ -166,52 +166,17 @@ pub(super) fn check_fn<'a, 'tcx>(
|
||||
if let Some(panic_impl_did) = tcx.lang_items().panic_impl()
|
||||
&& panic_impl_did == fn_def_id.to_def_id()
|
||||
{
|
||||
check_panic_info_fn(tcx, panic_impl_did.expect_local(), fn_sig, decl, declared_ret_ty);
|
||||
check_panic_info_fn(tcx, panic_impl_did.expect_local(), fn_sig);
|
||||
}
|
||||
|
||||
if let Some(lang_start_defid) = tcx.lang_items().start_fn() && lang_start_defid == fn_def_id.to_def_id() {
|
||||
check_lang_start_fn(tcx, fn_sig, decl, fn_def_id);
|
||||
check_lang_start_fn(tcx, fn_sig, fn_def_id);
|
||||
}
|
||||
|
||||
gen_ty
|
||||
}
|
||||
|
||||
fn check_panic_info_fn(
|
||||
tcx: TyCtxt<'_>,
|
||||
fn_id: LocalDefId,
|
||||
fn_sig: ty::FnSig<'_>,
|
||||
decl: &hir::FnDecl<'_>,
|
||||
declared_ret_ty: Ty<'_>,
|
||||
) {
|
||||
let Some(panic_info_did) = tcx.lang_items().panic_info() else {
|
||||
tcx.sess.err("language item required, but not found: `panic_info`");
|
||||
return;
|
||||
};
|
||||
|
||||
if *declared_ret_ty.kind() != ty::Never {
|
||||
tcx.sess.span_err(decl.output.span(), "return type should be `!`");
|
||||
}
|
||||
|
||||
let inputs = fn_sig.inputs();
|
||||
if inputs.len() != 1 {
|
||||
tcx.sess.span_err(tcx.def_span(fn_id), "function should have one argument");
|
||||
return;
|
||||
}
|
||||
|
||||
let arg_is_panic_info = match *inputs[0].kind() {
|
||||
ty::Ref(region, ty, mutbl) => match *ty.kind() {
|
||||
ty::Adt(ref adt, _) => {
|
||||
adt.did() == panic_info_did && mutbl.is_not() && !region.is_static()
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if !arg_is_panic_info {
|
||||
tcx.sess.span_err(decl.inputs[0].span, "argument should be `&PanicInfo`");
|
||||
}
|
||||
|
||||
fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_>) {
|
||||
let DefKind::Fn = tcx.def_kind(fn_id) else {
|
||||
let span = tcx.def_span(fn_id);
|
||||
tcx.sess.span_err(span, "should be a function");
|
||||
@ -227,125 +192,87 @@ fn check_panic_info_fn(
|
||||
let span = tcx.def_span(fn_id);
|
||||
tcx.sess.span_err(span, "should have no const parameters");
|
||||
}
|
||||
|
||||
let Some(panic_info_did) = tcx.lang_items().panic_info() else {
|
||||
tcx.sess.err("language item required, but not found: `panic_info`");
|
||||
return;
|
||||
};
|
||||
|
||||
// build type `for<'a, 'b> fn(&'a PanicInfo<'b>) -> !`
|
||||
let panic_info_ty = tcx.type_of(panic_info_did).instantiate(
|
||||
tcx,
|
||||
&[ty::GenericArg::from(ty::Region::new_late_bound(
|
||||
tcx,
|
||||
ty::INNERMOST,
|
||||
ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrAnon(None) },
|
||||
))],
|
||||
);
|
||||
let panic_info_ref_ty = Ty::new_imm_ref(
|
||||
tcx,
|
||||
ty::Region::new_late_bound(
|
||||
tcx,
|
||||
ty::INNERMOST,
|
||||
ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) },
|
||||
),
|
||||
panic_info_ty,
|
||||
);
|
||||
|
||||
let bounds = tcx.mk_bound_variable_kinds(&[
|
||||
ty::BoundVariableKind::Region(ty::BrAnon(None)),
|
||||
ty::BoundVariableKind::Region(ty::BrAnon(None)),
|
||||
]);
|
||||
let expected_sig = ty::Binder::bind_with_vars(
|
||||
tcx.mk_fn_sig([panic_info_ref_ty], tcx.types.never, false, fn_sig.unsafety, Abi::Rust),
|
||||
bounds,
|
||||
);
|
||||
|
||||
check_function_signature(
|
||||
tcx,
|
||||
ObligationCause::new(
|
||||
tcx.def_span(fn_id),
|
||||
fn_id,
|
||||
ObligationCauseCode::LangFunctionType(sym::panic_impl),
|
||||
),
|
||||
fn_id.into(),
|
||||
expected_sig,
|
||||
);
|
||||
}
|
||||
|
||||
fn check_lang_start_fn<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
fn_sig: ty::FnSig<'tcx>,
|
||||
decl: &'tcx hir::FnDecl<'tcx>,
|
||||
def_id: LocalDefId,
|
||||
) {
|
||||
let inputs = fn_sig.inputs();
|
||||
fn check_lang_start_fn<'tcx>(tcx: TyCtxt<'tcx>, fn_sig: ty::FnSig<'tcx>, def_id: LocalDefId) {
|
||||
// build type `fn(main: fn() -> T, argc: isize, argv: *const *const u8, sigpipe: u8)`
|
||||
|
||||
let arg_count = inputs.len();
|
||||
if arg_count != 4 {
|
||||
tcx.sess.emit_err(LangStartIncorrectNumberArgs {
|
||||
params_span: tcx.def_span(def_id),
|
||||
found_param_count: arg_count,
|
||||
});
|
||||
}
|
||||
// make a Ty for the generic on the fn for diagnostics
|
||||
// FIXME: make the lang item generic checks check for the right generic *kind*
|
||||
// for example `start`'s generic should be a type parameter
|
||||
let generics = tcx.generics_of(def_id);
|
||||
let fn_generic = generics.param_at(0, tcx);
|
||||
let generic_ty = Ty::new_param(tcx, fn_generic.index, fn_generic.name);
|
||||
let main_fn_ty = Ty::new_fn_ptr(
|
||||
tcx,
|
||||
Binder::dummy(tcx.mk_fn_sig([], generic_ty, false, hir::Unsafety::Normal, Abi::Rust)),
|
||||
);
|
||||
|
||||
// only check args if they should exist by checking the count
|
||||
// note: this does not handle args being shifted or their order swapped very nicely
|
||||
// but it's a lang item, users shouldn't frequently encounter this
|
||||
let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig(
|
||||
[
|
||||
main_fn_ty,
|
||||
tcx.types.isize,
|
||||
Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8)),
|
||||
tcx.types.u8,
|
||||
],
|
||||
tcx.types.isize,
|
||||
false,
|
||||
fn_sig.unsafety,
|
||||
Abi::Rust,
|
||||
));
|
||||
|
||||
// first arg is `main: fn() -> T`
|
||||
if let Some(&main_arg) = inputs.get(0) {
|
||||
// make a Ty for the generic on the fn for diagnostics
|
||||
// FIXME: make the lang item generic checks check for the right generic *kind*
|
||||
// for example `start`'s generic should be a type parameter
|
||||
let generics = tcx.generics_of(def_id);
|
||||
let fn_generic = generics.param_at(0, tcx);
|
||||
let generic_ty = Ty::new_param(tcx, fn_generic.index, fn_generic.name);
|
||||
let expected_fn_sig =
|
||||
tcx.mk_fn_sig([], generic_ty, false, hir::Unsafety::Normal, Abi::Rust);
|
||||
let expected_ty = Ty::new_fn_ptr(tcx, Binder::dummy(expected_fn_sig));
|
||||
|
||||
// we emit the same error to suggest changing the arg no matter what's wrong with the arg
|
||||
let emit_main_fn_arg_err = || {
|
||||
tcx.sess.emit_err(LangStartIncorrectParam {
|
||||
param_span: decl.inputs[0].span,
|
||||
param_num: 1,
|
||||
expected_ty: expected_ty,
|
||||
found_ty: main_arg,
|
||||
});
|
||||
};
|
||||
|
||||
if let ty::FnPtr(main_fn_sig) = main_arg.kind() {
|
||||
let main_fn_inputs = main_fn_sig.inputs();
|
||||
if main_fn_inputs.iter().count() != 0 {
|
||||
emit_main_fn_arg_err();
|
||||
}
|
||||
|
||||
let output = main_fn_sig.output();
|
||||
output.map_bound(|ret_ty| {
|
||||
// if the output ty is a generic, it's probably the right one
|
||||
if !matches!(ret_ty.kind(), ty::Param(_)) {
|
||||
emit_main_fn_arg_err();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
emit_main_fn_arg_err();
|
||||
}
|
||||
}
|
||||
|
||||
// second arg is isize
|
||||
if let Some(&argc_arg) = inputs.get(1) {
|
||||
if argc_arg != tcx.types.isize {
|
||||
tcx.sess.emit_err(LangStartIncorrectParam {
|
||||
param_span: decl.inputs[1].span,
|
||||
param_num: 2,
|
||||
expected_ty: tcx.types.isize,
|
||||
found_ty: argc_arg,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// third arg is `*const *const u8`
|
||||
if let Some(&argv_arg) = inputs.get(2) {
|
||||
let mut argv_is_okay = false;
|
||||
if let ty::RawPtr(outer_ptr) = argv_arg.kind() {
|
||||
if outer_ptr.mutbl.is_not() {
|
||||
if let ty::RawPtr(inner_ptr) = outer_ptr.ty.kind() {
|
||||
if inner_ptr.mutbl.is_not() && inner_ptr.ty == tcx.types.u8 {
|
||||
argv_is_okay = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !argv_is_okay {
|
||||
let inner_ptr_ty =
|
||||
Ty::new_ptr(tcx, ty::TypeAndMut { mutbl: hir::Mutability::Not, ty: tcx.types.u8 });
|
||||
let expected_ty =
|
||||
Ty::new_ptr(tcx, ty::TypeAndMut { mutbl: hir::Mutability::Not, ty: inner_ptr_ty });
|
||||
tcx.sess.emit_err(LangStartIncorrectParam {
|
||||
param_span: decl.inputs[2].span,
|
||||
param_num: 3,
|
||||
expected_ty,
|
||||
found_ty: argv_arg,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// fourth arg is `sigpipe: u8`
|
||||
if let Some(&sigpipe_arg) = inputs.get(3) {
|
||||
if sigpipe_arg != tcx.types.u8 {
|
||||
tcx.sess.emit_err(LangStartIncorrectParam {
|
||||
param_span: decl.inputs[3].span,
|
||||
param_num: 4,
|
||||
expected_ty: tcx.types.u8,
|
||||
found_ty: sigpipe_arg,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// output type is isize
|
||||
if fn_sig.output() != tcx.types.isize {
|
||||
tcx.sess.emit_err(LangStartIncorrectRetTy {
|
||||
ret_span: decl.output.span(),
|
||||
expected_ty: tcx.types.isize,
|
||||
found_ty: fn_sig.output(),
|
||||
});
|
||||
}
|
||||
check_function_signature(
|
||||
tcx,
|
||||
ObligationCause::new(
|
||||
tcx.def_span(def_id),
|
||||
def_id,
|
||||
ObligationCauseCode::LangFunctionType(sym::start),
|
||||
),
|
||||
def_id.into(),
|
||||
expected_sig,
|
||||
);
|
||||
}
|
||||
|
@ -236,39 +236,6 @@ impl AddToDiagnostic for TypeMismatchFruTypo {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_lang_start_incorrect_number_params)]
|
||||
#[note(hir_typeck_lang_start_incorrect_number_params_note_expected_count)]
|
||||
#[note(hir_typeck_lang_start_expected_sig_note)]
|
||||
pub struct LangStartIncorrectNumberArgs {
|
||||
#[primary_span]
|
||||
pub params_span: Span,
|
||||
pub found_param_count: usize,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_lang_start_incorrect_param)]
|
||||
pub struct LangStartIncorrectParam<'tcx> {
|
||||
#[primary_span]
|
||||
#[suggestion(style = "short", code = "{expected_ty}", applicability = "machine-applicable")]
|
||||
pub param_span: Span,
|
||||
|
||||
pub param_num: usize,
|
||||
pub expected_ty: Ty<'tcx>,
|
||||
pub found_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_lang_start_incorrect_ret_ty)]
|
||||
pub struct LangStartIncorrectRetTy<'tcx> {
|
||||
#[primary_span]
|
||||
#[suggestion(style = "short", code = "{expected_ty}", applicability = "machine-applicable")]
|
||||
pub ret_span: Span,
|
||||
|
||||
pub expected_ty: Ty<'tcx>,
|
||||
pub found_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(hir_typeck_lossy_provenance_int2ptr)]
|
||||
#[help]
|
||||
|
@ -198,6 +198,10 @@ infer_nothing = {""}
|
||||
infer_oc_cant_coerce = cannot coerce intrinsics to function pointers
|
||||
infer_oc_closure_selfref = closure/generator type that references itself
|
||||
infer_oc_const_compat = const not compatible with trait
|
||||
infer_oc_fn_lang_correct_type = {$lang_item_name ->
|
||||
[panic_impl] `#[panic_handler]`
|
||||
*[lang_item_name] lang item `{$lang_item_name}`
|
||||
} function has wrong type
|
||||
infer_oc_fn_main_correct_type = `main` function has wrong type
|
||||
infer_oc_fn_start_correct_type = `#[start]` function has wrong type
|
||||
infer_oc_generic = mismatched types
|
||||
@ -337,6 +341,7 @@ infer_subtype = ...so that the {$requirement ->
|
||||
[no_else] `if` missing an `else` returns `()`
|
||||
[fn_main_correct_type] `main` function has the correct type
|
||||
[fn_start_correct_type] `#[start]` function has the correct type
|
||||
[fn_lang_correct_type] lang item function has the correct type
|
||||
[intrinsic_correct_type] intrinsic has the correct type
|
||||
[method_correct_type] method receiver has the correct type
|
||||
*[other] types are compatible
|
||||
@ -350,6 +355,7 @@ infer_subtype_2 = ...so that {$requirement ->
|
||||
[no_else] `if` missing an `else` returns `()`
|
||||
[fn_main_correct_type] `main` function has the correct type
|
||||
[fn_start_correct_type] `#[start]` function has the correct type
|
||||
[fn_lang_correct_type] lang item function has the correct type
|
||||
[intrinsic_correct_type] intrinsic has the correct type
|
||||
[method_correct_type] method receiver has the correct type
|
||||
*[other] types are compatible
|
||||
|
@ -1463,6 +1463,14 @@ pub enum ObligationCauseFailureCode {
|
||||
#[subdiagnostic]
|
||||
subdiags: Vec<TypeErrorAdditionalDiags>,
|
||||
},
|
||||
#[diag(infer_oc_fn_lang_correct_type, code = "E0308")]
|
||||
FnLangCorrectType {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
#[subdiagnostic]
|
||||
subdiags: Vec<TypeErrorAdditionalDiags>,
|
||||
lang_item_name: Symbol,
|
||||
},
|
||||
#[diag(infer_oc_intrinsic_correct_type, code = "E0308")]
|
||||
IntrinsicCorrectType {
|
||||
#[primary_span]
|
||||
|
@ -2927,6 +2927,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
|
||||
| IfExpression { .. }
|
||||
| LetElse
|
||||
| StartFunctionType
|
||||
| LangFunctionType(_)
|
||||
| IntrinsicType
|
||||
| MethodReceiver => Error0308,
|
||||
|
||||
@ -2971,6 +2972,9 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
|
||||
LetElse => ObligationCauseFailureCode::NoDiverge { span, subdiags },
|
||||
MainFunctionType => ObligationCauseFailureCode::FnMainCorrectType { span },
|
||||
StartFunctionType => ObligationCauseFailureCode::FnStartCorrectType { span, subdiags },
|
||||
&LangFunctionType(lang_item_name) => {
|
||||
ObligationCauseFailureCode::FnLangCorrectType { span, subdiags, lang_item_name }
|
||||
}
|
||||
IntrinsicType => ObligationCauseFailureCode::IntrinsicCorrectType { span, subdiags },
|
||||
MethodReceiver => ObligationCauseFailureCode::MethodCorrectType { span, subdiags },
|
||||
|
||||
@ -3006,6 +3010,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
|
||||
IfExpressionWithNoElse => "`if` missing an `else` returns `()`",
|
||||
MainFunctionType => "`main` function has the correct type",
|
||||
StartFunctionType => "`#[start]` function has the correct type",
|
||||
LangFunctionType(_) => "lang item function has the correct type",
|
||||
IntrinsicType => "intrinsic has the correct type",
|
||||
MethodReceiver => "method receiver has the correct type",
|
||||
_ => "types are compatible",
|
||||
@ -3028,6 +3033,7 @@ impl IntoDiagnosticArg for ObligationCauseAsDiagArg<'_> {
|
||||
IfExpressionWithNoElse => "no_else",
|
||||
MainFunctionType => "fn_main_correct_type",
|
||||
StartFunctionType => "fn_start_correct_type",
|
||||
LangFunctionType(_) => "fn_lang_correct_type",
|
||||
IntrinsicType => "intrinsic_correct_type",
|
||||
MethodReceiver => "method_correct_type",
|
||||
_ => "other",
|
||||
|
@ -378,6 +378,9 @@ pub enum ObligationCauseCode<'tcx> {
|
||||
/// `start` has wrong type
|
||||
StartFunctionType,
|
||||
|
||||
/// language function has wrong type
|
||||
LangFunctionType(Symbol),
|
||||
|
||||
/// Intrinsic has wrong type
|
||||
IntrinsicType,
|
||||
|
||||
|
@ -2717,6 +2717,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
| ObligationCauseCode::IfExpressionWithNoElse
|
||||
| ObligationCauseCode::MainFunctionType
|
||||
| ObligationCauseCode::StartFunctionType
|
||||
| ObligationCauseCode::LangFunctionType(_)
|
||||
| ObligationCauseCode::IntrinsicType
|
||||
| ObligationCauseCode::MethodReceiver
|
||||
| ObligationCauseCode::ReturnNoExpression
|
||||
|
@ -4,8 +4,8 @@ error[E0580]: `main` function has wrong type
|
||||
LL | fn main(_: for<'a> fn(Foo<fn(&'a ())>::Assoc)) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
|
||||
|
|
||||
= note: expected fn pointer `fn()`
|
||||
found fn pointer `fn(for<'a> fn(Foo<fn(&'a ())>::Assoc))`
|
||||
= note: expected signature `fn()`
|
||||
found signature `fn(for<'a> fn(&'a ()))`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -9,7 +9,7 @@ extern {}
|
||||
|
||||
#[lang = "start"]
|
||||
fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize {
|
||||
//~^ ERROR: incorrect number of parameters for the `start` lang item
|
||||
//~^ ERROR lang item `start` function has wrong type [E0308]
|
||||
40+2
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,12 @@
|
||||
error: incorrect number of parameters for the `start` lang item
|
||||
error[E0308]: lang item `start` function has wrong type
|
||||
--> $DIR/issue-92157.rs:11:1
|
||||
|
|
||||
LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
|
||||
|
|
||||
= note: the `start` lang item should have four parameters, but found 3
|
||||
= note: the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize`
|
||||
= note: expected signature `fn(fn() -> T, isize, *const *const u8, u8) -> _`
|
||||
found signature `fn(fn() -> T, isize, *const *const u8) -> _`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
2
tests/ui/entry-point/auxiliary/bad_main_functions.rs
Normal file
2
tests/ui/entry-point/auxiliary/bad_main_functions.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub fn boilerplate(x: u8) {}
|
||||
//~^ ERROR: `main` function has wrong type [E0580]
|
@ -0,0 +1,6 @@
|
||||
// aux-build:bad_main_functions.rs
|
||||
|
||||
#![feature(imported_main)]
|
||||
|
||||
extern crate bad_main_functions;
|
||||
pub use bad_main_functions::boilerplate as main;
|
@ -0,0 +1,12 @@
|
||||
error[E0580]: `main` function has wrong type
|
||||
--> $DIR/auxiliary/bad_main_functions.rs:1:1
|
||||
|
|
||||
LL | pub fn boilerplate(x: u8) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
|
||||
|
|
||||
= note: expected signature `fn()`
|
||||
found signature `fn(u8)`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0580`.
|
@ -1,11 +1,11 @@
|
||||
error[E0308]: intrinsic has wrong type
|
||||
--> $DIR/E0308.rs:6:5
|
||||
--> $DIR/E0308.rs:6:20
|
||||
|
|
||||
LL | fn size_of<T>();
|
||||
| ^^^^^^^^^^^^^^^^ expected `()`, found `usize`
|
||||
| ^ expected `usize`, found `()`
|
||||
|
|
||||
= note: expected fn pointer `extern "rust-intrinsic" fn()`
|
||||
found fn pointer `extern "rust-intrinsic" fn() -> usize`
|
||||
= note: expected signature `extern "rust-intrinsic" fn() -> usize`
|
||||
found signature `extern "rust-intrinsic" fn()`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
4
tests/ui/extern/extern-main-fn.stderr
vendored
4
tests/ui/extern/extern-main-fn.stderr
vendored
@ -4,8 +4,8 @@ error[E0580]: `main` function has wrong type
|
||||
LL | extern "C" fn main() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^ expected "Rust" fn, found "C" fn
|
||||
|
|
||||
= note: expected fn pointer `fn()`
|
||||
found fn pointer `extern "C" fn()`
|
||||
= note: expected signature `fn()`
|
||||
found signature `extern "C" fn()`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -4,8 +4,8 @@ error[E0580]: `main` function has wrong type
|
||||
LL | fn main(x: isize) { }
|
||||
| ^^^^^^^^^^^^^^^^^ incorrect number of function parameters
|
||||
|
|
||||
= note: expected fn pointer `fn()`
|
||||
found fn pointer `fn(isize)`
|
||||
= note: expected signature `fn()`
|
||||
found signature `fn(isize)`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -4,8 +4,8 @@ error[E0308]: `#[start]` function has wrong type
|
||||
LL | fn start(argc: isize, argv: *const *const u8, crate_map: *const u8) -> isize {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
|
||||
|
|
||||
= note: expected fn pointer `fn(isize, *const *const u8) -> _`
|
||||
found fn pointer `fn(isize, *const *const u8, *const u8) -> _`
|
||||
= note: expected signature `fn(isize, *const *const u8) -> _`
|
||||
found signature `fn(isize, *const *const u8, *const u8) -> _`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,8 +1,12 @@
|
||||
error: parameter 2 of the `start` lang item is incorrect
|
||||
error[E0308]: lang item `start` function has wrong type
|
||||
--> $DIR/start_lang_item_args.rs:75:38
|
||||
|
|
||||
LL | fn start<T>(_main: fn() -> T, _argc: i8, _argv: *const *const u8, _sigpipe: u8) -> isize {
|
||||
| ^^ help: change the type from `i8` to `isize`
|
||||
| ^^ expected `isize`, found `i8`
|
||||
|
|
||||
= note: expected signature `fn(fn() -> _, isize, _, _) -> _`
|
||||
found signature `fn(fn() -> _, i8, _, _) -> _`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -1,8 +1,12 @@
|
||||
error: parameter 3 of the `start` lang item is incorrect
|
||||
error[E0308]: lang item `start` function has wrong type
|
||||
--> $DIR/start_lang_item_args.rs:89:52
|
||||
|
|
||||
LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: u8, _sigpipe: u8) -> isize {
|
||||
| ^^ help: change the type from `u8` to `*const *const u8`
|
||||
| ^^ expected `*const *const u8`, found `u8`
|
||||
|
|
||||
= note: expected signature `fn(fn() -> _, _, *const *const u8, _) -> _`
|
||||
found signature `fn(fn() -> _, _, u8, _) -> _`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -1,13 +1,12 @@
|
||||
error: parameter 3 of the `start` lang item is incorrect
|
||||
error[E0308]: lang item `start` function has wrong type
|
||||
--> $DIR/start_lang_item_args.rs:82:52
|
||||
|
|
||||
LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const usize, _sigpipe: u8) -> isize {
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^ expected `u8`, found `usize`
|
||||
|
|
||||
help: change the type from `*const *const usize` to `*const *const u8`
|
||||
|
|
||||
LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
|
||||
| ~~~~~~~~~~~~~~~~
|
||||
= note: expected signature `fn(fn() -> _, _, *const *const u8, _) -> _`
|
||||
found signature `fn(fn() -> _, _, *const *const usize, _) -> _`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -1,13 +1,12 @@
|
||||
error: parameter 1 of the `start` lang item is incorrect
|
||||
--> $DIR/start_lang_item_args.rs:61:20
|
||||
error[E0308]: lang item `start` function has wrong type
|
||||
--> $DIR/start_lang_item_args.rs:61:1
|
||||
|
|
||||
LL | fn start<T>(_main: fn(i32) -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
|
||||
| ^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
|
||||
|
|
||||
help: change the type from `fn(i32) -> T` to `fn() -> T`
|
||||
|
|
||||
LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
|
||||
| ~~~~~~~~~
|
||||
= note: expected signature `fn(fn() -> _, _, _, _) -> _`
|
||||
found signature `fn(fn(i32) -> _, _, _, _) -> _`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -1,13 +1,14 @@
|
||||
error: parameter 1 of the `start` lang item is incorrect
|
||||
error[E0308]: lang item `start` function has wrong type
|
||||
--> $DIR/start_lang_item_args.rs:68:20
|
||||
|
|
||||
LL | fn start<T>(_main: fn() -> u16, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
|
||||
| ^^^^^^^^^^^
|
||||
| - ^^^^^^^^^^^ expected type parameter `T`, found `u16`
|
||||
| |
|
||||
| this type parameter
|
||||
|
|
||||
help: change the type from `fn() -> u16` to `fn() -> T`
|
||||
|
|
||||
LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
|
||||
| ~~~~~~~~~
|
||||
= note: expected signature `fn(fn() -> T, _, _, _) -> _`
|
||||
found signature `fn(fn() -> u16, _, _, _) -> _`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -1,8 +1,12 @@
|
||||
error: parameter 1 of the `start` lang item is incorrect
|
||||
error[E0308]: lang item `start` function has wrong type
|
||||
--> $DIR/start_lang_item_args.rs:54:20
|
||||
|
|
||||
LL | fn start<T>(_main: u64, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
|
||||
| ^^^ help: change the type from `u64` to `fn() -> T`
|
||||
| ^^^ expected fn pointer, found `u64`
|
||||
|
|
||||
= note: expected signature `fn(fn() -> T, _, _, _) -> _`
|
||||
found signature `fn(u64, _, _, _) -> _`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -1,11 +1,12 @@
|
||||
error: incorrect number of parameters for the `start` lang item
|
||||
error[E0308]: lang item `start` function has wrong type
|
||||
--> $DIR/start_lang_item_args.rs:15:1
|
||||
|
|
||||
LL | fn start<T>() -> isize {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
|
||||
|
|
||||
= note: the `start` lang item should have four parameters, but found 0
|
||||
= note: the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize`
|
||||
= note: expected signature `fn(fn() -> T, isize, *const *const u8, u8) -> _`
|
||||
found signature `fn() -> _`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -1,8 +1,12 @@
|
||||
error: the return type of the `start` lang item is incorrect
|
||||
error[E0308]: lang item `start` function has wrong type
|
||||
--> $DIR/start_lang_item_args.rs:29:84
|
||||
|
|
||||
LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) {}
|
||||
| ^ help: change the type from `()` to `isize`
|
||||
| ^ expected `isize`, found `()`
|
||||
|
|
||||
= note: expected signature `fn(fn() -> _, _, _, _) -> isize`
|
||||
found signature `fn(fn() -> _, _, _, _)`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -1,11 +1,12 @@
|
||||
error: incorrect number of parameters for the `start` lang item
|
||||
error[E0308]: lang item `start` function has wrong type
|
||||
--> $DIR/start_lang_item_args.rs:22:1
|
||||
|
|
||||
LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
|
||||
|
|
||||
= note: the `start` lang item should have four parameters, but found 3
|
||||
= note: the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize`
|
||||
= note: expected signature `fn(fn() -> T, isize, *const *const u8, u8) -> _`
|
||||
found signature `fn(fn() -> T, isize, *const *const u8) -> _`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -13,33 +13,33 @@ pub trait Sized {}
|
||||
#[cfg(missing_all_args)]
|
||||
#[lang = "start"]
|
||||
fn start<T>() -> isize {
|
||||
//[missing_all_args]~^ ERROR incorrect number of parameters
|
||||
//[missing_all_args]~^ ERROR lang item `start` function has wrong type [E0308]
|
||||
100
|
||||
}
|
||||
|
||||
#[cfg(missing_sigpipe_arg)]
|
||||
#[lang = "start"]
|
||||
fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize {
|
||||
//[missing_sigpipe_arg]~^ ERROR incorrect number of parameters
|
||||
//[missing_sigpipe_arg]~^ ERROR lang item `start` function has wrong type [E0308]
|
||||
100
|
||||
}
|
||||
|
||||
#[cfg(missing_ret)]
|
||||
#[lang = "start"]
|
||||
fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) {}
|
||||
//[missing_ret]~^ ERROR the return type of the `start` lang item is incorrect
|
||||
//[missing_ret]~^ ERROR lang item `start` function has wrong type [E0308]
|
||||
|
||||
#[cfg(start_ret)]
|
||||
#[lang = "start"]
|
||||
fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> u8 {
|
||||
//[start_ret]~^ ERROR the return type of the `start` lang item is incorrect
|
||||
//[start_ret]~^ ERROR lang item `start` function has wrong type [E0308]
|
||||
100
|
||||
}
|
||||
|
||||
#[cfg(too_many_args)]
|
||||
#[lang = "start"]
|
||||
fn start<T>(
|
||||
//[too_many_args]~^ ERROR incorrect number of parameters
|
||||
//[too_many_args]~^ ERROR lang item `start` function has wrong type [E0308]
|
||||
_main: fn() -> T,
|
||||
_argc: isize,
|
||||
_argv: *const *const u8,
|
||||
@ -52,49 +52,49 @@ fn start<T>(
|
||||
#[cfg(main_ty)]
|
||||
#[lang = "start"]
|
||||
fn start<T>(_main: u64, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
|
||||
//[main_ty]~^ ERROR parameter 1 of the `start` lang item is incorrect
|
||||
//[main_ty]~^ ERROR lang item `start` function has wrong type [E0308]
|
||||
100
|
||||
}
|
||||
|
||||
#[cfg(main_args)]
|
||||
#[lang = "start"]
|
||||
fn start<T>(_main: fn(i32) -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
|
||||
//[main_args]~^ ERROR parameter 1 of the `start` lang item is incorrect
|
||||
//[main_args]~^ ERROR lang item `start` function has wrong type [E0308]
|
||||
100
|
||||
}
|
||||
|
||||
#[cfg(main_ret)]
|
||||
#[lang = "start"]
|
||||
fn start<T>(_main: fn() -> u16, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
|
||||
//[main_ret]~^ ERROR parameter 1 of the `start` lang item is incorrect
|
||||
//[main_ret]~^ ERROR lang item `start` function has wrong type [E0308]
|
||||
100
|
||||
}
|
||||
|
||||
#[cfg(argc)]
|
||||
#[lang = "start"]
|
||||
fn start<T>(_main: fn() -> T, _argc: i8, _argv: *const *const u8, _sigpipe: u8) -> isize {
|
||||
//[argc]~^ ERROR parameter 2 of the `start` lang item is incorrect
|
||||
//[argc]~^ ERROR lang item `start` function has wrong type [E0308]
|
||||
100
|
||||
}
|
||||
|
||||
#[cfg(argv_inner_ptr)]
|
||||
#[lang = "start"]
|
||||
fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const usize, _sigpipe: u8) -> isize {
|
||||
//[argv_inner_ptr]~^ ERROR parameter 3 of the `start` lang item is incorrect
|
||||
//[argv_inner_ptr]~^ ERROR lang item `start` function has wrong type [E0308]
|
||||
100
|
||||
}
|
||||
|
||||
#[cfg(argv)]
|
||||
#[lang = "start"]
|
||||
fn start<T>(_main: fn() -> T, _argc: isize, _argv: u8, _sigpipe: u8) -> isize {
|
||||
//[argv]~^ ERROR parameter 3 of the `start` lang item is incorrect
|
||||
//[argv]~^ ERROR lang item `start` function has wrong type [E0308]
|
||||
100
|
||||
}
|
||||
|
||||
#[cfg(sigpipe)]
|
||||
#[lang = "start"]
|
||||
fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: i64) -> isize {
|
||||
//[sigpipe]~^ ERROR parameter 4 of the `start` lang item is incorrect
|
||||
//[sigpipe]~^ ERROR lang item `start` function has wrong type [E0308]
|
||||
100
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,12 @@
|
||||
error: parameter 4 of the `start` lang item is incorrect
|
||||
error[E0308]: lang item `start` function has wrong type
|
||||
--> $DIR/start_lang_item_args.rs:96:80
|
||||
|
|
||||
LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: i64) -> isize {
|
||||
| ^^^ help: change the type from `i64` to `u8`
|
||||
| ^^^ expected `u8`, found `i64`
|
||||
|
|
||||
= note: expected signature `fn(fn() -> _, _, _, u8) -> _`
|
||||
found signature `fn(fn() -> _, _, _, i64) -> _`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -1,8 +1,12 @@
|
||||
error: the return type of the `start` lang item is incorrect
|
||||
error[E0308]: lang item `start` function has wrong type
|
||||
--> $DIR/start_lang_item_args.rs:34:87
|
||||
|
|
||||
LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> u8 {
|
||||
| ^^ help: change the type from `u8` to `isize`
|
||||
| ^^ expected `isize`, found `u8`
|
||||
|
|
||||
= note: expected signature `fn(fn() -> _, _, _, _) -> isize`
|
||||
found signature `fn(fn() -> _, _, _, _) -> u8`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: incorrect number of parameters for the `start` lang item
|
||||
error[E0308]: lang item `start` function has wrong type
|
||||
--> $DIR/start_lang_item_args.rs:41:1
|
||||
|
|
||||
LL | / fn start<T>(
|
||||
@ -8,10 +8,11 @@ LL | | _argc: isize,
|
||||
... |
|
||||
LL | | _extra_arg: (),
|
||||
LL | | ) -> isize {
|
||||
| |__________^
|
||||
| |__________^ incorrect number of function parameters
|
||||
|
|
||||
= note: the `start` lang item should have four parameters, but found 5
|
||||
= note: the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize`
|
||||
= note: expected signature `fn(fn() -> T, isize, *const *const u8, u8) -> _`
|
||||
found signature `fn(fn() -> T, isize, *const *const u8, u8, ()) -> _`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -4,8 +4,8 @@ error[E0580]: `main` function has wrong type
|
||||
LL | fn main(foo: S) {
|
||||
| ^^^^^^^^^^^^^^^ incorrect number of function parameters
|
||||
|
|
||||
= note: expected fn pointer `fn()`
|
||||
found fn pointer `fn(S)`
|
||||
= note: expected signature `fn()`
|
||||
found signature `fn(S)`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -6,8 +6,5 @@
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(
|
||||
info: PanicInfo, //~ ERROR argument should be `&PanicInfo`
|
||||
) -> () //~ ERROR return type should be `!`
|
||||
{
|
||||
}
|
||||
fn panic(info: PanicInfo) -> () {}
|
||||
//~^ `#[panic_handler]` function has wrong type [E0308]
|
||||
|
@ -1,14 +1,12 @@
|
||||
error: return type should be `!`
|
||||
--> $DIR/panic-handler-bad-signature-1.rs:11:6
|
||||
error[E0308]: `#[panic_handler]` function has wrong type
|
||||
--> $DIR/panic-handler-bad-signature-1.rs:9:16
|
||||
|
|
||||
LL | ) -> ()
|
||||
| ^^
|
||||
|
||||
error: argument should be `&PanicInfo`
|
||||
--> $DIR/panic-handler-bad-signature-1.rs:10:11
|
||||
LL | fn panic(info: PanicInfo) -> () {}
|
||||
| ^^^^^^^^^ expected `&PanicInfo<'_>`, found `PanicInfo<'_>`
|
||||
|
|
||||
LL | info: PanicInfo,
|
||||
| ^^^^^^^^^
|
||||
= note: expected signature `fn(&PanicInfo<'_>) -> !`
|
||||
found signature `fn(PanicInfo<'_>)`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -6,9 +6,8 @@
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(
|
||||
info: &'static PanicInfo, //~ ERROR argument should be `&PanicInfo`
|
||||
) -> !
|
||||
fn panic(info: &'static PanicInfo) -> !
|
||||
//~^ #[panic_handler]` function has wrong type [E0308]
|
||||
{
|
||||
loop {}
|
||||
}
|
||||
|
@ -1,8 +1,12 @@
|
||||
error: argument should be `&PanicInfo`
|
||||
--> $DIR/panic-handler-bad-signature-2.rs:10:11
|
||||
error[E0308]: `#[panic_handler]` function has wrong type
|
||||
--> $DIR/panic-handler-bad-signature-2.rs:9:1
|
||||
|
|
||||
LL | info: &'static PanicInfo,
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
LL | fn panic(info: &'static PanicInfo) -> !
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'a, 'b> fn(&'a PanicInfo<'b>) -> _`
|
||||
found fn pointer `for<'a> fn(&'static PanicInfo<'a>) -> _`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -6,6 +6,6 @@
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[panic_handler]
|
||||
fn panic() -> ! { //~ ERROR function should have one argument
|
||||
fn panic() -> ! { //~ #[panic_handler]` function has wrong type [E0308]
|
||||
loop {}
|
||||
}
|
||||
|
@ -1,8 +1,12 @@
|
||||
error: function should have one argument
|
||||
error[E0308]: `#[panic_handler]` function has wrong type
|
||||
--> $DIR/panic-handler-bad-signature-3.rs:9:1
|
||||
|
|
||||
LL | fn panic() -> ! {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^ incorrect number of function parameters
|
||||
|
|
||||
= note: expected signature `fn(&PanicInfo<'_>) -> _`
|
||||
found signature `fn() -> _`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
13
tests/ui/panic-handler/panic-handler-bad-signature-5.rs
Normal file
13
tests/ui/panic-handler/panic-handler-bad-signature-5.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// compile-flags:-C panic=abort
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(info: &PanicInfo<'static>) -> !
|
||||
//~^ #[panic_handler]` function has wrong type [E0308]
|
||||
{
|
||||
loop {}
|
||||
}
|
12
tests/ui/panic-handler/panic-handler-bad-signature-5.stderr
Normal file
12
tests/ui/panic-handler/panic-handler-bad-signature-5.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
error[E0308]: `#[panic_handler]` function has wrong type
|
||||
--> $DIR/panic-handler-bad-signature-5.rs:9:1
|
||||
|
|
||||
LL | fn panic(info: &PanicInfo<'static>) -> !
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'a, 'b> fn(&'a PanicInfo<'b>) -> _`
|
||||
found fn pointer `for<'a> fn(&'a PanicInfo<'static>) -> _`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -17,9 +17,9 @@ extern "C" fn eh_personality() {}
|
||||
static EH_CATCH_TYPEINFO: u8 = 0;
|
||||
|
||||
#[panic_handler]
|
||||
fn panic_handler() {}
|
||||
//~^ ERROR return type should be `!`
|
||||
//~| ERROR function should have one argument
|
||||
fn panic_handler(_: &core::panic::PanicInfo) -> ! {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
// take a reference to any built-in range
|
||||
fn take_range(_r: &impl RangeBounds<i8>) {}
|
||||
|
@ -1,15 +1,3 @@
|
||||
error: return type should be `!`
|
||||
--> $DIR/issue-54505-no-std.rs:20:20
|
||||
|
|
||||
LL | fn panic_handler() {}
|
||||
| ^
|
||||
|
||||
error: function should have one argument
|
||||
--> $DIR/issue-54505-no-std.rs:20:1
|
||||
|
|
||||
LL | fn panic_handler() {}
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-54505-no-std.rs:29:16
|
||||
|
|
||||
@ -130,6 +118,6 @@ help: consider borrowing here
|
||||
LL | take_range(&(..=42));
|
||||
| ++ +
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -16,8 +16,8 @@ error[E0580]: `main` function has wrong type
|
||||
LL | fn main(arguments: Vec<String>) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
|
||||
|
|
||||
= note: expected fn pointer `fn()`
|
||||
found fn pointer `fn(Vec<String>)`
|
||||
= note: expected signature `fn()`
|
||||
found signature `fn(Vec<String>)`
|
||||
|
||||
error[E0425]: cannot find function `log` in this scope
|
||||
--> $DIR/bad-expr-path.rs:4:5
|
||||
|
@ -16,8 +16,8 @@ error[E0580]: `main` function has wrong type
|
||||
LL | fn main(arguments: Vec<String>) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
|
||||
|
|
||||
= note: expected fn pointer `fn()`
|
||||
found fn pointer `fn(Vec<String>)`
|
||||
= note: expected signature `fn()`
|
||||
found signature `fn(Vec<String>)`
|
||||
|
||||
error[E0425]: cannot find function `log` in this scope
|
||||
--> $DIR/bad-expr-path2.rs:6:5
|
||||
|
Loading…
Reference in New Issue
Block a user