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:
bors 2024-02-07 00:03:50 +00:00
commit 586893c7b0
108 changed files with 1368 additions and 744 deletions

View file

@ -5,10 +5,13 @@
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 @@ pub(crate) fn new(
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 @@ pub(crate) fn new(
universal_regions,
region_bound_pairs,
implicit_region_bound,
param_env,
known_type_outlives_obligations,
locations,
span,
@ -137,36 +143,68 @@ fn convert(
// 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 @@ fn add_type_test(&mut self, type_test: TypeTest<'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> {

View file

@ -8,8 +8,11 @@
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 @@ pub(crate) fn known_outlives(&self) -> impl Iterator<Item = (RegionVid, RegionVi
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 @@ pub(crate) fn create(mut self) -> CreateResult<'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 @@ pub(crate) fn create(mut self) -> CreateResult<'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 @@ pub(crate) fn create(mut self) -> CreateResult<'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 @@ pub(crate) fn create(mut self) -> CreateResult<'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

View file

@ -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 @@ fn push_region_constraints(
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 @@ fn prove_closure_bounds(
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.

View file

@ -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);
}

View file

@ -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));
}

View file

@ -184,7 +184,6 @@ pub enum AttributeKind {
SanitizeMemory = 22,
NonLazyBind = 23,
OptimizeNone = 24,
ReturnsTwice = 25,
ReadNone = 26,
SanitizeHWAddress = 28,
WillReturn = 29,

View file

@ -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,

View file

@ -20,7 +20,7 @@
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 @@ fn in_return_place(
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,
}
}

View file

@ -10,7 +10,7 @@
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 @@ fn in_adt_inherently<'tcx>(
}
}
/// 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`.

View file

@ -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" {

View file

@ -440,9 +440,6 @@ pub struct 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!(

View file

@ -97,6 +97,9 @@ macro_rules! 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.

View file

@ -465,8 +465,6 @@ pub fn internal(&self, feature: Symbol) -> bool {
(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.

View file

@ -541,6 +541,7 @@ pub fn report_no_match_method_error(
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 @@ pub fn report_no_match_method_error(
"`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 @@ pub fn report_no_match_method_error(
.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 @@ trait bound{s}",
"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 @@ trait bound{s}",
);
}
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 @@ trait bound{s}",
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 @@ trait bound{s}",
}
}
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 @@ pub(crate) fn suggest_derive(
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 @@ pub(crate) fn suggest_derive(
Applicability::MaybeIncorrect,
);
}
!derives_grouped.is_empty()
}
fn note_derefed_ty_has_method(
@ -2698,11 +2712,6 @@ fn suggest_traits_to_import(
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 @@ fn suggest_traits_to_import(
// 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)

View file

@ -71,6 +71,7 @@
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 @@ pub fn report_region_errors(
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();
}
}

View file

@ -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> {

View file

@ -4,8 +4,8 @@
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)];
}
};

View file

@ -68,8 +68,9 @@
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 @@ pub fn take_registered_region_obligations(&self) -> Vec<RegionObligation<'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 @@ pub fn process_registered_region_obligations<E>(
.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(())

View file

@ -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 {

View file

@ -520,6 +520,11 @@ macro_rules! add_lint_group {
"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) {

View file

@ -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 @@
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 @@
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 @@
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>",
};
}

View file

