1
Fork 0

Auto merge of #61812 - jonas-schievink:assoc-ty-defaults, r=nikomatsakis

Implement RFC 2532 – Associated Type Defaults

This is a partial implementation that is still missing the changes to object types, since I ran into some trouble while implementing that. I'm opening this part already to get feedback on the implementation and the unexpected test fallout (see my comments below). The remaining changes can be done in a later PR.

Blockers before this can land:
* [x] Resolve unsoundness around interaction with specialization (https://github.com/rust-lang/rust/pull/61812#discussion_r300504010) - #64564

cc https://github.com/rust-lang/rust/issues/29661
Fixes #53907
Fixes #54182
Fixes #62211
Fixes #41868
Fixes #63593
Fixes #47385
Fixes #43924
Fixes #32350
Fixes #26681
Fixes https://github.com/rust-lang/rust/issues/67187
This commit is contained in:
bors 2020-02-26 09:27:06 +00:00
commit 3a0d106109
53 changed files with 2048 additions and 154 deletions

View file

@ -1,9 +1,11 @@
#### Note: this error code is no longer emitted by the compiler
You implemented a trait, overriding one or more of its associated types but did
not reimplement its default methods.
Example of erroneous code:
```compile_fail,E0399
```
#![feature(associated_type_defaults)]
pub trait Foo {

View file

@ -1054,27 +1054,42 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
// an error when we confirm the candidate
// (which will ultimately lead to `normalize_to_error`
// being invoked).
node_item.item.defaultness.has_value()
false
} else {
// If we're looking at a trait *impl*, the item is
// specializable if the impl or the item are marked
// `default`.
node_item.item.defaultness.is_default()
|| super::util::impl_is_default(selcx.tcx(), node_item.node.def_id())
};
match is_default {
// Non-specializable items are always projectable
false => true,
// Only reveal a specializable default if we're past type-checking
// and the obligations is monomorphic, otherwise passes such as
// and the obligation is monomorphic, otherwise passes such as
// transmute checking and polymorphic MIR optimizations could
// get a result which isn't correct for all monomorphizations.
if !is_default {
true
} else if obligation.param_env.reveal == Reveal::All {
true if obligation.param_env.reveal == Reveal::All => {
// NOTE(eddyb) inference variables can resolve to parameters, so
// assume `poly_trait_ref` isn't monomorphic, if it contains any.
let poly_trait_ref = selcx.infcx().resolve_vars_if_possible(&poly_trait_ref);
let poly_trait_ref =
selcx.infcx().resolve_vars_if_possible(&poly_trait_ref);
!poly_trait_ref.needs_infer() && !poly_trait_ref.needs_subst()
} else {
}
true => {
debug!(
"assemble_candidates_from_impls: not eligible due to default: \
assoc_ty={} predicate={}",
selcx.tcx().def_path_str(node_item.item.def_id),
obligation.predicate,
);
false
}
}
}
super::VtableParam(..) => {
// This case tell us nothing about the value of an
// associated type. Consider:

View file

@ -1964,7 +1964,6 @@ fn check_impl_items_against_trait<'tcx>(
// Locate trait definition and items
let trait_def = tcx.trait_def(impl_trait_ref.def_id);
let mut overridden_associated_type = None;
let impl_items = || impl_item_refs.iter().map(|iiref| tcx.hir().impl_item(iiref.id));
@ -2046,9 +2045,6 @@ fn check_impl_items_against_trait<'tcx>(
hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(_) => {
let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
if ty_trait_item.kind == ty::AssocKind::Type {
if ty_trait_item.defaultness.has_value() {
overridden_associated_type = Some(impl_item);
}
compare_ty_impl(
tcx,
&ty_impl_item,
@ -2082,8 +2078,6 @@ fn check_impl_items_against_trait<'tcx>(
// Check for missing items from trait
let mut missing_items = Vec::new();
let mut invalidated_items = Vec::new();
let associated_type_overridden = overridden_associated_type.is_some();
for trait_item in tcx.associated_items(impl_trait_ref.def_id).in_definition_order() {
let is_implemented = trait_def
.ancestors(tcx, impl_id)
@ -2094,8 +2088,6 @@ fn check_impl_items_against_trait<'tcx>(
if !is_implemented && !traits::impl_is_default(tcx, impl_id) {
if !trait_item.defaultness.has_value() {
missing_items.push(*trait_item);
} else if associated_type_overridden {
invalidated_items.push(trait_item.ident);
}
}
}
@ -2103,19 +2095,6 @@ fn check_impl_items_against_trait<'tcx>(
if !missing_items.is_empty() {
missing_items_err(tcx, impl_span, &missing_items, full_impl_span);
}
if !invalidated_items.is_empty() {
let invalidator = overridden_associated_type.unwrap();
struct_span_err!(
tcx.sess,
invalidator.span,
E0399,
"the following trait items need to be reimplemented as `{}` was overridden: `{}`",
invalidator.ident,
invalidated_items.iter().map(|name| name.to_string()).collect::<Vec<_>>().join("`, `")
)
.emit();
}
}
fn missing_items_err(

View file

@ -425,10 +425,109 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
for_item(tcx, item).with_fcx(|fcx, _| {
check_where_clauses(tcx, fcx, item.span, trait_def_id, None);
check_associated_type_defaults(fcx, trait_def_id);
vec![]
});
}
/// Checks all associated type defaults of trait `trait_def_id`.
///
/// Assuming the defaults are used, check that all predicates (bounds on the
/// assoc type and where clauses on the trait) hold.
fn check_associated_type_defaults(fcx: &FnCtxt<'_, '_>, trait_def_id: DefId) {
let tcx = fcx.tcx;
let substs = InternalSubsts::identity_for_item(tcx, trait_def_id);
// For all assoc. types with defaults, build a map from
// `<Self as Trait<...>>::Assoc` to the default type.
let map = tcx
.associated_items(trait_def_id)
.in_definition_order()
.filter_map(|item| {
if item.kind == ty::AssocKind::Type && item.defaultness.has_value() {
// `<Self as Trait<...>>::Assoc`
let proj = ty::ProjectionTy { substs, item_def_id: item.def_id };
let default_ty = tcx.type_of(item.def_id);
debug!("assoc. type default mapping: {} -> {}", proj, default_ty);
Some((proj, default_ty))
} else {
None
}
})
.collect::<FxHashMap<_, _>>();
/// Replaces projections of associated types with their default types.
///
/// This does a "shallow substitution", meaning that defaults that refer to
/// other defaulted assoc. types will still refer to the projection
/// afterwards, not to the other default. For example:
///
/// ```compile_fail
/// trait Tr {
/// type A: Clone = Vec<Self::B>;
/// type B = u8;
/// }
/// ```
///
/// This will end up replacing the bound `Self::A: Clone` with
/// `Vec<Self::B>: Clone`, not with `Vec<u8>: Clone`. If we did a deep
/// substitution and ended up with the latter, the trait would be accepted.
/// If an `impl` then replaced `B` with something that isn't `Clone`,
/// suddenly the default for `A` is no longer valid. The shallow
/// substitution forces the trait to add a `B: Clone` bound to be accepted,
/// which means that an `impl` can replace any default without breaking
/// others.
///
/// Note that this isn't needed for soundness: The defaults would still be
/// checked in any impl that doesn't override them.
struct DefaultNormalizer<'tcx> {
tcx: TyCtxt<'tcx>,
map: FxHashMap<ty::ProjectionTy<'tcx>, Ty<'tcx>>,
}
impl<'tcx> ty::fold::TypeFolder<'tcx> for DefaultNormalizer<'tcx> {
fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
self.tcx
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
match t.kind {
ty::Projection(proj_ty) => {
if let Some(default) = self.map.get(&proj_ty) {
default
} else {
t.super_fold_with(self)
}
}
_ => t.super_fold_with(self),
}
}
}
// Now take all predicates defined on the trait, replace any mention of
// the assoc. types with their default, and prove them.
// We only consider predicates that directly mention the assoc. type.
let mut norm = DefaultNormalizer { tcx, map };
let predicates = fcx.tcx.predicates_of(trait_def_id);
for &(orig_pred, span) in predicates.predicates.iter() {
let pred = orig_pred.fold_with(&mut norm);
if pred != orig_pred {
// Mentions one of the defaulted assoc. types
debug!("default suitability check: proving predicate: {} -> {}", orig_pred, pred);
let pred = fcx.normalize_associated_types_in(span, &pred);
let cause = traits::ObligationCause::new(
span,
fcx.body_id,
traits::ItemObligation(trait_def_id),
);
let obligation = traits::Obligation::new(cause, fcx.param_env, pred);
fcx.register_predicate(obligation);
}
}
}
fn check_item_fn(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
for_item(tcx, item).with_fcx(|fcx, tcx| {
let def_id = fcx.tcx.hir().local_def_id(item.hir_id);

View file

@ -0,0 +1,17 @@
// build-fail
// Cyclic assoc. const defaults don't error unless *used*
trait Tr {
const A: u8 = Self::B;
//~^ ERROR cycle detected when const-evaluating + checking `Tr::A`
const B: u8 = Self::A;
}
// This impl is *allowed* unless its assoc. consts are used
impl Tr for () {}
fn main() {
// This triggers the cycle error
assert_eq!(<() as Tr>::A, 0);
}

View file

@ -0,0 +1,31 @@
error[E0391]: cycle detected when const-evaluating + checking `Tr::A`
--> $DIR/defaults-cyclic-fail.rs:5:5
|
LL | const A: u8 = Self::B;
| ^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating `Tr::A`...
--> $DIR/defaults-cyclic-fail.rs:5:19
|
LL | const A: u8 = Self::B;
| ^^^^^^^
note: ...which requires const-evaluating + checking `Tr::B`...
--> $DIR/defaults-cyclic-fail.rs:8:5
|
LL | const B: u8 = Self::A;
| ^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires const-evaluating `Tr::B`...
--> $DIR/defaults-cyclic-fail.rs:8:19
|
LL | const B: u8 = Self::A;
| ^^^^^^^
= note: ...which again requires const-evaluating + checking `Tr::A`, completing the cycle
note: cycle used when const-evaluating `main`
--> $DIR/defaults-cyclic-fail.rs:16:16
|
LL | assert_eq!(<() as Tr>::A, 0);
| ^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0391`.

View file

@ -0,0 +1,36 @@
// run-pass
// Cyclic assoc. const defaults don't error unless *used*
trait Tr {
const A: u8 = Self::B;
const B: u8 = Self::A;
}
// This impl is *allowed* unless its assoc. consts are used, matching the
// behavior without defaults.
impl Tr for () {}
// Overriding either constant breaks the cycle
impl Tr for u8 {
const A: u8 = 42;
}
impl Tr for u16 {
const B: u8 = 0;
}
impl Tr for u32 {
const A: u8 = 100;
const B: u8 = 123;
}
fn main() {
assert_eq!(<u8 as Tr>::A, 42);
assert_eq!(<u8 as Tr>::B, 42);
assert_eq!(<u16 as Tr>::A, 0);
assert_eq!(<u16 as Tr>::B, 0);
assert_eq!(<u32 as Tr>::A, 100);
assert_eq!(<u32 as Tr>::B, 123);
}

View file

@ -0,0 +1,45 @@
// build-fail
trait Tr {
const A: u8 = 255;
// This should not be a constant evaluation error (overflow). The value of
// `Self::A` must not be assumed to hold inside the trait.
const B: u8 = Self::A + 1;
//~^ ERROR any use of this value will cause an error
}
// An impl that doesn't override any constant will NOT cause a const eval error
// just because it's defined, but only if the bad constant is used anywhere.
// This matches the behavior without defaults.
impl Tr for () {}
// An impl that overrides either constant with a suitable value will be fine.
impl Tr for u8 {
const A: u8 = 254;
}
impl Tr for u16 {
const B: u8 = 0;
}
impl Tr for u32 {
const A: u8 = 254;
const B: u8 = 0;
}
fn main() {
assert_eq!(<() as Tr>::A, 255);
assert_eq!(<() as Tr>::B, 0); // causes the error above
//~^ ERROR evaluation of constant expression failed
//~| ERROR erroneous constant used
assert_eq!(<u8 as Tr>::A, 254);
assert_eq!(<u8 as Tr>::B, 255);
assert_eq!(<u16 as Tr>::A, 255);
assert_eq!(<u16 as Tr>::B, 0);
assert_eq!(<u32 as Tr>::A, 254);
assert_eq!(<u32 as Tr>::B, 0);
}

View file

@ -0,0 +1,31 @@
error: any use of this value will cause an error
--> $DIR/defaults-not-assumed-fail.rs:8:19
|
LL | const B: u8 = Self::A + 1;
| --------------^^^^^^^^^^^-
| |
| attempt to add with overflow
|
= note: `#[deny(const_err)]` on by default
error[E0080]: evaluation of constant expression failed
--> $DIR/defaults-not-assumed-fail.rs:33:5
|
LL | assert_eq!(<() as Tr>::B, 0); // causes the error above
| ^^^^^^^^^^^-------------^^^^^
| |
| referenced constant has errors
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: erroneous constant used
--> $DIR/defaults-not-assumed-fail.rs:33:5
|
LL | assert_eq!(<() as Tr>::B, 0); // causes the error above
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0080`.

View file

@ -0,0 +1,42 @@
// run-pass
trait Tr {
const A: u8 = 255;
// This should not be a constant evaluation error (overflow). The value of
// `Self::A` must not be assumed to hold inside the trait.
const B: u8 = Self::A + 1;
}
// An impl that doesn't override any constant will NOT cause a const eval error
// just because it's defined, but only if the bad constant is used anywhere.
// This matches the behavior without defaults.
impl Tr for () {}
// An impl that overrides either constant with a suitable value will be fine.
impl Tr for u8 {
const A: u8 = 254;
}
impl Tr for u16 {
const B: u8 = 0;
}
impl Tr for u32 {
const A: u8 = 254;
const B: u8 = 0;
}
fn main() {
assert_eq!(<() as Tr>::A, 255);
//assert_eq!(<() as Tr>::B, 0); // using this is an error
assert_eq!(<u8 as Tr>::A, 254);
assert_eq!(<u8 as Tr>::B, 255);
assert_eq!(<u16 as Tr>::A, 255);
assert_eq!(<u16 as Tr>::B, 0);
assert_eq!(<u32 as Tr>::A, 254);
assert_eq!(<u32 as Tr>::B, 0);
}

View file

@ -1,3 +1,8 @@
// check-pass
// Before RFC 2532, overriding one assoc. type default required overriding all
// provided defaults.
#![feature(associated_type_defaults)]
pub trait Tr {
@ -9,7 +14,9 @@ pub trait Tr {
impl Tr for () {
type Assoc = ();
//~^ ERROR need to be reimplemented as `Assoc` was overridden: `Assoc2`, `C`, `foo`
}
fn main() {}
fn main() {
let _: <() as Tr>::Assoc = ();
let _: <() as Tr>::Assoc2 = ();
}

View file

@ -1,9 +0,0 @@
error[E0399]: the following trait items need to be reimplemented as `Assoc` was overridden: `Assoc2`, `C`, `foo`
--> $DIR/associated-types-overridden-default.rs:11:5
|
LL | type Assoc = ();
| ^^^^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0399`.

View file

@ -0,0 +1,45 @@
#![feature(associated_type_defaults)]
// Having a cycle in assoc. type defaults is okay...
trait Tr {
type A = Self::B;
type B = Self::A;
}
// ...but is an error in any impl that doesn't override at least one of the defaults
impl Tr for () {}
//~^ ERROR overflow evaluating the requirement
// As soon as at least one is redefined, it works:
impl Tr for u8 {
type A = u8;
}
impl Tr for u16 {
type B = ();
}
impl Tr for u32 {
type A = ();
type B = u8;
}
// ...but only if this actually breaks the cycle
impl Tr for bool {
//~^ ERROR overflow evaluating the requirement
type A = Box<Self::B>;
//~^ ERROR overflow evaluating the requirement
}
// (the error is shown twice for some reason)
impl Tr for usize {
//~^ ERROR overflow evaluating the requirement
type B = &'static Self::A;
//~^ ERROR overflow evaluating the requirement
}
fn main() {
// We don't check that the types project correctly because the cycle errors stop compilation
// before `main` is type-checked.
// `defaults-cyclic-pass-1.rs` does this.
}

View file

@ -0,0 +1,33 @@
error[E0275]: overflow evaluating the requirement `<() as Tr>::B`
--> $DIR/defaults-cyclic-fail-1.rs:10:6
|
LL | impl Tr for () {}
| ^^
error[E0275]: overflow evaluating the requirement `<bool as Tr>::B`
--> $DIR/defaults-cyclic-fail-1.rs:28:6
|
LL | impl Tr for bool {
| ^^
error[E0275]: overflow evaluating the requirement `<usize as Tr>::B`
--> $DIR/defaults-cyclic-fail-1.rs:35:6
|
LL | impl Tr for usize {
| ^^
error[E0275]: overflow evaluating the requirement `<bool as Tr>::B`
--> $DIR/defaults-cyclic-fail-1.rs:30:5
|
LL | type A = Box<Self::B>;
| ^^^^^^^^^^^^^^^^^^^^^^
error[E0275]: overflow evaluating the requirement `<usize as Tr>::A`
--> $DIR/defaults-cyclic-fail-1.rs:37:5
|
LL | type B = &'static Self::A;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0275`.

View file

@ -0,0 +1,47 @@
#![feature(associated_type_defaults)]
// A more complex version of `defaults-cyclic-fail-1.rs`, with non-trivial defaults.
// Having a cycle in assoc. type defaults is okay...
trait Tr {
type A = Vec<Self::B>;
type B = Box<Self::A>;
}
// ...but is an error in any impl that doesn't override at least one of the defaults
impl Tr for () {}
//~^ ERROR overflow evaluating the requirement
// As soon as at least one is redefined, it works:
impl Tr for u8 {
type A = u8;
}
impl Tr for u16 {
type B = ();
}
impl Tr for u32 {
type A = ();
type B = u8;
}
// ...but only if this actually breaks the cycle
impl Tr for bool {
//~^ ERROR overflow evaluating the requirement
type A = Box<Self::B>;
//~^ ERROR overflow evaluating the requirement
}
// (the error is shown twice for some reason)
impl Tr for usize {
//~^ ERROR overflow evaluating the requirement
type B = &'static Self::A;
//~^ ERROR overflow evaluating the requirement
}
fn main() {
// We don't check that the types project correctly because the cycle errors stop compilation
// before `main` is type-checked.
// `defaults-cyclic-pass-2.rs` does this.
}

View file

@ -0,0 +1,33 @@
error[E0275]: overflow evaluating the requirement `<() as Tr>::B`
--> $DIR/defaults-cyclic-fail-2.rs:12:6
|
LL | impl Tr for () {}
| ^^
error[E0275]: overflow evaluating the requirement `<bool as Tr>::B`
--> $DIR/defaults-cyclic-fail-2.rs:30:6
|
LL | impl Tr for bool {
| ^^
error[E0275]: overflow evaluating the requirement `<usize as Tr>::B`
--> $DIR/defaults-cyclic-fail-2.rs:37:6
|
LL | impl Tr for usize {
| ^^
error[E0275]: overflow evaluating the requirement `<bool as Tr>::B`
--> $DIR/defaults-cyclic-fail-2.rs:32:5
|
LL | type A = Box<Self::B>;
| ^^^^^^^^^^^^^^^^^^^^^^
error[E0275]: overflow evaluating the requirement `<usize as Tr>::A`
--> $DIR/defaults-cyclic-fail-2.rs:39:5
|
LL | type B = &'static Self::A;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0275`.

View file

@ -0,0 +1,56 @@
// check-pass
#![feature(associated_type_defaults)]
// Having a cycle in assoc. type defaults is okay, as long as there's no impl
// that retains it.
trait Tr {
type A = Self::B;
type B = Self::A;
fn f();
}
// An impl has to break the cycle to be accepted.
impl Tr for u8 {
type A = u8;
fn f() {
// Check that the type propagates as expected (seen from inside the impl)
let _: Self::A = 0u8;
let _: Self::B = 0u8;
}
}
impl Tr for String {
type B = ();
fn f() {
// Check that the type propagates as expected (seen from inside the impl)
let _: Self::A = ();
let _: Self::B = ();
}
}
impl Tr for () {
type A = Vec<()>;
type B = u8;
fn f() {
// Check that the type propagates as expected (seen from inside the impl)
let _: Self::A = Vec::<()>::new();
let _: Self::B = 0u8;
}
}
fn main() {
// Check that both impls now have the right types (seen from outside the impls)
let _: <u8 as Tr>::A = 0u8;
let _: <u8 as Tr>::B = 0u8;
let _: <String as Tr>::A = ();
let _: <String as Tr>::B = ();
let _: <() as Tr>::A = Vec::<()>::new();
let _: <() as Tr>::B = 0u8;
}

View file

@ -0,0 +1,56 @@
// check-pass
#![feature(associated_type_defaults)]
// Having a cycle in assoc. type defaults is okay, as long as there's no impl
// that retains it.
trait Tr {
type A = Vec<Self::B>;
type B = Box<Self::A>;
fn f();
}
// An impl has to break the cycle to be accepted.
impl Tr for u8 {
type A = u8;
fn f() {
// Check that the type propagates as expected (seen from inside the impl)
let _: Self::A = 0u8;
let _: Self::B = Box::new(0u8);
}
}
impl Tr for String {
type B = ();
fn f() {
// Check that the type propagates as expected (seen from inside the impl)
let _: Self::A = Vec::<()>::new();
let _: Self::B = ();
}
}
impl Tr for () {
type A = Vec<()>;
type B = u8;
fn f() {
// Check that the type propagates as expected (seen from inside the impl)
let _: Self::A = Vec::<()>::new();
let _: Self::B = 0u8;
}
}
fn main() {
// Check that both impls now have the right types (seen from outside the impls)
let _: <u8 as Tr>::A = 0u8;
let _: <u8 as Tr>::B = Box::new(0u8);
let _: <String as Tr>::A = Vec::<()>::new();
let _: <String as Tr>::B = ();
let _: <() as Tr>::A = Vec::<()>::new();
let _: <() as Tr>::B = 0u8;
}

View file

@ -0,0 +1,37 @@
// check-pass
#![feature(associated_type_defaults)]
trait Tr {
type Item = u8;
type Container = Vec<Self::Item>;
}
impl Tr for () {}
impl Tr for u16 {
type Item = u16;
}
impl Tr for String {
type Container = String;
}
impl Tr for usize {
type Item = u32;
type Container = Vec<()>;
}
fn main() {
let _container: <() as Tr>::Container = Vec::<u8>::new();
let _item: <() as Tr>::Item = 0u8;
let _container: <u16 as Tr>::Container = Vec::<u16>::new();
let _item: <u16 as Tr>::Item = 0u16;
let _container: <String as Tr>::Container = String::new();
let _item: <String as Tr>::Item = 0u8;
let _container: <usize as Tr>::Container = Vec::<()>::new();
let _item: <usize as Tr>::Item = 0u32;
}

View file

@ -0,0 +1,50 @@
#![feature(associated_type_defaults)]
// Associated type defaults may not be assumed inside the trait defining them.
// ie. they only resolve to `<Self as Tr>::A`, not the actual type `()`
trait Tr {
type A = ();
fn f(p: Self::A) {
let () = p;
//~^ ERROR mismatched types
//~| NOTE expected associated type, found `()`
//~| NOTE expected associated type `<Self as Tr>::A`
//~| NOTE consider constraining the associated type
//~| NOTE for more information, visit
}
}
// An impl that doesn't override the type *can* assume the default.
impl Tr for () {
fn f(p: Self::A) {
let () = p;
}
}
impl Tr for u8 {
type A = ();
fn f(p: Self::A) {
let () = p;
}
}
trait AssocConst {
type Ty = u8;
// Assoc. consts also cannot assume that default types hold
const C: Self::Ty = 0u8;
//~^ ERROR mismatched types
//~| NOTE expected associated type, found `u8`
//~| NOTE expected associated type `<Self as AssocConst>::Ty`
//~| NOTE consider constraining the associated type
//~| NOTE for more information, visit
}
// An impl can, however
impl AssocConst for () {
const C: Self::Ty = 0u8;
}
fn main() {}

View file

@ -0,0 +1,25 @@
error[E0308]: mismatched types
--> $DIR/defaults-in-other-trait-items.rs:9:13
|
LL | let () = p;
| ^^ expected associated type, found `()`
|
= note: expected associated type `<Self as Tr>::A`
found unit type `()`
= note: consider constraining the associated type `<Self as Tr>::A` to `()` or calling a method that returns `<Self as Tr>::A`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
error[E0308]: mismatched types
--> $DIR/defaults-in-other-trait-items.rs:37:25
|
LL | const C: Self::Ty = 0u8;
| ^^^ expected associated type, found `u8`
|
= note: expected associated type `<Self as AssocConst>::Ty`
found type `u8`
= note: consider constraining the associated type `<Self as AssocConst>::Ty` to `u8` or calling a method that returns `<Self as AssocConst>::Ty`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -0,0 +1,34 @@
#![feature(associated_type_defaults)]
// Tests that a trait with one defaulted and one non-defaulted assoc. type behaves properly.
trait Trait {
type Foo = u8;
type Bar;
}
// `Bar` must be specified
impl Trait for () {}
//~^ error: not all trait items implemented, missing: `Bar`
impl Trait for bool {
//~^ error: not all trait items implemented, missing: `Bar`
type Foo = ();
}
impl Trait for u8 {
type Bar = ();
}
impl Trait for u16 {
type Foo = String;
type Bar = bool;
}
fn main() {
let _: <u8 as Trait>::Foo = 0u8;
let _: <u8 as Trait>::Bar = ();
let _: <u16 as Trait>::Foo = String::new();
let _: <u16 as Trait>::Bar = true;
}

View file

@ -0,0 +1,21 @@
error[E0046]: not all trait items implemented, missing: `Bar`
--> $DIR/defaults-mixed.rs:11:1
|
LL | type Bar;
| --------- `Bar` from trait
...
LL | impl Trait for () {}
| ^^^^^^^^^^^^^^^^^ missing `Bar` in implementation
error[E0046]: not all trait items implemented, missing: `Bar`
--> $DIR/defaults-mixed.rs:14:1
|
LL | type Bar;
| --------- `Bar` from trait
...
LL | impl Trait for bool {
| ^^^^^^^^^^^^^^^^^^^ missing `Bar` in implementation
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0046`.

View file

@ -0,0 +1,95 @@
//! Tests the interaction of associated type defaults and specialization.
#![feature(associated_type_defaults, specialization)]
trait Tr {
type Ty = u8;
fn make() -> Self::Ty {
0u8
//~^ error: mismatched types
}
}
struct A<T>(T);
// In a `default impl`, assoc. types are defaulted as well,
// so their values can't be assumed.
default impl<T> Tr for A<T> {
fn make() -> u8 { 0 }
//~^ ERROR method `make` has an incompatible type for trait
}
struct A2<T>(T);
// ...same, but in the method body
default impl<T> Tr for A2<T> {
fn make() -> Self::Ty { 0u8 }
//~^ ERROR mismatched types
}
struct B<T>(T);
// Explicitly defaulting the type does the same.
impl<T> Tr for B<T> {
default type Ty = bool;
fn make() -> bool { true }
//~^ ERROR method `make` has an incompatible type for trait
}
struct B2<T>(T);
// ...same, but in the method body
impl<T> Tr for B2<T> {
default type Ty = bool;
fn make() -> Self::Ty { true }
//~^ ERROR mismatched types
}
struct C<T>(T);
// Only the method is defaulted, so this is fine.
impl<T> Tr for C<T> {
type Ty = bool;
default fn make() -> bool { true }
}
// Defaulted method *can* assume the type, if the default is kept.
struct D<T>(T);
impl<T> Tr for D<T> {
default fn make() -> u8 { 0 }
}
impl Tr for D<bool> {
fn make() -> u8 { 255 }
}
struct E<T>(T);
impl<T> Tr for E<T> {
default type Ty = bool;
default fn make() -> Self::Ty { panic!(); }
}
// This impl specializes and sets `Ty`, it can rely on `Ty=String`.
impl Tr for E<bool> {
type Ty = String;
fn make() -> String { String::new() }
}
fn main() {
// Test that we can assume the right set of assoc. types from outside the impl
// This is a `default impl`, which does *not* mean that `A`/`A2` actually implement the trait.
// cf. https://github.com/rust-lang/rust/issues/48515
//let _: <A<()> as Tr>::Ty = 0u8;
//let _: <A2<()> as Tr>::Ty = 0u8;
let _: <B<()> as Tr>::Ty = 0u8; //~ error: mismatched types
let _: <B<()> as Tr>::Ty = true; //~ error: mismatched types
let _: <B2<()> as Tr>::Ty = 0u8; //~ error: mismatched types
let _: <B2<()> as Tr>::Ty = true; //~ error: mismatched types
let _: <C<()> as Tr>::Ty = true;
let _: <D<()> as Tr>::Ty = 0u8;
let _: <D<bool> as Tr>::Ty = 0u8;
}

View file

@ -0,0 +1,123 @@
error[E0053]: method `make` has an incompatible type for trait
--> $DIR/defaults-specialization.rs:18:18
|
LL | fn make() -> Self::Ty {
| -------- type in trait
...
LL | fn make() -> u8 { 0 }
| ^^ expected associated type, found `u8`
|
= note: expected fn pointer `fn() -> <A<T> as Tr>::Ty`
found fn pointer `fn() -> u8`
= note: consider constraining the associated type `<A<T> as Tr>::Ty` to `u8` or calling a method that returns `<A<T> as Tr>::Ty`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
error[E0053]: method `make` has an incompatible type for trait
--> $DIR/defaults-specialization.rs:34:18
|
LL | fn make() -> Self::Ty {
| -------- type in trait
...
LL | fn make() -> bool { true }
| ^^^^ expected associated type, found `bool`
|
= note: expected fn pointer `fn() -> <B<T> as Tr>::Ty`
found fn pointer `fn() -> bool`
= note: consider constraining the associated type `<B<T> as Tr>::Ty` to `bool` or calling a method that returns `<B<T> as Tr>::Ty`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
error[E0308]: mismatched types
--> $DIR/defaults-specialization.rs:9:9
|
LL | fn make() -> Self::Ty {
| -------- expected `<Self as Tr>::Ty` because of return type
LL | 0u8
| ^^^ expected associated type, found `u8`
|
= note: expected associated type `<Self as Tr>::Ty`
found type `u8`
= note: consider constraining the associated type `<Self as Tr>::Ty` to `u8` or calling a method that returns `<Self as Tr>::Ty`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
error[E0308]: mismatched types
--> $DIR/defaults-specialization.rs:25:29
|
LL | fn make() -> Self::Ty { 0u8 }
| -------- ^^^ expected associated type, found `u8`
| |
| expected `<A2<T> as Tr>::Ty` because of return type
|
= note: expected associated type `<A2<T> as Tr>::Ty`
found type `u8`
= note: consider constraining the associated type `<A2<T> as Tr>::Ty` to `u8` or calling a method that returns `<A2<T> as Tr>::Ty`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
error[E0308]: mismatched types
--> $DIR/defaults-specialization.rs:43:29
|
LL | fn make() -> Self::Ty { true }
| -------- ^^^^ expected associated type, found `bool`
| |
| expected `<B2<T> as Tr>::Ty` because of return type
|
= note: expected associated type `<B2<T> as Tr>::Ty`
found type `bool`
= note: consider constraining the associated type `<B2<T> as Tr>::Ty` to `bool` or calling a method that returns `<B2<T> as Tr>::Ty`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
error[E0308]: mismatched types
--> $DIR/defaults-specialization.rs:86:32
|
LL | let _: <B<()> as Tr>::Ty = 0u8;
| ----------------- ^^^ expected associated type, found `u8`
| |
| expected due to this
|
= note: expected associated type `<B<()> as Tr>::Ty`
found type `u8`
= note: consider constraining the associated type `<B<()> as Tr>::Ty` to `u8` or calling a method that returns `<B<()> as Tr>::Ty`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
error[E0308]: mismatched types
--> $DIR/defaults-specialization.rs:87:32
|
LL | let _: <B<()> as Tr>::Ty = true;
| ----------------- ^^^^ expected associated type, found `bool`
| |
| expected due to this
|
= note: expected associated type `<B<()> as Tr>::Ty`
found type `bool`
= note: consider constraining the associated type `<B<()> as Tr>::Ty` to `bool` or calling a method that returns `<B<()> as Tr>::Ty`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
error[E0308]: mismatched types
--> $DIR/defaults-specialization.rs:88:33
|
LL | let _: <B2<()> as Tr>::Ty = 0u8;
| ------------------ ^^^ expected associated type, found `u8`
| |
| expected due to this
|
= note: expected associated type `<B2<()> as Tr>::Ty`
found type `u8`
= note: consider constraining the associated type `<B2<()> as Tr>::Ty` to `u8` or calling a method that returns `<B2<()> as Tr>::Ty`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
error[E0308]: mismatched types
--> $DIR/defaults-specialization.rs:89:33
|
LL | let _: <B2<()> as Tr>::Ty = true;
| ------------------ ^^^^ expected associated type, found `bool`
| |
| expected due to this
|
= note: expected associated type `<B2<()> as Tr>::Ty`
found type `bool`
= note: consider constraining the associated type `<B2<()> as Tr>::Ty` to `bool` or calling a method that returns `<B2<()> as Tr>::Ty`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
error: aborting due to 9 previous errors
Some errors have detailed explanations: E0053, E0308.
For more information about an error, try `rustc --explain E0053`.

View file

@ -0,0 +1,106 @@
//! Checks that associated type defaults are properly validated.
//!
//! This means:
//! * Default types are wfchecked
//! * Default types are checked against where clauses on the assoc. type
//! (eg. `type Assoc: Clone = NotClone`), and also against where clauses on
//! the trait itself when possible
#![feature(associated_type_defaults)]
struct NotClone;
// Assoc. type bounds must hold for the default type
trait Tr {
type Ty: Clone = NotClone;
//~^ ERROR the trait bound `NotClone: std::clone::Clone` is not satisfied
}
// Where-clauses defined on the trait must also be considered
trait Tr2 where Self::Ty: Clone {
//~^ ERROR the trait bound `NotClone: std::clone::Clone` is not satisfied
type Ty = NotClone;
}
// Independent of where-clauses (there are none here), default types must always be wf
trait Tr3 {
type Ty = Vec<[u8]>;
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
}
// Involved type parameters must fulfill all bounds required by defaults that mention them
trait Foo<T> {
type Bar: Clone = Vec<T>;
//~^ ERROR the trait bound `T: std::clone::Clone` is not satisfied
}
trait Bar: Sized {
// `(): Foo<Self>` might hold for some possible impls but not all.
type Assoc: Foo<Self> = ();
//~^ ERROR the trait bound `(): Foo<Self>` is not satisfied
}
trait IsU8<T> {}
impl<T> IsU8<u8> for T {}
// Test that mentioning the assoc. type inside where clauses works
trait C where
Vec<Self::Assoc>: Clone,
Self::Assoc: IsU8<Self::Assoc>,
bool: IsU8<Self::Assoc>,
{
type Assoc = u8;
}
// Test that we get all expected errors if that default is unsuitable
trait D where
Vec<Self::Assoc>: Clone,
//~^ ERROR the trait bound `NotClone: std::clone::Clone` is not satisfied
Self::Assoc: IsU8<Self::Assoc>,
//~^ ERROR the trait bound `NotClone: IsU8<NotClone>` is not satisfied
bool: IsU8<Self::Assoc>,
//~^ ERROR the trait bound `bool: IsU8<NotClone>` is not satisfied
{
type Assoc = NotClone;
}
// Test behavior of the check when defaults refer to other defaults:
// Shallow substitution rejects this trait since `Baz` isn't guaranteed to be
// `Clone`.
trait Foo2<T> {
type Bar: Clone = Vec<Self::Baz>;
//~^ ERROR the trait bound `<Self as Foo2<T>>::Baz: std::clone::Clone` is not satisfied
type Baz = T;
}
// Adding a `T: Clone` bound doesn't help since the requirement doesn't see `T`
// because of the shallow substitution. If we did a deep substitution instead,
// this would be accepted.
trait Foo25<T: Clone> {
type Bar: Clone = Vec<Self::Baz>;
//~^ ERROR the trait bound `<Self as Foo25<T>>::Baz: std::clone::Clone` is not satisfied
type Baz = T;
}
// Adding the `Baz: Clone` bound isn't enough since the default is type
// parameter `T`, which also might not be `Clone`.
trait Foo3<T> where
Self::Bar: Clone,
Self::Baz: Clone,
//~^ ERROR the trait bound `T: std::clone::Clone` is not satisfied
{
type Bar = Vec<Self::Baz>;
type Baz = T;
}
// This one finally works, with `Clone` bounds on all assoc. types and the type
// parameter.
trait Foo4<T> where
T: Clone,
{
type Bar: Clone = Vec<Self::Baz>;
type Baz: Clone = T;
}
fn main() {}

View file

@ -0,0 +1,140 @@
error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied
--> $DIR/defaults-suitability.rs:15:14
|
LL | trait Tr {
| -------- required by `Tr`
LL | type Ty: Clone = NotClone;
| ^^^^^ the trait `std::clone::Clone` is not implemented for `NotClone`
error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied
--> $DIR/defaults-suitability.rs:20:27
|
LL | trait Tr2 where Self::Ty: Clone {
| --------------------------^^^^^
| | |
| | the trait `std::clone::Clone` is not implemented for `NotClone`
| required by `Tr2`
error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied
--> $DIR/defaults-suitability.rs:33:15
|
LL | trait Foo<T> {
| ------------ required by `Foo`
LL | type Bar: Clone = Vec<T>;
| ^^^^^ the trait `std::clone::Clone` is not implemented for `T`
|
help: consider restricting this type parameter with `T: std::clone::Clone`
--> $DIR/defaults-suitability.rs:32:11
|
LL | trait Foo<T> {
| ^
= note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<T>`
error[E0277]: the trait bound `(): Foo<Self>` is not satisfied
--> $DIR/defaults-suitability.rs:39:17
|
LL | trait Bar: Sized {
| ---------------- required by `Bar`
LL | // `(): Foo<Self>` might hold for some possible impls but not all.
LL | type Assoc: Foo<Self> = ();
| ^^^^^^^^^ the trait `Foo<Self>` is not implemented for `()`
error[E0277]: the trait bound `NotClone: IsU8<NotClone>` is not satisfied
--> $DIR/defaults-suitability.rs:59:18
|
LL | / trait D where
LL | | Vec<Self::Assoc>: Clone,
LL | |
LL | | Self::Assoc: IsU8<Self::Assoc>,
| | ^^^^^^^^^^^^^^^^^ the trait `IsU8<NotClone>` is not implemented for `NotClone`
... |
LL | | type Assoc = NotClone;
LL | | }
| |_- required by `D`
error[E0277]: the trait bound `bool: IsU8<NotClone>` is not satisfied
--> $DIR/defaults-suitability.rs:61:11
|
LL | / trait D where
LL | | Vec<Self::Assoc>: Clone,
LL | |
LL | | Self::Assoc: IsU8<Self::Assoc>,
LL | |
LL | | bool: IsU8<Self::Assoc>,
| | ^^^^^^^^^^^^^^^^^ the trait `IsU8<NotClone>` is not implemented for `bool`
... |
LL | | type Assoc = NotClone;
LL | | }
| |_- required by `D`
error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied
--> $DIR/defaults-suitability.rs:57:23
|
LL | / trait D where
LL | | Vec<Self::Assoc>: Clone,
| | ^^^^^ the trait `std::clone::Clone` is not implemented for `NotClone`
LL | |
LL | | Self::Assoc: IsU8<Self::Assoc>,
... |
LL | | type Assoc = NotClone;
LL | | }
| |_- required by `D`
|
= note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<NotClone>`
error[E0277]: the trait bound `<Self as Foo2<T>>::Baz: std::clone::Clone` is not satisfied
--> $DIR/defaults-suitability.rs:72:15
|
LL | trait Foo2<T> {
| -------------- help: consider further restricting the associated type: `where <Self as Foo2<T>>::Baz: std::clone::Clone`
| |
| required by `Foo2`
LL | type Bar: Clone = Vec<Self::Baz>;
| ^^^^^ the trait `std::clone::Clone` is not implemented for `<Self as Foo2<T>>::Baz`
|
= note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<<Self as Foo2<T>>::Baz>`
error[E0277]: the trait bound `<Self as Foo25<T>>::Baz: std::clone::Clone` is not satisfied
--> $DIR/defaults-suitability.rs:81:15
|
LL | trait Foo25<T: Clone> {
| ---------------------- help: consider further restricting the associated type: `where <Self as Foo25<T>>::Baz: std::clone::Clone`
| |
| required by `Foo25`
LL | type Bar: Clone = Vec<Self::Baz>;
| ^^^^^ the trait `std::clone::Clone` is not implemented for `<Self as Foo25<T>>::Baz`
|
= note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<<Self as Foo25<T>>::Baz>`
error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied
--> $DIR/defaults-suitability.rs:90:16
|
LL | / trait Foo3<T> where
LL | | Self::Bar: Clone,
LL | | Self::Baz: Clone,
| | ^^^^^ the trait `std::clone::Clone` is not implemented for `T`
LL | |
... |
LL | | type Baz = T;
LL | | }
| |_- required by `Foo3`
|
help: consider restricting this type parameter with `where T: std::clone::Clone`
--> $DIR/defaults-suitability.rs:88:12
|
LL | trait Foo3<T> where
| ^
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/defaults-suitability.rs:27:5
|
LL | type Ty = Vec<[u8]>;
| ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[u8]`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: required by `std::vec::Vec`
error: aborting due to 11 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -0,0 +1,63 @@
//! Regression test for https://github.com/rust-lang/rust/issues/62211
//!
//! The old implementation of defaults did not check whether the provided
//! default actually fulfills all bounds on the assoc. type, leading to
//! unsoundness, demonstrated here as a use-after-free.
//!
//! Note that the underlying cause of this is still not yet fixed.
//! See: https://github.com/rust-lang/rust/issues/33017
#![feature(associated_type_defaults)]
use std::{
fmt::Display,
ops::{AddAssign, Deref}
};
trait UncheckedCopy: Sized {
// This Output is said to be Copy. Yet we default to Self
// and it's accepted, not knowing if Self ineed is Copy
type Output: Copy
//~^ ERROR the trait bound `Self: std::marker::Copy` is not satisfied
+ Deref<Target = str>
//~^ ERROR the trait bound `Self: std::ops::Deref` is not satisfied
+ AddAssign<&'static str>
//~^ ERROR cannot add-assign `&'static str` to `Self`
+ From<Self>
+ Display = Self;
//~^ ERROR `Self` doesn't implement `std::fmt::Display`
// We said the Output type was Copy, so we can Copy it freely!
fn unchecked_copy(other: &Self::Output) -> Self::Output {
(*other)
}
fn make_origin(s: Self) -> Self::Output {
s.into()
}
}
impl<T> UncheckedCopy for T {}
//~^ ERROR `T` doesn't implement `std::fmt::Display`
//~| ERROR the trait bound `T: std::ops::Deref` is not satisfied
//~| ERROR cannot add-assign `&'static str` to `T`
//~| ERROR the trait bound `T: std::marker::Copy` is not satisfied
fn bug<T: UncheckedCopy>(origin: T) {
let origin = T::make_origin(origin);
let mut copy = T::unchecked_copy(&origin);
// assert we indeed have 2 strings pointing to the same buffer.
assert_eq!(origin.as_ptr(), copy.as_ptr());
// Drop the origin. Any use of `copy` is UB.
drop(origin);
copy += "This is invalid!";
println!("{}", copy);
}
fn main() {
bug(String::from("hello!"));
}

View file

@ -0,0 +1,95 @@
error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied
--> $DIR/defaults-unsound-62211-1.rs:21:18
|
LL | trait UncheckedCopy: Sized {
| -------------------------- required by `UncheckedCopy`
...
LL | type Output: Copy
| ^^^^ the trait `std::marker::Copy` is not implemented for `Self`
error[E0277]: cannot add-assign `&'static str` to `Self`
--> $DIR/defaults-unsound-62211-1.rs:25:7
|
LL | trait UncheckedCopy: Sized {
| -------------------------- required by `UncheckedCopy`
...
LL | + AddAssign<&'static str>
| ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str`
|
= help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self`
error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied
--> $DIR/defaults-unsound-62211-1.rs:23:7
|
LL | trait UncheckedCopy: Sized {
| -------------------------- required by `UncheckedCopy`
...
LL | + Deref<Target = str>
| ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self`
error[E0277]: `Self` doesn't implement `std::fmt::Display`
--> $DIR/defaults-unsound-62211-1.rs:28:7
|
LL | trait UncheckedCopy: Sized {
| -------------------------- required by `UncheckedCopy`
...
LL | + Display = Self;
| ^^^^^^^ `Self` cannot be formatted with the default formatter
|
= help: the trait `std::fmt::Display` is not implemented for `Self`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
error[E0277]: `T` doesn't implement `std::fmt::Display`
--> $DIR/defaults-unsound-62211-1.rs:41:9
|
LL | impl<T> UncheckedCopy for T {}
| ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter
|
= help: the trait `std::fmt::Display` is not implemented for `T`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
help: consider restricting this type parameter with `T: std::fmt::Display`
--> $DIR/defaults-unsound-62211-1.rs:41:6
|
LL | impl<T> UncheckedCopy for T {}
| ^
error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied
--> $DIR/defaults-unsound-62211-1.rs:41:9
|
LL | impl<T> UncheckedCopy for T {}
| ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T`
|
help: consider restricting this type parameter with `T: std::ops::Deref`
--> $DIR/defaults-unsound-62211-1.rs:41:6
|
LL | impl<T> UncheckedCopy for T {}
| ^
error[E0277]: cannot add-assign `&'static str` to `T`
--> $DIR/defaults-unsound-62211-1.rs:41:9
|
LL | impl<T> UncheckedCopy for T {}
| ^^^^^^^^^^^^^ no implementation for `T += &'static str`
|
= help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `T`
help: consider restricting this type parameter with `T: std::ops::AddAssign<&'static str>`
--> $DIR/defaults-unsound-62211-1.rs:41:6
|
LL | impl<T> UncheckedCopy for T {}
| ^
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
--> $DIR/defaults-unsound-62211-1.rs:41:9
|
LL | impl<T> UncheckedCopy for T {}
| ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
help: consider restricting this type parameter with `T: std::marker::Copy`
--> $DIR/defaults-unsound-62211-1.rs:41:6
|
LL | impl<T> UncheckedCopy for T {}
| ^
error: aborting due to 8 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -0,0 +1,63 @@
//! Regression test for https://github.com/rust-lang/rust/issues/62211
//!
//! The old implementation of defaults did not check whether the provided
//! default actually fulfills all bounds on the assoc. type, leading to
//! unsoundness and ICEs, the latter being demonstrated here.
//!
//! Note that the underlying cause of this is still not yet fixed.
//! See: https://github.com/rust-lang/rust/issues/33017
#![feature(associated_type_defaults)]
use std::{
fmt::Display,
ops::{AddAssign, Deref}
};
trait UncheckedCopy: Sized {
// This Output is said to be Copy. Yet we default to Self
// and it's accepted, not knowing if Self ineed is Copy
type Output: Copy
//~^ ERROR the trait bound `Self: std::marker::Copy` is not satisfied
+ Deref<Target = str>
//~^ ERROR the trait bound `Self: std::ops::Deref` is not satisfied
+ AddAssign<&'static str>
//~^ ERROR cannot add-assign `&'static str` to `Self`
+ From<Self>
+ Display = Self;
//~^ ERROR `Self` doesn't implement `std::fmt::Display`
// We said the Output type was Copy, so we can Copy it freely!
fn unchecked_copy(other: &Self::Output) -> Self::Output {
(*other)
}
fn make_origin(s: Self) -> Self::Output {
s.into()
}
}
impl<T> UncheckedCopy for T {}
//~^ ERROR `T` doesn't implement `std::fmt::Display`
//~| ERROR the trait bound `T: std::ops::Deref` is not satisfied
//~| ERROR cannot add-assign `&'static str` to `T`
//~| ERROR the trait bound `T: std::marker::Copy` is not satisfied
fn bug<T: UncheckedCopy>(origin: T) {
let origin = T::make_origin(origin);
let mut copy = T::unchecked_copy(&origin);
// assert we indeed have 2 strings pointing to the same buffer.
assert_eq!(origin.as_ptr(), copy.as_ptr());
// Drop the origin. Any use of `copy` is UB.
drop(origin);
copy += "This is invalid!";
println!("{}", copy);
}
fn main() {
bug(());
}

View file

@ -0,0 +1,95 @@
error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied
--> $DIR/defaults-unsound-62211-2.rs:21:18
|
LL | trait UncheckedCopy: Sized {
| -------------------------- required by `UncheckedCopy`
...
LL | type Output: Copy
| ^^^^ the trait `std::marker::Copy` is not implemented for `Self`
error[E0277]: cannot add-assign `&'static str` to `Self`
--> $DIR/defaults-unsound-62211-2.rs:25:7
|
LL | trait UncheckedCopy: Sized {
| -------------------------- required by `UncheckedCopy`
...
LL | + AddAssign<&'static str>
| ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str`
|
= help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self`
error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied
--> $DIR/defaults-unsound-62211-2.rs:23:7
|
LL | trait UncheckedCopy: Sized {
| -------------------------- required by `UncheckedCopy`
...
LL | + Deref<Target = str>
| ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self`
error[E0277]: `Self` doesn't implement `std::fmt::Display`
--> $DIR/defaults-unsound-62211-2.rs:28:7
|
LL | trait UncheckedCopy: Sized {
| -------------------------- required by `UncheckedCopy`
...
LL | + Display = Self;
| ^^^^^^^ `Self` cannot be formatted with the default formatter
|
= help: the trait `std::fmt::Display` is not implemented for `Self`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
error[E0277]: `T` doesn't implement `std::fmt::Display`
--> $DIR/defaults-unsound-62211-2.rs:41:9
|
LL | impl<T> UncheckedCopy for T {}
| ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter
|
= help: the trait `std::fmt::Display` is not implemented for `T`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
help: consider restricting this type parameter with `T: std::fmt::Display`
--> $DIR/defaults-unsound-62211-2.rs:41:6
|
LL | impl<T> UncheckedCopy for T {}
| ^
error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied
--> $DIR/defaults-unsound-62211-2.rs:41:9
|
LL | impl<T> UncheckedCopy for T {}
| ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T`
|
help: consider restricting this type parameter with `T: std::ops::Deref`
--> $DIR/defaults-unsound-62211-2.rs:41:6
|
LL | impl<T> UncheckedCopy for T {}
| ^
error[E0277]: cannot add-assign `&'static str` to `T`
--> $DIR/defaults-unsound-62211-2.rs:41:9
|
LL | impl<T> UncheckedCopy for T {}
| ^^^^^^^^^^^^^ no implementation for `T += &'static str`
|
= help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `T`
help: consider restricting this type parameter with `T: std::ops::AddAssign<&'static str>`
--> $DIR/defaults-unsound-62211-2.rs:41:6
|
LL | impl<T> UncheckedCopy for T {}
| ^
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
--> $DIR/defaults-unsound-62211-2.rs:41:9
|
LL | impl<T> UncheckedCopy for T {}
| ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
help: consider restricting this type parameter with `T: std::marker::Copy`
--> $DIR/defaults-unsound-62211-2.rs:41:6
|
LL | impl<T> UncheckedCopy for T {}
| ^
error: aborting due to 8 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -0,0 +1,20 @@
#![feature(associated_type_defaults)]
// This is a partial regression test for #26681, which used to fail to resolve
// `Self` in the assoc. constant, and now fails with a type mismatch because
// `Self::Fv` cannot be assumed to equal `u8` inside the trait.
trait Foo {
type Bar;
}
impl Foo for u8 {
type Bar = ();
}
trait Baz {
type Fv: Foo = u8;
const C: <Self::Fv as Foo>::Bar = 6665; //~ error: mismatched types
}
fn main() {}

View file

@ -0,0 +1,14 @@
error[E0308]: mismatched types
--> $DIR/issue-26681.rs:17:39
|
LL | const C: <Self::Fv as Foo>::Bar = 6665;
| ^^^^ expected associated type, found integer
|
= note: expected associated type `<<Self as Baz>::Fv as Foo>::Bar`
found type `{integer}`
= note: consider constraining the associated type `<<Self as Baz>::Fv as Foo>::Bar` to `{integer}` or calling a method that returns `<<Self as Baz>::Fv as Foo>::Bar`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.

View file

@ -0,0 +1,29 @@
// check-pass
// This is another instance of the "normalizations don't work" issue with
// defaulted associated types.
#![feature(associated_type_defaults)]
pub trait Emitter<'a> {
type Ctxt: 'a;
type CtxtBrw: 'a = &'a Self::Ctxt;
fn get_cx(&'a self) -> Self::CtxtBrw;
}
struct MyCtxt;
struct MyEmitter {
ctxt: MyCtxt
}
impl <'a> Emitter<'a> for MyEmitter {
type Ctxt = MyCtxt;
fn get_cx(&'a self) -> &'a MyCtxt {
&self.ctxt
}
}
fn main() {}

View file

@ -0,0 +1,23 @@
// check-pass
// Defaulted assoc. types should normalize properly in impls that don't
// override them.
#![feature(associated_type_defaults)]
pub struct Foo;
pub trait CanDecode: Sized {
type Output = Self;
fn read(rdr: &mut Foo) -> Option<Self::Output>;
}
impl CanDecode for u8 {
fn read(rdr: &mut Foo) -> Option<Self::Output> { Some(42) }
}
impl CanDecode for u16 {
fn read(rdr: &mut Foo) -> Option<u16> { Some(17) }
}
fn main() {}

View file

@ -0,0 +1,15 @@
#![feature(associated_type_defaults)]
// This used to cause an ICE because assoc. type defaults weren't properly
// type-checked.
trait Foo<T: Default + ToString> {
type Out: Default + ToString + ?Sized = dyn ToString; //~ error: not satisfied
}
impl Foo<u32> for () {} //~ error: not satisfied
impl Foo<u64> for () {} //~ error: not satisfied
fn main() {
assert_eq!(<() as Foo<u32>>::Out::default().to_string(), "false");
}

View file

@ -0,0 +1,23 @@
error[E0277]: the trait bound `(dyn std::string::ToString + 'static): std::default::Default` is not satisfied
--> $DIR/issue-43924.rs:7:15
|
LL | trait Foo<T: Default + ToString> {
| -------------------------------- required by `Foo`
LL | type Out: Default + ToString + ?Sized = dyn ToString;
| ^^^^^^^ the trait `std::default::Default` is not implemented for `(dyn std::string::ToString + 'static)`
error[E0277]: the trait bound `(dyn std::string::ToString + 'static): std::default::Default` is not satisfied
--> $DIR/issue-43924.rs:10:6
|
LL | impl Foo<u32> for () {}
| ^^^^^^^^ the trait `std::default::Default` is not implemented for `(dyn std::string::ToString + 'static)`
error[E0277]: the trait bound `(dyn std::string::ToString + 'static): std::default::Default` is not satisfied
--> $DIR/issue-43924.rs:11:6
|
LL | impl Foo<u64> for () {}
| ^^^^^^^^ the trait `std::default::Default` is not implemented for `(dyn std::string::ToString + 'static)`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -0,0 +1,16 @@
// check-pass
#![feature(associated_type_defaults)]
pub struct Foo;
pub trait Bar: From<<Self as Bar>::Input> {
type Input = Self;
}
impl Bar for Foo {
// Will compile with explicit type:
// type Input = Self;
}
fn main() {}

View file

@ -0,0 +1,92 @@
// run-pass
// Tests that the return type of trait methods is correctly normalized when
// checking that a method in an impl matches the trait definition when the
// return type involves a defaulted associated type.
// ie. the trait has a method with return type `-> Self::R`, and `type R = ()`,
// but the impl leaves out the return type (resulting in `()`).
// Note that specialization is not involved in this test; no items in
// implementations may be overridden. If they were, the normalization wouldn't
// happen.
#![feature(associated_type_defaults)]
macro_rules! overload {
($a:expr, $b:expr) => {
overload::overload2($a, $b)
};
($a:expr, $b:expr, $c:expr) => {
overload::overload3($a, $b, $c)
}
}
fn main() {
let () = overload!(42, true);
let r: f32 = overload!("Hello world", 13.0);
assert_eq!(r, 13.0);
let () = overload!(42, true, 42.5);
let r: i32 = overload!("Hello world", 13.0, 42);
assert_eq!(r, 42);
}
mod overload {
/// This trait has an assoc. type defaulting to `()`, and a required method returning a value
/// of that assoc. type.
pub trait Overload {
// type R;
type R = ();
fn overload(self) -> Self::R;
}
// overloads for 2 args
impl Overload for (i32, bool) {
// type R = ();
/// This function has no return type specified, and so defaults to `()`.
///
/// This should work, but didn't, until RFC 2532 was implemented.
fn overload(self) /*-> Self::R*/ {
let (a, b) = self; // destructure args
println!("i32 and bool {:?}", (a, b));
}
}
impl<'a> Overload for (&'a str, f32) {
type R = f32;
fn overload(self) -> Self::R {
let (a, b) = self; // destructure args
println!("&str and f32 {:?}", (a, b));
b
}
}
// overloads for 3 args
impl Overload for (i32, bool, f32) {
// type R = ();
fn overload(self) /*-> Self::R*/ {
let (a, b, c) = self; // destructure args
println!("i32 and bool and f32 {:?}", (a, b, c));
}
}
impl<'a> Overload for (&'a str, f32, i32) {
type R = i32;
fn overload(self) -> Self::R {
let (a, b, c) = self; // destructure args
println!("&str and f32 and i32: {:?}", (a, b, c));
c
}
}
// overloads for more args
// ...
pub fn overload2<R, A, B>(a: A, b: B) -> R where (A, B): Overload<R = R> {
(a, b).overload()
}
pub fn overload3<R, A, B, C>(a: A, b: B, c: C) -> R where (A, B, C): Overload<R = R> {
(a, b, c).overload()
}
}

View file

@ -0,0 +1,19 @@
// check-pass
// Before RFC 2532, normalizing a defaulted assoc. type didn't work at all,
// unless the impl in question overrides that type, which makes the default
// pointless.
#![feature(associated_type_defaults)]
trait Tr {
type Assoc = ();
}
impl Tr for () {}
fn f(thing: <() as Tr>::Assoc) {
let c: () = thing;
}
fn main() {}

View file

@ -0,0 +1,13 @@
#![feature(associated_type_defaults)]
// Tests that `Self` is not assumed to implement `Sized` when used as an
// associated type default.
trait Inner<S> {}
trait MyTrait {
type This = Self; //~ error: size for values of type `Self` cannot be known
fn something<I: Inner<Self::This>>(i: I);
}
fn main() {}

View file

@ -0,0 +1,14 @@
error[E0277]: the size for values of type `Self` cannot be known at compilation time
--> $DIR/issue-63593.rs:9:5
|
LL | trait MyTrait {
| ------------- required by `MyTrait`
LL | type This = Self;
| ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `Self`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -0,0 +1,58 @@
#![feature(associated_type_defaults)]
trait MyDisplay { fn method(&self) { } }
impl<'a, T: MyDisplay> MyDisplay for &'a mut T { }
struct T;
trait MPU {
type MpuConfig: MyDisplay = T;
//~^ ERROR the trait bound `T: MyDisplay` is not satisfied
}
struct S;
impl MPU for S { }
//~^ ERROR the trait bound `T: MyDisplay` is not satisfied
trait MyWrite {
fn my_write(&self, _: &dyn MyDisplay) { }
}
trait ProcessType {
fn process_detail_fmt(&self, _: &mut dyn MyWrite);
}
struct Process;
impl ProcessType for Process {
fn process_detail_fmt(&self, writer: &mut dyn MyWrite)
{
let mut val: Option<<S as MPU>::MpuConfig> = None;
let valref: &mut <S as MPU>::MpuConfig = val.as_mut().unwrap();
// // This causes a different ICE (but its similar if you squint right):
// //
// // `Unimplemented` selecting `Binder(<T as MyDisplay>)` during codegen
//
// writer.my_write(valref)
// This one causes the ICE:
// FulfillmentError(Obligation(predicate=Binder(TraitPredicate(<T as MyDisplay>)),
// depth=1),Unimplemented)
let closure = |config: &mut <S as MPU>::MpuConfig| writer.my_write(&config);
closure(valref);
}
}
fn create() -> &'static dyn ProcessType {
let input: Option<&mut Process> = None;
let process: &mut Process = input.unwrap();
process
}
pub fn main() {
create();
}

View file

@ -0,0 +1,17 @@
error[E0277]: the trait bound `T: MyDisplay` is not satisfied
--> $DIR/issue-65774-1.rs:10:21
|
LL | trait MPU {
| --------- required by `MPU`
LL | type MpuConfig: MyDisplay = T;
| ^^^^^^^^^ the trait `MyDisplay` is not implemented for `T`
error[E0277]: the trait bound `T: MyDisplay` is not satisfied
--> $DIR/issue-65774-1.rs:16:6
|
LL | impl MPU for S { }
| ^^^ the trait `MyDisplay` is not implemented for `T`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -0,0 +1,58 @@
#![feature(associated_type_defaults)]
trait MyDisplay { fn method(&self) { } }
impl<'a, T: MyDisplay> MyDisplay for &'a mut T { }
struct T;
trait MPU {
type MpuConfig: MyDisplay = T;
//~^ ERROR the trait bound `T: MyDisplay` is not satisfied
}
struct S;
impl MPU for S { }
//~^ ERROR the trait bound `T: MyDisplay` is not satisfied
trait MyWrite {
fn my_write(&self, _: &dyn MyDisplay) { }
}
trait ProcessType {
fn process_detail_fmt(&self, _: &mut dyn MyWrite);
}
struct Process;
impl ProcessType for Process {
fn process_detail_fmt(&self, writer: &mut dyn MyWrite)
{
let mut val: Option<<S as MPU>::MpuConfig> = None;
let valref: &mut <S as MPU>::MpuConfig = val.as_mut().unwrap();
// // This causes a different ICE (but its similar if you squint right):
// //
// // `Unimplemented` selecting `Binder(<T as MyDisplay>)` during codegen
//
writer.my_write(valref)
// This one causes the ICE:
// FulfillmentError(Obligation(predicate=Binder(TraitPredicate(<T as MyDisplay>)),
// depth=1),Unimplemented)
/*let closure = |config: &mut <S as MPU>::MpuConfig| writer.my_write(&config);
closure(valref);*/
}
}
fn create() -> &'static dyn ProcessType {
let input: Option<&mut Process> = None;
let process: &mut Process = input.unwrap();
process
}
pub fn main() {
create();
}

View file

@ -0,0 +1,17 @@
error[E0277]: the trait bound `T: MyDisplay` is not satisfied
--> $DIR/issue-65774-2.rs:10:21
|
LL | trait MPU {
| --------- required by `MPU`
LL | type MpuConfig: MyDisplay = T;
| ^^^^^^^^^ the trait `MyDisplay` is not implemented for `T`
error[E0277]: the trait bound `T: MyDisplay` is not satisfied
--> $DIR/issue-65774-2.rs:16:6
|
LL | impl MPU for S { }
| ^^^ the trait `MyDisplay` is not implemented for `T`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -60,7 +60,7 @@ pub trait D {
}
/// dox
pub trait E {
pub trait E: Sized {
type AssociatedType; //~ ERROR: missing documentation for an associated type
type AssociatedTypeDef = Self; //~ ERROR: missing documentation for an associated type

View file

@ -23,8 +23,7 @@ mod priv_trait {
<Pub as PrivTr>::CONST;
//~^ ERROR associated constant `PrivTr::CONST` is private
let _: <Pub as PrivTr>::AssocTy;
//~^ ERROR trait `priv_trait::PrivTr` is private
//~| ERROR trait `priv_trait::PrivTr` is private
//~^ ERROR associated type `PrivTr::AssocTy` is private
pub type InSignatureTy = <Pub as PrivTr>::AssocTy;
//~^ ERROR trait `priv_trait::PrivTr` is private
pub trait InSignatureTr: PrivTr {}
@ -116,15 +115,11 @@ mod priv_parent_substs {
<Priv as PubTr<_>>::CONST;
//~^ ERROR type `priv_parent_substs::Priv` is private
let _: <Pub as PubTr>::AssocTy;
//~^ ERROR type `priv_parent_substs::Priv` is private
//~| ERROR type `priv_parent_substs::Priv` is private
let _: <Pub as PubTr>::AssocTy; // FIXME no longer an error?!
let _: <Pub as PubTr<_>>::AssocTy;
//~^ ERROR type `priv_parent_substs::Priv` is private
//~| ERROR type `priv_parent_substs::Priv` is private
let _: <Priv as PubTr<_>>::AssocTy;
//~^ ERROR type `priv_parent_substs::Priv` is private
//~| ERROR type `priv_parent_substs::Priv` is private
pub type InSignatureTy1 = <Pub as PubTr>::AssocTy;
//~^ ERROR type `priv_parent_substs::Priv` is private

View file

@ -42,18 +42,7 @@ LL | priv_trait::mac!();
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: trait `priv_trait::PrivTr` is private
--> $DIR/associated-item-privacy-trait.rs:25:13
|
LL | let _: <Pub as PrivTr>::AssocTy;
| ^
...
LL | priv_trait::mac!();
| ------------------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: trait `priv_trait::PrivTr` is private
error: associated type `PrivTr::AssocTy` is private
--> $DIR/associated-item-privacy-trait.rs:25:16
|
LL | let _: <Pub as PrivTr>::AssocTy;
@ -65,7 +54,7 @@ LL | priv_trait::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: trait `priv_trait::PrivTr` is private
--> $DIR/associated-item-privacy-trait.rs:28:34
--> $DIR/associated-item-privacy-trait.rs:27:34
|
LL | pub type InSignatureTy = <Pub as PrivTr>::AssocTy;
| ^^^^^^^^^^^^^^^^^^^^^^^^
@ -76,7 +65,7 @@ LL | priv_trait::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: trait `priv_trait::PrivTr` is private
--> $DIR/associated-item-privacy-trait.rs:30:34
--> $DIR/associated-item-privacy-trait.rs:29:34
|
LL | pub trait InSignatureTr: PrivTr {}
| ^^^^^^
@ -87,7 +76,7 @@ LL | priv_trait::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: trait `priv_trait::PrivTr` is private
--> $DIR/associated-item-privacy-trait.rs:32:14
--> $DIR/associated-item-privacy-trait.rs:31:14
|
LL | impl PrivTr for u8 {}
| ^^^^^^
@ -98,7 +87,7 @@ LL | priv_trait::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_signature::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:49:21
--> $DIR/associated-item-privacy-trait.rs:48:21
|
LL | let value = <Pub as PubTr>::method;
| ^^^^^^^^^^^^^^^^^^^^^^
@ -109,7 +98,7 @@ LL | priv_signature::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_signature::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:51:9
--> $DIR/associated-item-privacy-trait.rs:50:9
|
LL | value;
| ^^^^^
@ -120,7 +109,7 @@ LL | priv_signature::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_signature::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:53:13
--> $DIR/associated-item-privacy-trait.rs:52:13
|
LL | Pub.method(loop {});
| ^^^^^^
@ -131,7 +120,7 @@ LL | priv_signature::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_substs::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:70:21
--> $DIR/associated-item-privacy-trait.rs:69:21
|
LL | let value = <Pub as PubTr>::method::<Priv>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -142,7 +131,7 @@ LL | priv_substs::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_substs::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:72:9
--> $DIR/associated-item-privacy-trait.rs:71:9
|
LL | value;
| ^^^^^
@ -153,7 +142,7 @@ LL | priv_substs::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_substs::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:74:9
--> $DIR/associated-item-privacy-trait.rs:73:9
|
LL | Pub.method::<Priv>();
| ^^^^^^^^^^^^^^^^^^^^
@ -164,7 +153,7 @@ LL | priv_substs::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_parent_substs::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:94:21
--> $DIR/associated-item-privacy-trait.rs:93:21
|
LL | let value = <Pub as PubTr>::method;
| ^^^^^^^^^^^^^^^^^^^^^^
@ -175,7 +164,7 @@ LL | priv_parent_substs::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_parent_substs::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:96:9
--> $DIR/associated-item-privacy-trait.rs:95:9
|
LL | value;
| ^^^^^
@ -186,7 +175,7 @@ LL | priv_parent_substs::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_parent_substs::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:98:21
--> $DIR/associated-item-privacy-trait.rs:97:21
|
LL | let value = <Pub as PubTr<_>>::method;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@ -197,7 +186,7 @@ LL | priv_parent_substs::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_parent_substs::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:100:9
--> $DIR/associated-item-privacy-trait.rs:99:9
|
LL | value;
| ^^^^^
@ -208,7 +197,7 @@ LL | priv_parent_substs::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_parent_substs::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:102:9
--> $DIR/associated-item-privacy-trait.rs:101:9
|
LL | Pub.method();
| ^^^^^^^^^^^^
@ -219,7 +208,7 @@ LL | priv_parent_substs::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_parent_substs::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:105:21
--> $DIR/associated-item-privacy-trait.rs:104:21
|
LL | let value = <Priv as PubTr<_>>::method;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -230,7 +219,7 @@ LL | priv_parent_substs::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_parent_substs::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:107:9
--> $DIR/associated-item-privacy-trait.rs:106:9
|
LL | value;
| ^^^^^
@ -241,7 +230,7 @@ LL | priv_parent_substs::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_parent_substs::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:109:9
--> $DIR/associated-item-privacy-trait.rs:108:9
|
LL | Priv.method();
| ^^^^^^^^^^^^^
@ -252,7 +241,7 @@ LL | priv_parent_substs::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_parent_substs::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:112:9
--> $DIR/associated-item-privacy-trait.rs:111:9
|
LL | <Pub as PubTr>::CONST;
| ^^^^^^^^^^^^^^^^^^^^^
@ -263,7 +252,7 @@ LL | priv_parent_substs::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_parent_substs::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:114:9
--> $DIR/associated-item-privacy-trait.rs:113:9
|
LL | <Pub as PubTr<_>>::CONST;
| ^^^^^^^^^^^^^^^^^^^^^^^^
@ -274,7 +263,7 @@ LL | priv_parent_substs::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_parent_substs::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:116:9
--> $DIR/associated-item-privacy-trait.rs:115:9
|
LL | <Priv as PubTr<_>>::CONST;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@ -285,29 +274,7 @@ LL | priv_parent_substs::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_parent_substs::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:119:13
|
LL | let _: <Pub as PubTr>::AssocTy;
| ^
...
LL | priv_parent_substs::mac!();
| --------------------------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_parent_substs::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:119:16
|
LL | let _: <Pub as PubTr>::AssocTy;
| ^^^^^^^^^^^^^^^^^^^^^^^
...
LL | priv_parent_substs::mac!();
| --------------------------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_parent_substs::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:122:13
--> $DIR/associated-item-privacy-trait.rs:119:30
|
LL | let _: <Pub as PubTr<_>>::AssocTy;
| ^
@ -318,21 +285,10 @@ LL | priv_parent_substs::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_parent_substs::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:122:16
|
LL | let _: <Pub as PubTr<_>>::AssocTy;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
...
LL | priv_parent_substs::mac!();
| --------------------------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_parent_substs::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:125:13
--> $DIR/associated-item-privacy-trait.rs:121:17
|
LL | let _: <Priv as PubTr<_>>::AssocTy;
| ^
| ^^^^
...
LL | priv_parent_substs::mac!();
| --------------------------- in this macro invocation
@ -340,18 +296,7 @@ LL | priv_parent_substs::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_parent_substs::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:125:16
|
LL | let _: <Priv as PubTr<_>>::AssocTy;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
LL | priv_parent_substs::mac!();
| --------------------------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_parent_substs::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:129:35
--> $DIR/associated-item-privacy-trait.rs:124:35
|
LL | pub type InSignatureTy1 = <Pub as PubTr>::AssocTy;
| ^^^^^^^^^^^^^^^^^^^^^^^
@ -362,7 +307,7 @@ LL | priv_parent_substs::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_parent_substs::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:131:35
--> $DIR/associated-item-privacy-trait.rs:126:35
|
LL | pub type InSignatureTy2 = <Priv as PubTr<Pub>>::AssocTy;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -373,7 +318,7 @@ LL | priv_parent_substs::mac!();
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `priv_parent_substs::Priv` is private
--> $DIR/associated-item-privacy-trait.rs:133:14
--> $DIR/associated-item-privacy-trait.rs:128:14
|
LL | impl PubTr for u8 {}
| ^^^^^
@ -383,5 +328,5 @@ LL | priv_parent_substs::mac!();
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 35 previous errors
error: aborting due to 30 previous errors

View file

@ -10,6 +10,11 @@ mod m {
impl PrivTr for Priv {}
pub trait PubTrAux1<T> {}
pub trait PubTrAux2 { type A; }
impl<T> PubTrAux1<T> for u8 {}
impl PubTrAux2 for u8 {
type A = Priv;
//~^ ERROR private type `m::Priv` in public interface
}
// "Private-in-public in associated types is hard error" in RFC 2145
// applies only to the aliased types, not bounds.

View file

@ -1,5 +1,14 @@
error[E0446]: private type `m::Priv` in public interface
--> $DIR/private-in-public-assoc-ty.rs:15:9
|
LL | struct Priv;
| - `m::Priv` declared as private
...
LL | type A = Priv;
| ^^^^^^^^^^^^^^ can't leak private type
warning: private trait `m::PrivTr` in public interface (error E0445)
--> $DIR/private-in-public-assoc-ty.rs:16:5
--> $DIR/private-in-public-assoc-ty.rs:21:5
|
LL | / pub trait PubTr {
LL | |
@ -15,7 +24,7 @@ LL | | }
= note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
warning: private type `m::Priv` in public interface (error E0446)
--> $DIR/private-in-public-assoc-ty.rs:16:5
--> $DIR/private-in-public-assoc-ty.rs:21:5
|
LL | / pub trait PubTr {
LL | |
@ -30,7 +39,7 @@ LL | | }
= note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
warning: private type `m::Priv` in public interface (error E0446)
--> $DIR/private-in-public-assoc-ty.rs:16:5
--> $DIR/private-in-public-assoc-ty.rs:21:5
|
LL | / pub trait PubTr {
LL | |
@ -45,7 +54,7 @@ LL | | }
= note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
error[E0446]: private type `m::Priv` in public interface
--> $DIR/private-in-public-assoc-ty.rs:27:9
--> $DIR/private-in-public-assoc-ty.rs:32:9
|
LL | struct Priv;
| - `m::Priv` declared as private
@ -54,7 +63,7 @@ LL | type Alias4 = Priv;
| ^^^^^^^^^^^^^^^^^^^ can't leak private type
error[E0446]: private type `m::Priv` in public interface
--> $DIR/private-in-public-assoc-ty.rs:34:9
--> $DIR/private-in-public-assoc-ty.rs:39:9
|
LL | struct Priv;
| - `m::Priv` declared as private
@ -63,7 +72,7 @@ LL | type Alias1 = Priv;
| ^^^^^^^^^^^^^^^^^^^ can't leak private type
error[E0445]: private trait `m::PrivTr` in public interface
--> $DIR/private-in-public-assoc-ty.rs:37:9
--> $DIR/private-in-public-assoc-ty.rs:42:9
|
LL | trait PrivTr {}
| - `m::PrivTr` declared as private
@ -72,7 +81,7 @@ LL | type Exist = impl PrivTr;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
error[E0445]: private trait `m::PrivTr` in public interface
--> $DIR/private-in-public-assoc-ty.rs:37:9
--> $DIR/private-in-public-assoc-ty.rs:42:9
|
LL | trait PrivTr {}
| - `m::PrivTr` declared as private
@ -80,7 +89,7 @@ LL | trait PrivTr {}
LL | type Exist = impl PrivTr;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
error: aborting due to 4 previous errors
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0445, E0446.
For more information about an error, try `rustc --explain E0445`.

View file

@ -35,7 +35,7 @@ fn main() {
<u8 as A>::N::NN; //~ ERROR cannot find associated type `N` in `A`
let _: <u8 as Tr>::Y::NN; //~ ERROR ambiguous associated type
let _: <u8 as E>::Y::NN; //~ ERROR expected associated type, found variant `E::Y`
<u8 as Tr>::Y::NN; //~ ERROR no associated item named `NN` found
<u8 as Tr>::Y::NN; //~ ERROR no associated item named `NN` found for type `u16`
<u8 as E>::Y::NN; //~ ERROR expected associated type, found variant `E::Y`
let _: <u8 as Tr::N>::NN; //~ ERROR cannot find associated type `NN` in `Tr::N`
@ -52,5 +52,5 @@ fn main() {
let _: <u8 as Dr>::Z; //~ ERROR expected associated type, found method `Dr::Z`
<u8 as Dr>::X; //~ ERROR expected method or associated constant, found associated type `Dr::X`
let _: <u8 as Dr>::Z::N; //~ ERROR expected associated type, found method `Dr::Z`
<u8 as Dr>::X::N; //~ ERROR no associated item named `N` found
<u8 as Dr>::X::N; //~ ERROR no associated item named `N` found for type `u16`
}

View file

@ -205,19 +205,19 @@ error[E0223]: ambiguous associated type
--> $DIR/ufcs-partially-resolved.rs:36:12
|
LL | let _: <u8 as Tr>::Y::NN;
| ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<<u8 as Tr>::Y as Trait>::NN`
| ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<u16 as Trait>::NN`
error[E0599]: no associated item named `NN` found for associated type `<u8 as Tr>::Y` in the current scope
error[E0599]: no associated item named `NN` found for type `u16` in the current scope
--> $DIR/ufcs-partially-resolved.rs:38:20
|
LL | <u8 as Tr>::Y::NN;
| ^^ associated item not found in `<u8 as Tr>::Y`
| ^^ associated item not found in `u16`
error[E0599]: no associated item named `N` found for associated type `<u8 as Dr>::X` in the current scope
error[E0599]: no associated item named `N` found for type `u16` in the current scope
--> $DIR/ufcs-partially-resolved.rs:55:20
|
LL | <u8 as Dr>::X::N;
| ^ associated item not found in `<u8 as Dr>::X`
| ^ associated item not found in `u16`
error: aborting due to 32 previous errors