Rollup merge of #123924 - compiler-errors:tuple-sugg, r=estebank
Fix various bugs in `ty_kind_suggestion` Consolidates two implementations of `ty_kind_suggestion` Fixes some misuse of the empty param-env Fixes a problem where we suggested `(42)` instead of `(42,)` for tuple suggestions Suggest a value when `return;`, making it consistent with `break;` Fixes #123906
This commit is contained in:
commit
20a5fb3b4a
12 changed files with 139 additions and 130 deletions
|
@ -671,68 +671,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
err
|
err
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ty_kind_suggestion(&self, ty: Ty<'tcx>) -> Option<String> {
|
|
||||||
// Keep in sync with `rustc_hir_analysis/src/check/mod.rs:ty_kind_suggestion`.
|
|
||||||
// FIXME: deduplicate the above.
|
|
||||||
let tcx = self.infcx.tcx;
|
|
||||||
let implements_default = |ty| {
|
|
||||||
let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
self.infcx
|
|
||||||
.type_implements_trait(default_trait, [ty], self.param_env)
|
|
||||||
.must_apply_modulo_regions()
|
|
||||||
};
|
|
||||||
|
|
||||||
Some(match ty.kind() {
|
|
||||||
ty::Never | ty::Error(_) => return None,
|
|
||||||
ty::Bool => "false".to_string(),
|
|
||||||
ty::Char => "\'x\'".to_string(),
|
|
||||||
ty::Int(_) | ty::Uint(_) => "42".into(),
|
|
||||||
ty::Float(_) => "3.14159".into(),
|
|
||||||
ty::Slice(_) => "[]".to_string(),
|
|
||||||
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => {
|
|
||||||
"vec![]".to_string()
|
|
||||||
}
|
|
||||||
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::String) => {
|
|
||||||
"String::new()".to_string()
|
|
||||||
}
|
|
||||||
ty::Adt(def, args) if def.is_box() => {
|
|
||||||
format!("Box::new({})", self.ty_kind_suggestion(args[0].expect_ty())?)
|
|
||||||
}
|
|
||||||
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Option) => {
|
|
||||||
"None".to_string()
|
|
||||||
}
|
|
||||||
ty::Adt(def, args) if Some(def.did()) == tcx.get_diagnostic_item(sym::Result) => {
|
|
||||||
format!("Ok({})", self.ty_kind_suggestion(args[0].expect_ty())?)
|
|
||||||
}
|
|
||||||
ty::Adt(_, _) if implements_default(ty) => "Default::default()".to_string(),
|
|
||||||
ty::Ref(_, ty, mutability) => {
|
|
||||||
if let (ty::Str, hir::Mutability::Not) = (ty.kind(), mutability) {
|
|
||||||
"\"\"".to_string()
|
|
||||||
} else {
|
|
||||||
let Some(ty) = self.ty_kind_suggestion(*ty) else {
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
format!("&{}{ty}", mutability.prefix_str())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ty::Array(ty, len) => format!(
|
|
||||||
"[{}; {}]",
|
|
||||||
self.ty_kind_suggestion(*ty)?,
|
|
||||||
len.eval_target_usize(tcx, ty::ParamEnv::reveal_all()),
|
|
||||||
),
|
|
||||||
ty::Tuple(tys) => format!(
|
|
||||||
"({})",
|
|
||||||
tys.iter()
|
|
||||||
.map(|ty| self.ty_kind_suggestion(ty))
|
|
||||||
.collect::<Option<Vec<String>>>()?
|
|
||||||
.join(", ")
|
|
||||||
),
|
|
||||||
_ => "value".to_string(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn suggest_assign_value(
|
fn suggest_assign_value(
|
||||||
&self,
|
&self,
|
||||||
err: &mut Diag<'_>,
|
err: &mut Diag<'_>,
|
||||||
|
@ -742,7 +680,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
|
let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
|
||||||
debug!("ty: {:?}, kind: {:?}", ty, ty.kind());
|
debug!("ty: {:?}, kind: {:?}", ty, ty.kind());
|
||||||
|
|
||||||
let Some(assign_value) = self.ty_kind_suggestion(ty) else {
|
let Some(assign_value) = self.infcx.err_ctxt().ty_kind_suggestion(self.param_env, ty)
|
||||||
|
else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,6 @@ use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_errors::{pluralize, struct_span_code_err, Diag};
|
use rustc_errors::{pluralize, struct_span_code_err, Diag};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_hir::intravisit::Visitor;
|
use rustc_hir::intravisit::Visitor;
|
||||||
use rustc_hir::Mutability;
|
|
||||||
use rustc_index::bit_set::BitSet;
|
use rustc_index::bit_set::BitSet;
|
||||||
use rustc_infer::infer::error_reporting::ObligationCauseExt as _;
|
use rustc_infer::infer::error_reporting::ObligationCauseExt as _;
|
||||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||||
|
@ -96,8 +95,9 @@ use rustc_span::symbol::{kw, sym, Ident};
|
||||||
use rustc_span::{def_id::CRATE_DEF_ID, BytePos, Span, Symbol, DUMMY_SP};
|
use rustc_span::{def_id::CRATE_DEF_ID, BytePos, Span, Symbol, DUMMY_SP};
|
||||||
use rustc_target::abi::VariantIdx;
|
use rustc_target::abi::VariantIdx;
|
||||||
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::suggestions::{
|
||||||
use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;
|
ReturnsVisitor, TypeErrCtxtExt as _,
|
||||||
|
};
|
||||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
|
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
|
||||||
use rustc_trait_selection::traits::ObligationCtxt;
|
use rustc_trait_selection::traits::ObligationCtxt;
|
||||||
|
|
||||||
|
@ -467,67 +467,6 @@ fn fn_sig_suggestion<'tcx>(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ty_kind_suggestion<'tcx>(ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Option<String> {
|
|
||||||
// Keep in sync with `rustc_borrowck/src/diagnostics/conflict_errors.rs:ty_kind_suggestion`.
|
|
||||||
// FIXME: deduplicate the above.
|
|
||||||
let implements_default = |ty| {
|
|
||||||
let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
let infcx = tcx.infer_ctxt().build();
|
|
||||||
infcx
|
|
||||||
.type_implements_trait(default_trait, [ty], ty::ParamEnv::reveal_all())
|
|
||||||
.must_apply_modulo_regions()
|
|
||||||
};
|
|
||||||
Some(match ty.kind() {
|
|
||||||
ty::Never | ty::Error(_) => return None,
|
|
||||||
ty::Bool => "false".to_string(),
|
|
||||||
ty::Char => "\'x\'".to_string(),
|
|
||||||
ty::Int(_) | ty::Uint(_) => "42".into(),
|
|
||||||
ty::Float(_) => "3.14159".into(),
|
|
||||||
ty::Slice(_) => "[]".to_string(),
|
|
||||||
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => {
|
|
||||||
"vec![]".to_string()
|
|
||||||
}
|
|
||||||
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::String) => {
|
|
||||||
"String::new()".to_string()
|
|
||||||
}
|
|
||||||
ty::Adt(def, args) if def.is_box() => {
|
|
||||||
format!("Box::new({})", ty_kind_suggestion(args[0].expect_ty(), tcx)?)
|
|
||||||
}
|
|
||||||
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Option) => {
|
|
||||||
"None".to_string()
|
|
||||||
}
|
|
||||||
ty::Adt(def, args) if Some(def.did()) == tcx.get_diagnostic_item(sym::Result) => {
|
|
||||||
format!("Ok({})", ty_kind_suggestion(args[0].expect_ty(), tcx)?)
|
|
||||||
}
|
|
||||||
ty::Adt(_, _) if implements_default(ty) => "Default::default()".to_string(),
|
|
||||||
ty::Ref(_, ty, mutability) => {
|
|
||||||
if let (ty::Str, Mutability::Not) = (ty.kind(), mutability) {
|
|
||||||
"\"\"".to_string()
|
|
||||||
} else {
|
|
||||||
let Some(ty) = ty_kind_suggestion(*ty, tcx) else {
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
format!("&{}{ty}", mutability.prefix_str())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ty::Array(ty, len) => format!(
|
|
||||||
"[{}; {}]",
|
|
||||||
ty_kind_suggestion(*ty, tcx)?,
|
|
||||||
len.eval_target_usize(tcx, ty::ParamEnv::reveal_all()),
|
|
||||||
),
|
|
||||||
ty::Tuple(tys) => format!(
|
|
||||||
"({})",
|
|
||||||
tys.iter()
|
|
||||||
.map(|ty| ty_kind_suggestion(ty, tcx))
|
|
||||||
.collect::<Option<Vec<String>>>()?
|
|
||||||
.join(", ")
|
|
||||||
),
|
|
||||||
_ => "value".to_string(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return placeholder code for the given associated item.
|
/// Return placeholder code for the given associated item.
|
||||||
/// Similar to `ty::AssocItem::suggestion`, but appropriate for use as the code snippet of a
|
/// Similar to `ty::AssocItem::suggestion`, but appropriate for use as the code snippet of a
|
||||||
/// structured suggestion.
|
/// structured suggestion.
|
||||||
|
@ -562,7 +501,12 @@ fn suggestion_signature<'tcx>(
|
||||||
}
|
}
|
||||||
ty::AssocKind::Const => {
|
ty::AssocKind::Const => {
|
||||||
let ty = tcx.type_of(assoc.def_id).instantiate_identity();
|
let ty = tcx.type_of(assoc.def_id).instantiate_identity();
|
||||||
let val = ty_kind_suggestion(ty, tcx).unwrap_or_else(|| "value".to_string());
|
let val = tcx
|
||||||
|
.infer_ctxt()
|
||||||
|
.build()
|
||||||
|
.err_ctxt()
|
||||||
|
.ty_kind_suggestion(tcx.param_env(assoc.def_id), ty)
|
||||||
|
.unwrap_or_else(|| "value".to_string());
|
||||||
format!("const {}: {} = {};", assoc.name, ty, val)
|
format!("const {}: {} = {};", assoc.name, ty, val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,7 @@ use rustc_span::DesugaringKind;
|
||||||
use rustc_span::{BytePos, Span};
|
use rustc_span::{BytePos, Span};
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
use rustc_trait_selection::infer::InferCtxtExt as _;
|
use rustc_trait_selection::infer::InferCtxtExt as _;
|
||||||
|
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
|
||||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
|
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
|
||||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
||||||
use rustc_trait_selection::traits::TraitEngineExt as _;
|
use rustc_trait_selection::traits::TraitEngineExt as _;
|
||||||
|
@ -1616,6 +1617,15 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
||||||
E0069,
|
E0069,
|
||||||
"`return;` in a function whose return type is not `()`"
|
"`return;` in a function whose return type is not `()`"
|
||||||
);
|
);
|
||||||
|
if let Some(value) = fcx.err_ctxt().ty_kind_suggestion(fcx.param_env, found)
|
||||||
|
{
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
cause.span.shrink_to_hi(),
|
||||||
|
"give the `return` a value of the expected type",
|
||||||
|
format!(" {value}"),
|
||||||
|
Applicability::HasPlaceholders,
|
||||||
|
);
|
||||||
|
}
|
||||||
err.span_label(cause.span, "return type is not `()`");
|
err.span_label(cause.span, "return type is not `()`");
|
||||||
}
|
}
|
||||||
ObligationCauseCode::BlockTailExpression(blk_id, ..) => {
|
ObligationCauseCode::BlockTailExpression(blk_id, ..) => {
|
||||||
|
|
|
@ -35,7 +35,6 @@ use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::intravisit::Visitor;
|
use rustc_hir::intravisit::Visitor;
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir::{ExprKind, HirId, QPath};
|
use rustc_hir::{ExprKind, HirId, QPath};
|
||||||
use rustc_hir_analysis::check::ty_kind_suggestion;
|
|
||||||
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer as _;
|
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer as _;
|
||||||
use rustc_infer::infer;
|
use rustc_infer::infer;
|
||||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||||
|
@ -57,6 +56,7 @@ use rustc_span::Span;
|
||||||
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
|
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
|
||||||
use rustc_target::spec::abi::Abi::RustIntrinsic;
|
use rustc_target::spec::abi::Abi::RustIntrinsic;
|
||||||
use rustc_trait_selection::infer::InferCtxtExt;
|
use rustc_trait_selection::infer::InferCtxtExt;
|
||||||
|
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _;
|
||||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
||||||
use rustc_trait_selection::traits::ObligationCtxt;
|
use rustc_trait_selection::traits::ObligationCtxt;
|
||||||
use rustc_trait_selection::traits::{self, ObligationCauseCode};
|
use rustc_trait_selection::traits::{self, ObligationCauseCode};
|
||||||
|
@ -694,7 +694,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
let error = Some(Sorts(ExpectedFound { expected: ty, found: e_ty }));
|
let error = Some(Sorts(ExpectedFound { expected: ty, found: e_ty }));
|
||||||
self.annotate_loop_expected_due_to_inference(err, expr, error);
|
self.annotate_loop_expected_due_to_inference(err, expr, error);
|
||||||
if let Some(val) = ty_kind_suggestion(ty, tcx) {
|
if let Some(val) =
|
||||||
|
self.err_ctxt().ty_kind_suggestion(self.param_env, ty)
|
||||||
|
{
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
expr.span.shrink_to_hi(),
|
expr.span.shrink_to_hi(),
|
||||||
"give the `break` a value of the expected type",
|
"give the `break` a value of the expected type",
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(control_flow_enum)]
|
#![feature(control_flow_enum)]
|
||||||
#![feature(extract_if)]
|
#![feature(extract_if)]
|
||||||
|
#![feature(if_let_guard)]
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![feature(option_take_if)]
|
#![feature(option_take_if)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
|
|
|
@ -4540,6 +4540,61 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ty_kind_suggestion(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> Option<String> {
|
||||||
|
let tcx = self.infcx.tcx;
|
||||||
|
let implements_default = |ty| {
|
||||||
|
let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
self.type_implements_trait(default_trait, [ty], param_env).must_apply_modulo_regions()
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(match ty.kind() {
|
||||||
|
ty::Never | ty::Error(_) => return None,
|
||||||
|
ty::Bool => "false".to_string(),
|
||||||
|
ty::Char => "\'x\'".to_string(),
|
||||||
|
ty::Int(_) | ty::Uint(_) => "42".into(),
|
||||||
|
ty::Float(_) => "3.14159".into(),
|
||||||
|
ty::Slice(_) => "[]".to_string(),
|
||||||
|
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => {
|
||||||
|
"vec![]".to_string()
|
||||||
|
}
|
||||||
|
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::String) => {
|
||||||
|
"String::new()".to_string()
|
||||||
|
}
|
||||||
|
ty::Adt(def, args) if def.is_box() => {
|
||||||
|
format!("Box::new({})", self.ty_kind_suggestion(param_env, args[0].expect_ty())?)
|
||||||
|
}
|
||||||
|
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Option) => {
|
||||||
|
"None".to_string()
|
||||||
|
}
|
||||||
|
ty::Adt(def, args) if Some(def.did()) == tcx.get_diagnostic_item(sym::Result) => {
|
||||||
|
format!("Ok({})", self.ty_kind_suggestion(param_env, args[0].expect_ty())?)
|
||||||
|
}
|
||||||
|
ty::Adt(_, _) if implements_default(ty) => "Default::default()".to_string(),
|
||||||
|
ty::Ref(_, ty, mutability) => {
|
||||||
|
if let (ty::Str, hir::Mutability::Not) = (ty.kind(), mutability) {
|
||||||
|
"\"\"".to_string()
|
||||||
|
} else {
|
||||||
|
let ty = self.ty_kind_suggestion(param_env, *ty)?;
|
||||||
|
format!("&{}{ty}", mutability.prefix_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ty::Array(ty, len) if let Some(len) = len.try_eval_target_usize(tcx, param_env) => {
|
||||||
|
format!("[{}; {}]", self.ty_kind_suggestion(param_env, *ty)?, len)
|
||||||
|
}
|
||||||
|
ty::Tuple(tys) => format!(
|
||||||
|
"({}{})",
|
||||||
|
tys.iter()
|
||||||
|
.map(|ty| self.ty_kind_suggestion(param_env, ty))
|
||||||
|
.collect::<Option<Vec<String>>>()?
|
||||||
|
.join(", "),
|
||||||
|
if tys.len() == 1 { "," } else { "" }
|
||||||
|
),
|
||||||
|
_ => "value".to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a hint to add a missing borrow or remove an unnecessary one.
|
/// Add a hint to add a missing borrow or remove an unnecessary one.
|
||||||
|
|
8
tests/ui/consts/value-suggestion-ice-123906.rs
Normal file
8
tests/ui/consts/value-suggestion-ice-123906.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
fn as_chunks<const N: usize>() -> [u8; N] {
|
||||||
|
loop {
|
||||||
|
break;
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
18
tests/ui/consts/value-suggestion-ice-123906.stderr
Normal file
18
tests/ui/consts/value-suggestion-ice-123906.stderr
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/value-suggestion-ice-123906.rs:3:9
|
||||||
|
|
|
||||||
|
LL | fn as_chunks<const N: usize>() -> [u8; N] {
|
||||||
|
| ------- expected `[u8; ]` because of this return type
|
||||||
|
LL | loop {
|
||||||
|
| ---- this loop is expected to be of type `[u8; N]`
|
||||||
|
LL | break;
|
||||||
|
| ^^^^^ expected `[u8; N]`, found `()`
|
||||||
|
|
|
||||||
|
help: give the `break` a value of the expected type
|
||||||
|
|
|
||||||
|
LL | break value;
|
||||||
|
| +++++
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
|
@ -5,6 +5,11 @@ LL | fn foo() -> u8 {
|
||||||
| -- expected `u8` because of this return type
|
| -- expected `u8` because of this return type
|
||||||
LL | return;
|
LL | return;
|
||||||
| ^^^^^^ return type is not `()`
|
| ^^^^^^ return type is not `()`
|
||||||
|
|
|
||||||
|
help: give the `return` a value of the expected type
|
||||||
|
|
|
||||||
|
LL | return 42;
|
||||||
|
| ++
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,11 @@ LL | fn g() -> isize { return; }
|
||||||
| ----- ^^^^^^ return type is not `()`
|
| ----- ^^^^^^ return type is not `()`
|
||||||
| |
|
| |
|
||||||
| expected `isize` because of this return type
|
| expected `isize` because of this return type
|
||||||
|
|
|
||||||
|
help: give the `return` a value of the expected type
|
||||||
|
|
|
||||||
|
LL | fn g() -> isize { return 42; }
|
||||||
|
| ++
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
|
6
tests/ui/return/suggest-a-value.rs
Normal file
6
tests/ui/return/suggest-a-value.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
fn test() -> (i32,) {
|
||||||
|
return;
|
||||||
|
//~^ ERROR `return;` in a function whose return type is not `()`
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
16
tests/ui/return/suggest-a-value.stderr
Normal file
16
tests/ui/return/suggest-a-value.stderr
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
error[E0069]: `return;` in a function whose return type is not `()`
|
||||||
|
--> $DIR/suggest-a-value.rs:2:5
|
||||||
|
|
|
||||||
|
LL | fn test() -> (i32,) {
|
||||||
|
| ------ expected `(i32,)` because of this return type
|
||||||
|
LL | return;
|
||||||
|
| ^^^^^^ return type is not `()`
|
||||||
|
|
|
||||||
|
help: give the `return` a value of the expected type
|
||||||
|
|
|
||||||
|
LL | return (42,);
|
||||||
|
| +++++
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0069`.
|
Loading…
Add table
Add a link
Reference in a new issue