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),
("cmpxchg16b", Some(sym::cmpxchg16b_target_feature)),
("ermsb", Some(sym::ermsb_target_feature)),
("f16c", Some(sym::f16c_target_feature)),
("f16c", None),
("fma", None),
("fxsr", None),
("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::movbe_target_feature) => rust_features.movbe_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::bpf_target_feature) => rust_features.bpf_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 =
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
.immutable_borrow = also borrowed as immutable, by `{$name_immut}`, 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_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]`
.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),
/// Allows access to crate names passed via `--extern` through prelude.
(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.
(accepted, field_init_shorthand, "1.17.0", Some(37340), None),
/// 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, cmpxchg16b_target_feature, "1.32.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, mips_target_feature, "1.27.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`.
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::collect::HirPlaceholderCollector;
use crate::errors::{
@ -120,6 +123,13 @@ fn projected_ty_from_poly_trait_ref(
fn set_tainted_by_errors(&self, e: ErrorGuaranteed);
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)]
@ -279,7 +289,7 @@ pub fn ast_path_substs_for_ty(
ty::BoundConstness::NotConst,
);
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
@ -349,7 +359,7 @@ fn create_substs_for_ast_path<'a>(
assert!(self_ty.is_none());
}
let arg_count = Self::check_generic_arg_count(
let arg_count = check_generic_arg_count(
tcx,
span,
def_id,
@ -524,7 +534,7 @@ fn inferred_kind(
inferred_params: vec![],
infer_args,
};
let substs = Self::create_substs_for_generic_args(
let substs = create_substs_for_generic_args(
tcx,
def_id,
parent_substs,
@ -610,7 +620,7 @@ pub fn create_substs_for_associated_item(
);
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
@ -804,7 +814,7 @@ fn ast_path_to_mono_trait_ref(
constness,
);
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)
}
@ -2301,7 +2311,7 @@ pub fn prohibit_generics<'a>(
for segment in segments {
// Only emit the first error to avoid overloading the user with error messages.
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;
}
}

View file

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

View file

@ -1,4 +1,6 @@
use crate::autoderef::Autoderef;
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
use hir::def::DefKind;
use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
@ -22,7 +24,6 @@
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
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::outlives_bounds::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> {
<dyn AstConv<'_>>::ast_ty_to_ty(self, ast_ty)
self.astconv().ast_ty_to_ty(ast_ty)
}
pub fn hir_id(&self) -> hir::HirId {
@ -413,8 +413,7 @@ fn projected_ty_from_poly_trait_ref(
poly_trait_ref: ty::PolyTraitRef<'tcx>,
) -> Ty<'tcx> {
if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
let item_substs = <dyn AstConv<'tcx>>::create_substs_for_associated_item(
self,
let item_substs = self.astconv().create_substs_for_associated_item(
span,
item_def_id,
item_segment,
@ -1112,8 +1111,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
tcx.hir().get_parent(hir_id)
&& i.of_trait.is_some()
{
<dyn AstConv<'_>>::ty_of_fn(
&icx,
icx.astconv().ty_of_fn(
hir_id,
sig.header.unsafety,
sig.header.abi,
@ -1130,15 +1128,9 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _),
generics,
..
}) => <dyn AstConv<'_>>::ty_of_fn(
&icx,
hir_id,
header.unsafety,
header.abi,
decl,
Some(generics),
None,
),
}) => {
icx.astconv().ty_of_fn(hir_id, header.unsafety, header.abi, decl, Some(generics), None)
}
ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => {
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)
}
None => <dyn AstConv<'_>>::ty_of_fn(
icx,
None => icx.astconv().ty_of_fn(
hir_id,
sig.header.unsafety,
sig.header.abi,
@ -1354,8 +1345,7 @@ fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
match item.kind {
hir::ItemKind::Impl(ref impl_) => impl_.of_trait.as_ref().map(|ast_trait_ref| {
let selfty = tcx.type_of(def_id);
<dyn AstConv<'_>>::instantiate_mono_trait_ref(
&icx,
icx.astconv().instantiate_mono_trait_ref(
ast_trait_ref,
selfty,
check_impl_constness(tcx, impl_.constness, ast_trait_ref),
@ -1485,15 +1475,8 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
hir::Unsafety::Unsafe
};
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let fty = <dyn AstConv<'_>>::ty_of_fn(
&ItemCtxt::new(tcx, def_id),
hir_id,
unsafety,
abi,
decl,
None,
None,
);
let fty =
ItemCtxt::new(tcx, def_id).astconv().ty_of_fn(hir_id, unsafety, abi, decl, None, None);
// Feature gate SIMD types in FFI, since I am not sure that the
// 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 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
<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_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 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
<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);
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();
// Params are implicitly sized unless a `?Sized` bound is found
<dyn AstConv<'_>>::add_implicitly_sized(
&icx,
icx.astconv().add_implicitly_sized(
&mut bounds,
param_ty,
&[],
@ -211,22 +210,16 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
}
let mut bounds = Bounds::default();
<dyn AstConv<'_>>::add_bounds(
&icx,
ty,
bound_pred.bounds.iter(),
&mut bounds,
bound_vars,
);
icx.astconv().add_bounds(ty, bound_pred.bounds.iter(), &mut bounds, bound_vars);
predicates.extend(bounds.predicates());
}
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| {
let (r2, span) = match bound {
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!(),
};
@ -279,7 +272,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
debug!(?lifetimes);
for (arg, duplicate) in std::iter::zip(lifetimes, ast_generics.params) {
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(..)) {
// Only early-bound regions can point to the original generic parameter.
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`.
let self_param_ty = tcx.types.self_param;
let superbounds1 = if let Some(assoc_name) = assoc_name {
<dyn AstConv<'_>>::compute_bounds_that_match_assoc_type(
&icx,
self_param_ty,
bounds,
assoc_name,
)
icx.astconv().compute_bounds_that_match_assoc_type(self_param_ty, bounds, assoc_name)
} else {
<dyn AstConv<'_>>::compute_bounds(&icx, self_param_ty, bounds)
icx.astconv().compute_bounds(self_param_ty, bounds)
};
let superbounds1 = superbounds1.predicates();

View file

@ -300,3 +300,15 @@ pub(crate) struct LinkageType {
#[primary_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 astconv;
pub mod autoderef;
mod bounds;
mod check_unused;
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.
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());
<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>(
@ -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 item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
let mut bounds = Bounds::default();
let _ = <dyn AstConv<'_>>::instantiate_poly_trait_ref(
&item_cx,
let _ = &item_cx.astconv().instantiate_poly_trait_ref(
hir_trait,
DUMMY_SP,
ty::BoundConstness::NotConst,

View file

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

View file

@ -8,6 +8,7 @@
use rustc_hir as hir;
use rustc_hir::def::{self, CtorKind, Namespace, Res};
use rustc_hir::def_id::DefId;
use rustc_hir_analysis::autoderef::Autoderef;
use rustc_infer::{
infer,
traits::{self, Obligation},
@ -25,7 +26,6 @@
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
use rustc_target::spec::abi;
use rustc_trait_selection::autoderef::Autoderef;
use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::error_reporting::DefIdOrName;
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.
&& 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`.
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
@ -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 {
if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id)
&& 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()
{
return true;

View file

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

View file

@ -1664,15 +1664,15 @@ fn finish_resolving_struct_path(
match *qpath {
QPath::Resolved(ref maybe_qself, ref path) => {
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))
}
QPath::TypeRelative(ref qself, ref segment) => {
let ty = self.to_ty(qself);
let result = <dyn AstConv<'_>>::associated_path_to_ty(
self, hir_id, path_span, ty.raw, qself, segment, true,
);
let result = self
.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 = self.handle_raw_ty(path_span, ty);
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_session::Session;
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 std::cell::{Cell, RefCell};
@ -175,6 +175,14 @@ pub fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> {
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,
);
let item_substs = <dyn AstConv<'tcx>>::create_substs_for_associated_item(
self,
let item_substs = self.astconv().create_substs_for_associated_item(
span,
item_def_id,
item_segment,

View file

@ -5,7 +5,7 @@
use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX};
use rustc_errors::{Applicability, Diagnostic, MultiSpan};
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::{
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) {
return true;
} else if self.suggest_fn_call(err, expr, found, |output| self.can_coerce(output, expected))
&& let ty::FnDef(def_id, ..) = &found.kind()
&& let Some(sp) = self.tcx.hir().span_if_local(*def_id)
&& let ty::FnDef(def_id, ..) = *found.kind()
&& 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;
} else if self.check_for_cast(err, expr, found, expected, expected_ty_expr) {
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.
debug!("suggest_missing_return_type: return type {:?} node {:?}", ty, ty.kind);
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: expected type {:?}", ty);
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)
let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, bounded_ty);
let ty = self.astconv().ast_ty_to_ty(bounded_ty);
Some((ty, bounds))
}
_ => None,
@ -892,7 +902,7 @@ fn try_suggest_return_impl_trait(
let all_bounds_str = all_matching_bounds_strs.join(" + ");
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)
});
@ -946,7 +956,7 @@ pub(in super::super) fn suggest_missing_break_or_return_expr(
}
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 ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars));
let ty = match self.tcx.asyncness(fn_id.owner) {
@ -1339,7 +1349,7 @@ pub(crate) fn suggest_associated_const(
hir::Path { segments: [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(
Mode::Path,
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 {
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 {
tcx.fn_sig(def_id)
};
@ -220,7 +220,7 @@ fn typeck_with_fallback<'tcx>(
} else {
let expected_type = body_ty
.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,
})
.unwrap_or_else(|| match tcx.hir().get(id) {

View file

@ -4,6 +4,9 @@
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
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_infer::infer::{self, InferOk};
use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext};
@ -331,7 +334,7 @@ fn instantiate_method_substs(
// variables.
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.span,
pick.item.def_id,
@ -369,8 +372,7 @@ fn provided_kind(
) -> subst::GenericArg<'tcx> {
match (&param.kind, arg) {
(GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
<dyn AstConv<'_>>::ast_region_to_region(self.cfcx.fcx, lt, Some(param))
.into()
self.cfcx.fcx.astconv().ast_region_to_region(lt, Some(param)).into()
}
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
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,
pick.item.def_id,
parent_substs,

View file

@ -9,6 +9,7 @@
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir_analysis::autoderef::{self, Autoderef};
use rustc_infer::infer::canonical::OriginalQueryValues;
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@ -29,7 +30,6 @@
};
use rustc_span::symbol::sym;
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::method_autoderef::MethodAutoderefBadTy;
use rustc_trait_selection::traits::query::method_autoderef::{

View file

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

View file

@ -55,6 +55,7 @@
use crate::traits::error_reporting::report_object_safety_error;
use crate::traits::{
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
PredicateObligation,
};
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
@ -91,8 +92,12 @@
pub struct TypeErrCtxt<'a, 'tcx> {
pub infcx: &'a InferCtxt<'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 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<'_, '_> {

View file

@ -688,6 +688,10 @@ pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> {
typeck_results: None,
fallback_has_occurred: false,
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
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
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)]
pub struct Ascription<'tcx> {
pub annotation: CanonicalUserTypeAnnotation<'tcx>,

View file

@ -2,10 +2,10 @@
use crate::ty::diagnostics::suggest_constraining_type_param;
use crate::ty::print::{with_forced_trimmed_paths, FmtPrinter, Printer};
use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
use hir::def::DefKind;
use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
use rustc_errors::{pluralize, Diagnostic, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind};
use rustc_hir::def_id::DefId;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{BytePos, Span};
@ -319,7 +319,11 @@ pub fn sort_string(self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
.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::Dynamic(ref inner, ..) if let Some(principal) = inner.principal() => {
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",
}
.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::Dynamic(..) => "trait object".into(),
ty::Closure(..) => "closure".into(),

View file

@ -1,9 +1,13 @@
use crate::thir::pattern::deconstruct_pat::DeconstructedPat;
use crate::thir::pattern::MatchCheckCtxt;
use rustc_errors::Handler;
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_middle::thir::Pat;
use rustc_middle::ty::{self, Ty};
use rustc_span::{symbol::Ident, Span};
@ -624,3 +628,223 @@ pub enum MultipleMutBorrowOccurence {
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(min_specialization)]
#![feature(once_cell)]
#![feature(try_blocks)]
#![recursion_limit = "256"]
#[macro_use]

View file

@ -9,8 +9,7 @@
use rustc_arena::TypedArena;
use rustc_ast::Mutability;
use rustc_errors::{
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
MultiSpan,
struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
};
use rustc_hir as hir;
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_ty = pattern.ty();
let arms = vec![MatchArm { pat: pattern, hir_id: pat.hir_id, has_guard: false }];
let report = compute_match_usefulness(&cx, &arms, pat.hir_id, pattern_ty);
let arm = MatchArm { pat: pattern, hir_id: pat.hir_id, has_guard: false };
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
// only care about exhaustiveness here.
@ -390,145 +389,73 @@ fn check_irrefutable(&self, pat: &'tcx Pat<'tcx>, origin: &str, sp: Option<Span>
return;
}
let joined_patterns = joined_uncovered_patterns(&cx, &witnesses);
let mut bindings = vec![];
let mut err = struct_span_err!(
self.tcx.sess,
pat.span,
E0005,
"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() =>
let (inform, interpreted_as_const, res_defined_here,let_suggestion) =
if let hir::PatKind::Path(hir::QPath::Resolved(
None,
hir::Path {
segments: &[hir::PathSegment { args: None, res, ident, .. }],
..
},
)) = &pat.kind
{
const_not_var(&mut err, cx.tcx, pat, path);
false
}
_ => {
pat.walk(&mut |pat: &hir::Pat<'_>| {
match pat.kind {
hir::PatKind::Binding(_, _, ident, _) => {
bindings.push(ident);
(
None,
Some(InterpretedAsConst {
span: pat.span,
article: res.article(),
variable: ident.to_string().to_lowercase(),
res,
}),
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 start_span = span.shrink_to_lo();
let end_span = semi_span.shrink_to_lo();
err.multipart_suggestion(
&format!(
"you might want to use `if let` to ignore the variant{} that {} matched",
pluralize!(witnesses.len()),
match witnesses.len() {
1 => "isn't",
_ => "aren't",
},
),
vec![
match &bindings[..] {
[] => (start_span, "if ".to_string()),
[binding] => (start_span, format!("let {} = if ", binding)),
bindings => (
start_span,
format!(
"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,
);
}
let count = witnesses.len();
let let_suggestion = if bindings.is_empty() {SuggestLet::If{start_span, semi_span, count}} else{ SuggestLet::Else{end_span, count }};
(sp.map(|_|Inform), None, None, Some(let_suggestion))
} else{
(sp.map(|_|Inform), None, None, None)
};
let adt_defined_here = try {
let ty = pattern_ty.peel_refs();
let ty::Adt(def, _) = ty.kind() else { None? };
let adt_def_span = cx.tcx.hir().get_if_local(def.did())?.ident()?.span;
let mut variants = vec![];
for span in maybe_point_at_variant(&cx, *def, witnesses.iter().take(5)) {
variants.push(Variant { span });
}
err.note(
"for more information, visit \
https://doc.rust-lang.org/book/ch18-02-refutability.html",
);
}
AdtDefinedHere { adt_def_span, ty, variants }
};
adt_defined_here(&cx, &mut err, pattern_ty, &witnesses);
err.note(&format!("the matched value is of type `{}`", pattern_ty));
err.emit();
}
}
/// A path pattern was interpreted as a constant, not a new variable.
/// This caused an irrefutable match failure in e.g. `let`.
fn const_not_var(err: &mut Diagnostic, tcx: TyCtxt<'_>, pat: &Pat<'_>, path: &hir::Path<'_>) {
let descr = path.res.descr();
err.span_label(
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));
self.tcx.sess.emit_err(PatternNotCovered {
span: pat.span,
origin,
uncovered: Uncovered::new(pat.span, &cx, witnesses),
inform,
interpreted_as_const,
_p: (),
pattern_ty,
let_suggestion,
res_defined_here,
adt_defined_here,
});
}
}

View file

@ -1,11 +1,9 @@
use rustc_errors::DelayDm;
use rustc_hir as hir;
use rustc_index::vec::Idx;
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_middle::mir::{self, Field};
use rustc_middle::thir::{FieldPat, Pat, PatKind};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::lint;
use rustc_span::Span;
use rustc_trait_selection::traits::predicate_for_trait_def;
@ -15,6 +13,10 @@
use std::cell::Cell;
use super::PatCtxt;
use crate::errors::{
FloatPattern, IndirectStructuralMatch, InvalidPattern, NontrivialStructuralMatch,
PointerPattern, TypeNotStructural, UnionPattern, UnsizedPattern,
};
impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
/// Converts an evaluated constant to a pattern (if possible).
@ -105,47 +107,6 @@ fn tcx(&self) -> TyCtxt<'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 {
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,
// 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!(
"search_for_structural_match_violation cv.ty: {:?} returned: {:?}",
cv.ty(),
@ -194,17 +156,18 @@ fn to_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()) {
// span_fatal avoids ICE from resolution of non-existent method (rare case).
self.tcx().sess.span_fatal(self.span, &msg);
// fatal avoids ICE from resolution of non-existent method (rare case).
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() {
self.tcx().struct_span_lint_hir(
self.tcx().emit_spanned_lint(
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
self.id,
self.span,
msg,
|lint| lint,
IndirectStructuralMatch { non_sm_ty },
);
} else {
debug!(
@ -278,12 +241,11 @@ fn recur(
let kind = match cv.ty().kind() {
ty::Float(_) => {
if self.include_lint_checks {
tcx.struct_span_lint_hir(
tcx.emit_spanned_lint(
lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
id,
span,
"floating-point types cannot be used in patterns",
|lint| lint,
FloatPattern,
);
}
PatKind::Constant { value: cv }
@ -291,29 +253,22 @@ fn recur(
ty::Adt(adt_def, _) if adt_def.is_union() => {
// Matching on union fields is unsafe, we can't hide it in constants
self.saw_const_match_error.set(true);
let msg = "cannot use unions in constant patterns";
if self.include_lint_checks {
tcx.sess.span_err(span, msg);
} else {
tcx.sess.delay_span_bug(span, msg);
}
let err = UnionPattern { span };
tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
PatKind::Wild
}
ty::Adt(..)
if !self.type_may_have_partial_eq_impl(cv.ty())
// FIXME(#73448): Find a way to bring const qualification into parity with
// `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);
if self.include_lint_checks {
tcx.sess.span_err(self.span, &msg);
} else {
tcx.sess.delay_span_bug(self.span, &msg);
}
let err = TypeNotStructural { span, non_sm_ty };
tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
PatKind::Wild
}
// 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.set(true);
tcx.struct_span_lint_hir(
tcx.emit_spanned_lint(
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
id,
span,
DelayDm(|| {
format!(
"to use a constant of type `{}` in a pattern, \
`{}` must be annotated with `#[derive(PartialEq, Eq)]`",
cv.ty(),
cv.ty(),
)
}),
|lint| lint,
IndirectStructuralMatch { non_sm_ty: cv.ty() },
);
}
// 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,
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);
if self.include_lint_checks {
tcx.sess.span_err(span, &msg);
} else {
tcx.sess.delay_span_bug(span, &msg);
}
let err = TypeNotStructural { span, non_sm_ty: cv.ty() };
tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
PatKind::Wild
}
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.
ty::Dynamic(..) => {
self.saw_const_match_error.set(true);
let msg = format!("`{}` cannot be used in patterns", cv.ty());
if self.include_lint_checks {
tcx.sess.span_err(span, &msg);
} else {
tcx.sess.delay_span_bug(span, &msg);
}
let err = InvalidPattern { span, non_sm_ty: cv.ty() };
tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
PatKind::Wild
}
// `&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
// reference. This makes the rest of the matching logic simpler as it doesn't have
// 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.include_lint_checks
&& !self.saw_const_match_error.get()
&& !self.saw_const_match_lint.get()
{
self.saw_const_match_lint.set(true);
let msg = self.adt_derive_msg(adt_def);
self.tcx().struct_span_lint_hir(
self.saw_const_match_lint.set(true);
tcx.emit_spanned_lint(
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
self.id,
self.span,
msg,
|lint| lint,
span,
IndirectStructuralMatch { non_sm_ty: *pointee_ty },
);
}
PatKind::Constant { value: cv }
} else {
if !self.saw_const_match_error.get() {
self.saw_const_match_error.set(true);
let msg = self.adt_derive_msg(adt_def);
if self.include_lint_checks {
tcx.sess.span_err(span, &msg);
} else {
tcx.sess.delay_span_bug(span, &msg);
}
let err = TypeNotStructural { span, non_sm_ty: *pointee_ty };
tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
}
PatKind::Wild
}
@ -508,12 +436,10 @@ fn recur(
if !pointee_ty.is_sized(tcx, param_env) {
// `tcx.deref_mir_constant()` below will ICE with an unsized type
// (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 {
tcx.sess.span_err(span, &msg);
} else {
tcx.sess.delay_span_bug(span, &msg);
}
let err = UnsizedPattern { span, non_sm_ty: *pointee_ty };
tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
PatKind::Wild
} else {
let old = self.behind_reference.replace(true);
@ -545,27 +471,19 @@ fn recur(
&& !self.saw_const_match_lint.get()
{
self.saw_const_match_lint.set(true);
let msg = "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.";
tcx.struct_span_lint_hir(
tcx.emit_spanned_lint(
lint::builtin::POINTER_STRUCTURAL_MATCH,
id,
span,
msg,
|lint| lint,
PointerPattern
);
}
PatKind::Constant { value: cv }
}
_ => {
self.saw_const_match_error.set(true);
let msg = format!("`{}` cannot be used in patterns", cv.ty());
if self.include_lint_checks {
tcx.sess.span_err(span, &msg);
} else {
tcx.sess.delay_span_bug(span, &msg);
}
let err = InvalidPattern { span, non_sm_ty: cv.ty() };
tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
PatKind::Wild
}
};
@ -576,21 +494,17 @@ fn recur(
&& mir_structural_match_violation
// FIXME(#73448): Find a way to bring const qualification into parity with
// `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
// could get `Option<NonStructEq>`, even though `Option` is annotated with derive.
let msg = self.search_for_structural_match_violation(cv.ty()).unwrap().replace(
"in a pattern,",
"in a pattern, the constant's initializer must be trivial or",
);
tcx.struct_span_lint_hir(
&& let Some(non_sm_ty) = traits::search_for_structural_match_violation(span, tcx, cv.ty())
{
self.saw_const_match_lint.set(true);
tcx.emit_spanned_lint(
lint::builtin::NONTRIVIAL_STRUCTURAL_MATCH,
id,
span,
msg,
|lint| lint,
NontrivialStructuralMatch {non_sm_ty}
);
}

View file

@ -67,6 +67,7 @@
use super::compare_const_vals;
use super::usefulness::{MatchCheckCtxt, PatCtxt};
use crate::errors::{Overlap, OverlappingRangeEndpoints};
/// 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>> {
@ -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
/// around the (offset) space: i.e., `range.lo <= range.hi`.
#[derive(Clone, PartialEq, Eq)]
pub(super) struct IntRange {
pub(crate) struct IntRange {
range: RangeInclusive<u128>,
/// 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
@ -284,32 +285,21 @@ pub(super) fn lint_overlapping_range_endpoints<'a, 'p: 'a, 'tcx: 'a>(
return;
}
let overlaps: Vec<_> = pats
let overlap: Vec<_> = pats
.filter_map(|pat| Some((pat.ctor().as_int_range()?, pat.span())))
.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();
if !overlaps.is_empty() {
pcx.cx.tcx.struct_span_lint_hir(
if !overlap.is_empty() {
pcx.cx.tcx.emit_spanned_lint(
lint::builtin::OVERLAPPING_RANGE_ENDPOINTS,
hir_id,
pcx.span,
"multiple patterns overlap on their endpoints",
|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
},
OverlappingRangeEndpoints { overlap, range: pcx.span },
);
}
}

View file

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

View file

@ -291,9 +291,8 @@
use self::ArmType::*;
use self::Usefulness::*;
use super::check_match::{joined_uncovered_patterns, pattern_not_covered_label};
use super::deconstruct_pat::{Constructor, DeconstructedPat, Fields, SplitWildcard};
use crate::errors::{NonExhaustiveOmittedPattern, Uncovered};
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>.
/// The algorithm from the paper has been modified to correctly handle empty
/// types. The changes are:
@ -913,7 +887,19 @@ fn is_useful<'p, 'tcx>(
.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);

View file

@ -1,7 +1,6 @@
use rustc_errors::{fluent, ErrorGuaranteed, Handler, IntoDiagnostic};
use rustc_macros::Diagnostic;
use rustc_middle::ty::{self, PolyTraitRef, Ty};
use rustc_session::Limit;
use rustc_span::{Span, Symbol};
#[derive(Diagnostic)]
@ -21,18 +20,6 @@ pub struct UnableToConstructConstantValue<'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)]
#[diag(trait_selection_empty_on_clause_in_rustc_on_unimplemented, code = "E0232")]
pub struct EmptyOnClauseInOnUnimplemented {

View file

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

View file

@ -5,7 +5,6 @@
PredicateObligation,
};
use crate::autoderef::Autoderef;
use crate::infer::InferCtxt;
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() {
let mut autoderef = Autoderef::new(
self,
obligation.param_env,
obligation.cause.body_id,
span,
base_ty,
);
if let Some(steps) = autoderef.find_map(|(ty, steps)| {
// Re-add the `&`
let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl });
let autoderef = (self.autoderef_steps)(base_ty);
if let Some(steps) =
autoderef.into_iter().enumerate().find_map(|(steps, (ty, obligations))| {
// Re-add the `&`
let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl });
// Remapping bound vars here
let real_trait_pred_and_ty =
real_trait_pred.map_bound(|inner_trait_pred| (inner_trait_pred, ty));
let obligation = self.mk_trait_obligation_with_new_self_ty(
obligation.param_env,
real_trait_pred_and_ty,
);
Some(steps).filter(|_| self.predicate_may_hold(&obligation))
}) {
// Remapping bound vars here
let real_trait_pred_and_ty =
real_trait_pred.map_bound(|inner_trait_pred| (inner_trait_pred, ty));
let obligation = self.mk_trait_obligation_with_new_self_ty(
obligation.param_env,
real_trait_pred_and_ty,
);
if obligations
.iter()
.chain([&obligation])
.all(|obligation| self.predicate_may_hold(obligation))
{
Some(steps)
} else {
None
}
})
{
if steps > 0 {
// Don't care about `&mut` because `DerefMut` is used less
// often and user will not expect autoderef happens.
@ -1358,57 +1361,117 @@ fn suggest_remove_reference(
err: &mut Diagnostic,
trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> 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;
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
let refs_number =
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.
return false;
let new_obligation = self.mk_trait_obligation_with_new_self_ty(
obligation.param_env,
trait_pred_and_suggested_ty,
);
if self.predicate_may_hold(&new_obligation) {
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
let mut suggested_ty = trait_pred.self_ty().skip_binder();
// Maybe suggest removal of borrows from types in type parameters, like in
// `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 {
break;
};
suggested_ty = *inner_ty;
// Remapping bound vars here
let trait_pred_and_suggested_ty =
trait_pred.map_bound(|trait_pred| (trait_pred, suggested_ty));
hir_ty = mut_ty.ty;
let new_obligation = self.mk_trait_obligation_with_new_self_ty(
obligation.param_env,
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;
if maybe_suggest(suggested_ty, count, suggestions.clone()) {
return true;
}
}
}
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) {

View file

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

View file

@ -1514,37 +1514,50 @@ pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
(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
/// additional bit of overflow. This signed function is used only on the highest-ordered data,
/// for which the signed overflow result indicates whether the big integer overflowed or not.
/// Performs "ternary addition" of two integer operands and a carry-in
/// bit, and returns a tuple of the sum along with a boolean indicating
/// 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
///
/// Basic usage:
///
/// ```
/// #![feature(bigint_helper_methods)]
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, false), (7, false));")]
#[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!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(0, true), (", stringify!($SelfT), "::MIN, true));")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, true), (", stringify!($SelfT), "::MIN + 1, true));")]
#[doc = concat!("assert_eq!(",
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));")]
/// ```
/// // Only the most significant word is signed.
/// //
#[doc = concat!("// 10 MAX (a = 10 × 2^", stringify!($BITS), " + 2^", stringify!($BITS), " - 1)")]
#[doc = concat!("// + -5 9 (b = -5 × 2^", stringify!($BITS), " + 9)")]
/// // ---------
#[doc = concat!("// 6 8 (sum = 6 × 2^", stringify!($BITS), " + 8)")]
///
/// 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;
///
/// ```
/// #![feature(bigint_helper_methods)]
#[doc = concat!("assert_eq!(5_", stringify!($SelfT), ".carrying_add(2, false), 5_", stringify!($SelfT), ".overflowing_add(2));")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), ", stringify!($SelfT), "::MAX.overflowing_add(1));")]
#[doc = concat!("// ", stringify!($UnsignedT), "::carrying_add for the less significant words")]
/// let (sum0, carry1) = a0.carrying_add(b0, carry0);
/// assert_eq!(carry1, true);
///
#[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")]
#[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)
}
/// 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
/// additional bit of overflow. This signed function is used only on the highest-ordered data,
/// for which the signed overflow result indicates whether the big integer overflowed or not.
/// Performs "ternary subtraction" by subtracting both an integer
/// operandand a borrow-in bit from `self`, and returns a tuple of the
/// 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
///
/// Basic usage:
///
/// ```
/// #![feature(bigint_helper_methods)]
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".borrowing_sub(2, false), (3, false));")]
#[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!("assert_eq!(0", stringify!($SelfT), ".borrowing_sub(1, true), (-2, false));")]
#[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!("assert_eq!(", stringify!($SelfT), "::MAX.borrowing_sub(-1, true), (", stringify!($SelfT), "::MAX, false));")]
/// // Only the most significant word is signed.
/// //
#[doc = concat!("// 6 8 (a = 6 × 2^", stringify!($BITS), " + 8)")]
#[doc = concat!("// - -5 9 (b = -5 × 2^", stringify!($BITS), " + 9)")]
/// // ---------
#[doc = concat!("// 10 MAX (diff = 10 × 2^", stringify!($BITS), " + 2^", stringify!($BITS), " - 1)")]
///
#[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")]
#[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.
///
/// 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::task::Context;
/// use std::future::Future;
@ -1026,7 +1025,6 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
/// ### Basic usage
///
/// ```rust
/// #![feature(pin_macro)]
/// # use core::marker::PhantomPinned as Foo;
/// 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)
///
/// ```rust
/// #![feature(pin_macro)]
/// use std::{
/// future::Future,
/// pin::pin,
@ -1083,7 +1080,7 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
/// ### With `Generator`s
///
/// ```rust
/// #![feature(generators, generator_trait, pin_macro)]
/// #![feature(generators, generator_trait)]
/// use core::{
/// ops::{Generator, GeneratorState},
/// 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:
///
/// ```rust,compile_fail
/// #![feature(pin_macro)]
/// use core::pin::{pin, Pin};
/// # 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.
///
/// [`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"]
#[allow_internal_unstable(unsafe_pin_internals)]
pub macro pin($value:expr $(,)?) {

View file

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

View file

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

View file

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

View file

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

View file

@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/substs-ppaux.rs:16:17
|
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>;
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
@ -20,7 +20,7 @@ error[E0308]: mismatched types
--> $DIR/substs-ppaux.rs:25:17
|
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>;
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
@ -38,7 +38,7 @@ error[E0308]: mismatched types
--> $DIR/substs-ppaux.rs:33:17
|
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;
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
@ -56,7 +56,7 @@ error[E0308]: mismatched types
--> $DIR/substs-ppaux.rs:41:17
|
LL | fn foo<'z>() where &'z (): Sized {
| -------------------------------- fn() {foo::<ReStatic>} defined here
| -------------------------------- function `foo` defined here
...
LL | let x: () = foo::<'static>;
| -- ^^^^^^^^^^^^^^ 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>();
| ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`
|
= help: the trait `Signed` is implemented for `i32`
note: required for `&'static u32` to implement `Defaulted`
--> $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>() { }
| ^^^^^^^^^ 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

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
|
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
|
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
|
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 };
| ++ ~~~~~~~~~~~
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
|
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 };
| ++ ~~~~~~~~~~~
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
|
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 };
| ++ ~~~~~~~~~~~
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
|
LL | const X: i32 = { let 0 = 0; 0 };

View file

@ -9,8 +9,20 @@ mod foo {
const a: u8 = 2;
fn main() {
let a = 4; //~ ERROR refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8::MAX
let c = 4; //~ ERROR refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8::MAX
let d = 4; //~ ERROR refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8::MAX
let a = 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 `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).
}

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
|
LL | const a: u8 = 2;
@ -7,13 +7,14 @@ LL | const a: u8 = 2;
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`
|
= 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
--> $DIR/const-pattern-irrefutable.rs:13:9
error[E0005]: refutable pattern in local binding
--> $DIR/const-pattern-irrefutable.rs:17:9
|
LL | pub const b: u8 = 2;
| --------------- constant defined here
@ -21,13 +22,14 @@ LL | pub const b: u8 = 2;
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`
|
= 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
--> $DIR/const-pattern-irrefutable.rs:14:9
error[E0005]: refutable pattern in local binding
--> $DIR/const-pattern-irrefutable.rs:22:9
|
LL | pub const d: u8 = 2;
| --------------- constant defined here
@ -35,7 +37,8 @@ LL | pub const d: u8 = 2;
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`
|
= 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
|
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 {
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
}

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
|
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: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
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 | T(T, [!; 0]),
| ^ not covered
| - not covered
= 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
|
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
help: 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!() };
| ++++++++++++++++

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
|
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: 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>`
help: you might want to use `if let` to ignore 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
help: you might want to use `let else` to handle the variant that isn't matched
|
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
|
LL | for Some(x) in xs {}
| ^^^^^^^ 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>`
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
|
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: 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, !>`
help: you might want to use `if let` to ignore 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
help: you might want to use `let else` to handle the variant that isn't matched
|
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
|
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
|
LL | MyTrait::foo(&self)
| ------------ -^^^^
| | |
| | the trait `MyTrait` is not implemented for `&dyn MyTrait`
| | help: consider removing the leading `&`-reference
| ------------ ^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait`
| |
| 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
--> $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];
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);
}
}

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
|
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
|
LL | struct Foo(u32);
| ---------- fn(u32) -> Foo {Foo} defined here
| ---------- `Foo` defines a struct constructor here, which should be called
LL |
LL | fn test() -> Foo { Foo }
| --- ^^^ expected struct `Foo`, found fn item
| --- ^^^ expected struct `Foo`, found struct constructor
| |
| expected `Foo` because of return type
|
= note: expected struct `Foo`
found fn item `fn(u32) -> Foo {Foo}`
= note: expected struct `Foo`
found struct constructor `fn(u32) -> Foo {Foo}`
help: use parentheses to construct this tuple struct
|
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>();
| ^^^^^^^^^^^^^^^^^^ 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`
--> $DIR/kindck-copy.rs:5:18
|
LL | fn assert_copy<T: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
--> $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>();
| ^^^^^^^^^^^^^ 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`
--> $DIR/kindck-copy.rs:5:18
|
LL | fn assert_copy<T: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
--> $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
|
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: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `Either<(), !>` defined here
--> $DIR/exhaustive_patterns.rs:12:5
--> $DIR/exhaustive_patterns.rs:10:6
|
LL | enum Either<A, B> {
| ------
| ^^^^^^
LL | A(A),
LL | B(inner::Wrapper<B>),
| ^ not covered
| - not covered
= note: the matched value is of type `Either<(), !>`
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>() {}
| ^^^^^^^^^^ 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
--> $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>() {}
| ^^^^^^^^^^ 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

View file

@ -5,6 +5,6 @@
fn assert<T: UnwindSafe + ?Sized>() {}
fn main() {
assert::<&mut i32>();
//~^ ERROR the type `&mut i32` may not be safely transferred across an unwind boundary
assert::<&mut &mut &i32>();
//~^ 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
|
LL | assert::<&mut i32>();
| -^^^^^^^
| |
| `&mut i32` may not be safely transferred across an unwind boundary
| help: consider removing the leading `&`-reference
LL | assert::<&mut &mut &i32>();
| ^^^^^^^^^^^^^^ `&mut &mut &i32` may not be safely transferred across an unwind boundary
|
= help: the trait `UnwindSafe` is not implemented for `&mut i32`
= note: `UnwindSafe` is implemented for `&i32`, but not for `&mut i32`
= help: the trait `UnwindSafe` is not implemented for `&mut &mut &i32`
= note: `UnwindSafe` is implemented for `&&mut &i32`, but not for `&mut &mut &i32`
note: required by a bound in `assert`
--> $DIR/not-panic-safe.rs:5:14
|
LL | fn assert<T: UnwindSafe + ?Sized>() {}
| ^^^^^^^^^^ 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

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
|
LL | let (0 | (1 | 2)) = 0;

View file

@ -6,5 +6,6 @@ enum Thing {
fn main() {
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
|
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: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `Thing` defined here
--> $DIR/issue-31561.rs:3:5
--> $DIR/issue-31561.rs:1:6
|
LL | enum Thing {
| -----
| ^^^^^
LL | Foo(u8),
LL | Bar,
| ^^^ not covered
| --- not covered
LL | Baz
| ^^^ not covered
| --- not covered
= note: the matched value is of type `Thing`
help: you might want to use `if let` to ignore 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
help: 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!() };
| ++++++++++++++++

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

View file

@ -1,5 +1,5 @@
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 {
| ^^ patterns `E::B` and `E::C` not covered
@ -22,8 +22,8 @@ LL ~ E::A => {}
LL + E::B | E::C => todo!()
|
error[E0005]: refutable pattern in local binding: `E::B` and `E::C` not covered
--> $DIR/non-exhaustive-defined-here.rs:44:9
error[E0005]: refutable pattern in local binding
--> $DIR/non-exhaustive-defined-here.rs:41:9
|
LL | let E::A = e;
| ^^^^ 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: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `E` defined here
--> $DIR/non-exhaustive-defined-here.rs:14:5
--> $DIR/non-exhaustive-defined-here.rs:6:6
|
LL | enum E {
| -
| ^
...
LL | B,
| ^ not covered
| - not covered
...
LL | C
| ^ not covered
| - not covered
= note: the matched value is of type `E`
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
--> $DIR/non-exhaustive-defined-here.rs:52:11
--> $DIR/non-exhaustive-defined-here.rs:50:11
|
LL | match e {
| ^ patterns `&E::B` and `&E::C` not covered
@ -71,8 +71,8 @@ LL ~ E::A => {}
LL + &E::B | &E::C => todo!()
|
error[E0005]: refutable pattern in local binding: `&E::B` and `&E::C` not covered
--> $DIR/non-exhaustive-defined-here.rs:58:9
error[E0005]: refutable pattern in local binding
--> $DIR/non-exhaustive-defined-here.rs:57:9
|
LL | let E::A = e;
| ^^^^ 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: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `E` defined here
--> $DIR/non-exhaustive-defined-here.rs:14:5
--> $DIR/non-exhaustive-defined-here.rs:6:6
|
LL | enum E {
| -
| ^
...
LL | B,
| ^ not covered
| - not covered
...
LL | C
| ^ not covered
| - not covered
= note: the matched value is of type `&E`
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!()
|
error[E0005]: refutable pattern in local binding: `&&mut &E::B` and `&&mut &E::C` not covered
--> $DIR/non-exhaustive-defined-here.rs:72:9
error[E0005]: refutable pattern in local binding
--> $DIR/non-exhaustive-defined-here.rs:73:9
|
LL | let E::A = e;
| ^^^^ 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: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `E` defined here
--> $DIR/non-exhaustive-defined-here.rs:14:5
--> $DIR/non-exhaustive-defined-here.rs:6:6
|
LL | enum E {
| -
| ^
...
LL | B,
| ^ not covered
| - not covered
...
LL | C
| ^ not covered
| - not covered
= 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
|
@ -152,7 +152,7 @@ LL | match e {
| ^ pattern `Opt::None` not covered
|
note: `Opt` defined here
--> $DIR/non-exhaustive-defined-here.rs:84:5
--> $DIR/non-exhaustive-defined-here.rs:85:5
|
LL | enum Opt {
| ---
@ -166,8 +166,8 @@ LL ~ Opt::Some(ref _x) => {}
LL + Opt::None => todo!()
|
error[E0005]: refutable pattern in local binding: `Opt::None` not covered
--> $DIR/non-exhaustive-defined-here.rs:98:9
error[E0005]: refutable pattern in local binding
--> $DIR/non-exhaustive-defined-here.rs:99:9
|
LL | let Opt::Some(ref _x) = e;
| ^^^^^^^^^^^^^^^^^ 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: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `Opt` defined here
--> $DIR/non-exhaustive-defined-here.rs:84:5
--> $DIR/non-exhaustive-defined-here.rs:81:6
|
LL | enum Opt {
| ---
| ^^^
...
LL | None,
| ^^^^ not covered
| ---- not covered
= note: the matched value is of type `Opt`
help: you might want to use `if let` to ignore 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
help: you might want to use `let else` to handle the variant that isn't matched
|
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))) { }
//~^ ERROR refutable pattern in function argument: `(_, _)` not covered
//~^ ERROR refutable pattern in function argument
//~| `(_, _)` not covered
fn main() {
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
|
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))`
error[E0005]: refutable pattern in local binding: `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered
--> $DIR/refutable-pattern-errors.rs:5:9
error[E0005]: refutable pattern in local binding
--> $DIR/refutable-pattern-errors.rs:6:9
|
LL | let (1, (Some(1), 2..=3)) = (1, (None, 2));
| ^^^^^^^^^^^^^^^^^^^^^ patterns `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered

View file

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

View file

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

View file

@ -1,5 +1,5 @@
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);
| ^^^^^^^^^^^^^^^^^^^^^^

View file

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

View file

@ -1,5 +1,5 @@
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));
| ^^^^^^^^^^^^^^^^^^^ - 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)
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 = {
| -------------- 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
|
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: 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<'_>>`
help: you might want to use `if let` to ignore 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
help: you might want to use `let else` to handle the variant that isn't matched
|
LL | let Ok(x) = res else { todo!() };
| ++++++++++++++++

View file

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

View file

@ -1,7 +1,8 @@
fn main() {
let A = 3;
//~^ ERROR refutable pattern in local binding: `i32::MIN..=1_i32` and
//~| interpreted as a constant pattern, not a new variable
//~^ ERROR refutable pattern in local binding
//~| 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
//~| 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
|
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`
...
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
|
LL | fn foo(a: usize, b: usize) -> usize { a }
| ----------------------------------- fn(usize, usize) -> usize {foo} defined here
| ----------------------------------- function `foo` defined here
...
LL | let _: usize = foo;
| ----- ^^^ expected `usize`, found fn item
@ -20,15 +20,15 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:30:16
|
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;
| - ^ expected struct `S`, found fn item
| - ^ expected struct `S`, found struct constructor
| |
| expected due to this
|
= note: expected struct `S`
found fn item `fn(usize, usize) -> S {S}`
= note: expected struct `S`
found struct constructor `fn(usize, usize) -> S {S}`
help: use parentheses to construct this tuple struct
|
LL | let _: S = S(/* usize */, /* usize */);
@ -38,7 +38,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:31:20
|
LL | fn bar() -> usize { 42 }
| ----------------- fn() -> usize {bar} defined here
| ----------------- function `bar` defined here
...
LL | let _: usize = bar;
| ----- ^^^ expected `usize`, found fn item
@ -56,15 +56,15 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:32:16
|
LL | struct V();
| -------- fn() -> V {V} defined here
| -------- `V` defines a struct constructor here, which should be called
...
LL | let _: V = V;
| - ^ expected struct `V`, found fn item
| - ^ expected struct `V`, found struct constructor
| |
| expected due to this
|
= note: expected struct `V`
found fn item `fn() -> V {V}`
= note: expected struct `V`
found struct constructor `fn() -> V {V}`
help: use parentheses to construct this tuple struct
|
LL | let _: V = V();
@ -74,7 +74,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:33:20
|
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;
| ----- ^^^^^^ expected `usize`, found fn item
@ -92,7 +92,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:34:20
|
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;
| ----- ^^^^^^ expected `usize`, found fn item
@ -110,15 +110,15 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:35:16
|
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;
| - ^^^^ expected enum `E`, found fn item
| - ^^^^ expected enum `E`, found enum constructor
| |
| expected due to this
|
= note: expected enum `E`
found fn item `fn(usize) -> E {E::A}`
= note: expected enum `E`
found enum constructor `fn(usize) -> E {E::A}`
help: use parentheses to construct this tuple variant
|
LL | let _: E = E::A(/* usize */);
@ -134,7 +134,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:37:20
|
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;
| ----- ^^^^^^ expected `usize`, found fn item
@ -152,7 +152,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:38:20
|
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;
| ----- ^^^^^^ expected `usize`, found fn item
@ -170,7 +170,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:39:20
|
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;
| ----- ^^^^^^ expected `usize`, found fn item
@ -188,7 +188,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:40:20
|
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;
| ----- ^^^^^^^ expected `usize`, found fn item
@ -206,7 +206,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:41:20
|
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;
| ----- ^^^^^^ expected `usize`, found fn item
@ -224,7 +224,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:42:20
|
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;
| ----- ^^^^^^ 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
|
LL | for (i, _) in &v.iter().enumerate() {
| -^^^^^^^^^^^^^^^^^^^^
| |
| `&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
| help: consider removing the leading `&`-reference
| ^^^^^^^^^^^^^^^^^^^^^ `&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
|
= help: the trait `Iterator` is not implemented for `&Enumerate<std::slice::Iter<'_, {integer}>>`
= 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

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
|
LL | for (i, _) in & & & & &v.iter().enumerate() {
| ---------^^^^^^^^^^^^^^^^^^^^
| |
| `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
| help: consider removing 5 leading `&`-references
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
|
= help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
= 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

View file

@ -1,18 +1,20 @@
error[E0277]: `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
--> $DIR/suggest-remove-refs-3.rs:6:19
|
LL | for (i, _) in & & &
| ____________________^
| | ___________________|
| ||
LL | || & &v
| ||___________- help: consider removing 5 leading `&`-references
LL | | .iter()
LL | | .enumerate() {
| |_____________________^ `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
LL | for (i, _) in & & &
| ___________________^
LL | | & &v
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}>>`
= 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

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
|
LL | handlers.unwrap().as_mut().call_mut(&mut ());
| -------- -^^^^^^
| | |
| | the trait `Tuple` is not implemented for `&mut ()`
| | help: consider removing the leading `&`-reference
| -------- ^^^^^^^ the trait `Tuple` is not implemented for `&mut ()`
| |
| required by a bound introduced by this call
|
note: required by a bound in `call_mut`
--> $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

View file

@ -10,5 +10,5 @@ fn foo(&self) { }
fn main() {
let thing = Bar { 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
|
LL | thing.bar.foo();

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