@ -76,7 +76,6 @@ enum LLVMRustAttribute {
SanitizeMemory = 22,
NonLazyBind = 23,
OptimizeNone = 24,
ReturnsTwice = 25,
ReadNone = 26,
SanitizeHWAddress = 28,
WillReturn = 29,

View file

@ -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:

View file

@ -74,35 +74,32 @@ impl CodegenFnAttrFlags: u32 {
/// `#[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 }

View file

@ -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>,
}

View file

@ -1193,7 +1193,7 @@ pub fn is_suitable_region(self, mut region: Region<'tcx>) -> Option<FreeRegionIn
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);

View file

@ -291,7 +291,7 @@ fn lower_pattern(
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 @@ fn new_cx(
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,

View file

@ -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 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 @@ pub(super) fn const_to_pat(
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 @@ fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool {
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 @@ fn to_pat(
// 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 @@ fn to_pat(
| 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 @@ fn to_pat(
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 @@ fn to_pat(
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 @@ fn to_pat(
// 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 @@ fn field_pats(
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 @@ fn recur(
&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 @@ fn recur(
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 @@ fn recur(
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 @@ fn recur(
_ => *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 @@ fn recur(
}
};
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 }))
}
}

View file

@ -542,7 +542,7 @@ fn lower_path(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) ->
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 @@ fn lower_inline_const(
};
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 @@ fn lower_inline_const(
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 @@ fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'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"),
}

View file

@ -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

View file

@ -192,7 +192,6 @@ fn check_attributes(
}
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 @@ fn check_ffi_const(&self, attr_span: Span, target: Target) -> bool {
}
}
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!(

View file

@ -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 {

View file

@ -23,7 +23,10 @@ pub fn new<'p>(
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,

View file

@ -119,7 +119,7 @@ fn ctor_sub_tys<'a>(
/// `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 @@ fn write_variant_name(
/// 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 @@ fn lint_overlapping_range_endpoints(
/// 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,
}

View file

@ -6,7 +6,7 @@
use smallvec::{smallvec, SmallVec};
use crate::constructor::{Constructor, Slice, SliceKind};
use crate::{Captures, TypeCx};
use crate::TypeCx;
use self::Constructor::*;
@ -21,9 +21,9 @@
/// 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 @@ pub fn data(&self) -> Option<&Cx::PatData> {
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 @@ fn collect_redundant_subpatterns<'a>(&'a self, subpats: &mut Vec<&'a Self>) {
}
/// 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 @@ fn clone(&self) -> Self {
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),

View file

@ -13,7 +13,7 @@
#[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 @@ fn expand_and_push(&mut self, pat: PatOrWild<'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()
}

View file

@ -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 @@
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 @@ pub fn inner(self) -> Ty<'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 @@ pub(crate) fn lower_pat_range_bdy(
/// 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 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'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 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'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 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'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 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'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 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'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 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'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 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'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 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'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 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'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 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'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 @@ pub fn hoist_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> Pat<'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 @@ fn ctors_for_ty(
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 @@ fn bug(&self, fmt: fmt::Arguments<'_>) -> Self::Error {
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

View file

@ -848,7 +848,7 @@ fn clone(&self) -> Self {
}
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,

View file

@ -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

View file

@ -561,13 +561,21 @@ pub(crate) fn into_struct_error(
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();

View file

@ -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)]

View file

@ -10,9 +10,7 @@
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 @@ fn validate_res_from_ribs(
| 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 @@ fn validate_res_from_ribs(
}
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 @@ fn validate_res_from_ribs(
}
// 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 @@ fn validate_res_from_ribs(
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 @@ fn validate_res_from_ribs(
}
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 @@ fn validate_res_from_ribs(
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 @@ fn validate_res_from_ribs(
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;

View file

@ -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 @@ pub(crate) fn contains_params(&self) -> bool {
| 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 @@ fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef) {
}
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 @@ fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
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 @@ fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
);
}
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 @@ fn is_label_valid_from_rib(&self, rib_index: usize) -> bool {
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 @@ fn resolve_item(&mut self, item: &'ast Item) {
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 @@ fn resolve_item(&mut self, item: &'ast Item) {
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 @@ fn resolve_item(&mut self, item: &'ast Item) {
// 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 @@ fn resolve_item(&mut self, item: &'ast Item) {
// 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 @@ fn resolve_item(&mut self, item: &'ast Item) {
}
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 @@ fn resolve_item(&mut self, item: &'ast Item) {
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 @@ fn with_generic_param_rib<'c, F>(
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 @@ fn with_label_rib(&mut self, kind: RibKind<'a>, f: impl FnOnce(&mut Self)) {
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 @@ fn resolve_implementation(
// 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,

View file

@ -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 @@ fn local_def_id(&self, node: NodeId) -> LocalDefId {
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,

View file

@ -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 @@ fn resolve_regions(
),
ty,
)
.map_err(|_| ty)
.map_err(|_| NoSolution)
} else {
Ok(ty)
}

View file

@ -179,7 +179,7 @@ pub fn find_auto_trait_generics<A>(
}
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();

View file

@ -14,7 +14,7 @@
// #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

View file

@ -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();
}

View file

@ -0,0 +1,7 @@
// edition:2021
#[allow(async_fn_in_trait)]
pub trait BleRadio<'a> {
async fn transmit(&mut self);
}

View 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() {}

View 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`.

View file

@ -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

View file

@ -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)]

View 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() {}

View 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

View 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() {}

View 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

View 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() {}

View 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

View file

@ -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

View file

@ -63,4 +63,18 @@ enum CLike { One = 1, #[allow(dead_code)] Two = 2, }
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), };
}

View file

@ -12,6 +12,7 @@ fn eq(&self, _: &Self) -> bool {
}
#[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() {

View file

@ -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
_ => {}
}
}

View file

@ -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

View file

@ -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)]
| ^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -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)]
| ^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -1 +0,0 @@
WARN rustc_mir_build::thir::pattern::const_to_pat MIR const-checker found novel structural match violation. See #73448.

View file

@ -100,5 +100,5 @@ enum Derive<X> { Some(X), None, }
//~| 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
}

View file

@ -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)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -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
}

View file

@ -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

View 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)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -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)]

View file

@ -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

View file

@ -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();
}

View file

@ -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`.

View file

@ -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;
}

View file

@ -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`.

View file

@ -5,7 +5,7 @@ trait X {
type Y<T>;
}
trait M {
trait M { //~ NOTE
fn f(&self) {}
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)]`

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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
}
}
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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
}
}

View file

@ -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

View file

@ -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)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -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)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -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)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -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)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -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

View file

@ -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)]

View file

@ -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