Auto merge of #106760 - compiler-errors:rollup-0bogyco, r=compiler-errors

Rollup of 8 pull requests

Successful merges:

 - #103236 (doc: rewrite doc for signed int::{carrying_add,borrowing_sub})
 - #103800 (Stabilize `::{core,std}::pin::pin!`)
 - #106097 (Migrate mir_build diagnostics 2 of 3)
 - #106170 (Move autoderef to `rustc_hir_analysis`)
 - #106323 (Stabilize f16c_target_feature)
 - #106360 (Tweak E0277 `&`-removal suggestions)
 - #106524 (Label `struct/enum constructor` instead of `fn item`, mention that it should be called on type mismatch)
 - #106739 (Remove `<dyn AstConv<'tcx>>::fun(c, ...)` calls in favour of `c.astconv().fun(...)`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-01-12 10:46:19 +00:00
commit 606c390725
108 changed files with 1713 additions and 1422 deletions

View file

@ -187,7 +187,7 @@
("bmi2", None), ("bmi2", None),
("cmpxchg16b", Some(sym::cmpxchg16b_target_feature)), ("cmpxchg16b", Some(sym::cmpxchg16b_target_feature)),
("ermsb", Some(sym::ermsb_target_feature)), ("ermsb", Some(sym::ermsb_target_feature)),
("f16c", Some(sym::f16c_target_feature)), ("f16c", None),
("fma", None), ("fma", None),
("fxsr", None), ("fxsr", None),
("gfni", Some(sym::avx512_target_feature)), ("gfni", Some(sym::avx512_target_feature)),
@ -396,7 +396,6 @@ pub fn from_target_feature(
Some(sym::cmpxchg16b_target_feature) => rust_features.cmpxchg16b_target_feature, Some(sym::cmpxchg16b_target_feature) => rust_features.cmpxchg16b_target_feature,
Some(sym::movbe_target_feature) => rust_features.movbe_target_feature, Some(sym::movbe_target_feature) => rust_features.movbe_target_feature,
Some(sym::rtm_target_feature) => rust_features.rtm_target_feature, Some(sym::rtm_target_feature) => rust_features.rtm_target_feature,
Some(sym::f16c_target_feature) => rust_features.f16c_target_feature,
Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature, Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature,
Some(sym::bpf_target_feature) => rust_features.bpf_target_feature, Some(sym::bpf_target_feature) => rust_features.bpf_target_feature,
Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature, Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature,

View file

@ -120,3 +120,7 @@ hir_analysis_self_in_impl_self =
hir_analysis_linkage_type = hir_analysis_linkage_type =
invalid type for variable with `#[linkage]` attribute invalid type for variable with `#[linkage]` attribute
hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
.label = deref recursion limit reached
.help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)

View file

@ -303,3 +303,64 @@ mir_build_multiple_mut_borrows = cannot borrow value as mutable more than once a
.mutable_borrow = another mutable borrow, by `{$name_mut}`, occurs here .mutable_borrow = another mutable borrow, by `{$name_mut}`, occurs here
.immutable_borrow = also borrowed as immutable, by `{$name_immut}`, here .immutable_borrow = also borrowed as immutable, by `{$name_immut}`, here
.moved = also moved into `{$name_moved}` here .moved = also moved into `{$name_moved}` here
mir_build_union_pattern = cannot use unions in constant patterns
mir_build_type_not_structural =
to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
mir_build_unsized_pattern = cannot use unsized non-slice type `{$non_sm_ty}` in constant patterns
mir_build_invalid_pattern = `{$non_sm_ty}` cannot be used in patterns
mir_build_float_pattern = floating-point types cannot be used in patterns
mir_build_pointer_pattern = function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
mir_build_indirect_structural_match =
to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
mir_build_nontrivial_structural_match =
to use a constant of type `{$non_sm_ty}` in a pattern, the constant's initializer must be trivial or `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
mir_build_overlapping_range_endpoints = multiple patterns overlap on their endpoints
.range = ... with this range
.note = you likely meant to write mutually exclusive ranges
mir_build_non_exhaustive_omitted_pattern = some variants are not matched explicitly
.help = ensure that all variants are matched explicitly by adding the suggested match arms
.note = the matched value is of type `{$scrut_ty}` and the `non_exhaustive_omitted_patterns` attribute was found
mir_build_uncovered = {$count ->
[1] pattern `{$witness_1}`
[2] patterns `{$witness_1}` and `{$witness_2}`
[3] patterns `{$witness_1}`, `{$witness_2}` and `{$witness_3}`
*[other] patterns `{$witness_1}`, `{$witness_2}`, `{$witness_3}` and {$remainder} more
} not covered
mir_build_pattern_not_covered = refutable pattern in {$origin}
.pattern_ty = the matched value is of type `{$pattern_ty}`
mir_build_inform_irrefutable = `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
mir_build_more_information = for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
mir_build_res_defined_here = {$res} defined here
mir_build_adt_defined_here = `{$ty}` defined here
mir_build_variant_defined_here = not covered
mir_build_interpreted_as_const = introduce a variable instead
mir_build_confused = missing patterns are not covered because `{$variable}` is interpreted as {$article} {$res} pattern, not a new variable
mir_build_suggest_if_let = you might want to use `if let` to ignore the {$count ->
[one] variant that isn't
*[other] variants that aren't
} matched
mir_build_suggest_let_else = you might want to use `let else` to handle the {$count ->
[one] variant that isn't
*[other] variants that aren't
} matched

View file

@ -2,10 +2,6 @@ trait_selection_dump_vtable_entries = vtable entries for `{$trait_ref}`: {$entri
trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated} trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated}
trait_selection_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
.label = deref recursion limit reached
.help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
trait_selection_empty_on_clause_in_rustc_on_unimplemented = empty `on`-clause in `#[rustc_on_unimplemented]` trait_selection_empty_on_clause_in_rustc_on_unimplemented = empty `on`-clause in `#[rustc_on_unimplemented]`
.label = empty on-clause here .label = empty on-clause here

View file

@ -161,6 +161,8 @@ macro_rules! declare_features {
(accepted, extern_crate_self, "1.34.0", Some(56409), None), (accepted, extern_crate_self, "1.34.0", Some(56409), None),
/// Allows access to crate names passed via `--extern` through prelude. /// Allows access to crate names passed via `--extern` through prelude.
(accepted, extern_prelude, "1.30.0", Some(44660), None), (accepted, extern_prelude, "1.30.0", Some(44660), None),
/// Allows using F16C intrinsics from `core::arch::{x86, x86_64}`.
(accepted, f16c_target_feature, "CURRENT_RUSTC_VERSION", Some(44839), None),
/// Allows field shorthands (`x` meaning `x: x`) in struct literal expressions. /// Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
(accepted, field_init_shorthand, "1.17.0", Some(37340), None), (accepted, field_init_shorthand, "1.17.0", Some(37340), None),
/// Allows `#[must_use]` on functions, and introduces must-use operators (RFC 1940). /// Allows `#[must_use]` on functions, and introduces must-use operators (RFC 1940).

View file

@ -254,7 +254,6 @@ pub fn set(&self, features: &mut Features, span: Span) {
(active, bpf_target_feature, "1.54.0", Some(44839), None), (active, bpf_target_feature, "1.54.0", Some(44839), None),
(active, cmpxchg16b_target_feature, "1.32.0", Some(44839), None), (active, cmpxchg16b_target_feature, "1.32.0", Some(44839), None),
(active, ermsb_target_feature, "1.49.0", Some(44839), None), (active, ermsb_target_feature, "1.49.0", Some(44839), None),
(active, f16c_target_feature, "1.36.0", Some(44839), None),
(active, hexagon_target_feature, "1.27.0", Some(44839), None), (active, hexagon_target_feature, "1.27.0", Some(44839), None),
(active, mips_target_feature, "1.27.0", Some(44839), None), (active, mips_target_feature, "1.27.0", Some(44839), None),
(active, movbe_target_feature, "1.34.0", Some(44839), None), (active, movbe_target_feature, "1.34.0", Some(44839), None),

File diff suppressed because it is too large Load diff

View file

@ -3,8 +3,11 @@
//! instance of `AstConv`. //! instance of `AstConv`.
mod errors; mod errors;
mod generics; pub mod generics;
use crate::astconv::generics::{
check_generic_arg_count, create_substs_for_generic_args, prohibit_assoc_ty_binding,
};
use crate::bounds::Bounds; use crate::bounds::Bounds;
use crate::collect::HirPlaceholderCollector; use crate::collect::HirPlaceholderCollector;
use crate::errors::{ use crate::errors::{
@ -120,6 +123,13 @@ fn projected_ty_from_poly_trait_ref(
fn set_tainted_by_errors(&self, e: ErrorGuaranteed); fn set_tainted_by_errors(&self, e: ErrorGuaranteed);
fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span); fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span);
fn astconv(&self) -> &dyn AstConv<'tcx>
where
Self: Sized,
{
self
}
} }
#[derive(Debug)] #[derive(Debug)]
@ -279,7 +289,7 @@ pub fn ast_path_substs_for_ty(
ty::BoundConstness::NotConst, ty::BoundConstness::NotConst,
); );
if let Some(b) = item_segment.args().bindings.first() { if let Some(b) = item_segment.args().bindings.first() {
Self::prohibit_assoc_ty_binding(self.tcx(), b.span); prohibit_assoc_ty_binding(self.tcx(), b.span);
} }
substs substs
@ -349,7 +359,7 @@ fn create_substs_for_ast_path<'a>(
assert!(self_ty.is_none()); assert!(self_ty.is_none());
} }
let arg_count = Self::check_generic_arg_count( let arg_count = check_generic_arg_count(
tcx, tcx,
span, span,
def_id, def_id,
@ -524,7 +534,7 @@ fn inferred_kind(
inferred_params: vec![], inferred_params: vec![],
infer_args, infer_args,
}; };
let substs = Self::create_substs_for_generic_args( let substs = create_substs_for_generic_args(
tcx, tcx,
def_id, def_id,
parent_substs, parent_substs,
@ -610,7 +620,7 @@ pub fn create_substs_for_associated_item(
); );
if let Some(b) = item_segment.args().bindings.first() { if let Some(b) = item_segment.args().bindings.first() {
Self::prohibit_assoc_ty_binding(self.tcx(), b.span); prohibit_assoc_ty_binding(self.tcx(), b.span);
} }
args args
@ -804,7 +814,7 @@ fn ast_path_to_mono_trait_ref(
constness, constness,
); );
if let Some(b) = trait_segment.args().bindings.first() { if let Some(b) = trait_segment.args().bindings.first() {
Self::prohibit_assoc_ty_binding(self.tcx(), b.span); prohibit_assoc_ty_binding(self.tcx(), b.span);
} }
self.tcx().mk_trait_ref(trait_def_id, substs) self.tcx().mk_trait_ref(trait_def_id, substs)
} }
@ -2301,7 +2311,7 @@ pub fn prohibit_generics<'a>(
for segment in segments { for segment in segments {
// Only emit the first error to avoid overloading the user with error messages. // Only emit the first error to avoid overloading the user with error messages.
if let Some(b) = segment.args().bindings.first() { if let Some(b) = segment.args().bindings.first() {
Self::prohibit_assoc_ty_binding(self.tcx(), b.span); prohibit_assoc_ty_binding(self.tcx(), b.span);
return true; return true;
} }
} }

View file

@ -178,6 +178,10 @@ pub fn into_obligations(self) -> Vec<traits::PredicateObligation<'tcx>> {
self.state.obligations self.state.obligations
} }
pub fn current_obligations(&self) -> Vec<traits::PredicateObligation<'tcx>> {
self.state.obligations.clone()
}
pub fn steps(&self) -> &[(Ty<'tcx>, AutoderefKind)] { pub fn steps(&self) -> &[(Ty<'tcx>, AutoderefKind)] {
&self.state.steps &self.state.steps
} }

View file

@ -1,4 +1,6 @@
use crate::autoderef::Autoderef;
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter}; use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
use hir::def::DefKind; use hir::def::DefKind;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
@ -22,7 +24,6 @@
use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP}; use rustc_span::{Span, DUMMY_SP};
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
use rustc_trait_selection::autoderef::Autoderef;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;

View file

@ -351,7 +351,7 @@ pub fn new(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> ItemCtxt<'tcx> {
} }
pub fn to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { pub fn to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
<dyn AstConv<'_>>::ast_ty_to_ty(self, ast_ty) self.astconv().ast_ty_to_ty(ast_ty)
} }
pub fn hir_id(&self) -> hir::HirId { pub fn hir_id(&self) -> hir::HirId {
@ -413,8 +413,7 @@ fn projected_ty_from_poly_trait_ref(
poly_trait_ref: ty::PolyTraitRef<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>,
) -> Ty<'tcx> { ) -> Ty<'tcx> {
if let Some(trait_ref) = poly_trait_ref.no_bound_vars() { if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
let item_substs = <dyn AstConv<'tcx>>::create_substs_for_associated_item( let item_substs = self.astconv().create_substs_for_associated_item(
self,
span, span,
item_def_id, item_def_id,
item_segment, item_segment,
@ -1112,8 +1111,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
tcx.hir().get_parent(hir_id) tcx.hir().get_parent(hir_id)
&& i.of_trait.is_some() && i.of_trait.is_some()
{ {
<dyn AstConv<'_>>::ty_of_fn( icx.astconv().ty_of_fn(
&icx,
hir_id, hir_id,
sig.header.unsafety, sig.header.unsafety,
sig.header.abi, sig.header.abi,
@ -1130,15 +1128,9 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _), kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _),
generics, generics,
.. ..
}) => <dyn AstConv<'_>>::ty_of_fn( }) => {
&icx, icx.astconv().ty_of_fn(hir_id, header.unsafety, header.abi, decl, Some(generics), None)
hir_id, }
header.unsafety,
header.abi,
decl,
Some(generics),
None,
),
ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => { ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => {
let abi = tcx.hir().get_foreign_abi(hir_id); let abi = tcx.hir().get_foreign_abi(hir_id);
@ -1244,8 +1236,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
ty::Binder::dummy(fn_sig) ty::Binder::dummy(fn_sig)
} }
None => <dyn AstConv<'_>>::ty_of_fn( None => icx.astconv().ty_of_fn(
icx,
hir_id, hir_id,
sig.header.unsafety, sig.header.unsafety,
sig.header.abi, sig.header.abi,
@ -1354,8 +1345,7 @@ fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
match item.kind { match item.kind {
hir::ItemKind::Impl(ref impl_) => impl_.of_trait.as_ref().map(|ast_trait_ref| { hir::ItemKind::Impl(ref impl_) => impl_.of_trait.as_ref().map(|ast_trait_ref| {
let selfty = tcx.type_of(def_id); let selfty = tcx.type_of(def_id);
<dyn AstConv<'_>>::instantiate_mono_trait_ref( icx.astconv().instantiate_mono_trait_ref(
&icx,
ast_trait_ref, ast_trait_ref,
selfty, selfty,
check_impl_constness(tcx, impl_.constness, ast_trait_ref), check_impl_constness(tcx, impl_.constness, ast_trait_ref),
@ -1485,15 +1475,8 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
hir::Unsafety::Unsafe hir::Unsafety::Unsafe
}; };
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let fty = <dyn AstConv<'_>>::ty_of_fn( let fty =
&ItemCtxt::new(tcx, def_id), ItemCtxt::new(tcx, def_id).astconv().ty_of_fn(hir_id, unsafety, abi, decl, None, None);
hir_id,
unsafety,
abi,
decl,
None,
None,
);
// Feature gate SIMD types in FFI, since I am not sure that the // Feature gate SIMD types in FFI, since I am not sure that the
// ABIs are handled at all correctly. -huonw // ABIs are handled at all correctly. -huonw

View file

@ -26,9 +26,9 @@ fn associated_type_bounds<'tcx>(
); );
let icx = ItemCtxt::new(tcx, assoc_item_def_id); let icx = ItemCtxt::new(tcx, assoc_item_def_id);
let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, ast_bounds); let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds);
// Associated types are implicitly sized unless a `?Sized` bound is found // Associated types are implicitly sized unless a `?Sized` bound is found
<dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, item_ty, ast_bounds, None, span); icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
let trait_def_id = tcx.parent(assoc_item_def_id); let trait_def_id = tcx.parent(assoc_item_def_id);
let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local()); let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local());
@ -70,9 +70,9 @@ fn opaque_type_bounds<'tcx>(
}; };
let icx = ItemCtxt::new(tcx, opaque_def_id); let icx = ItemCtxt::new(tcx, opaque_def_id);
let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, ast_bounds); let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds);
// Opaque types are implicitly sized unless a `?Sized` bound is found // Opaque types are implicitly sized unless a `?Sized` bound is found
<dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, item_ty, ast_bounds, None, span); icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
debug!(?bounds); debug!(?bounds);
tcx.arena.alloc_from_iter(bounds.predicates()) tcx.arena.alloc_from_iter(bounds.predicates())

View file

