Auto merge of #120722 - matthiaskrgr:rollup-9o32280, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #119939 (Improve 'generic param from outer item' error for `Self` and inside `static`/`const` items) - #120331 (pattern_analysis: use a plain `Vec` in `DeconstructedPat`) - #120396 (Account for unbounded type param receiver in suggestions) - #120423 (update indirect structural match lints to match RFC and to show up for dependencies) - #120435 (Suggest name value cfg when only value is used for check-cfg) - #120502 (Remove `ffi_returns_twice` feature) - #120507 (Account for non-overlapping unmet trait bounds in suggestion) - #120513 (Normalize type outlives obligations in NLL for new solver) - #120707 (Don't expect early-bound region to be local when reporting errors in RPITIT well-formedness) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
586893c7b0
108 changed files with 1368 additions and 744 deletions
|
@ -5,10 +5,13 @@ use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelega
|
|||
use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound};
|
||||
use rustc_infer::infer::{self, InferCtxt, SubregionOrigin};
|
||||
use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory};
|
||||
use rustc_middle::ty::GenericArgKind;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_middle::ty::{TypeFoldable, TypeVisitableExt};
|
||||
use rustc_middle::traits::query::NoSolution;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_trait_selection::solve::deeply_normalize;
|
||||
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
|
||||
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
|
||||
|
||||
use crate::{
|
||||
constraints::OutlivesConstraint,
|
||||
|
@ -33,6 +36,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
|
|||
/// our special inference variable there, we would mess that up.
|
||||
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
|
||||
implicit_region_bound: ty::Region<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
|
||||
locations: Locations,
|
||||
span: Span,
|
||||
|
@ -47,6 +51,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
universal_regions: &'a UniversalRegions<'tcx>,
|
||||
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
|
||||
implicit_region_bound: ty::Region<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
|
||||
locations: Locations,
|
||||
span: Span,
|
||||
|
@ -59,6 +64,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
universal_regions,
|
||||
region_bound_pairs,
|
||||
implicit_region_bound,
|
||||
param_env,
|
||||
known_type_outlives_obligations,
|
||||
locations,
|
||||
span,
|
||||
|
@ -137,36 +143,68 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
// Extract out various useful fields we'll need below.
|
||||
let ConstraintConversion {
|
||||
tcx,
|
||||
infcx,
|
||||
region_bound_pairs,
|
||||
implicit_region_bound,
|
||||
known_type_outlives_obligations,
|
||||
..
|
||||
} = *self;
|
||||
|
||||
let ty::OutlivesPredicate(k1, r2) = predicate;
|
||||
match k1.unpack() {
|
||||
GenericArgKind::Lifetime(r1) => {
|
||||
let r1_vid = self.to_region_vid(r1);
|
||||
let r2_vid = self.to_region_vid(r2);
|
||||
self.add_outlives(r1_vid, r2_vid, constraint_category);
|
||||
let mut outlives_predicates = vec![(predicate, constraint_category)];
|
||||
for iteration in 0.. {
|
||||
if outlives_predicates.is_empty() {
|
||||
break;
|
||||
}
|
||||
|
||||
GenericArgKind::Type(t1) => {
|
||||
// we don't actually use this for anything, but
|
||||
// the `TypeOutlives` code needs an origin.
|
||||
let origin = infer::RelateParamBound(DUMMY_SP, t1, None);
|
||||
|
||||
TypeOutlives::new(
|
||||
&mut *self,
|
||||
tcx,
|
||||
region_bound_pairs,
|
||||
Some(implicit_region_bound),
|
||||
known_type_outlives_obligations,
|
||||
)
|
||||
.type_must_outlive(origin, t1, r2, constraint_category);
|
||||
if !self.tcx.recursion_limit().value_within_limit(iteration) {
|
||||
bug!(
|
||||
"FIXME(-Znext-solver): Overflowed when processing region obligations: {outlives_predicates:#?}"
|
||||
);
|
||||
}
|
||||
|
||||
GenericArgKind::Const(_) => unreachable!(),
|
||||
let mut next_outlives_predicates = vec![];
|
||||
for (ty::OutlivesPredicate(k1, r2), constraint_category) in outlives_predicates {
|
||||
match k1.unpack() {
|
||||
GenericArgKind::Lifetime(r1) => {
|
||||
let r1_vid = self.to_region_vid(r1);
|
||||
let r2_vid = self.to_region_vid(r2);
|
||||
self.add_outlives(r1_vid, r2_vid, constraint_category);
|
||||
}
|
||||
|
||||
GenericArgKind::Type(mut t1) => {
|
||||
// Normalize the type we receive from a `TypeOutlives` obligation
|
||||
// in the new trait solver.
|
||||
if infcx.next_trait_solver() {
|
||||
t1 = self.normalize_and_add_type_outlives_constraints(
|
||||
t1,
|
||||
&mut next_outlives_predicates,
|
||||
);
|
||||
}
|
||||
|
||||
// we don't actually use this for anything, but
|
||||
// the `TypeOutlives` code needs an origin.
|
||||
let origin = infer::RelateParamBound(DUMMY_SP, t1, None);
|
||||
|
||||
TypeOutlives::new(
|
||||
&mut *self,
|
||||
tcx,
|
||||
region_bound_pairs,
|
||||
Some(implicit_region_bound),
|
||||
known_type_outlives_obligations,
|
||||
)
|
||||
.type_must_outlive(
|
||||
origin,
|
||||
t1,
|
||||
r2,
|
||||
constraint_category,
|
||||
);
|
||||
}
|
||||
|
||||
GenericArgKind::Const(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
outlives_predicates = next_outlives_predicates;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,6 +270,42 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
debug!("add_type_test(type_test={:?})", type_test);
|
||||
self.constraints.type_tests.push(type_test);
|
||||
}
|
||||
|
||||
fn normalize_and_add_type_outlives_constraints(
|
||||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
next_outlives_predicates: &mut Vec<(
|
||||
ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>,
|
||||
ConstraintCategory<'tcx>,
|
||||
)>,
|
||||
) -> Ty<'tcx> {
|
||||
let result = CustomTypeOp::new(
|
||||
|ocx| {
|
||||
deeply_normalize(
|
||||
ocx.infcx.at(&ObligationCause::dummy_with_span(self.span), self.param_env),
|
||||
ty,
|
||||
)
|
||||
.map_err(|_| NoSolution)
|
||||
},
|
||||
"normalize type outlives obligation",
|
||||
)
|
||||
.fully_perform(self.infcx, self.span);
|
||||
|
||||
match result {
|
||||
Ok(TypeOpOutput { output: ty, constraints, .. }) => {
|
||||
if let Some(constraints) = constraints {
|
||||
assert!(
|
||||
constraints.member_constraints.is_empty(),
|
||||
"no member constraints expected from normalizing: {:#?}",
|
||||
constraints.member_constraints
|
||||
);
|
||||
next_outlives_predicates.extend(constraints.outlives.iter().copied());
|
||||
}
|
||||
ty
|
||||
}
|
||||
Err(_) => ty,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<'b, 'tcx> {
|
||||
|
|
|
@ -8,8 +8,11 @@ use rustc_infer::infer::region_constraints::GenericKind;
|
|||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
use rustc_middle::traits::query::OutlivesBound;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::{self, RegionVid, Ty, TypeVisitableExt};
|
||||
use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
|
||||
use rustc_span::{ErrorGuaranteed, DUMMY_SP};
|
||||
use rustc_trait_selection::solve::deeply_normalize;
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
|
||||
use std::rc::Rc;
|
||||
use type_op::TypeOpOutput;
|
||||
|
@ -52,7 +55,6 @@ pub(crate) struct CreateResult<'tcx> {
|
|||
pub(crate) fn create<'tcx>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
|
||||
implicit_region_bound: ty::Region<'tcx>,
|
||||
universal_regions: &Rc<UniversalRegions<'tcx>>,
|
||||
constraints: &mut MirTypeckRegionConstraints<'tcx>,
|
||||
|
@ -60,7 +62,6 @@ pub(crate) fn create<'tcx>(
|
|||
UniversalRegionRelationsBuilder {
|
||||
infcx,
|
||||
param_env,
|
||||
known_type_outlives_obligations,
|
||||
implicit_region_bound,
|
||||
constraints,
|
||||
universal_regions: universal_regions.clone(),
|
||||
|
@ -178,7 +179,6 @@ impl UniversalRegionRelations<'_> {
|
|||
struct UniversalRegionRelationsBuilder<'this, 'tcx> {
|
||||
infcx: &'this InferCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
|
||||
universal_regions: Rc<UniversalRegions<'tcx>>,
|
||||
implicit_region_bound: ty::Region<'tcx>,
|
||||
constraints: &'this mut MirTypeckRegionConstraints<'tcx>,
|
||||
|
@ -222,6 +222,32 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
|||
self.relate_universal_regions(fr, fr_fn_body);
|
||||
}
|
||||
|
||||
// Normalize the assumptions we use to borrowck the program.
|
||||
let mut constraints = vec![];
|
||||
let mut known_type_outlives_obligations = vec![];
|
||||
for bound in param_env.caller_bounds() {
|
||||
let Some(mut outlives) = bound.as_type_outlives_clause() else { continue };
|
||||
|
||||
// In the new solver, normalize the type-outlives obligation assumptions.
|
||||
if self.infcx.next_trait_solver() {
|
||||
match deeply_normalize(
|
||||
self.infcx.at(&ObligationCause::misc(span, defining_ty_def_id), self.param_env),
|
||||
outlives,
|
||||
) {
|
||||
Ok(normalized_outlives) => {
|
||||
outlives = normalized_outlives;
|
||||
}
|
||||
Err(e) => {
|
||||
self.infcx.err_ctxt().report_fulfillment_errors(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
known_type_outlives_obligations.push(outlives);
|
||||
}
|
||||
let known_type_outlives_obligations =
|
||||
self.infcx.tcx.arena.alloc_slice(&known_type_outlives_obligations);
|
||||
|
||||
let unnormalized_input_output_tys = self
|
||||
.universal_regions
|
||||
.unnormalized_input_tys
|
||||
|
@ -239,7 +265,6 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
|||
// the `relations` is built.
|
||||
let mut normalized_inputs_and_output =
|
||||
Vec::with_capacity(self.universal_regions.unnormalized_input_tys.len() + 1);
|
||||
let mut constraints = vec![];
|
||||
for ty in unnormalized_input_output_tys {
|
||||
debug!("build: input_or_output={:?}", ty);
|
||||
// We add implied bounds from both the unnormalized and normalized ty.
|
||||
|
@ -304,7 +329,19 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
|||
}
|
||||
|
||||
for c in constraints {
|
||||
self.push_region_constraints(c, span);
|
||||
constraint_conversion::ConstraintConversion::new(
|
||||
self.infcx,
|
||||
&self.universal_regions,
|
||||
&self.region_bound_pairs,
|
||||
self.implicit_region_bound,
|
||||
param_env,
|
||||
known_type_outlives_obligations,
|
||||
Locations::All(span),
|
||||
span,
|
||||
ConstraintCategory::Internal,
|
||||
self.constraints,
|
||||
)
|
||||
.convert_all(c);
|
||||
}
|
||||
|
||||
CreateResult {
|
||||
|
@ -313,30 +350,12 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
|||
outlives: self.outlives.freeze(),
|
||||
inverse_outlives: self.inverse_outlives.freeze(),
|
||||
}),
|
||||
known_type_outlives_obligations: self.known_type_outlives_obligations,
|
||||
known_type_outlives_obligations,
|
||||
region_bound_pairs: self.region_bound_pairs,
|
||||
normalized_inputs_and_output,
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(self, data), level = "debug")]
|
||||
fn push_region_constraints(&mut self, data: &QueryRegionConstraints<'tcx>, span: Span) {
|
||||
debug!("constraints generated: {:#?}", data);
|
||||
|
||||
constraint_conversion::ConstraintConversion::new(
|
||||
self.infcx,
|
||||
&self.universal_regions,
|
||||
&self.region_bound_pairs,
|
||||
self.implicit_region_bound,
|
||||
self.known_type_outlives_obligations,
|
||||
Locations::All(span),
|
||||
span,
|
||||
ConstraintCategory::Internal,
|
||||
self.constraints,
|
||||
)
|
||||
.convert_all(data);
|
||||
}
|
||||
|
||||
/// Update the type of a single local, which should represent
|
||||
/// either the return type of the MIR or one of its arguments. At
|
||||
/// the same time, compute and add any implied bounds that come
|
||||
|
|
|
@ -156,10 +156,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
|||
} = free_region_relations::create(
|
||||
infcx,
|
||||
param_env,
|
||||
// FIXME(-Znext-solver): These are unnormalized. Normalize them.
|
||||
infcx.tcx.arena.alloc_from_iter(
|
||||
param_env.caller_bounds().iter().filter_map(|clause| clause.as_type_outlives_clause()),
|
||||
),
|
||||
implicit_region_bound,
|
||||
universal_regions,
|
||||
&mut constraints,
|
||||
|
@ -1144,6 +1140,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
self.borrowck_context.universal_regions,
|
||||
self.region_bound_pairs,
|
||||
self.implicit_region_bound,
|
||||
self.param_env,
|
||||
self.known_type_outlives_obligations,
|
||||
locations,
|
||||
locations.span(self.body),
|
||||
|
@ -2759,6 +2756,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
self.borrowck_context.universal_regions,
|
||||
self.region_bound_pairs,
|
||||
self.implicit_region_bound,
|
||||
self.param_env,
|
||||
self.known_type_outlives_obligations,
|
||||
locations,
|
||||
DUMMY_SP, // irrelevant; will be overridden.
|
||||
|
|
|
@ -62,9 +62,6 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
|
|||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) {
|
||||
func.add_attribute(FnAttribute::Cold);
|
||||
}
|
||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_RETURNS_TWICE) {
|
||||
func.add_attribute(FnAttribute::ReturnsTwice);
|
||||
}
|
||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_PURE) {
|
||||
func.add_attribute(FnAttribute::Pure);
|
||||
}
|
||||
|
|
|
@ -356,9 +356,6 @@ pub fn from_fn_attrs<'ll, 'tcx>(
|
|||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) {
|
||||
to_add.push(AttributeKind::Cold.create_attr(cx.llcx));
|
||||
}
|
||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_RETURNS_TWICE) {
|
||||
to_add.push(AttributeKind::ReturnsTwice.create_attr(cx.llcx));
|
||||
}
|
||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_PURE) {
|
||||
to_add.push(MemoryEffects::ReadOnly.create_attr(cx.llcx));
|
||||
}
|
||||
|
|
|
@ -184,7 +184,6 @@ pub enum AttributeKind {
|
|||
SanitizeMemory = 22,
|
||||
NonLazyBind = 23,
|
||||
OptimizeNone = 24,
|
||||
ReturnsTwice = 25,
|
||||
ReadNone = 26,
|
||||
SanitizeHWAddress = 28,
|
||||
WillReturn = 29,
|
||||
|
|
|
@ -103,9 +103,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
match name {
|
||||
sym::cold => codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD,
|
||||
sym::rustc_allocator => codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR,
|
||||
sym::ffi_returns_twice => {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE
|
||||
}
|
||||
sym::ffi_pure => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE,
|
||||
sym::ffi_const => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST,
|
||||
sym::rustc_nounwind => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND,
|
||||
|
|
|
@ -20,7 +20,7 @@ use std::mem;
|
|||
use std::ops::{ControlFlow, Deref};
|
||||
|
||||
use super::ops::{self, NonConstOp, Status};
|
||||
use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop, NeedsNonConstDrop};
|
||||
use super::qualifs::{self, HasMutInterior, NeedsDrop, NeedsNonConstDrop};
|
||||
use super::resolver::FlowSensitiveAnalysis;
|
||||
use super::{ConstCx, Qualif};
|
||||
use crate::const_eval::is_unstable_const_fn;
|
||||
|
@ -149,37 +149,10 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
|
|||
|
||||
let return_loc = ccx.body.terminator_loc(return_block);
|
||||
|
||||
let custom_eq = match ccx.const_kind() {
|
||||
// We don't care whether a `const fn` returns a value that is not structurally
|
||||
// matchable. Functions calls are opaque and always use type-based qualification, so
|
||||
// this value should never be used.
|
||||
hir::ConstContext::ConstFn => true,
|
||||
|
||||
// If we know that all values of the return type are structurally matchable, there's no
|
||||
// need to run dataflow.
|
||||
// Opaque types do not participate in const generics or pattern matching, so we can safely count them out.
|
||||
_ if ccx.body.return_ty().has_opaque_types()
|
||||
|| !CustomEq::in_any_value_of_ty(ccx, ccx.body.return_ty()) =>
|
||||
{
|
||||
false
|
||||
}
|
||||
|
||||
hir::ConstContext::Const { .. } | hir::ConstContext::Static(_) => {
|
||||
let mut cursor = FlowSensitiveAnalysis::new(CustomEq, ccx)
|
||||
.into_engine(ccx.tcx, ccx.body)
|
||||
.iterate_to_fixpoint()
|
||||
.into_results_cursor(ccx.body);
|
||||
|
||||
cursor.seek_after_primary_effect(return_loc);
|
||||
cursor.get().contains(RETURN_PLACE)
|
||||
}
|
||||
};
|
||||
|
||||
ConstQualifs {
|
||||
needs_drop: self.needs_drop(ccx, RETURN_PLACE, return_loc),
|
||||
needs_non_const_drop: self.needs_non_const_drop(ccx, RETURN_PLACE, return_loc),
|
||||
has_mut_interior: self.has_mut_interior(ccx, RETURN_PLACE, return_loc),
|
||||
custom_eq,
|
||||
tainted_by_errors,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ use rustc_middle::mir::*;
|
|||
use rustc_middle::traits::BuiltinImplSource;
|
||||
use rustc_middle::ty::{self, AdtDef, GenericArgsRef, Ty};
|
||||
use rustc_trait_selection::traits::{
|
||||
self, ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext,
|
||||
ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext,
|
||||
};
|
||||
|
||||
use super::ConstCx;
|
||||
|
@ -24,7 +24,6 @@ pub fn in_any_value_of_ty<'tcx>(
|
|||
has_mut_interior: HasMutInterior::in_any_value_of_ty(cx, ty),
|
||||
needs_drop: NeedsDrop::in_any_value_of_ty(cx, ty),
|
||||
needs_non_const_drop: NeedsNonConstDrop::in_any_value_of_ty(cx, ty),
|
||||
custom_eq: CustomEq::in_any_value_of_ty(cx, ty),
|
||||
tainted_by_errors,
|
||||
}
|
||||
}
|
||||
|
@ -213,35 +212,6 @@ impl Qualif for NeedsNonConstDrop {
|
|||
}
|
||||
}
|
||||
|
||||
/// A constant that cannot be used as part of a pattern in a `match` expression.
|
||||
pub struct CustomEq;
|
||||
|
||||
impl Qualif for CustomEq {
|
||||
const ANALYSIS_NAME: &'static str = "flow_custom_eq";
|
||||
|
||||
fn in_qualifs(qualifs: &ConstQualifs) -> bool {
|
||||
qualifs.custom_eq
|
||||
}
|
||||
|
||||
fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
// If *any* component of a composite data type does not implement `Structural{Partial,}Eq`,
|
||||
// we know that at least some values of that type are not structural-match. I say "some"
|
||||
// because that component may be part of an enum variant (e.g.,
|
||||
// `Option::<NonStructuralMatchTy>::Some`), in which case some values of this type may be
|
||||
// structural-match (`Option::None`).
|
||||
traits::search_for_structural_match_violation(cx.body.span, cx.tcx, ty).is_some()
|
||||
}
|
||||
|
||||
fn in_adt_inherently<'tcx>(
|
||||
cx: &ConstCx<'_, 'tcx>,
|
||||
def: AdtDef<'tcx>,
|
||||
args: GenericArgsRef<'tcx>,
|
||||
) -> bool {
|
||||
let ty = Ty::new_adt(cx.tcx, def, args);
|
||||
!ty.is_structural_eq_shallow(cx.tcx)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Use `mir::visit::Visitor` for the `in_*` functions if/when it supports early return.
|
||||
|
||||
/// Returns `true` if this `Rvalue` contains qualif `Q`.
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
#### Note: this error code is no longer emitted by the compiler.
|
||||
|
||||
|
||||
`#[ffi_returns_twice]` was used on something other than a foreign function
|
||||
declaration.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0724
|
||||
```compile_fail
|
||||
#![feature(ffi_returns_twice)]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
|
@ -15,7 +18,7 @@ pub fn foo() {}
|
|||
For example, we might correct the previous example by declaring
|
||||
the function inside of an `extern` block.
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![feature(ffi_returns_twice)]
|
||||
|
||||
extern "C" {
|
||||
|
|
|
@ -440,9 +440,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
experimental!(optimize),
|
||||
),
|
||||
|
||||
gated!(
|
||||
ffi_returns_twice, Normal, template!(Word), WarnFollowing, experimental!(ffi_returns_twice)
|
||||
),
|
||||
gated!(ffi_pure, Normal, template!(Word), WarnFollowing, experimental!(ffi_pure)),
|
||||
gated!(ffi_const, Normal, template!(Word), WarnFollowing, experimental!(ffi_const)),
|
||||
gated!(
|
||||
|
|
|
@ -97,6 +97,9 @@ declare_features! (
|
|||
/// Allows `#[doc(include = "some-file")]`.
|
||||
(removed, external_doc, "1.54.0", Some(44732),
|
||||
Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations")),
|
||||
/// Allows using `#[ffi_returns_twice]` on foreign functions.
|
||||
(removed, ffi_returns_twice, "CURRENT_RUSTC_VERSION", Some(58314),
|
||||
Some("being investigated by the ffi-unwind project group")),
|
||||
/// Allows generators to be cloned.
|
||||
(removed, generator_clone, "1.65.0", Some(95360), Some("renamed to `coroutine_clone`")),
|
||||
/// Allows defining generators.
|
||||
|
|
|
@ -465,8 +465,6 @@ declare_features! (
|
|||
(unstable, ffi_const, "1.45.0", Some(58328)),
|
||||
/// Allows the use of `#[ffi_pure]` on foreign functions.
|
||||
(unstable, ffi_pure, "1.45.0", Some(58329)),
|
||||
/// Allows using `#[ffi_returns_twice]` on foreign functions.
|
||||
(unstable, ffi_returns_twice, "1.34.0", Some(58314)),
|
||||
/// Allows using `#[repr(align(...))]` on function items
|
||||
(unstable, fn_align, "1.53.0", Some(82232)),
|
||||
/// Support delegating implementation of functions to other already implemented functions.
|
||||
|
|
|
@ -541,6 +541,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
let mut bound_spans: SortedMap<Span, Vec<String>> = Default::default();
|
||||
let mut restrict_type_params = false;
|
||||
let mut suggested_derive = false;
|
||||
let mut unsatisfied_bounds = false;
|
||||
if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) {
|
||||
let msg = "consider using `len` instead";
|
||||
|
@ -555,6 +556,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
"`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement"
|
||||
));
|
||||
}
|
||||
} else if !unsatisfied_predicates.is_empty() && matches!(rcvr_ty.kind(), ty::Param(_)) {
|
||||
// We special case the situation where we are looking for `_` in
|
||||
// `<TypeParam as _>::method` because otherwise the machinery will look for blanket
|
||||
// implementations that have unsatisfied trait bounds to suggest, leading us to claim
|
||||
// things like "we're looking for a trait with method `cmp`, both `Iterator` and `Ord`
|
||||
// have one, in order to implement `Ord` you need to restrict `TypeParam: FnPtr` so
|
||||
// that `impl<T: FnPtr> Ord for T` can apply", which is not what we want. We have a type
|
||||
// parameter, we want to directly say "`Ord::cmp` and `Iterator::cmp` exist, restrict
|
||||
// `TypeParam: Ord` or `TypeParam: Iterator`"". That is done further down when calling
|
||||
// `self.suggest_traits_to_import`, so we ignore the `unsatisfied_predicates`
|
||||
// suggestions.
|
||||
} else if !unsatisfied_predicates.is_empty() {
|
||||
let mut type_params = FxIndexMap::default();
|
||||
|
||||
|
@ -917,20 +929,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.enumerate()
|
||||
.collect::<Vec<(usize, String)>>();
|
||||
|
||||
for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
|
||||
restrict_type_params = true;
|
||||
// #74886: Sort here so that the output is always the same.
|
||||
let obligations = obligations.into_sorted_stable_ord();
|
||||
err.span_suggestion_verbose(
|
||||
span,
|
||||
format!(
|
||||
"consider restricting the type parameter{s} to satisfy the \
|
||||
trait bound{s}",
|
||||
s = pluralize!(obligations.len())
|
||||
),
|
||||
format!("{} {}", add_where_or_comma, obligations.join(", ")),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
if !matches!(rcvr_ty.peel_refs().kind(), ty::Param(_)) {
|
||||
for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
|
||||
restrict_type_params = true;
|
||||
// #74886: Sort here so that the output is always the same.
|
||||
let obligations = obligations.into_sorted_stable_ord();
|
||||
err.span_suggestion_verbose(
|
||||
span,
|
||||
format!(
|
||||
"consider restricting the type parameter{s} to satisfy the trait \
|
||||
bound{s}",
|
||||
s = pluralize!(obligations.len())
|
||||
),
|
||||
format!("{} {}", add_where_or_comma, obligations.join(", ")),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
|
||||
|
@ -978,7 +992,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
"the following trait bounds were not satisfied:\n{bound_list}"
|
||||
));
|
||||
}
|
||||
self.suggest_derive(&mut err, unsatisfied_predicates);
|
||||
suggested_derive = self.suggest_derive(&mut err, unsatisfied_predicates);
|
||||
|
||||
unsatisfied_bounds = true;
|
||||
}
|
||||
|
@ -1201,7 +1215,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params {
|
||||
if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params || suggested_derive {
|
||||
} else {
|
||||
self.suggest_traits_to_import(
|
||||
&mut err,
|
||||
|
@ -1211,7 +1225,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
args.map(|args| args.len() + 1),
|
||||
source,
|
||||
no_match_data.out_of_scope_traits.clone(),
|
||||
unsatisfied_predicates,
|
||||
static_candidates,
|
||||
unsatisfied_bounds,
|
||||
expected.only_has_type(self),
|
||||
|
@ -1326,7 +1339,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected);
|
||||
return Some(err);
|
||||
Some(err)
|
||||
}
|
||||
|
||||
fn note_candidates_on_method_error(
|
||||
|
@ -2471,7 +2484,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
Option<ty::Predicate<'tcx>>,
|
||||
Option<ObligationCause<'tcx>>,
|
||||
)],
|
||||
) {
|
||||
) -> bool {
|
||||
let mut derives = self.note_predicate_source_and_get_derives(err, unsatisfied_predicates);
|
||||
derives.sort();
|
||||
derives.dedup();
|
||||
|
@ -2496,6 +2509,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
!derives_grouped.is_empty()
|
||||
}
|
||||
|
||||
fn note_derefed_ty_has_method(
|
||||
|
@ -2698,11 +2712,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
inputs_len: Option<usize>,
|
||||
source: SelfSource<'tcx>,
|
||||
valid_out_of_scope_traits: Vec<DefId>,
|
||||
unsatisfied_predicates: &[(
|
||||
ty::Predicate<'tcx>,
|
||||
Option<ty::Predicate<'tcx>>,
|
||||
Option<ObligationCause<'tcx>>,
|
||||
)],
|
||||
static_candidates: &[CandidateSource],
|
||||
unsatisfied_bounds: bool,
|
||||
return_type: Option<Ty<'tcx>>,
|
||||
|
@ -2919,19 +2928,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// this isn't perfect (that is, there are cases when
|
||||
// implementing a trait would be legal but is rejected
|
||||
// here).
|
||||
unsatisfied_predicates.iter().all(|(p, _, _)| {
|
||||
match p.kind().skip_binder() {
|
||||
// Hide traits if they are present in predicates as they can be fixed without
|
||||
// having to implement them.
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(t)) => {
|
||||
t.def_id() == info.def_id
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Projection(p)) => {
|
||||
p.projection_ty.def_id == info.def_id
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}) && (type_is_local || info.def_id.is_local())
|
||||
(type_is_local || info.def_id.is_local())
|
||||
&& !self.tcx.trait_is_auto(info.def_id)
|
||||
&& self
|
||||
.associated_value(info.def_id, item_name)
|
||||
|
|
|
@ -71,6 +71,7 @@ use rustc_hir::lang_items::LangItem;
|
|||
use rustc_middle::dep_graph::DepContext;
|
||||
use rustc_middle::ty::print::{with_forced_trimmed_paths, PrintError};
|
||||
use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
|
||||
use rustc_middle::ty::ToPredicate;
|
||||
use rustc_middle::ty::{
|
||||
self, error::TypeError, IsSuggestable, List, Region, Ty, TyCtxt, TypeFoldable,
|
||||
TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
|
||||
|
@ -519,10 +520,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit();
|
||||
}
|
||||
|
||||
RegionResolutionError::CannotNormalize(ty, origin) => {
|
||||
RegionResolutionError::CannotNormalize(clause, origin) => {
|
||||
let clause: ty::Clause<'tcx> =
|
||||
clause.map_bound(ty::ClauseKind::TypeOutlives).to_predicate(self.tcx);
|
||||
self.tcx
|
||||
.dcx()
|
||||
.struct_span_err(origin.span(), format!("cannot normalize `{ty}`"))
|
||||
.struct_span_err(origin.span(), format!("cannot normalize `{clause}`"))
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ pub enum RegionResolutionError<'tcx> {
|
|||
Region<'tcx>, // the placeholder `'b`
|
||||
),
|
||||
|
||||
CannotNormalize(Ty<'tcx>, SubregionOrigin<'tcx>),
|
||||
CannotNormalize(ty::PolyTypeOutlivesPredicate<'tcx>, SubregionOrigin<'tcx>),
|
||||
}
|
||||
|
||||
impl<'tcx> RegionResolutionError<'tcx> {
|
||||
|
|
|
@ -4,8 +4,8 @@ use super::region_constraints::RegionConstraintData;
|
|||
use super::{InferCtxt, RegionResolutionError, SubregionOrigin};
|
||||
use crate::infer::free_regions::RegionRelations;
|
||||
use crate::infer::lexical_region_resolve;
|
||||
use rustc_middle::traits::query::OutlivesBound;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_middle::traits::query::{NoSolution, OutlivesBound};
|
||||
use rustc_middle::ty;
|
||||
|
||||
pub mod components;
|
||||
pub mod env;
|
||||
|
@ -49,12 +49,15 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
pub fn resolve_regions_with_normalize(
|
||||
&self,
|
||||
outlives_env: &OutlivesEnvironment<'tcx>,
|
||||
deeply_normalize_ty: impl Fn(Ty<'tcx>, SubregionOrigin<'tcx>) -> Result<Ty<'tcx>, Ty<'tcx>>,
|
||||
deeply_normalize_ty: impl Fn(
|
||||
ty::PolyTypeOutlivesPredicate<'tcx>,
|
||||
SubregionOrigin<'tcx>,
|
||||
) -> Result<ty::PolyTypeOutlivesPredicate<'tcx>, NoSolution>,
|
||||
) -> Vec<RegionResolutionError<'tcx>> {
|
||||
match self.process_registered_region_obligations(outlives_env, deeply_normalize_ty) {
|
||||
Ok(()) => {}
|
||||
Err((ty, origin)) => {
|
||||
return vec![RegionResolutionError::CannotNormalize(ty, origin)];
|
||||
Err((clause, origin)) => {
|
||||
return vec![RegionResolutionError::CannotNormalize(clause, origin)];
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -68,8 +68,9 @@ use crate::infer::{
|
|||
use crate::traits::{ObligationCause, ObligationCauseCode};
|
||||
use rustc_data_structures::undo_log::UndoLogs;
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
use rustc_middle::ty::GenericArgKind;
|
||||
use rustc_middle::traits::query::NoSolution;
|
||||
use rustc_middle::ty::{self, GenericArgsRef, Region, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_middle::ty::{GenericArgKind, PolyTypeOutlivesPredicate};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use smallvec::smallvec;
|
||||
|
||||
|
@ -125,11 +126,15 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
/// invoked after all type-inference variables have been bound --
|
||||
/// right before lexical region resolution.
|
||||
#[instrument(level = "debug", skip(self, outlives_env, deeply_normalize_ty))]
|
||||
pub fn process_registered_region_obligations<E>(
|
||||
pub fn process_registered_region_obligations(
|
||||
&self,
|
||||
outlives_env: &OutlivesEnvironment<'tcx>,
|
||||
mut deeply_normalize_ty: impl FnMut(Ty<'tcx>, SubregionOrigin<'tcx>) -> Result<Ty<'tcx>, E>,
|
||||
) -> Result<(), (E, SubregionOrigin<'tcx>)> {
|
||||
mut deeply_normalize_ty: impl FnMut(
|
||||
PolyTypeOutlivesPredicate<'tcx>,
|
||||
SubregionOrigin<'tcx>,
|
||||
)
|
||||
-> Result<PolyTypeOutlivesPredicate<'tcx>, NoSolution>,
|
||||
) -> Result<(), (PolyTypeOutlivesPredicate<'tcx>, SubregionOrigin<'tcx>)> {
|
||||
assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot");
|
||||
|
||||
let normalized_caller_bounds: Vec<_> = outlives_env
|
||||
|
@ -137,38 +142,53 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
.caller_bounds()
|
||||
.iter()
|
||||
.filter_map(|clause| {
|
||||
let bound_clause = clause.kind();
|
||||
let ty::ClauseKind::TypeOutlives(outlives) = bound_clause.skip_binder() else {
|
||||
return None;
|
||||
};
|
||||
let outlives = clause.as_type_outlives_clause()?;
|
||||
Some(
|
||||
deeply_normalize_ty(
|
||||
outlives.0,
|
||||
outlives,
|
||||
SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP),
|
||||
)
|
||||
.map(|ty| bound_clause.rebind(ty::OutlivesPredicate(ty, outlives.1))),
|
||||
// FIXME(-Znext-solver): How do we accurately report an error span here :(
|
||||
.map_err(|NoSolution| {
|
||||
(outlives, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP))
|
||||
}),
|
||||
)
|
||||
})
|
||||
// FIXME(-Znext-solver): How do we accurately report an error here :(
|
||||
.try_collect()
|
||||
.map_err(|e| (e, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP)))?;
|
||||
.try_collect()?;
|
||||
|
||||
let my_region_obligations = self.take_registered_region_obligations();
|
||||
// Must loop since the process of normalizing may itself register region obligations.
|
||||
for iteration in 0.. {
|
||||
let my_region_obligations = self.take_registered_region_obligations();
|
||||
if my_region_obligations.is_empty() {
|
||||
break;
|
||||
}
|
||||
|
||||
for RegionObligation { sup_type, sub_region, origin } in my_region_obligations {
|
||||
let sup_type =
|
||||
deeply_normalize_ty(sup_type, origin.clone()).map_err(|e| (e, origin.clone()))?;
|
||||
debug!(?sup_type, ?sub_region, ?origin);
|
||||
if !self.tcx.recursion_limit().value_within_limit(iteration) {
|
||||
bug!(
|
||||
"FIXME(-Znext-solver): Overflowed when processing region obligations: {my_region_obligations:#?}"
|
||||
);
|
||||
}
|
||||
|
||||
let outlives = &mut TypeOutlives::new(
|
||||
self,
|
||||
self.tcx,
|
||||
outlives_env.region_bound_pairs(),
|
||||
None,
|
||||
&normalized_caller_bounds,
|
||||
);
|
||||
let category = origin.to_constraint_category();
|
||||
outlives.type_must_outlive(origin, sup_type, sub_region, category);
|
||||
for RegionObligation { sup_type, sub_region, origin } in my_region_obligations {
|
||||
let outlives = ty::Binder::dummy(ty::OutlivesPredicate(sup_type, sub_region));
|
||||
let ty::OutlivesPredicate(sup_type, sub_region) =
|
||||
deeply_normalize_ty(outlives, origin.clone())
|
||||
.map_err(|NoSolution| (outlives, origin.clone()))?
|
||||
.no_bound_vars()
|
||||
.expect("started with no bound vars, should end with no bound vars");
|
||||
|
||||
debug!(?sup_type, ?sub_region, ?origin);
|
||||
|
||||
let outlives = &mut TypeOutlives::new(
|
||||
self,
|
||||
self.tcx,
|
||||
outlives_env.region_bound_pairs(),
|
||||
None,
|
||||
&normalized_caller_bounds,
|
||||
);
|
||||
let category = origin.to_constraint_category();
|
||||
outlives.type_must_outlive(origin, sup_type, sub_region, category);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -188,6 +188,23 @@ pub(super) fn builtin(
|
|||
#[allow(rustc::potential_query_instability)]
|
||||
let possibilities: Vec<Symbol> =
|
||||
sess.parse_sess.check_config.expecteds.keys().copied().collect();
|
||||
|
||||
let mut names_possibilities: Vec<_> = if value.is_none() {
|
||||
// We later sort and display all the possibilities, so the order here does not matter.
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
sess.parse_sess
|
||||
.check_config
|
||||
.expecteds
|
||||
.iter()
|
||||
.filter_map(|(k, v)| match v {
|
||||
ExpectedValues::Some(v) if v.contains(&Some(name)) => Some(k),
|
||||
_ => None,
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
let is_from_cargo = std::env::var_os("CARGO").is_some();
|
||||
let mut is_feature_cfg = name == sym::feature;
|
||||
|
||||
|
@ -262,17 +279,30 @@ pub(super) fn builtin(
|
|||
}
|
||||
|
||||
is_feature_cfg |= best_match == sym::feature;
|
||||
} else if !possibilities.is_empty() {
|
||||
let mut possibilities =
|
||||
possibilities.iter().map(Symbol::as_str).collect::<Vec<_>>();
|
||||
possibilities.sort();
|
||||
let possibilities = possibilities.join("`, `");
|
||||
} else {
|
||||
if !names_possibilities.is_empty() && names_possibilities.len() <= 3 {
|
||||
names_possibilities.sort();
|
||||
for cfg_name in names_possibilities.iter() {
|
||||
db.span_suggestion(
|
||||
name_span,
|
||||
"found config with similar value",
|
||||
format!("{cfg_name} = \"{name}\""),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
if !possibilities.is_empty() {
|
||||
let mut possibilities =
|
||||
possibilities.iter().map(Symbol::as_str).collect::<Vec<_>>();
|
||||
possibilities.sort();
|
||||
let possibilities = possibilities.join("`, `");
|
||||
|
||||
// The list of expected names can be long (even by default) and
|
||||
// so the diagnostic produced can take a lot of space. To avoid
|
||||
// cloging the user output we only want to print that diagnostic
|
||||
// once.
|
||||
db.help_once(format!("expected names are: `{possibilities}`"));
|
||||
// The list of expected names can be long (even by default) and
|
||||
// so the diagnostic produced can take a lot of space. To avoid
|
||||
// cloging the user output we only want to print that diagnostic
|
||||
// once.
|
||||
db.help_once(format!("expected names are: `{possibilities}`"));
|
||||
}
|
||||
}
|
||||
|
||||
let inst = if let Some((value, _value_span)) = value {
|
||||
|
|
|
@ -520,6 +520,11 @@ fn register_builtins(store: &mut LintStore) {
|
|||
"illegal_floating_point_literal_pattern",
|
||||
"no longer a warning, float patterns behave the same as `==`",
|
||||
);
|
||||
store.register_removed(
|
||||
"nontrivial_structural_match",
|
||||
"no longer needed, see RFC #3535 \
|
||||
<https://rust-lang.github.io/rfcs/3535-constants-in-patterns.html> for more information",
|
||||
);
|
||||
}
|
||||
|
||||
fn register_internals(store: &mut LintStore) {
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
//! These are the built-in lints that are emitted direct in the main
|
||||
//! compiler code, rather than using their own custom pass. Those
|
||||
//! lints are all available in `rustc_lint::builtin`.
|
||||
//!
|
||||
//! When removing a lint, make sure to also add a call to `register_removed` in
|
||||
//! compiler/rustc_lint/src/lib.rs.
|
||||
|
||||
use crate::{declare_lint, declare_lint_pass, FutureIncompatibilityReason};
|
||||
use rustc_span::edition::Edition;
|
||||
|
@ -66,7 +69,6 @@ declare_lint_pass! {
|
|||
MUST_NOT_SUSPEND,
|
||||
NAMED_ARGUMENTS_USED_POSITIONALLY,
|
||||
NON_EXHAUSTIVE_OMITTED_PATTERNS,
|
||||
NONTRIVIAL_STRUCTURAL_MATCH,
|
||||
ORDER_DEPENDENT_TRAIT_OBJECTS,
|
||||
OVERLAPPING_RANGE_ENDPOINTS,
|
||||
PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||
|
@ -2280,8 +2282,8 @@ declare_lint! {
|
|||
Warn,
|
||||
"constant used in pattern contains value of non-structural-match type in a field or a variant",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
|
||||
reference: "issue #62411 <https://github.com/rust-lang/rust/issues/62411>",
|
||||
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
|
||||
reference: "issue #120362 <https://github.com/rust-lang/rust/issues/120362>",
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -2336,47 +2338,8 @@ declare_lint! {
|
|||
Warn,
|
||||
"pointers are not structural-match",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
|
||||
reference: "issue #62411 <https://github.com/rust-lang/rust/issues/70861>",
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `nontrivial_structural_match` lint detects constants that are used in patterns,
|
||||
/// whose type is not structural-match and whose initializer body actually uses values
|
||||
/// that are not structural-match. So `Option<NotStructuralMatch>` is ok if the constant
|
||||
/// is just `None`.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust,compile_fail
|
||||
/// #![deny(nontrivial_structural_match)]
|
||||
///
|
||||
/// #[derive(Copy, Clone, Debug)]
|
||||
/// struct NoDerive(u32);
|
||||
/// impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
|
||||
/// impl Eq for NoDerive { }
|
||||
/// fn main() {
|
||||
/// const INDEX: Option<NoDerive> = [None, Some(NoDerive(10))][0];
|
||||
/// match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), };
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Previous versions of Rust accepted constants in patterns, even if those constants' types
|
||||
/// did not have `PartialEq` derived. Thus the compiler falls back to runtime execution of
|
||||
/// `PartialEq`, which can report that two constants are not equal even if they are
|
||||
/// bit-equivalent.
|
||||
pub NONTRIVIAL_STRUCTURAL_MATCH,
|
||||
Warn,
|
||||
"constant used in pattern of non-structural-match type and the constant's initializer \
|
||||
expression contains values of non-structural-match types",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
|
||||
reference: "issue #73448 <https://github.com/rust-lang/rust/issues/73448>",
|
||||
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
|
||||
reference: "issue #120362 <https://github.com/rust-lang/rust/issues/120362>",
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,6 @@ enum LLVMRustAttribute {
|
|||
SanitizeMemory = 22,
|
||||
NonLazyBind = 23,
|
||||
OptimizeNone = 24,
|
||||
ReturnsTwice = 25,
|
||||
ReadNone = 26,
|
||||
SanitizeHWAddress = 28,
|
||||
WillReturn = 29,
|
||||
|
|
|
@ -250,8 +250,6 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
|
|||
return Attribute::NonLazyBind;
|
||||
case OptimizeNone:
|
||||
return Attribute::OptimizeNone;
|
||||
case ReturnsTwice:
|
||||
return Attribute::ReturnsTwice;
|
||||
case ReadNone:
|
||||
return Attribute::ReadNone;
|
||||
case SanitizeHWAddress:
|
||||
|
|
|
@ -74,35 +74,32 @@ bitflags! {
|
|||
/// `#[used]`: indicates that LLVM can't eliminate this function (but the
|
||||
/// linker can!).
|
||||
const USED = 1 << 9;
|
||||
/// `#[ffi_returns_twice]`, indicates that an extern function can return
|
||||
/// multiple times
|
||||
const FFI_RETURNS_TWICE = 1 << 10;
|
||||
/// `#[track_caller]`: allow access to the caller location
|
||||
const TRACK_CALLER = 1 << 11;
|
||||
const TRACK_CALLER = 1 << 10;
|
||||
/// #[ffi_pure]: applies clang's `pure` attribute to a foreign function
|
||||
/// declaration.
|
||||
const FFI_PURE = 1 << 12;
|
||||
const FFI_PURE = 1 << 11;
|
||||
/// #[ffi_const]: applies clang's `const` attribute to a foreign function
|
||||
/// declaration.
|
||||
const FFI_CONST = 1 << 13;
|
||||
const FFI_CONST = 1 << 12;
|
||||
/// #[cmse_nonsecure_entry]: with a TrustZone-M extension, declare a
|
||||
/// function as an entry function from Non-Secure code.
|
||||
const CMSE_NONSECURE_ENTRY = 1 << 14;
|
||||
const CMSE_NONSECURE_ENTRY = 1 << 13;
|
||||
/// `#[coverage(off)]`: indicates that the function should be ignored by
|
||||
/// the MIR `InstrumentCoverage` pass and not added to the coverage map
|
||||
/// during codegen.
|
||||
const NO_COVERAGE = 1 << 15;
|
||||
const NO_COVERAGE = 1 << 14;
|
||||
/// `#[used(linker)]`:
|
||||
/// indicates that neither LLVM nor the linker will eliminate this function.
|
||||
const USED_LINKER = 1 << 16;
|
||||
const USED_LINKER = 1 << 15;
|
||||
/// `#[rustc_deallocator]`: a hint to LLVM that the function only deallocates memory.
|
||||
const DEALLOCATOR = 1 << 17;
|
||||
const DEALLOCATOR = 1 << 16;
|
||||
/// `#[rustc_reallocator]`: a hint to LLVM that the function only reallocates memory.
|
||||
const REALLOCATOR = 1 << 18;
|
||||
const REALLOCATOR = 1 << 17;
|
||||
/// `#[rustc_allocator_zeroed]`: a hint to LLVM that the function only allocates zeroed memory.
|
||||
const ALLOCATOR_ZEROED = 1 << 19;
|
||||
const ALLOCATOR_ZEROED = 1 << 18;
|
||||
/// `#[no_builtins]`: indicates that disable implicit builtin knowledge of functions for the function.
|
||||
const NO_BUILTINS = 1 << 20;
|
||||
const NO_BUILTINS = 1 << 19;
|
||||
}
|
||||
}
|
||||
rustc_data_structures::external_bitflags_debug! { CodegenFnAttrFlags }
|
||||
|
|
|
@ -189,7 +189,7 @@ pub struct BorrowCheckResult<'tcx> {
|
|||
|
||||
/// The result of the `mir_const_qualif` query.
|
||||
///
|
||||
/// Each field (except `error_occurred`) corresponds to an implementer of the `Qualif` trait in
|
||||
/// Each field (except `tainted_by_errors`) corresponds to an implementer of the `Qualif` trait in
|
||||
/// `rustc_const_eval/src/transform/check_consts/qualifs.rs`. See that file for more information on each
|
||||
/// `Qualif`.
|
||||
#[derive(Clone, Copy, Debug, Default, TyEncodable, TyDecodable, HashStable)]
|
||||
|
@ -197,7 +197,6 @@ pub struct ConstQualifs {
|
|||
pub has_mut_interior: bool,
|
||||
pub needs_drop: bool,
|
||||
pub needs_non_const_drop: bool,
|
||||
pub custom_eq: bool,
|
||||
pub tainted_by_errors: Option<ErrorGuaranteed>,
|
||||
}
|
||||
|
||||
|
|
|
@ -1193,7 +1193,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
let (suitable_region_binding_scope, bound_region) = loop {
|
||||
let def_id = match region.kind() {
|
||||
ty::ReLateParam(fr) => fr.bound_region.get_id()?.as_local()?,
|
||||
ty::ReEarlyParam(ebr) => ebr.def_id.expect_local(),
|
||||
ty::ReEarlyParam(ebr) => ebr.def_id.as_local()?,
|
||||
_ => return None, // not a free region
|
||||
};
|
||||
let scope = self.local_parent(def_id);
|
||||
|
|
|
@ -291,7 +291,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
|
|||
err = err.and(check_never_pattern(cx, pat));
|
||||
});
|
||||
err?;
|
||||
Ok(cx.pattern_arena.alloc(cx.lower_pat(pat)))
|
||||
Ok(self.pattern_arena.alloc(cx.lower_pat(pat)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -388,7 +388,6 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
|
|||
typeck_results: self.typeck_results,
|
||||
param_env: self.param_env,
|
||||
module: self.tcx.parent_module(self.lint_level).to_def_id(),
|
||||
pattern_arena: self.pattern_arena,
|
||||
dropless_arena: self.dropless_arena,
|
||||
match_lint_level: self.lint_level,
|
||||
whole_match_span,
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use rustc_apfloat::Float;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_index::Idx;
|
||||
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||
use rustc_infer::traits::Obligation;
|
||||
|
@ -17,8 +16,8 @@ use std::cell::Cell;
|
|||
|
||||
use super::PatCtxt;
|
||||
use crate::errors::{
|
||||
IndirectStructuralMatch, InvalidPattern, NaNPattern, NonPartialEqMatch,
|
||||
NontrivialStructuralMatch, PointerPattern, TypeNotStructural, UnionPattern, UnsizedPattern,
|
||||
IndirectStructuralMatch, InvalidPattern, NaNPattern, NonPartialEqMatch, PointerPattern,
|
||||
TypeNotStructural, UnionPattern, UnsizedPattern,
|
||||
};
|
||||
|
||||
impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
|
@ -33,11 +32,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||
cv: mir::Const<'tcx>,
|
||||
id: hir::HirId,
|
||||
span: Span,
|
||||
check_body_for_struct_match_violation: Option<DefId>,
|
||||
) -> Box<Pat<'tcx>> {
|
||||
let infcx = self.tcx.infer_ctxt().build();
|
||||
let mut convert = ConstToPat::new(self, id, span, infcx);
|
||||
convert.to_pat(cv, check_body_for_struct_match_violation)
|
||||
convert.to_pat(cv)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,11 +101,7 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
ty.is_structural_eq_shallow(self.infcx.tcx)
|
||||
}
|
||||
|
||||
fn to_pat(
|
||||
&mut self,
|
||||
cv: mir::Const<'tcx>,
|
||||
check_body_for_struct_match_violation: Option<DefId>,
|
||||
) -> Box<Pat<'tcx>> {
|
||||
fn to_pat(&mut self, cv: mir::Const<'tcx>) -> Box<Pat<'tcx>> {
|
||||
trace!(self.treat_byte_string_as_slice);
|
||||
// This method is just a wrapper handling a validity check; the heavy lifting is
|
||||
// performed by the recursive `recur` method, which is not meant to be
|
||||
|
@ -116,14 +110,6 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
// once indirect_structural_match is a full fledged error, this
|
||||
// level of indirection can be eliminated
|
||||
|
||||
let mir_structural_match_violation = check_body_for_struct_match_violation.map(|def_id| {
|
||||
// `mir_const_qualif` must be called with the `DefId` of the item where the const is
|
||||
// defined, not where it is declared. The difference is significant for associated
|
||||
// constants.
|
||||
self.tcx().mir_const_qualif(def_id).custom_eq
|
||||
});
|
||||
debug!(?check_body_for_struct_match_violation, ?mir_structural_match_violation);
|
||||
|
||||
let have_valtree =
|
||||
matches!(cv, mir::Const::Ty(c) if matches!(c.kind(), ty::ConstKind::Value(_)));
|
||||
let inlined_const_as_pat = match cv {
|
||||
|
@ -137,15 +123,15 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
| ty::ConstKind::Expr(_) => {
|
||||
span_bug!(self.span, "unexpected const in `to_pat`: {:?}", c.kind())
|
||||
}
|
||||
ty::ConstKind::Value(valtree) => self
|
||||
.recur(valtree, cv.ty(), mir_structural_match_violation.unwrap_or(false))
|
||||
.unwrap_or_else(|_: FallbackToOpaqueConst| {
|
||||
ty::ConstKind::Value(valtree) => {
|
||||
self.recur(valtree, cv.ty()).unwrap_or_else(|_: FallbackToOpaqueConst| {
|
||||
Box::new(Pat {
|
||||
span: self.span,
|
||||
ty: cv.ty(),
|
||||
kind: PatKind::Constant { value: cv },
|
||||
})
|
||||
}),
|
||||
})
|
||||
}
|
||||
},
|
||||
mir::Const::Unevaluated(_, _) => {
|
||||
span_bug!(self.span, "unevaluated const in `to_pat`: {cv:?}")
|
||||
|
@ -160,7 +146,12 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
if self.saw_const_match_error.get().is_none() {
|
||||
// If we were able to successfully convert the const to some pat (possibly with some
|
||||
// lints, but no errors), double-check that all types in the const implement
|
||||
// `Structural` and `PartialEq`.
|
||||
// `PartialEq`. Even if we have a valtree, we may have found something
|
||||
// in there with non-structural-equality, meaning we match using `PartialEq`
|
||||
// and we hence have to check that that impl exists.
|
||||
// This is all messy but not worth cleaning up: at some point we'll emit
|
||||
// a hard error when we don't have a valtree or when we find something in
|
||||
// the valtree that is not structural; then this can all be made a lot simpler.
|
||||
|
||||
let structural =
|
||||
traits::search_for_structural_match_violation(self.span, self.tcx(), cv.ty());
|
||||
|
@ -170,19 +161,12 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
structural
|
||||
);
|
||||
|
||||
// This can occur because const qualification treats all associated constants as
|
||||
// opaque, whereas `search_for_structural_match_violation` tries to monomorphize them
|
||||
// before it runs.
|
||||
//
|
||||
// FIXME(#73448): Find a way to bring const qualification into parity with
|
||||
// `search_for_structural_match_violation`.
|
||||
if structural.is_none() && mir_structural_match_violation.unwrap_or(false) {
|
||||
warn!("MIR const-checker found novel structural match violation. See #73448.");
|
||||
return inlined_const_as_pat;
|
||||
}
|
||||
|
||||
if let Some(non_sm_ty) = structural {
|
||||
if !self.type_has_partial_eq_impl(cv.ty()) {
|
||||
// This is reachable and important even if we have a valtree: there might be
|
||||
// non-structural things in a valtree, in which case we fall back to `PartialEq`
|
||||
// comparison, in which case we better make sure the trait is implemented for
|
||||
// each inner type (and not just for the surrounding type).
|
||||
let e = if let ty::Adt(def, ..) = non_sm_ty.kind() {
|
||||
if def.is_union() {
|
||||
let err = UnionPattern { span: self.span };
|
||||
|
@ -201,35 +185,18 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
// We errored. Signal that in the pattern, so that follow up errors can be silenced.
|
||||
let kind = PatKind::Error(e);
|
||||
return Box::new(Pat { span: self.span, ty: cv.ty(), kind });
|
||||
} else if let ty::Adt(..) = cv.ty().kind()
|
||||
&& matches!(cv, mir::Const::Val(..))
|
||||
{
|
||||
// This branch is only entered when the current `cv` is `mir::Const::Val`.
|
||||
// This is because `mir::Const::ty` has already been handled by `Self::recur`
|
||||
// and the invalid types may be ignored.
|
||||
} else if !have_valtree {
|
||||
// Not being structural prevented us from constructing a valtree,
|
||||
// so this is definitely a case we want to reject.
|
||||
let err = TypeNotStructural { span: self.span, non_sm_ty };
|
||||
let e = self.tcx().dcx().emit_err(err);
|
||||
let kind = PatKind::Error(e);
|
||||
return Box::new(Pat { span: self.span, ty: cv.ty(), kind });
|
||||
} else if !self.saw_const_match_lint.get() {
|
||||
if let Some(mir_structural_match_violation) = mir_structural_match_violation {
|
||||
match non_sm_ty.kind() {
|
||||
ty::Adt(..) if mir_structural_match_violation => {
|
||||
self.tcx().emit_node_span_lint(
|
||||
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
|
||||
self.id,
|
||||
self.span,
|
||||
IndirectStructuralMatch { non_sm_ty },
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
debug!(
|
||||
"`search_for_structural_match_violation` found one, but `CustomEq` was \
|
||||
not in the qualifs for that `const`"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// This could be a violation in an inactive enum variant.
|
||||
// Since we have a valtree, we trust that we have traversed the full valtree and
|
||||
// complained about structural match violations there, so we don't
|
||||
// have to check anything any more.
|
||||
}
|
||||
} else if !have_valtree && !self.saw_const_match_lint.get() {
|
||||
// The only way valtree construction can fail without the structural match
|
||||
|
@ -299,7 +266,7 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
let field = FieldIdx::new(idx);
|
||||
// Patterns can only use monomorphic types.
|
||||
let ty = self.tcx().normalize_erasing_regions(self.param_env, ty);
|
||||
Ok(FieldPat { field, pattern: self.recur(val, ty, false)? })
|
||||
Ok(FieldPat { field, pattern: self.recur(val, ty)? })
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
@ -310,7 +277,6 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
&self,
|
||||
cv: ValTree<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
mir_structural_match_violation: bool,
|
||||
) -> Result<Box<Pat<'tcx>>, FallbackToOpaqueConst> {
|
||||
let id = self.id;
|
||||
let span = self.span;
|
||||
|
@ -395,7 +361,7 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
prefix: cv
|
||||
.unwrap_branch()
|
||||
.iter()
|
||||
.map(|val| self.recur(*val, *elem_ty, false))
|
||||
.map(|val| self.recur(*val, *elem_ty))
|
||||
.collect::<Result<_, _>>()?,
|
||||
slice: None,
|
||||
suffix: Box::new([]),
|
||||
|
@ -404,7 +370,7 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
prefix: cv
|
||||
.unwrap_branch()
|
||||
.iter()
|
||||
.map(|val| self.recur(*val, *elem_ty, false))
|
||||
.map(|val| self.recur(*val, *elem_ty))
|
||||
.collect::<Result<_, _>>()?,
|
||||
slice: None,
|
||||
suffix: Box::new([]),
|
||||
|
@ -471,7 +437,7 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
_ => *pointee_ty,
|
||||
};
|
||||
// References have the same valtree representation as their pointee.
|
||||
let subpattern = self.recur(cv, pointee_ty, false)?;
|
||||
let subpattern = self.recur(cv, pointee_ty)?;
|
||||
self.behind_reference.set(old);
|
||||
PatKind::Deref { subpattern }
|
||||
}
|
||||
|
@ -512,25 +478,6 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
}
|
||||
};
|
||||
|
||||
if self.saw_const_match_error.get().is_none()
|
||||
&& !self.saw_const_match_lint.get()
|
||||
&& 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.
|
||||
|
||||
// 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, ty)
|
||||
{
|
||||
self.saw_const_match_lint.set(true);
|
||||
tcx.emit_node_span_lint(
|
||||
lint::builtin::NONTRIVIAL_STRUCTURAL_MATCH,
|
||||
id,
|
||||
span,
|
||||
NontrivialStructuralMatch { non_sm_ty },
|
||||
);
|
||||
}
|
||||
|
||||
Ok(Box::new(Pat { span, ty, kind }))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -542,7 +542,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||
|
||||
match const_value {
|
||||
Ok(const_) => {
|
||||
let pattern = self.const_to_pat(const_, id, span, Some(instance.def_id()));
|
||||
let pattern = self.const_to_pat(const_, id, span);
|
||||
|
||||
if !is_associated_const {
|
||||
return pattern;
|
||||
|
@ -612,7 +612,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||
};
|
||||
if let Some(lit_input) = lit_input {
|
||||
match tcx.at(expr.span).lit_to_const(lit_input) {
|
||||
Ok(c) => return self.const_to_pat(Const::Ty(c), id, span, None).kind,
|
||||
Ok(c) => return self.const_to_pat(Const::Ty(c), id, span).kind,
|
||||
// If an error occurred, ignore that it's a literal
|
||||
// and leave reporting the error up to const eval of
|
||||
// the unevaluated constant below.
|
||||
|
@ -635,17 +635,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||
if let Ok(Some(valtree)) =
|
||||
self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, Some(span))
|
||||
{
|
||||
let subpattern = self.const_to_pat(
|
||||
Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)),
|
||||
id,
|
||||
span,
|
||||
None,
|
||||
);
|
||||
let subpattern =
|
||||
self.const_to_pat(Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)), id, span);
|
||||
PatKind::InlineConstant { subpattern, def: def_id }
|
||||
} else {
|
||||
// If that fails, convert it to an opaque constant pattern.
|
||||
match tcx.const_eval_resolve(self.param_env, uneval, Some(span)) {
|
||||
Ok(val) => self.const_to_pat(mir::Const::Val(val, ty), id, span, None).kind,
|
||||
Ok(val) => self.const_to_pat(mir::Const::Val(val, ty), id, span).kind,
|
||||
Err(ErrorHandled::TooGeneric(_)) => {
|
||||
// If we land here it means the const can't be evaluated because it's `TooGeneric`.
|
||||
let e = self.tcx.dcx().emit_err(ConstPatternDependsOnGenericParameter { span });
|
||||
|
@ -681,9 +677,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||
let lit_input =
|
||||
LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg };
|
||||
match self.tcx.at(expr.span).lit_to_const(lit_input) {
|
||||
Ok(constant) => {
|
||||
self.const_to_pat(Const::Ty(constant), expr.hir_id, lit.span, None).kind
|
||||
}
|
||||
Ok(constant) => self.const_to_pat(Const::Ty(constant), expr.hir_id, lit.span).kind,
|
||||
Err(LitToConstError::Reported(e)) => PatKind::Error(e),
|
||||
Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
|
||||
}
|
||||
|
|
|
@ -323,9 +323,6 @@ passes_ffi_const_invalid_target =
|
|||
passes_ffi_pure_invalid_target =
|
||||
`#[ffi_pure]` may only be used on foreign functions
|
||||
|
||||
passes_ffi_returns_twice_invalid_target =
|
||||
`#[ffi_returns_twice]` may only be used on foreign functions
|
||||
|
||||
passes_has_incoherent_inherent_impl =
|
||||
`rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits.
|
||||
.label = only adts, extern types and traits are supported
|
||||
|
|
|
@ -192,7 +192,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
sym::ffi_pure => self.check_ffi_pure(attr.span, attrs, target),
|
||||
sym::ffi_const => self.check_ffi_const(attr.span, target),
|
||||
sym::ffi_returns_twice => self.check_ffi_returns_twice(attr.span, target),
|
||||
sym::rustc_const_unstable
|
||||
| sym::rustc_const_stable
|
||||
| sym::unstable
|
||||
|
@ -1309,15 +1308,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_ffi_returns_twice(&self, attr_span: Span, target: Target) -> bool {
|
||||
if target == Target::ForeignFn {
|
||||
true
|
||||
} else {
|
||||
self.dcx().emit_err(errors::FfiReturnsTwiceInvalidTarget { attr_span });
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Warns against some misuses of `#[must_use]`
|
||||
fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) -> bool {
|
||||
if !matches!(
|
||||
|
|
|
@ -390,13 +390,6 @@ pub struct FfiConstInvalidTarget {
|
|||
pub attr_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_ffi_returns_twice_invalid_target, code = E0724)]
|
||||
pub struct FfiReturnsTwiceInvalidTarget {
|
||||
#[primary_span]
|
||||
pub attr_span: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(passes_must_use_async)]
|
||||
pub struct MustUseAsync {
|
||||
|
|
|
@ -23,7 +23,10 @@ impl<'tcx> Uncovered<'tcx> {
|
|||
span: Span,
|
||||
cx: &RustcMatchCheckCtxt<'p, 'tcx>,
|
||||
witnesses: Vec<WitnessPat<'p, 'tcx>>,
|
||||
) -> Self {
|
||||
) -> Self
|
||||
where
|
||||
'tcx: 'p,
|
||||
{
|
||||
let witness_1 = cx.hoist_witness_pat(witnesses.get(0).unwrap());
|
||||
Self {
|
||||
span,
|
||||
|
|
|
@ -119,7 +119,7 @@ pub trait TypeCx: Sized + fmt::Debug {
|
|||
/// `DeconstructedPat`. Only invoqued when `pat.ctor()` is `Struct | Variant(_) | UnionField`.
|
||||
fn write_variant_name(
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
pat: &crate::pat::DeconstructedPat<'_, Self>,
|
||||
pat: &crate::pat::DeconstructedPat<Self>,
|
||||
) -> fmt::Result;
|
||||
|
||||
/// Raise a bug.
|
||||
|
@ -130,9 +130,9 @@ pub trait TypeCx: Sized + fmt::Debug {
|
|||
/// The default implementation does nothing.
|
||||
fn lint_overlapping_range_endpoints(
|
||||
&self,
|
||||
_pat: &DeconstructedPat<'_, Self>,
|
||||
_pat: &DeconstructedPat<Self>,
|
||||
_overlaps_on: IntRange,
|
||||
_overlaps_with: &[&DeconstructedPat<'_, Self>],
|
||||
_overlaps_with: &[&DeconstructedPat<Self>],
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ pub trait TypeCx: Sized + fmt::Debug {
|
|||
/// The arm of a match expression.
|
||||
#[derive(Debug)]
|
||||
pub struct MatchArm<'p, Cx: TypeCx> {
|
||||
pub pat: &'p DeconstructedPat<'p, Cx>,
|
||||
pub pat: &'p DeconstructedPat<Cx>,
|
||||
pub has_guard: bool,
|
||||
pub arm_data: Cx::ArmData,
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::fmt;
|
|||
use smallvec::{smallvec, SmallVec};
|
||||
|
||||
use crate::constructor::{Constructor, Slice, SliceKind};
|
||||
use crate::{Captures, TypeCx};
|
||||
use crate::TypeCx;
|
||||
|
||||
use self::Constructor::*;
|
||||
|
||||
|
@ -21,9 +21,9 @@ use self::Constructor::*;
|
|||
/// This happens if a private or `non_exhaustive` field is uninhabited, because the code mustn't
|
||||
/// observe that it is uninhabited. In that case that field is not included in `fields`. Care must
|
||||
/// be taken when converting to/from `thir::Pat`.
|
||||
pub struct DeconstructedPat<'p, Cx: TypeCx> {
|
||||
pub struct DeconstructedPat<Cx: TypeCx> {
|
||||
ctor: Constructor<Cx>,
|
||||
fields: &'p [DeconstructedPat<'p, Cx>],
|
||||
fields: Vec<DeconstructedPat<Cx>>,
|
||||
ty: Cx::Ty,
|
||||
/// Extra data to store in a pattern. `None` if the pattern is a wildcard that does not
|
||||
/// correspond to a user-supplied pattern.
|
||||
|
@ -32,14 +32,20 @@ pub struct DeconstructedPat<'p, Cx: TypeCx> {
|
|||
useful: Cell<bool>,
|
||||
}
|
||||
|
||||
impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> {
|
||||
impl<Cx: TypeCx> DeconstructedPat<Cx> {
|
||||
pub fn wildcard(ty: Cx::Ty) -> Self {
|
||||
DeconstructedPat { ctor: Wildcard, fields: &[], ty, data: None, useful: Cell::new(false) }
|
||||
DeconstructedPat {
|
||||
ctor: Wildcard,
|
||||
fields: Vec::new(),
|
||||
ty,
|
||||
data: None,
|
||||
useful: Cell::new(false),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
ctor: Constructor<Cx>,
|
||||
fields: &'p [DeconstructedPat<'p, Cx>],
|
||||
fields: Vec<DeconstructedPat<Cx>>,
|
||||
ty: Cx::Ty,
|
||||
data: Cx::PatData,
|
||||
) -> Self {
|
||||
|
@ -62,17 +68,17 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> {
|
|||
self.data.as_ref()
|
||||
}
|
||||
|
||||
pub fn iter_fields(&self) -> impl Iterator<Item = &'p DeconstructedPat<'p, Cx>> + Captures<'_> {
|
||||
pub fn iter_fields<'a>(&'a self) -> impl Iterator<Item = &'a DeconstructedPat<Cx>> {
|
||||
self.fields.iter()
|
||||
}
|
||||
|
||||
/// Specialize this pattern with a constructor.
|
||||
/// `other_ctor` can be different from `self.ctor`, but must be covered by it.
|
||||
pub(crate) fn specialize(
|
||||
&self,
|
||||
pub(crate) fn specialize<'a>(
|
||||
&'a self,
|
||||
other_ctor: &Constructor<Cx>,
|
||||
ctor_arity: usize,
|
||||
) -> SmallVec<[PatOrWild<'p, Cx>; 2]> {
|
||||
) -> SmallVec<[PatOrWild<'a, Cx>; 2]> {
|
||||
let wildcard_sub_tys = || (0..ctor_arity).map(|_| PatOrWild::Wild).collect();
|
||||
match (&self.ctor, other_ctor) {
|
||||
// Return a wildcard for each field of `other_ctor`.
|
||||
|
@ -139,7 +145,7 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> {
|
|||
}
|
||||
|
||||
/// This is best effort and not good enough for a `Display` impl.
|
||||
impl<'p, Cx: TypeCx> fmt::Debug for DeconstructedPat<'p, Cx> {
|
||||
impl<Cx: TypeCx> fmt::Debug for DeconstructedPat<Cx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let pat = self;
|
||||
let mut first = true;
|
||||
|
@ -221,7 +227,7 @@ pub(crate) enum PatOrWild<'p, Cx: TypeCx> {
|
|||
/// A non-user-provided wildcard, created during specialization.
|
||||
Wild,
|
||||
/// A user-provided pattern.
|
||||
Pat(&'p DeconstructedPat<'p, Cx>),
|
||||
Pat(&'p DeconstructedPat<Cx>),
|
||||
}
|
||||
|
||||
impl<'p, Cx: TypeCx> Clone for PatOrWild<'p, Cx> {
|
||||
|
@ -236,7 +242,7 @@ impl<'p, Cx: TypeCx> Clone for PatOrWild<'p, Cx> {
|
|||
impl<'p, Cx: TypeCx> Copy for PatOrWild<'p, Cx> {}
|
||||
|
||||
impl<'p, Cx: TypeCx> PatOrWild<'p, Cx> {
|
||||
pub(crate) fn as_pat(&self) -> Option<&'p DeconstructedPat<'p, Cx>> {
|
||||
pub(crate) fn as_pat(&self) -> Option<&'p DeconstructedPat<Cx>> {
|
||||
match self {
|
||||
PatOrWild::Wild => None,
|
||||
PatOrWild::Pat(pat) => Some(pat),
|
||||
|
|
|
@ -13,7 +13,7 @@ use crate::{Captures, MatchArm, TypeCx};
|
|||
#[derive(Debug)]
|
||||
pub struct PatternColumn<'p, Cx: TypeCx> {
|
||||
/// This must not contain an or-pattern. `expand_and_push` takes care to expand them.
|
||||
patterns: Vec<&'p DeconstructedPat<'p, Cx>>,
|
||||
patterns: Vec<&'p DeconstructedPat<Cx>>,
|
||||
}
|
||||
|
||||
impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> {
|
||||
|
@ -41,7 +41,7 @@ impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> {
|
|||
pub fn head_ty(&self) -> Option<&Cx::Ty> {
|
||||
self.patterns.first().map(|pat| pat.ty())
|
||||
}
|
||||
pub fn iter<'a>(&'a self) -> impl Iterator<Item = &'p DeconstructedPat<'p, Cx>> + Captures<'a> {
|
||||
pub fn iter<'a>(&'a self) -> impl Iterator<Item = &'p DeconstructedPat<Cx>> + Captures<'a> {
|
||||
self.patterns.iter().copied()
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use smallvec::SmallVec;
|
||||
use std::fmt;
|
||||
use std::iter::once;
|
||||
|
||||
use rustc_arena::{DroplessArena, TypedArena};
|
||||
use rustc_arena::DroplessArena;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::HirId;
|
||||
use rustc_index::{Idx, IndexVec};
|
||||
|
@ -27,8 +26,7 @@ use crate::constructor::Constructor::*;
|
|||
pub type Constructor<'p, 'tcx> = crate::constructor::Constructor<RustcMatchCheckCtxt<'p, 'tcx>>;
|
||||
pub type ConstructorSet<'p, 'tcx> =
|
||||
crate::constructor::ConstructorSet<RustcMatchCheckCtxt<'p, 'tcx>>;
|
||||
pub type DeconstructedPat<'p, 'tcx> =
|
||||
crate::pat::DeconstructedPat<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
|
||||
pub type DeconstructedPat<'p, 'tcx> = crate::pat::DeconstructedPat<RustcMatchCheckCtxt<'p, 'tcx>>;
|
||||
pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
|
||||
pub type Usefulness<'p, 'tcx> = crate::usefulness::Usefulness<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
|
||||
pub type UsefulnessReport<'p, 'tcx> =
|
||||
|
@ -64,7 +62,7 @@ impl<'tcx> RevealedTy<'tcx> {
|
|||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RustcMatchCheckCtxt<'p, 'tcx> {
|
||||
pub struct RustcMatchCheckCtxt<'p, 'tcx: 'p> {
|
||||
pub tcx: TyCtxt<'tcx>,
|
||||
pub typeck_results: &'tcx ty::TypeckResults<'tcx>,
|
||||
/// The module in which the match occurs. This is necessary for
|
||||
|
@ -74,8 +72,6 @@ pub struct RustcMatchCheckCtxt<'p, 'tcx> {
|
|||
/// outside its module and should not be matchable with an empty match statement.
|
||||
pub module: DefId,
|
||||
pub param_env: ty::ParamEnv<'tcx>,
|
||||
/// To allocate lowered patterns
|
||||
pub pattern_arena: &'p TypedArena<DeconstructedPat<'p, 'tcx>>,
|
||||
/// To allocate the result of `self.ctor_sub_tys()`
|
||||
pub dropless_arena: &'p DroplessArena,
|
||||
/// Lint level at the match.
|
||||
|
@ -91,13 +87,13 @@ pub struct RustcMatchCheckCtxt<'p, 'tcx> {
|
|||
pub known_valid_scrutinee: bool,
|
||||
}
|
||||
|
||||
impl<'p, 'tcx> fmt::Debug for RustcMatchCheckCtxt<'p, 'tcx> {
|
||||
impl<'p, 'tcx: 'p> fmt::Debug for RustcMatchCheckCtxt<'p, 'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("RustcMatchCheckCtxt").finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
|
||||
impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
|
||||
/// Type inference occasionally gives us opaque types in places where corresponding patterns
|
||||
/// have more specific types. To avoid inconsistencies as well as detect opaque uninhabited
|
||||
/// types, we use the corresponding concrete type if possible.
|
||||
|
@ -459,21 +455,20 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
|
|||
/// Note: the input patterns must have been lowered through
|
||||
/// `rustc_mir_build::thir::pattern::check_match::MatchVisitor::lower_pattern`.
|
||||
pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'p, 'tcx> {
|
||||
let singleton = |pat| std::slice::from_ref(self.pattern_arena.alloc(pat));
|
||||
let cx = self;
|
||||
let ty = cx.reveal_opaque_ty(pat.ty);
|
||||
let ctor;
|
||||
let fields: &[_];
|
||||
let mut fields: Vec<_>;
|
||||
match &pat.kind {
|
||||
PatKind::AscribeUserType { subpattern, .. }
|
||||
| PatKind::InlineConstant { subpattern, .. } => return self.lower_pat(subpattern),
|
||||
PatKind::Binding { subpattern: Some(subpat), .. } => return self.lower_pat(subpat),
|
||||
PatKind::Binding { subpattern: None, .. } | PatKind::Wild => {
|
||||
ctor = Wildcard;
|
||||
fields = &[];
|
||||
fields = vec![];
|
||||
}
|
||||
PatKind::Deref { subpattern } => {
|
||||
fields = singleton(self.lower_pat(subpattern));
|
||||
fields = vec![self.lower_pat(subpattern)];
|
||||
ctor = match ty.kind() {
|
||||
// This is a box pattern.
|
||||
ty::Adt(adt, ..) if adt.is_box() => Struct,
|
||||
|
@ -485,15 +480,14 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
|
|||
match ty.kind() {
|
||||
ty::Tuple(fs) => {
|
||||
ctor = Struct;
|
||||
let mut wilds: SmallVec<[_; 2]> = fs
|
||||
fields = fs
|
||||
.iter()
|
||||
.map(|ty| cx.reveal_opaque_ty(ty))
|
||||
.map(|ty| DeconstructedPat::wildcard(ty))
|
||||
.collect();
|
||||
for pat in subpatterns {
|
||||
wilds[pat.field.index()] = self.lower_pat(&pat.pattern);
|
||||
fields[pat.field.index()] = self.lower_pat(&pat.pattern);
|
||||
}
|
||||
fields = cx.pattern_arena.alloc_from_iter(wilds);
|
||||
}
|
||||
ty::Adt(adt, args) if adt.is_box() => {
|
||||
// The only legal patterns of type `Box` (outside `std`) are `_` and box
|
||||
|
@ -515,7 +509,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
|
|||
DeconstructedPat::wildcard(self.reveal_opaque_ty(args.type_at(0)))
|
||||
};
|
||||
ctor = Struct;
|
||||
fields = singleton(pat);
|
||||
fields = vec![pat];
|
||||
}
|
||||
ty::Adt(adt, _) => {
|
||||
ctor = match pat.kind {
|
||||
|
@ -535,14 +529,12 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
|
|||
ty
|
||||
},
|
||||
);
|
||||
let mut wilds: SmallVec<[_; 2]> =
|
||||
tys.map(|ty| DeconstructedPat::wildcard(ty)).collect();
|
||||
fields = tys.map(|ty| DeconstructedPat::wildcard(ty)).collect();
|
||||
for pat in subpatterns {
|
||||
if let Some(i) = field_id_to_id[pat.field.index()] {
|
||||
wilds[i] = self.lower_pat(&pat.pattern);
|
||||
fields[i] = self.lower_pat(&pat.pattern);
|
||||
}
|
||||
}
|
||||
fields = cx.pattern_arena.alloc_from_iter(wilds);
|
||||
}
|
||||
_ => bug!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, ty),
|
||||
}
|
||||
|
@ -554,7 +546,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
|
|||
Some(b) => Bool(b),
|
||||
None => Opaque(OpaqueId::new()),
|
||||
};
|
||||
fields = &[];
|
||||
fields = vec![];
|
||||
}
|
||||
ty::Char | ty::Int(_) | ty::Uint(_) => {
|
||||
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
|
||||
|
@ -570,7 +562,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
|
|||
}
|
||||
None => Opaque(OpaqueId::new()),
|
||||
};
|
||||
fields = &[];
|
||||
fields = vec![];
|
||||
}
|
||||
ty::Float(ty::FloatTy::F32) => {
|
||||
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
|
||||
|
@ -581,7 +573,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
|
|||
}
|
||||
None => Opaque(OpaqueId::new()),
|
||||
};
|
||||
fields = &[];
|
||||
fields = vec![];
|
||||
}
|
||||
ty::Float(ty::FloatTy::F64) => {
|
||||
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
|
||||
|
@ -592,7 +584,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
|
|||
}
|
||||
None => Opaque(OpaqueId::new()),
|
||||
};
|
||||
fields = &[];
|
||||
fields = vec![];
|
||||
}
|
||||
ty::Ref(_, t, _) if t.is_str() => {
|
||||
// We want a `&str` constant to behave like a `Deref` pattern, to be compatible
|
||||
|
@ -603,16 +595,16 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
|
|||
// subfields.
|
||||
// Note: `t` is `str`, not `&str`.
|
||||
let ty = self.reveal_opaque_ty(*t);
|
||||
let subpattern = DeconstructedPat::new(Str(*value), &[], ty, pat);
|
||||
let subpattern = DeconstructedPat::new(Str(*value), Vec::new(), ty, pat);
|
||||
ctor = Ref;
|
||||
fields = singleton(subpattern)
|
||||
fields = vec![subpattern]
|
||||
}
|
||||
// All constants that can be structurally matched have already been expanded
|
||||
// into the corresponding `Pat`s by `const_to_pat`. Constants that remain are
|
||||
// opaque.
|
||||
_ => {
|
||||
ctor = Opaque(OpaqueId::new());
|
||||
fields = &[];
|
||||
fields = vec![];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -649,7 +641,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
|
|||
}
|
||||
_ => bug!("invalid type for range pattern: {}", ty.inner()),
|
||||
};
|
||||
fields = &[];
|
||||
fields = vec![];
|
||||
}
|
||||
PatKind::Array { prefix, slice, suffix } | PatKind::Slice { prefix, slice, suffix } => {
|
||||
let array_len = match ty.kind() {
|
||||
|
@ -665,26 +657,23 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
|
|||
SliceKind::FixedLen(prefix.len() + suffix.len())
|
||||
};
|
||||
ctor = Slice(Slice::new(array_len, kind));
|
||||
fields = cx.pattern_arena.alloc_from_iter(
|
||||
prefix.iter().chain(suffix.iter()).map(|p| self.lower_pat(&*p)),
|
||||
)
|
||||
fields = prefix.iter().chain(suffix.iter()).map(|p| self.lower_pat(&*p)).collect();
|
||||
}
|
||||
PatKind::Or { .. } => {
|
||||
ctor = Or;
|
||||
let pats = expand_or_pat(pat);
|
||||
fields =
|
||||
cx.pattern_arena.alloc_from_iter(pats.into_iter().map(|p| self.lower_pat(p)))
|
||||
fields = pats.into_iter().map(|p| self.lower_pat(p)).collect();
|
||||
}
|
||||
PatKind::Never => {
|
||||
// A never pattern matches all the values of its type (namely none). Moreover it
|
||||
// must be compatible with other constructors, since we can use `!` on a type like
|
||||
// `Result<!, !>` which has other constructors. Hence we lower it as a wildcard.
|
||||
ctor = Wildcard;
|
||||
fields = &[];
|
||||
fields = vec![];
|
||||
}
|
||||
PatKind::Error(_) => {
|
||||
ctor = Opaque(OpaqueId::new());
|
||||
fields = &[];
|
||||
fields = vec![];
|
||||
}
|
||||
}
|
||||
DeconstructedPat::new(ctor, fields, ty, pat)
|
||||
|
@ -855,7 +844,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
|
||||
impl<'p, 'tcx: 'p> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
|
||||
type Ty = RevealedTy<'tcx>;
|
||||
type Error = ErrorGuaranteed;
|
||||
type VariantIdx = VariantIdx;
|
||||
|
@ -889,7 +878,7 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
|
|||
|
||||
fn write_variant_name(
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
pat: &crate::pat::DeconstructedPat<'_, Self>,
|
||||
pat: &crate::pat::DeconstructedPat<Self>,
|
||||
) -> fmt::Result {
|
||||
if let ty::Adt(adt, _) = pat.ty().kind() {
|
||||
if adt.is_box() {
|
||||
|
@ -908,9 +897,9 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
|
|||
|
||||
fn lint_overlapping_range_endpoints(
|
||||
&self,
|
||||
pat: &crate::pat::DeconstructedPat<'_, Self>,
|
||||
pat: &crate::pat::DeconstructedPat<Self>,
|
||||
overlaps_on: IntRange,
|
||||
overlaps_with: &[&crate::pat::DeconstructedPat<'_, Self>],
|
||||
overlaps_with: &[&crate::pat::DeconstructedPat<Self>],
|
||||
) {
|
||||
let overlap_as_pat = self.hoist_pat_range(&overlaps_on, *pat.ty());
|
||||
let overlaps: Vec<_> = overlaps_with
|
||||
|
|
|
@ -848,7 +848,7 @@ impl<'p, Cx: TypeCx> Clone for PatStack<'p, Cx> {
|
|||
}
|
||||
|
||||
impl<'p, Cx: TypeCx> PatStack<'p, Cx> {
|
||||
fn from_pattern(pat: &'p DeconstructedPat<'p, Cx>) -> Self {
|
||||
fn from_pattern(pat: &'p DeconstructedPat<Cx>) -> Self {
|
||||
PatStack { pats: smallvec![PatOrWild::Pat(pat)], relevant: true }
|
||||
}
|
||||
|
||||
|
@ -1575,7 +1575,7 @@ pub enum Usefulness<'p, Cx: TypeCx> {
|
|||
/// The arm is useful. This additionally carries a set of or-pattern branches that have been
|
||||
/// found to be redundant despite the overall arm being useful. Used only in the presence of
|
||||
/// or-patterns, otherwise it stays empty.
|
||||
Useful(Vec<&'p DeconstructedPat<'p, Cx>>),
|
||||
Useful(Vec<&'p DeconstructedPat<Cx>>),
|
||||
/// The arm is redundant and can be removed without changing the behavior of the match
|
||||
/// expression.
|
||||
Redundant,
|
||||
|
|
|
@ -118,17 +118,27 @@ resolve_forward_declared_generic_param =
|
|||
.label = defaulted generic parameters cannot be forward declared
|
||||
|
||||
resolve_generic_params_from_outer_item =
|
||||
can't use generic parameters from outer item
|
||||
.label = use of generic parameter from outer item
|
||||
can't use {$is_self ->
|
||||
[true] `Self`
|
||||
*[false] generic parameters
|
||||
} from outer item
|
||||
.label = use of {$is_self ->
|
||||
[true] `Self`
|
||||
*[false] generic parameter
|
||||
} from outer item
|
||||
.refer_to_type_directly = refer to the type directly here instead
|
||||
.suggestion = try introducing a local generic parameter here
|
||||
|
||||
resolve_generic_params_from_outer_item_const = a `const` is a separate item from the item that contains it
|
||||
|
||||
resolve_generic_params_from_outer_item_const_param = const parameter from outer item
|
||||
|
||||
resolve_generic_params_from_outer_item_self_ty_alias = `Self` type implicitly declared here, by this `impl`
|
||||
|
||||
resolve_generic_params_from_outer_item_self_ty_param = can't use `Self` here
|
||||
|
||||
resolve_generic_params_from_outer_item_static = a `static` is a separate item from the item that contains it
|
||||
|
||||
resolve_generic_params_from_outer_item_ty_param = type parameter from outer item
|
||||
|
||||
|
||||
|
|
|
@ -561,13 +561,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
resolution_error: ResolutionError<'a>,
|
||||
) -> DiagnosticBuilder<'_> {
|
||||
match resolution_error {
|
||||
ResolutionError::GenericParamsFromOuterItem(outer_res, has_generic_params) => {
|
||||
ResolutionError::GenericParamsFromOuterItem(outer_res, has_generic_params, def_kind) => {
|
||||
use errs::GenericParamsFromOuterItemLabel as Label;
|
||||
let static_or_const = match def_kind {
|
||||
DefKind::Static(_) => Some(errs::GenericParamsFromOuterItemStaticOrConst::Static),
|
||||
DefKind::Const => Some(errs::GenericParamsFromOuterItemStaticOrConst::Const),
|
||||
_ => None,
|
||||
};
|
||||
let is_self = matches!(outer_res, Res::SelfTyParam { .. } | Res::SelfTyAlias { .. });
|
||||
let mut err = errs::GenericParamsFromOuterItem {
|
||||
span,
|
||||
label: None,
|
||||
refer_to_type_directly: None,
|
||||
sugg: None,
|
||||
static_or_const,
|
||||
is_self,
|
||||
};
|
||||
|
||||
let sm = self.tcx.sess.source_map();
|
||||
|
|
|
@ -45,6 +45,17 @@ pub(crate) struct GenericParamsFromOuterItem {
|
|||
pub(crate) refer_to_type_directly: Option<Span>,
|
||||
#[subdiagnostic]
|
||||
pub(crate) sugg: Option<GenericParamsFromOuterItemSugg>,
|
||||
#[subdiagnostic]
|
||||
pub(crate) static_or_const: Option<GenericParamsFromOuterItemStaticOrConst>,
|
||||
pub(crate) is_self: bool,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum GenericParamsFromOuterItemStaticOrConst {
|
||||
#[note(resolve_generic_params_from_outer_item_static)]
|
||||
Static,
|
||||
#[note(resolve_generic_params_from_outer_item_const)]
|
||||
Const,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
|
|
|
@ -10,9 +10,7 @@ use rustc_span::symbol::{kw, Ident};
|
|||
use rustc_span::Span;
|
||||
|
||||
use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst};
|
||||
use crate::late::{
|
||||
ConstantHasGenerics, HasGenericParams, NoConstantGenericsReason, PathSource, Rib, RibKind,
|
||||
};
|
||||
use crate::late::{ConstantHasGenerics, NoConstantGenericsReason, PathSource, Rib, RibKind};
|
||||
use crate::macros::{sub_namespace_match, MacroRulesScope};
|
||||
use crate::BindingKey;
|
||||
use crate::{errors, AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy, Finalize};
|
||||
|
@ -1090,7 +1088,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
| RibKind::ForwardGenericParamBan => {
|
||||
// Nothing to do. Continue.
|
||||
}
|
||||
RibKind::Item(_) | RibKind::AssocItem => {
|
||||
RibKind::Item(..) | RibKind::AssocItem => {
|
||||
// This was an attempt to access an upvar inside a
|
||||
// named function item. This is not allowed, so we
|
||||
// report an error.
|
||||
|
@ -1155,7 +1153,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
}
|
||||
Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => {
|
||||
for rib in ribs {
|
||||
let has_generic_params: HasGenericParams = match rib.kind {
|
||||
let (has_generic_params, def_kind) = match rib.kind {
|
||||
RibKind::Normal
|
||||
| RibKind::FnOrCoroutine
|
||||
| RibKind::Module(..)
|
||||
|
@ -1213,7 +1211,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
}
|
||||
|
||||
// This was an attempt to use a type parameter outside its scope.
|
||||
RibKind::Item(has_generic_params) => has_generic_params,
|
||||
RibKind::Item(has_generic_params, def_kind) => {
|
||||
(has_generic_params, def_kind)
|
||||
}
|
||||
RibKind::ConstParamTy => {
|
||||
if let Some(span) = finalize {
|
||||
self.report_error(
|
||||
|
@ -1231,7 +1231,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
if let Some(span) = finalize {
|
||||
self.report_error(
|
||||
span,
|
||||
ResolutionError::GenericParamsFromOuterItem(res, has_generic_params),
|
||||
ResolutionError::GenericParamsFromOuterItem(
|
||||
res,
|
||||
has_generic_params,
|
||||
def_kind,
|
||||
),
|
||||
);
|
||||
}
|
||||
return Res::Err;
|
||||
|
@ -1239,7 +1243,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
}
|
||||
Res::Def(DefKind::ConstParam, _) => {
|
||||
for rib in ribs {
|
||||
let has_generic_params = match rib.kind {
|
||||
let (has_generic_params, def_kind) = match rib.kind {
|
||||
RibKind::Normal
|
||||
| RibKind::FnOrCoroutine
|
||||
| RibKind::Module(..)
|
||||
|
@ -1276,7 +1280,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
continue;
|
||||
}
|
||||
|
||||
RibKind::Item(has_generic_params) => has_generic_params,
|
||||
RibKind::Item(has_generic_params, def_kind) => {
|
||||
(has_generic_params, def_kind)
|
||||
}
|
||||
RibKind::ConstParamTy => {
|
||||
if let Some(span) = finalize {
|
||||
self.report_error(
|
||||
|
@ -1295,7 +1301,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
if let Some(span) = finalize {
|
||||
self.report_error(
|
||||
span,
|
||||
ResolutionError::GenericParamsFromOuterItem(res, has_generic_params),
|
||||
ResolutionError::GenericParamsFromOuterItem(
|
||||
res,
|
||||
has_generic_params,
|
||||
def_kind,
|
||||
),
|
||||
);
|
||||
}
|
||||
return Res::Err;
|
||||
|
|
|
@ -185,7 +185,7 @@ pub(crate) enum RibKind<'a> {
|
|||
FnOrCoroutine,
|
||||
|
||||
/// We passed through an item scope. Disallow upvars.
|
||||
Item(HasGenericParams),
|
||||
Item(HasGenericParams, DefKind),
|
||||
|
||||
/// We're in a constant item. Can't refer to dynamic stuff.
|
||||
///
|
||||
|
@ -225,7 +225,7 @@ impl RibKind<'_> {
|
|||
| RibKind::MacroDefinition(_)
|
||||
| RibKind::ConstParamTy
|
||||
| RibKind::InlineAsmSym => false,
|
||||
RibKind::AssocItem | RibKind::Item(_) | RibKind::ForwardGenericParamBan => true,
|
||||
RibKind::AssocItem | RibKind::Item(..) | RibKind::ForwardGenericParamBan => true,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -869,11 +869,12 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
|
|||
}
|
||||
fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
|
||||
self.resolve_doc_links(&foreign_item.attrs, MaybeExported::Ok(foreign_item.id));
|
||||
let def_kind = self.r.local_def_kind(foreign_item.id);
|
||||
match foreign_item.kind {
|
||||
ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
|
||||
self.with_generic_param_rib(
|
||||
&generics.params,
|
||||
RibKind::Item(HasGenericParams::Yes(generics.span)),
|
||||
RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
|
||||
LifetimeRibKind::Generics {
|
||||
binder: foreign_item.id,
|
||||
kind: LifetimeBinderKind::Item,
|
||||
|
@ -885,7 +886,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
|
|||
ForeignItemKind::Fn(box Fn { ref generics, .. }) => {
|
||||
self.with_generic_param_rib(
|
||||
&generics.params,
|
||||
RibKind::Item(HasGenericParams::Yes(generics.span)),
|
||||
RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
|
||||
LifetimeRibKind::Generics {
|
||||
binder: foreign_item.id,
|
||||
kind: LifetimeBinderKind::Function,
|
||||
|
@ -895,7 +896,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
|
|||
);
|
||||
}
|
||||
ForeignItemKind::Static(..) => {
|
||||
self.with_static_rib(|this| {
|
||||
self.with_static_rib(def_kind, |this| {
|
||||
visit::walk_foreign_item(this, foreign_item);
|
||||
});
|
||||
}
|
||||
|
@ -2266,10 +2267,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
|
||||
fn resolve_adt(&mut self, item: &'ast Item, generics: &'ast Generics) {
|
||||
debug!("resolve_adt");
|
||||
let kind = self.r.local_def_kind(item.id);
|
||||
self.with_current_self_item(item, |this| {
|
||||
this.with_generic_param_rib(
|
||||
&generics.params,
|
||||
RibKind::Item(HasGenericParams::Yes(generics.span)),
|
||||
RibKind::Item(HasGenericParams::Yes(generics.span), kind),
|
||||
LifetimeRibKind::Generics {
|
||||
binder: item.id,
|
||||
kind: LifetimeBinderKind::Item,
|
||||
|
@ -2343,11 +2345,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
let name = item.ident.name;
|
||||
debug!("(resolving item) resolving {} ({:?})", name, item.kind);
|
||||
|
||||
let def_kind = self.r.local_def_kind(item.id);
|
||||
match item.kind {
|
||||
ItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
|
||||
self.with_generic_param_rib(
|
||||
&generics.params,
|
||||
RibKind::Item(HasGenericParams::Yes(generics.span)),
|
||||
RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
|
||||
LifetimeRibKind::Generics {
|
||||
binder: item.id,
|
||||
kind: LifetimeBinderKind::Item,
|
||||
|
@ -2360,7 +2363,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
ItemKind::Fn(box Fn { ref generics, .. }) => {
|
||||
self.with_generic_param_rib(
|
||||
&generics.params,
|
||||
RibKind::Item(HasGenericParams::Yes(generics.span)),
|
||||
RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
|
||||
LifetimeRibKind::Generics {
|
||||
binder: item.id,
|
||||
kind: LifetimeBinderKind::Function,
|
||||
|
@ -2399,7 +2402,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
// Create a new rib for the trait-wide type parameters.
|
||||
self.with_generic_param_rib(
|
||||
&generics.params,
|
||||
RibKind::Item(HasGenericParams::Yes(generics.span)),
|
||||
RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
|
||||
LifetimeRibKind::Generics {
|
||||
binder: item.id,
|
||||
kind: LifetimeBinderKind::Item,
|
||||
|
@ -2420,7 +2423,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
// Create a new rib for the trait-wide type parameters.
|
||||
self.with_generic_param_rib(
|
||||
&generics.params,
|
||||
RibKind::Item(HasGenericParams::Yes(generics.span)),
|
||||
RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
|
||||
LifetimeRibKind::Generics {
|
||||
binder: item.id,
|
||||
kind: LifetimeBinderKind::Item,
|
||||
|
@ -2454,7 +2457,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
}
|
||||
|
||||
ItemKind::Static(box ast::StaticItem { ref ty, ref expr, .. }) => {
|
||||
self.with_static_rib(|this| {
|
||||
self.with_static_rib(def_kind, |this| {
|
||||
this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| {
|
||||
this.visit_ty(ty);
|
||||
});
|
||||
|
@ -2469,11 +2472,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
ItemKind::Const(box ast::ConstItem { ref generics, ref ty, ref expr, .. }) => {
|
||||
self.with_generic_param_rib(
|
||||
&generics.params,
|
||||
RibKind::Item(if self.r.tcx.features().generic_const_items {
|
||||
HasGenericParams::Yes(generics.span)
|
||||
} else {
|
||||
HasGenericParams::No
|
||||
}),
|
||||
RibKind::Item(
|
||||
if self.r.tcx.features().generic_const_items {
|
||||
HasGenericParams::Yes(generics.span)
|
||||
} else {
|
||||
HasGenericParams::No
|
||||
},
|
||||
def_kind,
|
||||
),
|
||||
LifetimeRibKind::Generics {
|
||||
binder: item.id,
|
||||
kind: LifetimeBinderKind::ConstItem,
|
||||
|
@ -2558,7 +2564,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
let mut add_bindings_for_ns = |ns| {
|
||||
let parent_rib = self.ribs[ns]
|
||||
.iter()
|
||||
.rfind(|r| matches!(r.kind, RibKind::Item(_)))
|
||||
.rfind(|r| matches!(r.kind, RibKind::Item(..)))
|
||||
.expect("associated item outside of an item");
|
||||
seen_bindings.extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span)));
|
||||
};
|
||||
|
@ -2693,8 +2699,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
self.label_ribs.pop();
|
||||
}
|
||||
|
||||
fn with_static_rib(&mut self, f: impl FnOnce(&mut Self)) {
|
||||
let kind = RibKind::Item(HasGenericParams::No);
|
||||
fn with_static_rib(&mut self, def_kind: DefKind, f: impl FnOnce(&mut Self)) {
|
||||
let kind = RibKind::Item(HasGenericParams::No, def_kind);
|
||||
self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
|
||||
}
|
||||
|
||||
|
@ -2875,7 +2881,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
// If applicable, create a rib for the type parameters.
|
||||
self.with_generic_param_rib(
|
||||
&generics.params,
|
||||
RibKind::Item(HasGenericParams::Yes(generics.span)),
|
||||
RibKind::Item(HasGenericParams::Yes(generics.span), self.r.local_def_kind(item_id)),
|
||||
LifetimeRibKind::Generics {
|
||||
span: generics.span,
|
||||
binder: item_id,
|
||||
|
|
|
@ -184,7 +184,7 @@ struct BindingError {
|
|||
#[derive(Debug)]
|
||||
enum ResolutionError<'a> {
|
||||
/// Error E0401: can't use type or const parameters from outer item.
|
||||
GenericParamsFromOuterItem(Res, HasGenericParams),
|
||||
GenericParamsFromOuterItem(Res, HasGenericParams, DefKind),
|
||||
/// Error E0403: the name is already used for a type or const parameter in this generic
|
||||
/// parameter list.
|
||||
NameAlreadyUsedInParameterList(Symbol, Span),
|
||||
|
@ -1217,6 +1217,10 @@ impl<'tcx> Resolver<'_, 'tcx> {
|
|||
self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`"))
|
||||
}
|
||||
|
||||
fn local_def_kind(&self, node: NodeId) -> DefKind {
|
||||
self.tcx.def_kind(self.local_def_id(node))
|
||||
}
|
||||
|
||||
/// Adds a definition with a parent definition.
|
||||
fn create_def(
|
||||
&mut self,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||
use rustc_infer::infer::{InferCtxt, RegionResolutionError};
|
||||
use rustc_middle::traits::query::NoSolution;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
|
||||
pub trait InferCtxtRegionExt<'tcx> {
|
||||
|
@ -31,7 +32,7 @@ impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> {
|
|||
),
|
||||
ty,
|
||||
)
|
||||
.map_err(|_| ty)
|
||||
.map_err(|_| NoSolution)
|
||||
} else {
|
||||
Ok(ty)
|
||||
}
|
||||
|
|
|
@ -179,7 +179,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
|||
}
|
||||
|
||||
let outlives_env = OutlivesEnvironment::new(full_env);
|
||||
let _ = infcx.process_registered_region_obligations::<!>(&outlives_env, |ty, _| Ok(ty));
|
||||
let _ = infcx.process_registered_region_obligations(&outlives_env, |ty, _| Ok(ty));
|
||||
|
||||
let region_data =
|
||||
infcx.inner.borrow_mut().unwrap_region_constraints().region_constraint_data().clone();
|
||||
|
|
|
@ -14,7 +14,7 @@ use std::path::{Path, PathBuf};
|
|||
// #73494.
|
||||
const ENTRY_LIMIT: usize = 900;
|
||||
const ISSUES_ENTRY_LIMIT: usize = 1807;
|
||||
const ROOT_ENTRY_LIMIT: usize = 870;
|
||||
const ROOT_ENTRY_LIMIT: usize = 868;
|
||||
|
||||
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
|
||||
"rs", // test source files
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
// compile-flags: -C no-prepopulate-passes
|
||||
#![crate_type = "lib"]
|
||||
#![feature(ffi_returns_twice)]
|
||||
|
||||
pub fn bar() { unsafe { foo() } }
|
||||
|
||||
extern "C" {
|
||||
// CHECK: declare{{( dso_local)?}} void @foo(){{.*}}[[ATTRS:#[0-9]+]]
|
||||
// CHECK: attributes [[ATTRS]] = { {{.*}}returns_twice{{.*}} }
|
||||
#[ffi_returns_twice] pub fn foo();
|
||||
}
|
7
tests/ui/async-await/in-trait/auxiliary/bad-region.rs
Normal file
7
tests/ui/async-await/in-trait/auxiliary/bad-region.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
// edition:2021
|
||||
|
||||
#[allow(async_fn_in_trait)]
|
||||
|
||||
pub trait BleRadio<'a> {
|
||||
async fn transmit(&mut self);
|
||||
}
|
17
tests/ui/async-await/in-trait/bad-region.rs
Normal file
17
tests/ui/async-await/in-trait/bad-region.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
// aux-build:bad-region.rs
|
||||
// edition:2021
|
||||
|
||||
#![allow(async_fn_in_trait)]
|
||||
|
||||
extern crate bad_region as jewel;
|
||||
|
||||
use jewel::BleRadio;
|
||||
|
||||
pub struct Radio {}
|
||||
|
||||
impl BleRadio for Radio {
|
||||
//~^ ERROR implicit elided lifetime not allowed here
|
||||
async fn transmit(&mut self) {}
|
||||
}
|
||||
|
||||
fn main() {}
|
14
tests/ui/async-await/in-trait/bad-region.stderr
Normal file
14
tests/ui/async-await/in-trait/bad-region.stderr
Normal file
|
@ -0,0 +1,14 @@
|
|||
error[E0726]: implicit elided lifetime not allowed here
|
||||
--> $DIR/bad-region.rs:12:6
|
||||
|
|
||||
LL | impl BleRadio for Radio {
|
||||
| ^^^^^^^^ expected lifetime parameter
|
||||
|
|
||||
help: indicate the anonymous lifetime
|
||||
|
|
||||
LL | impl BleRadio<'_> for Radio {
|
||||
| ++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0726`.
|
|
@ -12,6 +12,9 @@ LL | let _z = y.clone();
|
|||
which is required by `Box<dyn Foo>: Clone`
|
||||
`dyn Foo: Clone`
|
||||
which is required by `Box<dyn Foo>: Clone`
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
= note: the following trait defines an item `clone`, perhaps you need to implement it:
|
||||
candidate #1: `Clone`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -10,9 +10,6 @@ LL | let _j = i.clone();
|
|||
= note: the following trait bounds were not satisfied:
|
||||
`R: Clone`
|
||||
which is required by `Box<R>: Clone`
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
= note: the following trait defines an item `clone`, perhaps you need to implement it:
|
||||
candidate #1: `Clone`
|
||||
help: consider annotating `R` with `#[derive(Clone)]`
|
||||
|
|
||||
LL + #[derive(Clone)]
|
||||
|
|
12
tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs
Normal file
12
tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
// #120427
|
||||
// This test checks we won't suggest more than 3 span suggestions for cfg names
|
||||
//
|
||||
// check-pass
|
||||
// compile-flags: -Z unstable-options
|
||||
// compile-flags: --check-cfg=cfg(foo,values("value")) --check-cfg=cfg(bar,values("value")) --check-cfg=cfg(bee,values("value")) --check-cfg=cfg(cow,values("value"))
|
||||
|
||||
#[cfg(value)]
|
||||
//~^ WARNING unexpected `cfg` condition name: `value`
|
||||
fn x() {}
|
||||
|
||||
fn main() {}
|
13
tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr
Normal file
13
tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr
Normal file
|
@ -0,0 +1,13 @@
|
|||
warning: unexpected `cfg` condition name: `value`
|
||||
--> $DIR/cfg-value-for-cfg-name-duplicate.rs:8:7
|
||||
|
|
||||
LL | #[cfg(value)]
|
||||
| ^^^^^
|
||||
|
|
||||
= help: expected names are: `bar`, `bee`, `cow`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
|
||||
= help: to expect this configuration use `--check-cfg=cfg(value)`
|
||||
= note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
12
tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs
Normal file
12
tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
// #120427
|
||||
// This test checks that when a single cfg has a value for user's specified name
|
||||
//
|
||||
// check-pass
|
||||
// compile-flags: -Z unstable-options
|
||||
// compile-flags: --check-cfg=cfg(foo,values("my_value")) --check-cfg=cfg(bar,values("my_value"))
|
||||
|
||||
#[cfg(my_value)]
|
||||
//~^ WARNING unexpected `cfg` condition name: `my_value`
|
||||
fn x() {}
|
||||
|
||||
fn main() {}
|
21
tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr
Normal file
21
tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr
Normal file
|
@ -0,0 +1,21 @@
|
|||
warning: unexpected `cfg` condition name: `my_value`
|
||||
--> $DIR/cfg-value-for-cfg-name-multiple.rs:8:7
|
||||
|
|
||||
LL | #[cfg(my_value)]
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= help: expected names are: `bar`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
|
||||
= help: to expect this configuration use `--check-cfg=cfg(my_value)`
|
||||
= note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
help: found config with similar value
|
||||
|
|
||||
LL | #[cfg(foo = "my_value")]
|
||||
| ~~~~~~~~~~~~~~~~
|
||||
help: found config with similar value
|
||||
|
|
||||
LL | #[cfg(bar = "my_value")]
|
||||
| ~~~~~~~~~~~~~~~~
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
18
tests/ui/check-cfg/cfg-value-for-cfg-name.rs
Normal file
18
tests/ui/check-cfg/cfg-value-for-cfg-name.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
// #120427
|
||||
// This test checks that when a single cfg has a value for user's specified name
|
||||
// suggest to use `#[cfg(target_os = "linux")]` instead of `#[cfg(linux)]`
|
||||
//
|
||||
// check-pass
|
||||
// compile-flags: -Z unstable-options
|
||||
// compile-flags: --check-cfg=cfg()
|
||||
|
||||
#[cfg(linux)]
|
||||
//~^ WARNING unexpected `cfg` condition name: `linux`
|
||||
fn x() {}
|
||||
|
||||
// will not suggest if the cfg has a value
|
||||
#[cfg(linux = "os-name")]
|
||||
//~^ WARNING unexpected `cfg` condition name: `linux`
|
||||
fn y() {}
|
||||
|
||||
fn main() {}
|
22
tests/ui/check-cfg/cfg-value-for-cfg-name.stderr
Normal file
22
tests/ui/check-cfg/cfg-value-for-cfg-name.stderr
Normal file
|
@ -0,0 +1,22 @@
|
|||
warning: unexpected `cfg` condition name: `linux`
|
||||
--> $DIR/cfg-value-for-cfg-name.rs:9:7
|
||||
|
|
||||
LL | #[cfg(linux)]
|
||||
| ^^^^^ help: found config with similar value: `target_os = "linux"`
|
||||
|
|
||||
= help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
|
||||
= help: to expect this configuration use `--check-cfg=cfg(linux)`
|
||||
= note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: unexpected `cfg` condition name: `linux`
|
||||
--> $DIR/cfg-value-for-cfg-name.rs:14:7
|
||||
|
|
||||
LL | #[cfg(linux = "os-name")]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: to expect this configuration use `--check-cfg=cfg(linux, values("os-name"))`
|
||||
= note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
|
@ -5,8 +5,19 @@ LL | NUMBER_POINTER => (),
|
|||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
Future incompatibility report: Future breakage diagnostic:
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/match-edge-cases_1.rs:29:13
|
||||
|
|
||||
LL | NUMBER_POINTER => (),
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
|
|
|
@ -63,4 +63,18 @@ fn main() {
|
|||
|
||||
const ADDR_OF: &OND = &None;
|
||||
match &None { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), };
|
||||
|
||||
// These ones are more subtle: the final value is fine, but statically analyzing the expression
|
||||
// that computes the value would likely (incorrectly) have us conclude that this may match on
|
||||
// values that do not have structural equality.
|
||||
const INDEX: Option<NoDerive> = [None, Some(NoDerive(10))][0];
|
||||
match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), };
|
||||
|
||||
const fn build() -> Option<NoDerive> { None }
|
||||
const CALL: Option<NoDerive> = build();
|
||||
match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), };
|
||||
|
||||
impl NoDerive { const fn none() -> Option<NoDerive> { None } }
|
||||
const METHOD_CALL: Option<NoDerive> = NoDerive::none();
|
||||
match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), };
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ impl PartialEq for CustomEq {
|
|||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
#[allow(unused)]
|
||||
enum Foo {
|
||||
Bar,
|
||||
Baz,
|
||||
|
@ -21,7 +22,7 @@ enum Foo {
|
|||
const BAR_BAZ: Foo = if 42 == 42 {
|
||||
Foo::Bar
|
||||
} else {
|
||||
Foo::Baz
|
||||
Foo::Qux(CustomEq) // dead arm
|
||||
};
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
// check-pass
|
||||
|
||||
struct CustomEq;
|
||||
|
||||
impl Eq for CustomEq {}
|
||||
impl PartialEq for CustomEq {
|
||||
fn eq(&self, _: &Self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
enum Foo {
|
||||
Bar,
|
||||
Baz,
|
||||
Qux(CustomEq),
|
||||
}
|
||||
|
||||
// We know that `BAR_BAZ` will always be `Foo::Bar` and thus eligible for structural matching, but
|
||||
// dataflow will be more conservative.
|
||||
const BAR_BAZ: Foo = if 42 == 42 {
|
||||
Foo::Bar
|
||||
} else {
|
||||
Foo::Qux(CustomEq)
|
||||
};
|
||||
|
||||
fn main() {
|
||||
match Foo::Qux(CustomEq) {
|
||||
BAR_BAZ => panic!(),
|
||||
//~^ WARN must be annotated with `#[derive(PartialEq)]`
|
||||
//~| NOTE the traits must be derived
|
||||
//~| NOTE StructuralPartialEq.html for details
|
||||
//~| WARN this was previously accepted
|
||||
//~| NOTE see issue #73448
|
||||
//~| NOTE `#[warn(nontrivial_structural_match)]` on by default
|
||||
_ => {}
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
warning: to use a constant of type `CustomEq` in a pattern, the constant's initializer must be trivial or `CustomEq` must be annotated with `#[derive(PartialEq)]`
|
||||
--> $DIR/custom-eq-branch-warn.rs:29:9
|
||||
|
|
||||
LL | BAR_BAZ => panic!(),
|
||||
| ^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #73448 <https://github.com/rust-lang/rust/issues/73448>
|
||||
= note: the traits must be derived, manual `impl`s are not sufficient
|
||||
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
|
||||
= note: `#[warn(nontrivial_structural_match)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
|
@ -5,7 +5,7 @@ LL | C => {}
|
|||
| ^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
note: the lint level is defined here
|
||||
--> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9
|
||||
|
|
||||
|
@ -19,7 +19,7 @@ LL | C_INNER => {}
|
|||
| ^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
|
||||
error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:30:9
|
||||
|
@ -28,7 +28,7 @@ LL | D => {}
|
|||
| ^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
|
||||
error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:36:9
|
||||
|
@ -37,7 +37,67 @@ LL | STR => {}
|
|||
| ^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Future incompatibility report: Future breakage diagnostic:
|
||||
error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:10:9
|
||||
|
|
||||
LL | C => {}
|
||||
| ^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
note: the lint level is defined here
|
||||
--> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9
|
||||
|
|
||||
LL | #![deny(pointer_structural_match)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Future breakage diagnostic:
|
||||
error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:18:9
|
||||
|
|
||||
LL | C_INNER => {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
note: the lint level is defined here
|
||||
--> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9
|
||||
|
|
||||
LL | #![deny(pointer_structural_match)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Future breakage diagnostic:
|
||||
error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:30:9
|
||||
|
|
||||
LL | D => {}
|
||||
| ^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
note: the lint level is defined here
|
||||
--> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9
|
||||
|
|
||||
LL | #![deny(pointer_structural_match)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Future breakage diagnostic:
|
||||
error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:36:9
|
||||
|
|
||||
LL | STR => {}
|
||||
| ^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
note: the lint level is defined here
|
||||
--> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9
|
||||
|
|
||||
LL | #![deny(pointer_structural_match)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | FOO => println!("foo"),
|
|||
| ^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
note: the lint level is defined here
|
||||
--> $DIR/issue-44333.rs:3:9
|
||||
|
|
||||
|
@ -19,7 +19,37 @@ LL | BAR => println!("bar"),
|
|||
| ^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
||||
Future incompatibility report: Future breakage diagnostic:
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/issue-44333.rs:19:9
|
||||
|
|
||||
LL | FOO => println!("foo"),
|
||||
| ^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
note: the lint level is defined here
|
||||
--> $DIR/issue-44333.rs:3:9
|
||||
|
|
||||
LL | #![warn(pointer_structural_match)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Future breakage diagnostic:
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/issue-44333.rs:21:9
|
||||
|
|
||||
LL | BAR => println!("bar"),
|
||||
| ^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
note: the lint level is defined here
|
||||
--> $DIR/issue-44333.rs:3:9
|
||||
|
|
||||
LL | #![warn(pointer_structural_match)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
WARN rustc_mir_build::thir::pattern::const_to_pat MIR const-checker found novel structural match violation. See #73448.
|
|
@ -100,5 +100,5 @@ fn main() {
|
|||
//~| NOTE the traits must be derived
|
||||
//~| NOTE StructuralPartialEq.html for details
|
||||
//~| WARN previously accepted by the compiler but is being phased out
|
||||
//~| NOTE for more information, see issue #62411
|
||||
//~| NOTE for more information, see
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ LL | match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops")
|
|||
| ^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: the traits must be derived, manual `impl`s are not sufficient
|
||||
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
|
||||
note: the lint level is defined here
|
||||
|
@ -97,3 +97,20 @@ LL | #![warn(indirect_structural_match)]
|
|||
|
||||
error: aborting due to 9 previous errors; 1 warning emitted
|
||||
|
||||
Future incompatibility report: Future breakage diagnostic:
|
||||
warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
|
||||
--> $DIR/reject_non_structural.rs:98:29
|
||||
|
|
||||
LL | match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), };
|
||||
| ^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: the traits must be derived, manual `impl`s are not sufficient
|
||||
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
|
||||
note: the lint level is defined here
|
||||
--> $DIR/reject_non_structural.rs:14:9
|
||||
|
|
||||
LL | #![warn(indirect_structural_match)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
// run-pass
|
||||
|
||||
// This test is checking our logic for structural match checking by enumerating
|
||||
// the different kinds of const expressions. This test is collecting cases where
|
||||
// we have accepted the const expression as a pattern in the past but we want
|
||||
// to begin warning the user that a future version of Rust may start rejecting
|
||||
// such const expressions.
|
||||
|
||||
// The specific corner cases we are exploring here are instances where the
|
||||
// const-evaluator computes a value that *does* meet the conditions for
|
||||
// structural-match, but the const expression itself has abstractions (like
|
||||
// calls to const functions) that may fit better with a type-based analysis
|
||||
// rather than a commitment to a specific value.
|
||||
|
||||
#![warn(indirect_structural_match)]
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
struct NoDerive(#[allow(dead_code)] u32);
|
||||
|
||||
// This impl makes `NoDerive` irreflexive.
|
||||
impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
|
||||
impl Eq for NoDerive { }
|
||||
|
||||
fn main() {
|
||||
const INDEX: Option<NoDerive> = [None, Some(NoDerive(10))][0];
|
||||
match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), };
|
||||
//~^ WARN must be annotated with `#[derive(PartialEq)]`
|
||||
//~| WARN this was previously accepted
|
||||
|
||||
const fn build() -> Option<NoDerive> { None }
|
||||
const CALL: Option<NoDerive> = build();
|
||||
match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), };
|
||||
//~^ WARN must be annotated with `#[derive(PartialEq)]`
|
||||
//~| WARN this was previously accepted
|
||||
|
||||
impl NoDerive { const fn none() -> Option<NoDerive> { None } }
|
||||
const METHOD_CALL: Option<NoDerive> = NoDerive::none();
|
||||
match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), };
|
||||
//~^ WARN must be annotated with `#[derive(PartialEq)]`
|
||||
//~| WARN this was previously accepted
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
warning: to use a constant of type `NoDerive` in a pattern, the constant's initializer must be trivial or `NoDerive` must be annotated with `#[derive(PartialEq)]`
|
||||
--> $DIR/warn_corner_cases.rs:26:47
|
||||
|
|
||||
LL | match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), };
|
||||
| ^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #73448 <https://github.com/rust-lang/rust/issues/73448>
|
||||
= note: the traits must be derived, manual `impl`s are not sufficient
|
||||
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
|
||||
= note: `#[warn(nontrivial_structural_match)]` on by default
|
||||
|
||||
warning: to use a constant of type `NoDerive` in a pattern, the constant's initializer must be trivial or `NoDerive` must be annotated with `#[derive(PartialEq)]`
|
||||
--> $DIR/warn_corner_cases.rs:32:47
|
||||
|
|
||||
LL | match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), };
|
||||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #73448 <https://github.com/rust-lang/rust/issues/73448>
|
||||
= note: the traits must be derived, manual `impl`s are not sufficient
|
||||
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
|
||||
|
||||
warning: to use a constant of type `NoDerive` in a pattern, the constant's initializer must be trivial or `NoDerive` must be annotated with `#[derive(PartialEq)]`
|
||||
--> $DIR/warn_corner_cases.rs:38:47
|
||||
|
|
||||
LL | match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), };
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #73448 <https://github.com/rust-lang/rust/issues/73448>
|
||||
= note: the traits must be derived, manual `impl`s are not sufficient
|
||||
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
|
||||
|
||||
warning: 3 warnings emitted
|
||||
|
17
tests/ui/consts/issue-89088.stderr
Normal file
17
tests/ui/consts/issue-89088.stderr
Normal file
|
@ -0,0 +1,17 @@
|
|||
Future incompatibility report: Future breakage diagnostic:
|
||||
warning: to use a constant of type `Cow<'_, str>` in a pattern, `Cow<'_, str>` must be annotated with `#[derive(PartialEq)]`
|
||||
--> $DIR/issue-89088.rs:19:9
|
||||
|
|
||||
LL | FOO => todo!(),
|
||||
| ^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: the traits must be derived, manual `impl`s are not sufficient
|
||||
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
|
||||
note: the lint level is defined here
|
||||
--> $DIR/issue-89088.rs:5:10
|
||||
|
|
||||
LL | #![allow(indirect_structural_match)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -15,9 +15,6 @@ note: trait bound `NotClone: Clone` was not satisfied
|
|||
|
|
||||
LL | #[derive(Clone)]
|
||||
| ^^^^^ unsatisfied trait bound introduced in this `derive` macro
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
= note: the following trait defines an item `clone`, perhaps you need to implement it:
|
||||
candidate #1: `Clone`
|
||||
help: consider annotating `NotClone` with `#[derive(Clone)]`
|
||||
|
|
||||
LL + #[derive(Clone)]
|
||||
|
|
|
@ -20,7 +20,7 @@ LL | fn baz<U,
|
|||
LL | (y: T) {
|
||||
| ^ use of generic parameter from outer item
|
||||
|
||||
error[E0401]: can't use generic parameters from outer item
|
||||
error[E0401]: can't use `Self` from outer item
|
||||
--> $DIR/E0401.rs:24:25
|
||||
|
|
||||
LL | impl<T> Iterator for A<T> {
|
||||
|
@ -29,7 +29,7 @@ LL | impl<T> Iterator for A<T> {
|
|||
LL | fn helper(sel: &Self) -> u8 {
|
||||
| ^^^^
|
||||
| |
|
||||
| use of generic parameter from outer item
|
||||
| use of `Self` from outer item
|
||||
| refer to the type directly here instead
|
||||
|
||||
error[E0283]: type annotations needed
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
#![crate_type = "lib"]
|
||||
|
||||
extern "C" {
|
||||
#[ffi_returns_twice] //~ ERROR the `#[ffi_returns_twice]` attribute is an experimental feature
|
||||
pub fn foo();
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
error[E0658]: the `#[ffi_returns_twice]` attribute is an experimental feature
|
||||
--> $DIR/feature-gate-ffi_returns_twice.rs:4:5
|
||||
|
|
||||
LL | #[ffi_returns_twice]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #58314 <https://github.com/rust-lang/rust/issues/58314> for more information
|
||||
= help: add `#![feature(ffi_returns_twice)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
|
@ -1,15 +0,0 @@
|
|||
#![feature(ffi_returns_twice)]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
#[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions
|
||||
pub fn foo() {}
|
||||
|
||||
#[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions
|
||||
macro_rules! bar {
|
||||
() => ()
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions
|
||||
static INT: i32;
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
error[E0724]: `#[ffi_returns_twice]` may only be used on foreign functions
|
||||
--> $DIR/ffi_returns_twice.rs:4:1
|
||||
|
|
||||
LL | #[ffi_returns_twice]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0724]: `#[ffi_returns_twice]` may only be used on foreign functions
|
||||
--> $DIR/ffi_returns_twice.rs:7:1
|
||||
|
|
||||
LL | #[ffi_returns_twice]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0724]: `#[ffi_returns_twice]` may only be used on foreign functions
|
||||
--> $DIR/ffi_returns_twice.rs:13:5
|
||||
|
|
||||
LL | #[ffi_returns_twice]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0724`.
|
|
@ -5,7 +5,7 @@ trait X {
|
|||
type Y<T>;
|
||||
}
|
||||
|
||||
trait M {
|
||||
trait M { //~ NOTE
|
||||
fn f(&self) {}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,12 @@ LL | impl<T: X<Y<i32> = i32>> M for T {}
|
|||
| ^^^^^^^^^^^^ - -
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
note: `M` defines an item `f`, perhaps you need to implement it
|
||||
--> $DIR/method-unsatisfied-assoc-type-predicate.rs:8:1
|
||||
|
|
||||
LL | trait M {
|
||||
| ^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -15,6 +15,12 @@ note: the following trait bounds were not satisfied:
|
|||
|
|
||||
LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
|
||||
| --------- - ^^^^^^ unsatisfied trait bound introduced here
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
note: `StreamExt` defines an item `filterx`, perhaps you need to implement it
|
||||
--> $DIR/issue-30786.rs:66:1
|
||||
|
|
||||
LL | pub trait StreamExt
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, fn(&u64) -> &u64 {identity::<u64>}>, {closure@issue-30786.rs:131:30}>`, but its trait bounds were not satisfied
|
||||
--> $DIR/issue-30786.rs:132:24
|
||||
|
@ -33,6 +39,12 @@ note: the following trait bounds were not satisfied:
|
|||
|
|
||||
LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
|
||||
| --------- - ^^^^^^ unsatisfied trait bound introduced here
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
note: `StreamExt` defines an item `countx`, perhaps you need to implement it
|
||||
--> $DIR/issue-30786.rs:66:1
|
||||
|
|
||||
LL | pub trait StreamExt
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@ LL | fn foo<T>() {
|
|||
| - type parameter from outer item
|
||||
LL | static a: Bar<T> = Bar::What;
|
||||
| ^ use of generic parameter from outer item
|
||||
|
|
||||
= note: a `static` is a separate item from the item that contains it
|
||||
|
||||
error[E0392]: type parameter `T` is never used
|
||||
--> $DIR/inner-static-type-parameter.rs:3:10
|
||||
|
|
|
@ -63,8 +63,9 @@ LL | | .take()
|
|||
note: the trait `Iterator` must be implemented
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
= note: the following trait defines an item `take`, perhaps you need to implement it:
|
||||
candidate #1: `Iterator`
|
||||
= note: the following traits define an item `take`, perhaps you need to implement one of them:
|
||||
candidate #1: `std::io::Read`
|
||||
candidate #2: `Iterator`
|
||||
|
||||
error[E0061]: this method takes 3 arguments but 0 arguments were supplied
|
||||
--> $DIR/method-call-err-msg.rs:21:7
|
||||
|
|
|
@ -9,3 +9,21 @@ LL | if let CONSTANT = &&MyType {
|
|||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
Future incompatibility report: Future breakage diagnostic:
|
||||
warning: to use a constant of type `MyType` in a pattern, `MyType` must be annotated with `#[derive(PartialEq)]`
|
||||
--> $DIR/const-partial_eq-fallback-ice.rs:14:12
|
||||
|
|
||||
LL | if let CONSTANT = &&MyType {
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: the traits must be derived, manual `impl`s are not sufficient
|
||||
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
|
||||
note: the lint level is defined here
|
||||
--> $DIR/const-partial_eq-fallback-ice.rs:1:10
|
||||
|
|
||||
LL | #![allow(warnings)]
|
||||
| ^^^^^^^^
|
||||
= note: `#[allow(indirect_structural_match)]` implied by `#[allow(warnings)]`
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | QUUX => {}
|
|||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
|
@ -15,7 +15,7 @@ LL | QUUX => {}
|
|||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/consts-opaque.rs:108:9
|
||||
|
@ -24,7 +24,7 @@ LL | WRAPQUUX => {}
|
|||
| ^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/consts-opaque.rs:110:9
|
||||
|
@ -33,7 +33,7 @@ LL | WRAPQUUX => {}
|
|||
| ^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/consts-opaque.rs:117:9
|
||||
|
@ -42,7 +42,7 @@ LL | WRAPQUUX => {}
|
|||
| ^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/consts-opaque.rs:127:9
|
||||
|
@ -51,7 +51,7 @@ LL | WRAPQUUX => {}
|
|||
| ^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/consts-opaque.rs:139:9
|
||||
|
@ -60,7 +60,7 @@ LL | WHOKNOWSQUUX => {}
|
|||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/consts-opaque.rs:142:9
|
||||
|
@ -69,7 +69,7 @@ LL | WHOKNOWSQUUX => {}
|
|||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/consts-opaque.rs:48:9
|
||||
|
@ -166,3 +166,91 @@ LL | WRAPQUUX => {}, Wrap(_) => todo!()
|
|||
error: aborting due to 10 previous errors; 8 warnings emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0004`.
|
||||
Future incompatibility report: Future breakage diagnostic:
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/consts-opaque.rs:96:9
|
||||
|
|
||||
LL | QUUX => {}
|
||||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
Future breakage diagnostic:
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/consts-opaque.rs:98:9
|
||||
|
|
||||
LL | QUUX => {}
|
||||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
Future breakage diagnostic:
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/consts-opaque.rs:108:9
|
||||
|
|
||||
LL | WRAPQUUX => {}
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
Future breakage diagnostic:
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/consts-opaque.rs:110:9
|
||||
|
|
||||
LL | WRAPQUUX => {}
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
Future breakage diagnostic:
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/consts-opaque.rs:117:9
|
||||
|
|
||||
LL | WRAPQUUX => {}
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
Future breakage diagnostic:
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/consts-opaque.rs:127:9
|
||||
|
|
||||
LL | WRAPQUUX => {}
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
Future breakage diagnostic:
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/consts-opaque.rs:139:9
|
||||
|
|
||||
LL | WHOKNOWSQUUX => {}
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
Future breakage diagnostic:
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/consts-opaque.rs:142:9
|
||||
|
|
||||
LL | WHOKNOWSQUUX => {}
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@ LL | fn outer<T: Tr>() { // outer function
|
|||
| - type parameter from outer item
|
||||
LL | const K: u32 = T::C;
|
||||
| ^^^^ use of generic parameter from outer item
|
||||
|
|
||||
= note: a `const` is a separate item from the item that contains it
|
||||
|
||||
error[E0401]: can't use generic parameters from outer item
|
||||
--> $DIR/generic-params-from-outer-item-in-const-item.rs:19:24
|
||||
|
@ -14,6 +16,8 @@ LL | impl<T> Tr for T { // outer impl block
|
|||
LL | const C: u32 = {
|
||||
LL | const I: u32 = T::C;
|
||||
| ^^^^ use of generic parameter from outer item
|
||||
|
|
||||
= note: a `const` is a separate item from the item that contains it
|
||||
|
||||
error[E0401]: can't use generic parameters from outer item
|
||||
--> $DIR/generic-params-from-outer-item-in-const-item.rs:27:20
|
||||
|
@ -22,6 +26,8 @@ LL | struct S<T: Tr>(U32<{ // outer struct
|
|||
| - type parameter from outer item
|
||||
LL | const _: u32 = T::C;
|
||||
| ^^^^ use of generic parameter from outer item
|
||||
|
|
||||
= note: a `const` is a separate item from the item that contains it
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@ LL | const K: u32 = T::C;
|
|||
| - ^^^^ use of generic parameter from outer item
|
||||
| |
|
||||
| help: try introducing a local generic parameter here: `<T>`
|
||||
|
|
||||
= note: a `const` is a separate item from the item that contains it
|
||||
|
||||
error[E0401]: can't use generic parameters from outer item
|
||||
--> $DIR/generic-params-from-outer-item-in-const-item.rs:19:24
|
||||
|
@ -18,6 +20,8 @@ LL | const I: u32 = T::C;
|
|||
| - ^^^^ use of generic parameter from outer item
|
||||
| |
|
||||
| help: try introducing a local generic parameter here: `<T>`
|
||||
|
|
||||
= note: a `const` is a separate item from the item that contains it
|
||||
|
||||
error[E0401]: can't use generic parameters from outer item
|
||||
--> $DIR/generic-params-from-outer-item-in-const-item.rs:27:20
|
||||
|
@ -28,6 +32,8 @@ LL | const _: u32 = T::C;
|
|||
| - ^^^^ use of generic parameter from outer item
|
||||
| |
|
||||
| help: try introducing a local generic parameter here: `<T>`
|
||||
|
|
||||
= note: a `const` is a separate item from the item that contains it
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
trait Trait {
|
||||
fn outer(&self) {
|
||||
fn inner(_: &Self) {
|
||||
//~^ ERROR can't use generic parameters from outer item
|
||||
//~^ ERROR can't use `Self` from outer item
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
error[E0401]: can't use generic parameters from outer item
|
||||
error[E0401]: can't use `Self` from outer item
|
||||
--> $DIR/issue-12796.rs:3:22
|
||||
|
|
||||
LL | fn inner(_: &Self) {
|
||||
| ^^^^
|
||||
| |
|
||||
| use of generic parameter from outer item
|
||||
| use of `Self` from outer item
|
||||
| can't use `Self` here
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
|
|
@ -6,6 +6,8 @@ LL | unsafe fn foo<A>() {
|
|||
LL | extern "C" {
|
||||
LL | static baz: *const A;
|
||||
| ^ use of generic parameter from outer item
|
||||
|
|
||||
= note: a `static` is a separate item from the item that contains it
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@ LL | fn f<T>() {
|
|||
LL | extern "C" {
|
||||
LL | static a: *const T;
|
||||
| ^ use of generic parameter from outer item
|
||||
|
|
||||
= note: a `static` is a separate item from the item that contains it
|
||||
|
||||
error[E0401]: can't use generic parameters from outer item
|
||||
--> $DIR/issue-65035-static-with-parent-generics.rs:9:22
|
||||
|
@ -14,6 +16,8 @@ LL | fn g<T: Default>() {
|
|||
| - type parameter from outer item
|
||||
LL | static a: *const T = Default::default();
|
||||
| ^ use of generic parameter from outer item
|
||||
|
|
||||
= note: a `static` is a separate item from the item that contains it
|
||||
|
||||
error[E0401]: can't use generic parameters from outer item
|
||||
--> $DIR/issue-65035-static-with-parent-generics.rs:15:24
|
||||
|
@ -23,6 +27,8 @@ LL | fn h<const N: usize>() {
|
|||
LL | extern "C" {
|
||||
LL | static a: [u8; N];
|
||||
| ^ use of generic parameter from outer item
|
||||
|
|
||||
= note: a `static` is a separate item from the item that contains it
|
||||
|
||||
error[E0401]: can't use generic parameters from outer item
|
||||
--> $DIR/issue-65035-static-with-parent-generics.rs:21:20
|
||||
|
@ -31,6 +37,8 @@ LL | fn i<const N: usize>() {
|
|||
| - const parameter from outer item
|
||||
LL | static a: [u8; N] = [0; N];
|
||||
| ^ use of generic parameter from outer item
|
||||
|
|
||||
= note: a `static` is a separate item from the item that contains it
|
||||
|
||||
error[E0401]: can't use generic parameters from outer item
|
||||
--> $DIR/issue-65035-static-with-parent-generics.rs:21:29
|
||||
|
@ -39,6 +47,8 @@ LL | fn i<const N: usize>() {
|
|||
| - const parameter from outer item
|
||||
LL | static a: [u8; N] = [0; N];
|
||||
| ^ use of generic parameter from outer item
|
||||
|
|
||||
= note: a `static` is a separate item from the item that contains it
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ impl A {
|
|||
//~^ NOTE `Self` type implicitly declared here, by this `impl`
|
||||
fn banana(&mut self) {
|
||||
fn peach(this: &Self) {
|
||||
//~^ ERROR can't use generic parameters from outer item
|
||||
//~| NOTE use of generic parameter from outer item
|
||||
//~^ ERROR can't use `Self` from outer item
|
||||
//~| NOTE use of `Self` from outer item
|
||||
//~| NOTE refer to the type directly here instead
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0401]: can't use generic parameters from outer item
|
||||
error[E0401]: can't use `Self` from outer item
|
||||
--> $DIR/use-self-in-inner-fn.rs:6:25
|
||||
|
|
||||
LL | impl A {
|
||||
|
@ -7,7 +7,7 @@ LL | impl A {
|
|||
LL | fn peach(this: &Self) {
|
||||
| ^^^^
|
||||
| |
|
||||
| use of generic parameter from outer item
|
||||
| use of `Self` from outer item
|
||||
| refer to the type directly here instead
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLIN
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: the traits must be derived, manual `impl`s are not sufficient
|
||||
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
|
||||
note: the lint level is defined here
|
||||
|
@ -16,3 +16,20 @@ LL | #![warn(indirect_structural_match)]
|
|||
|
||||
warning: 1 warning emitted
|
||||
|
||||
Future incompatibility report: Future breakage diagnostic:
|
||||
warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
|
||||
--> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:24:9
|
||||
|
|
||||
LL | WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: the traits must be derived, manual `impl`s are not sufficient
|
||||
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
|
||||
note: the lint level is defined here
|
||||
--> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:7:9
|
||||
|
|
||||
LL | #![warn(indirect_structural_match)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: the traits must be derived, manual `impl`s are not sufficient
|
||||
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
|
||||
note: the lint level is defined here
|
||||
|
@ -16,3 +16,20 @@ LL | #![warn(indirect_structural_match)]
|
|||
|
||||
warning: 1 warning emitted
|
||||
|
||||
Future incompatibility report: Future breakage diagnostic:
|
||||
warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
|
||||
--> $DIR/cant-hide-behind-doubly-indirect-param.rs:24:9
|
||||
|
|
||||
LL | WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: the traits must be derived, manual `impl`s are not sufficient
|
||||
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
|
||||
note: the lint level is defined here
|
||||
--> $DIR/cant-hide-behind-doubly-indirect-param.rs:7:9
|
||||
|
|
||||
LL | #![warn(indirect_structural_match)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itse
|
|||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: the traits must be derived, manual `impl`s are not sufficient
|
||||
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
|
||||
note: the lint level is defined here
|
||||
|
@ -16,3 +16,20 @@ LL | #![warn(indirect_structural_match)]
|
|||
|
||||
warning: 1 warning emitted
|
||||
|
||||
Future incompatibility report: Future breakage diagnostic:
|
||||
warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
|
||||
--> $DIR/cant-hide-behind-indirect-struct-embedded.rs:24:9
|
||||
|
|
||||
LL | WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); }
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: the traits must be derived, manual `impl`s are not sufficient
|
||||
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
|
||||
note: the lint level is defined here
|
||||
--> $DIR/cant-hide-behind-indirect-struct-embedded.rs:7:9
|
||||
|
|
||||
LL | #![warn(indirect_structural_match)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself
|
|||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: the traits must be derived, manual `impl`s are not sufficient
|
||||
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
|
||||
note: the lint level is defined here
|
||||
|
@ -16,3 +16,20 @@ LL | #![warn(indirect_structural_match)]
|
|||
|
||||
warning: 1 warning emitted
|
||||
|
||||
Future incompatibility report: Future breakage diagnostic:
|
||||
warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
|
||||
--> $DIR/cant-hide-behind-indirect-struct-param.rs:24:9
|
||||
|
|
||||
LL | WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); }
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: the traits must be derived, manual `impl`s are not sufficient
|
||||
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
|
||||
note: the lint level is defined here
|
||||
--> $DIR/cant-hide-behind-indirect-struct-param.rs:7:9
|
||||
|
|
||||
LL | #![warn(indirect_structural_match)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | Wrap(CFN1) => count += 1,
|
|||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
|
@ -15,7 +15,7 @@ LL | Wrap(CFN2) => count += 1,
|
|||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/fn-ptr-is-structurally-matchable.rs:61:14
|
||||
|
@ -24,7 +24,7 @@ LL | Wrap(CFN3) => count += 1,
|
|||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/fn-ptr-is-structurally-matchable.rs:70:14
|
||||
|
@ -33,7 +33,7 @@ LL | Wrap(CFN4) => count += 1,
|
|||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/fn-ptr-is-structurally-matchable.rs:79:14
|
||||
|
@ -42,7 +42,7 @@ LL | Wrap(CFN5) => count += 1,
|
|||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/fn-ptr-is-structurally-matchable.rs:88:14
|
||||
|
@ -51,7 +51,7 @@ LL | Wrap(CFN6) => count += 1,
|
|||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/fn-ptr-is-structurally-matchable.rs:97:14
|
||||
|
@ -60,7 +60,7 @@ LL | Wrap(CFN7) => count += 1,
|
|||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/fn-ptr-is-structurally-matchable.rs:106:14
|
||||
|
@ -69,7 +69,7 @@ LL | Wrap(CFN8) => count += 1,
|
|||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/fn-ptr-is-structurally-matchable.rs:115:14
|
||||
|
@ -78,7 +78,7 @@ LL | Wrap(CFN9) => count += 1,
|
|||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/fn-ptr-is-structurally-matchable.rs:138:9
|
||||
|
@ -87,7 +87,117 @@ LL | CFOO => count += 1,
|
|||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
|
||||
warning: 10 warnings emitted
|
||||
|
||||
Future incompatibility report: Future breakage diagnostic:
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/fn-ptr-is-structurally-matchable.rs:43:14
|
||||
|
|
||||
LL | Wrap(CFN1) => count += 1,
|
||||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
Future breakage diagnostic:
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/fn-ptr-is-structurally-matchable.rs:52:14
|
||||
|
|
||||
LL | Wrap(CFN2) => count += 1,
|
||||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
Future breakage diagnostic:
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/fn-ptr-is-structurally-matchable.rs:61:14
|
||||
|
|
||||
LL | Wrap(CFN3) => count += 1,
|
||||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
Future breakage diagnostic:
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/fn-ptr-is-structurally-matchable.rs:70:14
|
||||
|
|
||||
LL | Wrap(CFN4) => count += 1,
|
||||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
Future breakage diagnostic:
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/fn-ptr-is-structurally-matchable.rs:79:14
|
||||
|
|
||||
LL | Wrap(CFN5) => count += 1,
|
||||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
Future breakage diagnostic:
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/fn-ptr-is-structurally-matchable.rs:88:14
|
||||
|
|
||||
LL | Wrap(CFN6) => count += 1,
|
||||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
Future breakage diagnostic:
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/fn-ptr-is-structurally-matchable.rs:97:14
|
||||
|
|
||||
LL | Wrap(CFN7) => count += 1,
|
||||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
Future breakage diagnostic:
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/fn-ptr-is-structurally-matchable.rs:106:14
|
||||
|
|
||||
LL | Wrap(CFN8) => count += 1,
|
||||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
Future breakage diagnostic:
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/fn-ptr-is-structurally-matchable.rs:115:14
|
||||
|
|
||||
LL | Wrap(CFN9) => count += 1,
|
||||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
Future breakage diagnostic:
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/fn-ptr-is-structurally-matchable.rs:138:9
|
||||
|
|
||||
LL | CFOO => count += 1,
|
||||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
// Issue 62307 pointed out a case where the structural-match checking
|
||||
// was too shallow.
|
||||
#![warn(indirect_structural_match, nontrivial_structural_match)]
|
||||
#![warn(indirect_structural_match)]
|
||||
// run-pass
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -5,13 +5,13 @@ LL | RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0);
|
|||
| ^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: the traits must be derived, manual `impl`s are not sufficient
|
||||
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
|
||||
note: the lint level is defined here
|
||||
--> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9
|
||||
|
|
||||
LL | #![warn(indirect_structural_match, nontrivial_structural_match)]
|
||||
LL | #![warn(indirect_structural_match)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq)]`
|
||||
|
@ -21,9 +21,43 @@ LL | RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1);
|
|||
| ^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: the traits must be derived, manual `impl`s are not sufficient
|
||||
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
||||
Future incompatibility report: Future breakage diagnostic:
|
||||
warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq)]`
|
||||
--> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:31:9
|
||||
|
|
||||
LL | RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); }
|
||||
| ^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: the traits must be derived, manual `impl`s are not sufficient
|
||||
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
|
||||
note: the lint level is defined here
|
||||
--> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9
|
||||
|
|
||||
LL | #![warn(indirect_structural_match)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Future breakage diagnostic:
|
||||
warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq)]`
|
||||
--> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:38:9
|
||||
|
|
||||
LL | RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); }
|
||||
| ^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: the traits must be derived, manual `impl`s are not sufficient
|
||||
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
|
||||
note: the lint level is defined here
|
||||
--> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9
|
||||
|
|
||||
LL | #![warn(indirect_structural_match)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue