mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Auto merge of #95448 - Dylan-DPC:rollup-wpj5yto, r=Dylan-DPC
Rollup of 4 pull requests Successful merges: - #93840 (Stabilize Termination and ExitCode) - #95256 (Ensure io::Error's bitpacked repr doesn't accidentally impl UnwindSafe) - #95386 (Suggest wrapping patterns in enum variants) - #95437 (diagnostics: regression test for derive bounds) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
9c06e1ba47
@ -65,6 +65,7 @@ use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{Item, ItemKind, Node};
|
||||
use rustc_middle::dep_graph::DepContext;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{
|
||||
self,
|
||||
error::TypeError,
|
||||
@ -1736,6 +1737,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
};
|
||||
|
||||
if should_suggest_fixes {
|
||||
self.suggest_tuple_pattern(cause, &exp_found, diag);
|
||||
self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
|
||||
self.suggest_accessing_field_where_appropriate(cause, &exp_found, diag);
|
||||
self.suggest_await_on_expect_found(cause, span, &exp_found, diag);
|
||||
@ -1766,6 +1768,73 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
self.note_error_origin(diag, cause, exp_found, terr);
|
||||
}
|
||||
|
||||
fn suggest_tuple_pattern(
|
||||
&self,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
|
||||
diag: &mut Diagnostic,
|
||||
) {
|
||||
// Heavily inspired by `FnCtxt::suggest_compatible_variants`, with
|
||||
// some modifications due to that being in typeck and this being in infer.
|
||||
if let ObligationCauseCode::Pattern { .. } = cause.code() {
|
||||
if let ty::Adt(expected_adt, substs) = exp_found.expected.kind() {
|
||||
let compatible_variants: Vec<_> = expected_adt
|
||||
.variants()
|
||||
.iter()
|
||||
.filter(|variant| {
|
||||
variant.fields.len() == 1 && variant.ctor_kind == hir::def::CtorKind::Fn
|
||||
})
|
||||
.filter_map(|variant| {
|
||||
let sole_field = &variant.fields[0];
|
||||
let sole_field_ty = sole_field.ty(self.tcx, substs);
|
||||
if same_type_modulo_infer(sole_field_ty, exp_found.found) {
|
||||
let variant_path =
|
||||
with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id));
|
||||
// FIXME #56861: DRYer prelude filtering
|
||||
if let Some(path) = variant_path.strip_prefix("std::prelude::") {
|
||||
if let Some((_, path)) = path.split_once("::") {
|
||||
return Some(path.to_string());
|
||||
}
|
||||
}
|
||||
Some(variant_path)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
match &compatible_variants[..] {
|
||||
[] => {}
|
||||
[variant] => {
|
||||
diag.multipart_suggestion_verbose(
|
||||
&format!("try wrapping the pattern in `{}`", variant),
|
||||
vec![
|
||||
(cause.span.shrink_to_lo(), format!("{}(", variant)),
|
||||
(cause.span.shrink_to_hi(), ")".to_string()),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
// More than one matching variant.
|
||||
diag.multipart_suggestions(
|
||||
&format!(
|
||||
"try wrapping the pattern in a variant of `{}`",
|
||||
self.tcx.def_path_str(expected_adt.did())
|
||||
),
|
||||
compatible_variants.into_iter().map(|variant| {
|
||||
vec![
|
||||
(cause.span.shrink_to_lo(), format!("{}(", variant)),
|
||||
(cause.span.shrink_to_hi(), ")".to_string()),
|
||||
]
|
||||
}),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Binder<'tcx, Ty<'tcx>>> {
|
||||
if let ty::Opaque(def_id, substs) = ty.kind() {
|
||||
let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
|
||||
|
@ -268,10 +268,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
expr_ty: Ty<'tcx>,
|
||||
) {
|
||||
if let ty::Adt(expected_adt, substs) = expected.kind() {
|
||||
if !expected_adt.is_enum() {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the expression is of type () and it's the return expression of a block,
|
||||
// we suggest adding a separate return expression instead.
|
||||
// (To avoid things like suggesting `Ok(while .. { .. })`.)
|
||||
@ -336,7 +332,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let compatible_variants: Vec<String> = expected_adt
|
||||
.variants()
|
||||
.iter()
|
||||
.filter(|variant| variant.fields.len() == 1)
|
||||
.filter(|variant| {
|
||||
variant.fields.len() == 1 && variant.ctor_kind == hir::def::CtorKind::Fn
|
||||
})
|
||||
.filter_map(|variant| {
|
||||
let sole_field = &variant.fields[0];
|
||||
let sole_field_ty = sole_field.ty(self.tcx, substs);
|
||||
|
@ -104,6 +104,7 @@
|
||||
|
||||
use super::{Custom, ErrorData, ErrorKind, SimpleMessage};
|
||||
use alloc::boxed::Box;
|
||||
use core::marker::PhantomData;
|
||||
use core::mem::{align_of, size_of};
|
||||
use core::ptr::NonNull;
|
||||
|
||||
@ -114,8 +115,17 @@ const TAG_CUSTOM: usize = 0b01;
|
||||
const TAG_OS: usize = 0b10;
|
||||
const TAG_SIMPLE: usize = 0b11;
|
||||
|
||||
/// The internal representation.
|
||||
///
|
||||
/// See the module docs for more, this is just a way to hack in a check that we
|
||||
/// indeed are not unwind-safe.
|
||||
///
|
||||
/// ```compile_fail,E0277
|
||||
/// fn is_unwind_safe<T: core::panic::UnwindSafe>() {}
|
||||
/// is_unwind_safe::<std::io::Error>();
|
||||
/// ```
|
||||
#[repr(transparent)]
|
||||
pub(super) struct Repr(NonNull<()>);
|
||||
pub(super) struct Repr(NonNull<()>, PhantomData<ErrorData<Box<Custom>>>);
|
||||
|
||||
// All the types `Repr` stores internally are Send + Sync, and so is it.
|
||||
unsafe impl Send for Repr {}
|
||||
@ -145,7 +155,7 @@ impl Repr {
|
||||
// box, and `TAG_CUSTOM` just... isn't zero -- it's `0b01`). Therefore,
|
||||
// `TAG_CUSTOM + p` isn't zero and so `tagged` can't be, and the
|
||||
// `new_unchecked` is safe.
|
||||
let res = Self(unsafe { NonNull::new_unchecked(tagged) });
|
||||
let res = Self(unsafe { NonNull::new_unchecked(tagged) }, PhantomData);
|
||||
// quickly smoke-check we encoded the right thing (This generally will
|
||||
// only run in libstd's tests, unless the user uses -Zbuild-std)
|
||||
debug_assert!(matches!(res.data(), ErrorData::Custom(_)), "repr(custom) encoding failed");
|
||||
@ -156,7 +166,7 @@ impl Repr {
|
||||
pub(super) fn new_os(code: i32) -> Self {
|
||||
let utagged = ((code as usize) << 32) | TAG_OS;
|
||||
// Safety: `TAG_OS` is not zero, so the result of the `|` is not 0.
|
||||
let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) });
|
||||
let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) }, PhantomData);
|
||||
// quickly smoke-check we encoded the right thing (This generally will
|
||||
// only run in libstd's tests, unless the user uses -Zbuild-std)
|
||||
debug_assert!(
|
||||
@ -170,7 +180,7 @@ impl Repr {
|
||||
pub(super) fn new_simple(kind: ErrorKind) -> Self {
|
||||
let utagged = ((kind as usize) << 32) | TAG_SIMPLE;
|
||||
// Safety: `TAG_SIMPLE` is not zero, so the result of the `|` is not 0.
|
||||
let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) });
|
||||
let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) }, PhantomData);
|
||||
// quickly smoke-check we encoded the right thing (This generally will
|
||||
// only run in libstd's tests, unless the user uses -Zbuild-std)
|
||||
debug_assert!(
|
||||
@ -184,7 +194,7 @@ impl Repr {
|
||||
#[inline]
|
||||
pub(super) const fn new_simple_message(m: &'static SimpleMessage) -> Self {
|
||||
// Safety: References are never null.
|
||||
Self(unsafe { NonNull::new_unchecked(m as *const _ as *mut ()) })
|
||||
Self(unsafe { NonNull::new_unchecked(m as *const _ as *mut ()) }, PhantomData)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -1417,6 +1417,15 @@ impl From<fs::File> for Stdio {
|
||||
/// For proper error reporting of failed processes, print the value of `ExitStatus` or
|
||||
/// `ExitStatusError` using their implementations of [`Display`](crate::fmt::Display).
|
||||
///
|
||||
/// # Differences from `ExitStatus`
|
||||
///
|
||||
/// `ExitCode` is intended for terminating the currently running process, via
|
||||
/// the `Termination` trait, in contrast to [`ExitStatus`], which represents the
|
||||
/// termination of a child process. These APIs are separate due to platform
|
||||
/// compatibility differences and their expected usage; it is not generally
|
||||
/// possible to exactly reproduce an ExitStatus from a child for the current
|
||||
/// process after the fact.
|
||||
///
|
||||
/// [`status`]: Command::status
|
||||
/// [`wait`]: Child::wait
|
||||
//
|
||||
@ -1649,8 +1658,16 @@ impl fmt::Display for ExitStatusError {
|
||||
#[unstable(feature = "exit_status_error", issue = "84908")]
|
||||
impl crate::error::Error for ExitStatusError {}
|
||||
|
||||
/// This type represents the status code a process can return to its
|
||||
/// parent under normal termination.
|
||||
/// This type represents the status code the current process can return
|
||||
/// to its parent under normal termination.
|
||||
///
|
||||
/// `ExitCode` is intended to be consumed only by the standard library (via
|
||||
/// [`Termination::report()`]), and intentionally does not provide accessors like
|
||||
/// `PartialEq`, `Eq`, or `Hash`. Instead the standard library provides the
|
||||
/// canonical `SUCCESS` and `FAILURE` exit codes as well as `From<u8> for
|
||||
/// ExitCode` for constructing other arbitrary exit codes.
|
||||
///
|
||||
/// # Portability
|
||||
///
|
||||
/// Numeric values used in this type don't have portable meanings, and
|
||||
/// different platforms may mask different amounts of them.
|
||||
@ -1661,52 +1678,78 @@ impl crate::error::Error for ExitStatusError {}
|
||||
/// [`SUCCESS`]: ExitCode::SUCCESS
|
||||
/// [`FAILURE`]: ExitCode::FAILURE
|
||||
///
|
||||
/// **Warning**: While various forms of this were discussed in [RFC #1937],
|
||||
/// it was ultimately cut from that RFC, and thus this type is more subject
|
||||
/// to change even than the usual unstable item churn.
|
||||
/// # Differences from `ExitStatus`
|
||||
///
|
||||
/// [RFC #1937]: https://github.com/rust-lang/rfcs/pull/1937
|
||||
/// `ExitCode` is intended for terminating the currently running process, via
|
||||
/// the `Termination` trait, in contrast to [`ExitStatus`], which represents the
|
||||
/// termination of a child process. These APIs are separate due to platform
|
||||
/// compatibility differences and their expected usage; it is not generally
|
||||
/// possible to exactly reproduce an ExitStatus from a child for the current
|
||||
/// process after the fact.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// `ExitCode` can be returned from the `main` function of a crate, as it implements
|
||||
/// [`Termination`]:
|
||||
///
|
||||
/// ```
|
||||
/// use std::process::ExitCode;
|
||||
/// # fn check_foo() -> bool { true }
|
||||
///
|
||||
/// fn main() -> ExitCode {
|
||||
/// if !check_foo() {
|
||||
/// return ExitCode::from(42);
|
||||
/// }
|
||||
///
|
||||
/// ExitCode::SUCCESS
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
|
||||
#[stable(feature = "process_exitcode", since = "1.60.0")]
|
||||
pub struct ExitCode(imp::ExitCode);
|
||||
|
||||
#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
|
||||
#[stable(feature = "process_exitcode", since = "1.60.0")]
|
||||
impl ExitCode {
|
||||
/// The canonical ExitCode for successful termination on this platform.
|
||||
/// The canonical `ExitCode` for successful termination on this platform.
|
||||
///
|
||||
/// Note that a `()`-returning `main` implicitly results in a successful
|
||||
/// termination, so there's no need to return this from `main` unless
|
||||
/// you're also returning other possible codes.
|
||||
#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
|
||||
#[stable(feature = "process_exitcode", since = "1.60.0")]
|
||||
pub const SUCCESS: ExitCode = ExitCode(imp::ExitCode::SUCCESS);
|
||||
|
||||
/// The canonical ExitCode for unsuccessful termination on this platform.
|
||||
/// The canonical `ExitCode` for unsuccessful termination on this platform.
|
||||
///
|
||||
/// If you're only returning this and `SUCCESS` from `main`, consider
|
||||
/// instead returning `Err(_)` and `Ok(())` respectively, which will
|
||||
/// return the same codes (but will also `eprintln!` the error).
|
||||
#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
|
||||
#[stable(feature = "process_exitcode", since = "1.60.0")]
|
||||
pub const FAILURE: ExitCode = ExitCode(imp::ExitCode::FAILURE);
|
||||
}
|
||||
|
||||
impl ExitCode {
|
||||
// This should not be stabilized when stabilizing ExitCode, we don't know that i32 will serve
|
||||
// This is private/perma-unstable because ExitCode is opaque; we don't know that i32 will serve
|
||||
// all usecases, for example windows seems to use u32, unix uses the 8-15th bits of an i32, we
|
||||
// likely want to isolate users anything that could restrict the platform specific
|
||||
// representation of an ExitCode
|
||||
//
|
||||
// More info: https://internals.rust-lang.org/t/mini-pre-rfc-redesigning-process-exitstatus/5426
|
||||
/// Convert an ExitCode into an i32
|
||||
#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
|
||||
/// Convert an `ExitCode` into an i32
|
||||
#[unstable(
|
||||
feature = "process_exitcode_internals",
|
||||
reason = "exposed only for libstd",
|
||||
issue = "none"
|
||||
)]
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
pub fn to_i32(self) -> i32 {
|
||||
self.0.as_i32()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
|
||||
#[stable(feature = "process_exitcode", since = "1.60.0")]
|
||||
impl From<u8> for ExitCode {
|
||||
/// Construct an exit code from an arbitrary u8 value.
|
||||
/// Construct an `ExitCode` from an arbitrary u8 value.
|
||||
fn from(code: u8) -> Self {
|
||||
ExitCode(imp::ExitCode::from(code))
|
||||
}
|
||||
@ -2049,7 +2092,7 @@ pub fn id() -> u32 {
|
||||
/// standard library's runtime for convenience. Other runtimes are not required
|
||||
/// to provide similar functionality.
|
||||
#[cfg_attr(not(test), lang = "termination")]
|
||||
#[unstable(feature = "termination_trait_lib", issue = "43301")]
|
||||
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
|
||||
#[rustc_on_unimplemented(
|
||||
message = "`main` has invalid return type `{Self}`",
|
||||
label = "`main` can only return types that implement `{Termination}`"
|
||||
@ -2057,10 +2100,11 @@ pub fn id() -> u32 {
|
||||
pub trait Termination {
|
||||
/// Is called to get the representation of the value as status code.
|
||||
/// This status code is returned to the operating system.
|
||||
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
|
||||
fn report(self) -> ExitCode;
|
||||
}
|
||||
|
||||
#[unstable(feature = "termination_trait_lib", issue = "43301")]
|
||||
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
|
||||
impl Termination for () {
|
||||
#[inline]
|
||||
fn report(self) -> ExitCode {
|
||||
@ -2068,7 +2112,7 @@ impl Termination for () {
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "termination_trait_lib", issue = "43301")]
|
||||
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
|
||||
impl<E: fmt::Debug> Termination for Result<(), E> {
|
||||
fn report(self) -> ExitCode {
|
||||
match self {
|
||||
@ -2078,14 +2122,14 @@ impl<E: fmt::Debug> Termination for Result<(), E> {
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "termination_trait_lib", issue = "43301")]
|
||||
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
|
||||
impl Termination for ! {
|
||||
fn report(self) -> ExitCode {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "termination_trait_lib", issue = "43301")]
|
||||
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
|
||||
impl<E: fmt::Debug> Termination for Result<!, E> {
|
||||
fn report(self) -> ExitCode {
|
||||
let Err(err) = self;
|
||||
@ -2094,7 +2138,7 @@ impl<E: fmt::Debug> Termination for Result<!, E> {
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "termination_trait_lib", issue = "43301")]
|
||||
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
|
||||
impl<E: fmt::Debug> Termination for Result<Infallible, E> {
|
||||
fn report(self) -> ExitCode {
|
||||
let Err(err) = self;
|
||||
@ -2102,7 +2146,7 @@ impl<E: fmt::Debug> Termination for Result<Infallible, E> {
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "termination_trait_lib", issue = "43301")]
|
||||
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
|
||||
impl Termination for ExitCode {
|
||||
#[inline]
|
||||
fn report(self) -> ExitCode {
|
||||
|
@ -19,8 +19,7 @@
|
||||
#![feature(bench_black_box)]
|
||||
#![feature(internal_output_capture)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(termination_trait_lib)]
|
||||
#![feature(process_exitcode_placeholder)]
|
||||
#![feature(process_exitcode_internals)]
|
||||
#![feature(test)]
|
||||
#![feature(total_cmp)]
|
||||
|
||||
|
41
src/test/ui/did_you_mean/compatible-variants-in-pat.rs
Normal file
41
src/test/ui/did_you_mean/compatible-variants-in-pat.rs
Normal file
@ -0,0 +1,41 @@
|
||||
enum Foo {
|
||||
Bar(Bar),
|
||||
}
|
||||
struct Bar {
|
||||
x: i32,
|
||||
}
|
||||
|
||||
fn a(f: Foo) {
|
||||
match f {
|
||||
Bar { x } => {
|
||||
//~^ ERROR mismatched types
|
||||
//~| HELP try wrapping
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct S;
|
||||
|
||||
fn b(s: Option<S>) {
|
||||
match s {
|
||||
S => {
|
||||
//~^ ERROR mismatched types
|
||||
//~| HELP try wrapping
|
||||
//~| HELP introduce a new binding instead
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn c(s: Result<S, S>) {
|
||||
match s {
|
||||
S => {
|
||||
//~^ ERROR mismatched types
|
||||
//~| HELP try wrapping
|
||||
//~| HELP introduce a new binding instead
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
68
src/test/ui/did_you_mean/compatible-variants-in-pat.stderr
Normal file
68
src/test/ui/did_you_mean/compatible-variants-in-pat.stderr
Normal file
@ -0,0 +1,68 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/compatible-variants-in-pat.rs:10:9
|
||||
|
|
||||
LL | match f {
|
||||
| - this expression has type `Foo`
|
||||
LL | Bar { x } => {
|
||||
| ^^^^^^^^^ expected enum `Foo`, found struct `Bar`
|
||||
|
|
||||
help: try wrapping the pattern in `Foo::Bar`
|
||||
|
|
||||
LL | Foo::Bar(Bar { x }) => {
|
||||
| +++++++++ +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/compatible-variants-in-pat.rs:21:9
|
||||
|
|
||||
LL | struct S;
|
||||
| --------- unit struct defined here
|
||||
...
|
||||
LL | match s {
|
||||
| - this expression has type `Option<S>`
|
||||
LL | S => {
|
||||
| ^
|
||||
| |
|
||||
| expected enum `Option`, found struct `S`
|
||||
| `S` is interpreted as a unit struct, not a new binding
|
||||
|
|
||||
= note: expected enum `Option<S>`
|
||||
found struct `S`
|
||||
help: try wrapping the pattern in `Some`
|
||||
|
|
||||
LL | Some(S) => {
|
||||
| +++++ +
|
||||
help: introduce a new binding instead
|
||||
|
|
||||
LL | other_s => {
|
||||
| ~~~~~~~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/compatible-variants-in-pat.rs:32:9
|
||||
|
|
||||
LL | struct S;
|
||||
| --------- unit struct defined here
|
||||
...
|
||||
LL | match s {
|
||||
| - this expression has type `Result<S, S>`
|
||||
LL | S => {
|
||||
| ^
|
||||
| |
|
||||
| expected enum `Result`, found struct `S`
|
||||
| `S` is interpreted as a unit struct, not a new binding
|
||||
|
|
||||
= note: expected enum `Result<S, S>`
|
||||
found struct `S`
|
||||
help: try wrapping the pattern in a variant of `Result`
|
||||
|
|
||||
LL | Ok(S) => {
|
||||
| +++ +
|
||||
LL | Err(S) => {
|
||||
| ++++ +
|
||||
help: introduce a new binding instead
|
||||
|
|
||||
LL | other_s => {
|
||||
| ~~~~~~~
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -64,3 +64,27 @@ fn main() {
|
||||
//~^ ERROR mismatched types
|
||||
//~| HELP try wrapping
|
||||
}
|
||||
|
||||
enum A {
|
||||
B { b: B},
|
||||
}
|
||||
|
||||
struct A2(B);
|
||||
|
||||
enum B {
|
||||
Fst,
|
||||
Snd,
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
// We don't want to suggest `A::B(B::Fst)` here.
|
||||
let a: A = B::Fst;
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn bar() {
|
||||
// But we _do_ want to suggest `A2(B::Fst)` here!
|
||||
let a: A2 = B::Fst;
|
||||
//~^ ERROR mismatched types
|
||||
//~| HELP try wrapping
|
||||
}
|
||||
|
@ -190,6 +190,27 @@ help: try wrapping the expression in `Some`
|
||||
LL | let _ = Foo { bar: Some(bar) };
|
||||
| ++++++++++ +
|
||||
|
||||
error: aborting due to 11 previous errors
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/compatible-variants.rs:81:16
|
||||
|
|
||||
LL | let a: A = B::Fst;
|
||||
| - ^^^^^^ expected enum `A`, found enum `B`
|
||||
| |
|
||||
| expected due to this
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/compatible-variants.rs:87:17
|
||||
|
|
||||
LL | let a: A2 = B::Fst;
|
||||
| -- ^^^^^^ expected struct `A2`, found enum `B`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
help: try wrapping the expression in `A2`
|
||||
|
|
||||
LL | let a: A2 = A2(B::Fst);
|
||||
| +++ +
|
||||
|
||||
error: aborting due to 13 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -8,6 +8,10 @@ LL | Some(k) => match k {
|
||||
|
|
||||
= note: expected enum `Result<_, {integer}>`
|
||||
found enum `Option<_>`
|
||||
help: try wrapping the pattern in `Ok`
|
||||
|
|
||||
LL | Ok(Some(k)) => match k {
|
||||
| +++ +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-12552.rs:9:5
|
||||
@ -20,6 +24,10 @@ LL | None => ()
|
||||
|
|
||||
= note: expected enum `Result<_, {integer}>`
|
||||
found enum `Option<_>`
|
||||
help: try wrapping the pattern in `Ok`
|
||||
|
|
||||
LL | Ok(None) => ()
|
||||
| +++ +
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -8,6 +8,10 @@ LL | Err(_) => ()
|
||||
|
|
||||
= note: expected enum `Option<_>`
|
||||
found enum `Result<_, _>`
|
||||
help: try wrapping the pattern in `Some`
|
||||
|
|
||||
LL | Some(Err(_)) => ()
|
||||
| +++++ +
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -8,6 +8,10 @@ LL | Either::Right(_) => {}
|
||||
|
|
||||
= note: expected struct `S`
|
||||
found enum `Either<_, _>`
|
||||
help: try wrapping the pattern in `S`
|
||||
|
|
||||
LL | S(Either::Right(_)) => {}
|
||||
| ++ +
|
||||
help: you might have meant to use field `0` whose type is `Either<usize, usize>`
|
||||
|
|
||||
LL | match S(Either::Left(5)).0 {
|
||||
|
@ -1,5 +1,4 @@
|
||||
// run-pass
|
||||
#![feature(process_exitcode_placeholder)]
|
||||
|
||||
use std::process::ExitCode;
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
// run-pass
|
||||
#![feature(termination_trait_lib)]
|
||||
|
||||
fn main() -> impl std::process::Termination { }
|
||||
|
18
src/test/ui/suggestions/derive-clone-for-eq.fixed
Normal file
18
src/test/ui/suggestions/derive-clone-for-eq.fixed
Normal file
@ -0,0 +1,18 @@
|
||||
// run-rustfix
|
||||
// https://github.com/rust-lang/rust/issues/79076
|
||||
|
||||
use std::cmp::PartialEq;
|
||||
|
||||
#[derive(Clone, Eq)] //~ ERROR [E0277]
|
||||
pub struct Struct<T: std::clone::Clone>(T);
|
||||
|
||||
impl<T: Clone, U> PartialEq<U> for Struct<T>
|
||||
where
|
||||
U: Into<Struct<T>> + Clone
|
||||
{
|
||||
fn eq(&self, _other: &U) -> bool {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
18
src/test/ui/suggestions/derive-clone-for-eq.rs
Normal file
18
src/test/ui/suggestions/derive-clone-for-eq.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// run-rustfix
|
||||
// https://github.com/rust-lang/rust/issues/79076
|
||||
|
||||
use std::cmp::PartialEq;
|
||||
|
||||
#[derive(Clone, Eq)] //~ ERROR [E0277]
|
||||
pub struct Struct<T>(T);
|
||||
|
||||
impl<T: Clone, U> PartialEq<U> for Struct<T>
|
||||
where
|
||||
U: Into<Struct<T>> + Clone
|
||||
{
|
||||
fn eq(&self, _other: &U) -> bool {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
25
src/test/ui/suggestions/derive-clone-for-eq.stderr
Normal file
25
src/test/ui/suggestions/derive-clone-for-eq.stderr
Normal file
@ -0,0 +1,25 @@
|
||||
error[E0277]: the trait bound `T: Clone` is not satisfied
|
||||
--> $DIR/derive-clone-for-eq.rs:6:17
|
||||
|
|
||||
LL | #[derive(Clone, Eq)]
|
||||
| ^^ the trait `Clone` is not implemented for `T`
|
||||
|
|
||||
note: required because of the requirements on the impl of `PartialEq` for `Struct<T>`
|
||||
--> $DIR/derive-clone-for-eq.rs:9:19
|
||||
|
|
||||
LL | impl<T: Clone, U> PartialEq<U> for Struct<T>
|
||||
| ^^^^^^^^^^^^ ^^^^^^^^^
|
||||
note: required by a bound in `Eq`
|
||||
--> $SRC_DIR/core/src/cmp.rs:LL:COL
|
||||
|
|
||||
LL | pub trait Eq: PartialEq<Self> {
|
||||
| ^^^^^^^^^^^^^^^ required by this bound in `Eq`
|
||||
= note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | pub struct Struct<T: std::clone::Clone>(T);
|
||||
| +++++++++++++++++++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
Loading…
Reference in New Issue
Block a user