@ -162,8 +162,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
let mut bounds = Bounds::default(); let mut bounds = Bounds::default();
// Params are implicitly sized unless a `?Sized` bound is found // Params are implicitly sized unless a `?Sized` bound is found
<dyn AstConv<'_>>::add_implicitly_sized( icx.astconv().add_implicitly_sized(
&icx,
&mut bounds, &mut bounds,
param_ty, param_ty,
&[], &[],
@ -211,22 +210,16 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
} }
let mut bounds = Bounds::default(); let mut bounds = Bounds::default();
<dyn AstConv<'_>>::add_bounds( icx.astconv().add_bounds(ty, bound_pred.bounds.iter(), &mut bounds, bound_vars);
&icx,
ty,
bound_pred.bounds.iter(),
&mut bounds,
bound_vars,
);
predicates.extend(bounds.predicates()); predicates.extend(bounds.predicates());
} }
hir::WherePredicate::RegionPredicate(region_pred) => { hir::WherePredicate::RegionPredicate(region_pred) => {
let r1 = <dyn AstConv<'_>>::ast_region_to_region(&icx, &region_pred.lifetime, None); let r1 = icx.astconv().ast_region_to_region(&region_pred.lifetime, None);
predicates.extend(region_pred.bounds.iter().map(|bound| { predicates.extend(region_pred.bounds.iter().map(|bound| {
let (r2, span) = match bound { let (r2, span) = match bound {
hir::GenericBound::Outlives(lt) => { hir::GenericBound::Outlives(lt) => {
(<dyn AstConv<'_>>::ast_region_to_region(&icx, lt, None), lt.ident.span) (icx.astconv().ast_region_to_region(lt, None), lt.ident.span)
} }
_ => bug!(), _ => bug!(),
}; };
@ -279,7 +272,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
debug!(?lifetimes); debug!(?lifetimes);
for (arg, duplicate) in std::iter::zip(lifetimes, ast_generics.params) { for (arg, duplicate) in std::iter::zip(lifetimes, ast_generics.params) {
let hir::GenericArg::Lifetime(arg) = arg else { bug!() }; let hir::GenericArg::Lifetime(arg) = arg else { bug!() };
let orig_region = <dyn AstConv<'_>>::ast_region_to_region(&icx, &arg, None); let orig_region = icx.astconv().ast_region_to_region(&arg, None);
if !matches!(orig_region.kind(), ty::ReEarlyBound(..)) { if !matches!(orig_region.kind(), ty::ReEarlyBound(..)) {
// Only early-bound regions can point to the original generic parameter. // Only early-bound regions can point to the original generic parameter.
continue; continue;
@ -527,14 +520,9 @@ pub(super) fn super_predicates_that_define_assoc_type(
// Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`. // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`.
let self_param_ty = tcx.types.self_param; let self_param_ty = tcx.types.self_param;
let superbounds1 = if let Some(assoc_name) = assoc_name { let superbounds1 = if let Some(assoc_name) = assoc_name {
<dyn AstConv<'_>>::compute_bounds_that_match_assoc_type( icx.astconv().compute_bounds_that_match_assoc_type(self_param_ty, bounds, assoc_name)
&icx,
self_param_ty,
bounds,
assoc_name,
)
} else { } else {
<dyn AstConv<'_>>::compute_bounds(&icx, self_param_ty, bounds) icx.astconv().compute_bounds(self_param_ty, bounds)
}; };
let superbounds1 = superbounds1.predicates(); let superbounds1 = superbounds1.predicates();

View file

@ -300,3 +300,15 @@ pub(crate) struct LinkageType {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(Diagnostic)]
#[help]
#[diag(hir_analysis_auto_deref_reached_recursion_limit, code = "E0055")]
pub struct AutoDerefReachedRecursionLimit<'a> {
#[primary_span]
#[label]
pub span: Span,
pub ty: Ty<'a>,
pub suggested_limit: rustc_session::Limit,
pub crate_name: Symbol,
}

View file

@ -84,6 +84,7 @@
pub mod check; pub mod check;
pub mod astconv; pub mod astconv;
pub mod autoderef;
mod bounds; mod bounds;
mod check_unused; mod check_unused;
mod coherence; mod coherence;
@ -544,7 +545,7 @@ pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> {
// scope. This is derived from the enclosing item-like thing. // scope. This is derived from the enclosing item-like thing.
let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id); let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id);
let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id()); let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
<dyn AstConv<'_>>::ast_ty_to_ty(&item_cx, hir_ty) item_cx.astconv().ast_ty_to_ty(hir_ty)
} }
pub fn hir_trait_to_predicates<'tcx>( pub fn hir_trait_to_predicates<'tcx>(
@ -558,8 +559,7 @@ pub fn hir_trait_to_predicates<'tcx>(
let env_def_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id); let env_def_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id);
let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id()); let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
let mut bounds = Bounds::default(); let mut bounds = Bounds::default();
let _ = <dyn AstConv<'_>>::instantiate_poly_trait_ref( let _ = &item_cx.astconv().instantiate_poly_trait_ref(
&item_cx,
hir_trait, hir_trait,
DUMMY_SP, DUMMY_SP,
ty::BoundConstness::NotConst, ty::BoundConstness::NotConst,

View file

@ -2,11 +2,11 @@
use super::method::MethodCallee; use super::method::MethodCallee;
use super::{FnCtxt, PlaceOp}; use super::{FnCtxt, PlaceOp};
use rustc_hir_analysis::autoderef::{Autoderef, AutoderefKind};
use rustc_infer::infer::InferOk; use rustc_infer::infer::InferOk;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::autoderef::{Autoderef, AutoderefKind};
use std::iter; use std::iter;

View file

@ -8,6 +8,7 @@
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{self, CtorKind, Namespace, Res}; use rustc_hir::def::{self, CtorKind, Namespace, Res};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir_analysis::autoderef::Autoderef;
use rustc_infer::{ use rustc_infer::{
infer, infer,
traits::{self, Obligation}, traits::{self, Obligation},
@ -25,7 +26,6 @@
use rustc_span::symbol::{sym, Ident}; use rustc_span::symbol::{sym, Ident};
use rustc_span::Span; use rustc_span::Span;
use rustc_target::spec::abi; use rustc_target::spec::abi;
use rustc_trait_selection::autoderef::Autoderef;
use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::error_reporting::DefIdOrName; use rustc_trait_selection::traits::error_reporting::DefIdOrName;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;

View file

@ -1807,7 +1807,7 @@ fn add_impl_trait_explanation<'a>(
// Get the return type. // Get the return type.
&& let hir::TyKind::OpaqueDef(..) = ty.kind && let hir::TyKind::OpaqueDef(..) = ty.kind
{ {
let ty = <dyn AstConv<'_>>::ast_ty_to_ty(fcx, ty); let ty = fcx.astconv().ast_ty_to_ty( ty);
// Get the `impl Trait`'s `DefId`. // Get the `impl Trait`'s `DefId`.
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind() if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind()
// Get the `impl Trait`'s `Item` so that we can get its trait bounds and // Get the `impl Trait`'s `Item` so that we can get its trait bounds and
@ -1866,7 +1866,7 @@ fn add_impl_trait_explanation<'a>(
fn is_return_ty_unsized<'a>(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool { fn is_return_ty_unsized<'a>(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool {
if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id) if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id)
&& let hir::FnRetTy::Return(ty) = fn_decl.output && let hir::FnRetTy::Return(ty) = fn_decl.output
&& let ty = <dyn AstConv<'_>>::ast_ty_to_ty(fcx, ty) && let ty = fcx.astconv().ast_ty_to_ty( ty)
&& let ty::Dynamic(..) = ty.kind() && let ty::Dynamic(..) = ty.kind()
{ {
return true; return true;

View file

@ -10,6 +10,9 @@
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_hir::{ExprKind, GenericArg, Node, QPath}; use rustc_hir::{ExprKind, GenericArg, Node, QPath};
use rustc_hir_analysis::astconv::generics::{
check_generic_arg_count_for_call, create_substs_for_generic_args,
};
use rustc_hir_analysis::astconv::{ use rustc_hir_analysis::astconv::{
AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch, AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
GenericArgCountResult, IsMethodCall, PathSeg, GenericArgCountResult, IsMethodCall, PathSeg,
@ -374,7 +377,7 @@ pub fn handle_raw_ty(&self, span: Span, ty: Ty<'tcx>) -> RawTy<'tcx> {
} }
pub fn to_ty(&self, ast_t: &hir::Ty<'_>) -> RawTy<'tcx> { pub fn to_ty(&self, ast_t: &hir::Ty<'_>) -> RawTy<'tcx> {
let t = <dyn AstConv<'_>>::ast_ty_to_ty(self, ast_t); let t = self.astconv().ast_ty_to_ty(ast_t);
self.register_wf_obligation(t.into(), ast_t.span, traits::WellFormed(None)); self.register_wf_obligation(t.into(), ast_t.span, traits::WellFormed(None));
self.handle_raw_ty(ast_t.span, t) self.handle_raw_ty(ast_t.span, t)
} }
@ -777,7 +780,7 @@ pub fn resolve_ty_and_res_fully_qualified_call(
// to be object-safe. // to be object-safe.
// We manually call `register_wf_obligation` in the success path // We manually call `register_wf_obligation` in the success path
// below. // below.
let ty = <dyn AstConv<'_>>::ast_ty_to_ty_in_path(self, qself); let ty = self.astconv().ast_ty_to_ty_in_path(qself);
(self.handle_raw_ty(span, ty), qself, segment) (self.handle_raw_ty(span, ty), qself, segment)
} }
QPath::LangItem(..) => { QPath::LangItem(..) => {
@ -975,8 +978,7 @@ pub fn instantiate_value_path(
let path_segs = match res { let path_segs = match res {
Res::Local(_) | Res::SelfCtor(_) => vec![], Res::Local(_) | Res::SelfCtor(_) => vec![],
Res::Def(kind, def_id) => <dyn AstConv<'_>>::def_ids_for_value_path_segments( Res::Def(kind, def_id) => self.astconv().def_ids_for_value_path_segments(
self,
segments, segments,
self_ty.map(|ty| ty.raw), self_ty.map(|ty| ty.raw),
kind, kind,
@ -1027,8 +1029,7 @@ pub fn instantiate_value_path(
// errors if type parameters are provided in an inappropriate place. // errors if type parameters are provided in an inappropriate place.
let generic_segs: FxHashSet<_> = path_segs.iter().map(|PathSeg(_, index)| index).collect(); let generic_segs: FxHashSet<_> = path_segs.iter().map(|PathSeg(_, index)| index).collect();
let generics_has_err = <dyn AstConv<'_>>::prohibit_generics( let generics_has_err = self.astconv().prohibit_generics(
self,
segments.iter().enumerate().filter_map(|(index, seg)| { segments.iter().enumerate().filter_map(|(index, seg)| {
if !generic_segs.contains(&index) || is_alias_variant_ctor { if !generic_segs.contains(&index) || is_alias_variant_ctor {
Some(seg) Some(seg)
@ -1069,7 +1070,7 @@ pub fn instantiate_value_path(
// parameter internally, but we don't allow users to specify the // parameter internally, but we don't allow users to specify the
// parameter's value explicitly, so we have to do some error- // parameter's value explicitly, so we have to do some error-
// checking here. // checking here.
let arg_count = <dyn AstConv<'_>>::check_generic_arg_count_for_call( let arg_count = check_generic_arg_count_for_call(
tcx, tcx,
span, span,
def_id, def_id,
@ -1177,7 +1178,7 @@ fn provided_kind(
) -> ty::GenericArg<'tcx> { ) -> ty::GenericArg<'tcx> {
match (&param.kind, arg) { match (&param.kind, arg) {
(GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => { (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
<dyn AstConv<'_>>::ast_region_to_region(self.fcx, lt, Some(param)).into() self.fcx.astconv().ast_region_to_region(lt, Some(param)).into()
} }
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
self.fcx.to_ty(ty).raw.into() self.fcx.to_ty(ty).raw.into()
@ -1235,7 +1236,7 @@ fn inferred_kind(
} }
let substs_raw = self_ctor_substs.unwrap_or_else(|| { let substs_raw = self_ctor_substs.unwrap_or_else(|| {
<dyn AstConv<'_>>::create_substs_for_generic_args( create_substs_for_generic_args(
tcx, tcx,
def_id, def_id,
&[], &[],

View file

@ -1664,15 +1664,15 @@ fn finish_resolving_struct_path(
match *qpath { match *qpath {
QPath::Resolved(ref maybe_qself, ref path) => { QPath::Resolved(ref maybe_qself, ref path) => {
let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself).raw); let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself).raw);
let ty = <dyn AstConv<'_>>::res_to_ty(self, self_ty, path, true); let ty = self.astconv().res_to_ty(self_ty, path, true);
(path.res, self.handle_raw_ty(path_span, ty)) (path.res, self.handle_raw_ty(path_span, ty))
} }
QPath::TypeRelative(ref qself, ref segment) => { QPath::TypeRelative(ref qself, ref segment) => {
let ty = self.to_ty(qself); let ty = self.to_ty(qself);
let result = <dyn AstConv<'_>>::associated_path_to_ty( let result = self
self, hir_id, path_span, ty.raw, qself, segment, true, .astconv()
); .associated_path_to_ty(hir_id, path_span, ty.raw, qself, segment, true);
let ty = result.map(|(ty, _, _)| ty).unwrap_or_else(|_| self.tcx().ty_error()); let ty = result.map(|(ty, _, _)| ty).unwrap_or_else(|_| self.tcx().ty_error());
let ty = self.handle_raw_ty(path_span, ty); let ty = self.handle_raw_ty(path_span, ty);
let result = result.map(|(_, kind, def_id)| (kind, def_id)); let result = result.map(|(_, kind, def_id)| (kind, def_id));

View file

@ -20,7 +20,7 @@
use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitable}; use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitable};
use rustc_session::Session; use rustc_session::Session;
use rustc_span::symbol::Ident; use rustc_span::symbol::Ident;
use rustc_span::{self, Span}; use rustc_span::{self, Span, DUMMY_SP};
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt}; use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt};
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
@ -175,6 +175,14 @@ pub fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> {
fn_sig fn_sig
}) })
}), }),
autoderef_steps: Box::new(|ty| {
let mut autoderef = self.autoderef(DUMMY_SP, ty).silence_errors();
let mut steps = vec![];
while let Some((ty, _)) = autoderef.next() {
steps.push((ty, autoderef.current_obligations()));
}
steps
}),
} }
} }
@ -286,8 +294,7 @@ fn projected_ty_from_poly_trait_ref(
poly_trait_ref, poly_trait_ref,
); );
let item_substs = <dyn AstConv<'tcx>>::create_substs_for_associated_item( let item_substs = self.astconv().create_substs_for_associated_item(
self,
span, span,
item_def_id, item_def_id,
item_segment, item_segment,

View file

@ -5,7 +5,7 @@
use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX}; use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX};
use rustc_errors::{Applicability, Diagnostic, MultiSpan}; use rustc_errors::{Applicability, Diagnostic, MultiSpan};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind}; use rustc_hir::def::{CtorKind, CtorOf, DefKind};
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_hir::{ use rustc_hir::{
Expr, ExprKind, GenericBound, Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicate, Expr, ExprKind, GenericBound, Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicate,
@ -417,10 +417,20 @@ pub fn suggest_deref_ref_or_into(
} else if self.suggest_else_fn_with_closure(err, expr, found, expected) { } else if self.suggest_else_fn_with_closure(err, expr, found, expected) {
return true; return true;
} else if self.suggest_fn_call(err, expr, found, |output| self.can_coerce(output, expected)) } else if self.suggest_fn_call(err, expr, found, |output| self.can_coerce(output, expected))
&& let ty::FnDef(def_id, ..) = &found.kind() && let ty::FnDef(def_id, ..) = *found.kind()
&& let Some(sp) = self.tcx.hir().span_if_local(*def_id) && let Some(sp) = self.tcx.hir().span_if_local(def_id)
{ {
err.span_label(sp, format!("{found} defined here")); let name = self.tcx.item_name(def_id);
let kind = self.tcx.def_kind(def_id);
if let DefKind::Ctor(of, CtorKind::Fn) = kind {
err.span_label(sp, format!("`{name}` defines {} constructor here, which should be called", match of {
CtorOf::Struct => "a struct",
CtorOf::Variant => "an enum variant",
}));
} else {
let descr = kind.descr(def_id);
err.span_label(sp, format!("{descr} `{name}` defined here"));
}
return true; return true;
} else if self.check_for_cast(err, expr, found, expected, expected_ty_expr) { } else if self.check_for_cast(err, expr, found, expected, expected_ty_expr) {
return true; return true;
@ -783,7 +793,7 @@ pub(in super::super) fn suggest_missing_return_type(
// are not, the expectation must have been caused by something else. // are not, the expectation must have been caused by something else.
debug!("suggest_missing_return_type: return type {:?} node {:?}", ty, ty.kind); debug!("suggest_missing_return_type: return type {:?} node {:?}", ty, ty.kind);
let span = ty.span; let span = ty.span;
let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, ty); let ty = self.astconv().ast_ty_to_ty(ty);
debug!("suggest_missing_return_type: return type {:?}", ty); debug!("suggest_missing_return_type: return type {:?}", ty);
debug!("suggest_missing_return_type: expected type {:?}", ty); debug!("suggest_missing_return_type: expected type {:?}", ty);
let bound_vars = self.tcx.late_bound_vars(fn_id); let bound_vars = self.tcx.late_bound_vars(fn_id);
@ -854,7 +864,7 @@ fn try_suggest_return_impl_trait(
.. ..
}) => { }) => {
// FIXME: Maybe these calls to `ast_ty_to_ty` can be removed (and the ones below) // FIXME: Maybe these calls to `ast_ty_to_ty` can be removed (and the ones below)
let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, bounded_ty); let ty = self.astconv().ast_ty_to_ty(bounded_ty);
Some((ty, bounds)) Some((ty, bounds))
} }
_ => None, _ => None,
@ -892,7 +902,7 @@ fn try_suggest_return_impl_trait(
let all_bounds_str = all_matching_bounds_strs.join(" + "); let all_bounds_str = all_matching_bounds_strs.join(" + ");
let ty_param_used_in_fn_params = fn_parameters.iter().any(|param| { let ty_param_used_in_fn_params = fn_parameters.iter().any(|param| {
let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, param); let ty = self.astconv().ast_ty_to_ty( param);
matches!(ty.kind(), ty::Param(fn_param_ty_param) if expected_ty_as_param == fn_param_ty_param) matches!(ty.kind(), ty::Param(fn_param_ty_param) if expected_ty_as_param == fn_param_ty_param)
}); });
@ -946,7 +956,7 @@ pub(in super::super) fn suggest_missing_break_or_return_expr(
} }
if let hir::FnRetTy::Return(ty) = fn_decl.output { if let hir::FnRetTy::Return(ty) = fn_decl.output {
let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, ty); let ty = self.astconv().ast_ty_to_ty(ty);
let bound_vars = self.tcx.late_bound_vars(fn_id); let bound_vars = self.tcx.late_bound_vars(fn_id);
let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars)); let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars));
let ty = match self.tcx.asyncness(fn_id.owner) { let ty = match self.tcx.asyncness(fn_id.owner) {
@ -1339,7 +1349,7 @@ pub(crate) fn suggest_associated_const(
hir::Path { segments: [segment], .. }, hir::Path { segments: [segment], .. },
)) ))
| hir::ExprKind::Path(QPath::TypeRelative(ty, segment)) => { | hir::ExprKind::Path(QPath::TypeRelative(ty, segment)) => {
let self_ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, ty); let self_ty = self.astconv().ast_ty_to_ty(ty);
if let Ok(pick) = self.probe_for_name( if let Ok(pick) = self.probe_for_name(
Mode::Path, Mode::Path,
Ident::new(capitalized_name, segment.ident.span), Ident::new(capitalized_name, segment.ident.span),

View file

@ -205,7 +205,7 @@ fn typeck_with_fallback<'tcx>(
if let Some(hir::FnSig { header, decl, .. }) = fn_sig { if let Some(hir::FnSig { header, decl, .. }) = fn_sig {
let fn_sig = if rustc_hir_analysis::collect::get_infer_ret_ty(&decl.output).is_some() { let fn_sig = if rustc_hir_analysis::collect::get_infer_ret_ty(&decl.output).is_some() {
<dyn AstConv<'_>>::ty_of_fn(&fcx, id, header.unsafety, header.abi, decl, None, None) fcx.astconv().ty_of_fn(id, header.unsafety, header.abi, decl, None, None)
} else { } else {
tcx.fn_sig(def_id) tcx.fn_sig(def_id)
}; };
@ -220,7 +220,7 @@ fn typeck_with_fallback<'tcx>(
} else { } else {
let expected_type = body_ty let expected_type = body_ty
.and_then(|ty| match ty.kind { .and_then(|ty| match ty.kind {
hir::TyKind::Infer => Some(<dyn AstConv<'_>>::ast_ty_to_ty(&fcx, ty)), hir::TyKind::Infer => Some(fcx.astconv().ast_ty_to_ty(ty)),
_ => None, _ => None,
}) })
.unwrap_or_else(|| match tcx.hir().get(id) { .unwrap_or_else(|| match tcx.hir().get(id) {

View file

@ -4,6 +4,9 @@
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::GenericArg; use rustc_hir::GenericArg;
use rustc_hir_analysis::astconv::generics::{
check_generic_arg_count_for_call, create_substs_for_generic_args,
};
use rustc_hir_analysis::astconv::{AstConv, CreateSubstsForGenericArgsCtxt, IsMethodCall}; use rustc_hir_analysis::astconv::{AstConv, CreateSubstsForGenericArgsCtxt, IsMethodCall};
use rustc_infer::infer::{self, InferOk}; use rustc_infer::infer::{self, InferOk};
use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext}; use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext};
@ -331,7 +334,7 @@ fn instantiate_method_substs(
// variables. // variables.
let generics = self.tcx.generics_of(pick.item.def_id); let generics = self.tcx.generics_of(pick.item.def_id);
let arg_count_correct = <dyn AstConv<'_>>::check_generic_arg_count_for_call( let arg_count_correct = check_generic_arg_count_for_call(
self.tcx, self.tcx,
self.span, self.span,
pick.item.def_id, pick.item.def_id,
@ -369,8 +372,7 @@ fn provided_kind(
) -> subst::GenericArg<'tcx> { ) -> subst::GenericArg<'tcx> {
match (&param.kind, arg) { match (&param.kind, arg) {
(GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => { (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
<dyn AstConv<'_>>::ast_region_to_region(self.cfcx.fcx, lt, Some(param)) self.cfcx.fcx.astconv().ast_region_to_region(lt, Some(param)).into()
.into()
} }
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
self.cfcx.to_ty(ty).raw.into() self.cfcx.to_ty(ty).raw.into()
@ -399,7 +401,7 @@ fn inferred_kind(
} }
} }
let substs = <dyn AstConv<'_>>::create_substs_for_generic_args( let substs = create_substs_for_generic_args(
self.tcx, self.tcx,
pick.item.def_id, pick.item.def_id,
parent_substs, parent_substs,

View file

@ -9,6 +9,7 @@
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_hir_analysis::autoderef::{self, Autoderef};
use rustc_infer::infer::canonical::OriginalQueryValues; use rustc_infer::infer::canonical::OriginalQueryValues;
use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::canonical::{Canonical, QueryResponse};
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@ -29,7 +30,6 @@
}; };
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use rustc_span::{symbol::Ident, Span, Symbol, DUMMY_SP}; use rustc_span::{symbol::Ident, Span, Symbol, DUMMY_SP};
use rustc_trait_selection::autoderef::{self, Autoderef};
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
use rustc_trait_selection::traits::query::method_autoderef::MethodAutoderefBadTy; use rustc_trait_selection::traits::query::method_autoderef::MethodAutoderefBadTy;
use rustc_trait_selection::traits::query::method_autoderef::{ use rustc_trait_selection::traits::query::method_autoderef::{

View file

@ -3,6 +3,7 @@
use rustc_ast as ast; use rustc_ast as ast;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir_analysis::autoderef::Autoderef;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::InferOk; use rustc_infer::infer::InferOk;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref, PointerCast}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref, PointerCast};
@ -10,7 +11,6 @@
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
use rustc_span::symbol::{sym, Ident}; use rustc_span::symbol::{sym, Ident};
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::autoderef::Autoderef;
use std::slice; use std::slice;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> { impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

View file

@ -55,6 +55,7 @@
use crate::traits::error_reporting::report_object_safety_error; use crate::traits::error_reporting::report_object_safety_error;
use crate::traits::{ use crate::traits::{
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode, IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
PredicateObligation,
}; };
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
@ -91,8 +92,12 @@
pub struct TypeErrCtxt<'a, 'tcx> { pub struct TypeErrCtxt<'a, 'tcx> {
pub infcx: &'a InferCtxt<'tcx>, pub infcx: &'a InferCtxt<'tcx>,
pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>, pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
pub normalize_fn_sig: Box<dyn Fn(ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> + 'a>,
pub fallback_has_occurred: bool, pub fallback_has_occurred: bool,
pub normalize_fn_sig: Box<dyn Fn(ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> + 'a>,
pub autoderef_steps:
Box<dyn Fn(Ty<'tcx>) -> Vec<(Ty<'tcx>, Vec<PredicateObligation<'tcx>>)> + 'a>,
} }
impl TypeErrCtxt<'_, '_> { impl TypeErrCtxt<'_, '_> {

View file

@ -688,6 +688,10 @@ pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> {
typeck_results: None, typeck_results: None,
fallback_has_occurred: false, fallback_has_occurred: false,
normalize_fn_sig: Box::new(|fn_sig| fn_sig), normalize_fn_sig: Box::new(|fn_sig| fn_sig),
autoderef_steps: Box::new(|ty| {
debug_assert!(false, "shouldn't be using autoderef_steps outside of typeck");
vec![(ty, vec![])]
}),
} }
} }

View file

@ -9,6 +9,7 @@
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/thir.html //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/thir.html
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::RangeEnd; use rustc_hir::RangeEnd;
@ -575,6 +576,12 @@ pub fn simple_ident(&self) -> Option<Symbol> {
} }
} }
impl<'tcx> IntoDiagnosticArg for Pat<'tcx> {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
format!("{}", self).into_diagnostic_arg()
}
}
#[derive(Clone, Debug, HashStable)] #[derive(Clone, Debug, HashStable)]
pub struct Ascription<'tcx> { pub struct Ascription<'tcx> {
pub annotation: CanonicalUserTypeAnnotation<'tcx>, pub annotation: CanonicalUserTypeAnnotation<'tcx>,

View file

@ -2,10 +2,10 @@
use crate::ty::diagnostics::suggest_constraining_type_param; use crate::ty::diagnostics::suggest_constraining_type_param;
use crate::ty::print::{with_forced_trimmed_paths, FmtPrinter, Printer}; use crate::ty::print::{with_forced_trimmed_paths, FmtPrinter, Printer};
use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt}; use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
use hir::def::DefKind;
use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect}; use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
use rustc_errors::{pluralize, Diagnostic, MultiSpan}; use rustc_errors::{pluralize, Diagnostic, MultiSpan};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_span::symbol::{sym, Symbol}; use rustc_span::symbol::{sym, Symbol};
use rustc_span::{BytePos, Span}; use rustc_span::{BytePos, Span};
@ -319,7 +319,11 @@ pub fn sort_string(self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
.into() .into()
} }
} }
ty::FnDef(..) => "fn item".into(), ty::FnDef(def_id, ..) => match tcx.def_kind(def_id) {
DefKind::Ctor(CtorOf::Struct, _) => "struct constructor".into(),
DefKind::Ctor(CtorOf::Variant, _) => "enum constructor".into(),
_ => "fn item".into(),
},
ty::FnPtr(_) => "fn pointer".into(), ty::FnPtr(_) => "fn pointer".into(),
ty::Dynamic(ref inner, ..) if let Some(principal) = inner.principal() => { ty::Dynamic(ref inner, ..) if let Some(principal) = inner.principal() => {
format!("trait object `dyn {}`", tcx.def_path_str(principal.def_id())).into() format!("trait object `dyn {}`", tcx.def_path_str(principal.def_id())).into()
@ -366,7 +370,11 @@ pub fn prefix_string(self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
_ => "reference", _ => "reference",
} }
.into(), .into(),
ty::FnDef(..) => "fn item".into(), ty::FnDef(def_id, ..) => match tcx.def_kind(def_id) {
DefKind::Ctor(CtorOf::Struct, _) => "struct constructor".into(),
DefKind::Ctor(CtorOf::Variant, _) => "enum constructor".into(),
_ => "fn item".into(),
},
ty::FnPtr(_) => "fn pointer".into(), ty::FnPtr(_) => "fn pointer".into(),
ty::Dynamic(..) => "trait object".into(), ty::Dynamic(..) => "trait object".into(),
ty::Closure(..) => "closure".into(), ty::Closure(..) => "closure".into(),

View file

@ -1,9 +1,13 @@
use crate::thir::pattern::deconstruct_pat::DeconstructedPat;
use crate::thir::pattern::MatchCheckCtxt; use crate::thir::pattern::MatchCheckCtxt;
use rustc_errors::Handler; use rustc_errors::Handler;
use rustc_errors::{ use rustc_errors::{
error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, MultiSpan, error_code, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
IntoDiagnostic, MultiSpan, SubdiagnosticMessage,
}; };
use rustc_hir::def::Res;
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::thir::Pat;
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
use rustc_span::{symbol::Ident, Span}; use rustc_span::{symbol::Ident, Span};
@ -624,3 +628,223 @@ pub enum MultipleMutBorrowOccurence {
name_moved: Ident, name_moved: Ident,
}, },
} }
#[derive(Diagnostic)]
#[diag(mir_build_union_pattern)]
pub struct UnionPattern {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(mir_build_type_not_structural)]
pub struct TypeNotStructural<'tcx> {
#[primary_span]
pub span: Span,
pub non_sm_ty: Ty<'tcx>,
}
#[derive(Diagnostic)]
#[diag(mir_build_invalid_pattern)]
pub struct InvalidPattern<'tcx> {
#[primary_span]
pub span: Span,
pub non_sm_ty: Ty<'tcx>,
}
#[derive(Diagnostic)]
#[diag(mir_build_unsized_pattern)]
pub struct UnsizedPattern<'tcx> {
#[primary_span]
pub span: Span,
pub non_sm_ty: Ty<'tcx>,
}
#[derive(LintDiagnostic)]
#[diag(mir_build_float_pattern)]
pub struct FloatPattern;
#[derive(LintDiagnostic)]
#[diag(mir_build_pointer_pattern)]
pub struct PointerPattern;
#[derive(LintDiagnostic)]
#[diag(mir_build_indirect_structural_match)]
pub struct IndirectStructuralMatch<'tcx> {
pub non_sm_ty: Ty<'tcx>,
}
#[derive(LintDiagnostic)]
#[diag(mir_build_nontrivial_structural_match)]
pub struct NontrivialStructuralMatch<'tcx> {
pub non_sm_ty: Ty<'tcx>,
}
#[derive(LintDiagnostic)]
#[diag(mir_build_overlapping_range_endpoints)]
#[note]
pub struct OverlappingRangeEndpoints<'tcx> {
#[label(range)]
pub range: Span,
#[subdiagnostic]
pub overlap: Vec<Overlap<'tcx>>,
}
pub struct Overlap<'tcx> {
pub span: Span,
pub range: Pat<'tcx>,
}
impl<'tcx> AddToDiagnostic for Overlap<'tcx> {
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
where
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
{
let Overlap { span, range } = self;
// FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]`
// does not support `#[subdiagnostic(eager)]`...
let message = format!("this range overlaps on `{range}`...");
diag.span_label(span, message);
}
}
#[derive(LintDiagnostic)]
#[diag(mir_build_non_exhaustive_omitted_pattern)]
#[help]
#[note]
pub(crate) struct NonExhaustiveOmittedPattern<'tcx> {
pub scrut_ty: Ty<'tcx>,
#[subdiagnostic]
pub uncovered: Uncovered<'tcx>,
}
#[derive(Subdiagnostic)]
#[label(mir_build_uncovered)]
pub(crate) struct Uncovered<'tcx> {
#[primary_span]
span: Span,
count: usize,
witness_1: Pat<'tcx>,
witness_2: Pat<'tcx>,
witness_3: Pat<'tcx>,
remainder: usize,
}
impl<'tcx> Uncovered<'tcx> {
pub fn new<'p>(
span: Span,
cx: &MatchCheckCtxt<'p, 'tcx>,
witnesses: Vec<DeconstructedPat<'p, 'tcx>>,
) -> Self {
let witness_1 = witnesses.get(0).unwrap().to_pat(cx);
Self {
span,
count: witnesses.len(),
// Substitute dummy values if witnesses is smaller than 3. These will never be read.
witness_2: witnesses.get(1).map(|w| w.to_pat(cx)).unwrap_or_else(|| witness_1.clone()),
witness_3: witnesses.get(2).map(|w| w.to_pat(cx)).unwrap_or_else(|| witness_1.clone()),
witness_1,
remainder: witnesses.len().saturating_sub(3),
}
}
}
#[derive(Diagnostic)]
#[diag(mir_build_pattern_not_covered, code = "E0005")]
pub(crate) struct PatternNotCovered<'s, 'tcx> {
#[primary_span]
pub span: Span,
pub origin: &'s str,
#[subdiagnostic]
pub uncovered: Uncovered<'tcx>,
#[subdiagnostic]
pub inform: Option<Inform>,
#[subdiagnostic]
pub interpreted_as_const: Option<InterpretedAsConst>,
#[subdiagnostic]
pub adt_defined_here: Option<AdtDefinedHere<'tcx>>,
#[note(pattern_ty)]
pub _p: (),
pub pattern_ty: Ty<'tcx>,
#[subdiagnostic]
pub let_suggestion: Option<SuggestLet>,
#[subdiagnostic]
pub res_defined_here: Option<ResDefinedHere>,
}
#[derive(Subdiagnostic)]
#[note(mir_build_inform_irrefutable)]
#[note(mir_build_more_information)]
pub struct Inform;
pub struct AdtDefinedHere<'tcx> {
pub adt_def_span: Span,
pub ty: Ty<'tcx>,
pub variants: Vec<Variant>,
}
pub struct Variant {
pub span: Span,
}
impl<'tcx> AddToDiagnostic for AdtDefinedHere<'tcx> {
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
where
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
{
diag.set_arg("ty", self.ty);
let mut spans = MultiSpan::from(self.adt_def_span);
for Variant { span } in self.variants {
spans.push_span_label(span, rustc_errors::fluent::mir_build_variant_defined_here);
}
diag.span_note(spans, rustc_errors::fluent::mir_build_adt_defined_here);
}
}
#[derive(Subdiagnostic)]
#[label(mir_build_res_defined_here)]
pub struct ResDefinedHere {
#[primary_span]
pub def_span: Span,
pub res: Res,
}
#[derive(Subdiagnostic)]
#[suggestion(
mir_build_interpreted_as_const,
code = "{variable}_var",
applicability = "maybe-incorrect"
)]
#[label(mir_build_confused)]
pub struct InterpretedAsConst {
#[primary_span]
pub span: Span,
pub article: &'static str,
pub variable: String,
pub res: Res,
}
#[derive(Subdiagnostic)]
pub enum SuggestLet {
#[multipart_suggestion(mir_build_suggest_if_let, applicability = "has-placeholders")]
If {
#[suggestion_part(code = "if ")]
start_span: Span,
#[suggestion_part(code = " {{ todo!() }}")]
semi_span: Span,
count: usize,
},
#[suggestion(
mir_build_suggest_let_else,
code = " else {{ todo!() }}",
applicability = "has-placeholders"
)]
Else {
#[primary_span]
end_span: Span,
count: usize,
},
}

