Rollup merge of #137764 - compiler-errors:always-applicable-negative-impl, r=lcnr
Ensure that negative auto impls are always applicable r? lcnr (or reassign if you dont want to review) https://github.com/rust-lang/rust/issues/68318#issuecomment-2689265030
This commit is contained in:
commit
00132141c7
23 changed files with 359 additions and 151 deletions
|
@ -1,3 +1,5 @@
|
||||||
|
use std::alloc::Allocator;
|
||||||
|
|
||||||
#[rustc_on_unimplemented(message = "`{Self}` doesn't implement `DynSend`. \
|
#[rustc_on_unimplemented(message = "`{Self}` doesn't implement `DynSend`. \
|
||||||
Add it to `rustc_data_structures::marker` or use `IntoDynSyncSend` if it's already `Send`")]
|
Add it to `rustc_data_structures::marker` or use `IntoDynSyncSend` if it's already `Send`")]
|
||||||
// This is an auto trait for types which can be sent across threads if `sync::is_dyn_thread_safe()`
|
// This is an auto trait for types which can be sent across threads if `sync::is_dyn_thread_safe()`
|
||||||
|
@ -28,8 +30,8 @@ impls_dyn_send_neg!(
|
||||||
[*const T where T: ?Sized]
|
[*const T where T: ?Sized]
|
||||||
[*mut T where T: ?Sized]
|
[*mut T where T: ?Sized]
|
||||||
[std::ptr::NonNull<T> where T: ?Sized]
|
[std::ptr::NonNull<T> where T: ?Sized]
|
||||||
[std::rc::Rc<T> where T: ?Sized]
|
[std::rc::Rc<T, A> where T: ?Sized, A: Allocator]
|
||||||
[std::rc::Weak<T> where T: ?Sized]
|
[std::rc::Weak<T, A> where T: ?Sized, A: Allocator]
|
||||||
[std::sync::MutexGuard<'_, T> where T: ?Sized]
|
[std::sync::MutexGuard<'_, T> where T: ?Sized]
|
||||||
[std::sync::RwLockReadGuard<'_, T> where T: ?Sized]
|
[std::sync::RwLockReadGuard<'_, T> where T: ?Sized]
|
||||||
[std::sync::RwLockWriteGuard<'_, T> where T: ?Sized]
|
[std::sync::RwLockWriteGuard<'_, T> where T: ?Sized]
|
||||||
|
@ -96,8 +98,8 @@ impls_dyn_sync_neg!(
|
||||||
[std::cell::RefCell<T> where T: ?Sized]
|
[std::cell::RefCell<T> where T: ?Sized]
|
||||||
[std::cell::UnsafeCell<T> where T: ?Sized]
|
[std::cell::UnsafeCell<T> where T: ?Sized]
|
||||||
[std::ptr::NonNull<T> where T: ?Sized]
|
[std::ptr::NonNull<T> where T: ?Sized]
|
||||||
[std::rc::Rc<T> where T: ?Sized]
|
[std::rc::Rc<T, A> where T: ?Sized, A: Allocator]
|
||||||
[std::rc::Weak<T> where T: ?Sized]
|
[std::rc::Weak<T, A> where T: ?Sized, A: Allocator]
|
||||||
[std::cell::OnceCell<T> where T]
|
[std::cell::OnceCell<T> where T]
|
||||||
[std::sync::mpsc::Receiver<T> where T]
|
[std::sync::mpsc::Receiver<T> where T]
|
||||||
[std::sync::mpsc::Sender<T> where T]
|
[std::sync::mpsc::Sender<T> where T]
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
|
//! This module contains methods that assist in checking that impls are general
|
||||||
|
//! enough, i.e. that they always apply to every valid instantaiton of the ADT
|
||||||
|
//! they're implemented for.
|
||||||
|
//!
|
||||||
|
//! This is necessary for `Drop` and negative impls to be well-formed.
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_errors::codes::*;
|
use rustc_errors::codes::*;
|
||||||
use rustc_errors::{ErrorGuaranteed, struct_span_code_err};
|
use rustc_errors::{ErrorGuaranteed, struct_span_code_err};
|
||||||
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
|
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
|
||||||
use rustc_infer::traits::{ObligationCause, ObligationCauseCode};
|
use rustc_infer::traits::{ObligationCause, ObligationCauseCode};
|
||||||
|
use rustc_middle::span_bug;
|
||||||
use rustc_middle::ty::util::CheckRegions;
|
use rustc_middle::ty::util::CheckRegions;
|
||||||
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypingMode};
|
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypingMode};
|
||||||
use rustc_trait_selection::regions::InferCtxtRegionExt;
|
use rustc_trait_selection::regions::InferCtxtRegionExt;
|
||||||
|
@ -27,11 +34,12 @@ use crate::hir::def_id::{DefId, LocalDefId};
|
||||||
/// 3. Any bounds on the generic parameters must be reflected in the
|
/// 3. Any bounds on the generic parameters must be reflected in the
|
||||||
/// struct/enum definition for the nominal type itself (i.e.
|
/// struct/enum definition for the nominal type itself (i.e.
|
||||||
/// cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
|
/// cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
|
||||||
///
|
|
||||||
pub(crate) fn check_drop_impl(
|
pub(crate) fn check_drop_impl(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
drop_impl_did: DefId,
|
drop_impl_did: DefId,
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
|
let drop_impl_did = drop_impl_did.expect_local();
|
||||||
|
|
||||||
match tcx.impl_polarity(drop_impl_did) {
|
match tcx.impl_polarity(drop_impl_did) {
|
||||||
ty::ImplPolarity::Positive => {}
|
ty::ImplPolarity::Positive => {}
|
||||||
ty::ImplPolarity::Negative => {
|
ty::ImplPolarity::Negative => {
|
||||||
|
@ -45,55 +53,107 @@ pub(crate) fn check_drop_impl(
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let dtor_self_type = tcx.type_of(drop_impl_did).instantiate_identity();
|
|
||||||
match dtor_self_type.kind() {
|
tcx.ensure_ok().orphan_check_impl(drop_impl_did)?;
|
||||||
|
|
||||||
|
let dtor_impl_trait_ref = tcx.impl_trait_ref(drop_impl_did).unwrap().instantiate_identity();
|
||||||
|
|
||||||
|
match dtor_impl_trait_ref.self_ty().kind() {
|
||||||
ty::Adt(adt_def, adt_to_impl_args) => {
|
ty::Adt(adt_def, adt_to_impl_args) => {
|
||||||
ensure_drop_params_and_item_params_correspond(
|
ensure_impl_params_and_item_params_correspond(
|
||||||
tcx,
|
tcx,
|
||||||
drop_impl_did.expect_local(),
|
drop_impl_did,
|
||||||
adt_def.did(),
|
adt_def.did(),
|
||||||
adt_to_impl_args,
|
adt_to_impl_args,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
ensure_drop_predicates_are_implied_by_item_defn(
|
ensure_impl_predicates_are_implied_by_item_defn(
|
||||||
tcx,
|
tcx,
|
||||||
drop_impl_did.expect_local(),
|
drop_impl_did,
|
||||||
adt_def.did().expect_local(),
|
adt_def.did(),
|
||||||
adt_to_impl_args,
|
adt_to_impl_args,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// Destructors only work on nominal types. This was
|
span_bug!(tcx.def_span(drop_impl_did), "incoherent impl of Drop");
|
||||||
// already checked by coherence, but compilation may
|
|
||||||
// not have been terminated.
|
|
||||||
let span = tcx.def_span(drop_impl_did);
|
|
||||||
let reported = tcx.dcx().span_delayed_bug(
|
|
||||||
span,
|
|
||||||
format!("should have been rejected by coherence check: {dtor_self_type}"),
|
|
||||||
);
|
|
||||||
Err(reported)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ensure_drop_params_and_item_params_correspond<'tcx>(
|
pub(crate) fn check_negative_auto_trait_impl<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
drop_impl_did: LocalDefId,
|
impl_def_id: LocalDefId,
|
||||||
self_type_did: DefId,
|
impl_trait_ref: ty::TraitRef<'tcx>,
|
||||||
|
polarity: ty::ImplPolarity,
|
||||||
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
|
let ty::ImplPolarity::Negative = polarity else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
|
if !tcx.trait_is_auto(impl_trait_ref.def_id) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if tcx.defaultness(impl_def_id).is_default() {
|
||||||
|
tcx.dcx().span_delayed_bug(tcx.def_span(impl_def_id), "default impl cannot be negative");
|
||||||
|
}
|
||||||
|
|
||||||
|
tcx.ensure_ok().orphan_check_impl(impl_def_id)?;
|
||||||
|
|
||||||
|
match impl_trait_ref.self_ty().kind() {
|
||||||
|
ty::Adt(adt_def, adt_to_impl_args) => {
|
||||||
|
ensure_impl_params_and_item_params_correspond(
|
||||||
|
tcx,
|
||||||
|
impl_def_id,
|
||||||
|
adt_def.did(),
|
||||||
|
adt_to_impl_args,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
ensure_impl_predicates_are_implied_by_item_defn(
|
||||||
|
tcx,
|
||||||
|
impl_def_id,
|
||||||
|
adt_def.did(),
|
||||||
|
adt_to_impl_args,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
if tcx.features().auto_traits() {
|
||||||
|
// NOTE: We ignore the applicability check for negative auto impls
|
||||||
|
// defined in libcore. In the (almost impossible) future where we
|
||||||
|
// stabilize auto impls, then the proper applicability check MUST
|
||||||
|
// be implemented here to handle non-ADT rigid types.
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
span_bug!(tcx.def_span(impl_def_id), "incoherent impl of negative auto trait");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ensure_impl_params_and_item_params_correspond<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
impl_def_id: LocalDefId,
|
||||||
|
adt_def_id: DefId,
|
||||||
adt_to_impl_args: GenericArgsRef<'tcx>,
|
adt_to_impl_args: GenericArgsRef<'tcx>,
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_args, CheckRegions::OnlyParam) else {
|
let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_args, CheckRegions::OnlyParam) else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
let drop_impl_span = tcx.def_span(drop_impl_did);
|
let impl_span = tcx.def_span(impl_def_id);
|
||||||
let item_span = tcx.def_span(self_type_did);
|
let item_span = tcx.def_span(adt_def_id);
|
||||||
let self_descr = tcx.def_descr(self_type_did);
|
let self_descr = tcx.def_descr(adt_def_id);
|
||||||
|
let polarity = match tcx.impl_polarity(impl_def_id) {
|
||||||
|
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
|
||||||
|
ty::ImplPolarity::Negative => "!",
|
||||||
|
};
|
||||||
|
let trait_name = tcx
|
||||||
|
.item_name(tcx.trait_id_of_impl(impl_def_id.to_def_id()).expect("expected impl of trait"));
|
||||||
let mut err = struct_span_code_err!(
|
let mut err = struct_span_code_err!(
|
||||||
tcx.dcx(),
|
tcx.dcx(),
|
||||||
drop_impl_span,
|
impl_span,
|
||||||
E0366,
|
E0366,
|
||||||
"`Drop` impls cannot be specialized"
|
"`{polarity}{trait_name}` impls cannot be specialized",
|
||||||
);
|
);
|
||||||
match arg {
|
match arg {
|
||||||
ty::util::NotUniqueParam::DuplicateParam(arg) => {
|
ty::util::NotUniqueParam::DuplicateParam(arg) => {
|
||||||
|
@ -116,17 +176,22 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
|
||||||
/// Confirms that all predicates defined on the `Drop` impl (`drop_impl_def_id`) are able to be
|
/// Confirms that all predicates defined on the `Drop` impl (`drop_impl_def_id`) are able to be
|
||||||
/// proven from within `adt_def_id`'s environment. I.e. all the predicates on the impl are
|
/// proven from within `adt_def_id`'s environment. I.e. all the predicates on the impl are
|
||||||
/// implied by the ADT being well formed.
|
/// implied by the ADT being well formed.
|
||||||
fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
fn ensure_impl_predicates_are_implied_by_item_defn<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
drop_impl_def_id: LocalDefId,
|
impl_def_id: LocalDefId,
|
||||||
adt_def_id: LocalDefId,
|
adt_def_id: DefId,
|
||||||
adt_to_impl_args: GenericArgsRef<'tcx>,
|
adt_to_impl_args: GenericArgsRef<'tcx>,
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||||
|
|
||||||
let impl_span = tcx.def_span(drop_impl_def_id.to_def_id());
|
let impl_span = tcx.def_span(impl_def_id.to_def_id());
|
||||||
|
let trait_name = tcx
|
||||||
|
.item_name(tcx.trait_id_of_impl(impl_def_id.to_def_id()).expect("expected impl of trait"));
|
||||||
|
let polarity = match tcx.impl_polarity(impl_def_id) {
|
||||||
|
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
|
||||||
|
ty::ImplPolarity::Negative => "!",
|
||||||
|
};
|
||||||
// Take the param-env of the adt and instantiate the args that show up in
|
// Take the param-env of the adt and instantiate the args that show up in
|
||||||
// the implementation's self type. This gives us the assumptions that the
|
// the implementation's self type. This gives us the assumptions that the
|
||||||
// self ty of the implementation is allowed to know just from it being a
|
// self ty of the implementation is allowed to know just from it being a
|
||||||
|
@ -145,17 +210,21 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
||||||
let adt_env =
|
let adt_env =
|
||||||
ty::EarlyBinder::bind(tcx.param_env(adt_def_id)).instantiate(tcx, adt_to_impl_args);
|
ty::EarlyBinder::bind(tcx.param_env(adt_def_id)).instantiate(tcx, adt_to_impl_args);
|
||||||
|
|
||||||
let fresh_impl_args = infcx.fresh_args_for_item(impl_span, drop_impl_def_id.to_def_id());
|
let fresh_impl_args = infcx.fresh_args_for_item(impl_span, impl_def_id.to_def_id());
|
||||||
let fresh_adt_ty =
|
let fresh_adt_ty =
|
||||||
tcx.impl_trait_ref(drop_impl_def_id).unwrap().instantiate(tcx, fresh_impl_args).self_ty();
|
tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, fresh_impl_args).self_ty();
|
||||||
|
|
||||||
ocx.eq(&ObligationCause::dummy_with_span(impl_span), adt_env, fresh_adt_ty, impl_adt_ty)
|
ocx.eq(&ObligationCause::dummy_with_span(impl_span), adt_env, fresh_adt_ty, impl_adt_ty)
|
||||||
.unwrap();
|
.expect("equating fully generic trait ref should never fail");
|
||||||
|
|
||||||
for (clause, span) in tcx.predicates_of(drop_impl_def_id).instantiate(tcx, fresh_impl_args) {
|
for (clause, span) in tcx.predicates_of(impl_def_id).instantiate(tcx, fresh_impl_args) {
|
||||||
let normalize_cause = traits::ObligationCause::misc(span, adt_def_id);
|
let normalize_cause = traits::ObligationCause::misc(span, impl_def_id);
|
||||||
let pred = ocx.normalize(&normalize_cause, adt_env, clause);
|
let pred = ocx.normalize(&normalize_cause, adt_env, clause);
|
||||||
let cause = traits::ObligationCause::new(span, adt_def_id, ObligationCauseCode::DropImpl);
|
let cause = traits::ObligationCause::new(
|
||||||
|
span,
|
||||||
|
impl_def_id,
|
||||||
|
ObligationCauseCode::AlwaysApplicableImpl,
|
||||||
|
);
|
||||||
ocx.register_obligation(traits::Obligation::new(tcx, cause, adt_env, pred));
|
ocx.register_obligation(traits::Obligation::new(tcx, cause, adt_env, pred));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,13 +242,13 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
||||||
let root_predicate = error.root_obligation.predicate;
|
let root_predicate = error.root_obligation.predicate;
|
||||||
if root_predicates.insert(root_predicate) {
|
if root_predicates.insert(root_predicate) {
|
||||||
let item_span = tcx.def_span(adt_def_id);
|
let item_span = tcx.def_span(adt_def_id);
|
||||||
let self_descr = tcx.def_descr(adt_def_id.to_def_id());
|
let self_descr = tcx.def_descr(adt_def_id);
|
||||||
guar = Some(
|
guar = Some(
|
||||||
struct_span_code_err!(
|
struct_span_code_err!(
|
||||||
tcx.dcx(),
|
tcx.dcx(),
|
||||||
error.root_obligation.cause.span,
|
error.root_obligation.cause.span,
|
||||||
E0367,
|
E0367,
|
||||||
"`Drop` impl requires `{root_predicate}` \
|
"`{polarity}{trait_name}` impl requires `{root_predicate}` \
|
||||||
but the {self_descr} it is implemented for does not",
|
but the {self_descr} it is implemented for does not",
|
||||||
)
|
)
|
||||||
.with_span_note(item_span, "the implementor must specify the same requirement")
|
.with_span_note(item_span, "the implementor must specify the same requirement")
|
||||||
|
@ -190,12 +259,12 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
||||||
return Err(guar.unwrap());
|
return Err(guar.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
let errors = ocx.infcx.resolve_regions(adt_def_id, adt_env, []);
|
let errors = ocx.infcx.resolve_regions(impl_def_id, adt_env, []);
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
let mut guar = None;
|
let mut guar = None;
|
||||||
for error in errors {
|
for error in errors {
|
||||||
let item_span = tcx.def_span(adt_def_id);
|
let item_span = tcx.def_span(adt_def_id);
|
||||||
let self_descr = tcx.def_descr(adt_def_id.to_def_id());
|
let self_descr = tcx.def_descr(adt_def_id);
|
||||||
let outlives = match error {
|
let outlives = match error {
|
||||||
RegionResolutionError::ConcreteFailure(_, a, b) => format!("{b}: {a}"),
|
RegionResolutionError::ConcreteFailure(_, a, b) => format!("{b}: {a}"),
|
||||||
RegionResolutionError::GenericBoundFailure(_, generic, r) => {
|
RegionResolutionError::GenericBoundFailure(_, generic, r) => {
|
||||||
|
@ -212,7 +281,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
||||||
tcx.dcx(),
|
tcx.dcx(),
|
||||||
error.origin().span(),
|
error.origin().span(),
|
||||||
E0367,
|
E0367,
|
||||||
"`Drop` impl requires `{outlives}` \
|
"`{polarity}{trait_name}` impl requires `{outlives}` \
|
||||||
but the {self_descr} it is implemented for does not",
|
but the {self_descr} it is implemented for does not",
|
||||||
)
|
)
|
||||||
.with_span_note(item_span, "the implementor must specify the same requirement")
|
.with_span_note(item_span, "the implementor must specify the same requirement")
|
|
@ -62,9 +62,9 @@ a type parameter).
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
pub mod always_applicable;
|
||||||
mod check;
|
mod check;
|
||||||
mod compare_impl_item;
|
mod compare_impl_item;
|
||||||
pub mod dropck;
|
|
||||||
mod entry;
|
mod entry;
|
||||||
pub mod intrinsic;
|
pub mod intrinsic;
|
||||||
pub mod intrinsicck;
|
pub mod intrinsicck;
|
||||||
|
@ -113,11 +113,11 @@ pub fn provide(providers: &mut Providers) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Destructor> {
|
fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Destructor> {
|
||||||
tcx.calculate_dtor(def_id.to_def_id(), dropck::check_drop_impl)
|
tcx.calculate_dtor(def_id.to_def_id(), always_applicable::check_drop_impl)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn adt_async_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::AsyncDestructor> {
|
fn adt_async_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::AsyncDestructor> {
|
||||||
tcx.calculate_async_dtor(def_id.to_def_id(), dropck::check_drop_impl)
|
tcx.calculate_async_dtor(def_id.to_def_id(), always_applicable::check_drop_impl)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a `DefId` for an opaque type in return position, find its parent item's return
|
/// Given a `DefId` for an opaque type in return position, find its parent item's return
|
||||||
|
|
|
@ -16,6 +16,7 @@ use rustc_span::{ErrorGuaranteed, sym};
|
||||||
use rustc_type_ir::elaborate;
|
use rustc_type_ir::elaborate;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
|
use crate::check::always_applicable;
|
||||||
use crate::errors;
|
use crate::errors;
|
||||||
|
|
||||||
mod builtin;
|
mod builtin;
|
||||||
|
@ -24,11 +25,12 @@ mod inherent_impls_overlap;
|
||||||
mod orphan;
|
mod orphan;
|
||||||
mod unsafety;
|
mod unsafety;
|
||||||
|
|
||||||
fn check_impl(
|
fn check_impl<'tcx>(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'tcx>,
|
||||||
impl_def_id: LocalDefId,
|
impl_def_id: LocalDefId,
|
||||||
trait_ref: ty::TraitRef<'_>,
|
trait_ref: ty::TraitRef<'tcx>,
|
||||||
trait_def: &ty::TraitDef,
|
trait_def: &'tcx ty::TraitDef,
|
||||||
|
polarity: ty::ImplPolarity,
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
debug!(
|
debug!(
|
||||||
"(checking implementation) adding impl for trait '{:?}', item '{}'",
|
"(checking implementation) adding impl for trait '{:?}', item '{}'",
|
||||||
|
@ -44,6 +46,12 @@ fn check_impl(
|
||||||
|
|
||||||
enforce_trait_manually_implementable(tcx, impl_def_id, trait_ref.def_id, trait_def)
|
enforce_trait_manually_implementable(tcx, impl_def_id, trait_ref.def_id, trait_def)
|
||||||
.and(enforce_empty_impls_for_marker_traits(tcx, impl_def_id, trait_ref.def_id, trait_def))
|
.and(enforce_empty_impls_for_marker_traits(tcx, impl_def_id, trait_ref.def_id, trait_def))
|
||||||
|
.and(always_applicable::check_negative_auto_trait_impl(
|
||||||
|
tcx,
|
||||||
|
impl_def_id,
|
||||||
|
trait_ref,
|
||||||
|
polarity,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enforce_trait_manually_implementable(
|
fn enforce_trait_manually_implementable(
|
||||||
|
@ -154,16 +162,16 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed>
|
||||||
let mut res = tcx.ensure_ok().specialization_graph_of(def_id);
|
let mut res = tcx.ensure_ok().specialization_graph_of(def_id);
|
||||||
|
|
||||||
for &impl_def_id in impls {
|
for &impl_def_id in impls {
|
||||||
let trait_header = tcx.impl_trait_header(impl_def_id).unwrap();
|
let impl_header = tcx.impl_trait_header(impl_def_id).unwrap();
|
||||||
let trait_ref = trait_header.trait_ref.instantiate_identity();
|
let trait_ref = impl_header.trait_ref.instantiate_identity();
|
||||||
let trait_def = tcx.trait_def(trait_ref.def_id);
|
let trait_def = tcx.trait_def(trait_ref.def_id);
|
||||||
|
|
||||||
res = res
|
res = res
|
||||||
.and(check_impl(tcx, impl_def_id, trait_ref, trait_def))
|
.and(check_impl(tcx, impl_def_id, trait_ref, trait_def, impl_header.polarity))
|
||||||
.and(check_object_overlap(tcx, impl_def_id, trait_ref))
|
.and(check_object_overlap(tcx, impl_def_id, trait_ref))
|
||||||
.and(unsafety::check_item(tcx, impl_def_id, trait_header, trait_def))
|
.and(unsafety::check_item(tcx, impl_def_id, impl_header, trait_def))
|
||||||
.and(tcx.ensure_ok().orphan_check_impl(impl_def_id))
|
.and(tcx.ensure_ok().orphan_check_impl(impl_def_id))
|
||||||
.and(builtin::check_trait(tcx, def_id, impl_def_id, trait_header));
|
.and(builtin::check_trait(tcx, def_id, impl_def_id, impl_header));
|
||||||
}
|
}
|
||||||
|
|
||||||
res
|
res
|
||||||
|
|
|
@ -397,9 +397,9 @@ pub enum ObligationCauseCode<'tcx> {
|
||||||
|
|
||||||
RustCall,
|
RustCall,
|
||||||
|
|
||||||
/// Obligations to prove that a `std::ops::Drop` impl is not stronger than
|
/// Obligations to prove that a `Drop` or negative auto trait impl is not stronger than
|
||||||
/// the ADT it's being implemented for.
|
/// the ADT it's being implemented for.
|
||||||
DropImpl,
|
AlwaysApplicableImpl,
|
||||||
|
|
||||||
/// Requirement for a `const N: Ty` to implement `Ty: ConstParamTy`
|
/// Requirement for a `const N: Ty` to implement `Ty: ConstParamTy`
|
||||||
ConstParam(Ty<'tcx>),
|
ConstParam(Ty<'tcx>),
|
||||||
|
|
|
@ -2695,7 +2695,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
| ObligationCauseCode::LetElse
|
| ObligationCauseCode::LetElse
|
||||||
| ObligationCauseCode::BinOp { .. }
|
| ObligationCauseCode::BinOp { .. }
|
||||||
| ObligationCauseCode::AscribeUserTypeProvePredicate(..)
|
| ObligationCauseCode::AscribeUserTypeProvePredicate(..)
|
||||||
| ObligationCauseCode::DropImpl
|
| ObligationCauseCode::AlwaysApplicableImpl
|
||||||
| ObligationCauseCode::ConstParam(_)
|
| ObligationCauseCode::ConstParam(_)
|
||||||
| ObligationCauseCode::ReferenceOutlivesReferent(..)
|
| ObligationCauseCode::ReferenceOutlivesReferent(..)
|
||||||
| ObligationCauseCode::ObjectTypeBound(..) => {}
|
| ObligationCauseCode::ObjectTypeBound(..) => {}
|
||||||
|
|
|
@ -778,7 +778,6 @@ impl<T> From<T> for T {
|
||||||
///
|
///
|
||||||
/// [#64715]: https://github.com/rust-lang/rust/issues/64715
|
/// [#64715]: https://github.com/rust-lang/rust/issues/64715
|
||||||
#[stable(feature = "convert_infallible", since = "1.34.0")]
|
#[stable(feature = "convert_infallible", since = "1.34.0")]
|
||||||
#[allow(unused_attributes)] // FIXME(#58633): do a principled fix instead.
|
|
||||||
#[rustc_reservation_impl = "permitting this impl would forbid us from adding \
|
#[rustc_reservation_impl = "permitting this impl would forbid us from adding \
|
||||||
`impl<T> From<!> for T` later; see rust-lang/rust#64715 for details"]
|
`impl<T> From<!> for T` later; see rust-lang/rust#64715 for details"]
|
||||||
impl<T> From<!> for T {
|
impl<T> From<!> for T {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
extern crate rustdoc_impl_parts_crosscrate;
|
extern crate rustdoc_impl_parts_crosscrate;
|
||||||
|
|
||||||
pub struct Bar<T> { t: T }
|
pub struct Bar<T: Copy + Send> { t: T }
|
||||||
|
|
||||||
// The output file is html embedded in javascript, so the html tags
|
// The output file is html embedded in javascript, so the html tags
|
||||||
// aren't stripped by the processing script and we can't check for the
|
// aren't stripped by the processing script and we can't check for the
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
pub auto trait AnAutoTrait {}
|
pub auto trait AnAutoTrait {}
|
||||||
|
|
||||||
pub struct Foo<T> { field: T }
|
pub struct Foo<T: Clone + Sync> { field: T }
|
||||||
|
|
||||||
//@ has impl_parts/struct.Foo.html '//*[@class="impl"]//h3[@class="code-header"]' \
|
//@ has impl_parts/struct.Foo.html '//*[@class="impl"]//h3[@class="code-header"]' \
|
||||||
// "impl<T> !AnAutoTrait for Foo<T>where T: Sync + Clone,"
|
// "impl<T> !AnAutoTrait for Foo<T>where T: Sync + Clone,"
|
||||||
|
|
|
@ -8,10 +8,14 @@ struct TestType<T>(::std::marker::PhantomData<T>);
|
||||||
|
|
||||||
unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
|
unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
|
||||||
|
|
||||||
impl<T: MyTrait> !Send for TestType<T> {} //~ ERROR found both positive and negative implementation
|
impl<T: MyTrait> !Send for TestType<T> {}
|
||||||
|
//~^ ERROR found both positive and negative implementation
|
||||||
|
//~| ERROR `!Send` impl requires `T: MyTrait` but the struct it is implemented for does not
|
||||||
|
|
||||||
unsafe impl<T: 'static> Send for TestType<T> {} //~ ERROR conflicting implementations
|
unsafe impl<T: 'static> Send for TestType<T> {}
|
||||||
|
//~^ ERROR conflicting implementations
|
||||||
|
|
||||||
impl !Send for TestType<i32> {}
|
impl !Send for TestType<i32> {}
|
||||||
|
//~^ ERROR `!Send` impls cannot be specialized
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -8,7 +8,7 @@ LL | impl<T: MyTrait> !Send for TestType<T> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here
|
||||||
|
|
||||||
error[E0119]: conflicting implementations of trait `Send` for type `TestType<_>`
|
error[E0119]: conflicting implementations of trait `Send` for type `TestType<_>`
|
||||||
--> $DIR/coherence-conflicting-negative-trait-impl.rs:13:1
|
--> $DIR/coherence-conflicting-negative-trait-impl.rs:15:1
|
||||||
|
|
|
|
||||||
LL | unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
|
LL | unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
|
||||||
| ------------------------------------------------------ first implementation here
|
| ------------------------------------------------------ first implementation here
|
||||||
|
@ -16,7 +16,32 @@ LL | unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
|
||||||
LL | unsafe impl<T: 'static> Send for TestType<T> {}
|
LL | unsafe impl<T: 'static> Send for TestType<T> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error[E0367]: `!Send` impl requires `T: MyTrait` but the struct it is implemented for does not
|
||||||
|
--> $DIR/coherence-conflicting-negative-trait-impl.rs:11:9
|
||||||
|
|
|
||||||
|
LL | impl<T: MyTrait> !Send for TestType<T> {}
|
||||||
|
| ^^^^^^^
|
||||||
|
|
|
||||||
|
note: the implementor must specify the same requirement
|
||||||
|
--> $DIR/coherence-conflicting-negative-trait-impl.rs:7:1
|
||||||
|
|
|
||||||
|
LL | struct TestType<T>(::std::marker::PhantomData<T>);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Some errors have detailed explanations: E0119, E0751.
|
error[E0366]: `!Send` impls cannot be specialized
|
||||||
|
--> $DIR/coherence-conflicting-negative-trait-impl.rs:18:1
|
||||||
|
|
|
||||||
|
LL | impl !Send for TestType<i32> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `i32` is not a generic parameter
|
||||||
|
note: use the same sequence of generic lifetime, type and const parameters as the struct definition
|
||||||
|
--> $DIR/coherence-conflicting-negative-trait-impl.rs:7:1
|
||||||
|
|
|
||||||
|
LL | struct TestType<T>(::std::marker::PhantomData<T>);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0119, E0366, E0367, E0751.
|
||||||
For more information about an error, try `rustc --explain E0119`.
|
For more information about an error, try `rustc --explain E0119`.
|
||||||
|
|
|
@ -1,9 +1,3 @@
|
||||||
error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
|
|
||||||
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1
|
|
||||||
|
|
|
||||||
LL | impl !Marker1 for dyn Object + Marker2 {}
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
|
|
||||||
|
|
||||||
error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)`
|
error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)`
|
||||||
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1
|
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1
|
||||||
|
|
|
|
||||||
|
@ -12,11 +6,11 @@ LL | impl !Marker1 for dyn Object + Marker2 {}
|
||||||
|
|
|
|
||||||
= note: a trait object implements `Marker1` if and only if `Marker1` is one of the trait object's trait bounds
|
= note: a trait object implements `Marker1` if and only if `Marker1` is one of the trait object's trait bounds
|
||||||
|
|
||||||
error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
|
error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
|
||||||
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:18:1
|
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1
|
||||||
|
|
|
|
||||||
LL | impl !Marker2 for dyn Object + Marker2 {}
|
LL | impl !Marker1 for dyn Object + Marker2 {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
|
||||||
|
|
||||||
error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)`
|
error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)`
|
||||||
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:18:1
|
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:18:1
|
||||||
|
@ -26,6 +20,12 @@ LL | impl !Marker2 for dyn Object + Marker2 {}
|
||||||
|
|
|
|
||||||
= note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds
|
= note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds
|
||||||
|
|
||||||
|
error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
|
||||||
|
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:18:1
|
||||||
|
|
|
||||||
|
LL | impl !Marker2 for dyn Object + Marker2 {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
|
||||||
|
|
||||||
error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + 'static)`
|
error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + 'static)`
|
||||||
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:26:1
|
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:26:1
|
||||||
|
|
|
|
||||||
|
|
|
@ -8,12 +8,13 @@ use lib::TheTrait;
|
||||||
struct TheType;
|
struct TheType;
|
||||||
|
|
||||||
impl TheTrait<usize> for isize {}
|
impl TheTrait<usize> for isize {}
|
||||||
//~^ ERROR E0117
|
//~^ ERROR only traits defined in the current crate can be implemented for primitive types
|
||||||
|
|
||||||
impl TheTrait<TheType> for isize {}
|
impl TheTrait<TheType> for isize {}
|
||||||
|
|
||||||
impl TheTrait<isize> for TheType {}
|
impl TheTrait<isize> for TheType {}
|
||||||
|
|
||||||
impl !Send for Vec<isize> {} //~ ERROR E0117
|
impl !Send for Vec<isize> {}
|
||||||
|
//~^ ERROR only traits defined in the current crate can be implemented for types defined outside of the crate
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
//@ check-pass
|
|
||||||
//@ known-bug: #74629
|
|
||||||
|
|
||||||
// Should fail. The `0` and `1` impls overlap, violating coherence. Eg, with
|
|
||||||
// `T = Test, F = ()`, all bounds are true, making both impls applicable.
|
|
||||||
// `Test: Fold<Nil>`, `Test: Fold<()>` are true because of `2`.
|
|
||||||
// `Is<Test>: NotNil` is true because of `auto trait` and lack of negative impl.
|
|
||||||
|
|
||||||
#![feature(negative_impls)]
|
|
||||||
#![feature(auto_traits)]
|
|
||||||
|
|
||||||
struct Nil;
|
|
||||||
struct Cons<H>(H);
|
|
||||||
struct Test;
|
|
||||||
|
|
||||||
trait Fold<F> {}
|
|
||||||
|
|
||||||
impl<T, F> Fold<F> for Cons<T>
|
|
||||||
// 0
|
|
||||||
where
|
|
||||||
T: Fold<Nil>,
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, F> Fold<F> for Cons<T>
|
|
||||||
// 1
|
|
||||||
where
|
|
||||||
T: Fold<F>,
|
|
||||||
private::Is<T>: private::NotNil,
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<F> Fold<F> for Test {} // 2
|
|
||||||
|
|
||||||
mod private {
|
|
||||||
use crate::Nil;
|
|
||||||
|
|
||||||
pub struct Is<T>(T);
|
|
||||||
pub auto trait NotNil {}
|
|
||||||
|
|
||||||
impl !NotNil for Is<Nil> {}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -10,10 +10,13 @@ struct TestType<T>(::std::marker::PhantomData<T>);
|
||||||
|
|
||||||
unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
|
unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
|
||||||
|
|
||||||
impl<T: MyTrait> !Send for TestType<T> {} //~ ERROR found both positive and negative implementation
|
impl<T: MyTrait> !Send for TestType<T> {}
|
||||||
|
//~^ ERROR found both positive and negative implementation
|
||||||
|
//~| ERROR `!Send` impl requires `T: MyTrait` but the struct it is implemented for does not
|
||||||
|
|
||||||
unsafe impl<T: 'static> Send for TestType<T> {} //~ ERROR conflicting implementations
|
unsafe impl<T: 'static> Send for TestType<T> {} //~ ERROR conflicting implementations
|
||||||
|
|
||||||
impl !Send for TestType<i32> {}
|
impl !Send for TestType<i32> {}
|
||||||
|
//~^ ERROR `!Send` impls cannot be specialized
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -8,7 +8,7 @@ LL | impl<T: MyTrait> !Send for TestType<T> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here
|
||||||
|
|
||||||
error[E0119]: conflicting implementations of trait `Send` for type `TestType<_>`
|
error[E0119]: conflicting implementations of trait `Send` for type `TestType<_>`
|
||||||
--> $DIR/issue-106755.rs:15:1
|
--> $DIR/issue-106755.rs:17:1
|
||||||
|
|
|
|
||||||
LL | unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
|
LL | unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
|
||||||
| ------------------------------------------------------ first implementation here
|
| ------------------------------------------------------ first implementation here
|
||||||
|
@ -16,7 +16,32 @@ LL | unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
|
||||||
LL | unsafe impl<T: 'static> Send for TestType<T> {}
|
LL | unsafe impl<T: 'static> Send for TestType<T> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error[E0367]: `!Send` impl requires `T: MyTrait` but the struct it is implemented for does not
|
||||||
|
--> $DIR/issue-106755.rs:13:9
|
||||||
|
|
|
||||||
|
LL | impl<T: MyTrait> !Send for TestType<T> {}
|
||||||
|
| ^^^^^^^
|
||||||
|
|
|
||||||
|
note: the implementor must specify the same requirement
|
||||||
|
--> $DIR/issue-106755.rs:9:1
|
||||||
|
|
|
||||||
|
LL | struct TestType<T>(::std::marker::PhantomData<T>);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Some errors have detailed explanations: E0119, E0751.
|
error[E0366]: `!Send` impls cannot be specialized
|
||||||
|
--> $DIR/issue-106755.rs:19:1
|
||||||
|
|
|
||||||
|
LL | impl !Send for TestType<i32> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= 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-106755.rs:9:1
|
||||||
|
|
|
||||||
|
LL | struct TestType<T>(::std::marker::PhantomData<T>);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0119, E0366, E0367, E0751.
|
||||||
For more information about an error, try `rustc --explain E0119`.
|
For more information about an error, try `rustc --explain E0119`.
|
||||||
|
|
|
@ -6,12 +6,17 @@ struct Z;
|
||||||
|
|
||||||
default impl S {} //~ ERROR inherent impls cannot be `default`
|
default impl S {} //~ ERROR inherent impls cannot be `default`
|
||||||
|
|
||||||
default unsafe impl Send for S {} //~ ERROR impls of auto traits cannot be default
|
default unsafe impl Send for S {}
|
||||||
//~^ ERROR `S` cannot be sent between threads safely
|
//~^ ERROR impls of auto traits cannot be default
|
||||||
default impl !Send for Z {} //~ ERROR impls of auto traits cannot be default
|
|
||||||
//~^ ERROR negative impls cannot be default impls
|
default impl !Send for Z {}
|
||||||
|
//~^ ERROR impls of auto traits cannot be default
|
||||||
|
//~| ERROR negative impls cannot be default impls
|
||||||
|
//~| ERROR `!Send` impl requires `Z: Send` but the struct it is implemented for does not
|
||||||
|
|
||||||
trait Tr {}
|
trait Tr {}
|
||||||
default impl !Tr for S {} //~ ERROR negative impls cannot be default impls
|
|
||||||
|
default impl !Tr for S {}
|
||||||
|
//~^ ERROR negative impls cannot be default impls
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -26,22 +26,20 @@ LL | default unsafe impl Send for S {}
|
||||||
| |
|
| |
|
||||||
| default because of this
|
| default because of this
|
||||||
|
|
||||||
error[E0277]: `S` cannot be sent between threads safely
|
error[E0367]: `!Send` impl requires `Z: Send` but the struct it is implemented for does not
|
||||||
--> $DIR/validation.rs:9:1
|
--> $DIR/validation.rs:12:1
|
||||||
|
|
|
|
||||||
LL | default unsafe impl Send for S {}
|
LL | default impl !Send for Z {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `S` cannot be sent between threads safely
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: the trait `Send` is not implemented for `S`
|
note: the implementor must specify the same requirement
|
||||||
= help: the trait `Send` is implemented for `S`
|
--> $DIR/validation.rs:5:1
|
||||||
= help: see issue #48214
|
|
||||||
help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
|
|
||||||
|
|
|
||||||
LL + #![feature(trivial_bounds)]
|
|
||||||
|
|
|
|
||||||
|
LL | struct Z;
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
error: impls of auto traits cannot be default
|
error: impls of auto traits cannot be default
|
||||||
--> $DIR/validation.rs:11:15
|
--> $DIR/validation.rs:12:15
|
||||||
|
|
|
|
||||||
LL | default impl !Send for Z {}
|
LL | default impl !Send for Z {}
|
||||||
| ------- ^^^^ auto trait
|
| ------- ^^^^ auto trait
|
||||||
|
@ -49,18 +47,18 @@ LL | default impl !Send for Z {}
|
||||||
| default because of this
|
| default because of this
|
||||||
|
|
||||||
error[E0750]: negative impls cannot be default impls
|
error[E0750]: negative impls cannot be default impls
|
||||||
--> $DIR/validation.rs:11:1
|
--> $DIR/validation.rs:12:1
|
||||||
|
|
|
|
||||||
LL | default impl !Send for Z {}
|
LL | default impl !Send for Z {}
|
||||||
| ^^^^^^^ ^
|
| ^^^^^^^ ^
|
||||||
|
|
||||||
error[E0750]: negative impls cannot be default impls
|
error[E0750]: negative impls cannot be default impls
|
||||||
--> $DIR/validation.rs:15:1
|
--> $DIR/validation.rs:19:1
|
||||||
|
|
|
|
||||||
LL | default impl !Tr for S {}
|
LL | default impl !Tr for S {}
|
||||||
| ^^^^^^^ ^
|
| ^^^^^^^ ^
|
||||||
|
|
||||||
error: aborting due to 6 previous errors; 1 warning emitted
|
error: aborting due to 6 previous errors; 1 warning emitted
|
||||||
|
|
||||||
Some errors have detailed explanations: E0277, E0750.
|
Some errors have detailed explanations: E0367, E0750.
|
||||||
For more information about an error, try `rustc --explain E0277`.
|
For more information about an error, try `rustc --explain E0367`.
|
||||||
|
|
|
@ -6,6 +6,8 @@ trait MyTrait {}
|
||||||
struct TestType<T>(::std::marker::PhantomData<T>);
|
struct TestType<T>(::std::marker::PhantomData<T>);
|
||||||
|
|
||||||
unsafe impl<T: Clone> Send for TestType<T> {}
|
unsafe impl<T: Clone> Send for TestType<T> {}
|
||||||
impl<T: MyTrait> !Send for TestType<T> {} //~ ERROR E0751
|
impl<T: MyTrait> !Send for TestType<T> {}
|
||||||
|
//~^ ERROR found both positive and negative implementation of trait `Send` for type `TestType<_>`
|
||||||
|
//~| ERROR `!Send` impl requires `T: MyTrait` but the struct it is implemented for does not
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -16,6 +16,19 @@ LL | unsafe impl<T: Clone> Send for TestType<T> {}
|
||||||
LL | impl<T: MyTrait> !Send for TestType<T> {}
|
LL | impl<T: MyTrait> !Send for TestType<T> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here
|
||||||
|
|
||||||
error: aborting due to 1 previous error; 1 warning emitted
|
error[E0367]: `!Send` impl requires `T: MyTrait` but the struct it is implemented for does not
|
||||||
|
--> $DIR/specialization-overlap-negative.rs:9:9
|
||||||
|
|
|
||||||
|
LL | impl<T: MyTrait> !Send for TestType<T> {}
|
||||||
|
| ^^^^^^^
|
||||||
|
|
|
||||||
|
note: the implementor must specify the same requirement
|
||||||
|
--> $DIR/specialization-overlap-negative.rs:6:1
|
||||||
|
|
|
||||||
|
LL | struct TestType<T>(::std::marker::PhantomData<T>);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0751`.
|
error: aborting due to 2 previous errors; 1 warning emitted
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0367, E0751.
|
||||||
|
For more information about an error, try `rustc --explain E0367`.
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
#![feature(auto_traits, negative_impls)]
|
||||||
|
|
||||||
|
auto trait Foo {}
|
||||||
|
|
||||||
|
struct AdditionalLt<'a, T>(&'a (), T);
|
||||||
|
impl<'a, T: 'a> !Foo for AdditionalLt<'a, T> {}
|
||||||
|
//~^ ERROR `!Foo` impl requires `T: 'a` but the struct it is implemented for does not
|
||||||
|
|
||||||
|
struct AdditionalBound<T>(T);
|
||||||
|
trait Bound {}
|
||||||
|
impl<T: Bound> !Foo for AdditionalBound<T> {}
|
||||||
|
//~^ ERROR `!Foo` impl requires `T: Bound` but the struct it is implemented for does not
|
||||||
|
|
||||||
|
struct TwoParam<T, U>(T, U);
|
||||||
|
impl<T> !Foo for TwoParam<T, T> {}
|
||||||
|
//~^ ERROR `!Foo` impls cannot be specialized
|
||||||
|
|
||||||
|
struct ConcreteParam<T>(T);
|
||||||
|
impl !Foo for ConcreteParam<i32> {}
|
||||||
|
//~^ ERROR `!Foo` impls cannot be specialized
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,54 @@
|
||||||
|
error[E0367]: `!Foo` impl requires `T: 'a` but the struct it is implemented for does not
|
||||||
|
--> $DIR/negated-auto-traits-validity-error.rs:6:13
|
||||||
|
|
|
||||||
|
LL | impl<'a, T: 'a> !Foo for AdditionalLt<'a, T> {}
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
note: the implementor must specify the same requirement
|
||||||
|
--> $DIR/negated-auto-traits-validity-error.rs:5:1
|
||||||
|
|
|
||||||
|
LL | struct AdditionalLt<'a, T>(&'a (), T);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0367]: `!Foo` impl requires `T: Bound` but the struct it is implemented for does not
|
||||||
|
--> $DIR/negated-auto-traits-validity-error.rs:11:9
|
||||||
|
|
|
||||||
|
LL | impl<T: Bound> !Foo for AdditionalBound<T> {}
|
||||||
|
| ^^^^^
|
||||||
|
|
|
||||||
|
note: the implementor must specify the same requirement
|
||||||
|
--> $DIR/negated-auto-traits-validity-error.rs:9:1
|
||||||
|
|
|
||||||
|
LL | struct AdditionalBound<T>(T);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0366]: `!Foo` impls cannot be specialized
|
||||||
|
--> $DIR/negated-auto-traits-validity-error.rs:15:1
|
||||||
|
|
|
||||||
|
LL | impl<T> !Foo for TwoParam<T, T> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `T` is mentioned multiple times
|
||||||
|
note: use the same sequence of generic lifetime, type and const parameters as the struct definition
|
||||||
|
--> $DIR/negated-auto-traits-validity-error.rs:14:1
|
||||||
|
|
|
||||||
|
LL | struct TwoParam<T, U>(T, U);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0366]: `!Foo` impls cannot be specialized
|
||||||
|
--> $DIR/negated-auto-traits-validity-error.rs:19:1
|
||||||
|
|
|
||||||
|
LL | impl !Foo for ConcreteParam<i32> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `i32` is not a generic parameter
|
||||||
|
note: use the same sequence of generic lifetime, type and const parameters as the struct definition
|
||||||
|
--> $DIR/negated-auto-traits-validity-error.rs:18:1
|
||||||
|
|
|
||||||
|
LL | struct ConcreteParam<T>(T);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0366, E0367.
|
||||||
|
For more information about an error, try `rustc --explain E0366`.
|
|
@ -0,0 +1,22 @@
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
#![feature(auto_traits, negative_impls)]
|
||||||
|
|
||||||
|
auto trait Foo {}
|
||||||
|
auto trait Bar {}
|
||||||
|
|
||||||
|
struct NeedsOutlives<'a, T>(&'a T);
|
||||||
|
|
||||||
|
impl<'a, T: 'a> !Foo for NeedsOutlives<'a, T> {}
|
||||||
|
|
||||||
|
// Leaving out the lifetime bound
|
||||||
|
impl<'a, T> !Bar for NeedsOutlives<'a, T> {}
|
||||||
|
|
||||||
|
struct NeedsSend<T: Send>(T);
|
||||||
|
|
||||||
|
impl<T: Send> !Foo for NeedsSend<T> {}
|
||||||
|
|
||||||
|
// Leaving off the trait bound
|
||||||
|
impl<T> !Bar for NeedsSend<T> {}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Add table
Add a link
Reference in a new issue