mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-23 12:23:22 +00:00
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:
commit
606c390725
@ -187,7 +187,7 @@ const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
||||
("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,
|
||||
|
@ -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}`)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -161,6 +161,8 @@ 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).
|
||||
|
@ -254,7 +254,6 @@ declare_features! (
|
||||
(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
@ -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 @@ pub trait AstConv<'tcx> {
|
||||
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 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
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 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
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 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
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 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
);
|
||||
|
||||
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 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
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 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -178,6 +178,10 @@ impl<'a, 'tcx> Autoderef<'a, '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
|
||||
}
|
@ -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_session::parse::feature_err;
|
||||
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 _;
|
||||
|
@ -351,7 +351,7 @@ impl<'tcx> 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 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
|
||||
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
|
||||
|
@ -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())
|
||||
|
@ -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, ®ion_pred.lifetime, None);
|
||||
let r1 = icx.astconv().ast_region_to_region(®ion_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();
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -84,6 +84,7 @@ extern crate rustc_middle;
|
||||
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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -8,6 +8,7 @@ use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed,
|
||||
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::def_id::LocalDefId;
|
||||
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 _;
|
||||
|
@ -1807,7 +1807,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
||||
// 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 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
||||
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;
|
||||
|
@ -10,6 +10,9 @@ use rustc_hir::def::{CtorOf, DefKind, Res};
|
||||
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 @@ impl<'a, 'tcx> FnCtxt<'a, '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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// 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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// 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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// 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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
) -> ty::GenericArg<'tcx> {
|
||||
match (¶m.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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
let substs_raw = self_ctor_substs.unwrap_or_else(|| {
|
||||
<dyn AstConv<'_>>::create_substs_for_generic_args(
|
||||
create_substs_for_generic_args(
|
||||
tcx,
|
||||
def_id,
|
||||
&[],
|
||||
|
@ -1664,15 +1664,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
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));
|
||||
|
@ -20,7 +20,7 @@ use rustc_middle::ty::subst::GenericArgKind;
|
||||
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 @@ impl<'a, 'tcx> FnCtxt<'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 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
|
||||
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,
|
||||
|
@ -5,7 +5,7 @@ use crate::method::probe::{IsSuggestion, Mode, ProbeScope};
|
||||
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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
} 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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// 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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
..
|
||||
}) => {
|
||||
// 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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
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),
|
||||
|
@ -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) {
|
||||
|
@ -4,6 +4,9 @@ use crate::{callee, FnCtxt};
|
||||
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 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
// 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 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
) -> subst::GenericArg<'tcx> {
|
||||
match (¶m.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 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
let substs = <dyn AstConv<'_>>::create_substs_for_generic_args(
|
||||
let substs = create_substs_for_generic_args(
|
||||
self.tcx,
|
||||
pick.item.def_id,
|
||||
parent_substs,
|
||||
|
@ -9,6 +9,7 @@ use rustc_data_structures::fx::FxHashSet;
|
||||
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::lev_distance::{
|
||||
};
|
||||
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::{
|
||||
|
@ -3,6 +3,7 @@ use crate::{has_expected_num_generic_args, FnCtxt, PlaceOp};
|
||||
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::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutabili
|
||||
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> {
|
||||
|
@ -55,6 +55,7 @@ use crate::infer::ExpectedFound;
|
||||
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 mod nice_region_error;
|
||||
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<'_, '_> {
|
||||
|
@ -688,6 +688,10 @@ impl<'tcx> InferCtxt<'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![])]
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 @@ impl<'tcx> Pat<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
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>,
|
||||
|
@ -2,10 +2,10 @@ use crate::traits::{ObligationCause, ObligationCauseCode};
|
||||
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 @@ impl<'tcx> Ty<'tcx> {
|
||||
.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 @@ impl<'tcx> Ty<'tcx> {
|
||||
_ => "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(),
|
||||
|
@ -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,
|
||||
},
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
#![feature(let_chains)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(once_cell)]
|
||||
#![feature(try_blocks)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
#[macro_use]
|
||||
|
@ -9,8 +9,7 @@ use crate::errors::*;
|
||||
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 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
|
||||
|
||||
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 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
|
||||
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,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 rustc_trait_selection::traits::{self, ObligationCause, PredicateObligation};
|
||||
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 @@ impl<'tcx> ConstToPat<'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 @@ impl<'tcx> ConstToPat<'tcx> {
|
||||
// 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 @@ impl<'tcx> ConstToPat<'tcx> {
|
||||
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 @@ impl<'tcx> ConstToPat<'tcx> {
|
||||
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 @@ impl<'tcx> ConstToPat<'tcx> {
|
||||
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 @@ impl<'tcx> ConstToPat<'tcx> {
|
||||
&& !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 @@ impl<'tcx> ConstToPat<'tcx> {
|
||||
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 @@ impl<'tcx> ConstToPat<'tcx> {
|
||||
// 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 @@ impl<'tcx> ConstToPat<'tcx> {
|
||||
// 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 @@ impl<'tcx> ConstToPat<'tcx> {
|
||||
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 @@ impl<'tcx> ConstToPat<'tcx> {
|
||||
&& !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 @@ impl<'tcx> ConstToPat<'tcx> {
|
||||
&& 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}
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,7 @@ use self::SliceKind::*;
|
||||
|
||||
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_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> 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 @@ impl IntRange {
|
||||
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 },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 @@ impl<'p, 'tcx> Witness<'p, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// 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);
|
||||
|
@ -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 {
|
||||
|
@ -35,7 +35,6 @@ extern crate rustc_middle;
|
||||
#[macro_use]
|
||||
extern crate smallvec;
|
||||
|
||||
pub mod autoderef;
|
||||
pub mod errors;
|
||||
pub mod infer;
|
||||
pub mod solve;
|
||||
|
@ -5,7 +5,6 @@ use super::{
|
||||
PredicateObligation,
|
||||
};
|
||||
|
||||
use crate::autoderef::Autoderef;
|
||||
use crate::infer::InferCtxt;
|
||||
use crate::traits::{NormalizeExt, ObligationCtxt};
|
||||
|
||||
@ -750,26 +749,30 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
}
|
||||
|
||||
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 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
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) {
|
||||
|
@ -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)]
|
||||
|
@ -1514,37 +1514,50 @@ macro_rules! int_impl {
|
||||
(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 @@ macro_rules! int_impl {
|
||||
(a as Self, b)
|
||||
}
|
||||
|
||||
/// Calculates `self - rhs - borrow` without the ability to overflow.
|
||||
/// Calculates `self` − `rhs` − `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")]
|
||||
|
@ -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 $(,)?) {
|
||||
|
@ -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)]
|
||||
|
@ -1,5 +1,3 @@
|
||||
#![feature(pin_macro)]
|
||||
|
||||
use core::future::Future;
|
||||
use core::pin::Pin;
|
||||
use core::task::{Context, Poll};
|
||||
|
@ -1,5 +1,3 @@
|
||||
#![feature(pin_macro)]
|
||||
|
||||
use std::future::*;
|
||||
use std::marker::PhantomPinned;
|
||||
use std::pin::*;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 },
|
||||
|
@ -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 }] = [];
|
||||
|
@ -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 };
|
||||
|
@ -9,8 +9,20 @@ use foo::d;
|
||||
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).
|
||||
}
|
||||
|
@ -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`
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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!() };
|
||||
| ++++++++++++++++
|
||||
|
@ -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!() };
|
||||
| ++++++++++++++++
|
||||
|
@ -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
|
||||
|
@ -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!() };
|
||||
| ++++++++++++++++
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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 */) }
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
|
||||
|
@ -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
|
||||
|
||||
|
@ -5,6 +5,6 @@ use std::panic::UnwindSafe;
|
||||
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
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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!() };
|
||||
| ++++++++++++++++
|
||||
|
@ -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
|
||||
|
@ -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!() };
|
||||
| ++++++++++++++++
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -1,5 +1,4 @@
|
||||
// edition:2018
|
||||
#![feature(pin_macro)]
|
||||
|
||||
use core::{
|
||||
marker::PhantomPinned,
|
||||
|
@ -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);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -1,5 +1,4 @@
|
||||
// edition:2018
|
||||
#![feature(pin_macro)]
|
||||
|
||||
use core::{
|
||||
convert::identity,
|
||||
|
@ -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
|
||||
|
@ -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!() };
|
||||
| ++++++++++++++++
|
||||
|
@ -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 */);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
5
tests/ui/suggestions/suggest-remove-refs-4.fixed
Normal file
5
tests/ui/suggestions/suggest-remove-refs-4.fixed
Normal file
@ -0,0 +1,5 @@
|
||||
// run-rustfix
|
||||
fn main() {
|
||||
let foo = [1,2,3].iter();
|
||||
for _i in foo {} //~ ERROR E0277
|
||||
}
|
5
tests/ui/suggestions/suggest-remove-refs-4.rs
Normal file
5
tests/ui/suggestions/suggest-remove-refs-4.rs
Normal file
@ -0,0 +1,5 @@
|
||||
// run-rustfix
|
||||
fn main() {
|
||||
let foo = &[1,2,3].iter();
|
||||
for _i in &foo {} //~ ERROR E0277
|
||||
}
|
17
tests/ui/suggestions/suggest-remove-refs-4.stderr
Normal file
17
tests/ui/suggestions/suggest-remove-refs-4.stderr
Normal 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`.
|
8
tests/ui/suggestions/suggest-remove-refs-5.fixed
Normal file
8
tests/ui/suggestions/suggest-remove-refs-5.fixed
Normal 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
|
||||
}
|
8
tests/ui/suggestions/suggest-remove-refs-5.rs
Normal file
8
tests/ui/suggestions/suggest-remove-refs-5.rs
Normal 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
|
||||
}
|
37
tests/ui/suggestions/suggest-remove-refs-5.stderr
Normal file
37
tests/ui/suggestions/suggest-remove-refs-5.stderr
Normal 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`.
|
@ -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
|
||||
|
||||
|
@ -10,5 +10,5 @@ impl Foo {
|
||||
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]
|
||||
}
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user