View file

@ -10,6 +10,7 @@
#![feature(let_chains)] #![feature(let_chains)]
#![feature(min_specialization)] #![feature(min_specialization)]
#![feature(once_cell)] #![feature(once_cell)]
#![feature(try_blocks)]
#![recursion_limit = "256"] #![recursion_limit = "256"]
#[macro_use] #[macro_use]

View file

@ -9,8 +9,7 @@
use rustc_arena::TypedArena; use rustc_arena::TypedArena;
use rustc_ast::Mutability; use rustc_ast::Mutability;
use rustc_errors::{ use rustc_errors::{
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
MultiSpan,
}; };
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::*; use rustc_hir::def::*;
@ -378,8 +377,8 @@ fn check_irrefutable(&self, pat: &'tcx Pat<'tcx>, origin: &str, sp: Option<Span>
let pattern = self.lower_pattern(&mut cx, pat, &mut false); let pattern = self.lower_pattern(&mut cx, pat, &mut false);
let pattern_ty = pattern.ty(); let pattern_ty = pattern.ty();
let arms = vec![MatchArm { pat: pattern, hir_id: pat.hir_id, has_guard: false }]; let arm = MatchArm { pat: pattern, hir_id: pat.hir_id, has_guard: false };
let report = compute_match_usefulness(&cx, &arms, pat.hir_id, pattern_ty); let report = compute_match_usefulness(&cx, &[arm], pat.hir_id, pattern_ty);
// Note: we ignore whether the pattern is unreachable (i.e. whether the type is empty). We // Note: we ignore whether the pattern is unreachable (i.e. whether the type is empty). We
// only care about exhaustiveness here. // only care about exhaustiveness here.
@ -390,145 +389,73 @@ fn check_irrefutable(&self, pat: &'tcx Pat<'tcx>, origin: &str, sp: Option<Span>
return; return;
} }
let joined_patterns = joined_uncovered_patterns(&cx, &witnesses); let (inform, interpreted_as_const, res_defined_here,let_suggestion) =
if let hir::PatKind::Path(hir::QPath::Resolved(
let mut bindings = vec![]; None,
hir::Path {
let mut err = struct_span_err!( segments: &[hir::PathSegment { args: None, res, ident, .. }],
self.tcx.sess, ..
pat.span, },
E0005, )) = &pat.kind
"refutable pattern in {}: {} not covered",
origin,
joined_patterns
);
let suggest_if_let = match &pat.kind {
hir::PatKind::Path(hir::QPath::Resolved(None, path))
if path.segments.len() == 1 && path.segments[0].args.is_none() =>
{ {
const_not_var(&mut err, cx.tcx, pat, path); (
false None,
} Some(InterpretedAsConst {
_ => { span: pat.span,
pat.walk(&mut |pat: &hir::Pat<'_>| { article: res.article(),
match pat.kind { variable: ident.to_string().to_lowercase(),
hir::PatKind::Binding(_, _, ident, _) => { res,
bindings.push(ident); }),
try {
ResDefinedHere {
def_span: cx.tcx.hir().res_span(res)?,
res,
} }
_ => {} },
None,
)
} else if let Some(span) = sp && self.tcx.sess.source_map().is_span_accessible(span) {
let mut bindings = vec![];
pat.walk_always(&mut |pat: &hir::Pat<'_>| {
if let hir::PatKind::Binding(_, _, ident, _) = pat.kind {
bindings.push(ident);
} }
true
}); });
err.span_label(pat.span, pattern_not_covered_label(&witnesses, &joined_patterns));
true
}
};
if let (Some(span), true) = (sp, suggest_if_let) {
err.note(
"`let` bindings require an \"irrefutable pattern\", like a `struct` or \
an `enum` with only one variant",
);
if self.tcx.sess.source_map().is_span_accessible(span) {
let semi_span = span.shrink_to_hi().with_lo(span.hi() - BytePos(1)); let semi_span = span.shrink_to_hi().with_lo(span.hi() - BytePos(1));
let start_span = span.shrink_to_lo(); let start_span = span.shrink_to_lo();
let end_span = semi_span.shrink_to_lo(); let end_span = semi_span.shrink_to_lo();
err.multipart_suggestion( let count = witnesses.len();
&format!(
"you might want to use `if let` to ignore the variant{} that {} matched", let let_suggestion = if bindings.is_empty() {SuggestLet::If{start_span, semi_span, count}} else{ SuggestLet::Else{end_span, count }};
pluralize!(witnesses.len()), (sp.map(|_|Inform), None, None, Some(let_suggestion))
match witnesses.len() { } else{
1 => "isn't", (sp.map(|_|Inform), None, None, None)
_ => "aren't", };
},
), let adt_defined_here = try {
vec![ let ty = pattern_ty.peel_refs();
match &bindings[..] { let ty::Adt(def, _) = ty.kind() else { None? };
[] => (start_span, "if ".to_string()), let adt_def_span = cx.tcx.hir().get_if_local(def.did())?.ident()?.span;
[binding] => (start_span, format!("let {} = if ", binding)), let mut variants = vec![];
bindings => (
start_span, for span in maybe_point_at_variant(&cx, *def, witnesses.iter().take(5)) {
format!( variants.push(Variant { span });
"let ({}) = if ",
bindings
.iter()
.map(|ident| ident.to_string())
.collect::<Vec<_>>()
.join(", ")
),
),
},
match &bindings[..] {
[] => (semi_span, " { todo!() }".to_string()),
[binding] => {
(end_span, format!(" {{ {} }} else {{ todo!() }}", binding))
}
bindings => (
end_span,
format!(
" {{ ({}) }} else {{ todo!() }}",
bindings
.iter()
.map(|ident| ident.to_string())
.collect::<Vec<_>>()
.join(", ")
),
),
},
],
Applicability::HasPlaceholders,
);
if !bindings.is_empty() {
err.span_suggestion_verbose(
semi_span.shrink_to_lo(),
&format!(
"alternatively, you might want to use \
let else to handle the variant{} that {} matched",
pluralize!(witnesses.len()),
match witnesses.len() {
1 => "isn't",
_ => "aren't",
},
),
" else { todo!() }",
Applicability::HasPlaceholders,
);
}
} }
err.note( AdtDefinedHere { adt_def_span, ty, variants }
"for more information, visit \ };
https://doc.rust-lang.org/book/ch18-02-refutability.html",
);
}
adt_defined_here(&cx, &mut err, pattern_ty, &witnesses); self.tcx.sess.emit_err(PatternNotCovered {
err.note(&format!("the matched value is of type `{}`", pattern_ty)); span: pat.span,
err.emit(); origin,
} uncovered: Uncovered::new(pat.span, &cx, witnesses),
} inform,
interpreted_as_const,
/// A path pattern was interpreted as a constant, not a new variable. _p: (),
/// This caused an irrefutable match failure in e.g. `let`. pattern_ty,
fn const_not_var(err: &mut Diagnostic, tcx: TyCtxt<'_>, pat: &Pat<'_>, path: &hir::Path<'_>) { let_suggestion,
let descr = path.res.descr(); res_defined_here,
err.span_label( adt_defined_here,
pat.span, });
format!("interpreted as {} {} pattern, not a new variable", path.res.article(), descr,),
);
err.span_suggestion(
pat.span,
"introduce a variable instead",
format!("{}_var", path.segments[0].ident).to_lowercase(),
// Cannot use `MachineApplicable` as it's not really *always* correct
// because there may be such an identifier in scope or the user maybe
// really wanted to match against the constant. This is quite unlikely however.
Applicability::MaybeIncorrect,
);
if let Some(span) = tcx.hir().res_span(path.res) {
err.span_label(span, format!("{} defined here", descr));
} }
} }

View file

@ -1,11 +1,9 @@
use rustc_errors::DelayDm;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_index::vec::Idx; use rustc_index::vec::Idx;
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_middle::mir::{self, Field}; use rustc_middle::mir::{self, Field};
use rustc_middle::thir::{FieldPat, Pat, PatKind}; use rustc_middle::thir::{FieldPat, Pat, PatKind};
use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
use rustc_session::lint; use rustc_session::lint;
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::traits::predicate_for_trait_def; use rustc_trait_selection::traits::predicate_for_trait_def;
@ -15,6 +13,10 @@
use std::cell::Cell; use std::cell::Cell;
use super::PatCtxt; use super::PatCtxt;
use crate::errors::{
FloatPattern, IndirectStructuralMatch, InvalidPattern, NontrivialStructuralMatch,
PointerPattern, TypeNotStructural, UnionPattern, UnsizedPattern,
};
impl<'a, 'tcx> PatCtxt<'a, 'tcx> { impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
/// Converts an evaluated constant to a pattern (if possible). /// Converts an evaluated constant to a pattern (if possible).
@ -105,47 +107,6 @@ fn tcx(&self) -> TyCtxt<'tcx> {
self.infcx.tcx self.infcx.tcx
} }
fn adt_derive_msg(&self, adt_def: AdtDef<'tcx>) -> String {
let path = self.tcx().def_path_str(adt_def.did());
format!(
"to use a constant of type `{}` in a pattern, \
`{}` must be annotated with `#[derive(PartialEq, Eq)]`",
path, path,
)
}
fn search_for_structural_match_violation(&self, ty: Ty<'tcx>) -> Option<String> {
traits::search_for_structural_match_violation(self.span, self.tcx(), ty).map(|non_sm_ty| {
with_no_trimmed_paths!(match non_sm_ty.kind() {
ty::Adt(adt, _) => self.adt_derive_msg(*adt),
ty::Dynamic(..) => {
"trait objects cannot be used in patterns".to_string()
}
ty::Alias(ty::Opaque, ..) => {
"opaque types cannot be used in patterns".to_string()
}
ty::Closure(..) => {
"closures cannot be used in patterns".to_string()
}
ty::Generator(..) | ty::GeneratorWitness(..) => {
"generators cannot be used in patterns".to_string()
}
ty::Float(..) => {
"floating-point numbers cannot be used in patterns".to_string()
}
ty::FnPtr(..) => {
"function pointers cannot be used in patterns".to_string()
}
ty::RawPtr(..) => {
"raw pointers cannot be used in patterns".to_string()
}
_ => {
bug!("use of a value of `{non_sm_ty}` inside a pattern")
}
})
})
}
fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool { fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool {
ty.is_structural_eq_shallow(self.infcx.tcx) ty.is_structural_eq_shallow(self.infcx.tcx)
} }
@ -176,7 +137,8 @@ fn to_pat(
// If we were able to successfully convert the const to some pat, // If we were able to successfully convert the const to some pat,
// double-check that all types in the const implement `Structural`. // double-check that all types in the const implement `Structural`.
let structural = self.search_for_structural_match_violation(cv.ty()); let structural =
traits::search_for_structural_match_violation(self.span, self.tcx(), cv.ty());
debug!( debug!(
"search_for_structural_match_violation cv.ty: {:?} returned: {:?}", "search_for_structural_match_violation cv.ty: {:?} returned: {:?}",
cv.ty(), cv.ty(),
@ -194,17 +156,18 @@ fn to_pat(
return inlined_const_as_pat; return inlined_const_as_pat;
} }
if let Some(msg) = structural { if let Some(non_sm_ty) = structural {
if !self.type_may_have_partial_eq_impl(cv.ty()) { if !self.type_may_have_partial_eq_impl(cv.ty()) {
// span_fatal avoids ICE from resolution of non-existent method (rare case). // fatal avoids ICE from resolution of non-existent method (rare case).
self.tcx().sess.span_fatal(self.span, &msg); self.tcx()
.sess
.emit_fatal(TypeNotStructural { span: self.span, non_sm_ty: non_sm_ty });
} else if mir_structural_match_violation && !self.saw_const_match_lint.get() { } else if mir_structural_match_violation && !self.saw_const_match_lint.get() {
self.tcx().struct_span_lint_hir( self.tcx().emit_spanned_lint(
lint::builtin::INDIRECT_STRUCTURAL_MATCH, lint::builtin::INDIRECT_STRUCTURAL_MATCH,
self.id, self.id,
self.span, self.span,
msg, IndirectStructuralMatch { non_sm_ty },
|lint| lint,
); );
} else { } else {
debug!( debug!(
@ -278,12 +241,11 @@ fn recur(
let kind = match cv.ty().kind() { let kind = match cv.ty().kind() {
ty::Float(_) => { ty::Float(_) => {
if self.include_lint_checks { if self.include_lint_checks {
tcx.struct_span_lint_hir( tcx.emit_spanned_lint(
lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
id, id,
span, span,
"floating-point types cannot be used in patterns", FloatPattern,
|lint| lint,
); );
} }
PatKind::Constant { value: cv } PatKind::Constant { value: cv }
@ -291,29 +253,22 @@ fn recur(
ty::Adt(adt_def, _) if adt_def.is_union() => { ty::Adt(adt_def, _) if adt_def.is_union() => {
// Matching on union fields is unsafe, we can't hide it in constants // Matching on union fields is unsafe, we can't hide it in constants
self.saw_const_match_error.set(true); self.saw_const_match_error.set(true);
let msg = "cannot use unions in constant patterns"; let err = UnionPattern { span };
if self.include_lint_checks { tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
tcx.sess.span_err(span, msg);
} else {
tcx.sess.delay_span_bug(span, msg);
}
PatKind::Wild PatKind::Wild
} }
ty::Adt(..) ty::Adt(..)
if !self.type_may_have_partial_eq_impl(cv.ty()) if !self.type_may_have_partial_eq_impl(cv.ty())
// FIXME(#73448): Find a way to bring const qualification into parity with // FIXME(#73448): Find a way to bring const qualification into parity with
// `search_for_structural_match_violation` and then remove this condition. // `search_for_structural_match_violation` and then remove this condition.
&& self.search_for_structural_match_violation(cv.ty()).is_some() =>
// Obtain the actual type that isn't annotated. If we just looked at `cv.ty` we
// could get `Option<NonStructEq>`, even though `Option` is annotated with derive.
&& let Some(non_sm_ty) = traits::search_for_structural_match_violation(span, tcx, cv.ty()) =>
{ {
// Obtain the actual type that isn't annotated. If we just looked at `cv.ty` we
// could get `Option<NonStructEq>`, even though `Option` is annotated with derive.
let msg = self.search_for_structural_match_violation(cv.ty()).unwrap();
self.saw_const_match_error.set(true); self.saw_const_match_error.set(true);
if self.include_lint_checks { let err = TypeNotStructural { span, non_sm_ty };
tcx.sess.span_err(self.span, &msg); tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
} else {
tcx.sess.delay_span_bug(self.span, &msg);
}
PatKind::Wild PatKind::Wild
} }
// If the type is not structurally comparable, just emit the constant directly, // If the type is not structurally comparable, just emit the constant directly,
@ -331,19 +286,11 @@ fn recur(
&& !self.saw_const_match_lint.get() && !self.saw_const_match_lint.get()
{ {
self.saw_const_match_lint.set(true); self.saw_const_match_lint.set(true);
tcx.struct_span_lint_hir( tcx.emit_spanned_lint(
lint::builtin::INDIRECT_STRUCTURAL_MATCH, lint::builtin::INDIRECT_STRUCTURAL_MATCH,
id, id,
span, span,
DelayDm(|| { IndirectStructuralMatch { non_sm_ty: cv.ty() },
format!(
"to use a constant of type `{}` in a pattern, \
`{}` must be annotated with `#[derive(PartialEq, Eq)]`",
cv.ty(),
cv.ty(),
)
}),
|lint| lint,
); );
} }
// Since we are behind a reference, we can just bubble the error up so we get a // Since we are behind a reference, we can just bubble the error up so we get a
@ -357,18 +304,9 @@ fn recur(
adt_def, adt_def,
cv.ty() cv.ty()
); );
let path = tcx.def_path_str(adt_def.did());
let msg = format!(
"to use a constant of type `{}` in a pattern, \
`{}` must be annotated with `#[derive(PartialEq, Eq)]`",
path, path,
);
self.saw_const_match_error.set(true); self.saw_const_match_error.set(true);
if self.include_lint_checks { let err = TypeNotStructural { span, non_sm_ty: cv.ty() };
tcx.sess.span_err(span, &msg); tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
} else {
tcx.sess.delay_span_bug(span, &msg);
}
PatKind::Wild PatKind::Wild
} }
ty::Adt(adt_def, substs) if adt_def.is_enum() => { ty::Adt(adt_def, substs) if adt_def.is_enum() => {
@ -401,12 +339,8 @@ fn recur(
// These are not allowed and will error elsewhere anyway. // These are not allowed and will error elsewhere anyway.
ty::Dynamic(..) => { ty::Dynamic(..) => {
self.saw_const_match_error.set(true); self.saw_const_match_error.set(true);
let msg = format!("`{}` cannot be used in patterns", cv.ty()); let err = InvalidPattern { span, non_sm_ty: cv.ty() };
if self.include_lint_checks { tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
tcx.sess.span_err(span, &msg);
} else {
tcx.sess.delay_span_bug(span, &msg);
}
PatKind::Wild PatKind::Wild
} }
// `&str` is represented as `ConstValue::Slice`, let's keep using this // `&str` is represented as `ConstValue::Slice`, let's keep using this
@ -471,32 +405,26 @@ fn recur(
// this pattern to a `PartialEq::eq` comparison and `PartialEq::eq` takes a // this pattern to a `PartialEq::eq` comparison and `PartialEq::eq` takes a
// reference. This makes the rest of the matching logic simpler as it doesn't have // reference. This makes the rest of the matching logic simpler as it doesn't have
// to figure out how to get a reference again. // to figure out how to get a reference again.
ty::Adt(adt_def, _) if !self.type_marked_structural(*pointee_ty) => { ty::Adt(_, _) if !self.type_marked_structural(*pointee_ty) => {
if self.behind_reference.get() { if self.behind_reference.get() {
if self.include_lint_checks if self.include_lint_checks
&& !self.saw_const_match_error.get() && !self.saw_const_match_error.get()
&& !self.saw_const_match_lint.get() && !self.saw_const_match_lint.get()
{ {
self.saw_const_match_lint.set(true); self.saw_const_match_lint.set(true);
let msg = self.adt_derive_msg(adt_def); tcx.emit_spanned_lint(
self.tcx().struct_span_lint_hir(
lint::builtin::INDIRECT_STRUCTURAL_MATCH, lint::builtin::INDIRECT_STRUCTURAL_MATCH,
self.id, self.id,
self.span, span,
msg, IndirectStructuralMatch { non_sm_ty: *pointee_ty },
|lint| lint,
); );
} }
PatKind::Constant { value: cv } PatKind::Constant { value: cv }
} else { } else {
if !self.saw_const_match_error.get() { if !self.saw_const_match_error.get() {
self.saw_const_match_error.set(true); self.saw_const_match_error.set(true);
let msg = self.adt_derive_msg(adt_def); let err = TypeNotStructural { span, non_sm_ty: *pointee_ty };
if self.include_lint_checks { tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
tcx.sess.span_err(span, &msg);
} else {
tcx.sess.delay_span_bug(span, &msg);
}
} }
PatKind::Wild PatKind::Wild
} }
@ -508,12 +436,10 @@ fn recur(
if !pointee_ty.is_sized(tcx, param_env) { if !pointee_ty.is_sized(tcx, param_env) {
// `tcx.deref_mir_constant()` below will ICE with an unsized type // `tcx.deref_mir_constant()` below will ICE with an unsized type
// (except slices, which are handled in a separate arm above). // (except slices, which are handled in a separate arm above).
let msg = format!("cannot use unsized non-slice type `{}` in constant patterns", pointee_ty);
if self.include_lint_checks { let err = UnsizedPattern { span, non_sm_ty: *pointee_ty };
tcx.sess.span_err(span, &msg); tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
} else {
tcx.sess.delay_span_bug(span, &msg);
}
PatKind::Wild PatKind::Wild
} else { } else {
let old = self.behind_reference.replace(true); let old = self.behind_reference.replace(true);
@ -545,27 +471,19 @@ fn recur(
&& !self.saw_const_match_lint.get() && !self.saw_const_match_lint.get()
{ {
self.saw_const_match_lint.set(true); self.saw_const_match_lint.set(true);
let msg = "function pointers and unsized pointers in patterns behave \ tcx.emit_spanned_lint(
unpredictably and should not be relied upon. \
See https://github.com/rust-lang/rust/issues/70861 for details.";
tcx.struct_span_lint_hir(
lint::builtin::POINTER_STRUCTURAL_MATCH, lint::builtin::POINTER_STRUCTURAL_MATCH,
id, id,
span, span,
msg, PointerPattern
|lint| lint,
); );
} }
PatKind::Constant { value: cv } PatKind::Constant { value: cv }
} }
_ => { _ => {
self.saw_const_match_error.set(true); self.saw_const_match_error.set(true);
let msg = format!("`{}` cannot be used in patterns", cv.ty()); let err = InvalidPattern { span, non_sm_ty: cv.ty() };
if self.include_lint_checks { tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
tcx.sess.span_err(span, &msg);
} else {
tcx.sess.delay_span_bug(span, &msg);
}
PatKind::Wild PatKind::Wild
} }
}; };
@ -576,21 +494,17 @@ fn recur(
&& mir_structural_match_violation && mir_structural_match_violation
// FIXME(#73448): Find a way to bring const qualification into parity with // FIXME(#73448): Find a way to bring const qualification into parity with
// `search_for_structural_match_violation` and then remove this condition. // `search_for_structural_match_violation` and then remove this condition.
&& self.search_for_structural_match_violation(cv.ty()).is_some()
{
self.saw_const_match_lint.set(true);
// Obtain the actual type that isn't annotated. If we just looked at `cv.ty` we // Obtain the actual type that isn't annotated. If we just looked at `cv.ty` we
// could get `Option<NonStructEq>`, even though `Option` is annotated with derive. // could get `Option<NonStructEq>`, even though `Option` is annotated with derive.
let msg = self.search_for_structural_match_violation(cv.ty()).unwrap().replace( && let Some(non_sm_ty) = traits::search_for_structural_match_violation(span, tcx, cv.ty())
"in a pattern,", {
"in a pattern, the constant's initializer must be trivial or", self.saw_const_match_lint.set(true);
); tcx.emit_spanned_lint(
tcx.struct_span_lint_hir(
lint::builtin::NONTRIVIAL_STRUCTURAL_MATCH, lint::builtin::NONTRIVIAL_STRUCTURAL_MATCH,
id, id,
span, span,
msg, NontrivialStructuralMatch {non_sm_ty}
|lint| lint,
); );
} }

View file

@ -67,6 +67,7 @@
use super::compare_const_vals; use super::compare_const_vals;
use super::usefulness::{MatchCheckCtxt, PatCtxt}; use super::usefulness::{MatchCheckCtxt, PatCtxt};
use crate::errors::{Overlap, OverlappingRangeEndpoints};
/// Recursively expand this pattern into its subpatterns. Only useful for or-patterns. /// Recursively expand this pattern into its subpatterns. Only useful for or-patterns.
fn expand_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> Vec<&'p Pat<'tcx>> { fn expand_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> Vec<&'p Pat<'tcx>> {
@ -96,7 +97,7 @@ fn expand<'p, 'tcx>(pat: &'p Pat<'tcx>, vec: &mut Vec<&'p Pat<'tcx>>) {
/// `IntRange` is never used to encode an empty range or a "range" that wraps /// `IntRange` is never used to encode an empty range or a "range" that wraps
/// around the (offset) space: i.e., `range.lo <= range.hi`. /// around the (offset) space: i.e., `range.lo <= range.hi`.
#[derive(Clone, PartialEq, Eq)] #[derive(Clone, PartialEq, Eq)]
pub(super) struct IntRange { pub(crate) struct IntRange {
range: RangeInclusive<u128>, range: RangeInclusive<u128>,
/// Keeps the bias used for encoding the range. It depends on the type of the range and /// Keeps the bias used for encoding the range. It depends on the type of the range and
/// possibly the pointer size of the current architecture. The algorithm ensures we never /// possibly the pointer size of the current architecture. The algorithm ensures we never
@ -284,32 +285,21 @@ pub(super) fn lint_overlapping_range_endpoints<'a, 'p: 'a, 'tcx: 'a>(
return; return;
} }
let overlaps: Vec<_> = pats let overlap: Vec<_> = pats
.filter_map(|pat| Some((pat.ctor().as_int_range()?, pat.span()))) .filter_map(|pat| Some((pat.ctor().as_int_range()?, pat.span())))
.filter(|(range, _)| self.suspicious_intersection(range)) .filter(|(range, _)| self.suspicious_intersection(range))
.map(|(range, span)| (self.intersection(&range).unwrap(), span)) .map(|(range, span)| Overlap {
range: self.intersection(&range).unwrap().to_pat(pcx.cx.tcx, pcx.ty),
span,
})
.collect(); .collect();
if !overlaps.is_empty() { if !overlap.is_empty() {
pcx.cx.tcx.struct_span_lint_hir( pcx.cx.tcx.emit_spanned_lint(
lint::builtin::OVERLAPPING_RANGE_ENDPOINTS, lint::builtin::OVERLAPPING_RANGE_ENDPOINTS,
hir_id, hir_id,
pcx.span, pcx.span,
"multiple patterns overlap on their endpoints", OverlappingRangeEndpoints { overlap, range: pcx.span },
|lint| {
for (int_range, span) in overlaps {
lint.span_label(
span,
&format!(
"this range overlaps on `{}`...",
int_range.to_pat(pcx.cx.tcx, pcx.ty)
),
);
}
lint.span_label(pcx.span, "... with this range");
lint.note("you likely meant to write mutually exclusive ranges");
lint
},
); );
} }
} }

View file

@ -2,7 +2,7 @@
mod check_match; mod check_match;
mod const_to_pat; mod const_to_pat;
mod deconstruct_pat; pub(crate) mod deconstruct_pat;
mod usefulness; mod usefulness;
pub(crate) use self::check_match::check_match; pub(crate) use self::check_match::check_match;

View file

@ -291,9 +291,8 @@
use self::ArmType::*; use self::ArmType::*;
use self::Usefulness::*; use self::Usefulness::*;
use super::check_match::{joined_uncovered_patterns, pattern_not_covered_label};
use super::deconstruct_pat::{Constructor, DeconstructedPat, Fields, SplitWildcard}; use super::deconstruct_pat::{Constructor, DeconstructedPat, Fields, SplitWildcard};
use crate::errors::{NonExhaustiveOmittedPattern, Uncovered};
use rustc_data_structures::captures::Captures; use rustc_data_structures::captures::Captures;
@ -743,31 +742,6 @@ fn apply_constructor(mut self, pcx: &PatCtxt<'_, 'p, 'tcx>, ctor: &Constructor<'
} }
} }
/// Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
/// is not exhaustive enough.
///
/// NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`.
fn lint_non_exhaustive_omitted_patterns<'p, 'tcx>(
cx: &MatchCheckCtxt<'p, 'tcx>,
scrut_ty: Ty<'tcx>,
sp: Span,
hir_id: HirId,
witnesses: Vec<DeconstructedPat<'p, 'tcx>>,
) {
cx.tcx.struct_span_lint_hir(NON_EXHAUSTIVE_OMITTED_PATTERNS, hir_id, sp, "some variants are not matched explicitly", |lint| {
let joined_patterns = joined_uncovered_patterns(cx, &witnesses);
lint.span_label(sp, pattern_not_covered_label(&witnesses, &joined_patterns));
lint.help(
"ensure that all variants are matched explicitly by adding the suggested match arms",
);
lint.note(&format!(
"the matched value is of type `{}` and the `non_exhaustive_omitted_patterns` attribute was found",
scrut_ty,
));
lint
});
}
/// Algorithm from <http://moscova.inria.fr/~maranget/papers/warn/index.html>. /// Algorithm from <http://moscova.inria.fr/~maranget/papers/warn/index.html>.
/// The algorithm from the paper has been modified to correctly handle empty /// The algorithm from the paper has been modified to correctly handle empty
/// types. The changes are: /// types. The changes are:
@ -913,7 +887,19 @@ fn is_useful<'p, 'tcx>(
.collect::<Vec<_>>() .collect::<Vec<_>>()
}; };
lint_non_exhaustive_omitted_patterns(pcx.cx, pcx.ty, pcx.span, hir_id, patterns); // Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
// is not exhaustive enough.
//
// NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`.
cx.tcx.emit_spanned_lint(
NON_EXHAUSTIVE_OMITTED_PATTERNS,
hir_id,
pcx.span,
NonExhaustiveOmittedPattern {
scrut_ty: pcx.ty,
uncovered: Uncovered::new(pcx.span, pcx.cx, patterns),
},
);
} }
ret.extend(usefulness); ret.extend(usefulness);

View file

@ -1,7 +1,6 @@
use rustc_errors::{fluent, ErrorGuaranteed, Handler, IntoDiagnostic}; use rustc_errors::{fluent, ErrorGuaranteed, Handler, IntoDiagnostic};
use rustc_macros::Diagnostic; use rustc_macros::Diagnostic;
use rustc_middle::ty::{self, PolyTraitRef, Ty}; use rustc_middle::ty::{self, PolyTraitRef, Ty};
use rustc_session::Limit;
use rustc_span::{Span, Symbol}; use rustc_span::{Span, Symbol};
#[derive(Diagnostic)] #[derive(Diagnostic)]
@ -21,18 +20,6 @@ pub struct UnableToConstructConstantValue<'a> {
pub unevaluated: ty::UnevaluatedConst<'a>, pub unevaluated: ty::UnevaluatedConst<'a>,
} }
#[derive(Diagnostic)]
#[help]
#[diag(trait_selection_auto_deref_reached_recursion_limit, code = "E0055")]
pub struct AutoDerefReachedRecursionLimit<'a> {
#[primary_span]
#[label]
pub span: Span,
pub ty: Ty<'a>,
pub suggested_limit: Limit,
pub crate_name: Symbol,
}
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(trait_selection_empty_on_clause_in_rustc_on_unimplemented, code = "E0232")] #[diag(trait_selection_empty_on_clause_in_rustc_on_unimplemented, code = "E0232")]
pub struct EmptyOnClauseInOnUnimplemented { pub struct EmptyOnClauseInOnUnimplemented {

View file

@ -35,7 +35,6 @@
#[macro_use] #[macro_use]
extern crate smallvec; extern crate smallvec;
pub mod autoderef;
pub mod errors; pub mod errors;
pub mod infer; pub mod infer;
pub mod solve; pub mod solve;

View file

@ -5,7 +5,6 @@
PredicateObligation, PredicateObligation,
}; };
use crate::autoderef::Autoderef;
use crate::infer::InferCtxt; use crate::infer::InferCtxt;
use crate::traits::{NormalizeExt, ObligationCtxt}; use crate::traits::{NormalizeExt, ObligationCtxt};
@ -750,26 +749,30 @@ fn suggest_dereferences(
} }
if let ty::Ref(region, base_ty, mutbl) = *real_ty.skip_binder().kind() { if let ty::Ref(region, base_ty, mutbl) = *real_ty.skip_binder().kind() {
let mut autoderef = Autoderef::new( let autoderef = (self.autoderef_steps)(base_ty);
self, if let Some(steps) =
obligation.param_env, autoderef.into_iter().enumerate().find_map(|(steps, (ty, obligations))| {
obligation.cause.body_id, // Re-add the `&`
span, let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl });
base_ty,
);
if let Some(steps) = autoderef.find_map(|(ty, steps)| {
// Re-add the `&`
let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl });
// Remapping bound vars here // Remapping bound vars here
let real_trait_pred_and_ty = let real_trait_pred_and_ty =
real_trait_pred.map_bound(|inner_trait_pred| (inner_trait_pred, ty)); real_trait_pred.map_bound(|inner_trait_pred| (inner_trait_pred, ty));
let obligation = self.mk_trait_obligation_with_new_self_ty( let obligation = self.mk_trait_obligation_with_new_self_ty(
obligation.param_env, obligation.param_env,
real_trait_pred_and_ty, real_trait_pred_and_ty,
); );
Some(steps).filter(|_| self.predicate_may_hold(&obligation)) if obligations
}) { .iter()
.chain([&obligation])
.all(|obligation| self.predicate_may_hold(obligation))
{
Some(steps)
} else {
None
}
})
{
if steps > 0 { if steps > 0 {
// Don't care about `&mut` because `DerefMut` is used less // Don't care about `&mut` because `DerefMut` is used less
// often and user will not expect autoderef happens. // often and user will not expect autoderef happens.
@ -1358,57 +1361,117 @@ fn suggest_remove_reference(
err: &mut Diagnostic, err: &mut Diagnostic,
trait_pred: ty::PolyTraitPredicate<'tcx>, trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> bool { ) -> bool {
let span = obligation.cause.span; let mut span = obligation.cause.span;
let mut trait_pred = trait_pred;
let mut code = obligation.cause.code();
while let Some((c, Some(parent_trait_pred))) = code.parent() {
// We want the root obligation, in order to detect properly handle
// `for _ in &mut &mut vec![] {}`.
code = c;
trait_pred = parent_trait_pred;
}
while span.desugaring_kind().is_some() {
// Remove all the hir desugaring contexts while maintaining the macro contexts.
span.remove_mark();
}
let mut expr_finder = super::FindExprBySpan::new(span);
let Some(hir::Node::Expr(body)) = self.tcx.hir().find(obligation.cause.body_id) else {
return false;
};
expr_finder.visit_expr(&body);
let mut maybe_suggest = |suggested_ty, count, suggestions| {
// Remapping bound vars here
let trait_pred_and_suggested_ty =
trait_pred.map_bound(|trait_pred| (trait_pred, suggested_ty));
let mut suggested = false; let new_obligation = self.mk_trait_obligation_with_new_self_ty(
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { obligation.param_env,
let refs_number = trait_pred_and_suggested_ty,
snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count(); );
if let Some('\'') = snippet.chars().filter(|c| !c.is_whitespace()).nth(refs_number) {
// Do not suggest removal of borrow from type arguments. if self.predicate_may_hold(&new_obligation) {
return false; let msg = if count == 1 {
"consider removing the leading `&`-reference".to_string()
} else {
format!("consider removing {count} leading `&`-references")
};
err.multipart_suggestion_verbose(
&msg,
suggestions,
Applicability::MachineApplicable,
);
true
} else {
false
} }
};
// Skipping binder here, remapping below // Maybe suggest removal of borrows from types in type parameters, like in
let mut suggested_ty = trait_pred.self_ty().skip_binder(); // `src/test/ui/not-panic/not-panic-safe.rs`.
let mut count = 0;
let mut suggestions = vec![];
// Skipping binder here, remapping below
let mut suggested_ty = trait_pred.self_ty().skip_binder();
if let Some(mut hir_ty) = expr_finder.ty_result {
while let hir::TyKind::Ref(_, mut_ty) = &hir_ty.kind {
count += 1;
let span = hir_ty.span.until(mut_ty.ty.span);
suggestions.push((span, String::new()));
for refs_remaining in 0..refs_number {
let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else { let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else {
break; break;
}; };
suggested_ty = *inner_ty; suggested_ty = *inner_ty;
// Remapping bound vars here hir_ty = mut_ty.ty;
let trait_pred_and_suggested_ty =
trait_pred.map_bound(|trait_pred| (trait_pred, suggested_ty));
let new_obligation = self.mk_trait_obligation_with_new_self_ty( if maybe_suggest(suggested_ty, count, suggestions.clone()) {
obligation.param_env, return true;
trait_pred_and_suggested_ty,
);
if self.predicate_may_hold(&new_obligation) {
let sp = self
.tcx
.sess
.source_map()
.span_take_while(span, |c| c.is_whitespace() || *c == '&');
let remove_refs = refs_remaining + 1;
let msg = if remove_refs == 1 {
"consider removing the leading `&`-reference".to_string()
} else {
format!("consider removing {} leading `&`-references", remove_refs)
};
err.span_suggestion_short(sp, &msg, "", Applicability::MachineApplicable);
suggested = true;
break;
} }
} }
} }
suggested
// Maybe suggest removal of borrows from expressions, like in `for i in &&&foo {}`.
let Some(mut expr) = expr_finder.result else { return false; };
let mut count = 0;
let mut suggestions = vec![];
// Skipping binder here, remapping below
let mut suggested_ty = trait_pred.self_ty().skip_binder();
'outer: loop {
while let hir::ExprKind::AddrOf(_, _, borrowed) = expr.kind {
count += 1;
let span = if expr.span.eq_ctxt(borrowed.span) {
expr.span.until(borrowed.span)
} else {
expr.span.with_hi(expr.span.lo() + BytePos(1))
};
suggestions.push((span, String::new()));
let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else {
break 'outer;
};
suggested_ty = *inner_ty;
expr = borrowed;
if maybe_suggest(suggested_ty, count, suggestions.clone()) {
return true;
}
}
if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
&& let hir::def::Res::Local(hir_id) = path.res
&& let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(hir_id)
&& let Some(hir::Node::Local(local)) = self.tcx.hir().find_parent(binding.hir_id)
&& let None = local.ty
&& let Some(binding_expr) = local.init
{
expr = binding_expr;
} else {
break 'outer;
}
}
false
} }
fn suggest_remove_await(&self, obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic) { fn suggest_remove_await(&self, obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic) {

View file

@ -239,7 +239,6 @@
#![feature(arm_target_feature)] #![feature(arm_target_feature)]
#![feature(avx512_target_feature)] #![feature(avx512_target_feature)]
#![feature(cmpxchg16b_target_feature)] #![feature(cmpxchg16b_target_feature)]
#![feature(f16c_target_feature)]
#![feature(hexagon_target_feature)] #![feature(hexagon_target_feature)]
#![feature(mips_target_feature)] #![feature(mips_target_feature)]
#![feature(powerpc_target_feature)] #![feature(powerpc_target_feature)]
@ -248,6 +247,7 @@
#![feature(sse4a_target_feature)] #![feature(sse4a_target_feature)]
#![feature(tbm_target_feature)] #![feature(tbm_target_feature)]
#![feature(wasm_target_feature)] #![feature(wasm_target_feature)]
#![cfg_attr(bootstrap, feature(f16c_target_feature))]
// allow using `core::` in intra-doc links // allow using `core::` in intra-doc links
#[allow(unused_extern_crates)] #[allow(unused_extern_crates)]

View file

@ -1514,37 +1514,50 @@ pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
(a as Self, b) (a as Self, b)
} }
/// Calculates `self + rhs + carry` without the ability to overflow. /// Calculates `self` + `rhs` + `carry` and checks for overflow.
/// ///
/// Performs "signed ternary addition" which takes in an extra bit to add, and may return an /// Performs "ternary addition" of two integer operands and a carry-in
/// additional bit of overflow. This signed function is used only on the highest-ordered data, /// bit, and returns a tuple of the sum along with a boolean indicating
/// for which the signed overflow result indicates whether the big integer overflowed or not. /// whether an arithmetic overflow would occur. On overflow, the wrapped
/// value is returned.
///
/// This allows chaining together multiple additions to create a wider
/// addition, and can be useful for bignum addition. This method should
/// only be used for the most significant word; for the less significant
/// words the unsigned method
#[doc = concat!("[`", stringify!($UnsignedT), "::carrying_add`]")]
/// should be used.
///
/// The output boolean returned by this method is *not* a carry flag,
/// and should *not* be added to a more significant word.
///
/// If the input carry is false, this method is equivalent to
/// [`overflowing_add`](Self::overflowing_add).
/// ///
/// # Examples /// # Examples
/// ///
/// Basic usage:
///
/// ``` /// ```
/// #![feature(bigint_helper_methods)] /// #![feature(bigint_helper_methods)]
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, false), (7, false));")] /// // Only the most significant word is signed.
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, true), (8, false));")] /// //
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), (", stringify!($SelfT), "::MIN, true));")] #[doc = concat!("// 10 MAX (a = 10 × 2^", stringify!($BITS), " + 2^", stringify!($BITS), " - 1)")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(0, true), (", stringify!($SelfT), "::MIN, true));")] #[doc = concat!("// + -5 9 (b = -5 × 2^", stringify!($BITS), " + 9)")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, true), (", stringify!($SelfT), "::MIN + 1, true));")] /// // ---------
#[doc = concat!("assert_eq!(", #[doc = concat!("// 6 8 (sum = 6 × 2^", stringify!($BITS), " + 8)")]
stringify!($SelfT), "::MAX.carrying_add(", stringify!($SelfT), "::MAX, true), ",
"(-1, true));"
)]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.carrying_add(-1, true), (", stringify!($SelfT), "::MIN, false));")]
#[doc = concat!("assert_eq!(0", stringify!($SelfT), ".carrying_add(", stringify!($SelfT), "::MAX, true), (", stringify!($SelfT), "::MIN, true));")]
/// ```
/// ///
/// If `carry` is false, this method is equivalent to [`overflowing_add`](Self::overflowing_add): #[doc = concat!("let (a1, a0): (", stringify!($SelfT), ", ", stringify!($UnsignedT), ") = (10, ", stringify!($UnsignedT), "::MAX);")]
#[doc = concat!("let (b1, b0): (", stringify!($SelfT), ", ", stringify!($UnsignedT), ") = (-5, 9);")]
/// let carry0 = false;
/// ///
/// ``` #[doc = concat!("// ", stringify!($UnsignedT), "::carrying_add for the less significant words")]
/// #![feature(bigint_helper_methods)] /// let (sum0, carry1) = a0.carrying_add(b0, carry0);
#[doc = concat!("assert_eq!(5_", stringify!($SelfT), ".carrying_add(2, false), 5_", stringify!($SelfT), ".overflowing_add(2));")] /// assert_eq!(carry1, true);
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), ", stringify!($SelfT), "::MAX.overflowing_add(1));")] ///
#[doc = concat!("// ", stringify!($SelfT), "::carrying_add for the most significant word")]
/// let (sum1, overflow) = a1.carrying_add(b1, carry1);
/// assert_eq!(overflow, false);
///
/// assert_eq!((sum1, sum0), (6, 8));
/// ``` /// ```
#[unstable(feature = "bigint_helper_methods", issue = "85532")] #[unstable(feature = "bigint_helper_methods", issue = "85532")]
#[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")] #[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
@ -1608,25 +1621,51 @@ pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
(a as Self, b) (a as Self, b)
} }
/// Calculates `self - rhs - borrow` without the ability to overflow. /// Calculates `self` &minus; `rhs` &minus; `borrow` and checks for
/// overflow.
/// ///
/// Performs "signed ternary subtraction" which takes in an extra bit to subtract, and may return an /// Performs "ternary subtraction" by subtracting both an integer
/// additional bit of overflow. This signed function is used only on the highest-ordered data, /// operandand a borrow-in bit from `self`, and returns a tuple of the
/// for which the signed overflow result indicates whether the big integer overflowed or not. /// difference along with a boolean indicating whether an arithmetic
/// overflow would occur. On overflow, the wrapped value is returned.
///
/// This allows chaining together multiple subtractions to create a
/// wider subtraction, and can be useful for bignum subtraction. This
/// method should only be used for the most significant word; for the
/// less significant words the unsigned method
#[doc = concat!("[`", stringify!($UnsignedT), "::borrowing_sub`]")]
/// should be used.
///
/// The output boolean returned by this method is *not* a borrow flag,
/// and should *not* be subtracted from a more significant word.
///
/// If the input borrow is false, this method is equivalent to
/// [`overflowing_sub`](Self::overflowing_sub).
/// ///
/// # Examples /// # Examples
/// ///
/// Basic usage:
///
/// ``` /// ```
/// #![feature(bigint_helper_methods)] /// #![feature(bigint_helper_methods)]
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".borrowing_sub(2, false), (3, false));")] /// // Only the most significant word is signed.
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".borrowing_sub(2, true), (2, false));")] /// //
#[doc = concat!("assert_eq!(0", stringify!($SelfT), ".borrowing_sub(1, false), (-1, false));")] #[doc = concat!("// 6 8 (a = 6 × 2^", stringify!($BITS), " + 8)")]
#[doc = concat!("assert_eq!(0", stringify!($SelfT), ".borrowing_sub(1, true), (-2, false));")] #[doc = concat!("// - -5 9 (b = -5 × 2^", stringify!($BITS), " + 9)")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.borrowing_sub(1, true), (", stringify!($SelfT), "::MAX - 1, true));")] /// // ---------
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.borrowing_sub(-1, false), (", stringify!($SelfT), "::MIN, true));")] #[doc = concat!("// 10 MAX (diff = 10 × 2^", stringify!($BITS), " + 2^", stringify!($BITS), " - 1)")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.borrowing_sub(-1, true), (", stringify!($SelfT), "::MAX, false));")] ///
#[doc = concat!("let (a1, a0): (", stringify!($SelfT), ", ", stringify!($UnsignedT), ") = (6, 8);")]
#[doc = concat!("let (b1, b0): (", stringify!($SelfT), ", ", stringify!($UnsignedT), ") = (-5, 9);")]
/// let borrow0 = false;
///
#[doc = concat!("// ", stringify!($UnsignedT), "::borrowing_sub for the less significant words")]
/// let (diff0, borrow1) = a0.borrowing_sub(b0, borrow0);
/// assert_eq!(borrow1, true);
///
#[doc = concat!("// ", stringify!($SelfT), "::borrowing_sub for the most significant word")]
/// let (diff1, overflow) = a1.borrowing_sub(b1, borrow1);
/// assert_eq!(overflow, false);
///
#[doc = concat!("assert_eq!((diff1, diff0), (10, ", stringify!($UnsignedT), "::MAX));")]
/// ``` /// ```
#[unstable(feature = "bigint_helper_methods", issue = "85532")] #[unstable(feature = "bigint_helper_methods", issue = "85532")]
#[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")] #[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]

