split up #[rustc_deny_explicit_impl]
attribute
This commit splits the `#[rustc_deny_explicit_impl(implement_via_object = ...)]` attribute into two attributes `#[rustc_deny_explicit_impl]` and `#[rustc_do_not_implement_via_object]`. This allows us to have special traits that can have user-defined impls but do not have the automatic trait impl for trait objects (`impl Trait for dyn Trait`).
This commit is contained in:
parent
8a1f8039a7
commit
42c00cb647
13 changed files with 152 additions and 91 deletions
|
@ -912,11 +912,20 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
rustc_attr!(
|
rustc_attr!(
|
||||||
rustc_deny_explicit_impl,
|
rustc_deny_explicit_impl,
|
||||||
AttributeType::Normal,
|
AttributeType::Normal,
|
||||||
template!(List: "implement_via_object = (true|false)"),
|
template!(Word),
|
||||||
ErrorFollowing,
|
ErrorFollowing,
|
||||||
EncodeCrossCrate::No,
|
EncodeCrossCrate::No,
|
||||||
"#[rustc_deny_explicit_impl] enforces that a trait can have no user-provided impls"
|
"#[rustc_deny_explicit_impl] enforces that a trait can have no user-provided impls"
|
||||||
),
|
),
|
||||||
|
rustc_attr!(
|
||||||
|
rustc_do_not_implement_via_object,
|
||||||
|
AttributeType::Normal,
|
||||||
|
template!(Word),
|
||||||
|
ErrorFollowing,
|
||||||
|
EncodeCrossCrate::No,
|
||||||
|
"#[rustc_do_not_implement_via_object] opts out of the automatic trait impl for trait objects \
|
||||||
|
(`impl Trait for dyn Trait`)"
|
||||||
|
),
|
||||||
rustc_attr!(
|
rustc_attr!(
|
||||||
rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word),
|
rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word),
|
||||||
ErrorFollowing, EncodeCrossCrate::Yes,
|
ErrorFollowing, EncodeCrossCrate::Yes,
|
||||||
|
|
|
@ -206,7 +206,9 @@ fn check_object_overlap<'tcx>(
|
||||||
// so this is valid.
|
// so this is valid.
|
||||||
} else {
|
} else {
|
||||||
let mut supertrait_def_ids = tcx.supertrait_def_ids(component_def_id);
|
let mut supertrait_def_ids = tcx.supertrait_def_ids(component_def_id);
|
||||||
if supertrait_def_ids.any(|d| d == trait_def_id) {
|
if supertrait_def_ids
|
||||||
|
.any(|d| d == trait_def_id && tcx.trait_def(d).implement_via_object)
|
||||||
|
{
|
||||||
let span = tcx.def_span(impl_def_id);
|
let span = tcx.def_span(impl_def_id);
|
||||||
return Err(struct_span_code_err!(
|
return Err(struct_span_code_err!(
|
||||||
tcx.dcx(),
|
tcx.dcx(),
|
||||||
|
|
|
@ -1261,49 +1261,8 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
|
||||||
no_dups.then_some(list)
|
no_dups.then_some(list)
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut deny_explicit_impl = false;
|
let deny_explicit_impl = tcx.has_attr(def_id, sym::rustc_deny_explicit_impl);
|
||||||
let mut implement_via_object = true;
|
let implement_via_object = !tcx.has_attr(def_id, sym::rustc_do_not_implement_via_object);
|
||||||
if let Some(attr) = tcx.get_attr(def_id, sym::rustc_deny_explicit_impl) {
|
|
||||||
deny_explicit_impl = true;
|
|
||||||
let mut seen_attr = false;
|
|
||||||
for meta in attr.meta_item_list().iter().flatten() {
|
|
||||||
if let Some(meta) = meta.meta_item()
|
|
||||||
&& meta.name_or_empty() == sym::implement_via_object
|
|
||||||
&& let Some(lit) = meta.name_value_literal()
|
|
||||||
{
|
|
||||||
if seen_attr {
|
|
||||||
tcx.dcx().span_err(meta.span, "duplicated `implement_via_object` meta item");
|
|
||||||
}
|
|
||||||
seen_attr = true;
|
|
||||||
|
|
||||||
match lit.symbol {
|
|
||||||
kw::True => {
|
|
||||||
implement_via_object = true;
|
|
||||||
}
|
|
||||||
kw::False => {
|
|
||||||
implement_via_object = false;
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
tcx.dcx().span_err(
|
|
||||||
meta.span,
|
|
||||||
format!(
|
|
||||||
"unknown literal passed to `implement_via_object` attribute: {}",
|
|
||||||
lit.symbol
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tcx.dcx().span_err(
|
|
||||||
meta.span(),
|
|
||||||
format!("unknown meta item passed to `rustc_deny_explicit_impl` {meta:?}"),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !seen_attr {
|
|
||||||
tcx.dcx().span_err(attr.span, "missing `implement_via_object` meta item");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::TraitDef {
|
ty::TraitDef {
|
||||||
def_id: def_id.to_def_id(),
|
def_id: def_id.to_def_id(),
|
||||||
|
|
|
@ -70,12 +70,12 @@ pub struct TraitDef {
|
||||||
|
|
||||||
/// Whether to add a builtin `dyn Trait: Trait` implementation.
|
/// Whether to add a builtin `dyn Trait: Trait` implementation.
|
||||||
/// This is enabled for all traits except ones marked with
|
/// This is enabled for all traits except ones marked with
|
||||||
/// `#[rustc_deny_explicit_impl(implement_via_object = false)]`.
|
/// `#[rustc_do_not_implement_via_object]`.
|
||||||
pub implement_via_object: bool,
|
pub implement_via_object: bool,
|
||||||
|
|
||||||
/// Whether a trait is fully built-in, and any implementation is disallowed.
|
/// Whether a trait is fully built-in, and any implementation is disallowed.
|
||||||
/// This only applies to built-in traits, and is marked via
|
/// This only applies to built-in traits, and is marked via
|
||||||
/// `#[rustc_deny_explicit_impl(implement_via_object = ...)]`.
|
/// `#[rustc_deny_explicit_impl]`.
|
||||||
pub deny_explicit_impl: bool,
|
pub deny_explicit_impl: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -186,6 +186,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
[sym::rustc_coinductive, ..]
|
[sym::rustc_coinductive, ..]
|
||||||
| [sym::rustc_must_implement_one_of, ..]
|
| [sym::rustc_must_implement_one_of, ..]
|
||||||
| [sym::rustc_deny_explicit_impl, ..]
|
| [sym::rustc_deny_explicit_impl, ..]
|
||||||
|
| [sym::rustc_do_not_implement_via_object, ..]
|
||||||
| [sym::const_trait, ..] => self.check_must_be_applied_to_trait(attr, span, target),
|
| [sym::const_trait, ..] => self.check_must_be_applied_to_trait(attr, span, target),
|
||||||
[sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target),
|
[sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target),
|
||||||
[sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target),
|
[sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target),
|
||||||
|
|
|
@ -1717,6 +1717,7 @@ symbols! {
|
||||||
rustc_diagnostic_macros,
|
rustc_diagnostic_macros,
|
||||||
rustc_dirty,
|
rustc_dirty,
|
||||||
rustc_do_not_const_check,
|
rustc_do_not_const_check,
|
||||||
|
rustc_do_not_implement_via_object,
|
||||||
rustc_doc_primitive,
|
rustc_doc_primitive,
|
||||||
rustc_driver,
|
rustc_driver,
|
||||||
rustc_dummy,
|
rustc_dummy,
|
||||||
|
|
|
@ -133,7 +133,9 @@ pub trait AsyncDrop {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[lang = "async_destruct"]
|
#[lang = "async_destruct"]
|
||||||
#[rustc_deny_explicit_impl(implement_via_object = false)]
|
#[cfg_attr(bootstrap, rustc_deny_explicit_impl(implement_via_object = false))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)]
|
||||||
trait AsyncDestruct {
|
trait AsyncDestruct {
|
||||||
type AsyncDestructor: Future<Output = ()>;
|
type AsyncDestructor: Future<Output = ()>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,7 +141,9 @@ unsafe impl<T: Sync + ?Sized> Send for &T {}
|
||||||
)]
|
)]
|
||||||
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
|
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
|
||||||
#[rustc_specialization_trait]
|
#[rustc_specialization_trait]
|
||||||
#[rustc_deny_explicit_impl(implement_via_object = false)]
|
#[cfg_attr(bootstrap, rustc_deny_explicit_impl(implement_via_object = false))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)]
|
||||||
#[rustc_coinductive]
|
#[rustc_coinductive]
|
||||||
pub trait Sized {
|
pub trait Sized {
|
||||||
// Empty.
|
// Empty.
|
||||||
|
@ -181,7 +183,9 @@ pub trait Sized {
|
||||||
/// [^1]: Formerly known as *object safe*.
|
/// [^1]: Formerly known as *object safe*.
|
||||||
#[unstable(feature = "unsize", issue = "18598")]
|
#[unstable(feature = "unsize", issue = "18598")]
|
||||||
#[lang = "unsize"]
|
#[lang = "unsize"]
|
||||||
#[rustc_deny_explicit_impl(implement_via_object = false)]
|
#[cfg_attr(bootstrap, rustc_deny_explicit_impl(implement_via_object = false))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)]
|
||||||
pub trait Unsize<T: ?Sized> {
|
pub trait Unsize<T: ?Sized> {
|
||||||
// Empty.
|
// Empty.
|
||||||
}
|
}
|
||||||
|
@ -815,7 +819,9 @@ impl<T: ?Sized> StructuralPartialEq for PhantomData<T> {}
|
||||||
reason = "this trait is unlikely to ever be stabilized, use `mem::discriminant` instead"
|
reason = "this trait is unlikely to ever be stabilized, use `mem::discriminant` instead"
|
||||||
)]
|
)]
|
||||||
#[lang = "discriminant_kind"]
|
#[lang = "discriminant_kind"]
|
||||||
#[rustc_deny_explicit_impl(implement_via_object = false)]
|
#[cfg_attr(bootstrap, rustc_deny_explicit_impl(implement_via_object = false))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)]
|
||||||
pub trait DiscriminantKind {
|
pub trait DiscriminantKind {
|
||||||
/// The type of the discriminant, which must satisfy the trait
|
/// The type of the discriminant, which must satisfy the trait
|
||||||
/// bounds required by `mem::Discriminant`.
|
/// bounds required by `mem::Discriminant`.
|
||||||
|
@ -956,7 +962,9 @@ marker_impls! {
|
||||||
#[unstable(feature = "const_destruct", issue = "133214")]
|
#[unstable(feature = "const_destruct", issue = "133214")]
|
||||||
#[lang = "destruct"]
|
#[lang = "destruct"]
|
||||||
#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]
|
#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]
|
||||||
#[rustc_deny_explicit_impl(implement_via_object = false)]
|
#[cfg_attr(bootstrap, rustc_deny_explicit_impl(implement_via_object = false))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)]
|
||||||
#[cfg_attr(not(bootstrap), const_trait)]
|
#[cfg_attr(not(bootstrap), const_trait)]
|
||||||
pub trait Destruct {}
|
pub trait Destruct {}
|
||||||
|
|
||||||
|
@ -967,7 +975,9 @@ pub trait Destruct {}
|
||||||
#[unstable(feature = "tuple_trait", issue = "none")]
|
#[unstable(feature = "tuple_trait", issue = "none")]
|
||||||
#[lang = "tuple_trait"]
|
#[lang = "tuple_trait"]
|
||||||
#[diagnostic::on_unimplemented(message = "`{Self}` is not a tuple")]
|
#[diagnostic::on_unimplemented(message = "`{Self}` is not a tuple")]
|
||||||
#[rustc_deny_explicit_impl(implement_via_object = false)]
|
#[cfg_attr(bootstrap, rustc_deny_explicit_impl(implement_via_object = false))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)]
|
||||||
pub trait Tuple {}
|
pub trait Tuple {}
|
||||||
|
|
||||||
/// A marker for pointer-like types.
|
/// A marker for pointer-like types.
|
||||||
|
@ -1068,7 +1078,9 @@ marker_impls! {
|
||||||
reason = "internal trait for implementing various traits for all function pointers"
|
reason = "internal trait for implementing various traits for all function pointers"
|
||||||
)]
|
)]
|
||||||
#[lang = "fn_ptr_trait"]
|
#[lang = "fn_ptr_trait"]
|
||||||
#[rustc_deny_explicit_impl(implement_via_object = false)]
|
#[cfg_attr(bootstrap, rustc_deny_explicit_impl(implement_via_object = false))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)]
|
||||||
pub trait FnPtr: Copy + Clone {
|
pub trait FnPtr: Copy + Clone {
|
||||||
/// Returns the address of the function pointer.
|
/// Returns the address of the function pointer.
|
||||||
#[lang = "fn_ptr_addr"]
|
#[lang = "fn_ptr_addr"]
|
||||||
|
|
|
@ -84,7 +84,9 @@ use crate::marker::{ConstParamTy_, UnsizedConstParamTy};
|
||||||
/// `usize` is stable, but not portable.
|
/// `usize` is stable, but not portable.
|
||||||
#[unstable(feature = "transmutability", issue = "99571")]
|
#[unstable(feature = "transmutability", issue = "99571")]
|
||||||
#[lang = "transmute_trait"]
|
#[lang = "transmute_trait"]
|
||||||
#[rustc_deny_explicit_impl(implement_via_object = false)]
|
#[cfg_attr(bootstrap, rustc_deny_explicit_impl(implement_via_object = false))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)]
|
||||||
#[rustc_coinductive]
|
#[rustc_coinductive]
|
||||||
pub unsafe trait TransmuteFrom<Src, const ASSUME: Assume = { Assume::NOTHING }>
|
pub unsafe trait TransmuteFrom<Src, const ASSUME: Assume = { Assume::NOTHING }>
|
||||||
where
|
where
|
||||||
|
|
|
@ -53,7 +53,9 @@ use crate::ptr::NonNull;
|
||||||
///
|
///
|
||||||
/// [`to_raw_parts`]: *const::to_raw_parts
|
/// [`to_raw_parts`]: *const::to_raw_parts
|
||||||
#[lang = "pointee_trait"]
|
#[lang = "pointee_trait"]
|
||||||
#[rustc_deny_explicit_impl(implement_via_object = false)]
|
#[cfg_attr(bootstrap, rustc_deny_explicit_impl(implement_via_object = false))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)]
|
||||||
pub trait Pointee {
|
pub trait Pointee {
|
||||||
/// The type for metadata in pointers and references to `Self`.
|
/// The type for metadata in pointers and references to `Self`.
|
||||||
#[lang = "metadata_type"]
|
#[lang = "metadata_type"]
|
||||||
|
|
|
@ -1,20 +1,44 @@
|
||||||
error[E0277]: the trait bound `dyn NotObject: NotObject` is not satisfied
|
error[E0322]: explicit impls for the `NotImplYesObject` trait are not permitted
|
||||||
--> $DIR/deny-builtin-object-impl.rs:19:23
|
--> $DIR/deny-builtin-object-impl.rs:20:1
|
||||||
|
|
|
|
||||||
LL | test_not_object::<dyn NotObject>();
|
LL | impl NotImplYesObject for () {}
|
||||||
| ^^^^^^^^^^^^^ the trait `NotObject` is not implemented for `dyn NotObject`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `NotImplYesObject` not allowed
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `dyn NotImplNotObject: NotImplNotObject` is not satisfied
|
||||||
|
--> $DIR/deny-builtin-object-impl.rs:37:32
|
||||||
|
|
|
||||||
|
LL | test_not_impl_not_object::<dyn NotImplNotObject>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^ the trait `NotImplNotObject` is not implemented for `dyn NotImplNotObject`
|
||||||
|
|
|
|
||||||
help: this trait has no implementations, consider adding one
|
help: this trait has no implementations, consider adding one
|
||||||
--> $DIR/deny-builtin-object-impl.rs:11:1
|
--> $DIR/deny-builtin-object-impl.rs:12:1
|
||||||
|
|
|
|
||||||
LL | trait NotObject {}
|
LL | trait NotImplNotObject {}
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: required by a bound in `test_not_object`
|
note: required by a bound in `test_not_impl_not_object`
|
||||||
--> $DIR/deny-builtin-object-impl.rs:15:23
|
--> $DIR/deny-builtin-object-impl.rs:28:32
|
||||||
|
|
|
|
||||||
LL | fn test_not_object<T: NotObject + ?Sized>() {}
|
LL | fn test_not_impl_not_object<T: NotImplNotObject + ?Sized>() {}
|
||||||
| ^^^^^^^^^ required by this bound in `test_not_object`
|
| ^^^^^^^^^^^^^^^^ required by this bound in `test_not_impl_not_object`
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error[E0277]: the trait bound `dyn YesImplNotObject: YesImplNotObject` is not satisfied
|
||||||
|
--> $DIR/deny-builtin-object-impl.rs:40:32
|
||||||
|
|
|
||||||
|
LL | test_yes_impl_not_object::<dyn YesImplNotObject>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^ the trait `YesImplNotObject` is not implemented for `dyn YesImplNotObject`
|
||||||
|
|
|
||||||
|
help: this trait has no implementations, consider adding one
|
||||||
|
--> $DIR/deny-builtin-object-impl.rs:15:1
|
||||||
|
|
|
||||||
|
LL | trait YesImplNotObject {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
note: required by a bound in `test_yes_impl_not_object`
|
||||||
|
--> $DIR/deny-builtin-object-impl.rs:30:32
|
||||||
|
|
|
||||||
|
LL | fn test_yes_impl_not_object<T: YesImplNotObject + ?Sized>() {}
|
||||||
|
| ^^^^^^^^^^^^^^^^ required by this bound in `test_yes_impl_not_object`
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0277`.
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0277, E0322.
|
||||||
|
For more information about an error, try `rustc --explain E0277`.
|
||||||
|
|
|
@ -1,20 +1,44 @@
|
||||||
error[E0277]: the trait bound `dyn NotObject: NotObject` is not satisfied
|
error[E0322]: explicit impls for the `NotImplYesObject` trait are not permitted
|
||||||
--> $DIR/deny-builtin-object-impl.rs:19:23
|
--> $DIR/deny-builtin-object-impl.rs:20:1
|
||||||
|
|
|
|
||||||
LL | test_not_object::<dyn NotObject>();
|
LL | impl NotImplYesObject for () {}
|
||||||
| ^^^^^^^^^^^^^ the trait `NotObject` is not implemented for `dyn NotObject`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `NotImplYesObject` not allowed
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `dyn NotImplNotObject: NotImplNotObject` is not satisfied
|
||||||
|
--> $DIR/deny-builtin-object-impl.rs:37:32
|
||||||
|
|
|
||||||
|
LL | test_not_impl_not_object::<dyn NotImplNotObject>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^ the trait `NotImplNotObject` is not implemented for `dyn NotImplNotObject`
|
||||||
|
|
|
|
||||||
help: this trait has no implementations, consider adding one
|
help: this trait has no implementations, consider adding one
|
||||||
--> $DIR/deny-builtin-object-impl.rs:11:1
|
--> $DIR/deny-builtin-object-impl.rs:12:1
|
||||||
|
|
|
|
||||||
LL | trait NotObject {}
|
LL | trait NotImplNotObject {}
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: required by a bound in `test_not_object`
|
note: required by a bound in `test_not_impl_not_object`
|
||||||
--> $DIR/deny-builtin-object-impl.rs:15:23
|
--> $DIR/deny-builtin-object-impl.rs:28:32
|
||||||
|
|
|
|
||||||
LL | fn test_not_object<T: NotObject + ?Sized>() {}
|
LL | fn test_not_impl_not_object<T: NotImplNotObject + ?Sized>() {}
|
||||||
| ^^^^^^^^^ required by this bound in `test_not_object`
|
| ^^^^^^^^^^^^^^^^ required by this bound in `test_not_impl_not_object`
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error[E0277]: the trait bound `dyn YesImplNotObject: YesImplNotObject` is not satisfied
|
||||||
|
--> $DIR/deny-builtin-object-impl.rs:40:32
|
||||||
|
|
|
||||||
|
LL | test_yes_impl_not_object::<dyn YesImplNotObject>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^ the trait `YesImplNotObject` is not implemented for `dyn YesImplNotObject`
|
||||||
|
|
|
||||||
|
help: this trait has no implementations, consider adding one
|
||||||
|
--> $DIR/deny-builtin-object-impl.rs:15:1
|
||||||
|
|
|
||||||
|
LL | trait YesImplNotObject {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
note: required by a bound in `test_yes_impl_not_object`
|
||||||
|
--> $DIR/deny-builtin-object-impl.rs:30:32
|
||||||
|
|
|
||||||
|
LL | fn test_yes_impl_not_object<T: YesImplNotObject + ?Sized>() {}
|
||||||
|
| ^^^^^^^^^^^^^^^^ required by this bound in `test_yes_impl_not_object`
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0277`.
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0277, E0322.
|
||||||
|
For more information about an error, try `rustc --explain E0277`.
|
||||||
|
|
|
@ -4,18 +4,41 @@
|
||||||
|
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
#[rustc_deny_explicit_impl(implement_via_object = true)]
|
#[rustc_deny_explicit_impl]
|
||||||
trait YesObject {}
|
trait NotImplYesObject {}
|
||||||
|
|
||||||
#[rustc_deny_explicit_impl(implement_via_object = false)]
|
#[rustc_deny_explicit_impl]
|
||||||
trait NotObject {}
|
#[rustc_do_not_implement_via_object]
|
||||||
|
trait NotImplNotObject {}
|
||||||
|
|
||||||
fn test_yes_object<T: YesObject + ?Sized>() {}
|
#[rustc_do_not_implement_via_object]
|
||||||
|
trait YesImplNotObject {}
|
||||||
|
|
||||||
fn test_not_object<T: NotObject + ?Sized>() {}
|
#[rustc_do_not_implement_via_object]
|
||||||
|
trait YesImplNotObject2 {}
|
||||||
|
|
||||||
|
impl NotImplYesObject for () {}
|
||||||
|
//~^ ERROR explicit impls for the `NotImplYesObject` trait are not permitted
|
||||||
|
|
||||||
|
// If there is no automatic impl then we can add a manual impl:
|
||||||
|
impl YesImplNotObject2 for dyn YesImplNotObject2 {}
|
||||||
|
|
||||||
|
fn test_not_impl_yes_object<T: NotImplYesObject + ?Sized>() {}
|
||||||
|
|
||||||
|
fn test_not_impl_not_object<T: NotImplNotObject + ?Sized>() {}
|
||||||
|
|
||||||
|
fn test_yes_impl_not_object<T: YesImplNotObject + ?Sized>() {}
|
||||||
|
|
||||||
|
fn test_yes_impl_not_object2<T: YesImplNotObject2 + ?Sized>() {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
test_yes_object::<dyn YesObject>();
|
test_not_impl_yes_object::<dyn NotImplYesObject>();
|
||||||
test_not_object::<dyn NotObject>();
|
|
||||||
//~^ ERROR the trait bound `dyn NotObject: NotObject` is not satisfied
|
test_not_impl_not_object::<dyn NotImplNotObject>();
|
||||||
|
//~^ ERROR the trait bound `dyn NotImplNotObject: NotImplNotObject` is not satisfied
|
||||||
|
|
||||||
|
test_yes_impl_not_object::<dyn YesImplNotObject>();
|
||||||
|
//~^ ERROR the trait bound `dyn YesImplNotObject: YesImplNotObject` is not satisfied
|
||||||
|
|
||||||
|
test_yes_impl_not_object2::<dyn YesImplNotObject2>();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue