1
Fork 0

Auto merge of #95309 - lcnr:dropck-cleanup, r=nikomatsakis

rewrite `ensure_drop_params_and_item_params_correspond`

actually relating types here seems like it's overkill
This commit is contained in:
bors 2022-05-20 10:37:48 +00:00
commit 512a328e2f
9 changed files with 177 additions and 222 deletions

View file

@ -181,7 +181,7 @@ pub struct InferCtxtInner<'tcx> {
/// ///
/// Before running `resolve_regions_and_report_errors`, the creator /// Before running `resolve_regions_and_report_errors`, the creator
/// of the inference context is expected to invoke /// of the inference context is expected to invoke
/// `process_region_obligations` (defined in `self::region_obligations`) /// [`InferCtxt::process_registered_region_obligations`]
/// for each body-id in this map, which will process the /// for each body-id in this map, which will process the
/// obligations within. This is expected to be done 'late enough' /// obligations within. This is expected to be done 'late enough'
/// that all type inference variables have been bound and so forth. /// that all type inference variables have been bound and so forth.

View file

@ -136,7 +136,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
/// ///
/// # Parameters /// # Parameters
/// ///
/// - `region_bound_pairs`: the set of region bounds implied by /// - `region_bound_pairs_map`: the set of region bounds implied by
/// the parameters and where-clauses. In particular, each pair /// the parameters and where-clauses. In particular, each pair
/// `('a, K)` in this list tells us that the bounds in scope /// `('a, K)` in this list tells us that the bounds in scope
/// indicate that `K: 'a`, where `K` is either a generic /// indicate that `K: 'a`, where `K` is either a generic
@ -147,12 +147,6 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
/// - `param_env` is the parameter environment for the enclosing function. /// - `param_env` is the parameter environment for the enclosing function.
/// - `body_id` is the body-id whose region obligations are being /// - `body_id` is the body-id whose region obligations are being
/// processed. /// processed.
///
/// # Returns
///
/// This function may have to perform normalizations, and hence it
/// returns an `InferOk` with subobligations that must be
/// processed.
#[instrument(level = "debug", skip(self, region_bound_pairs_map))] #[instrument(level = "debug", skip(self, region_bound_pairs_map))]
pub fn process_registered_region_obligations( pub fn process_registered_region_obligations(
&self, &self,

View file

@ -5,10 +5,7 @@ use crate::ty::fold::{FallibleTypeFolder, TypeFolder};
use crate::ty::layout::IntegerExt; use crate::ty::layout::IntegerExt;
use crate::ty::query::TyCtxtAt; use crate::ty::query::TyCtxtAt;
use crate::ty::subst::{GenericArgKind, Subst, SubstsRef}; use crate::ty::subst::{GenericArgKind, Subst, SubstsRef};
use crate::ty::{ use crate::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable};
self, DebruijnIndex, DefIdTree, EarlyBinder, List, ReEarlyBound, Ty, TyCtxt, TyKind::*,
TypeFoldable,
};
use rustc_apfloat::Float as _; use rustc_apfloat::Float as _;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_attr::{self as attr, SignedInt, UnsignedInt}; use rustc_attr::{self as attr, SignedInt, UnsignedInt};
@ -18,6 +15,7 @@ use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_index::bit_set::GrowableBitSet;
use rustc_macros::HashStable; use rustc_macros::HashStable;
use rustc_span::{sym, DUMMY_SP}; use rustc_span::{sym, DUMMY_SP};
use rustc_target::abi::{Integer, Size, TargetDataLayout}; use rustc_target::abi::{Integer, Size, TargetDataLayout};
@ -32,6 +30,19 @@ pub struct Discr<'tcx> {
pub ty: Ty<'tcx>, pub ty: Ty<'tcx>,
} }
/// Used as an input to [`TyCtxt::uses_unique_generic_params`].
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum IgnoreRegions {
Yes,
No,
}
#[derive(Copy, Clone, Debug)]
pub enum NotUniqueParam<'tcx> {
DuplicateParam(ty::GenericArg<'tcx>),
NotParam(ty::GenericArg<'tcx>),
}
impl<'tcx> fmt::Display for Discr<'tcx> { impl<'tcx> fmt::Display for Discr<'tcx> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self.ty.kind() { match *self.ty.kind() {
@ -49,8 +60,8 @@ impl<'tcx> fmt::Display for Discr<'tcx> {
fn int_size_and_signed<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (Size, bool) { fn int_size_and_signed<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (Size, bool) {
let (int, signed) = match *ty.kind() { let (int, signed) = match *ty.kind() {
Int(ity) => (Integer::from_int_ty(&tcx, ity), true), ty::Int(ity) => (Integer::from_int_ty(&tcx, ity), true),
Uint(uty) => (Integer::from_uint_ty(&tcx, uty), false), ty::Uint(uty) => (Integer::from_uint_ty(&tcx, uty), false),
_ => bug!("non integer discriminant"), _ => bug!("non integer discriminant"),
}; };
(int.size(), signed) (int.size(), signed)
@ -176,7 +187,7 @@ impl<'tcx> TyCtxt<'tcx> {
if let ty::Adt(def, substs) = *ty.kind() { if let ty::Adt(def, substs) = *ty.kind() {
for field in def.all_fields() { for field in def.all_fields() {
let field_ty = field.ty(self, substs); let field_ty = field.ty(self, substs);
if let Error(_) = field_ty.kind() { if let ty::Error(_) = field_ty.kind() {
return true; return true;
} }
} }
@ -311,7 +322,7 @@ impl<'tcx> TyCtxt<'tcx> {
let (mut a, mut b) = (source, target); let (mut a, mut b) = (source, target);
loop { loop {
match (&a.kind(), &b.kind()) { match (&a.kind(), &b.kind()) {
(&Adt(a_def, a_substs), &Adt(b_def, b_substs)) (&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs))
if a_def == b_def && a_def.is_struct() => if a_def == b_def && a_def.is_struct() =>
{ {
if let Some(f) = a_def.non_enum_variant().fields.last() { if let Some(f) = a_def.non_enum_variant().fields.last() {
@ -321,7 +332,7 @@ impl<'tcx> TyCtxt<'tcx> {
break; break;
} }
} }
(&Tuple(a_tys), &Tuple(b_tys)) if a_tys.len() == b_tys.len() => { (&ty::Tuple(a_tys), &ty::Tuple(b_tys)) if a_tys.len() == b_tys.len() => {
if let Some(&a_last) = a_tys.last() { if let Some(&a_last) = a_tys.last() {
a = a_last; a = a_last;
b = *b_tys.last().unwrap(); b = *b_tys.last().unwrap();
@ -427,7 +438,7 @@ impl<'tcx> TyCtxt<'tcx> {
.filter(|&(_, k)| { .filter(|&(_, k)| {
match k.unpack() { match k.unpack() {
GenericArgKind::Lifetime(region) => match region.kind() { GenericArgKind::Lifetime(region) => match region.kind() {
ReEarlyBound(ref ebr) => { ty::ReEarlyBound(ref ebr) => {
!impl_generics.region_param(ebr, self).pure_wrt_drop !impl_generics.region_param(ebr, self).pure_wrt_drop
} }
// Error: not a region param // Error: not a region param
@ -453,6 +464,47 @@ impl<'tcx> TyCtxt<'tcx> {
result result
} }
/// Checks whether each generic argument is simply a unique generic parameter.
pub fn uses_unique_generic_params(
self,
substs: SubstsRef<'tcx>,
ignore_regions: IgnoreRegions,
) -> Result<(), NotUniqueParam<'tcx>> {
let mut seen = GrowableBitSet::default();
for arg in substs {
match arg.unpack() {
GenericArgKind::Lifetime(lt) => {
if ignore_regions == IgnoreRegions::No {
let ty::ReEarlyBound(p) = lt.kind() else {
return Err(NotUniqueParam::NotParam(lt.into()))
};
if !seen.insert(p.index) {
return Err(NotUniqueParam::DuplicateParam(lt.into()));
}
}
}
GenericArgKind::Type(t) => match t.kind() {
ty::Param(p) => {
if !seen.insert(p.index) {
return Err(NotUniqueParam::DuplicateParam(t.into()));
}
}
_ => return Err(NotUniqueParam::NotParam(t.into())),
},
GenericArgKind::Const(c) => match c.val() {
ty::ConstKind::Param(p) => {
if !seen.insert(p.index) {
return Err(NotUniqueParam::DuplicateParam(c.into()));
}
}
_ => return Err(NotUniqueParam::NotParam(c.into())),
},
}
}
Ok(())
}
/// Returns `true` if `def_id` refers to a closure (e.g., `|x| x * 2`). Note /// Returns `true` if `def_id` refers to a closure (e.g., `|x| x * 2`). Note
/// that closures have a `DefId`, but the closure *expression* also /// that closures have a `DefId`, but the closure *expression* also
/// has a `HirId` that is located within the context where the /// has a `HirId` that is located within the context where the
@ -594,30 +646,33 @@ impl<'tcx> TyCtxt<'tcx> {
if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) } if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) }
} }
pub fn bound_type_of(self, def_id: DefId) -> EarlyBinder<Ty<'tcx>> { pub fn bound_type_of(self, def_id: DefId) -> ty::EarlyBinder<Ty<'tcx>> {
EarlyBinder(self.type_of(def_id)) ty::EarlyBinder(self.type_of(def_id))
} }
pub fn bound_fn_sig(self, def_id: DefId) -> EarlyBinder<ty::PolyFnSig<'tcx>> { pub fn bound_fn_sig(self, def_id: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'tcx>> {
EarlyBinder(self.fn_sig(def_id)) ty::EarlyBinder(self.fn_sig(def_id))
} }
pub fn bound_impl_trait_ref(self, def_id: DefId) -> Option<EarlyBinder<ty::TraitRef<'tcx>>> { pub fn bound_impl_trait_ref(
self.impl_trait_ref(def_id).map(|i| EarlyBinder(i)) self,
def_id: DefId,
) -> Option<ty::EarlyBinder<ty::TraitRef<'tcx>>> {
self.impl_trait_ref(def_id).map(|i| ty::EarlyBinder(i))
} }
pub fn bound_explicit_item_bounds( pub fn bound_explicit_item_bounds(
self, self,
def_id: DefId, def_id: DefId,
) -> EarlyBinder<&'tcx [(ty::Predicate<'tcx>, rustc_span::Span)]> { ) -> ty::EarlyBinder<&'tcx [(ty::Predicate<'tcx>, rustc_span::Span)]> {
EarlyBinder(self.explicit_item_bounds(def_id)) ty::EarlyBinder(self.explicit_item_bounds(def_id))
} }
pub fn bound_item_bounds( pub fn bound_item_bounds(
self, self,
def_id: DefId, def_id: DefId,
) -> EarlyBinder<&'tcx ty::List<ty::Predicate<'tcx>>> { ) -> ty::EarlyBinder<&'tcx ty::List<ty::Predicate<'tcx>>> {
EarlyBinder(self.item_bounds(def_id)) ty::EarlyBinder(self.item_bounds(def_id))
} }
} }
@ -930,35 +985,40 @@ impl<'tcx> Ty<'tcx> {
pub fn is_structural_eq_shallow(self, tcx: TyCtxt<'tcx>) -> bool { pub fn is_structural_eq_shallow(self, tcx: TyCtxt<'tcx>) -> bool {
match self.kind() { match self.kind() {
// Look for an impl of both `PartialStructuralEq` and `StructuralEq`. // Look for an impl of both `PartialStructuralEq` and `StructuralEq`.
Adt(..) => tcx.has_structural_eq_impls(self), ty::Adt(..) => tcx.has_structural_eq_impls(self),
// Primitive types that satisfy `Eq`. // Primitive types that satisfy `Eq`.
Bool | Char | Int(_) | Uint(_) | Str | Never => true, ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Str | ty::Never => true,
// Composite types that satisfy `Eq` when all of their fields do. // Composite types that satisfy `Eq` when all of their fields do.
// //
// Because this function is "shallow", we return `true` for these composites regardless // Because this function is "shallow", we return `true` for these composites regardless
// of the type(s) contained within. // of the type(s) contained within.
Ref(..) | Array(..) | Slice(_) | Tuple(..) => true, ty::Ref(..) | ty::Array(..) | ty::Slice(_) | ty::Tuple(..) => true,
// Raw pointers use bitwise comparison. // Raw pointers use bitwise comparison.
RawPtr(_) | FnPtr(_) => true, ty::RawPtr(_) | ty::FnPtr(_) => true,
// Floating point numbers are not `Eq`. // Floating point numbers are not `Eq`.
Float(_) => false, ty::Float(_) => false,
// Conservatively return `false` for all others... // Conservatively return `false` for all others...
// Anonymous function types // Anonymous function types
FnDef(..) | Closure(..) | Dynamic(..) | Generator(..) => false, ty::FnDef(..) | ty::Closure(..) | ty::Dynamic(..) | ty::Generator(..) => false,
// Generic or inferred types // Generic or inferred types
// //
// FIXME(ecstaticmorse): Maybe we should `bug` here? This should probably only be // FIXME(ecstaticmorse): Maybe we should `bug` here? This should probably only be
// called for known, fully-monomorphized types. // called for known, fully-monomorphized types.
Projection(_) | Opaque(..) | Param(_) | Bound(..) | Placeholder(_) | Infer(_) => false, ty::Projection(_)
| ty::Opaque(..)
| ty::Param(_)
| ty::Bound(..)
| ty::Placeholder(_)
| ty::Infer(_) => false,
Foreign(_) | GeneratorWitness(..) | Error(_) => false, ty::Foreign(_) | ty::GeneratorWitness(..) | ty::Error(_) => false,
} }
} }
@ -974,13 +1034,13 @@ impl<'tcx> Ty<'tcx> {
/// - `&'a *const &'b u8 -> *const &'b u8` /// - `&'a *const &'b u8 -> *const &'b u8`
pub fn peel_refs(self) -> Ty<'tcx> { pub fn peel_refs(self) -> Ty<'tcx> {
let mut ty = self; let mut ty = self;
while let Ref(_, inner_ty, _) = ty.kind() { while let ty::Ref(_, inner_ty, _) = ty.kind() {
ty = *inner_ty; ty = *inner_ty;
} }
ty ty
} }
pub fn outer_exclusive_binder(self) -> DebruijnIndex { pub fn outer_exclusive_binder(self) -> ty::DebruijnIndex {
self.0.outer_exclusive_binder self.0.outer_exclusive_binder
} }
} }
@ -1177,8 +1237,8 @@ pub struct AlwaysRequiresDrop;
/// with their underlying types. /// with their underlying types.
pub fn normalize_opaque_types<'tcx>( pub fn normalize_opaque_types<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
val: &'tcx List<ty::Predicate<'tcx>>, val: &'tcx ty::List<ty::Predicate<'tcx>>,
) -> &'tcx List<ty::Predicate<'tcx>> { ) -> &'tcx ty::List<ty::Predicate<'tcx>> {
let mut visitor = OpaqueTypeExpander { let mut visitor = OpaqueTypeExpander {
seen_opaque_tys: FxHashSet::default(), seen_opaque_tys: FxHashSet::default(),
expanded_cache: FxHashMap::default(), expanded_cache: FxHashMap::default(),

View file

@ -2,17 +2,14 @@ use crate::check::regionck::RegionCtxt;
use crate::hir; use crate::hir;
use crate::hir::def_id::{DefId, LocalDefId}; use crate::hir::def_id::{DefId, LocalDefId};
use rustc_errors::{struct_span_err, ErrorGuaranteed}; use rustc_errors::{struct_span_err, ErrorGuaranteed};
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{InferOk, RegionckMode, TyCtxtInferExt};
use rustc_infer::traits::TraitEngineExt as _;
use rustc_middle::ty::error::TypeError; use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
use rustc_middle::ty::subst::{Subst, SubstsRef}; use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, EarlyBinder, Predicate, Ty, TyCtxt}; use rustc_middle::ty::util::IgnoreRegions;
use rustc_middle::ty::{self, Predicate, Ty, TyCtxt};
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
use rustc_trait_selection::traits::query::dropck_outlives::AtExt; use rustc_trait_selection::traits::query::dropck_outlives::AtExt;
use rustc_trait_selection::traits::{ObligationCause, TraitEngine, TraitEngineExt}; use rustc_trait_selection::traits::ObligationCause;
/// This function confirms that the `Drop` implementation identified by /// This function confirms that the `Drop` implementation identified by
/// `drop_impl_did` is not any more specialized than the type it is /// `drop_impl_did` is not any more specialized than the type it is
@ -39,8 +36,8 @@ pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), Erro
ensure_drop_params_and_item_params_correspond( ensure_drop_params_and_item_params_correspond(
tcx, tcx,
drop_impl_did.expect_local(), drop_impl_did.expect_local(),
dtor_self_type,
adt_def.did(), adt_def.did(),
self_to_impl_substs,
)?; )?;
ensure_drop_predicates_are_implied_by_item_defn( ensure_drop_predicates_are_implied_by_item_defn(
@ -67,75 +64,34 @@ pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), Erro
fn ensure_drop_params_and_item_params_correspond<'tcx>( fn ensure_drop_params_and_item_params_correspond<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
drop_impl_did: LocalDefId, drop_impl_did: LocalDefId,
drop_impl_ty: Ty<'tcx>,
self_type_did: DefId, self_type_did: DefId,
drop_impl_substs: SubstsRef<'tcx>,
) -> Result<(), ErrorGuaranteed> { ) -> Result<(), ErrorGuaranteed> {
let drop_impl_hir_id = tcx.hir().local_def_id_to_hir_id(drop_impl_did); let Err(arg) = tcx.uses_unique_generic_params(drop_impl_substs, IgnoreRegions::No) else {
return Ok(())
};
// check that the impl type can be made to match the trait type. let drop_impl_span = tcx.def_span(drop_impl_did);
let item_span = tcx.def_span(self_type_did);
tcx.infer_ctxt().enter(|ref infcx| { let self_descr = tcx.def_kind(self_type_did).descr(self_type_did);
let impl_param_env = tcx.param_env(self_type_did); let mut err =
let tcx = infcx.tcx; struct_span_err!(tcx.sess, drop_impl_span, E0366, "`Drop` impls cannot be specialized");
let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(tcx); match arg {
ty::util::NotUniqueParam::DuplicateParam(arg) => {
let named_type = tcx.type_of(self_type_did); err.note(&format!("`{arg}` is mentioned multiple times"))
let drop_impl_span = tcx.def_span(drop_impl_did);
let fresh_impl_substs =
infcx.fresh_substs_for_item(drop_impl_span, drop_impl_did.to_def_id());
let fresh_impl_self_ty = EarlyBinder(drop_impl_ty).subst(tcx, fresh_impl_substs);
let cause = &ObligationCause::misc(drop_impl_span, drop_impl_hir_id);
match infcx.at(cause, impl_param_env).eq(named_type, fresh_impl_self_ty) {
Ok(InferOk { obligations, .. }) => {
fulfillment_cx.register_predicate_obligations(infcx, obligations);
}
Err(_) => {
let item_span = tcx.def_span(self_type_did);
let self_descr = tcx.def_kind(self_type_did).descr(self_type_did);
let reported = struct_span_err!(
tcx.sess,
drop_impl_span,
E0366,
"`Drop` impls cannot be specialized"
)
.span_note(
item_span,
&format!(
"use the same sequence of generic type, lifetime and const parameters \
as the {self_descr} definition",
),
)
.emit();
return Err(reported);
}
} }
ty::util::NotUniqueParam::NotParam(arg) => {
let errors = fulfillment_cx.select_all_or_error(&infcx); err.note(&format!("`{arg}` is not a generic parameter"))
if !errors.is_empty() {
// this could be reached when we get lazy normalization
let reported = infcx.report_fulfillment_errors(&errors, None, false);
return Err(reported);
} }
};
// NB. It seems a bit... suspicious to use an empty param-env err.span_note(
// here. The correct thing, I imagine, would be item_span,
// `OutlivesEnvironment::new(impl_param_env)`, which would &format!(
// allow region solving to take any `a: 'b` relations on the "use the same sequence of generic lifetime, type and const parameters \
// impl into account. But I could not create a test case where as the {self_descr} definition",
// it did the wrong thing, so I chose to preserve existing ),
// behavior, since it ought to be simply more );
// conservative. -nmatsakis Err(err.emit())
let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty());
infcx.resolve_regions_and_report_errors(
drop_impl_did.to_def_id(),
&outlives_env,
RegionckMode::default(),
);
Ok(())
})
} }
/// Confirms that every predicate imposed by dtor_predicates is /// Confirms that every predicate imposed by dtor_predicates is

View file

@ -5,10 +5,10 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_errors::struct_span_err; use rustc_errors::struct_span_err;
use rustc_errors::ErrorGuaranteed; use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_index::bit_set::GrowableBitSet;
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::subst::{GenericArg, InternalSubsts}; use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::util::IgnoreRegions;
use rustc_middle::ty::{self, ImplPolarity, Ty, TyCtxt, TypeFoldable, TypeVisitor}; use rustc_middle::ty::{self, ImplPolarity, Ty, TyCtxt, TypeFoldable, TypeVisitor};
use rustc_session::lint; use rustc_session::lint;
use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::def_id::{DefId, LocalDefId};
@ -325,51 +325,6 @@ fn emit_orphan_check_error<'tcx>(
}) })
} }
#[derive(Default)]
struct AreUniqueParamsVisitor {
seen: GrowableBitSet<u32>,
}
#[derive(Copy, Clone)]
enum NotUniqueParam<'tcx> {
DuplicateParam(GenericArg<'tcx>),
NotParam(GenericArg<'tcx>),
}
impl<'tcx> TypeVisitor<'tcx> for AreUniqueParamsVisitor {
type BreakTy = NotUniqueParam<'tcx>;
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match t.kind() {
ty::Param(p) => {
if self.seen.insert(p.index) {
ControlFlow::CONTINUE
} else {
ControlFlow::Break(NotUniqueParam::DuplicateParam(t.into()))
}
}
_ => ControlFlow::Break(NotUniqueParam::NotParam(t.into())),
}
}
fn visit_region(&mut self, _: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
// We don't drop candidates during candidate assembly because of region
// constraints, so the behavior for impls only constrained by regions
// will not change.
ControlFlow::CONTINUE
}
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
match c.val() {
ty::ConstKind::Param(p) => {
if self.seen.insert(p.index) {
ControlFlow::CONTINUE
} else {
ControlFlow::Break(NotUniqueParam::DuplicateParam(c.into()))
}
}
_ => ControlFlow::Break(NotUniqueParam::NotParam(c.into())),
}
}
}
/// Lint impls of auto traits if they are likely to have /// Lint impls of auto traits if they are likely to have
/// unsound or surprising effects on auto impls. /// unsound or surprising effects on auto impls.
fn lint_auto_trait_impls(tcx: TyCtxt<'_>, trait_def_id: DefId, impls: &[LocalDefId]) { fn lint_auto_trait_impls(tcx: TyCtxt<'_>, trait_def_id: DefId, impls: &[LocalDefId]) {
@ -400,9 +355,9 @@ fn lint_auto_trait_impls(tcx: TyCtxt<'_>, trait_def_id: DefId, impls: &[LocalDef
// Impls which completely cover a given root type are fine as they // Impls which completely cover a given root type are fine as they
// disable auto impls entirely. So only lint if the substs // disable auto impls entirely. So only lint if the substs
// are not a permutation of the identity substs. // are not a permutation of the identity substs.
match substs.visit_with(&mut AreUniqueParamsVisitor::default()) { match tcx.uses_unique_generic_params(substs, IgnoreRegions::Yes) {
ControlFlow::Continue(()) => {} // ok Ok(()) => {} // ok
ControlFlow::Break(arg) => { Err(arg) => {
// Ideally: // Ideally:
// //
// - compute the requirements for the auto impl candidate // - compute the requirements for the auto impl candidate
@ -429,13 +384,21 @@ fn lint_auto_trait_impls(tcx: TyCtxt<'_>, trait_def_id: DefId, impls: &[LocalDef
tcx.hir().local_def_id_to_hir_id(impl_def_id), tcx.hir().local_def_id_to_hir_id(impl_def_id),
tcx.def_span(impl_def_id), tcx.def_span(impl_def_id),
|err| { |err| {
let item_span = tcx.def_span(self_type_did);
let self_descr = tcx.def_kind(self_type_did).descr(self_type_did);
let mut err = err.build(&format!( let mut err = err.build(&format!(
"cross-crate traits with a default impl, like `{}`, \ "cross-crate traits with a default impl, like `{}`, \
should not be specialized", should not be specialized",
tcx.def_path_str(trait_def_id), tcx.def_path_str(trait_def_id),
)); ));
let item_span = tcx.def_span(self_type_did); match arg {
let self_descr = tcx.def_kind(self_type_did).descr(self_type_did); ty::util::NotUniqueParam::DuplicateParam(arg) => {
err.note(&format!("`{}` is mentioned multiple times", arg));
}
ty::util::NotUniqueParam::NotParam(arg) => {
err.note(&format!("`{}` is not a generic parameter", arg));
}
}
err.span_note( err.span_note(
item_span, item_span,
&format!( &format!(
@ -443,14 +406,6 @@ fn lint_auto_trait_impls(tcx: TyCtxt<'_>, trait_def_id: DefId, impls: &[LocalDef
self_descr, self_descr,
), ),
); );
match arg {
NotUniqueParam::DuplicateParam(arg) => {
err.note(&format!("`{}` is mentioned multiple times", arg));
}
NotUniqueParam::NotParam(arg) => {
err.note(&format!("`{}` is not a generic parameter", arg));
}
}
err.emit(); err.emit();
}, },
); );

View file

@ -11,12 +11,12 @@ LL | #![deny(suspicious_auto_trait_impls)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this will change its meaning in a future release! = warning: this will change its meaning in a future release!
= note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367> = note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367>
= note: `&T` is not a generic parameter
note: try using the same sequence of generic parameters as the struct definition note: try using the same sequence of generic parameters as the struct definition
--> $DIR/suspicious-impls-lint.rs:8:1 --> $DIR/suspicious-impls-lint.rs:8:1
| |
LL | struct MayImplementSendErr<T>(T); LL | struct MayImplementSendErr<T>(T);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: `&T` is not a generic parameter
error: cross-crate traits with a default impl, like `Send`, should not be specialized error: cross-crate traits with a default impl, like `Send`, should not be specialized
--> $DIR/suspicious-impls-lint.rs:21:1 --> $DIR/suspicious-impls-lint.rs:21:1
@ -26,12 +26,12 @@ LL | unsafe impl Send for ContainsVec<i32> {}
| |
= warning: this will change its meaning in a future release! = warning: this will change its meaning in a future release!
= note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367> = note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367>
= note: `i32` is not a generic parameter
note: try using the same sequence of generic parameters as the struct definition note: try using the same sequence of generic parameters as the struct definition
--> $DIR/suspicious-impls-lint.rs:20:1 --> $DIR/suspicious-impls-lint.rs:20:1
| |
LL | struct ContainsVec<T>(Vec<T>); LL | struct ContainsVec<T>(Vec<T>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: `i32` is not a generic parameter
error: cross-crate traits with a default impl, like `Send`, should not be specialized error: cross-crate traits with a default impl, like `Send`, should not be specialized
--> $DIR/suspicious-impls-lint.rs:32:1 --> $DIR/suspicious-impls-lint.rs:32:1
@ -41,12 +41,12 @@ LL | unsafe impl<T: Send> Send for TwoParamsSame<T, T> {}
| |
= warning: this will change its meaning in a future release! = warning: this will change its meaning in a future release!
= note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367> = note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367>
= note: `T` is mentioned multiple times
note: try using the same sequence of generic parameters as the struct definition note: try using the same sequence of generic parameters as the struct definition
--> $DIR/suspicious-impls-lint.rs:31:1 --> $DIR/suspicious-impls-lint.rs:31:1
| |
LL | struct TwoParamsSame<T, U>(T, U); LL | struct TwoParamsSame<T, U>(T, U);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: `T` is mentioned multiple times
error: cross-crate traits with a default impl, like `Send`, should not be specialized error: cross-crate traits with a default impl, like `Send`, should not be specialized
--> $DIR/suspicious-impls-lint.rs:40:1 --> $DIR/suspicious-impls-lint.rs:40:1
@ -56,12 +56,12 @@ LL | unsafe impl<T> Send for WithPhantomDataSend<*const T, i8> {}
| |
= warning: this will change its meaning in a future release! = warning: this will change its meaning in a future release!
= note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367> = note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367>
= note: `*const T` is not a generic parameter
note: try using the same sequence of generic parameters as the struct definition note: try using the same sequence of generic parameters as the struct definition
--> $DIR/suspicious-impls-lint.rs:39:1 --> $DIR/suspicious-impls-lint.rs:39:1
| |
LL | pub struct WithPhantomDataSend<T, U>(PhantomData<T>, U); LL | pub struct WithPhantomDataSend<T, U>(PhantomData<T>, U);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: `*const T` is not a generic parameter
error: cross-crate traits with a default impl, like `Sync`, should not be specialized error: cross-crate traits with a default impl, like `Sync`, should not be specialized
--> $DIR/suspicious-impls-lint.rs:46:1 --> $DIR/suspicious-impls-lint.rs:46:1
@ -71,12 +71,12 @@ LL | unsafe impl<T> Sync for WithLifetime<'static, Vec<T>> {}
| |
= warning: this will change its meaning in a future release! = warning: this will change its meaning in a future release!
= note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367> = note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367>
= note: `Vec<T>` is not a generic parameter
note: try using the same sequence of generic parameters as the struct definition note: try using the same sequence of generic parameters as the struct definition
--> $DIR/suspicious-impls-lint.rs:44:1 --> $DIR/suspicious-impls-lint.rs:44:1
| |
LL | pub struct WithLifetime<'a, T>(&'a (), T); LL | pub struct WithLifetime<'a, T>(&'a (), T);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: `Vec<T>` is not a generic parameter
error: aborting due to 5 previous errors error: aborting due to 5 previous errors

View file

@ -8,7 +8,8 @@ LL | | }
LL | | } LL | | }
| |_^ | |_^
| |
note: use the same sequence of generic type, lifetime and const parameters as the struct definition = note: `i32` is not a generic parameter
note: use the same sequence of generic lifetime, type and const parameters as the struct definition
--> $DIR/issue-38868.rs:1:1 --> $DIR/issue-38868.rs:1:1
| |
LL | / pub struct List<T> { LL | / pub struct List<T> {

View file

@ -32,9 +32,7 @@ impl<'al,'adds_bnd> Drop for L<'al,'adds_bnd> where 'adds_bnd:'al { // RE
impl<'ml> Drop for M<'ml> { fn drop(&mut self) { } } // ACCEPT impl<'ml> Drop for M<'ml> { fn drop(&mut self) { } } // ACCEPT
impl Drop for N<'static> { fn drop(&mut self) { } } // REJECT impl Drop for N<'static> { fn drop(&mut self) { } } // REJECT
//~^ ERROR mismatched types //~^ ERROR `Drop` impls cannot be specialized
//~| expected struct `N<'n>`
//~| found struct `N<'static>`
impl<COkNoBound> Drop for O<COkNoBound> { fn drop(&mut self) { } } // ACCEPT impl<COkNoBound> Drop for O<COkNoBound> { fn drop(&mut self) { } } // ACCEPT
@ -57,7 +55,7 @@ impl<One> Drop for V<One,One> { fn drop(&mut self) { } } // REJECT
//~^ ERROR `Drop` impls cannot be specialized //~^ ERROR `Drop` impls cannot be specialized
impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT
//~^ ERROR cannot infer an appropriate lifetime for lifetime parameter `'lw` //~^ ERROR `Drop` impls cannot be specialized
impl Drop for X<3> { fn drop(&mut self) { } } // REJECT impl Drop for X<3> { fn drop(&mut self) { } } // REJECT
//~^ ERROR `Drop` impls cannot be specialized //~^ ERROR `Drop` impls cannot be specialized

View file

@ -22,35 +22,34 @@ note: the implementor must specify the same requirement
LL | struct L<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 } LL | struct L<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types error[E0366]: `Drop` impls cannot be specialized
--> $DIR/reject-specialized-drops-8142.rs:34:1 --> $DIR/reject-specialized-drops-8142.rs:34:1
| |
LL | impl Drop for N<'static> { fn drop(&mut self) { } } // REJECT LL | impl Drop for N<'static> { fn drop(&mut self) { } } // REJECT
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: expected struct `N<'n>` = note: `'static` is not a generic parameter
found struct `N<'static>` note: use the same sequence of generic lifetime, type and const parameters as the struct definition
note: the lifetime `'n` as defined here... --> $DIR/reject-specialized-drops-8142.rs:7:1
--> $DIR/reject-specialized-drops-8142.rs:7:10
| |
LL | struct N<'n> { x: &'n i8 } LL | struct N<'n> { x: &'n i8 }
| ^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...does not necessarily outlive the static lifetime
error[E0366]: `Drop` impls cannot be specialized error[E0366]: `Drop` impls cannot be specialized
--> $DIR/reject-specialized-drops-8142.rs:41:1 --> $DIR/reject-specialized-drops-8142.rs:39:1
| |
LL | impl Drop for P<i8> { fn drop(&mut self) { } } // REJECT LL | impl Drop for P<i8> { fn drop(&mut self) { } } // REJECT
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
note: use the same sequence of generic type, lifetime and const parameters as the struct definition = note: `i8` is not a generic parameter
note: use the same sequence of generic lifetime, type and const parameters as the struct definition
--> $DIR/reject-specialized-drops-8142.rs:9:1 --> $DIR/reject-specialized-drops-8142.rs:9:1
| |
LL | struct P<Tp> { x: *const Tp } LL | struct P<Tp> { x: *const Tp }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not
--> $DIR/reject-specialized-drops-8142.rs:44:14 --> $DIR/reject-specialized-drops-8142.rs:42:14
| |
LL | impl<AddsBnd:Bound> Drop for Q<AddsBnd> { fn drop(&mut self) { } } // REJECT LL | impl<AddsBnd:Bound> Drop for Q<AddsBnd> { fn drop(&mut self) { } } // REJECT
| ^^^^^ | ^^^^^
@ -62,7 +61,7 @@ LL | struct Q<Tq> { x: *const Tq }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0367]: `Drop` impl requires `AddsRBnd: 'rbnd` but the struct it is implemented for does not error[E0367]: `Drop` impl requires `AddsRBnd: 'rbnd` but the struct it is implemented for does not
--> $DIR/reject-specialized-drops-8142.rs:47:21 --> $DIR/reject-specialized-drops-8142.rs:45:21
| |
LL | impl<'rbnd,AddsRBnd:'rbnd> Drop for R<AddsRBnd> { fn drop(&mut self) { } } // REJECT LL | impl<'rbnd,AddsRBnd:'rbnd> Drop for R<AddsRBnd> { fn drop(&mut self) { } } // REJECT
| ^^^^^ | ^^^^^
@ -74,67 +73,59 @@ LL | struct R<Tr> { x: *const Tr }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0366]: `Drop` impls cannot be specialized error[E0366]: `Drop` impls cannot be specialized
--> $DIR/reject-specialized-drops-8142.rs:56:1 --> $DIR/reject-specialized-drops-8142.rs:54:1
| |
LL | impl<One> Drop for V<One,One> { fn drop(&mut self) { } } // REJECT LL | impl<One> Drop for V<One,One> { fn drop(&mut self) { } } // REJECT
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
note: use the same sequence of generic type, lifetime and const parameters as the struct definition = note: `One` is mentioned multiple times
note: use the same sequence of generic lifetime, type and const parameters as the struct definition
--> $DIR/reject-specialized-drops-8142.rs:15:1 --> $DIR/reject-specialized-drops-8142.rs:15:1
| |
LL | struct V<Tva, Tvb> { x: *const Tva, y: *const Tvb } LL | struct V<Tva, Tvb> { x: *const Tva, y: *const Tvb }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'lw` due to conflicting requirements error[E0366]: `Drop` impls cannot be specialized
--> $DIR/reject-specialized-drops-8142.rs:59:1 --> $DIR/reject-specialized-drops-8142.rs:57:1
| |
LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
note: first, the lifetime cannot outlive the lifetime `'l1` as defined here... = note: `'lw` is mentioned multiple times
--> $DIR/reject-specialized-drops-8142.rs:16:10 note: use the same sequence of generic lifetime, type and const parameters as the struct definition
--> $DIR/reject-specialized-drops-8142.rs:16:1
| |
LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 }
| ^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...but the lifetime must also be valid for the lifetime `'l2` as defined here...
--> $DIR/reject-specialized-drops-8142.rs:16:15
|
LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 }
| ^^^
note: ...so that the types are compatible
--> $DIR/reject-specialized-drops-8142.rs:59:1
|
LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `W<'l1, 'l2>`
found `W<'_, '_>`
error[E0366]: `Drop` impls cannot be specialized error[E0366]: `Drop` impls cannot be specialized
--> $DIR/reject-specialized-drops-8142.rs:62:1 --> $DIR/reject-specialized-drops-8142.rs:60:1
| |
LL | impl Drop for X<3> { fn drop(&mut self) { } } // REJECT LL | impl Drop for X<3> { fn drop(&mut self) { } } // REJECT
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
note: use the same sequence of generic type, lifetime and const parameters as the struct definition = note: `3_usize` is not a generic parameter
note: use the same sequence of generic lifetime, type and const parameters as the struct definition
--> $DIR/reject-specialized-drops-8142.rs:17:1 --> $DIR/reject-specialized-drops-8142.rs:17:1
| |
LL | struct X<const Ca: usize>; LL | struct X<const Ca: usize>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0366]: `Drop` impls cannot be specialized error[E0366]: `Drop` impls cannot be specialized
--> $DIR/reject-specialized-drops-8142.rs:65:1 --> $DIR/reject-specialized-drops-8142.rs:63:1
| |
LL | impl<const Ca: usize> Drop for Y<Ca, Ca> { fn drop(&mut self) { } } // REJECT LL | impl<const Ca: usize> Drop for Y<Ca, Ca> { fn drop(&mut self) { } } // REJECT
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
note: use the same sequence of generic type, lifetime and const parameters as the struct definition = note: `Ca` is mentioned multiple times
note: use the same sequence of generic lifetime, type and const parameters as the struct definition
--> $DIR/reject-specialized-drops-8142.rs:18:1 --> $DIR/reject-specialized-drops-8142.rs:18:1
| |
LL | struct Y<const Ca: usize, const Cb: usize>; LL | struct Y<const Ca: usize, const Cb: usize>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the enum it is implemented for does not error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the enum it is implemented for does not
--> $DIR/reject-specialized-drops-8142.rs:68:14 --> $DIR/reject-specialized-drops-8142.rs:66:14
| |
LL | impl<AddsBnd:Bound> Drop for Enum<AddsBnd> { fn drop(&mut self) { } } // REJECT LL | impl<AddsBnd:Bound> Drop for Enum<AddsBnd> { fn drop(&mut self) { } } // REJECT
| ^^^^^ | ^^^^^
@ -146,7 +137,7 @@ LL | enum Enum<T> { Variant(T) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not
--> $DIR/reject-specialized-drops-8142.rs:71:14 --> $DIR/reject-specialized-drops-8142.rs:69:14
| |
LL | impl<AddsBnd:Bound> Drop for TupleStruct<AddsBnd> { fn drop(&mut self) { } } // REJECT LL | impl<AddsBnd:Bound> Drop for TupleStruct<AddsBnd> { fn drop(&mut self) { } } // REJECT
| ^^^^^ | ^^^^^
@ -158,7 +149,7 @@ LL | struct TupleStruct<T>(T);
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the union it is implemented for does not error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the union it is implemented for does not
--> $DIR/reject-specialized-drops-8142.rs:74:21 --> $DIR/reject-specialized-drops-8142.rs:72:21
| |
LL | impl<AddsBnd:Copy + Bound> Drop for Union<AddsBnd> { fn drop(&mut self) { } } // REJECT LL | impl<AddsBnd:Copy + Bound> Drop for Union<AddsBnd> { fn drop(&mut self) { } } // REJECT
| ^^^^^ | ^^^^^
@ -171,5 +162,5 @@ LL | union Union<T: Copy> { f: T }
error: aborting due to 13 previous errors error: aborting due to 13 previous errors
Some errors have detailed explanations: E0308, E0366, E0367, E0495. Some errors have detailed explanations: E0366, E0367.
For more information about an error, try `rustc --explain E0308`. For more information about an error, try `rustc --explain E0366`.