View file

@ -622,9 +622,8 @@ impl<P: Deref> Pin<P> {
/// that the closure is pinned. /// that the closure is pinned.
/// ///
/// The better alternative is to avoid all that trouble and do the pinning in the outer function /// The better alternative is to avoid all that trouble and do the pinning in the outer function
/// instead (here using the unstable `pin` macro): /// instead (here using the [`pin!`][crate::pin::pin] macro):
/// ``` /// ```
/// #![feature(pin_macro)]
/// use std::pin::pin; /// use std::pin::pin;
/// use std::task::Context; /// use std::task::Context;
/// use std::future::Future; /// use std::future::Future;
@ -1026,7 +1025,6 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
/// ### Basic usage /// ### Basic usage
/// ///
/// ```rust /// ```rust
/// #![feature(pin_macro)]
/// # use core::marker::PhantomPinned as Foo; /// # use core::marker::PhantomPinned as Foo;
/// use core::pin::{pin, Pin}; /// use core::pin::{pin, Pin};
/// ///
@ -1044,7 +1042,6 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
/// ### Manually polling a `Future` (without `Unpin` bounds) /// ### Manually polling a `Future` (without `Unpin` bounds)
/// ///
/// ```rust /// ```rust
/// #![feature(pin_macro)]
/// use std::{ /// use std::{
/// future::Future, /// future::Future,
/// pin::pin, /// pin::pin,
@ -1083,7 +1080,7 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
/// ### With `Generator`s /// ### With `Generator`s
/// ///
/// ```rust /// ```rust
/// #![feature(generators, generator_trait, pin_macro)] /// #![feature(generators, generator_trait)]
/// use core::{ /// use core::{
/// ops::{Generator, GeneratorState}, /// ops::{Generator, GeneratorState},
/// pin::pin, /// pin::pin,
@ -1126,7 +1123,6 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
/// The following, for instance, fails to compile: /// The following, for instance, fails to compile:
/// ///
/// ```rust,compile_fail /// ```rust,compile_fail
/// #![feature(pin_macro)]
/// use core::pin::{pin, Pin}; /// use core::pin::{pin, Pin};
/// # use core::{marker::PhantomPinned as Foo, mem::drop as stuff}; /// # use core::{marker::PhantomPinned as Foo, mem::drop as stuff};
/// ///
@ -1168,7 +1164,7 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
/// constructor. /// constructor.
/// ///
/// [`Box::pin`]: ../../std/boxed/struct.Box.html#method.pin /// [`Box::pin`]: ../../std/boxed/struct.Box.html#method.pin
#[unstable(feature = "pin_macro", issue = "93178")] #[stable(feature = "pin_macro", since = "CURRENT_RUSTC_VERSION")]
#[rustc_macro_transparency = "semitransparent"] #[rustc_macro_transparency = "semitransparent"]
#[allow_internal_unstable(unsafe_pin_internals)] #[allow_internal_unstable(unsafe_pin_internals)]
pub macro pin($value:expr $(,)?) { pub macro pin($value:expr $(,)?) {

View file

@ -48,7 +48,6 @@
#![feature(is_sorted)] #![feature(is_sorted)]
#![feature(layout_for_ptr)] #![feature(layout_for_ptr)]
#![feature(pattern)] #![feature(pattern)]
#![feature(pin_macro)]
#![feature(sort_internals)] #![feature(sort_internals)]
#![feature(slice_take)] #![feature(slice_take)]
#![feature(slice_from_ptr_range)] #![feature(slice_from_ptr_range)]

View file

@ -1,5 +1,3 @@
#![feature(pin_macro)]
use core::future::Future; use core::future::Future;
use core::pin::Pin; use core::pin::Pin;
use core::task::{Context, Poll}; use core::task::{Context, Poll};

View file

@ -1,5 +1,3 @@
#![feature(pin_macro)]
use std::future::*; use std::future::*;
use std::marker::PhantomPinned; use std::marker::PhantomPinned;
use std::pin::*; use std::pin::*;

View file

@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/substs-ppaux.rs:16:17 --> $DIR/substs-ppaux.rs:16:17
| |
LL | fn bar<'a, T>() where T: 'a {} LL | fn bar<'a, T>() where T: 'a {}
| --------------------------- fn() {<i8 as Foo<'static, 'static, u8>>::bar::<'static, char>} defined here | --------------------------- associated function `bar` defined here
... ...
LL | let x: () = <i8 as Foo<'static, 'static, u8>>::bar::<'static, char>; LL | let x: () = <i8 as Foo<'static, 'static, u8>>::bar::<'static, char>;
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
@ -20,7 +20,7 @@ error[E0308]: mismatched types
--> $DIR/substs-ppaux.rs:25:17 --> $DIR/substs-ppaux.rs:25:17
| |
LL | fn bar<'a, T>() where T: 'a {} LL | fn bar<'a, T>() where T: 'a {}
| --------------------------- fn() {<i8 as Foo<'static, 'static>>::bar::<'static, char>} defined here | --------------------------- associated function `bar` defined here
... ...
LL | let x: () = <i8 as Foo<'static, 'static, u32>>::bar::<'static, char>; LL | let x: () = <i8 as Foo<'static, 'static, u32>>::bar::<'static, char>;
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
@ -38,7 +38,7 @@ error[E0308]: mismatched types
--> $DIR/substs-ppaux.rs:33:17 --> $DIR/substs-ppaux.rs:33:17
| |
LL | fn baz() {} LL | fn baz() {}
| -------- fn() {<i8 as Foo<'static, 'static, u8>>::baz} defined here | -------- associated function `baz` defined here
... ...
LL | let x: () = <i8 as Foo<'static, 'static, u8>>::baz; LL | let x: () = <i8 as Foo<'static, 'static, u8>>::baz;
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
@ -56,7 +56,7 @@ error[E0308]: mismatched types
--> $DIR/substs-ppaux.rs:41:17 --> $DIR/substs-ppaux.rs:41:17
| |
LL | fn foo<'z>() where &'z (): Sized { LL | fn foo<'z>() where &'z (): Sized {
| -------------------------------- fn() {foo::<'static>} defined here | -------------------------------- function `foo` defined here
... ...
LL | let x: () = foo::<'static>; LL | let x: () = foo::<'static>;
| -- ^^^^^^^^^^^^^^ expected `()`, found fn item | -- ^^^^^^^^^^^^^^ expected `()`, found fn item

View file

@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/substs-ppaux.rs:16:17 --> $DIR/substs-ppaux.rs:16:17
| |
LL | fn bar<'a, T>() where T: 'a {} LL | fn bar<'a, T>() where T: 'a {}
| --------------------------- fn() {<i8 as Foo<ReStatic, ReStatic, u8>>::bar::<ReStatic, char>} defined here | --------------------------- associated function `bar` defined here
... ...
LL | let x: () = <i8 as Foo<'static, 'static, u8>>::bar::<'static, char>; LL | let x: () = <i8 as Foo<'static, 'static, u8>>::bar::<'static, char>;
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
@ -20,7 +20,7 @@ error[E0308]: mismatched types
--> $DIR/substs-ppaux.rs:25:17 --> $DIR/substs-ppaux.rs:25:17
| |
LL | fn bar<'a, T>() where T: 'a {} LL | fn bar<'a, T>() where T: 'a {}
| --------------------------- fn() {<i8 as Foo<ReStatic, ReStatic>>::bar::<ReStatic, char>} defined here | --------------------------- associated function `bar` defined here
... ...
LL | let x: () = <i8 as Foo<'static, 'static, u32>>::bar::<'static, char>; LL | let x: () = <i8 as Foo<'static, 'static, u32>>::bar::<'static, char>;
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
@ -38,7 +38,7 @@ error[E0308]: mismatched types
--> $DIR/substs-ppaux.rs:33:17 --> $DIR/substs-ppaux.rs:33:17
| |
LL | fn baz() {} LL | fn baz() {}
| -------- fn() {<i8 as Foo<ReStatic, ReStatic, u8>>::baz} defined here | -------- associated function `baz` defined here
... ...
LL | let x: () = <i8 as Foo<'static, 'static, u8>>::baz; LL | let x: () = <i8 as Foo<'static, 'static, u8>>::baz;
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
@ -56,7 +56,7 @@ error[E0308]: mismatched types
--> $DIR/substs-ppaux.rs:41:17 --> $DIR/substs-ppaux.rs:41:17
| |
LL | fn foo<'z>() where &'z (): Sized { LL | fn foo<'z>() where &'z (): Sized {
| -------------------------------- fn() {foo::<ReStatic>} defined here | -------------------------------- function `foo` defined here
... ...
LL | let x: () = foo::<'static>; LL | let x: () = foo::<'static>;
| -- ^^^^^^^^^^^^^^ expected `()`, found fn item | -- ^^^^^^^^^^^^^^ expected `()`, found fn item

View file

@ -4,7 +4,6 @@ error[E0277]: the trait bound `u32: Signed` is not satisfied
LL | is_defaulted::<&'static u32>(); LL | is_defaulted::<&'static u32>();
| ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32` | ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`
| |
= help: the trait `Signed` is implemented for `i32`
note: required for `&'static u32` to implement `Defaulted` note: required for `&'static u32` to implement `Defaulted`
--> $DIR/typeck-default-trait-impl-precedence.rs:10:19 --> $DIR/typeck-default-trait-impl-precedence.rs:10:19
| |
@ -17,6 +16,11 @@ note: required by a bound in `is_defaulted`
| |
LL | fn is_defaulted<T:Defaulted>() { } LL | fn is_defaulted<T:Defaulted>() { }
| ^^^^^^^^^ required by this bound in `is_defaulted` | ^^^^^^^^^ required by this bound in `is_defaulted`
help: consider removing the leading `&`-reference
|
LL - is_defaulted::<&'static u32>();
LL + is_defaulted::<u32>();
|
error: aborting due to previous error error: aborting due to previous error

View file

@ -1,4 +1,4 @@
error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered error[E0005]: refutable pattern in local binding
--> $DIR/const-match-check.rs:25:15 --> $DIR/const-match-check.rs:25:15
| |
LL | A = { let 0 = 0; 0 }, LL | A = { let 0 = 0; 0 },

View file

@ -1,4 +1,4 @@
error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered error[E0005]: refutable pattern in local binding
--> $DIR/const-match-check.rs:31:24 --> $DIR/const-match-check.rs:31:24
| |
LL | let x: [i32; { let 0 = 0; 0 }] = []; LL | let x: [i32; { let 0 = 0; 0 }] = [];

View file

@ -1,4 +1,4 @@
error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered error[E0005]: refutable pattern in local binding
--> $DIR/const-match-check.rs:4:22 --> $DIR/const-match-check.rs:4:22
| |
LL | const X: i32 = { let 0 = 0; 0 }; LL | const X: i32 = { let 0 = 0; 0 };
@ -12,7 +12,7 @@ help: you might want to use `if let` to ignore the variants that aren't matched
LL | const X: i32 = { if let 0 = 0 { todo!() } 0 }; LL | const X: i32 = { if let 0 = 0 { todo!() } 0 };
| ++ ~~~~~~~~~~~ | ++ ~~~~~~~~~~~
error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered error[E0005]: refutable pattern in local binding
--> $DIR/const-match-check.rs:8:23 --> $DIR/const-match-check.rs:8:23
| |
LL | static Y: i32 = { let 0 = 0; 0 }; LL | static Y: i32 = { let 0 = 0; 0 };
@ -26,7 +26,7 @@ help: you might want to use `if let` to ignore the variants that aren't matched
LL | static Y: i32 = { if let 0 = 0 { todo!() } 0 }; LL | static Y: i32 = { if let 0 = 0 { todo!() } 0 };
| ++ ~~~~~~~~~~~ | ++ ~~~~~~~~~~~
error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered error[E0005]: refutable pattern in local binding
--> $DIR/const-match-check.rs:13:26 --> $DIR/const-match-check.rs:13:26
| |
LL | const X: i32 = { let 0 = 0; 0 }; LL | const X: i32 = { let 0 = 0; 0 };
@ -40,7 +40,7 @@ help: you might want to use `if let` to ignore the variants that aren't matched
LL | const X: i32 = { if let 0 = 0 { todo!() } 0 }; LL | const X: i32 = { if let 0 = 0 { todo!() } 0 };
| ++ ~~~~~~~~~~~ | ++ ~~~~~~~~~~~
error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered error[E0005]: refutable pattern in local binding
--> $DIR/const-match-check.rs:19:26 --> $DIR/const-match-check.rs:19:26
| |
LL | const X: i32 = { let 0 = 0; 0 }; LL | const X: i32 = { let 0 = 0; 0 };

View file

@ -9,8 +9,20 @@ mod foo {
const a: u8 = 2; const a: u8 = 2;
fn main() { fn main() {
let a = 4; //~ ERROR refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8::MAX let a = 4;
let c = 4; //~ ERROR refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8::MAX //~^ ERROR refutable pattern in local binding
let d = 4; //~ ERROR refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8::MAX //~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
//~| missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
//~| HELP introduce a variable instead
let c = 4;
//~^ ERROR refutable pattern in local binding
//~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
//~| missing patterns are not covered because `c` is interpreted as a constant pattern, not a new variable
//~| HELP introduce a variable instead
let d = 4;
//~^ ERROR refutable pattern in local binding
//~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
//~| missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable
//~| HELP introduce a variable instead
fn f() {} // Check that the `NOTE`s still work with an item here (cf. issue #35115). fn f() {} // Check that the `NOTE`s still work with an item here (cf. issue #35115).
} }

View file

@ -1,4 +1,4 @@
error[E0005]: refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered error[E0005]: refutable pattern in local binding
--> $DIR/const-pattern-irrefutable.rs:12:9 --> $DIR/const-pattern-irrefutable.rs:12:9
| |
LL | const a: u8 = 2; LL | const a: u8 = 2;
@ -7,13 +7,14 @@ LL | const a: u8 = 2;
LL | let a = 4; LL | let a = 4;
| ^ | ^
| | | |
| interpreted as a constant pattern, not a new variable | patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
| missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
| help: introduce a variable instead: `a_var` | help: introduce a variable instead: `a_var`
| |
= note: the matched value is of type `u8` = note: the matched value is of type `u8`
error[E0005]: refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered error[E0005]: refutable pattern in local binding
--> $DIR/const-pattern-irrefutable.rs:13:9 --> $DIR/const-pattern-irrefutable.rs:17:9
| |
LL | pub const b: u8 = 2; LL | pub const b: u8 = 2;
| --------------- constant defined here | --------------- constant defined here
@ -21,13 +22,14 @@ LL | pub const b: u8 = 2;
LL | let c = 4; LL | let c = 4;
| ^ | ^
| | | |
| interpreted as a constant pattern, not a new variable | patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
| missing patterns are not covered because `c` is interpreted as a constant pattern, not a new variable
| help: introduce a variable instead: `c_var` | help: introduce a variable instead: `c_var`
| |
= note: the matched value is of type `u8` = note: the matched value is of type `u8`
error[E0005]: refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered error[E0005]: refutable pattern in local binding
--> $DIR/const-pattern-irrefutable.rs:14:9 --> $DIR/const-pattern-irrefutable.rs:22:9
| |
LL | pub const d: u8 = 2; LL | pub const d: u8 = 2;
| --------------- constant defined here | --------------- constant defined here
@ -35,7 +37,8 @@ LL | pub const d: u8 = 2;
LL | let d = 4; LL | let d = 4;
| ^ | ^
| | | |
| interpreted as a constant pattern, not a new variable | patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
| missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable
| help: introduce a variable instead: `d_var` | help: introduce a variable instead: `d_var`
| |
= note: the matched value is of type `u8` = note: the matched value is of type `u8`

View file

@ -1,4 +1,4 @@
error[E0005]: refutable pattern in function argument: `&[]`, `&[_]` and `&[_, _, _, ..]` not covered error[E0005]: refutable pattern in function argument
--> $DIR/const_let_refutable.rs:3:16 --> $DIR/const_let_refutable.rs:3:16
| |
LL | const fn slice(&[a, b]: &[i32]) -> i32 { LL | const fn slice(&[a, b]: &[i32]) -> i32 {

View file

@ -8,7 +8,8 @@ enum Helper<T, U> {
fn transmute<T, U>(t: T) -> U { fn transmute<T, U>(t: T) -> U {
let Helper::U(u) = Helper::T(t, []); let Helper::U(u) = Helper::T(t, []);
//~^ ERROR refutable pattern in local binding: `Helper::T(_, _)` not covered //~^ ERROR refutable pattern in local binding
//~| `Helper::T(_, _)` not covered
u u
} }

View file

@ -1,4 +1,4 @@
error[E0005]: refutable pattern in local binding: `Helper::T(_, _)` not covered error[E0005]: refutable pattern in local binding
--> $DIR/empty-never-array.rs:10:9 --> $DIR/empty-never-array.rs:10:9
| |
LL | let Helper::U(u) = Helper::T(t, []); LL | let Helper::U(u) = Helper::T(t, []);
@ -7,18 +7,14 @@ LL | let Helper::U(u) = Helper::T(t, []);
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `Helper<T, U>` defined here note: `Helper<T, U>` defined here
--> $DIR/empty-never-array.rs:4:5 --> $DIR/empty-never-array.rs:3:6
| |
LL | enum Helper<T, U> { LL | enum Helper<T, U> {
| ------ | ^^^^^^
LL | T(T, [!; 0]), LL | T(T, [!; 0]),
| ^ not covered | - not covered
= note: the matched value is of type `Helper<T, U>` = note: the matched value is of type `Helper<T, U>`
help: you might want to use `if let` to ignore the variant that isn't matched help: you might want to use `let else` to handle the variant that isn't matched
|
LL | let u = if let Helper::U(u) = Helper::T(t, []) { u } else { todo!() };
| ++++++++++ ++++++++++++++++++++++
help: alternatively, you might want to use let else to handle the variant that isn't matched
| |
LL | let Helper::U(u) = Helper::T(t, []) else { todo!() }; LL | let Helper::U(u) = Helper::T(t, []) else { todo!() };
| ++++++++++++++++ | ++++++++++++++++

View file

@ -1,4 +1,4 @@
error[E0005]: refutable pattern in local binding: `None` not covered error[E0005]: refutable pattern in local binding
--> $DIR/E0005.rs:3:9 --> $DIR/E0005.rs:3:9
| |
LL | let Some(y) = x; LL | let Some(y) = x;
@ -6,17 +6,8 @@ LL | let Some(y) = x;
| |
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `Option<i32>` defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
::: $SRC_DIR/core/src/option.rs:LL:COL
|
= note: not covered
= note: the matched value is of type `Option<i32>` = note: the matched value is of type `Option<i32>`
help: you might want to use `if let` to ignore the variant that isn't matched help: you might want to use `let else` to handle the variant that isn't matched
|
LL | let y = if let Some(y) = x { y } else { todo!() };
| ++++++++++ ++++++++++++++++++++++
help: alternatively, you might want to use let else to handle the variant that isn't matched
| |
LL | let Some(y) = x else { todo!() }; LL | let Some(y) = x else { todo!() };
| ++++++++++++++++ | ++++++++++++++++

View file

@ -1,14 +1,9 @@
error[E0005]: refutable pattern in `for` loop binding: `None` not covered error[E0005]: refutable pattern in `for` loop binding
--> $DIR/E0297.rs:4:9 --> $DIR/E0297.rs:4:9
| |
LL | for Some(x) in xs {} LL | for Some(x) in xs {}
| ^^^^^^^ pattern `None` not covered | ^^^^^^^ pattern `None` not covered
| |
note: `Option<i32>` defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
::: $SRC_DIR/core/src/option.rs:LL:COL
|
= note: not covered
= note: the matched value is of type `Option<i32>` = note: the matched value is of type `Option<i32>`
error: aborting due to previous error error: aborting due to previous error

View file

@ -1,4 +1,4 @@
error[E0005]: refutable pattern in local binding: `Err(_)` not covered error[E0005]: refutable pattern in local binding
--> $DIR/feature-gate-exhaustive-patterns.rs:8:9 --> $DIR/feature-gate-exhaustive-patterns.rs:8:9
| |
LL | let Ok(_x) = foo(); LL | let Ok(_x) = foo();
@ -6,17 +6,8 @@ LL | let Ok(_x) = foo();
| |
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `Result<u32, !>` defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
::: $SRC_DIR/core/src/result.rs:LL:COL
|
= note: not covered
= note: the matched value is of type `Result<u32, !>` = note: the matched value is of type `Result<u32, !>`
help: you might want to use `if let` to ignore the variant that isn't matched help: you might want to use `let else` to handle the variant that isn't matched
|
LL | let _x = if let Ok(_x) = foo() { _x } else { todo!() };
| +++++++++++ +++++++++++++++++++++++
help: alternatively, you might want to use let else to handle the variant that isn't matched
| |
LL | let Ok(_x) = foo() else { todo!() }; LL | let Ok(_x) = foo() else { todo!() };
| ++++++++++++++++ | ++++++++++++++++

View file

@ -1,4 +1,4 @@
error[E0005]: refutable pattern in `for` loop binding: `&i32::MIN..=0_i32` and `&2_i32..=i32::MAX` not covered error[E0005]: refutable pattern in `for` loop binding
--> $DIR/for-loop-refutable-pattern-error-message.rs:2:9 --> $DIR/for-loop-refutable-pattern-error-message.rs:2:9
| |
LL | for &1 in [1].iter() {} LL | for &1 in [1].iter() {}

View file

@ -2,11 +2,15 @@ error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied
--> $DIR/issue-102140.rs:23:22 --> $DIR/issue-102140.rs:23:22
| |
LL | MyTrait::foo(&self) LL | MyTrait::foo(&self)
| ------------ -^^^^ | ------------ ^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait`
| | | | |
| | the trait `MyTrait` is not implemented for `&dyn MyTrait`
| | help: consider removing the leading `&`-reference
| required by a bound introduced by this call | required by a bound introduced by this call
|
help: consider removing the leading `&`-reference
|
LL - MyTrait::foo(&self)
LL + MyTrait::foo(self)
|
error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied
--> $DIR/issue-102140.rs:23:9 --> $DIR/issue-102140.rs:23:9

View file

@ -2,7 +2,8 @@ fn main() {
let values: Vec<u8> = vec![1,2,3,4,5,6,7,8]; let values: Vec<u8> = vec![1,2,3,4,5,6,7,8];
for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) { for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) {
//~^ ERROR refutable pattern in `for` loop binding: `&[]`, `&[_]`, `&[_, _]` and 1 more not //~^ ERROR refutable pattern in `for` loop binding
//~| patterns `&[]`, `&[_]`, `&[_, _]` and 1 more not covered
println!("y={}", y); println!("y={}", y);
} }
} }

View file

@ -1,4 +1,4 @@
error[E0005]: refutable pattern in `for` loop binding: `&[]`, `&[_]`, `&[_, _]` and 1 more not covered error[E0005]: refutable pattern in `for` loop binding
--> $DIR/issue-15381.rs:4:9 --> $DIR/issue-15381.rs:4:9
| |
LL | for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) { LL | for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) {

View file

@ -2,15 +2,15 @@ error[E0308]: mismatched types
--> $DIR/issue-35241.rs:3:20 --> $DIR/issue-35241.rs:3:20
| |
LL | struct Foo(u32); LL | struct Foo(u32);
| ---------- fn(u32) -> Foo {Foo} defined here | ---------- `Foo` defines a struct constructor here, which should be called
LL | LL |
LL | fn test() -> Foo { Foo } LL | fn test() -> Foo { Foo }
| --- ^^^ expected struct `Foo`, found fn item | --- ^^^ expected struct `Foo`, found struct constructor
| | | |
| expected `Foo` because of return type | expected `Foo` because of return type
| |
= note: expected struct `Foo` = note: expected struct `Foo`
found fn item `fn(u32) -> Foo {Foo}` found struct constructor `fn(u32) -> Foo {Foo}`
help: use parentheses to construct this tuple struct help: use parentheses to construct this tuple struct
| |
LL | fn test() -> Foo { Foo(/* u32 */) } LL | fn test() -> Foo { Foo(/* u32 */) }

View file

@ -4,12 +4,16 @@ error[E0277]: the trait bound `&'static mut isize: Copy` is not satisfied
LL | assert_copy::<&'static mut isize>(); LL | assert_copy::<&'static mut isize>();
| ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'static mut isize` | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'static mut isize`
| |
= help: the trait `Copy` is implemented for `isize`
note: required by a bound in `assert_copy` note: required by a bound in `assert_copy`
--> $DIR/kindck-copy.rs:5:18 --> $DIR/kindck-copy.rs:5:18
| |
LL | fn assert_copy<T:Copy>() { } LL | fn assert_copy<T:Copy>() { }
| ^^^^ required by this bound in `assert_copy` | ^^^^ required by this bound in `assert_copy`
help: consider removing the leading `&`-reference
|
LL - assert_copy::<&'static mut isize>();
LL + assert_copy::<isize>();
|
error[E0277]: the trait bound `&'a mut isize: Copy` is not satisfied error[E0277]: the trait bound `&'a mut isize: Copy` is not satisfied
--> $DIR/kindck-copy.rs:28:19 --> $DIR/kindck-copy.rs:28:19
@ -17,12 +21,16 @@ error[E0277]: the trait bound `&'a mut isize: Copy` is not satisfied
LL | assert_copy::<&'a mut isize>(); LL | assert_copy::<&'a mut isize>();
| ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'a mut isize` | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'a mut isize`
| |
= help: the trait `Copy` is implemented for `isize`
note: required by a bound in `assert_copy` note: required by a bound in `assert_copy`
--> $DIR/kindck-copy.rs:5:18 --> $DIR/kindck-copy.rs:5:18
| |
LL | fn assert_copy<T:Copy>() { } LL | fn assert_copy<T:Copy>() { }
| ^^^^ required by this bound in `assert_copy` | ^^^^ required by this bound in `assert_copy`
help: consider removing the leading `&`-reference
|
LL - assert_copy::<&'a mut isize>();
LL + assert_copy::<isize>();
|
error[E0277]: the trait bound `Box<isize>: Copy` is not satisfied error[E0277]: the trait bound `Box<isize>: Copy` is not satisfied
--> $DIR/kindck-copy.rs:31:19 --> $DIR/kindck-copy.rs:31:19

View file

@ -1,4 +1,4 @@
error[E0005]: refutable pattern in local binding: `Either::B(_)` not covered error[E0005]: refutable pattern in local binding
--> $DIR/exhaustive_patterns.rs:20:9 --> $DIR/exhaustive_patterns.rs:20:9
| |
LL | let Either::A(()) = foo(); LL | let Either::A(()) = foo();
@ -7,13 +7,13 @@ LL | let Either::A(()) = foo();
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `Either<(), !>` defined here note: `Either<(), !>` defined here
--> $DIR/exhaustive_patterns.rs:12:5 --> $DIR/exhaustive_patterns.rs:10:6
| |
LL | enum Either<A, B> { LL | enum Either<A, B> {
| ------ | ^^^^^^
LL | A(A), LL | A(A),
LL | B(inner::Wrapper<B>), LL | B(inner::Wrapper<B>),
| ^ not covered | - not covered
= note: the matched value is of type `Either<(), !>` = note: the matched value is of type `Either<(), !>`
help: you might want to use `if let` to ignore the variant that isn't matched help: you might want to use `if let` to ignore the variant that isn't matched
| |

View file

@ -12,6 +12,11 @@ note: required by a bound in `assert`
| |
LL | fn assert<T: UnwindSafe + ?Sized>() {} LL | fn assert<T: UnwindSafe + ?Sized>() {}
| ^^^^^^^^^^ required by this bound in `assert` | ^^^^^^^^^^ required by this bound in `assert`
help: consider removing the leading `&`-reference
|
LL - assert::<&RefCell<i32>>();
LL + assert::<RefCell<i32>>();
|
error[E0277]: the type `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary error[E0277]: the type `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
--> $DIR/not-panic-safe-4.rs:9:14 --> $DIR/not-panic-safe-4.rs:9:14
@ -28,6 +33,11 @@ note: required by a bound in `assert`
| |
LL | fn assert<T: UnwindSafe + ?Sized>() {} LL | fn assert<T: UnwindSafe + ?Sized>() {}
| ^^^^^^^^^^ required by this bound in `assert` | ^^^^^^^^^^ required by this bound in `assert`
help: consider removing the leading `&`-reference
|
LL - assert::<&RefCell<i32>>();
LL + assert::<RefCell<i32>>();
|
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -5,6 +5,6 @@
fn assert<T: UnwindSafe + ?Sized>() {} fn assert<T: UnwindSafe + ?Sized>() {}
fn main() { fn main() {
assert::<&mut i32>(); assert::<&mut &mut &i32>();
//~^ ERROR the type `&mut i32` may not be safely transferred across an unwind boundary //~^ ERROR the type `&mut &mut &i32` may not be safely transferred across an unwind boundary
} }

View file

@ -1,19 +1,21 @@
error[E0277]: the type `&mut i32` may not be safely transferred across an unwind boundary error[E0277]: the type `&mut &mut &i32` may not be safely transferred across an unwind boundary
--> $DIR/not-panic-safe.rs:8:14 --> $DIR/not-panic-safe.rs:8:14
| |
LL | assert::<&mut i32>(); LL | assert::<&mut &mut &i32>();
| -^^^^^^^ | ^^^^^^^^^^^^^^ `&mut &mut &i32` may not be safely transferred across an unwind boundary
| |
| `&mut i32` may not be safely transferred across an unwind boundary
| help: consider removing the leading `&`-reference
| |
= help: the trait `UnwindSafe` is not implemented for `&mut i32` = help: the trait `UnwindSafe` is not implemented for `&mut &mut &i32`
= note: `UnwindSafe` is implemented for `&i32`, but not for `&mut i32` = note: `UnwindSafe` is implemented for `&&mut &i32`, but not for `&mut &mut &i32`
note: required by a bound in `assert` note: required by a bound in `assert`
--> $DIR/not-panic-safe.rs:5:14 --> $DIR/not-panic-safe.rs:5:14
| |
LL | fn assert<T: UnwindSafe + ?Sized>() {} LL | fn assert<T: UnwindSafe + ?Sized>() {}
| ^^^^^^^^^^ required by this bound in `assert` | ^^^^^^^^^^ required by this bound in `assert`
help: consider removing 2 leading `&`-references
|
LL - assert::<&mut &mut &i32>();
LL + assert::<&i32>();
|
error: aborting due to previous error error: aborting due to previous error

View file

@ -1,4 +1,4 @@
error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered error[E0005]: refutable pattern in local binding
--> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:2:10 --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:2:10
| |
LL | let (0 | (1 | 2)) = 0; LL | let (0 | (1 | 2)) = 0;

View file

@ -6,5 +6,6 @@ enum Thing {
fn main() { fn main() {
let Thing::Foo(y) = Thing::Foo(1); let Thing::Foo(y) = Thing::Foo(1);
//~^ ERROR refutable pattern in local binding: `Thing::Bar` and `Thing::Baz` not covered //~^ ERROR refutable pattern in local binding
//~| `Thing::Bar` and `Thing::Baz` not covered
} }

View file

@ -1,4 +1,4 @@
error[E0005]: refutable pattern in local binding: `Thing::Bar` and `Thing::Baz` not covered error[E0005]: refutable pattern in local binding
--> $DIR/issue-31561.rs:8:9 --> $DIR/issue-31561.rs:8:9
| |
LL | let Thing::Foo(y) = Thing::Foo(1); LL | let Thing::Foo(y) = Thing::Foo(1);
@ -7,21 +7,17 @@ LL | let Thing::Foo(y) = Thing::Foo(1);
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `Thing` defined here note: `Thing` defined here
--> $DIR/issue-31561.rs:3:5 --> $DIR/issue-31561.rs:1:6
| |
LL | enum Thing { LL | enum Thing {
| ----- | ^^^^^
LL | Foo(u8), LL | Foo(u8),
LL | Bar, LL | Bar,
| ^^^ not covered | --- not covered
LL | Baz LL | Baz
| ^^^ not covered | --- not covered
= note: the matched value is of type `Thing` = note: the matched value is of type `Thing`
help: you might want to use `if let` to ignore the variants that aren't matched help: you might want to use `let else` to handle the variants that aren't matched
|
LL | let y = if let Thing::Foo(y) = Thing::Foo(1) { y } else { todo!() };
| ++++++++++ ++++++++++++++++++++++
help: alternatively, you might want to use let else to handle the variants that aren't matched
| |
LL | let Thing::Foo(y) = Thing::Foo(1) else { todo!() }; LL | let Thing::Foo(y) = Thing::Foo(1) else { todo!() };
| ++++++++++++++++ | ++++++++++++++++

View file

@ -15,9 +15,6 @@ enum E {
//~^ NOTE `E` defined here //~^ NOTE `E` defined here
//~| NOTE `E` defined here //~| NOTE `E` defined here
//~| NOTE `E` defined here //~| NOTE `E` defined here
//~| NOTE `E` defined here
//~| NOTE `E` defined here
//~| NOTE `E` defined here
//~| NOTE not covered //~| NOTE not covered
//~| NOTE not covered //~| NOTE not covered
//~| NOTE not covered //~| NOTE not covered
@ -41,37 +38,41 @@ fn by_val(e: E) {
E::A => {} E::A => {}
} }
let E::A = e; //~ ERROR refutable pattern in local binding: `E::B` and `E::C` not covered let E::A = e;
//~^ NOTE patterns `E::B` and `E::C` not covered //~^ ERROR refutable pattern in local binding
//~| patterns `E::B` and `E::C` not covered
//~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with
//~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
//~| NOTE the matched value is of type `E` //~| NOTE the matched value is of type `E`
} }
fn by_ref_once(e: &E) { fn by_ref_once(e: &E) {
match e { //~ ERROR non-exhaustive patterns: `&E::B` and `&E::C` not covered match e {
//~^ NOTE patterns `&E::B` and `&E::C` not covered //~^ ERROR non-exhaustive patterns
//~| patterns `&E::B` and `&E::C` not covered
//~| NOTE the matched value is of type `&E` //~| NOTE the matched value is of type `&E`
E::A => {} E::A => {}
} }
let E::A = e; //~ ERROR refutable pattern in local binding: `&E::B` and `&E::C` not covered let E::A = e;
//~^ NOTE patterns `&E::B` and `&E::C` not covered //~^ ERROR refutable pattern in local binding
//~| patterns `&E::B` and `&E::C` not covered
//~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with
//~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
//~| NOTE the matched value is of type `&E` //~| NOTE the matched value is of type `&E`
} }
fn by_ref_thrice(e: & &mut &E) { fn by_ref_thrice(e: & &mut &E) {
match e { //~ ERROR non-exhaustive patterns: `&&mut &E::B` and `&&mut &E::C` not covered match e {
//~^ NOTE patterns `&&mut &E::B` and `&&mut &E::C` not covered //~^ ERROR non-exhaustive patterns
//~| patterns `&&mut &E::B` and `&&mut &E::C` not covered
//~| NOTE the matched value is of type `&&mut &E` //~| NOTE the matched value is of type `&&mut &E`
E::A => {} E::A => {}
} }
let E::A = e; let E::A = e;
//~^ ERROR refutable pattern in local binding: `&&mut &E::B` and `&&mut &E::C` not covered //~^ ERROR refutable pattern in local binding
//~| NOTE patterns `&&mut &E::B` and `&&mut &E::C` not covered //~| patterns `&&mut &E::B` and `&&mut &E::C` not covered
//~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with
//~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
//~| NOTE the matched value is of type `&&mut &E` //~| NOTE the matched value is of type `&&mut &E`
@ -83,20 +84,21 @@ enum Opt {
Some(u8), Some(u8),
None, None,
//~^ NOTE `Opt` defined here //~^ NOTE `Opt` defined here
//~| NOTE `Opt` defined here
//~| NOTE not covered //~| NOTE not covered
//~| NOTE not covered //~| NOTE not covered
} }
fn ref_pat(e: Opt) { fn ref_pat(e: Opt) {
match e {//~ ERROR non-exhaustive patterns: `Opt::None` not covered match e {
//~^ NOTE pattern `Opt::None` not covered //~^ ERROR non-exhaustive patterns
//~| pattern `Opt::None` not covered
//~| NOTE the matched value is of type `Opt` //~| NOTE the matched value is of type `Opt`
Opt::Some(ref _x) => {} Opt::Some(ref _x) => {}
} }
let Opt::Some(ref _x) = e; //~ ERROR refutable pattern in local binding: `Opt::None` not covered let Opt::Some(ref _x) = e;
//~^ NOTE the matched value is of type `Opt` //~^ ERROR refutable pattern in local binding
//~| NOTE the matched value is of type `Opt`
//~| NOTE pattern `Opt::None` not covered //~| NOTE pattern `Opt::None` not covered
//~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with
//~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html

View file

@ -1,5 +1,5 @@
error[E0004]: non-exhaustive patterns: `E::B` and `E::C` not covered error[E0004]: non-exhaustive patterns: `E::B` and `E::C` not covered
--> $DIR/non-exhaustive-defined-here.rs:38:11 --> $DIR/non-exhaustive-defined-here.rs:35:11
| |
LL | match e1 { LL | match e1 {
| ^^ patterns `E::B` and `E::C` not covered | ^^ patterns `E::B` and `E::C` not covered
@ -22,8 +22,8 @@ LL ~ E::A => {}
LL + E::B | E::C => todo!() LL + E::B | E::C => todo!()
| |
error[E0005]: refutable pattern in local binding: `E::B` and `E::C` not covered error[E0005]: refutable pattern in local binding
--> $DIR/non-exhaustive-defined-here.rs:44:9 --> $DIR/non-exhaustive-defined-here.rs:41:9
| |
LL | let E::A = e; LL | let E::A = e;
| ^^^^ patterns `E::B` and `E::C` not covered | ^^^^ patterns `E::B` and `E::C` not covered
@ -31,16 +31,16 @@ LL | let E::A = e;
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `E` defined here note: `E` defined here
--> $DIR/non-exhaustive-defined-here.rs:14:5 --> $DIR/non-exhaustive-defined-here.rs:6:6
| |
LL | enum E { LL | enum E {
| - | ^
... ...
LL | B, LL | B,
| ^ not covered | - not covered
... ...
LL | C LL | C
| ^ not covered | - not covered
= note: the matched value is of type `E` = note: the matched value is of type `E`
help: you might want to use `if let` to ignore the variants that aren't matched help: you might want to use `if let` to ignore the variants that aren't matched
| |
@ -48,7 +48,7 @@ LL | if let E::A = e { todo!() }
| ++ ~~~~~~~~~~~ | ++ ~~~~~~~~~~~
error[E0004]: non-exhaustive patterns: `&E::B` and `&E::C` not covered error[E0004]: non-exhaustive patterns: `&E::B` and `&E::C` not covered
--> $DIR/non-exhaustive-defined-here.rs:52:11 --> $DIR/non-exhaustive-defined-here.rs:50:11
| |
LL | match e { LL | match e {
| ^ patterns `&E::B` and `&E::C` not covered | ^ patterns `&E::B` and `&E::C` not covered
@ -71,8 +71,8 @@ LL ~ E::A => {}
LL + &E::B | &E::C => todo!() LL + &E::B | &E::C => todo!()
| |
error[E0005]: refutable pattern in local binding: `&E::B` and `&E::C` not covered error[E0005]: refutable pattern in local binding
--> $DIR/non-exhaustive-defined-here.rs:58:9 --> $DIR/non-exhaustive-defined-here.rs:57:9
| |
LL | let E::A = e; LL | let E::A = e;
| ^^^^ patterns `&E::B` and `&E::C` not covered | ^^^^ patterns `&E::B` and `&E::C` not covered
@ -80,16 +80,16 @@ LL | let E::A = e;
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `E` defined here note: `E` defined here
--> $DIR/non-exhaustive-defined-here.rs:14:5 --> $DIR/non-exhaustive-defined-here.rs:6:6
| |
LL | enum E { LL | enum E {
| - | ^
... ...
LL | B, LL | B,
| ^ not covered | - not covered
... ...
LL | C LL | C
| ^ not covered | - not covered
= note: the matched value is of type `&E` = note: the matched value is of type `&E`
help: you might want to use `if let` to ignore the variants that aren't matched help: you might want to use `if let` to ignore the variants that aren't matched
| |
@ -120,8 +120,8 @@ LL ~ E::A => {}
LL + &&mut &E::B | &&mut &E::C => todo!() LL + &&mut &E::B | &&mut &E::C => todo!()
| |
error[E0005]: refutable pattern in local binding: `&&mut &E::B` and `&&mut &E::C` not covered error[E0005]: refutable pattern in local binding
--> $DIR/non-exhaustive-defined-here.rs:72:9 --> $DIR/non-exhaustive-defined-here.rs:73:9
| |
LL | let E::A = e; LL | let E::A = e;
| ^^^^ patterns `&&mut &E::B` and `&&mut &E::C` not covered | ^^^^ patterns `&&mut &E::B` and `&&mut &E::C` not covered
@ -129,16 +129,16 @@ LL | let E::A = e;
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `E` defined here note: `E` defined here
--> $DIR/non-exhaustive-defined-here.rs:14:5 --> $DIR/non-exhaustive-defined-here.rs:6:6
| |
LL | enum E { LL | enum E {
| - | ^
... ...
LL | B, LL | B,
| ^ not covered | - not covered
... ...
LL | C LL | C
| ^ not covered | - not covered
= note: the matched value is of type `&&mut &E` = note: the matched value is of type `&&mut &E`
help: you might want to use `if let` to ignore the variants that aren't matched help: you might want to use `if let` to ignore the variants that aren't matched
| |
@ -152,7 +152,7 @@ LL | match e {
| ^ pattern `Opt::None` not covered | ^ pattern `Opt::None` not covered
| |
note: `Opt` defined here note: `Opt` defined here
--> $DIR/non-exhaustive-defined-here.rs:84:5 --> $DIR/non-exhaustive-defined-here.rs:85:5
| |
LL | enum Opt { LL | enum Opt {
| --- | ---
@ -166,8 +166,8 @@ LL ~ Opt::Some(ref _x) => {}
LL + Opt::None => todo!() LL + Opt::None => todo!()
| |
error[E0005]: refutable pattern in local binding: `Opt::None` not covered error[E0005]: refutable pattern in local binding
--> $DIR/non-exhaustive-defined-here.rs:98:9 --> $DIR/non-exhaustive-defined-here.rs:99:9
| |
LL | let Opt::Some(ref _x) = e; LL | let Opt::Some(ref _x) = e;
| ^^^^^^^^^^^^^^^^^ pattern `Opt::None` not covered | ^^^^^^^^^^^^^^^^^ pattern `Opt::None` not covered
@ -175,19 +175,15 @@ LL | let Opt::Some(ref _x) = e;
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `Opt` defined here note: `Opt` defined here
--> $DIR/non-exhaustive-defined-here.rs:84:5 --> $DIR/non-exhaustive-defined-here.rs:81:6
| |
LL | enum Opt { LL | enum Opt {
| --- | ^^^
... ...
LL | None, LL | None,
| ^^^^ not covered | ---- not covered
= note: the matched value is of type `Opt` = note: the matched value is of type `Opt`
help: you might want to use `if let` to ignore the variant that isn't matched help: you might want to use `let else` to handle the variant that isn't matched
|
LL | let _x = if let Opt::Some(ref _x) = e { _x } else { todo!() };
| +++++++++++ +++++++++++++++++++++++
help: alternatively, you might want to use let else to handle the variant that isn't matched
| |
LL | let Opt::Some(ref _x) = e else { todo!() }; LL | let Opt::Some(ref _x) = e else { todo!() };
| ++++++++++++++++ | ++++++++++++++++

View file

@ -1,7 +1,9 @@
fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { } fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
//~^ ERROR refutable pattern in function argument: `(_, _)` not covered //~^ ERROR refutable pattern in function argument
//~| `(_, _)` not covered
fn main() { fn main() {
let (1, (Some(1), 2..=3)) = (1, (None, 2)); let (1, (Some(1), 2..=3)) = (1, (None, 2));
//~^ ERROR refutable pattern in local binding: `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered //~^ ERROR refutable pattern in local binding
//~| `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered
} }

View file

@ -1,4 +1,4 @@
error[E0005]: refutable pattern in function argument: `(_, _)` not covered error[E0005]: refutable pattern in function argument
--> $DIR/refutable-pattern-errors.rs:1:9 --> $DIR/refutable-pattern-errors.rs:1:9
| |
LL | fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { } LL | fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
@ -6,8 +6,8 @@ LL | fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
| |
= note: the matched value is of type `(isize, (Option<isize>, isize))` = note: the matched value is of type `(isize, (Option<isize>, isize))`
error[E0005]: refutable pattern in local binding: `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered error[E0005]: refutable pattern in local binding
--> $DIR/refutable-pattern-errors.rs:5:9 --> $DIR/refutable-pattern-errors.rs:6:9
| |
LL | let (1, (Some(1), 2..=3)) = (1, (None, 2)); LL | let (1, (Some(1), 2..=3)) = (1, (None, 2));
| ^^^^^^^^^^^^^^^^^^^^^ patterns `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered | ^^^^^^^^^^^^^^^^^^^^^ patterns `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered

View file

@ -1,5 +1,6 @@
fn main() { fn main() {
let f = |3: isize| println!("hello"); let f = |3: isize| println!("hello");
//~^ ERROR refutable pattern in function argument: `_` not covered //~^ ERROR refutable pattern in function argument
//~| `_` not covered
f(4); f(4);
} }

View file

@ -1,4 +1,4 @@
error[E0005]: refutable pattern in function argument: `_` not covered error[E0005]: refutable pattern in function argument
--> $DIR/refutable-pattern-in-fn-arg.rs:2:14 --> $DIR/refutable-pattern-in-fn-arg.rs:2:14
| |
LL | let f = |3: isize| println!("hello"); LL | let f = |3: isize| println!("hello");

View file

@ -1,5 +1,4 @@
// edition:2018 // edition:2018
#![feature(pin_macro)]
use core::{ use core::{
marker::PhantomPinned, marker::PhantomPinned,

View file

@ -1,5 +1,5 @@
error[E0658]: use of unstable library feature 'unsafe_pin_internals' error[E0658]: use of unstable library feature 'unsafe_pin_internals'
--> $DIR/cant_access_internals.rs:12:15 --> $DIR/cant_access_internals.rs:11:15
| |
LL | mem::take(phantom_pinned.pointer); LL | mem::take(phantom_pinned.pointer);
| ^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^

View file

@ -1,5 +1,4 @@
// edition:2018 // edition:2018
#![feature(pin_macro)]
use core::{ use core::{
convert::identity, convert::identity,

View file

@ -1,5 +1,5 @@
error[E0716]: temporary value dropped while borrowed error[E0716]: temporary value dropped while borrowed
--> $DIR/lifetime_errors_on_promotion_misusage.rs:12:35 --> $DIR/lifetime_errors_on_promotion_misusage.rs:11:35
| |
LL | let phantom_pinned = identity(pin!(PhantomPinned)); LL | let phantom_pinned = identity(pin!(PhantomPinned));
| ^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement | ^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
@ -13,7 +13,7 @@ LL | stuff(phantom_pinned)
= note: this error originates in the macro `pin` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `pin` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0716]: temporary value dropped while borrowed error[E0716]: temporary value dropped while borrowed
--> $DIR/lifetime_errors_on_promotion_misusage.rs:19:30 --> $DIR/lifetime_errors_on_promotion_misusage.rs:18:30
| |
LL | let phantom_pinned = { LL | let phantom_pinned = {
| -------------- borrow later stored here | -------------- borrow later stored here

View file

@ -1,4 +1,4 @@
error[E0005]: refutable pattern in local binding: `Err(_)` not covered error[E0005]: refutable pattern in local binding
--> $DIR/recursive-types-are-not-uninhabited.rs:6:9 --> $DIR/recursive-types-are-not-uninhabited.rs:6:9
| |
LL | let Ok(x) = res; LL | let Ok(x) = res;
@ -6,17 +6,8 @@ LL | let Ok(x) = res;
| |
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `Result<u32, &R<'_>>` defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
::: $SRC_DIR/core/src/result.rs:LL:COL
|
= note: not covered
= note: the matched value is of type `Result<u32, &R<'_>>` = note: the matched value is of type `Result<u32, &R<'_>>`
help: you might want to use `if let` to ignore the variant that isn't matched help: you might want to use `let else` to handle the variant that isn't matched
|
LL | let x = if let Ok(x) = res { x } else { todo!() };
| ++++++++++ ++++++++++++++++++++++
help: alternatively, you might want to use let else to handle the variant that isn't matched
| |
LL | let Ok(x) = res else { todo!() }; LL | let Ok(x) = res else { todo!() };
| ++++++++++++++++ | ++++++++++++++++

View file

@ -264,15 +264,15 @@ error[E0308]: mismatched types
--> $DIR/privacy-enum-ctor.rs:27:20 --> $DIR/privacy-enum-ctor.rs:27:20
| |
LL | Fn(u8), LL | Fn(u8),
| -- fn(u8) -> Z {Z::Fn} defined here | -- `Fn` defines an enum variant constructor here, which should be called
... ...
LL | let _: Z = Z::Fn; LL | let _: Z = Z::Fn;
| - ^^^^^ expected enum `Z`, found fn item | - ^^^^^ expected enum `Z`, found enum constructor
| | | |
| expected due to this | expected due to this
| |
= note: expected enum `Z` = note: expected enum `Z`
found fn item `fn(u8) -> Z {Z::Fn}` found enum constructor `fn(u8) -> Z {Z::Fn}`
help: use parentheses to construct this tuple variant help: use parentheses to construct this tuple variant
| |
LL | let _: Z = Z::Fn(/* u8 */); LL | let _: Z = Z::Fn(/* u8 */);
@ -305,15 +305,15 @@ error[E0308]: mismatched types
--> $DIR/privacy-enum-ctor.rs:43:16 --> $DIR/privacy-enum-ctor.rs:43:16
| |
LL | Fn(u8), LL | Fn(u8),
| -- fn(u8) -> E {E::Fn} defined here | -- `Fn` defines an enum variant constructor here, which should be called
... ...
LL | let _: E = m::E::Fn; LL | let _: E = m::E::Fn;
| - ^^^^^^^^ expected enum `E`, found fn item | - ^^^^^^^^ expected enum `E`, found enum constructor
| | | |
| expected due to this | expected due to this
| |
= note: expected enum `E` = note: expected enum `E`
found fn item `fn(u8) -> E {E::Fn}` found enum constructor `fn(u8) -> E {E::Fn}`
help: use parentheses to construct this tuple variant help: use parentheses to construct this tuple variant
| |
LL | let _: E = m::E::Fn(/* u8 */); LL | let _: E = m::E::Fn(/* u8 */);
@ -346,15 +346,15 @@ error[E0308]: mismatched types
--> $DIR/privacy-enum-ctor.rs:51:16 --> $DIR/privacy-enum-ctor.rs:51:16
| |
LL | Fn(u8), LL | Fn(u8),
| -- fn(u8) -> E {E::Fn} defined here | -- `Fn` defines an enum variant constructor here, which should be called
... ...
LL | let _: E = E::Fn; LL | let _: E = E::Fn;
| - ^^^^^ expected enum `E`, found fn item | - ^^^^^ expected enum `E`, found enum constructor
| | | |
| expected due to this | expected due to this
| |
= note: expected enum `E` = note: expected enum `E`
found fn item `fn(u8) -> E {E::Fn}` found enum constructor `fn(u8) -> E {E::Fn}`
help: use parentheses to construct this tuple variant help: use parentheses to construct this tuple variant
| |
LL | let _: E = E::Fn(/* u8 */); LL | let _: E = E::Fn(/* u8 */);

View file

@ -1,7 +1,8 @@
fn main() { fn main() {
let A = 3; let A = 3;
//~^ ERROR refutable pattern in local binding: `i32::MIN..=1_i32` and //~^ ERROR refutable pattern in local binding
//~| interpreted as a constant pattern, not a new variable //~| patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered
//~| missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
//~| HELP introduce a variable instead //~| HELP introduce a variable instead
//~| SUGGESTION a_var //~| SUGGESTION a_var

View file

@ -1,10 +1,11 @@
error[E0005]: refutable pattern in local binding: `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered error[E0005]: refutable pattern in local binding
--> $DIR/const-pat-non-exaustive-let-new-var.rs:2:9 --> $DIR/const-pat-non-exaustive-let-new-var.rs:2:9
| |
LL | let A = 3; LL | let A = 3;
| ^ | ^
| | | |
| interpreted as a constant pattern, not a new variable | patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered
| missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
| help: introduce a variable instead: `a_var` | help: introduce a variable instead: `a_var`
... ...
LL | const A: i32 = 2; LL | const A: i32 = 2;

View file

@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:29:20 --> $DIR/fn-or-tuple-struct-without-args.rs:29:20
| |
LL | fn foo(a: usize, b: usize) -> usize { a } LL | fn foo(a: usize, b: usize) -> usize { a }
| ----------------------------------- fn(usize, usize) -> usize {foo} defined here | ----------------------------------- function `foo` defined here
... ...
LL | let _: usize = foo; LL | let _: usize = foo;
| ----- ^^^ expected `usize`, found fn item | ----- ^^^ expected `usize`, found fn item
@ -20,15 +20,15 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:30:16 --> $DIR/fn-or-tuple-struct-without-args.rs:30:16
| |
LL | struct S(usize, usize); LL | struct S(usize, usize);
| -------- fn(usize, usize) -> S {S} defined here | -------- `S` defines a struct constructor here, which should be called
... ...
LL | let _: S = S; LL | let _: S = S;
| - ^ expected struct `S`, found fn item | - ^ expected struct `S`, found struct constructor
| | | |
| expected due to this | expected due to this
| |
= note: expected struct `S` = note: expected struct `S`
found fn item `fn(usize, usize) -> S {S}` found struct constructor `fn(usize, usize) -> S {S}`
help: use parentheses to construct this tuple struct help: use parentheses to construct this tuple struct
| |
LL | let _: S = S(/* usize */, /* usize */); LL | let _: S = S(/* usize */, /* usize */);
@ -38,7 +38,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:31:20 --> $DIR/fn-or-tuple-struct-without-args.rs:31:20
| |
LL | fn bar() -> usize { 42 } LL | fn bar() -> usize { 42 }
| ----------------- fn() -> usize {bar} defined here | ----------------- function `bar` defined here
... ...
LL | let _: usize = bar; LL | let _: usize = bar;
| ----- ^^^ expected `usize`, found fn item | ----- ^^^ expected `usize`, found fn item
@ -56,15 +56,15 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:32:16 --> $DIR/fn-or-tuple-struct-without-args.rs:32:16
| |
LL | struct V(); LL | struct V();
| -------- fn() -> V {V} defined here | -------- `V` defines a struct constructor here, which should be called
... ...
LL | let _: V = V; LL | let _: V = V;
| - ^ expected struct `V`, found fn item | - ^ expected struct `V`, found struct constructor
| | | |
| expected due to this | expected due to this
| |
= note: expected struct `V` = note: expected struct `V`
found fn item `fn() -> V {V}` found struct constructor `fn() -> V {V}`
help: use parentheses to construct this tuple struct help: use parentheses to construct this tuple struct
| |
LL | let _: V = V(); LL | let _: V = V();
@ -74,7 +74,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:33:20 --> $DIR/fn-or-tuple-struct-without-args.rs:33:20
| |
LL | fn baz(x: usize, y: usize) -> usize { x } LL | fn baz(x: usize, y: usize) -> usize { x }
| ----------------------------------- fn(usize, usize) -> usize {<_ as T>::baz} defined here | ----------------------------------- associated function `baz` defined here
... ...
LL | let _: usize = T::baz; LL | let _: usize = T::baz;
| ----- ^^^^^^ expected `usize`, found fn item | ----- ^^^^^^ expected `usize`, found fn item
@ -92,7 +92,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:34:20 --> $DIR/fn-or-tuple-struct-without-args.rs:34:20
| |
LL | fn bat(x: usize) -> usize { 42 } LL | fn bat(x: usize) -> usize { 42 }
| ------------------------- fn(usize) -> usize {<_ as T>::bat} defined here | ------------------------- associated function `bat` defined here
... ...
LL | let _: usize = T::bat; LL | let _: usize = T::bat;
| ----- ^^^^^^ expected `usize`, found fn item | ----- ^^^^^^ expected `usize`, found fn item
@ -110,15 +110,15 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:35:16 --> $DIR/fn-or-tuple-struct-without-args.rs:35:16
| |
LL | A(usize), LL | A(usize),
| - fn(usize) -> E {E::A} defined here | - `A` defines an enum variant constructor here, which should be called
... ...
LL | let _: E = E::A; LL | let _: E = E::A;
| - ^^^^ expected enum `E`, found fn item | - ^^^^ expected enum `E`, found enum constructor
| | | |
| expected due to this | expected due to this
| |
= note: expected enum `E` = note: expected enum `E`
found fn item `fn(usize) -> E {E::A}` found enum constructor `fn(usize) -> E {E::A}`
help: use parentheses to construct this tuple variant help: use parentheses to construct this tuple variant
| |
LL | let _: E = E::A(/* usize */); LL | let _: E = E::A(/* usize */);
@ -134,7 +134,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:37:20 --> $DIR/fn-or-tuple-struct-without-args.rs:37:20
| |
LL | fn baz(x: usize, y: usize) -> usize { x } LL | fn baz(x: usize, y: usize) -> usize { x }
| ----------------------------------- fn(usize, usize) -> usize {<X as T>::baz} defined here | ----------------------------------- associated function `baz` defined here
... ...
LL | let _: usize = X::baz; LL | let _: usize = X::baz;
| ----- ^^^^^^ expected `usize`, found fn item | ----- ^^^^^^ expected `usize`, found fn item
@ -152,7 +152,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:38:20 --> $DIR/fn-or-tuple-struct-without-args.rs:38:20
| |
LL | fn bat(x: usize) -> usize { 42 } LL | fn bat(x: usize) -> usize { 42 }
| ------------------------- fn(usize) -> usize {<X as T>::bat} defined here | ------------------------- associated function `bat` defined here
... ...
LL | let _: usize = X::bat; LL | let _: usize = X::bat;
| ----- ^^^^^^ expected `usize`, found fn item | ----- ^^^^^^ expected `usize`, found fn item
@ -170,7 +170,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:39:20 --> $DIR/fn-or-tuple-struct-without-args.rs:39:20
| |
LL | fn bax(x: usize) -> usize { 42 } LL | fn bax(x: usize) -> usize { 42 }
| ------------------------- fn(usize) -> usize {<X as T>::bax} defined here | ------------------------- associated function `bax` defined here
... ...
LL | let _: usize = X::bax; LL | let _: usize = X::bax;
| ----- ^^^^^^ expected `usize`, found fn item | ----- ^^^^^^ expected `usize`, found fn item
@ -188,7 +188,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:40:20 --> $DIR/fn-or-tuple-struct-without-args.rs:40:20
| |
LL | fn bach(x: usize) -> usize; LL | fn bach(x: usize) -> usize;
| --------------------------- fn(usize) -> usize {<X as T>::bach} defined here | --------------------------- associated function `bach` defined here
... ...
LL | let _: usize = X::bach; LL | let _: usize = X::bach;
| ----- ^^^^^^^ expected `usize`, found fn item | ----- ^^^^^^^ expected `usize`, found fn item
@ -206,7 +206,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:41:20 --> $DIR/fn-or-tuple-struct-without-args.rs:41:20
| |
LL | fn ban(&self) -> usize { 42 } LL | fn ban(&self) -> usize { 42 }
| ---------------------- for<'a> fn(&'a X) -> usize {<X as T>::ban} defined here | ---------------------- associated function `ban` defined here
... ...
LL | let _: usize = X::ban; LL | let _: usize = X::ban;
| ----- ^^^^^^ expected `usize`, found fn item | ----- ^^^^^^ expected `usize`, found fn item
@ -224,7 +224,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:42:20 --> $DIR/fn-or-tuple-struct-without-args.rs:42:20
| |
LL | fn bal(&self) -> usize; LL | fn bal(&self) -> usize;
| ----------------------- for<'a> fn(&'a X) -> usize {<X as T>::bal} defined here | ----------------------- associated function `bal` defined here
... ...
LL | let _: usize = X::bal; LL | let _: usize = X::bal;
| ----- ^^^^^^ expected `usize`, found fn item | ----- ^^^^^^ expected `usize`, found fn item

View file

@ -2,13 +2,15 @@ error[E0277]: `&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
--> $DIR/suggest-remove-refs-1.rs:6:19 --> $DIR/suggest-remove-refs-1.rs:6:19
| |
LL | for (i, _) in &v.iter().enumerate() { LL | for (i, _) in &v.iter().enumerate() {
| -^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^ `&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
| |
| `&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
| help: consider removing the leading `&`-reference
| |
= help: the trait `Iterator` is not implemented for `&Enumerate<std::slice::Iter<'_, {integer}>>` = help: the trait `Iterator` is not implemented for `&Enumerate<std::slice::Iter<'_, {integer}>>`
= note: required for `&Enumerate<std::slice::Iter<'_, {integer}>>` to implement `IntoIterator` = note: required for `&Enumerate<std::slice::Iter<'_, {integer}>>` to implement `IntoIterator`
help: consider removing the leading `&`-reference
|
LL - for (i, _) in &v.iter().enumerate() {
LL + for (i, _) in v.iter().enumerate() {
|
error: aborting due to previous error error: aborting due to previous error

View file

@ -2,13 +2,15 @@ error[E0277]: `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterat
--> $DIR/suggest-remove-refs-2.rs:6:19 --> $DIR/suggest-remove-refs-2.rs:6:19
| |
LL | for (i, _) in & & & & &v.iter().enumerate() { LL | for (i, _) in & & & & &v.iter().enumerate() {
| ---------^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
| |
| `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
| help: consider removing 5 leading `&`-references
| |
= help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` = help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
= note: required for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` to implement `IntoIterator` = note: required for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` to implement `IntoIterator`
help: consider removing 5 leading `&`-references
|
LL - for (i, _) in & & & & &v.iter().enumerate() {
LL + for (i, _) in v.iter().enumerate() {
|
error: aborting due to previous error error: aborting due to previous error

View file

@ -1,18 +1,20 @@
error[E0277]: `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator error[E0277]: `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
--> $DIR/suggest-remove-refs-3.rs:6:19 --> $DIR/suggest-remove-refs-3.rs:6:19
| |
LL | for (i, _) in & & & LL | for (i, _) in & & &
| ____________________^ | ___________________^
| | ___________________| LL | | & &v
| || LL | | .iter()
LL | || & &v LL | | .enumerate() {
| ||___________- help: consider removing 5 leading `&`-references | |____________________^ `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
LL | | .iter()
LL | | .enumerate() {
| |_____________________^ `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
| |
= help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` = help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
= note: required for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` to implement `IntoIterator` = note: required for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` to implement `IntoIterator`
help: consider removing 5 leading `&`-references
|
LL - for (i, _) in & & &
LL + for (i, _) in v
|
error: aborting due to previous error error: aborting due to previous error

View file

@ -0,0 +1,5 @@
// run-rustfix
fn main() {
let foo = [1,2,3].iter();
for _i in foo {} //~ ERROR E0277
}

View file

@ -0,0 +1,5 @@
// run-rustfix
fn main() {
let foo = &[1,2,3].iter();
for _i in &foo {} //~ ERROR E0277
}

View file

@ -0,0 +1,17 @@
error[E0277]: `&&std::slice::Iter<'_, {integer}>` is not an iterator
--> $DIR/suggest-remove-refs-4.rs:4:15
|
LL | for _i in &foo {}
| ^^^^ `&&std::slice::Iter<'_, {integer}>` is not an iterator
|
= help: the trait `Iterator` is not implemented for `&&std::slice::Iter<'_, {integer}>`
= note: required for `&&std::slice::Iter<'_, {integer}>` to implement `IntoIterator`
help: consider removing 2 leading `&`-references
|
LL ~ let foo = [1,2,3].iter();
LL ~ for _i in foo {}
|
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -0,0 +1,8 @@
// run-rustfix
fn main() {
let v = &mut Vec::<i32>::new();
for _ in v {} //~ ERROR E0277
let v = &mut [1u8];
for _ in v {} //~ ERROR E0277
}

View file

@ -0,0 +1,8 @@
// run-rustfix
fn main() {
let v = &mut &mut Vec::<i32>::new();
for _ in &mut &mut v {} //~ ERROR E0277
let v = &mut &mut [1u8];
for _ in &mut v {} //~ ERROR E0277
}

View file

@ -0,0 +1,37 @@
error[E0277]: `Vec<i32>` is not an iterator
--> $DIR/suggest-remove-refs-5.rs:4:14
|
LL | for _ in &mut &mut v {}
| ^^^^^^^^^^^ `Vec<i32>` is not an iterator; try calling `.into_iter()` or `.iter()`
|
= help: the trait `Iterator` is not implemented for `Vec<i32>`
= note: required for `&mut Vec<i32>` to implement `Iterator`
= note: 3 redundant requirements hidden
= note: required for `&mut &mut &mut &mut Vec<i32>` to implement `Iterator`
= note: required for `&mut &mut &mut &mut Vec<i32>` to implement `IntoIterator`
help: consider removing 3 leading `&`-references
|
LL ~ let v = &mut Vec::<i32>::new();
LL ~ for _ in v {}
|
error[E0277]: `[u8; 1]` is not an iterator
--> $DIR/suggest-remove-refs-5.rs:7:14
|
LL | for _ in &mut v {}
| ^^^^^^ `[u8; 1]` is not an iterator; try calling `.into_iter()` or `.iter()`
|
= help: the trait `Iterator` is not implemented for `[u8; 1]`
= note: required for `&mut [u8; 1]` to implement `Iterator`
= note: 2 redundant requirements hidden
= note: required for `&mut &mut &mut [u8; 1]` to implement `Iterator`
= note: required for `&mut &mut &mut [u8; 1]` to implement `IntoIterator`
help: consider removing 2 leading `&`-references
|
LL ~ let v = &mut [1u8];
LL ~ for _ in v {}
|
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -2,14 +2,17 @@ error[E0277]: `&mut ()` is not a tuple
--> $DIR/issue-57404.rs:6:41 --> $DIR/issue-57404.rs:6:41
| |
LL | handlers.unwrap().as_mut().call_mut(&mut ()); LL | handlers.unwrap().as_mut().call_mut(&mut ());
| -------- -^^^^^^ | -------- ^^^^^^^ the trait `Tuple` is not implemented for `&mut ()`
| | | | |
| | the trait `Tuple` is not implemented for `&mut ()`
| | help: consider removing the leading `&`-reference
| required by a bound introduced by this call | required by a bound introduced by this call
| |
note: required by a bound in `call_mut` note: required by a bound in `call_mut`
--> $SRC_DIR/core/src/ops/function.rs:LL:COL --> $SRC_DIR/core/src/ops/function.rs:LL:COL
help: consider removing the leading `&`-reference
|
LL - handlers.unwrap().as_mut().call_mut(&mut ());
LL + handlers.unwrap().as_mut().call_mut(());
|
error: aborting due to previous error error: aborting due to previous error

View file

@ -10,5 +10,5 @@ fn foo(&self) { }
fn main() { fn main() {
let thing = Bar { bar: Foo }; let thing = Bar { bar: Foo };
thing.bar.foo(); thing.bar.foo();
//~^ ERROR no method named `foo` found for fn item `fn() -> Foo {Foo}` in the current scope [E0599] //~^ ERROR no method named `foo` found for struct constructor `fn() -> Foo {Foo}` in the current scope [E0599]
} }

View file

@ -1,4 +1,4 @@
error[E0599]: no method named `foo` found for fn item `fn() -> Foo {Foo}` in the current scope error[E0599]: no method named `foo` found for struct constructor `fn() -> Foo {Foo}` in the current scope
--> $DIR/empty-tuple-method.rs:12:15 --> $DIR/empty-tuple-method.rs:12:15
| |
LL | thing.bar.foo(); LL | thing.bar.foo();

Some files were not shown because too many files have changed in this diff Show more