mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Rollup merge of #115879 - clubby789:migrate-hir-typeck-cast, r=compiler-errors
Migrate diagnostics in `hir_typeck/src/cast.rs`
This commit is contained in:
commit
970ee09c22
@ -16,6 +16,21 @@ hir_typeck_candidate_trait_note = `{$trait_name}` defines an item `{$item_name}`
|
||||
*[other] , perhaps you need to restrict type parameter `{$action_or_ty}` with it
|
||||
}
|
||||
|
||||
hir_typeck_cannot_cast_to_bool = cannot cast `{$expr_ty}` as `bool`
|
||||
.suggestion = compare with zero instead
|
||||
.help = compare with zero instead
|
||||
.label = unsupported cast
|
||||
|
||||
hir_typeck_cast_enum_drop = cannot cast enum `{$expr_ty}` into integer `{$cast_ty}` because it implements `Drop`
|
||||
|
||||
hir_typeck_cast_unknown_pointer = cannot cast {$to ->
|
||||
[true] to
|
||||
*[false] from
|
||||
} a pointer of an unknown kind
|
||||
.label_to = needs more type information
|
||||
.note = the type information given here is insufficient to check whether the pointer cast is valid
|
||||
.label_from = the type information given here is insufficient to check whether the pointer cast is valid
|
||||
|
||||
hir_typeck_const_select_must_be_const = this argument must be a `const fn`
|
||||
.help = consult the documentation on `const_eval_select` for more information
|
||||
|
||||
@ -29,6 +44,8 @@ hir_typeck_convert_using_method = try using `{$sugg}` to convert `{$found}` to `
|
||||
|
||||
hir_typeck_ctor_is_private = tuple struct constructor `{$def}` is private
|
||||
|
||||
hir_typeck_deref_is_empty = this expression `Deref`s to `{$deref_ty}` which implements `is_empty`
|
||||
|
||||
hir_typeck_expected_default_return_type = expected `()` because of default return type
|
||||
|
||||
hir_typeck_expected_return_type = expected `{$expected}` because of return type
|
||||
@ -57,6 +74,13 @@ hir_typeck_functional_record_update_on_non_struct =
|
||||
hir_typeck_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
|
||||
hir_typeck_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
|
||||
|
||||
hir_typeck_int_to_fat = cannot cast `{$expr_ty}` to a pointer that {$known_wide ->
|
||||
[true] is
|
||||
*[false] may be
|
||||
} wide
|
||||
hir_typeck_int_to_fat_label = creating a `{$cast_ty}` requires both an address and {$metadata}
|
||||
hir_typeck_int_to_fat_label_nightly = consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts`
|
||||
|
||||
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`
|
||||
@ -69,6 +93,16 @@ hir_typeck_lang_start_incorrect_param = parameter {$param_num} of the `start` la
|
||||
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
|
||||
.help = if you can't comply with strict provenance and don't have a pointer with the correct provenance you can use `std::ptr::from_exposed_addr()` instead
|
||||
|
||||
hir_typeck_lossy_provenance_ptr2int =
|
||||
under strict provenance it is considered bad style to cast pointer `{$expr_ty}` to integer `{$cast_ty}`
|
||||
.suggestion = use `.addr()` to obtain the address of a pointer
|
||||
.help = if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
|
||||
|
||||
hir_typeck_method_call_on_unknown_raw_pointee =
|
||||
cannot call a method on a raw pointer with an unknown pointee type
|
||||
|
||||
@ -113,8 +147,18 @@ hir_typeck_suggest_boxing_when_appropriate = store this in the heap by calling `
|
||||
|
||||
hir_typeck_suggest_ptr_null_mut = consider using `core::ptr::null_mut` instead
|
||||
|
||||
hir_typeck_trivial_cast = trivial {$numeric ->
|
||||
[true] numeric cast
|
||||
*[false] cast
|
||||
}: `{$expr_ty}` as `{$cast_ty}`
|
||||
.help = cast can be replaced by coercion; this might require a temporary variable
|
||||
|
||||
hir_typeck_union_pat_dotdot = `..` cannot be used in union patterns
|
||||
|
||||
hir_typeck_union_pat_multiple_fields = union patterns should have exactly one field
|
||||
|
||||
hir_typeck_use_is_empty =
|
||||
consider using the `is_empty` method on `{$expr_ty}` to determine if it contains anything
|
||||
|
||||
hir_typeck_yield_expr_outside_of_generator =
|
||||
yield expression outside of generator literal
|
||||
|
@ -30,11 +30,10 @@
|
||||
|
||||
use super::FnCtxt;
|
||||
|
||||
use crate::errors;
|
||||
use crate::type_error_struct;
|
||||
use hir::ExprKind;
|
||||
use rustc_errors::{
|
||||
struct_span_err, Applicability, DelayDm, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
|
||||
};
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_hir as hir;
|
||||
use rustc_macros::{TypeFoldable, TypeVisitable};
|
||||
use rustc_middle::mir::Mutability;
|
||||
@ -321,33 +320,15 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
.emit();
|
||||
}
|
||||
CastError::CastToBool => {
|
||||
let mut err = struct_span_err!(
|
||||
fcx.tcx.sess,
|
||||
self.span,
|
||||
E0054,
|
||||
"cannot cast `{}` as `bool`",
|
||||
self.expr_ty
|
||||
);
|
||||
|
||||
if self.expr_ty.is_numeric() {
|
||||
match fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) {
|
||||
Ok(snippet) => {
|
||||
err.span_suggestion(
|
||||
self.span,
|
||||
"compare with zero instead",
|
||||
format!("{snippet} != 0"),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
Err(_) => {
|
||||
err.span_help(self.span, "compare with zero instead");
|
||||
}
|
||||
}
|
||||
let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
|
||||
let help = if self.expr_ty.is_numeric() {
|
||||
errors::CannotCastToBoolHelp::Numeric(
|
||||
self.expr_span.shrink_to_hi().with_hi(self.span.hi()),
|
||||
)
|
||||
} else {
|
||||
err.span_label(self.span, "unsupported cast");
|
||||
}
|
||||
|
||||
err.emit();
|
||||
errors::CannotCastToBoolHelp::Unsupported(self.span)
|
||||
};
|
||||
fcx.tcx.sess.emit_err(errors::CannotCastToBool { span: self.span, expr_ty, help });
|
||||
}
|
||||
CastError::CastToChar => {
|
||||
let mut err = type_error_struct!(
|
||||
@ -536,33 +517,20 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
.emit();
|
||||
}
|
||||
CastError::IntToFatCast(known_metadata) => {
|
||||
let mut err = struct_span_err!(
|
||||
fcx.tcx.sess,
|
||||
self.cast_span,
|
||||
E0606,
|
||||
"cannot cast `{}` to a pointer that {} wide",
|
||||
fcx.ty_to_string(self.expr_ty),
|
||||
if known_metadata.is_some() { "is" } else { "may be" }
|
||||
);
|
||||
|
||||
err.span_label(
|
||||
self.cast_span,
|
||||
format!(
|
||||
"creating a `{}` requires both an address and {}",
|
||||
self.cast_ty,
|
||||
known_metadata.unwrap_or("type-specific metadata"),
|
||||
),
|
||||
);
|
||||
|
||||
if fcx.tcx.sess.is_nightly_build() {
|
||||
err.span_label(
|
||||
self.expr_span,
|
||||
"consider casting this expression to `*const ()`, \
|
||||
then using `core::ptr::from_raw_parts`",
|
||||
);
|
||||
}
|
||||
|
||||
err.emit();
|
||||
let expr_if_nightly = fcx.tcx.sess.is_nightly_build().then_some(self.expr_span);
|
||||
let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty);
|
||||
let expr_ty = fcx.ty_to_string(self.expr_ty);
|
||||
let metadata = known_metadata.unwrap_or("type-specific metadata");
|
||||
let known_wide = known_metadata.is_some();
|
||||
let span = self.cast_span;
|
||||
fcx.tcx.sess.emit_err(errors::IntToWide {
|
||||
span,
|
||||
metadata,
|
||||
expr_ty,
|
||||
cast_ty,
|
||||
expr_if_nightly,
|
||||
known_wide,
|
||||
});
|
||||
}
|
||||
CastError::UnknownCastPtrKind | CastError::UnknownExprPtrKind => {
|
||||
let unknown_cast_to = match e {
|
||||
@ -570,27 +538,16 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
CastError::UnknownExprPtrKind => false,
|
||||
_ => bug!(),
|
||||
};
|
||||
let mut err = struct_span_err!(
|
||||
fcx.tcx.sess,
|
||||
if unknown_cast_to { self.cast_span } else { self.span },
|
||||
E0641,
|
||||
"cannot cast {} a pointer of an unknown kind",
|
||||
if unknown_cast_to { "to" } else { "from" }
|
||||
);
|
||||
if unknown_cast_to {
|
||||
err.span_label(self.cast_span, "needs more type information");
|
||||
err.note(
|
||||
"the type information given here is insufficient to check whether \
|
||||
the pointer cast is valid",
|
||||
);
|
||||
let (span, sub) = if unknown_cast_to {
|
||||
(self.cast_span, errors::CastUnknownPointerSub::To(self.cast_span))
|
||||
} else {
|
||||
err.span_label(
|
||||
self.span,
|
||||
"the type information given here is insufficient to check whether \
|
||||
the pointer cast is valid",
|
||||
);
|
||||
}
|
||||
err.emit();
|
||||
(self.cast_span, errors::CastUnknownPointerSub::From(self.span))
|
||||
};
|
||||
fcx.tcx.sess.emit_err(errors::CastUnknownPointer {
|
||||
span,
|
||||
to: unknown_cast_to,
|
||||
sub,
|
||||
});
|
||||
}
|
||||
CastError::ForeignNonExhaustiveAdt => {
|
||||
make_invalid_casting_error(
|
||||
@ -674,31 +631,18 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
}
|
||||
|
||||
fn trivial_cast_lint(&self, fcx: &FnCtxt<'a, 'tcx>) {
|
||||
let t_cast = self.cast_ty;
|
||||
let t_expr = self.expr_ty;
|
||||
let (adjective, lint) = if t_cast.is_numeric() && t_expr.is_numeric() {
|
||||
("numeric ", lint::builtin::TRIVIAL_NUMERIC_CASTS)
|
||||
let (numeric, lint) = if self.cast_ty.is_numeric() && self.expr_ty.is_numeric() {
|
||||
(true, lint::builtin::TRIVIAL_NUMERIC_CASTS)
|
||||
} else {
|
||||
("", lint::builtin::TRIVIAL_CASTS)
|
||||
(false, lint::builtin::TRIVIAL_CASTS)
|
||||
};
|
||||
fcx.tcx.struct_span_lint_hir(
|
||||
let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
|
||||
let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty);
|
||||
fcx.tcx.emit_spanned_lint(
|
||||
lint,
|
||||
self.expr.hir_id,
|
||||
self.span,
|
||||
DelayDm(|| {
|
||||
format!(
|
||||
"trivial {}cast: `{}` as `{}`",
|
||||
adjective,
|
||||
fcx.ty_to_string(t_expr),
|
||||
fcx.ty_to_string(t_cast)
|
||||
)
|
||||
}),
|
||||
|lint| {
|
||||
lint.help(
|
||||
"cast can be replaced by coercion; this might \
|
||||
require a temporary variable",
|
||||
)
|
||||
},
|
||||
errors::TrivialCast { numeric, expr_ty, cast_ty },
|
||||
);
|
||||
}
|
||||
|
||||
@ -991,93 +935,67 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
if let ty::Adt(d, _) = self.expr_ty.kind()
|
||||
&& d.has_dtor(fcx.tcx)
|
||||
{
|
||||
fcx.tcx.struct_span_lint_hir(
|
||||
let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
|
||||
let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty);
|
||||
|
||||
fcx.tcx.emit_spanned_lint(
|
||||
lint::builtin::CENUM_IMPL_DROP_CAST,
|
||||
self.expr.hir_id,
|
||||
self.span,
|
||||
DelayDm(|| format!(
|
||||
"cannot cast enum `{}` into integer `{}` because it implements `Drop`",
|
||||
self.expr_ty, self.cast_ty
|
||||
)),
|
||||
|lint| {
|
||||
lint
|
||||
},
|
||||
errors::CastEnumDrop {
|
||||
expr_ty,
|
||||
cast_ty,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn lossy_provenance_ptr2int_lint(&self, fcx: &FnCtxt<'a, 'tcx>, t_c: ty::cast::IntTy) {
|
||||
fcx.tcx.struct_span_lint_hir(
|
||||
let expr_prec = self.expr.precedence().order();
|
||||
let needs_parens = expr_prec < rustc_ast::util::parser::PREC_POSTFIX;
|
||||
|
||||
let needs_cast = !matches!(t_c, ty::cast::IntTy::U(ty::UintTy::Usize));
|
||||
let cast_span = self.expr_span.shrink_to_hi().to(self.cast_span);
|
||||
let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
|
||||
let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty);
|
||||
let expr_span = self.expr_span.shrink_to_lo();
|
||||
let sugg = match (needs_parens, needs_cast) {
|
||||
(true, true) => errors::LossyProvenancePtr2IntSuggestion::NeedsParensCast {
|
||||
expr_span,
|
||||
cast_span,
|
||||
cast_ty,
|
||||
},
|
||||
(true, false) => {
|
||||
errors::LossyProvenancePtr2IntSuggestion::NeedsParens { expr_span, cast_span }
|
||||
}
|
||||
(false, true) => {
|
||||
errors::LossyProvenancePtr2IntSuggestion::NeedsCast { cast_span, cast_ty }
|
||||
}
|
||||
(false, false) => errors::LossyProvenancePtr2IntSuggestion::Other { cast_span },
|
||||
};
|
||||
|
||||
let lint = errors::LossyProvenancePtr2Int { expr_ty, cast_ty, sugg };
|
||||
fcx.tcx.emit_spanned_lint(
|
||||
lint::builtin::LOSSY_PROVENANCE_CASTS,
|
||||
self.expr.hir_id,
|
||||
self.span,
|
||||
DelayDm(|| format!(
|
||||
"under strict provenance it is considered bad style to cast pointer `{}` to integer `{}`",
|
||||
self.expr_ty, self.cast_ty
|
||||
)),
|
||||
|lint| {
|
||||
let msg = "use `.addr()` to obtain the address of a pointer";
|
||||
|
||||
let expr_prec = self.expr.precedence().order();
|
||||
let needs_parens = expr_prec < rustc_ast::util::parser::PREC_POSTFIX;
|
||||
|
||||
let scalar_cast = match t_c {
|
||||
ty::cast::IntTy::U(ty::UintTy::Usize) => String::new(),
|
||||
_ => format!(" as {}", self.cast_ty),
|
||||
};
|
||||
|
||||
let cast_span = self.expr_span.shrink_to_hi().to(self.cast_span);
|
||||
|
||||
if needs_parens {
|
||||
let suggestions = vec![
|
||||
(self.expr_span.shrink_to_lo(), String::from("(")),
|
||||
(cast_span, format!(").addr(){scalar_cast}")),
|
||||
];
|
||||
|
||||
lint.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
|
||||
} else {
|
||||
lint.span_suggestion(
|
||||
cast_span,
|
||||
msg,
|
||||
format!(".addr(){scalar_cast}"),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
|
||||
lint.help(
|
||||
"if you can't comply with strict provenance and need to expose the pointer \
|
||||
provenance you can use `.expose_addr()` instead"
|
||||
);
|
||||
|
||||
lint
|
||||
},
|
||||
lint,
|
||||
);
|
||||
}
|
||||
|
||||
fn fuzzy_provenance_int2ptr_lint(&self, fcx: &FnCtxt<'a, 'tcx>) {
|
||||
fcx.tcx.struct_span_lint_hir(
|
||||
let sugg = errors::LossyProvenanceInt2PtrSuggestion {
|
||||
lo: self.expr_span.shrink_to_lo(),
|
||||
hi: self.expr_span.shrink_to_hi().to(self.cast_span),
|
||||
};
|
||||
let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
|
||||
let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty);
|
||||
let lint = errors::LossyProvenanceInt2Ptr { expr_ty, cast_ty, sugg };
|
||||
fcx.tcx.emit_spanned_lint(
|
||||
lint::builtin::FUZZY_PROVENANCE_CASTS,
|
||||
self.expr.hir_id,
|
||||
self.span,
|
||||
DelayDm(|| format!(
|
||||
"strict provenance disallows casting integer `{}` to pointer `{}`",
|
||||
self.expr_ty, self.cast_ty
|
||||
)),
|
||||
|lint| {
|
||||
let msg = "use `.with_addr()` to adjust a valid pointer in the same allocation, to this address";
|
||||
let suggestions = vec![
|
||||
(self.expr_span.shrink_to_lo(), String::from("(...).with_addr(")),
|
||||
(self.expr_span.shrink_to_hi().to(self.cast_span), String::from(")")),
|
||||
];
|
||||
|
||||
lint.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
|
||||
lint.help(
|
||||
"if you can't comply with strict provenance and don't have a pointer with \
|
||||
the correct provenance you can use `std::ptr::from_exposed_addr()` instead"
|
||||
);
|
||||
|
||||
lint
|
||||
},
|
||||
lint,
|
||||
);
|
||||
}
|
||||
|
||||
@ -1093,26 +1011,19 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
if let Some((deref_ty, _)) = derefed {
|
||||
// Give a note about what the expr derefs to.
|
||||
if deref_ty != self.expr_ty.peel_refs() {
|
||||
err.span_note(
|
||||
self.expr_span,
|
||||
format!(
|
||||
"this expression `Deref`s to `{}` which implements `is_empty`",
|
||||
fcx.ty_to_string(deref_ty)
|
||||
),
|
||||
);
|
||||
err.subdiagnostic(errors::DerefImplsIsEmpty {
|
||||
span: self.expr_span,
|
||||
deref_ty: fcx.ty_to_string(deref_ty),
|
||||
});
|
||||
}
|
||||
|
||||
// Create a multipart suggestion: add `!` and `.is_empty()` in
|
||||
// place of the cast.
|
||||
let suggestion = vec![
|
||||
(self.expr_span.shrink_to_lo(), "!".to_string()),
|
||||
(self.span.with_lo(self.expr_span.hi()), ".is_empty()".to_string()),
|
||||
];
|
||||
|
||||
err.multipart_suggestion_verbose(format!(
|
||||
"consider using the `is_empty` method on `{}` to determine if it contains anything",
|
||||
fcx.ty_to_string(self.expr_ty),
|
||||
), suggestion, Applicability::MaybeIncorrect);
|
||||
err.subdiagnostic(errors::UseIsEmpty {
|
||||
lo: self.expr_span.shrink_to_lo(),
|
||||
hi: self.span.with_lo(self.expr_span.hi()),
|
||||
expr_ty: fcx.ty_to_string(self.expr_ty),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use rustc_errors::{
|
||||
AddToDiagnostic, Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnosticArg, MultiSpan,
|
||||
SubdiagnosticMessage,
|
||||
};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_span::{
|
||||
edition::{Edition, LATEST_STABLE_EDITION},
|
||||
@ -269,6 +269,69 @@ pub struct LangStartIncorrectRetTy<'tcx> {
|
||||
pub found_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(hir_typeck_lossy_provenance_int2ptr)]
|
||||
#[help]
|
||||
pub struct LossyProvenanceInt2Ptr<'tcx> {
|
||||
pub expr_ty: Ty<'tcx>,
|
||||
pub cast_ty: Ty<'tcx>,
|
||||
#[subdiagnostic]
|
||||
pub sugg: LossyProvenanceInt2PtrSuggestion,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(hir_typeck_suggestion, applicability = "has-placeholders")]
|
||||
pub struct LossyProvenanceInt2PtrSuggestion {
|
||||
#[suggestion_part(code = "(...).with_addr(")]
|
||||
pub lo: Span,
|
||||
#[suggestion_part(code = ")")]
|
||||
pub hi: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(hir_typeck_lossy_provenance_ptr2int)]
|
||||
#[help]
|
||||
pub struct LossyProvenancePtr2Int<'tcx> {
|
||||
pub expr_ty: Ty<'tcx>,
|
||||
pub cast_ty: Ty<'tcx>,
|
||||
#[subdiagnostic]
|
||||
pub sugg: LossyProvenancePtr2IntSuggestion<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub enum LossyProvenancePtr2IntSuggestion<'tcx> {
|
||||
#[multipart_suggestion(hir_typeck_suggestion, applicability = "maybe-incorrect")]
|
||||
NeedsParensCast {
|
||||
#[suggestion_part(code = "(")]
|
||||
expr_span: Span,
|
||||
#[suggestion_part(code = ").addr() as {cast_ty}")]
|
||||
cast_span: Span,
|
||||
cast_ty: Ty<'tcx>,
|
||||
},
|
||||
#[multipart_suggestion(hir_typeck_suggestion, applicability = "maybe-incorrect")]
|
||||
NeedsParens {
|
||||
#[suggestion_part(code = "(")]
|
||||
expr_span: Span,
|
||||
#[suggestion_part(code = ").addr()")]
|
||||
cast_span: Span,
|
||||
},
|
||||
#[suggestion(
|
||||
hir_typeck_suggestion,
|
||||
code = ".addr() as {cast_ty}",
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
NeedsCast {
|
||||
#[primary_span]
|
||||
cast_span: Span,
|
||||
cast_ty: Ty<'tcx>,
|
||||
},
|
||||
#[suggestion(hir_typeck_suggestion, code = ".addr()", applicability = "maybe-incorrect")]
|
||||
Other {
|
||||
#[primary_span]
|
||||
cast_span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub enum HelpUseLatestEdition {
|
||||
#[help(hir_typeck_help_set_edition_cargo)]
|
||||
@ -298,6 +361,20 @@ pub struct InvalidCallee {
|
||||
pub ty: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_int_to_fat, code = "E0606")]
|
||||
pub struct IntToWide<'tcx> {
|
||||
#[primary_span]
|
||||
#[label(hir_typeck_int_to_fat_label)]
|
||||
pub span: Span,
|
||||
pub metadata: &'tcx str,
|
||||
pub expr_ty: String,
|
||||
pub cast_ty: Ty<'tcx>,
|
||||
#[label(hir_typeck_int_to_fat_label_nightly)]
|
||||
pub expr_if_nightly: Option<Span>,
|
||||
pub known_wide: bool,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub enum OptionResultRefMismatch {
|
||||
#[suggestion(
|
||||
@ -396,6 +473,20 @@ pub struct UnionPatDotDot {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(
|
||||
hir_typeck_use_is_empty,
|
||||
applicability = "maybe-incorrect",
|
||||
style = "verbose"
|
||||
)]
|
||||
pub struct UseIsEmpty {
|
||||
#[suggestion_part(code = "!")]
|
||||
pub lo: Span,
|
||||
#[suggestion_part(code = ".is_empty()")]
|
||||
pub hi: Span,
|
||||
pub expr_ty: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_arg_mismatch_indeterminate)]
|
||||
pub struct ArgMismatchIndeterminate {
|
||||
@ -442,6 +533,15 @@ pub struct SuggestPtrNullMut {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(hir_typeck_trivial_cast)]
|
||||
#[help]
|
||||
pub struct TrivialCast<'tcx> {
|
||||
pub numeric: bool,
|
||||
pub expr_ty: Ty<'tcx>,
|
||||
pub cast_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_no_associated_item, code = "E0599")]
|
||||
pub struct NoAssociatedItem {
|
||||
@ -464,6 +564,74 @@ pub struct CandidateTraitNote {
|
||||
pub action_or_ty: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_cannot_cast_to_bool, code = "E0054")]
|
||||
pub struct CannotCastToBool<'tcx> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub expr_ty: Ty<'tcx>,
|
||||
#[subdiagnostic]
|
||||
pub help: CannotCastToBoolHelp,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(hir_typeck_cast_enum_drop)]
|
||||
pub struct CastEnumDrop<'tcx> {
|
||||
pub expr_ty: Ty<'tcx>,
|
||||
pub cast_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_cast_unknown_pointer, code = "E0641")]
|
||||
pub struct CastUnknownPointer {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub to: bool,
|
||||
#[subdiagnostic]
|
||||
pub sub: CastUnknownPointerSub,
|
||||
}
|
||||
|
||||
pub enum CastUnknownPointerSub {
|
||||
To(Span),
|
||||
From(Span),
|
||||
}
|
||||
|
||||
impl rustc_errors::AddToDiagnostic for CastUnknownPointerSub {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, f: F)
|
||||
where
|
||||
F: Fn(
|
||||
&mut Diagnostic,
|
||||
rustc_errors::SubdiagnosticMessage,
|
||||
) -> rustc_errors::SubdiagnosticMessage,
|
||||
{
|
||||
match self {
|
||||
CastUnknownPointerSub::To(span) => {
|
||||
let msg = f(diag, crate::fluent_generated::hir_typeck_label_to.into());
|
||||
diag.span_label(span, msg);
|
||||
let msg = f(diag, crate::fluent_generated::hir_typeck_note.into());
|
||||
diag.note(msg);
|
||||
}
|
||||
CastUnknownPointerSub::From(span) => {
|
||||
let msg = f(diag, crate::fluent_generated::hir_typeck_label_from.into());
|
||||
diag.span_label(span, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub enum CannotCastToBoolHelp {
|
||||
#[suggestion(
|
||||
hir_typeck_suggestion,
|
||||
applicability = "machine-applicable",
|
||||
code = " != 0",
|
||||
style = "verbose"
|
||||
)]
|
||||
Numeric(#[primary_span] Span),
|
||||
#[label(hir_typeck_label)]
|
||||
Unsupported(#[primary_span] Span),
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_ctor_is_private, code = "E0603")]
|
||||
pub struct CtorIsPrivate {
|
||||
@ -472,6 +640,14 @@ pub struct CtorIsPrivate {
|
||||
pub def: String,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[note(hir_typeck_deref_is_empty)]
|
||||
pub struct DerefImplsIsEmpty {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub deref_ty: String,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(
|
||||
hir_typeck_convert_using_method,
|
||||
|
@ -1,11 +1,11 @@
|
||||
fn main() {
|
||||
let u = 5 as bool; //~ ERROR cannot cast `i32` as `bool`
|
||||
//~| HELP compare with zero instead
|
||||
//~| SUGGESTION 5 != 0
|
||||
//~| SUGGESTION != 0
|
||||
|
||||
let t = (1 + 2) as bool; //~ ERROR cannot cast `i32` as `bool`
|
||||
//~| HELP compare with zero instead
|
||||
//~| SUGGESTION (1 + 2) != 0
|
||||
//~| SUGGESTION != 0
|
||||
|
||||
let _ = 5_u32 as bool; //~ ERROR cannot cast `u32` as `bool`
|
||||
//~| HELP compare with zero instead
|
||||
|
@ -2,25 +2,45 @@ error[E0054]: cannot cast `i32` as `bool`
|
||||
--> $DIR/cast-as-bool.rs:2:13
|
||||
|
|
||||
LL | let u = 5 as bool;
|
||||
| ^^^^^^^^^ help: compare with zero instead: `5 != 0`
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
help: compare with zero instead
|
||||
|
|
||||
LL | let u = 5 != 0;
|
||||
| ~~~~
|
||||
|
||||
error[E0054]: cannot cast `i32` as `bool`
|
||||
--> $DIR/cast-as-bool.rs:6:13
|
||||
|
|
||||
LL | let t = (1 + 2) as bool;
|
||||
| ^^^^^^^^^^^^^^^ help: compare with zero instead: `(1 + 2) != 0`
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: compare with zero instead
|
||||
|
|
||||
LL | let t = (1 + 2) != 0;
|
||||
| ~~~~
|
||||
|
||||
error[E0054]: cannot cast `u32` as `bool`
|
||||
--> $DIR/cast-as-bool.rs:10:13
|
||||
|
|
||||
LL | let _ = 5_u32 as bool;
|
||||
| ^^^^^^^^^^^^^ help: compare with zero instead: `5_u32 != 0`
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
help: compare with zero instead
|
||||
|
|
||||
LL | let _ = 5_u32 != 0;
|
||||
| ~~~~
|
||||
|
||||
error[E0054]: cannot cast `f64` as `bool`
|
||||
--> $DIR/cast-as-bool.rs:13:13
|
||||
|
|
||||
LL | let _ = 64.0_f64 as bool;
|
||||
| ^^^^^^^^^^^^^^^^ help: compare with zero instead: `64.0_f64 != 0`
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: compare with zero instead
|
||||
|
|
||||
LL | let _ = 64.0_f64 != 0;
|
||||
| ~~~~
|
||||
|
||||
error[E0054]: cannot cast `IntEnum` as `bool`
|
||||
--> $DIR/cast-as-bool.rs:24:13
|
||||
|
@ -2,7 +2,12 @@ error[E0054]: cannot cast `i32` as `bool`
|
||||
--> $DIR/cast-rfc0401-2.rs:6:13
|
||||
|
|
||||
LL | let _ = 3 as bool;
|
||||
| ^^^^^^^^^ help: compare with zero instead: `3 != 0`
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
help: compare with zero instead
|
||||
|
|
||||
LL | let _ = 3 != 0;
|
||||
| ~~~~
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -2,7 +2,12 @@ error[E0054]: cannot cast `i32` as `bool`
|
||||
--> $DIR/E0054.rs:3:24
|
||||
|
|
||||
LL | let x_is_nonzero = x as bool;
|
||||
| ^^^^^^^^^ help: compare with zero instead: `x != 0`
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
help: compare with zero instead
|
||||
|
|
||||
LL | let x_is_nonzero = x != 0;
|
||||
| ~~~~
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -63,7 +63,12 @@ error[E0054]: cannot cast `{integer}` as `bool`
|
||||
--> $DIR/error-festival.rs:33:24
|
||||
|
|
||||
LL | let x_is_nonzero = x as bool;
|
||||
| ^^^^^^^^^ help: compare with zero instead: `x != 0`
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
help: compare with zero instead
|
||||
|
|
||||
LL | let x_is_nonzero = x != 0;
|
||||
| ~~~~
|
||||
|
||||
error[E0606]: casting `&u8` as `u32` is invalid
|
||||
--> $DIR/error-festival.rs:37:18
|
||||
|
@ -86,7 +86,12 @@ error[E0054]: cannot cast `i32` as `bool`
|
||||
--> $DIR/cast-rfc0401.rs:39:13
|
||||
|
|
||||
LL | let _ = 3_i32 as bool;
|
||||
| ^^^^^^^^^^^^^ help: compare with zero instead: `3_i32 != 0`
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
help: compare with zero instead
|
||||
|
|
||||
LL | let _ = 3_i32 != 0;
|
||||
| ~~~~
|
||||
|
||||
error[E0054]: cannot cast `E` as `bool`
|
||||
--> $DIR/cast-rfc0401.rs:40:13
|
||||
|
Loading…
Reference in New Issue
Block a user