From a323ff2c864801fdc8e044e88f11efb49a565ed1 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 13 Jun 2019 21:36:15 +0200 Subject: [PATCH 01/31] =?UTF-8?q?Implement=20RFC=202532=20=E2=80=93=20Asso?= =?UTF-8?q?ciated=20Type=20Defaults?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/librustc_infer/traits/project.rs | 43 ++++--- src/librustc_typeck/check/mod.rs | 21 ---- .../associated-types-overridden-default.rs | 6 +- ...associated-types-overridden-default.stderr | 9 -- .../associated-types/defaults-cyclic-fail.rs | 35 ++++++ .../defaults-cyclic-fail.stderr | 21 ++++ .../associated-types/defaults-cyclic-pass.rs | 22 ++++ .../defaults-in-other-trait-items.rs | 50 ++++++++ .../defaults-in-other-trait-items.stderr | 25 ++++ .../privacy/associated-item-privacy-trait.rs | 9 +- .../associated-item-privacy-trait.stderr | 113 +++++------------- .../ui/privacy/private-in-public-assoc-ty.rs | 5 + .../privacy/private-in-public-assoc-ty.stderr | 25 ++-- src/test/ui/ufcs/ufcs-partially-resolved.rs | 4 +- .../ui/ufcs/ufcs-partially-resolved.stderr | 10 +- 15 files changed, 247 insertions(+), 151 deletions(-) delete mode 100644 src/test/ui/associated-types/associated-types-overridden-default.stderr create mode 100644 src/test/ui/associated-types/defaults-cyclic-fail.rs create mode 100644 src/test/ui/associated-types/defaults-cyclic-fail.stderr create mode 100644 src/test/ui/associated-types/defaults-cyclic-pass.rs create mode 100644 src/test/ui/associated-types/defaults-in-other-trait-items.rs create mode 100644 src/test/ui/associated-types/defaults-in-other-trait-items.stderr diff --git a/src/librustc_infer/traits/project.rs b/src/librustc_infer/traits/project.rs index a7c3e9110abd2..8d9e5d3fa20fb 100644 --- a/src/librustc_infer/traits/project.rs +++ b/src/librustc_infer/traits/project.rs @@ -1054,25 +1054,40 @@ 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()) }; - // Only reveal a specializable default if we're past type-checking - // and the obligations 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 { - // 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); - !poly_trait_ref.needs_infer() && !poly_trait_ref.needs_subst() - } else { - false + match is_default { + // Non-specializable items are always projectable + false => true, + + // Only reveal a specializable default if we're past type-checking + // 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. + 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); + !poly_trait_ref.needs_infer() && !poly_trait_ref.needs_subst() + } + + 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(..) => { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 4f6eb20e6ebbd..4ab5d8f9ad3f6 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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::>().join("`, `") - ) - .emit(); - } } fn missing_items_err( diff --git a/src/test/ui/associated-types/associated-types-overridden-default.rs b/src/test/ui/associated-types/associated-types-overridden-default.rs index 629fc7a7668ad..72c30df0b3dff 100644 --- a/src/test/ui/associated-types/associated-types-overridden-default.rs +++ b/src/test/ui/associated-types/associated-types-overridden-default.rs @@ -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,6 @@ pub trait Tr { impl Tr for () { type Assoc = (); - //~^ ERROR need to be reimplemented as `Assoc` was overridden: `Assoc2`, `C`, `foo` } fn main() {} diff --git a/src/test/ui/associated-types/associated-types-overridden-default.stderr b/src/test/ui/associated-types/associated-types-overridden-default.stderr deleted file mode 100644 index 79fb9a613c2da..0000000000000 --- a/src/test/ui/associated-types/associated-types-overridden-default.stderr +++ /dev/null @@ -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`. diff --git a/src/test/ui/associated-types/defaults-cyclic-fail.rs b/src/test/ui/associated-types/defaults-cyclic-fail.rs new file mode 100644 index 0000000000000..ab66fe0b52ee7 --- /dev/null +++ b/src/test/ui/associated-types/defaults-cyclic-fail.rs @@ -0,0 +1,35 @@ +#![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 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; + //~^ ERROR overflow evaluating the requirement +} +// (the error is shown twice for some reason) + +fn main() { + // Check that the overridden type propagates to the other + let _a: ::A = 0u8; + let _b: ::B = 0u8; +} diff --git a/src/test/ui/associated-types/defaults-cyclic-fail.stderr b/src/test/ui/associated-types/defaults-cyclic-fail.stderr new file mode 100644 index 0000000000000..dd0e5c2ef4214 --- /dev/null +++ b/src/test/ui/associated-types/defaults-cyclic-fail.stderr @@ -0,0 +1,21 @@ +error[E0275]: overflow evaluating the requirement `<() as Tr>::B` + --> $DIR/defaults-cyclic-fail.rs:10:6 + | +LL | impl Tr for () {} + | ^^ + +error[E0275]: overflow evaluating the requirement `::B` + --> $DIR/defaults-cyclic-fail.rs:24:6 + | +LL | impl Tr for bool { + | ^^ + +error[E0275]: overflow evaluating the requirement `::B` + --> $DIR/defaults-cyclic-fail.rs:26:5 + | +LL | type A = Box; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/associated-types/defaults-cyclic-pass.rs b/src/test/ui/associated-types/defaults-cyclic-pass.rs new file mode 100644 index 0000000000000..618a203850785 --- /dev/null +++ b/src/test/ui/associated-types/defaults-cyclic-pass.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(associated_type_defaults)] + +trait Tr { + type Item = u8; + type Container = Vec; +} + +impl Tr for () {} + +impl Tr for u16 { + type Item = u16; +} + +fn main() { + let _container: <() as Tr>::Container = Vec::::new(); + let _item: <() as Tr>::Item = 0u8; + + let _container: ::Container = Vec::::new(); + let _item: ::Item = 0u16; +} diff --git a/src/test/ui/associated-types/defaults-in-other-trait-items.rs b/src/test/ui/associated-types/defaults-in-other-trait-items.rs new file mode 100644 index 0000000000000..0455997b16808 --- /dev/null +++ b/src/test/ui/associated-types/defaults-in-other-trait-items.rs @@ -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 `::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 `::A` + //~| NOTE consider constraining + //~| 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 `::Ty` + //~| NOTE consider constraining + //~| NOTE for more information, visit +} + +// An impl can, however +impl AssocConst for () { + const C: Self::Ty = 0u8; +} + +fn main() {} diff --git a/src/test/ui/associated-types/defaults-in-other-trait-items.stderr b/src/test/ui/associated-types/defaults-in-other-trait-items.stderr new file mode 100644 index 0000000000000..9ecfe49c2b571 --- /dev/null +++ b/src/test/ui/associated-types/defaults-in-other-trait-items.stderr @@ -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 `::A` + found unit type `()` + = note: consider constraining the associated type `::A` to `()` or calling a method that returns `::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 `::Ty` + found type `u8` + = note: consider constraining the associated type `::Ty` to `u8` or calling a method that returns `::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`. diff --git a/src/test/ui/privacy/associated-item-privacy-trait.rs b/src/test/ui/privacy/associated-item-privacy-trait.rs index b3d42f0959627..03347d5b99a31 100644 --- a/src/test/ui/privacy/associated-item-privacy-trait.rs +++ b/src/test/ui/privacy/associated-item-privacy-trait.rs @@ -23,8 +23,7 @@ mod priv_trait { ::CONST; //~^ ERROR associated constant `PrivTr::CONST` is private let _: ::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 = ::AssocTy; //~^ ERROR trait `priv_trait::PrivTr` is private pub trait InSignatureTr: PrivTr {} @@ -116,15 +115,11 @@ mod priv_parent_substs { >::CONST; //~^ ERROR type `priv_parent_substs::Priv` is private - let _: ::AssocTy; - //~^ ERROR type `priv_parent_substs::Priv` is private - //~| ERROR type `priv_parent_substs::Priv` is private + let _: ::AssocTy; // FIXME no longer an error?! let _: >::AssocTy; //~^ ERROR type `priv_parent_substs::Priv` is private - //~| ERROR type `priv_parent_substs::Priv` is private let _: >::AssocTy; //~^ ERROR type `priv_parent_substs::Priv` is private - //~| ERROR type `priv_parent_substs::Priv` is private pub type InSignatureTy1 = ::AssocTy; //~^ ERROR type `priv_parent_substs::Priv` is private diff --git a/src/test/ui/privacy/associated-item-privacy-trait.stderr b/src/test/ui/privacy/associated-item-privacy-trait.stderr index ac422e99855be..db24e425a01f6 100644 --- a/src/test/ui/privacy/associated-item-privacy-trait.stderr +++ b/src/test/ui/privacy/associated-item-privacy-trait.stderr @@ -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 _: ::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 _: ::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 = ::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 = ::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 = ::method::; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -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::(); | ^^^^^^^^^^^^^^^^^^^^ @@ -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 = ::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 = >::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 = >::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 | ::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 | >::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 | >::CONST; | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -285,54 +274,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:119:13 - | -LL | let _: ::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 _: ::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 - | -LL | let _: >::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:16 + --> $DIR/associated-item-privacy-trait.rs:119:30 | LL | let _: >::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 - | -LL | let _: >::AssocTy; - | ^ + | ^ ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -340,10 +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:125:16 + --> $DIR/associated-item-privacy-trait.rs:121:17 | LL | let _: >::AssocTy; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -351,7 +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:129:35 + --> $DIR/associated-item-privacy-trait.rs:124:35 | LL | pub type InSignatureTy1 = ::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 = >::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 diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.rs b/src/test/ui/privacy/private-in-public-assoc-ty.rs index ad1052ada6084..62faae1f399e8 100644 --- a/src/test/ui/privacy/private-in-public-assoc-ty.rs +++ b/src/test/ui/privacy/private-in-public-assoc-ty.rs @@ -10,6 +10,11 @@ mod m { impl PrivTr for Priv {} pub trait PubTrAux1 {} pub trait PubTrAux2 { type A; } + impl PubTrAux1 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. diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.stderr b/src/test/ui/privacy/private-in-public-assoc-ty.stderr index 3cc551cdeded6..c57073a004d8f 100644 --- a/src/test/ui/privacy/private-in-public-assoc-ty.stderr +++ b/src/test/ui/privacy/private-in-public-assoc-ty.stderr @@ -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 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 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 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`. diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.rs b/src/test/ui/ufcs/ufcs-partially-resolved.rs index 66d4db3ebaf0a..e8c767b13e9cf 100644 --- a/src/test/ui/ufcs/ufcs-partially-resolved.rs +++ b/src/test/ui/ufcs/ufcs-partially-resolved.rs @@ -35,7 +35,7 @@ fn main() { ::N::NN; //~ ERROR cannot find associated type `N` in `A` let _: ::Y::NN; //~ ERROR ambiguous associated type let _: ::Y::NN; //~ ERROR expected associated type, found variant `E::Y` - ::Y::NN; //~ ERROR no associated item named `NN` found + ::Y::NN; //~ ERROR no associated item named `NN` found for type `u16` ::Y::NN; //~ ERROR expected associated type, found variant `E::Y` let _: ::NN; //~ ERROR cannot find associated type `NN` in `Tr::N` @@ -52,5 +52,5 @@ fn main() { let _: ::Z; //~ ERROR expected associated type, found method `Dr::Z` ::X; //~ ERROR expected method or associated constant, found associated type `Dr::X` let _: ::Z::N; //~ ERROR expected associated type, found method `Dr::Z` - ::X::N; //~ ERROR no associated item named `N` found + ::X::N; //~ ERROR no associated item named `N` found for type `u16` } diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.stderr b/src/test/ui/ufcs/ufcs-partially-resolved.stderr index 60ebe8ee053a6..e5e6ed9fac911 100644 --- a/src/test/ui/ufcs/ufcs-partially-resolved.stderr +++ b/src/test/ui/ufcs/ufcs-partially-resolved.stderr @@ -205,19 +205,19 @@ error[E0223]: ambiguous associated type --> $DIR/ufcs-partially-resolved.rs:36:12 | LL | let _: ::Y::NN; - | ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<::Y as Trait>::NN` + | ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `::NN` -error[E0599]: no associated item named `NN` found for associated type `::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 | ::Y::NN; - | ^^ associated item not found in `::Y` + | ^^ associated item not found in `u16` -error[E0599]: no associated item named `N` found for associated type `::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 | ::X::N; - | ^ associated item not found in `::X` + | ^ associated item not found in `u16` error: aborting due to 32 previous errors From a549bbdc3230b44d18d8828610053c521fe95d9e Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 13 Jun 2019 22:03:42 +0200 Subject: [PATCH 02/31] Add regression test for #54182 --- src/test/ui/associated-types/issue-54182-1.rs | 79 +++++++++++++++++++ src/test/ui/associated-types/issue-54182-2.rs | 15 ++++ 2 files changed, 94 insertions(+) create mode 100644 src/test/ui/associated-types/issue-54182-1.rs create mode 100644 src/test/ui/associated-types/issue-54182-2.rs diff --git a/src/test/ui/associated-types/issue-54182-1.rs b/src/test/ui/associated-types/issue-54182-1.rs new file mode 100644 index 0000000000000..bfbf7ed1f223d --- /dev/null +++ b/src/test/ui/associated-types/issue-54182-1.rs @@ -0,0 +1,79 @@ +// run-pass + +#![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 r = overload!(42, true); + println!("-> {:?}", r); + + let r = overload!("Hello world", 13.0); + println!("-> {:?}", r); + + let r = overload!(42, true, 42.5); + println!("-> {:?}", r); + + let r = overload!("Hello world", 13.0, 42); + println!("-> {:?}", r); +} + +mod overload { + pub trait Overload { + // type R; + type R = (); + fn overload(self) -> Self::R; + } + + // overloads for 2 args + impl Overload for (i32, bool) { + // type R = (); + 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(a: A, b: B) -> R where (A, B): Overload { + (a, b).overload() + } + + pub fn overload3(a: A, b: B, c: C) -> R where (A, B, C): Overload { + (a, b, c).overload() + } +} diff --git a/src/test/ui/associated-types/issue-54182-2.rs b/src/test/ui/associated-types/issue-54182-2.rs new file mode 100644 index 0000000000000..cba1b1b3ca6a1 --- /dev/null +++ b/src/test/ui/associated-types/issue-54182-2.rs @@ -0,0 +1,15 @@ +// compile-pass + +#![feature(associated_type_defaults)] + +trait Tr { + type Assoc = (); +} + +impl Tr for () {} + +fn f(thing: <() as Tr>::Assoc) { + let c: () = thing; +} + +fn main() {} From 37686edb852f857b0356c6ec41b1c46ed83e9582 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 13 Jun 2019 23:21:19 +0200 Subject: [PATCH 03/31] Add comments and assertions to tests --- src/test/ui/associated-types/issue-54182-1.rs | 29 ++++++++++++++----- src/test/ui/associated-types/issue-54182-2.rs | 4 +++ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/test/ui/associated-types/issue-54182-1.rs b/src/test/ui/associated-types/issue-54182-1.rs index bfbf7ed1f223d..3e10f3fb7dff3 100644 --- a/src/test/ui/associated-types/issue-54182-1.rs +++ b/src/test/ui/associated-types/issue-54182-1.rs @@ -1,5 +1,14 @@ // 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 { @@ -12,20 +21,20 @@ macro_rules! overload { } fn main() { - let r = overload!(42, true); - println!("-> {:?}", r); + let r: () = overload!(42, true); - let r = overload!("Hello world", 13.0); - println!("-> {:?}", r); + let r: f32 = overload!("Hello world", 13.0); + assert_eq!(r, 13.0); - let r = overload!(42, true, 42.5); - println!("-> {:?}", r); + let r: () = overload!(42, true, 42.5); - let r = overload!("Hello world", 13.0, 42); - println!("-> {:?}", r); + 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 = (); @@ -35,6 +44,10 @@ mod overload { // 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)); diff --git a/src/test/ui/associated-types/issue-54182-2.rs b/src/test/ui/associated-types/issue-54182-2.rs index cba1b1b3ca6a1..f55f480978030 100644 --- a/src/test/ui/associated-types/issue-54182-2.rs +++ b/src/test/ui/associated-types/issue-54182-2.rs @@ -1,5 +1,9 @@ // compile-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 { From de447eb9f20cbc2a330d6093a4ac8b5eb730b193 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 14 Jun 2019 00:03:32 +0200 Subject: [PATCH 04/31] Add tests for assoc. const defaults --- .../associated-const/defaults-cyclic-fail.rs | 17 +++++++ .../defaults-cyclic-fail.stderr | 21 +++++++++ .../associated-const/defaults-cyclic-pass.rs | 35 +++++++++++++++ .../defaults-not-assumed-fail.rs | 44 +++++++++++++++++++ .../defaults-not-assumed-fail.stderr | 23 ++++++++++ .../defaults-not-assumed-pass.rs | 42 ++++++++++++++++++ 6 files changed, 182 insertions(+) create mode 100644 src/test/ui/associated-const/defaults-cyclic-fail.rs create mode 100644 src/test/ui/associated-const/defaults-cyclic-fail.stderr create mode 100644 src/test/ui/associated-const/defaults-cyclic-pass.rs create mode 100644 src/test/ui/associated-const/defaults-not-assumed-fail.rs create mode 100644 src/test/ui/associated-const/defaults-not-assumed-fail.stderr create mode 100644 src/test/ui/associated-const/defaults-not-assumed-pass.rs diff --git a/src/test/ui/associated-const/defaults-cyclic-fail.rs b/src/test/ui/associated-const/defaults-cyclic-fail.rs new file mode 100644 index 0000000000000..0f54d67574d36 --- /dev/null +++ b/src/test/ui/associated-const/defaults-cyclic-fail.rs @@ -0,0 +1,17 @@ +// compile-fail + +// Cyclic assoc. const defaults don't error unless *used* +trait Tr { + const A: u8 = Self::B; + //~^ ERROR cycle detected when const-evaluating `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); +} diff --git a/src/test/ui/associated-const/defaults-cyclic-fail.stderr b/src/test/ui/associated-const/defaults-cyclic-fail.stderr new file mode 100644 index 0000000000000..4e59519909137 --- /dev/null +++ b/src/test/ui/associated-const/defaults-cyclic-fail.stderr @@ -0,0 +1,21 @@ +error[E0391]: cycle detected when const-evaluating `Tr::A` + --> $DIR/defaults-cyclic-fail.rs:5:19 + | +LL | const A: u8 = Self::B; + | ^^^^^^^ + | +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 `Tr::A`, completing the cycle +note: cycle used when processing `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`. diff --git a/src/test/ui/associated-const/defaults-cyclic-pass.rs b/src/test/ui/associated-const/defaults-cyclic-pass.rs new file mode 100644 index 0000000000000..1de733cfc37ab --- /dev/null +++ b/src/test/ui/associated-const/defaults-cyclic-pass.rs @@ -0,0 +1,35 @@ +// 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 +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!(::A, 42); + assert_eq!(::B, 42); + + assert_eq!(::A, 0); + assert_eq!(::B, 0); + + assert_eq!(::A, 100); + assert_eq!(::B, 123); +} diff --git a/src/test/ui/associated-const/defaults-not-assumed-fail.rs b/src/test/ui/associated-const/defaults-not-assumed-fail.rs new file mode 100644 index 0000000000000..27435ef34a0e9 --- /dev/null +++ b/src/test/ui/associated-const/defaults-not-assumed-fail.rs @@ -0,0 +1,44 @@ +// compile-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 + + assert_eq!(::A, 254); + assert_eq!(::B, 255); + + assert_eq!(::A, 255); + assert_eq!(::B, 0); + + assert_eq!(::A, 254); + assert_eq!(::B, 0); +} diff --git a/src/test/ui/associated-const/defaults-not-assumed-fail.stderr b/src/test/ui/associated-const/defaults-not-assumed-fail.stderr new file mode 100644 index 0000000000000..aac1765c4b2d8 --- /dev/null +++ b/src/test/ui/associated-const/defaults-not-assumed-fail.stderr @@ -0,0 +1,23 @@ +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 outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/associated-const/defaults-not-assumed-pass.rs b/src/test/ui/associated-const/defaults-not-assumed-pass.rs new file mode 100644 index 0000000000000..c08e05c8a3073 --- /dev/null +++ b/src/test/ui/associated-const/defaults-not-assumed-pass.rs @@ -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!(::A, 254); + assert_eq!(::B, 255); + + assert_eq!(::A, 255); + assert_eq!(::B, 0); + + assert_eq!(::A, 254); + assert_eq!(::B, 0); +} From 1e3c02006372ca68d07d32493660583cc1c9e12c Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 14 Jun 2019 21:26:42 +0200 Subject: [PATCH 05/31] Test interactions with specialization --- .../defaults-specialization.rs | 46 +++++++++++++++++++ .../defaults-specialization.stderr | 27 +++++++++++ 2 files changed, 73 insertions(+) create mode 100644 src/test/ui/associated-types/defaults-specialization.rs create mode 100644 src/test/ui/associated-types/defaults-specialization.stderr diff --git a/src/test/ui/associated-types/defaults-specialization.rs b/src/test/ui/associated-types/defaults-specialization.rs new file mode 100644 index 0000000000000..c8aab8fb3ec4a --- /dev/null +++ b/src/test/ui/associated-types/defaults-specialization.rs @@ -0,0 +1,46 @@ +// compile-fail + +#![feature(associated_type_defaults, specialization)] + +trait Tr { + type Ty = u8; + + fn make() -> Self::Ty; +} + +struct A(T); +// In a `default impl`, assoc. types are defaulted as well, +// so their values can't be assumed. +default impl Tr for A { + fn make() -> u8 { 0 } + //~^ ERROR method `make` has an incompatible type for trait +} + +struct B(T); +// Explicitly defaulting the type does the same. +impl Tr for B { + default type Ty = bool; + + fn make() -> bool { true } + //~^ ERROR method `make` has an incompatible type for trait +} + +struct C(T); +// Only the method is defaulted, so this is fine. +impl Tr for C { + type Ty = bool; + + default fn make() -> bool { true } +} + +// Defaulted method *can* assume the type, if the default is kept. +struct D(T); +impl Tr for D { + default fn make() -> u8 { 0 } +} + +impl Tr for D { + fn make() -> u8 { 255 } +} + +fn main() {} diff --git a/src/test/ui/associated-types/defaults-specialization.stderr b/src/test/ui/associated-types/defaults-specialization.stderr new file mode 100644 index 0000000000000..0e6711780f8dd --- /dev/null +++ b/src/test/ui/associated-types/defaults-specialization.stderr @@ -0,0 +1,27 @@ +error[E0053]: method `make` has an incompatible type for trait + --> $DIR/defaults-specialization.rs:15:18 + | +LL | fn make() -> Self::Ty; + | -------- type in trait +... +LL | fn make() -> u8 { 0 } + | ^^ expected associated type, found u8 + | + = note: expected type `fn() -> as Tr>::Ty` + found type `fn() -> u8` + +error[E0053]: method `make` has an incompatible type for trait + --> $DIR/defaults-specialization.rs:24:18 + | +LL | fn make() -> Self::Ty; + | -------- type in trait +... +LL | fn make() -> bool { true } + | ^^^^ expected associated type, found bool + | + = note: expected type `fn() -> as Tr>::Ty` + found type `fn() -> bool` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0053`. From d3be26d6a8eaf3b5a7c22ba2324ef0751835ce26 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 14 Jun 2019 21:59:11 +0200 Subject: [PATCH 06/31] Improve test --- .../defaults-specialization.rs | 18 +++++++++++ .../defaults-specialization.stderr | 31 ++++++++++++++++--- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/test/ui/associated-types/defaults-specialization.rs b/src/test/ui/associated-types/defaults-specialization.rs index c8aab8fb3ec4a..e3a5db0960cf0 100644 --- a/src/test/ui/associated-types/defaults-specialization.rs +++ b/src/test/ui/associated-types/defaults-specialization.rs @@ -1,3 +1,5 @@ +//! Tests the interaction of associated type defaults and specialization. + // compile-fail #![feature(associated_type_defaults, specialization)] @@ -16,6 +18,13 @@ default impl Tr for A { //~^ ERROR method `make` has an incompatible type for trait } +struct A2(T); +// ...same, but in the method body +default impl Tr for A2 { + fn make() -> Self::Ty { 0u8 } + //~^ ERROR mismatched types +} + struct B(T); // Explicitly defaulting the type does the same. impl Tr for B { @@ -25,6 +34,15 @@ impl Tr for B { //~^ ERROR method `make` has an incompatible type for trait } +struct B2(T); +// ...same, but in the method body +impl Tr for B2 { + default type Ty = bool; + + fn make() -> Self::Ty { true } + //~^ ERROR mismatched types +} + struct C(T); // Only the method is defaulted, so this is fine. impl Tr for C { diff --git a/src/test/ui/associated-types/defaults-specialization.stderr b/src/test/ui/associated-types/defaults-specialization.stderr index 0e6711780f8dd..2b2adfdb7c965 100644 --- a/src/test/ui/associated-types/defaults-specialization.stderr +++ b/src/test/ui/associated-types/defaults-specialization.stderr @@ -1,5 +1,5 @@ error[E0053]: method `make` has an incompatible type for trait - --> $DIR/defaults-specialization.rs:15:18 + --> $DIR/defaults-specialization.rs:17:18 | LL | fn make() -> Self::Ty; | -------- type in trait @@ -11,7 +11,7 @@ LL | fn make() -> u8 { 0 } found type `fn() -> u8` error[E0053]: method `make` has an incompatible type for trait - --> $DIR/defaults-specialization.rs:24:18 + --> $DIR/defaults-specialization.rs:33:18 | LL | fn make() -> Self::Ty; | -------- type in trait @@ -22,6 +22,29 @@ LL | fn make() -> bool { true } = note: expected type `fn() -> as Tr>::Ty` found type `fn() -> bool` -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/defaults-specialization.rs:24:29 + | +LL | fn make() -> Self::Ty { 0u8 } + | -------- ^^^ expected associated type, found u8 + | | + | expected ` as Tr>::Ty` because of return type + | + = note: expected type ` as Tr>::Ty` + found type `u8` + +error[E0308]: mismatched types + --> $DIR/defaults-specialization.rs:42:29 + | +LL | fn make() -> Self::Ty { true } + | -------- ^^^^ expected associated type, found bool + | | + | expected ` as Tr>::Ty` because of return type + | + = note: expected type ` as Tr>::Ty` + found type `bool` + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0053`. +Some errors have detailed explanations: E0053, E0308. +For more information about an error, try `rustc --explain E0053`. From c73ee9861b44a16245e35615307425f6c928fd5e Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 15 Jun 2019 19:02:27 +0200 Subject: [PATCH 07/31] Check suitability of the provided default --- src/librustc_typeck/check/wfcheck.rs | 72 +++++++ .../associated-types/defaults-suitability.rs | 93 +++++++++ .../defaults-suitability.stderr | 177 ++++++++++++++++++ 3 files changed, 342 insertions(+) create mode 100644 src/test/ui/associated-types/defaults-suitability.rs create mode 100644 src/test/ui/associated-types/defaults-suitability.stderr diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 4ffc3bf8e78fd..959feb766ee00 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -425,6 +425,78 @@ 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); + + // Type-check associated type defaults (if there are any): + // Assuming the defaults are used, check that all predicates (bounds on + // the assoc type and where clauses on the trait) hold. + + let substs = InternalSubsts::identity_for_item(tcx, trait_def_id); + + // For all assoc. types with defaults, build a map from + // `>::Assoc` to the default type. + let map = tcx.associated_items(trait_def_id) + .filter_map(|item| { + if item.kind == ty::AssocKind::Type && item.defaultness.has_value() { + // `>::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::>(); + + struct DefaultNormalizer<'tcx> { + tcx: TyCtxt<'tcx>, + map: FxHashMap, 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.sty { + 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); + } + } + vec![] }); } diff --git a/src/test/ui/associated-types/defaults-suitability.rs b/src/test/ui/associated-types/defaults-suitability.rs new file mode 100644 index 0000000000000..6a8ea3b6d42f4 --- /dev/null +++ b/src/test/ui/associated-types/defaults-suitability.rs @@ -0,0 +1,93 @@ +//! 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 + +// compile-fail + +#![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 { + type Bar: Clone = Vec; + //~^ ERROR the trait bound `T: std::clone::Clone` is not satisfied +} + +trait Bar: Sized { + // `(): Foo` might hold for some possible impls but not all. + type Assoc: Foo = (); + //~^ ERROR the trait bound `(): Foo` is not satisfied +} + +trait IsU8 {} +impl IsU8 for T {} + +// Test that mentioning the assoc. type inside where clauses works +trait C where + Vec: Clone, + Self::Assoc: IsU8, + bool: IsU8, +{ + type Assoc = u8; +} + +// Test that we get all expected errors if that default is unsuitable +trait D where + Vec: Clone, + //~^ ERROR the trait bound `NotClone: std::clone::Clone` is not satisfied + Self::Assoc: IsU8, + //~^ ERROR the trait bound `NotClone: IsU8` is not satisfied + bool: IsU8, + //~^ ERROR the trait bound `bool: IsU8` is not satisfied +{ + type Assoc = NotClone; +} + +trait Foo2 where + >::Bar: Clone, + //~^ ERROR the trait bound `>::Baz: std::clone::Clone` is not satisfied +{ + type Bar = Vec; + type Baz = T; +} + +trait Foo3 where + >::Bar: Clone, + //~^ ERROR the trait bound `>::Baz: std::clone::Clone` is not satisfied +{ + type Bar = Vec; + type Baz = T; +} + +trait Foo4 where + >::Bar: Clone, +{ + type Bar = Vec; + type Baz: Clone = T; + //~^ ERROR the trait bound `T: std::clone::Clone` is not satisfied +} + +fn main() {} diff --git a/src/test/ui/associated-types/defaults-suitability.stderr b/src/test/ui/associated-types/defaults-suitability.stderr new file mode 100644 index 0000000000000..67b31b414fa95 --- /dev/null +++ b/src/test/ui/associated-types/defaults-suitability.stderr @@ -0,0 +1,177 @@ +error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:17:14 + | +LL | type Ty: Clone = NotClone; + | ^^^^^ the trait `std::clone::Clone` is not implemented for `NotClone` + | +note: required by `Tr` + --> $DIR/defaults-suitability.rs:16:1 + | +LL | trait Tr { + | ^^^^^^^^ + +error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:22:27 + | +LL | trait Tr2 where Self::Ty: Clone { + | ^^^^^ the trait `std::clone::Clone` is not implemented for `NotClone` + | +note: required by `Tr2` + --> $DIR/defaults-suitability.rs:22:1 + | +LL | trait Tr2 where Self::Ty: Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:35:15 + | +LL | type Bar: Clone = Vec; + | ^^^^^ the trait `std::clone::Clone` is not implemented for `T` + | + = help: consider adding a `where T: std::clone::Clone` bound + = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec` +note: required by `Foo` + --> $DIR/defaults-suitability.rs:34:1 + | +LL | trait Foo { + | ^^^^^^^^^^^^ + +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/defaults-suitability.rs:41:17 + | +LL | type Assoc: Foo = (); + | ^^^^^^^^^ the trait `Foo` is not implemented for `()` + | +note: required by `Bar` + --> $DIR/defaults-suitability.rs:39:1 + | +LL | trait Bar: Sized { + | ^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `NotClone: IsU8` is not satisfied + --> $DIR/defaults-suitability.rs:61:18 + | +LL | Self::Assoc: IsU8, + | ^^^^^^^^^^^^^^^^^ the trait `IsU8` is not implemented for `NotClone` + | +note: required by `D` + --> $DIR/defaults-suitability.rs:58:1 + | +LL | / trait D where +LL | | Vec: Clone, +LL | | +LL | | Self::Assoc: IsU8, +... | +LL | | type Assoc = NotClone; +LL | | } + | |_^ + +error[E0277]: the trait bound `bool: IsU8` is not satisfied + --> $DIR/defaults-suitability.rs:63:11 + | +LL | bool: IsU8, + | ^^^^^^^^^^^^^^^^^ the trait `IsU8` is not implemented for `bool` + | +note: required by `D` + --> $DIR/defaults-suitability.rs:58:1 + | +LL | / trait D where +LL | | Vec: Clone, +LL | | +LL | | Self::Assoc: IsU8, +... | +LL | | type Assoc = NotClone; +LL | | } + | |_^ + +error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:59:23 + | +LL | Vec: Clone, + | ^^^^^ the trait `std::clone::Clone` is not implemented for `NotClone` + | + = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec` +note: required by `D` + --> $DIR/defaults-suitability.rs:58:1 + | +LL | / trait D where +LL | | Vec: Clone, +LL | | +LL | | Self::Assoc: IsU8, +... | +LL | | type Assoc = NotClone; +LL | | } + | |_^ + +error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:70:29 + | +LL | >::Bar: Clone, + | ^^^^^ the trait `std::clone::Clone` is not implemented for `>::Baz` + | + = help: consider adding a `where >::Baz: std::clone::Clone` bound + = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` +note: required by `Foo2` + --> $DIR/defaults-suitability.rs:69:1 + | +LL | / trait Foo2 where +LL | | >::Bar: Clone, +LL | | +LL | | { +LL | | type Bar = Vec; +LL | | type Baz = T; +LL | | } + | |_^ + +error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:78:29 + | +LL | >::Bar: Clone, + | ^^^^^ the trait `std::clone::Clone` is not implemented for `>::Baz` + | + = help: consider adding a `where >::Baz: std::clone::Clone` bound + = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` +note: required by `Foo3` + --> $DIR/defaults-suitability.rs:77:1 + | +LL | / trait Foo3 where +LL | | >::Bar: Clone, +LL | | +LL | | { +LL | | type Bar = Vec; +LL | | type Baz = T; +LL | | } + | |_^ + +error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:89:15 + | +LL | type Baz: Clone = T; + | ^^^^^ the trait `std::clone::Clone` is not implemented for `T` + | + = help: consider adding a `where T: std::clone::Clone` bound +note: required by `Foo4` + --> $DIR/defaults-suitability.rs:85:1 + | +LL | / trait Foo4 where +LL | | >::Bar: Clone, +LL | | { +LL | | type Bar = Vec; +LL | | type Baz: Clone = T; +LL | | +LL | | } + | |_^ + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/defaults-suitability.rs:29: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 + = note: required by `std::vec::Vec` + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0277`. From f40388292765477881d95a84eb11ef47f8a69500 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 15 Jun 2019 19:07:56 +0200 Subject: [PATCH 08/31] Add a `Self: Sized` bound --- src/test/ui/lint/lint-missing-doc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/lint/lint-missing-doc.rs b/src/test/ui/lint/lint-missing-doc.rs index a2466d28fb028..77f9a3770a339 100644 --- a/src/test/ui/lint/lint-missing-doc.rs +++ b/src/test/ui/lint/lint-missing-doc.rs @@ -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 From 5e9317a023ef6b5b5146a29d6b96ca3710d8fbfe Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 15 Jun 2019 20:51:13 +0200 Subject: [PATCH 09/31] Put the check into its own function --- src/librustc_typeck/check/wfcheck.rs | 133 ++++++++++++++------------- 1 file changed, 70 insertions(+), 63 deletions(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 959feb766ee00..603d877cf53fd 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -425,80 +425,87 @@ 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); - // Type-check associated type defaults (if there are any): - // Assuming the defaults are used, check that all predicates (bounds on - // the assoc type and where clauses on the trait) hold. - - let substs = InternalSubsts::identity_for_item(tcx, trait_def_id); - - // For all assoc. types with defaults, build a map from - // `>::Assoc` to the default type. - let map = tcx.associated_items(trait_def_id) - .filter_map(|item| { - if item.kind == ty::AssocKind::Type && item.defaultness.has_value() { - // `>::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::>(); - - struct DefaultNormalizer<'tcx> { - tcx: TyCtxt<'tcx>, - map: FxHashMap, Ty<'tcx>>, - } + vec![] + }); +} - impl<'tcx> ty::fold::TypeFolder<'tcx> for DefaultNormalizer<'tcx> { - fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { - self.tcx +/// 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 + // `>::Assoc` to the default type. + let map = tcx.associated_items(trait_def_id) + .filter_map(|item| { + if item.kind == ty::AssocKind::Type && item.defaultness.has_value() { + // `>::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::>(); - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - match t.sty { - ty::Projection(proj_ty) => { - if let Some(default) = self.map.get(&proj_ty) { - default - } else { - t.super_fold_with(self) - } + struct DefaultNormalizer<'tcx> { + tcx: TyCtxt<'tcx>, + map: FxHashMap, 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.sty { + 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), } + _ => 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); + // 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); - } + fcx.register_predicate(obligation); } - - vec![] - }); + } } fn check_item_fn(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { From ff5d11e0434217531f2699543c7ec7f1e550a42f Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 16 Jun 2019 20:53:35 +0200 Subject: [PATCH 10/31] Add comments and tests explaining the shallow substitution rule --- src/librustc_typeck/check/wfcheck.rs | 21 ++++++ .../associated-types/defaults-suitability.rs | 35 +++++++--- .../defaults-suitability.stderr | 66 ++++++++----------- 3 files changed, 73 insertions(+), 49 deletions(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 603d877cf53fd..9f1ae37da1ad3 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -461,6 +461,27 @@ fn check_associated_type_defaults( }) .collect::>(); + /// 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; + /// type B = u8; + /// } + /// ``` + /// + /// This will end up replacing the bound `Self::A: Clone` with + /// `Vec: Clone`, not with `Vec: 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. struct DefaultNormalizer<'tcx> { tcx: TyCtxt<'tcx>, map: FxHashMap, Ty<'tcx>>, diff --git a/src/test/ui/associated-types/defaults-suitability.rs b/src/test/ui/associated-types/defaults-suitability.rs index 6a8ea3b6d42f4..5a128e56bcb14 100644 --- a/src/test/ui/associated-types/defaults-suitability.rs +++ b/src/test/ui/associated-types/defaults-suitability.rs @@ -66,28 +66,43 @@ trait D where type Assoc = NotClone; } -trait Foo2 where - >::Bar: Clone, +// 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 { + type Bar: Clone = Vec; //~^ ERROR the trait bound `>::Baz: std::clone::Clone` is not satisfied -{ - type Bar = Vec; type Baz = T; } -trait Foo3 where - >::Bar: Clone, - //~^ ERROR the trait bound `>::Baz: std::clone::Clone` is not satisfied +// 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 { + type Bar: Clone = Vec; + //~^ ERROR the trait bound `>::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 where + Self::Bar: Clone, + Self::Baz: Clone, + //~^ ERROR the trait bound `T: std::clone::Clone` is not satisfied { type Bar = Vec; type Baz = T; } +// This one finally works, with `Clone` bounds on all assoc. types and the type +// parameter. trait Foo4 where - >::Bar: Clone, + T: Clone, { - type Bar = Vec; + type Bar: Clone = Vec; type Baz: Clone = T; - //~^ ERROR the trait bound `T: std::clone::Clone` is not satisfied } fn main() {} diff --git a/src/test/ui/associated-types/defaults-suitability.stderr b/src/test/ui/associated-types/defaults-suitability.stderr index 67b31b414fa95..9a7febeb62de0 100644 --- a/src/test/ui/associated-types/defaults-suitability.stderr +++ b/src/test/ui/associated-types/defaults-suitability.stderr @@ -104,61 +104,49 @@ LL | | } | |_^ error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:70:29 + --> $DIR/defaults-suitability.rs:74:15 | -LL | >::Bar: Clone, - | ^^^^^ the trait `std::clone::Clone` is not implemented for `>::Baz` +LL | type Bar: Clone = Vec; + | ^^^^^ the trait `std::clone::Clone` is not implemented for `>::Baz` | = help: consider adding a `where >::Baz: std::clone::Clone` bound = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` note: required by `Foo2` - --> $DIR/defaults-suitability.rs:69:1 + --> $DIR/defaults-suitability.rs:73:1 | -LL | / trait Foo2 where -LL | | >::Bar: Clone, -LL | | -LL | | { -LL | | type Bar = Vec; -LL | | type Baz = T; -LL | | } - | |_^ +LL | trait Foo2 { + | ^^^^^^^^^^^^^ -error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:78:29 +error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:83:15 | -LL | >::Bar: Clone, - | ^^^^^ the trait `std::clone::Clone` is not implemented for `>::Baz` +LL | type Bar: Clone = Vec; + | ^^^^^ the trait `std::clone::Clone` is not implemented for `>::Baz` | - = help: consider adding a `where >::Baz: std::clone::Clone` bound - = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` -note: required by `Foo3` - --> $DIR/defaults-suitability.rs:77:1 + = help: consider adding a `where >::Baz: std::clone::Clone` bound + = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` +note: required by `Foo25` + --> $DIR/defaults-suitability.rs:82:1 | -LL | / trait Foo3 where -LL | | >::Bar: Clone, -LL | | -LL | | { -LL | | type Bar = Vec; -LL | | type Baz = T; -LL | | } - | |_^ +LL | trait Foo25 { + | ^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:89:15 + --> $DIR/defaults-suitability.rs:92:16 | -LL | type Baz: Clone = T; - | ^^^^^ the trait `std::clone::Clone` is not implemented for `T` +LL | Self::Baz: Clone, + | ^^^^^ the trait `std::clone::Clone` is not implemented for `T` | = help: consider adding a `where T: std::clone::Clone` bound -note: required by `Foo4` - --> $DIR/defaults-suitability.rs:85:1 - | -LL | / trait Foo4 where -LL | | >::Bar: Clone, -LL | | { -LL | | type Bar = Vec; -LL | | type Baz: Clone = T; +note: required by `Foo3` + --> $DIR/defaults-suitability.rs:90:1 + | +LL | / trait Foo3 where +LL | | Self::Bar: Clone, +LL | | Self::Baz: Clone, LL | | +... | +LL | | type Baz = T; LL | | } | |_^ From 07ad64f70fb0c28f6efa107d147e36a07f48610d Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 29 Jun 2019 00:30:35 +0200 Subject: [PATCH 11/31] Add tests for #62211 --- .../defaults-unsound-62211-1.rs | 62 +++++++++++++ .../defaults-unsound-62211-1.stderr | 93 +++++++++++++++++++ .../defaults-unsound-62211-2.rs | 62 +++++++++++++ .../defaults-unsound-62211-2.stderr | 93 +++++++++++++++++++ 4 files changed, 310 insertions(+) create mode 100644 src/test/ui/associated-types/defaults-unsound-62211-1.rs create mode 100644 src/test/ui/associated-types/defaults-unsound-62211-1.stderr create mode 100644 src/test/ui/associated-types/defaults-unsound-62211-2.rs create mode 100644 src/test/ui/associated-types/defaults-unsound-62211-2.stderr diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.rs b/src/test/ui/associated-types/defaults-unsound-62211-1.rs new file mode 100644 index 0000000000000..aa7beca00476c --- /dev/null +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.rs @@ -0,0 +1,62 @@ +//! 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. + +// compile-fail + +#![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 + //~^ ERROR the trait bound `Self: std::ops::Deref` is not satisfied + + AddAssign<&'static str> + //~^ ERROR cannot add-assign `&'static str` to `Self` + + From + + 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 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(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!")); +} diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr new file mode 100644 index 0000000000000..417edd873ec34 --- /dev/null +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr @@ -0,0 +1,93 @@ +error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied + --> $DIR/defaults-unsound-62211-1.rs:20:18 + | +LL | type Output: Copy + | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` + | + = help: consider adding a `where Self: std::marker::Copy` bound +note: required by `UncheckedCopy` + --> $DIR/defaults-unsound-62211-1.rs:17:1 + | +LL | trait UncheckedCopy: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: cannot add-assign `&'static str` to `Self` + --> $DIR/defaults-unsound-62211-1.rs:24:7 + | +LL | + AddAssign<&'static str> + | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` + | + = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self` + = help: consider adding a `where Self: std::ops::AddAssign<&'static str>` bound +note: required by `UncheckedCopy` + --> $DIR/defaults-unsound-62211-1.rs:17:1 + | +LL | trait UncheckedCopy: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied + --> $DIR/defaults-unsound-62211-1.rs:22:7 + | +LL | + Deref + | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` + | + = help: consider adding a `where Self: std::ops::Deref` bound +note: required by `UncheckedCopy` + --> $DIR/defaults-unsound-62211-1.rs:17:1 + | +LL | trait UncheckedCopy: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: `Self` doesn't implement `std::fmt::Display` + --> $DIR/defaults-unsound-62211-1.rs:27:7 + | +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 + = help: consider adding a `where Self: std::fmt::Display` bound +note: required by `UncheckedCopy` + --> $DIR/defaults-unsound-62211-1.rs:17:1 + | +LL | trait UncheckedCopy: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: `T` doesn't implement `std::fmt::Display` + --> $DIR/defaults-unsound-62211-1.rs:40:9 + | +LL | impl 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 adding a `where T: std::fmt::Display` bound + +error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied + --> $DIR/defaults-unsound-62211-1.rs:40:9 + | +LL | impl UncheckedCopy for T {} + | ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T` + | + = help: consider adding a `where T: std::ops::Deref` bound + +error[E0277]: cannot add-assign `&'static str` to `T` + --> $DIR/defaults-unsound-62211-1.rs:40:9 + | +LL | impl UncheckedCopy for T {} + | ^^^^^^^^^^^^^ no implementation for `T += &'static str` + | + = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `T` + = help: consider adding a `where T: std::ops::AddAssign<&'static str>` bound + +error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied + --> $DIR/defaults-unsound-62211-1.rs:40:9 + | +LL | impl UncheckedCopy for T {} + | ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | + = help: consider adding a `where T: std::marker::Copy` bound + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.rs b/src/test/ui/associated-types/defaults-unsound-62211-2.rs new file mode 100644 index 0000000000000..ce12bd4858758 --- /dev/null +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.rs @@ -0,0 +1,62 @@ +//! 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. + +// compile-fail + +#![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 + //~^ ERROR the trait bound `Self: std::ops::Deref` is not satisfied + + AddAssign<&'static str> + //~^ ERROR cannot add-assign `&'static str` to `Self` + + From + + 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 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(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(()); +} diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr new file mode 100644 index 0000000000000..a1ce1f6db3162 --- /dev/null +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr @@ -0,0 +1,93 @@ +error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied + --> $DIR/defaults-unsound-62211-2.rs:20:18 + | +LL | type Output: Copy + | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` + | + = help: consider adding a `where Self: std::marker::Copy` bound +note: required by `UncheckedCopy` + --> $DIR/defaults-unsound-62211-2.rs:17:1 + | +LL | trait UncheckedCopy: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: cannot add-assign `&'static str` to `Self` + --> $DIR/defaults-unsound-62211-2.rs:24:7 + | +LL | + AddAssign<&'static str> + | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` + | + = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self` + = help: consider adding a `where Self: std::ops::AddAssign<&'static str>` bound +note: required by `UncheckedCopy` + --> $DIR/defaults-unsound-62211-2.rs:17:1 + | +LL | trait UncheckedCopy: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied + --> $DIR/defaults-unsound-62211-2.rs:22:7 + | +LL | + Deref + | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` + | + = help: consider adding a `where Self: std::ops::Deref` bound +note: required by `UncheckedCopy` + --> $DIR/defaults-unsound-62211-2.rs:17:1 + | +LL | trait UncheckedCopy: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: `Self` doesn't implement `std::fmt::Display` + --> $DIR/defaults-unsound-62211-2.rs:27:7 + | +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 + = help: consider adding a `where Self: std::fmt::Display` bound +note: required by `UncheckedCopy` + --> $DIR/defaults-unsound-62211-2.rs:17:1 + | +LL | trait UncheckedCopy: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: `T` doesn't implement `std::fmt::Display` + --> $DIR/defaults-unsound-62211-2.rs:40:9 + | +LL | impl 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 adding a `where T: std::fmt::Display` bound + +error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied + --> $DIR/defaults-unsound-62211-2.rs:40:9 + | +LL | impl UncheckedCopy for T {} + | ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T` + | + = help: consider adding a `where T: std::ops::Deref` bound + +error[E0277]: cannot add-assign `&'static str` to `T` + --> $DIR/defaults-unsound-62211-2.rs:40:9 + | +LL | impl UncheckedCopy for T {} + | ^^^^^^^^^^^^^ no implementation for `T += &'static str` + | + = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `T` + = help: consider adding a `where T: std::ops::AddAssign<&'static str>` bound + +error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied + --> $DIR/defaults-unsound-62211-2.rs:40:9 + | +LL | impl UncheckedCopy for T {} + | ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | + = help: consider adding a `where T: std::marker::Copy` bound + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0277`. From fead45815c626f5086e7e24ae6014fdfd104bff9 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 29 Aug 2019 12:37:41 +0200 Subject: [PATCH 12/31] Fix tests after rebase --- src/test/ui/associated-const/defaults-cyclic-fail.stderr | 2 +- src/test/ui/associated-const/defaults-not-assumed-fail.stderr | 2 +- src/test/ui/associated-types/issue-54182-2.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/ui/associated-const/defaults-cyclic-fail.stderr b/src/test/ui/associated-const/defaults-cyclic-fail.stderr index 4e59519909137..dee4620cdf692 100644 --- a/src/test/ui/associated-const/defaults-cyclic-fail.stderr +++ b/src/test/ui/associated-const/defaults-cyclic-fail.stderr @@ -10,7 +10,7 @@ note: ...which requires const-evaluating `Tr::B`... LL | const B: u8 = Self::A; | ^^^^^^^ = note: ...which again requires const-evaluating `Tr::A`, completing the cycle -note: cycle used when processing `main` +note: cycle used when const-evaluating `main` --> $DIR/defaults-cyclic-fail.rs:16:16 | LL | assert_eq!(<() as Tr>::A, 0); diff --git a/src/test/ui/associated-const/defaults-not-assumed-fail.stderr b/src/test/ui/associated-const/defaults-not-assumed-fail.stderr index aac1765c4b2d8..365ad3224105b 100644 --- a/src/test/ui/associated-const/defaults-not-assumed-fail.stderr +++ b/src/test/ui/associated-const/defaults-not-assumed-fail.stderr @@ -6,7 +6,7 @@ LL | const B: u8 = Self::A + 1; | | | attempt to add with overflow | - = note: #[deny(const_err)] on by default + = note: `#[deny(const_err)]` on by default error[E0080]: evaluation of constant expression failed --> $DIR/defaults-not-assumed-fail.rs:33:5 diff --git a/src/test/ui/associated-types/issue-54182-2.rs b/src/test/ui/associated-types/issue-54182-2.rs index f55f480978030..c88c766313671 100644 --- a/src/test/ui/associated-types/issue-54182-2.rs +++ b/src/test/ui/associated-types/issue-54182-2.rs @@ -1,4 +1,4 @@ -// compile-pass +// 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 From 485111c48e79e2b41381ff6d4f3301a38b5a167d Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 29 Aug 2019 13:40:27 +0200 Subject: [PATCH 13/31] Add regression tests for issues --- .../associated-const/defaults-cyclic-pass.rs | 3 +- .../associated-types/defaults-cyclic-pass.rs | 21 +++++--------- .../defaults-in-other-trait-items-pass.rs | 22 ++++++++++++++ .../defaults-unsound-62211-1.rs | 3 ++ .../defaults-unsound-62211-1.stderr | 24 +++++++-------- .../defaults-unsound-62211-2.rs | 3 ++ .../defaults-unsound-62211-2.stderr | 24 +++++++-------- src/test/ui/associated-types/issue-32350.rs | 29 +++++++++++++++++++ src/test/ui/associated-types/issue-41868.rs | 23 +++++++++++++++ src/test/ui/associated-types/issue-43924.rs | 15 ++++++++++ .../ui/associated-types/issue-43924.stderr | 27 +++++++++++++++++ src/test/ui/associated-types/issue-47385.rs | 16 ++++++++++ src/test/ui/associated-types/issue-63593.rs | 11 +++++++ .../ui/associated-types/issue-63593.stderr | 23 +++++++++++++++ 14 files changed, 206 insertions(+), 38 deletions(-) create mode 100644 src/test/ui/associated-types/defaults-in-other-trait-items-pass.rs create mode 100644 src/test/ui/associated-types/issue-32350.rs create mode 100644 src/test/ui/associated-types/issue-41868.rs create mode 100644 src/test/ui/associated-types/issue-43924.rs create mode 100644 src/test/ui/associated-types/issue-43924.stderr create mode 100644 src/test/ui/associated-types/issue-47385.rs create mode 100644 src/test/ui/associated-types/issue-63593.rs create mode 100644 src/test/ui/associated-types/issue-63593.stderr diff --git a/src/test/ui/associated-const/defaults-cyclic-pass.rs b/src/test/ui/associated-const/defaults-cyclic-pass.rs index 1de733cfc37ab..82105f25f9240 100644 --- a/src/test/ui/associated-const/defaults-cyclic-pass.rs +++ b/src/test/ui/associated-const/defaults-cyclic-pass.rs @@ -6,7 +6,8 @@ trait Tr { const B: u8 = Self::A; } -// This impl is *allowed* unless its assoc. consts are used +// This impl is *allowed* unless its assoc. consts are used, matching the +// behavior without defaults. impl Tr for () {} // Overriding either constant breaks the cycle diff --git a/src/test/ui/associated-types/defaults-cyclic-pass.rs b/src/test/ui/associated-types/defaults-cyclic-pass.rs index 618a203850785..74a0cfa6b73a4 100644 --- a/src/test/ui/associated-types/defaults-cyclic-pass.rs +++ b/src/test/ui/associated-types/defaults-cyclic-pass.rs @@ -2,21 +2,16 @@ #![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 Item = u8; - type Container = Vec; + type A = Self::B; + type B = Self::A; } -impl Tr for () {} - -impl Tr for u16 { - type Item = u16; +// An impl has to break the cycle to be accepted. +impl Tr for u8 { + type A = u8; } -fn main() { - let _container: <() as Tr>::Container = Vec::::new(); - let _item: <() as Tr>::Item = 0u8; - - let _container: ::Container = Vec::::new(); - let _item: ::Item = 0u16; -} +fn main() {} diff --git a/src/test/ui/associated-types/defaults-in-other-trait-items-pass.rs b/src/test/ui/associated-types/defaults-in-other-trait-items-pass.rs new file mode 100644 index 0000000000000..618a203850785 --- /dev/null +++ b/src/test/ui/associated-types/defaults-in-other-trait-items-pass.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(associated_type_defaults)] + +trait Tr { + type Item = u8; + type Container = Vec; +} + +impl Tr for () {} + +impl Tr for u16 { + type Item = u16; +} + +fn main() { + let _container: <() as Tr>::Container = Vec::::new(); + let _item: <() as Tr>::Item = 0u8; + + let _container: ::Container = Vec::::new(); + let _item: ::Item = 0u16; +} diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.rs b/src/test/ui/associated-types/defaults-unsound-62211-1.rs index aa7beca00476c..37d52ed16b61c 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-1.rs +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.rs @@ -3,6 +3,9 @@ //! 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 // compile-fail diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr index 417edd873ec34..0cad08f675223 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr @@ -1,18 +1,18 @@ error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:20:18 + --> $DIR/defaults-unsound-62211-1.rs:23:18 | LL | type Output: Copy | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` | = help: consider adding a `where Self: std::marker::Copy` bound note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-1.rs:17:1 + --> $DIR/defaults-unsound-62211-1.rs:20:1 | LL | trait UncheckedCopy: Sized { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: cannot add-assign `&'static str` to `Self` - --> $DIR/defaults-unsound-62211-1.rs:24:7 + --> $DIR/defaults-unsound-62211-1.rs:27:7 | LL | + AddAssign<&'static str> | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` @@ -20,26 +20,26 @@ LL | + AddAssign<&'static str> = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self` = help: consider adding a `where Self: std::ops::AddAssign<&'static str>` bound note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-1.rs:17:1 + --> $DIR/defaults-unsound-62211-1.rs:20:1 | LL | trait UncheckedCopy: Sized { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:22:7 + --> $DIR/defaults-unsound-62211-1.rs:25:7 | LL | + Deref | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` | = help: consider adding a `where Self: std::ops::Deref` bound note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-1.rs:17:1 + --> $DIR/defaults-unsound-62211-1.rs:20:1 | LL | trait UncheckedCopy: Sized { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `Self` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-1.rs:27:7 + --> $DIR/defaults-unsound-62211-1.rs:30:7 | LL | + Display = Self; | ^^^^^^^ `Self` cannot be formatted with the default formatter @@ -48,13 +48,13 @@ LL | + Display = Self; = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = help: consider adding a `where Self: std::fmt::Display` bound note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-1.rs:17:1 + --> $DIR/defaults-unsound-62211-1.rs:20:1 | LL | trait UncheckedCopy: Sized { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `T` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-1.rs:40:9 + --> $DIR/defaults-unsound-62211-1.rs:43:9 | LL | impl UncheckedCopy for T {} | ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter @@ -64,7 +64,7 @@ LL | impl UncheckedCopy for T {} = help: consider adding a `where T: std::fmt::Display` bound error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:40:9 + --> $DIR/defaults-unsound-62211-1.rs:43:9 | LL | impl UncheckedCopy for T {} | ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T` @@ -72,7 +72,7 @@ LL | impl UncheckedCopy for T {} = help: consider adding a `where T: std::ops::Deref` bound error[E0277]: cannot add-assign `&'static str` to `T` - --> $DIR/defaults-unsound-62211-1.rs:40:9 + --> $DIR/defaults-unsound-62211-1.rs:43:9 | LL | impl UncheckedCopy for T {} | ^^^^^^^^^^^^^ no implementation for `T += &'static str` @@ -81,7 +81,7 @@ LL | impl UncheckedCopy for T {} = help: consider adding a `where T: std::ops::AddAssign<&'static str>` bound error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:40:9 + --> $DIR/defaults-unsound-62211-1.rs:43:9 | LL | impl UncheckedCopy for T {} | ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.rs b/src/test/ui/associated-types/defaults-unsound-62211-2.rs index ce12bd4858758..d042a1478a3aa 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-2.rs +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.rs @@ -3,6 +3,9 @@ //! 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 // compile-fail diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr index a1ce1f6db3162..3a57f7df055fd 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr @@ -1,18 +1,18 @@ error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:20:18 + --> $DIR/defaults-unsound-62211-2.rs:23:18 | LL | type Output: Copy | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` | = help: consider adding a `where Self: std::marker::Copy` bound note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-2.rs:17:1 + --> $DIR/defaults-unsound-62211-2.rs:20:1 | LL | trait UncheckedCopy: Sized { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: cannot add-assign `&'static str` to `Self` - --> $DIR/defaults-unsound-62211-2.rs:24:7 + --> $DIR/defaults-unsound-62211-2.rs:27:7 | LL | + AddAssign<&'static str> | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` @@ -20,26 +20,26 @@ LL | + AddAssign<&'static str> = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self` = help: consider adding a `where Self: std::ops::AddAssign<&'static str>` bound note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-2.rs:17:1 + --> $DIR/defaults-unsound-62211-2.rs:20:1 | LL | trait UncheckedCopy: Sized { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:22:7 + --> $DIR/defaults-unsound-62211-2.rs:25:7 | LL | + Deref | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` | = help: consider adding a `where Self: std::ops::Deref` bound note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-2.rs:17:1 + --> $DIR/defaults-unsound-62211-2.rs:20:1 | LL | trait UncheckedCopy: Sized { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `Self` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-2.rs:27:7 + --> $DIR/defaults-unsound-62211-2.rs:30:7 | LL | + Display = Self; | ^^^^^^^ `Self` cannot be formatted with the default formatter @@ -48,13 +48,13 @@ LL | + Display = Self; = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = help: consider adding a `where Self: std::fmt::Display` bound note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-2.rs:17:1 + --> $DIR/defaults-unsound-62211-2.rs:20:1 | LL | trait UncheckedCopy: Sized { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `T` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-2.rs:40:9 + --> $DIR/defaults-unsound-62211-2.rs:43:9 | LL | impl UncheckedCopy for T {} | ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter @@ -64,7 +64,7 @@ LL | impl UncheckedCopy for T {} = help: consider adding a `where T: std::fmt::Display` bound error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:40:9 + --> $DIR/defaults-unsound-62211-2.rs:43:9 | LL | impl UncheckedCopy for T {} | ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T` @@ -72,7 +72,7 @@ LL | impl UncheckedCopy for T {} = help: consider adding a `where T: std::ops::Deref` bound error[E0277]: cannot add-assign `&'static str` to `T` - --> $DIR/defaults-unsound-62211-2.rs:40:9 + --> $DIR/defaults-unsound-62211-2.rs:43:9 | LL | impl UncheckedCopy for T {} | ^^^^^^^^^^^^^ no implementation for `T += &'static str` @@ -81,7 +81,7 @@ LL | impl UncheckedCopy for T {} = help: consider adding a `where T: std::ops::AddAssign<&'static str>` bound error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:40:9 + --> $DIR/defaults-unsound-62211-2.rs:43:9 | LL | impl UncheckedCopy for T {} | ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` diff --git a/src/test/ui/associated-types/issue-32350.rs b/src/test/ui/associated-types/issue-32350.rs new file mode 100644 index 0000000000000..bda21eb0e0ac8 --- /dev/null +++ b/src/test/ui/associated-types/issue-32350.rs @@ -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() {} diff --git a/src/test/ui/associated-types/issue-41868.rs b/src/test/ui/associated-types/issue-41868.rs new file mode 100644 index 0000000000000..52bbd1f5d2863 --- /dev/null +++ b/src/test/ui/associated-types/issue-41868.rs @@ -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; +} + +impl CanDecode for u8 { + fn read(rdr: &mut Foo) -> Option { Some(42) } +} + +impl CanDecode for u16 { + fn read(rdr: &mut Foo) -> Option { Some(17) } +} + +fn main() {} diff --git a/src/test/ui/associated-types/issue-43924.rs b/src/test/ui/associated-types/issue-43924.rs new file mode 100644 index 0000000000000..26f1183c6bd76 --- /dev/null +++ b/src/test/ui/associated-types/issue-43924.rs @@ -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 { + type Out: Default + ToString + ?Sized = dyn ToString; //~ error: not satisfied +} + +impl Foo for () {} //~ error: not satisfied +impl Foo for () {} //~ error: not satisfied + +fn main() { + assert_eq!(<() as Foo>::Out::default().to_string(), "false"); +} diff --git a/src/test/ui/associated-types/issue-43924.stderr b/src/test/ui/associated-types/issue-43924.stderr new file mode 100644 index 0000000000000..67a963b501357 --- /dev/null +++ b/src/test/ui/associated-types/issue-43924.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `(dyn std::string::ToString + 'static): std::default::Default` is not satisfied + --> $DIR/issue-43924.rs:7:15 + | +LL | type Out: Default + ToString + ?Sized = dyn ToString; + | ^^^^^^^ the trait `std::default::Default` is not implemented for `(dyn std::string::ToString + 'static)` + | +note: required by `Foo` + --> $DIR/issue-43924.rs:6:1 + | +LL | trait Foo { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +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 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 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`. diff --git a/src/test/ui/associated-types/issue-47385.rs b/src/test/ui/associated-types/issue-47385.rs new file mode 100644 index 0000000000000..d43d674e9c3a0 --- /dev/null +++ b/src/test/ui/associated-types/issue-47385.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(associated_type_defaults)] + +pub struct Foo; + +pub trait Bar: From<::Input> { + type Input = Self; +} + +impl Bar for Foo { + // Will compile with explicit type: + // type Input = Self; +} + +fn main() {} diff --git a/src/test/ui/associated-types/issue-63593.rs b/src/test/ui/associated-types/issue-63593.rs new file mode 100644 index 0000000000000..1452467f3736e --- /dev/null +++ b/src/test/ui/associated-types/issue-63593.rs @@ -0,0 +1,11 @@ +#![feature(associated_type_defaults)] + +// Tests that `Self` is not assumed to implement `Sized` when used as an +// associated type default. + +trait Inner {} + +trait MyTrait { + type This = Self; //~ error: size for values of type `Self` cannot be known + fn something>(i: I); +} diff --git a/src/test/ui/associated-types/issue-63593.stderr b/src/test/ui/associated-types/issue-63593.stderr new file mode 100644 index 0000000000000..ea462eac9b4d3 --- /dev/null +++ b/src/test/ui/associated-types/issue-63593.stderr @@ -0,0 +1,23 @@ +error[E0601]: `main` function not found in crate `issue_63593` + | + = note: consider adding a `main` function to `$DIR/issue-63593.rs` + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/issue-63593.rs:9:5 + | +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 + = help: consider adding a `where Self: std::marker::Sized` bound +note: required by `MyTrait` + --> $DIR/issue-63593.rs:8:1 + | +LL | trait MyTrait { + | ^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0601. +For more information about an error, try `rustc --explain E0277`. From 1f61f36849249b5333c74f63d54d2f8bfe30ad59 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 29 Aug 2019 14:11:55 +0200 Subject: [PATCH 14/31] Add comment about the shallow subst rule --- src/librustc_typeck/check/wfcheck.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 9f1ae37da1ad3..e39beb547d1a7 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -482,6 +482,9 @@ fn check_associated_type_defaults( /// 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<'tcx>>, From fd28614cb799b762880b25b976760ddd0c530e92 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 15 Sep 2019 01:15:22 +0200 Subject: [PATCH 15/31] Add regression test for #26681 --- src/test/ui/associated-types/issue-26681.rs | 20 +++++++++++++++++++ .../ui/associated-types/issue-26681.stderr | 12 +++++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/test/ui/associated-types/issue-26681.rs create mode 100644 src/test/ui/associated-types/issue-26681.stderr diff --git a/src/test/ui/associated-types/issue-26681.rs b/src/test/ui/associated-types/issue-26681.rs new file mode 100644 index 0000000000000..a0a8c86d94954 --- /dev/null +++ b/src/test/ui/associated-types/issue-26681.rs @@ -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: ::Bar = 6665; //~ error: mismatched types +} + +fn main() {} diff --git a/src/test/ui/associated-types/issue-26681.stderr b/src/test/ui/associated-types/issue-26681.stderr new file mode 100644 index 0000000000000..27175a247fa8a --- /dev/null +++ b/src/test/ui/associated-types/issue-26681.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/issue-26681.rs:17:39 + | +LL | const C: ::Bar = 6665; + | ^^^^ expected associated type, found integer + | + = note: expected type `<::Fv as Foo>::Bar` + found type `{integer}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From c96452074027479cec7d93cad8a8688577ec3cf1 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 15 Sep 2019 16:52:02 +0200 Subject: [PATCH 16/31] Update tests after compiletest changes --- .../defaults-suitability.stderr | 93 ++++++------------- .../defaults-unsound-62211-1.stderr | 32 +++---- .../defaults-unsound-62211-2.stderr | 32 +++---- .../ui/associated-types/issue-43924.stderr | 8 +- src/test/ui/associated-types/issue-54182-1.rs | 4 +- src/test/ui/associated-types/issue-63593.rs | 2 + .../ui/associated-types/issue-63593.stderr | 16 +--- 7 files changed, 63 insertions(+), 124 deletions(-) diff --git a/src/test/ui/associated-types/defaults-suitability.stderr b/src/test/ui/associated-types/defaults-suitability.stderr index 9a7febeb62de0..dd45c9e443668 100644 --- a/src/test/ui/associated-types/defaults-suitability.stderr +++ b/src/test/ui/associated-types/defaults-suitability.stderr @@ -1,154 +1,119 @@ error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied --> $DIR/defaults-suitability.rs:17:14 | +LL | trait Tr { + | -------- required by `Tr` LL | type Ty: Clone = NotClone; | ^^^^^ the trait `std::clone::Clone` is not implemented for `NotClone` - | -note: required by `Tr` - --> $DIR/defaults-suitability.rs:16:1 - | -LL | trait Tr { - | ^^^^^^^^ error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied --> $DIR/defaults-suitability.rs:22:27 | LL | trait Tr2 where Self::Ty: Clone { - | ^^^^^ the trait `std::clone::Clone` is not implemented for `NotClone` - | -note: required by `Tr2` - --> $DIR/defaults-suitability.rs:22:1 - | -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:35:15 | +LL | trait Foo { + | ------------ required by `Foo` LL | type Bar: Clone = Vec; | ^^^^^ the trait `std::clone::Clone` is not implemented for `T` | = help: consider adding a `where T: std::clone::Clone` bound = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec` -note: required by `Foo` - --> $DIR/defaults-suitability.rs:34:1 - | -LL | trait Foo { - | ^^^^^^^^^^^^ error[E0277]: the trait bound `(): Foo` is not satisfied --> $DIR/defaults-suitability.rs:41:17 | +LL | trait Bar: Sized { + | ---------------- required by `Bar` +LL | // `(): Foo` might hold for some possible impls but not all. LL | type Assoc: Foo = (); | ^^^^^^^^^ the trait `Foo` is not implemented for `()` - | -note: required by `Bar` - --> $DIR/defaults-suitability.rs:39:1 - | -LL | trait Bar: Sized { - | ^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `NotClone: IsU8` is not satisfied --> $DIR/defaults-suitability.rs:61:18 | -LL | Self::Assoc: IsU8, - | ^^^^^^^^^^^^^^^^^ the trait `IsU8` is not implemented for `NotClone` - | -note: required by `D` - --> $DIR/defaults-suitability.rs:58:1 - | LL | / trait D where LL | | Vec: Clone, LL | | LL | | Self::Assoc: IsU8, + | | ^^^^^^^^^^^^^^^^^ the trait `IsU8` is not implemented for `NotClone` ... | LL | | type Assoc = NotClone; LL | | } - | |_^ + | |_- required by `D` error[E0277]: the trait bound `bool: IsU8` is not satisfied --> $DIR/defaults-suitability.rs:63:11 | -LL | bool: IsU8, - | ^^^^^^^^^^^^^^^^^ the trait `IsU8` is not implemented for `bool` - | -note: required by `D` - --> $DIR/defaults-suitability.rs:58:1 - | LL | / trait D where LL | | Vec: Clone, LL | | LL | | Self::Assoc: IsU8, +LL | | +LL | | bool: IsU8, + | | ^^^^^^^^^^^^^^^^^ the trait `IsU8` 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:59:23 | -LL | Vec: Clone, - | ^^^^^ the trait `std::clone::Clone` is not implemented for `NotClone` - | - = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec` -note: required by `D` - --> $DIR/defaults-suitability.rs:58:1 - | LL | / trait D where LL | | Vec: Clone, + | | ^^^^^ the trait `std::clone::Clone` is not implemented for `NotClone` LL | | LL | | Self::Assoc: IsU8, ... | 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` error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied --> $DIR/defaults-suitability.rs:74:15 | +LL | trait Foo2 { + | ------------- required by `Foo2` LL | type Bar: Clone = Vec; | ^^^^^ the trait `std::clone::Clone` is not implemented for `>::Baz` | = help: consider adding a `where >::Baz: std::clone::Clone` bound = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` -note: required by `Foo2` - --> $DIR/defaults-suitability.rs:73:1 - | -LL | trait Foo2 { - | ^^^^^^^^^^^^^ error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied --> $DIR/defaults-suitability.rs:83:15 | +LL | trait Foo25 { + | --------------------- required by `Foo25` LL | type Bar: Clone = Vec; | ^^^^^ the trait `std::clone::Clone` is not implemented for `>::Baz` | = help: consider adding a `where >::Baz: std::clone::Clone` bound = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` -note: required by `Foo25` - --> $DIR/defaults-suitability.rs:82:1 - | -LL | trait Foo25 { - | ^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied --> $DIR/defaults-suitability.rs:92:16 | -LL | Self::Baz: Clone, - | ^^^^^ the trait `std::clone::Clone` is not implemented for `T` - | - = help: consider adding a `where T: std::clone::Clone` bound -note: required by `Foo3` - --> $DIR/defaults-suitability.rs:90:1 - | LL | / trait Foo3 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 adding a `where T: std::clone::Clone` bound error[E0277]: the size for values of type `[u8]` cannot be known at compilation time --> $DIR/defaults-suitability.rs:29:5 diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr index 0cad08f675223..e8eb085b79146 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr @@ -1,57 +1,49 @@ error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied --> $DIR/defaults-unsound-62211-1.rs:23:18 | +LL | trait UncheckedCopy: Sized { + | -------------------------- required by `UncheckedCopy` +... LL | type Output: Copy | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` | = help: consider adding a `where Self: std::marker::Copy` bound -note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-1.rs:20:1 - | -LL | trait UncheckedCopy: Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: cannot add-assign `&'static str` to `Self` --> $DIR/defaults-unsound-62211-1.rs:27: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` = help: consider adding a `where Self: std::ops::AddAssign<&'static str>` bound -note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-1.rs:20:1 - | -LL | trait UncheckedCopy: Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied --> $DIR/defaults-unsound-62211-1.rs:25:7 | +LL | trait UncheckedCopy: Sized { + | -------------------------- required by `UncheckedCopy` +... LL | + Deref | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` | = help: consider adding a `where Self: std::ops::Deref` bound -note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-1.rs:20:1 - | -LL | trait UncheckedCopy: Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `Self` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-1.rs:30: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 = help: consider adding a `where Self: std::fmt::Display` bound -note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-1.rs:20:1 - | -LL | trait UncheckedCopy: Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `T` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-1.rs:43:9 diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr index 3a57f7df055fd..a0b5d6b9cbb46 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr @@ -1,57 +1,49 @@ error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied --> $DIR/defaults-unsound-62211-2.rs:23:18 | +LL | trait UncheckedCopy: Sized { + | -------------------------- required by `UncheckedCopy` +... LL | type Output: Copy | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` | = help: consider adding a `where Self: std::marker::Copy` bound -note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-2.rs:20:1 - | -LL | trait UncheckedCopy: Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: cannot add-assign `&'static str` to `Self` --> $DIR/defaults-unsound-62211-2.rs:27: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` = help: consider adding a `where Self: std::ops::AddAssign<&'static str>` bound -note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-2.rs:20:1 - | -LL | trait UncheckedCopy: Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied --> $DIR/defaults-unsound-62211-2.rs:25:7 | +LL | trait UncheckedCopy: Sized { + | -------------------------- required by `UncheckedCopy` +... LL | + Deref | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` | = help: consider adding a `where Self: std::ops::Deref` bound -note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-2.rs:20:1 - | -LL | trait UncheckedCopy: Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `Self` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-2.rs:30: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 = help: consider adding a `where Self: std::fmt::Display` bound -note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-2.rs:20:1 - | -LL | trait UncheckedCopy: Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `T` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-2.rs:43:9 diff --git a/src/test/ui/associated-types/issue-43924.stderr b/src/test/ui/associated-types/issue-43924.stderr index 67a963b501357..75a5b3f3551cb 100644 --- a/src/test/ui/associated-types/issue-43924.stderr +++ b/src/test/ui/associated-types/issue-43924.stderr @@ -1,14 +1,10 @@ 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 { + | -------------------------------- 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)` - | -note: required by `Foo` - --> $DIR/issue-43924.rs:6:1 - | -LL | trait Foo { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `(dyn std::string::ToString + 'static): std::default::Default` is not satisfied --> $DIR/issue-43924.rs:10:6 diff --git a/src/test/ui/associated-types/issue-54182-1.rs b/src/test/ui/associated-types/issue-54182-1.rs index 3e10f3fb7dff3..1a1e98cbac27f 100644 --- a/src/test/ui/associated-types/issue-54182-1.rs +++ b/src/test/ui/associated-types/issue-54182-1.rs @@ -21,12 +21,12 @@ macro_rules! overload { } fn main() { - let r: () = overload!(42, true); + let () = overload!(42, true); let r: f32 = overload!("Hello world", 13.0); assert_eq!(r, 13.0); - let r: () = overload!(42, true, 42.5); + let () = overload!(42, true, 42.5); let r: i32 = overload!("Hello world", 13.0, 42); assert_eq!(r, 42); diff --git a/src/test/ui/associated-types/issue-63593.rs b/src/test/ui/associated-types/issue-63593.rs index 1452467f3736e..8dbc24c067320 100644 --- a/src/test/ui/associated-types/issue-63593.rs +++ b/src/test/ui/associated-types/issue-63593.rs @@ -9,3 +9,5 @@ trait MyTrait { type This = Self; //~ error: size for values of type `Self` cannot be known fn something>(i: I); } + +fn main() {} diff --git a/src/test/ui/associated-types/issue-63593.stderr b/src/test/ui/associated-types/issue-63593.stderr index ea462eac9b4d3..37dd52980d996 100644 --- a/src/test/ui/associated-types/issue-63593.stderr +++ b/src/test/ui/associated-types/issue-63593.stderr @@ -1,23 +1,15 @@ -error[E0601]: `main` function not found in crate `issue_63593` - | - = note: consider adding a `main` function to `$DIR/issue-63593.rs` - 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 = help: consider adding a `where Self: std::marker::Sized` bound -note: required by `MyTrait` - --> $DIR/issue-63593.rs:8:1 - | -LL | trait MyTrait { - | ^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0277, E0601. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. From 3f03d95bb0e7d2421e1809aa1d69c9c38871092f Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 15 Sep 2019 17:31:40 +0200 Subject: [PATCH 17/31] Improve associated-types-overridden-default.rs Check that the resulting assoc. types are as expected --- .../associated-types/associated-types-overridden-default.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/ui/associated-types/associated-types-overridden-default.rs b/src/test/ui/associated-types/associated-types-overridden-default.rs index 72c30df0b3dff..3e12c92289618 100644 --- a/src/test/ui/associated-types/associated-types-overridden-default.rs +++ b/src/test/ui/associated-types/associated-types-overridden-default.rs @@ -16,4 +16,7 @@ impl Tr for () { type Assoc = (); } -fn main() {} +fn main() { + let _: <() as Tr>::Assoc = (); + let _: <() as Tr>::Assoc2 = (); +} From f40879408cb055fc078912ca226ac0a41ddb61ce Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 15 Sep 2019 17:59:37 +0200 Subject: [PATCH 18/31] Improve defaults-in-other-trait-items-pass --- .../defaults-in-other-trait-items-pass.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/test/ui/associated-types/defaults-in-other-trait-items-pass.rs b/src/test/ui/associated-types/defaults-in-other-trait-items-pass.rs index 618a203850785..a3bfcd8efe29a 100644 --- a/src/test/ui/associated-types/defaults-in-other-trait-items-pass.rs +++ b/src/test/ui/associated-types/defaults-in-other-trait-items-pass.rs @@ -13,10 +13,25 @@ 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::::new(); let _item: <() as Tr>::Item = 0u8; let _container: ::Container = Vec::::new(); let _item: ::Item = 0u16; + + let _container: ::Container = String::new(); + let _item: ::Item = 0u8; + + let _container: ::Container = Vec::<()>::new(); + let _item: ::Item = 0u32; } From fbcd136b655c2743d3a8c3aa87e460ac38d57046 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 15 Sep 2019 01:18:37 +0200 Subject: [PATCH 19/31] Improve the cycle tests --- ...clic-fail.rs => defaults-cyclic-fail-1.rs} | 16 +++++- .../defaults-cyclic-fail-1.stderr | 33 +++++++++++ .../defaults-cyclic-fail-2.rs | 49 ++++++++++++++++ .../defaults-cyclic-fail-2.stderr | 33 +++++++++++ .../defaults-cyclic-fail.stderr | 21 ------- .../defaults-cyclic-pass-1.rs | 56 +++++++++++++++++++ .../defaults-cyclic-pass-2.rs | 56 +++++++++++++++++++ .../associated-types/defaults-cyclic-pass.rs | 17 ------ 8 files changed, 240 insertions(+), 41 deletions(-) rename src/test/ui/associated-types/{defaults-cyclic-fail.rs => defaults-cyclic-fail-1.rs} (65%) create mode 100644 src/test/ui/associated-types/defaults-cyclic-fail-1.stderr create mode 100644 src/test/ui/associated-types/defaults-cyclic-fail-2.rs create mode 100644 src/test/ui/associated-types/defaults-cyclic-fail-2.stderr delete mode 100644 src/test/ui/associated-types/defaults-cyclic-fail.stderr create mode 100644 src/test/ui/associated-types/defaults-cyclic-pass-1.rs create mode 100644 src/test/ui/associated-types/defaults-cyclic-pass-2.rs delete mode 100644 src/test/ui/associated-types/defaults-cyclic-pass.rs diff --git a/src/test/ui/associated-types/defaults-cyclic-fail.rs b/src/test/ui/associated-types/defaults-cyclic-fail-1.rs similarity index 65% rename from src/test/ui/associated-types/defaults-cyclic-fail.rs rename to src/test/ui/associated-types/defaults-cyclic-fail-1.rs index ab66fe0b52ee7..71ac914ef5759 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail.rs +++ b/src/test/ui/associated-types/defaults-cyclic-fail-1.rs @@ -15,6 +15,10 @@ impl Tr for u8 { type A = u8; } +impl Tr for u16 { + type B = (); +} + impl Tr for u32 { type A = (); type B = u8; @@ -28,8 +32,14 @@ impl Tr for bool { } // (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() { - // Check that the overridden type propagates to the other - let _a: ::A = 0u8; - let _b: ::B = 0u8; + // 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. } diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr b/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr new file mode 100644 index 0000000000000..4f28a50701ad0 --- /dev/null +++ b/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr @@ -0,0 +1,33 @@ +error[E0275]: overflow evaluating the requirement `<() as Tr>::B` + --> $DIR/defaults-cyclic-fail-1.rs:12:6 + | +LL | impl Tr for () {} + | ^^ + +error[E0275]: overflow evaluating the requirement `::B` + --> $DIR/defaults-cyclic-fail-1.rs:30:6 + | +LL | impl Tr for bool { + | ^^ + +error[E0275]: overflow evaluating the requirement `::B` + --> $DIR/defaults-cyclic-fail-1.rs:37:6 + | +LL | impl Tr for usize { + | ^^ + +error[E0275]: overflow evaluating the requirement `::B` + --> $DIR/defaults-cyclic-fail-1.rs:32:5 + | +LL | type A = Box; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0275]: overflow evaluating the requirement `::A` + --> $DIR/defaults-cyclic-fail-1.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`. diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-2.rs b/src/test/ui/associated-types/defaults-cyclic-fail-2.rs new file mode 100644 index 0000000000000..2f2e84c60002a --- /dev/null +++ b/src/test/ui/associated-types/defaults-cyclic-fail-2.rs @@ -0,0 +1,49 @@ +// compile-fail + +#![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; + type B = Box; +} + +// ...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; + //~^ 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. +} diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr b/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr new file mode 100644 index 0000000000000..bbc130f11f729 --- /dev/null +++ b/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr @@ -0,0 +1,33 @@ +error[E0275]: overflow evaluating the requirement `<() as Tr>::B` + --> $DIR/defaults-cyclic-fail-2.rs:14:6 + | +LL | impl Tr for () {} + | ^^ + +error[E0275]: overflow evaluating the requirement `::B` + --> $DIR/defaults-cyclic-fail-2.rs:32:6 + | +LL | impl Tr for bool { + | ^^ + +error[E0275]: overflow evaluating the requirement `::B` + --> $DIR/defaults-cyclic-fail-2.rs:39:6 + | +LL | impl Tr for usize { + | ^^ + +error[E0275]: overflow evaluating the requirement `::B` + --> $DIR/defaults-cyclic-fail-2.rs:34:5 + | +LL | type A = Box; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0275]: overflow evaluating the requirement `::A` + --> $DIR/defaults-cyclic-fail-2.rs:41:5 + | +LL | type B = &'static Self::A; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/associated-types/defaults-cyclic-fail.stderr b/src/test/ui/associated-types/defaults-cyclic-fail.stderr deleted file mode 100644 index dd0e5c2ef4214..0000000000000 --- a/src/test/ui/associated-types/defaults-cyclic-fail.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0275]: overflow evaluating the requirement `<() as Tr>::B` - --> $DIR/defaults-cyclic-fail.rs:10:6 - | -LL | impl Tr for () {} - | ^^ - -error[E0275]: overflow evaluating the requirement `::B` - --> $DIR/defaults-cyclic-fail.rs:24:6 - | -LL | impl Tr for bool { - | ^^ - -error[E0275]: overflow evaluating the requirement `::B` - --> $DIR/defaults-cyclic-fail.rs:26:5 - | -LL | type A = Box; - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/associated-types/defaults-cyclic-pass-1.rs b/src/test/ui/associated-types/defaults-cyclic-pass-1.rs new file mode 100644 index 0000000000000..97c6e5bade233 --- /dev/null +++ b/src/test/ui/associated-types/defaults-cyclic-pass-1.rs @@ -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 _: ::A = 0u8; + let _: ::B = 0u8; + + let _: ::A = (); + let _: ::B = (); + + let _: <() as Tr>::A = Vec::<()>::new(); + let _: <() as Tr>::B = 0u8; +} diff --git a/src/test/ui/associated-types/defaults-cyclic-pass-2.rs b/src/test/ui/associated-types/defaults-cyclic-pass-2.rs new file mode 100644 index 0000000000000..69315a022100b --- /dev/null +++ b/src/test/ui/associated-types/defaults-cyclic-pass-2.rs @@ -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; + type B = Box; + + 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 _: ::A = 0u8; + let _: ::B = Box::new(0u8); + + let _: ::A = Vec::<()>::new(); + let _: ::B = (); + + let _: <() as Tr>::A = Vec::<()>::new(); + let _: <() as Tr>::B = 0u8; +} diff --git a/src/test/ui/associated-types/defaults-cyclic-pass.rs b/src/test/ui/associated-types/defaults-cyclic-pass.rs deleted file mode 100644 index 74a0cfa6b73a4..0000000000000 --- a/src/test/ui/associated-types/defaults-cyclic-pass.rs +++ /dev/null @@ -1,17 +0,0 @@ -// 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; -} - -// An impl has to break the cycle to be accepted. -impl Tr for u8 { - type A = u8; -} - -fn main() {} From c8da9ee50af722385e673e79c466fb3abcb75697 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 15 Sep 2019 22:02:44 +0200 Subject: [PATCH 20/31] Improve specialization test --- .../defaults-specialization.rs | 36 ++++++++++- .../defaults-specialization.stderr | 61 ++++++++++++++++--- 2 files changed, 88 insertions(+), 9 deletions(-) diff --git a/src/test/ui/associated-types/defaults-specialization.rs b/src/test/ui/associated-types/defaults-specialization.rs index e3a5db0960cf0..833981fc8e3c8 100644 --- a/src/test/ui/associated-types/defaults-specialization.rs +++ b/src/test/ui/associated-types/defaults-specialization.rs @@ -7,7 +7,10 @@ trait Tr { type Ty = u8; - fn make() -> Self::Ty; + fn make() -> Self::Ty { + 0u8 + //~^ error: mismatched types + } } struct A(T); @@ -61,4 +64,33 @@ impl Tr for D { fn make() -> u8 { 255 } } -fn main() {} +struct E(T); +impl Tr for E { + default fn make() -> Self::Ty { panic!(); } +} + +// This impl specializes and sets `Ty`, it can rely on `Ty=String`. +impl Tr for E { + 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 _: as Tr>::Ty = 0u8; + //let _: as Tr>::Ty = 0u8; + + let _: as Tr>::Ty = 0u8; //~ error: mismatched types + let _: as Tr>::Ty = true; //~ error: mismatched types + let _: as Tr>::Ty = 0u8; //~ error: mismatched types + let _: as Tr>::Ty = true; //~ error: mismatched types + + let _: as Tr>::Ty = true; + + let _: as Tr>::Ty = 0u8; + let _: as Tr>::Ty = 0u8; +} diff --git a/src/test/ui/associated-types/defaults-specialization.stderr b/src/test/ui/associated-types/defaults-specialization.stderr index 2b2adfdb7c965..bd0fd7166f668 100644 --- a/src/test/ui/associated-types/defaults-specialization.stderr +++ b/src/test/ui/associated-types/defaults-specialization.stderr @@ -1,7 +1,7 @@ error[E0053]: method `make` has an incompatible type for trait - --> $DIR/defaults-specialization.rs:17:18 + --> $DIR/defaults-specialization.rs:20:18 | -LL | fn make() -> Self::Ty; +LL | fn make() -> Self::Ty { | -------- type in trait ... LL | fn make() -> u8 { 0 } @@ -11,9 +11,9 @@ LL | fn make() -> u8 { 0 } found type `fn() -> u8` error[E0053]: method `make` has an incompatible type for trait - --> $DIR/defaults-specialization.rs:33:18 + --> $DIR/defaults-specialization.rs:36:18 | -LL | fn make() -> Self::Ty; +LL | fn make() -> Self::Ty { | -------- type in trait ... LL | fn make() -> bool { true } @@ -23,7 +23,18 @@ LL | fn make() -> bool { true } found type `fn() -> bool` error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:24:29 + --> $DIR/defaults-specialization.rs:11:9 + | +LL | fn make() -> Self::Ty { + | -------- expected `::Ty` because of return type +LL | 0u8 + | ^^^ expected associated type, found u8 + | + = note: expected type `::Ty` + found type `u8` + +error[E0308]: mismatched types + --> $DIR/defaults-specialization.rs:27:29 | LL | fn make() -> Self::Ty { 0u8 } | -------- ^^^ expected associated type, found u8 @@ -34,7 +45,7 @@ LL | fn make() -> Self::Ty { 0u8 } found type `u8` error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:42:29 + --> $DIR/defaults-specialization.rs:45:29 | LL | fn make() -> Self::Ty { true } | -------- ^^^^ expected associated type, found bool @@ -44,7 +55,43 @@ LL | fn make() -> Self::Ty { true } = note: expected type ` as Tr>::Ty` found type `bool` -error: aborting due to 4 previous errors +error[E0308]: mismatched types + --> $DIR/defaults-specialization.rs:87:32 + | +LL | let _: as Tr>::Ty = 0u8; + | ^^^ expected associated type, found u8 + | + = note: expected type ` as Tr>::Ty` + found type `u8` + +error[E0308]: mismatched types + --> $DIR/defaults-specialization.rs:88:32 + | +LL | let _: as Tr>::Ty = true; + | ^^^^ expected associated type, found bool + | + = note: expected type ` as Tr>::Ty` + found type `bool` + +error[E0308]: mismatched types + --> $DIR/defaults-specialization.rs:89:33 + | +LL | let _: as Tr>::Ty = 0u8; + | ^^^ expected associated type, found u8 + | + = note: expected type ` as Tr>::Ty` + found type `u8` + +error[E0308]: mismatched types + --> $DIR/defaults-specialization.rs:90:33 + | +LL | let _: as Tr>::Ty = true; + | ^^^^ expected associated type, found bool + | + = note: expected type ` as Tr>::Ty` + found type `bool` + +error: aborting due to 9 previous errors Some errors have detailed explanations: E0053, E0308. For more information about an error, try `rustc --explain E0053`. From 24ec364713daad4f5014a0921c3dbc1b59ade1ac Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 15 Sep 2019 22:07:01 +0200 Subject: [PATCH 21/31] Test mixed default and non-default --- .../ui/associated-types/defaults-mixed.rs | 36 +++++++++++++++++++ .../ui/associated-types/defaults-mixed.stderr | 21 +++++++++++ 2 files changed, 57 insertions(+) create mode 100644 src/test/ui/associated-types/defaults-mixed.rs create mode 100644 src/test/ui/associated-types/defaults-mixed.stderr diff --git a/src/test/ui/associated-types/defaults-mixed.rs b/src/test/ui/associated-types/defaults-mixed.rs new file mode 100644 index 0000000000000..7601ab71e4a2b --- /dev/null +++ b/src/test/ui/associated-types/defaults-mixed.rs @@ -0,0 +1,36 @@ +// compile-fail + +#![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 _: ::Foo = 0u8; + let _: ::Bar = (); + + let _: ::Foo = String::new(); + let _: ::Bar = true; +} diff --git a/src/test/ui/associated-types/defaults-mixed.stderr b/src/test/ui/associated-types/defaults-mixed.stderr new file mode 100644 index 0000000000000..2d31d1dbdfeef --- /dev/null +++ b/src/test/ui/associated-types/defaults-mixed.stderr @@ -0,0 +1,21 @@ +error[E0046]: not all trait items implemented, missing: `Bar` + --> $DIR/defaults-mixed.rs:13: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:16: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`. From f94eaeaf736e19b9249eb690a381202bcc5065b3 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 8 Oct 2019 01:14:45 +0200 Subject: [PATCH 22/31] Fix rebase damage --- src/librustc_typeck/check/wfcheck.rs | 2 +- .../defaults-in-other-trait-items.rs | 4 +- .../defaults-in-other-trait-items.stderr | 2 +- .../defaults-specialization.rs | 1 + .../defaults-specialization.stderr | 80 ++++++++++++------- .../defaults-suitability.stderr | 22 ++--- .../defaults-unsound-62211-1.stderr | 28 +++---- .../defaults-unsound-62211-2.stderr | 28 +++---- .../ui/associated-types/issue-26681.stderr | 6 +- .../ui/associated-types/issue-63593.stderr | 1 - 10 files changed, 95 insertions(+), 79 deletions(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index e39beb547d1a7..a6189a346645d 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -496,7 +496,7 @@ fn check_associated_type_defaults( } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - match t.sty { + match t.kind { ty::Projection(proj_ty) => { if let Some(default) = self.map.get(&proj_ty) { default diff --git a/src/test/ui/associated-types/defaults-in-other-trait-items.rs b/src/test/ui/associated-types/defaults-in-other-trait-items.rs index 0455997b16808..9f2e8aca47712 100644 --- a/src/test/ui/associated-types/defaults-in-other-trait-items.rs +++ b/src/test/ui/associated-types/defaults-in-other-trait-items.rs @@ -10,7 +10,7 @@ trait Tr { //~^ ERROR mismatched types //~| NOTE expected associated type, found `()` //~| NOTE expected associated type `::A` - //~| NOTE consider constraining + //~| NOTE consider constraining the associated type //~| NOTE for more information, visit } } @@ -38,7 +38,7 @@ trait AssocConst { //~^ ERROR mismatched types //~| NOTE expected associated type, found `u8` //~| NOTE expected associated type `::Ty` - //~| NOTE consider constraining + //~| NOTE consider constraining the associated type //~| NOTE for more information, visit } diff --git a/src/test/ui/associated-types/defaults-in-other-trait-items.stderr b/src/test/ui/associated-types/defaults-in-other-trait-items.stderr index 9ecfe49c2b571..b759276d2484b 100644 --- a/src/test/ui/associated-types/defaults-in-other-trait-items.stderr +++ b/src/test/ui/associated-types/defaults-in-other-trait-items.stderr @@ -10,7 +10,7 @@ LL | let () = p; = 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 + --> $DIR/defaults-in-other-trait-items.rs:39:25 | LL | const C: Self::Ty = 0u8; | ^^^ expected associated type, found `u8` diff --git a/src/test/ui/associated-types/defaults-specialization.rs b/src/test/ui/associated-types/defaults-specialization.rs index 833981fc8e3c8..cb0d231bfcd7c 100644 --- a/src/test/ui/associated-types/defaults-specialization.rs +++ b/src/test/ui/associated-types/defaults-specialization.rs @@ -66,6 +66,7 @@ impl Tr for D { struct E(T); impl Tr for E { + default type Ty = bool; default fn make() -> Self::Ty { panic!(); } } diff --git a/src/test/ui/associated-types/defaults-specialization.stderr b/src/test/ui/associated-types/defaults-specialization.stderr index bd0fd7166f668..9b10940cbc485 100644 --- a/src/test/ui/associated-types/defaults-specialization.stderr +++ b/src/test/ui/associated-types/defaults-specialization.stderr @@ -5,10 +5,12 @@ LL | fn make() -> Self::Ty { | -------- type in trait ... LL | fn make() -> u8 { 0 } - | ^^ expected associated type, found u8 + | ^^ expected associated type, found `u8` | - = note: expected type `fn() -> as Tr>::Ty` - found type `fn() -> u8` + = note: expected fn pointer `fn() -> as Tr>::Ty` + found fn pointer `fn() -> u8` + = note: consider constraining the associated type ` as Tr>::Ty` to `u8` or calling a method that returns ` 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:36:18 @@ -17,10 +19,12 @@ LL | fn make() -> Self::Ty { | -------- type in trait ... LL | fn make() -> bool { true } - | ^^^^ expected associated type, found bool + | ^^^^ expected associated type, found `bool` | - = note: expected type `fn() -> as Tr>::Ty` - found type `fn() -> bool` + = note: expected fn pointer `fn() -> as Tr>::Ty` + found fn pointer `fn() -> bool` + = note: consider constraining the associated type ` as Tr>::Ty` to `bool` or calling a method that returns ` 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:11:9 @@ -28,68 +32,82 @@ error[E0308]: mismatched types LL | fn make() -> Self::Ty { | -------- expected `::Ty` because of return type LL | 0u8 - | ^^^ expected associated type, found u8 + | ^^^ expected associated type, found `u8` | - = note: expected type `::Ty` - found type `u8` + = note: expected associated type `::Ty` + found type `u8` + = note: consider constraining the associated type `::Ty` to `u8` or calling a method that returns `::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:27:29 | LL | fn make() -> Self::Ty { 0u8 } - | -------- ^^^ expected associated type, found u8 + | -------- ^^^ expected associated type, found `u8` | | | expected ` as Tr>::Ty` because of return type | - = note: expected type ` as Tr>::Ty` - found type `u8` + = note: expected associated type ` as Tr>::Ty` + found type `u8` + = note: consider constraining the associated type ` as Tr>::Ty` to `u8` or calling a method that returns ` 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:45:29 | LL | fn make() -> Self::Ty { true } - | -------- ^^^^ expected associated type, found bool + | -------- ^^^^ expected associated type, found `bool` | | | expected ` as Tr>::Ty` because of return type | - = note: expected type ` as Tr>::Ty` - found type `bool` + = note: expected associated type ` as Tr>::Ty` + found type `bool` + = note: consider constraining the associated type ` as Tr>::Ty` to `bool` or calling a method that returns ` 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 + --> $DIR/defaults-specialization.rs:88:32 | LL | let _: as Tr>::Ty = 0u8; - | ^^^ expected associated type, found u8 + | ^^^ expected associated type, found `u8` | - = note: expected type ` as Tr>::Ty` - found type `u8` + = note: expected associated type ` as Tr>::Ty` + found type `u8` + = note: consider constraining the associated type ` as Tr>::Ty` to `u8` or calling a method that returns ` 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:32 + --> $DIR/defaults-specialization.rs:89:32 | LL | let _: as Tr>::Ty = true; - | ^^^^ expected associated type, found bool + | ^^^^ expected associated type, found `bool` | - = note: expected type ` as Tr>::Ty` - found type `bool` + = note: expected associated type ` as Tr>::Ty` + found type `bool` + = note: consider constraining the associated type ` as Tr>::Ty` to `bool` or calling a method that returns ` 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 + --> $DIR/defaults-specialization.rs:90:33 | LL | let _: as Tr>::Ty = 0u8; - | ^^^ expected associated type, found u8 + | ^^^ expected associated type, found `u8` | - = note: expected type ` as Tr>::Ty` - found type `u8` + = note: expected associated type ` as Tr>::Ty` + found type `u8` + = note: consider constraining the associated type ` as Tr>::Ty` to `u8` or calling a method that returns ` 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:90:33 + --> $DIR/defaults-specialization.rs:91:33 | LL | let _: as Tr>::Ty = true; - | ^^^^ expected associated type, found bool + | ^^^^ expected associated type, found `bool` | - = note: expected type ` as Tr>::Ty` - found type `bool` + = note: expected associated type ` as Tr>::Ty` + found type `bool` + = note: consider constraining the associated type ` as Tr>::Ty` to `bool` or calling a method that returns ` 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 diff --git a/src/test/ui/associated-types/defaults-suitability.stderr b/src/test/ui/associated-types/defaults-suitability.stderr index dd45c9e443668..861f178fd194a 100644 --- a/src/test/ui/associated-types/defaults-suitability.stderr +++ b/src/test/ui/associated-types/defaults-suitability.stderr @@ -19,11 +19,13 @@ error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied --> $DIR/defaults-suitability.rs:35:15 | LL | trait Foo { - | ------------ required by `Foo` + | ------------ + | | | + | | help: consider restricting this bound: `T: std::clone::Clone` + | required by `Foo` LL | type Bar: Clone = Vec; | ^^^^^ the trait `std::clone::Clone` is not implemented for `T` | - = help: consider adding a `where T: std::clone::Clone` bound = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec` error[E0277]: the trait bound `(): Foo` is not satisfied @@ -82,22 +84,24 @@ error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not --> $DIR/defaults-suitability.rs:74:15 | LL | trait Foo2 { - | ------------- required by `Foo2` + | -------------- help: consider further restricting the associated type: `where >::Baz: std::clone::Clone` + | | + | required by `Foo2` LL | type Bar: Clone = Vec; | ^^^^^ the trait `std::clone::Clone` is not implemented for `>::Baz` | - = help: consider adding a `where >::Baz: std::clone::Clone` bound = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied --> $DIR/defaults-suitability.rs:83:15 | LL | trait Foo25 { - | --------------------- required by `Foo25` + | ---------------------- help: consider further restricting the associated type: `where >::Baz: std::clone::Clone` + | | + | required by `Foo25` LL | type Bar: Clone = Vec; | ^^^^^ the trait `std::clone::Clone` is not implemented for `>::Baz` | - = help: consider adding a `where >::Baz: std::clone::Clone` bound = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied @@ -106,14 +110,14 @@ error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied LL | / trait Foo3 where LL | | Self::Bar: Clone, LL | | Self::Baz: Clone, - | | ^^^^^ the trait `std::clone::Clone` is not implemented for `T` + | | ^^^^^ - help: consider further restricting type parameter `T`: `, T: std::clone::Clone` + | | | + | | the trait `std::clone::Clone` is not implemented for `T` LL | | ... | LL | | type Baz = T; LL | | } | |_- required by `Foo3` - | - = help: consider adding a `where T: std::clone::Clone` bound error[E0277]: the size for values of type `[u8]` cannot be known at compilation time --> $DIR/defaults-suitability.rs:29:5 diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr index e8eb085b79146..35164c4f3d37e 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr @@ -6,8 +6,6 @@ LL | trait UncheckedCopy: Sized { ... LL | type Output: Copy | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` - | - = help: consider adding a `where Self: std::marker::Copy` bound error[E0277]: cannot add-assign `&'static str` to `Self` --> $DIR/defaults-unsound-62211-1.rs:27:7 @@ -19,7 +17,6 @@ LL | + AddAssign<&'static str> | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` | = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self` - = help: consider adding a `where Self: std::ops::AddAssign<&'static str>` bound error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied --> $DIR/defaults-unsound-62211-1.rs:25:7 @@ -29,8 +26,6 @@ LL | trait UncheckedCopy: Sized { ... LL | + Deref | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` - | - = help: consider adding a `where Self: std::ops::Deref` bound error[E0277]: `Self` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-1.rs:30:7 @@ -43,42 +38,43 @@ LL | + Display = Self; | = 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 - = help: consider adding a `where Self: std::fmt::Display` bound error[E0277]: `T` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-1.rs:43:9 | LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter + | - ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter + | | + | help: consider restricting this bound: `T: std::fmt::Display` | = 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 adding a `where T: std::fmt::Display` bound error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied --> $DIR/defaults-unsound-62211-1.rs:43:9 | LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T` - | - = help: consider adding a `where T: std::ops::Deref` bound + | - ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T` + | | + | help: consider restricting this bound: `T: std::ops::Deref` error[E0277]: cannot add-assign `&'static str` to `T` --> $DIR/defaults-unsound-62211-1.rs:43:9 | LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ no implementation for `T += &'static str` + | - ^^^^^^^^^^^^^ no implementation for `T += &'static str` + | | + | help: consider restricting this bound: `T: std::ops::AddAssign<&'static str>` | = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `T` - = help: consider adding a `where T: std::ops::AddAssign<&'static str>` bound error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/defaults-unsound-62211-1.rs:43:9 | LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` - | - = help: consider adding a `where T: std::marker::Copy` bound + | - ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | | + | help: consider restricting this bound: `T: std::marker::Copy` error: aborting due to 8 previous errors diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr index a0b5d6b9cbb46..af66ee117a3a3 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr @@ -6,8 +6,6 @@ LL | trait UncheckedCopy: Sized { ... LL | type Output: Copy | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` - | - = help: consider adding a `where Self: std::marker::Copy` bound error[E0277]: cannot add-assign `&'static str` to `Self` --> $DIR/defaults-unsound-62211-2.rs:27:7 @@ -19,7 +17,6 @@ LL | + AddAssign<&'static str> | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` | = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self` - = help: consider adding a `where Self: std::ops::AddAssign<&'static str>` bound error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied --> $DIR/defaults-unsound-62211-2.rs:25:7 @@ -29,8 +26,6 @@ LL | trait UncheckedCopy: Sized { ... LL | + Deref | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` - | - = help: consider adding a `where Self: std::ops::Deref` bound error[E0277]: `Self` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-2.rs:30:7 @@ -43,42 +38,43 @@ LL | + Display = Self; | = 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 - = help: consider adding a `where Self: std::fmt::Display` bound error[E0277]: `T` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-2.rs:43:9 | LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter + | - ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter + | | + | help: consider restricting this bound: `T: std::fmt::Display` | = 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 adding a `where T: std::fmt::Display` bound error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied --> $DIR/defaults-unsound-62211-2.rs:43:9 | LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T` - | - = help: consider adding a `where T: std::ops::Deref` bound + | - ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T` + | | + | help: consider restricting this bound: `T: std::ops::Deref` error[E0277]: cannot add-assign `&'static str` to `T` --> $DIR/defaults-unsound-62211-2.rs:43:9 | LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ no implementation for `T += &'static str` + | - ^^^^^^^^^^^^^ no implementation for `T += &'static str` + | | + | help: consider restricting this bound: `T: std::ops::AddAssign<&'static str>` | = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `T` - = help: consider adding a `where T: std::ops::AddAssign<&'static str>` bound error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/defaults-unsound-62211-2.rs:43:9 | LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` - | - = help: consider adding a `where T: std::marker::Copy` bound + | - ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | | + | help: consider restricting this bound: `T: std::marker::Copy` error: aborting due to 8 previous errors diff --git a/src/test/ui/associated-types/issue-26681.stderr b/src/test/ui/associated-types/issue-26681.stderr index 27175a247fa8a..da10933df92b0 100644 --- a/src/test/ui/associated-types/issue-26681.stderr +++ b/src/test/ui/associated-types/issue-26681.stderr @@ -4,8 +4,10 @@ error[E0308]: mismatched types LL | const C: ::Bar = 6665; | ^^^^ expected associated type, found integer | - = note: expected type `<::Fv as Foo>::Bar` - found type `{integer}` + = note: expected associated type `<::Fv as Foo>::Bar` + found type `{integer}` + = note: consider constraining the associated type `<::Fv as Foo>::Bar` to `{integer}` or calling a method that returns `<::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 diff --git a/src/test/ui/associated-types/issue-63593.stderr b/src/test/ui/associated-types/issue-63593.stderr index 37dd52980d996..c27800f5a3fb1 100644 --- a/src/test/ui/associated-types/issue-63593.stderr +++ b/src/test/ui/associated-types/issue-63593.stderr @@ -8,7 +8,6 @@ LL | type This = Self; | = help: the trait `std::marker::Sized` is not implemented for `Self` = note: to learn more, visit - = help: consider adding a `where Self: std::marker::Sized` bound error: aborting due to previous error From 708f053807a0844d8d772d14a9d636b232ec5f90 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 24 Nov 2019 16:39:04 +0100 Subject: [PATCH 23/31] Add test for #65774 Closes #65774 --- src/test/ui/associated-types/issue-65774-1.rs | 57 +++++++++++++++++++ .../ui/associated-types/issue-65774-1.stderr | 17 ++++++ src/test/ui/associated-types/issue-65774-2.rs | 57 +++++++++++++++++++ .../ui/associated-types/issue-65774-2.stderr | 17 ++++++ 4 files changed, 148 insertions(+) create mode 100644 src/test/ui/associated-types/issue-65774-1.rs create mode 100644 src/test/ui/associated-types/issue-65774-1.stderr create mode 100644 src/test/ui/associated-types/issue-65774-2.rs create mode 100644 src/test/ui/associated-types/issue-65774-2.stderr diff --git a/src/test/ui/associated-types/issue-65774-1.rs b/src/test/ui/associated-types/issue-65774-1.rs new file mode 100644 index 0000000000000..e087da5d0ef40 --- /dev/null +++ b/src/test/ui/associated-types/issue-65774-1.rs @@ -0,0 +1,57 @@ +#![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<::MpuConfig> = None; + let valref: &mut ::MpuConfig = val.as_mut().unwrap(); + + // // This causes a different ICE (but its similar if you squint right): + // // + // // `Unimplemented` selecting `Binder()` during codegen + // + // writer.my_write(valref) + + // This one causes the ICE: + // FulfillmentError(Obligation(predicate=Binder(TraitPredicate()), depth=1),Unimplemented) + let closure = |config: &mut ::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(); +} diff --git a/src/test/ui/associated-types/issue-65774-1.stderr b/src/test/ui/associated-types/issue-65774-1.stderr new file mode 100644 index 0000000000000..559136be705e2 --- /dev/null +++ b/src/test/ui/associated-types/issue-65774-1.stderr @@ -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`. diff --git a/src/test/ui/associated-types/issue-65774-2.rs b/src/test/ui/associated-types/issue-65774-2.rs new file mode 100644 index 0000000000000..fba41fc0af797 --- /dev/null +++ b/src/test/ui/associated-types/issue-65774-2.rs @@ -0,0 +1,57 @@ +#![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<::MpuConfig> = None; + let valref: &mut ::MpuConfig = val.as_mut().unwrap(); + + // // This causes a different ICE (but its similar if you squint right): + // // + // // `Unimplemented` selecting `Binder()` during codegen + // + writer.my_write(valref) + + // This one causes the ICE: + // FulfillmentError(Obligation(predicate=Binder(TraitPredicate()), depth=1),Unimplemented) + /*let closure = |config: &mut ::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(); +} diff --git a/src/test/ui/associated-types/issue-65774-2.stderr b/src/test/ui/associated-types/issue-65774-2.stderr new file mode 100644 index 0000000000000..cb515964226a5 --- /dev/null +++ b/src/test/ui/associated-types/issue-65774-2.stderr @@ -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`. From a01846f0c37d705f527e39dbeac3f886d72c1a50 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 24 Nov 2019 17:08:48 +0100 Subject: [PATCH 24/31] appease tidy --- src/test/ui/associated-types/issue-65774-1.rs | 3 ++- src/test/ui/associated-types/issue-65774-2.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/ui/associated-types/issue-65774-1.rs b/src/test/ui/associated-types/issue-65774-1.rs index e087da5d0ef40..0ffd6cc2cf230 100644 --- a/src/test/ui/associated-types/issue-65774-1.rs +++ b/src/test/ui/associated-types/issue-65774-1.rs @@ -40,7 +40,8 @@ impl ProcessType for Process { // writer.my_write(valref) // This one causes the ICE: - // FulfillmentError(Obligation(predicate=Binder(TraitPredicate()), depth=1),Unimplemented) + // FulfillmentError(Obligation(predicate=Binder(TraitPredicate()), + // depth=1),Unimplemented) let closure = |config: &mut ::MpuConfig| writer.my_write(&config); closure(valref); } diff --git a/src/test/ui/associated-types/issue-65774-2.rs b/src/test/ui/associated-types/issue-65774-2.rs index fba41fc0af797..31e203a81d397 100644 --- a/src/test/ui/associated-types/issue-65774-2.rs +++ b/src/test/ui/associated-types/issue-65774-2.rs @@ -40,7 +40,8 @@ impl ProcessType for Process { writer.my_write(valref) // This one causes the ICE: - // FulfillmentError(Obligation(predicate=Binder(TraitPredicate()), depth=1),Unimplemented) + // FulfillmentError(Obligation(predicate=Binder(TraitPredicate()), + // depth=1),Unimplemented) /*let closure = |config: &mut ::MpuConfig| writer.my_write(&config); closure(valref);*/ } From ec501903994911892bb43c388564326b70b7104b Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 8 Dec 2019 13:34:52 +0100 Subject: [PATCH 25/31] Bless test output --- .../defaults-specialization.stderr | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/test/ui/associated-types/defaults-specialization.stderr b/src/test/ui/associated-types/defaults-specialization.stderr index 9b10940cbc485..15146d1a9c062 100644 --- a/src/test/ui/associated-types/defaults-specialization.stderr +++ b/src/test/ui/associated-types/defaults-specialization.stderr @@ -69,7 +69,9 @@ error[E0308]: mismatched types --> $DIR/defaults-specialization.rs:88:32 | LL | let _: as Tr>::Ty = 0u8; - | ^^^ expected associated type, found `u8` + | ----------------- ^^^ expected associated type, found `u8` + | | + | expected due to this | = note: expected associated type ` as Tr>::Ty` found type `u8` @@ -80,7 +82,9 @@ error[E0308]: mismatched types --> $DIR/defaults-specialization.rs:89:32 | LL | let _: as Tr>::Ty = true; - | ^^^^ expected associated type, found `bool` + | ----------------- ^^^^ expected associated type, found `bool` + | | + | expected due to this | = note: expected associated type ` as Tr>::Ty` found type `bool` @@ -91,7 +95,9 @@ error[E0308]: mismatched types --> $DIR/defaults-specialization.rs:90:33 | LL | let _: as Tr>::Ty = 0u8; - | ^^^ expected associated type, found `u8` + | ------------------ ^^^ expected associated type, found `u8` + | | + | expected due to this | = note: expected associated type ` as Tr>::Ty` found type `u8` @@ -102,7 +108,9 @@ error[E0308]: mismatched types --> $DIR/defaults-specialization.rs:91:33 | LL | let _: as Tr>::Ty = true; - | ^^^^ expected associated type, found `bool` + | ------------------ ^^^^ expected associated type, found `bool` + | | + | expected due to this | = note: expected associated type ` as Tr>::Ty` found type `bool` From 232c1f331c8703f6484e29b8da1cec9bb67f443e Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 5 Jan 2020 01:04:18 +0100 Subject: [PATCH 26/31] Format code --- src/librustc_typeck/check/wfcheck.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index a6189a346645d..b2169413f46ef 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -435,23 +435,18 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { /// /// 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, -) { +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 // `>::Assoc` to the default type. - let map = tcx.associated_items(trait_def_id) + let map = tcx + .associated_items(trait_def_id) .filter_map(|item| { if item.kind == ty::AssocKind::Type && item.defaultness.has_value() { // `>::Assoc` - let proj = ty::ProjectionTy { - substs, - item_def_id: item.def_id, - }; + 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)) From 9930e1ff0a889631f853a31838121600cea2b400 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 5 Jan 2020 02:12:16 +0100 Subject: [PATCH 27/31] Fix tests that fail with `--emit metadata` --- .../ui/associated-const/defaults-cyclic-fail.rs | 4 ++-- .../associated-const/defaults-cyclic-fail.stderr | 14 ++++++++++++-- .../associated-const/defaults-not-assumed-fail.rs | 2 +- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/test/ui/associated-const/defaults-cyclic-fail.rs b/src/test/ui/associated-const/defaults-cyclic-fail.rs index 0f54d67574d36..9b899ee316a0e 100644 --- a/src/test/ui/associated-const/defaults-cyclic-fail.rs +++ b/src/test/ui/associated-const/defaults-cyclic-fail.rs @@ -1,9 +1,9 @@ -// compile-fail +// build-fail // Cyclic assoc. const defaults don't error unless *used* trait Tr { const A: u8 = Self::B; - //~^ ERROR cycle detected when const-evaluating `Tr::A` + //~^ ERROR cycle detected when const-evaluating + checking `Tr::A` const B: u8 = Self::A; } diff --git a/src/test/ui/associated-const/defaults-cyclic-fail.stderr b/src/test/ui/associated-const/defaults-cyclic-fail.stderr index dee4620cdf692..940182d4aa676 100644 --- a/src/test/ui/associated-const/defaults-cyclic-fail.stderr +++ b/src/test/ui/associated-const/defaults-cyclic-fail.stderr @@ -1,15 +1,25 @@ -error[E0391]: cycle detected when const-evaluating `Tr::A` +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 `Tr::A`, completing the cycle + = 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 | diff --git a/src/test/ui/associated-const/defaults-not-assumed-fail.rs b/src/test/ui/associated-const/defaults-not-assumed-fail.rs index 27435ef34a0e9..5a0704231ad94 100644 --- a/src/test/ui/associated-const/defaults-not-assumed-fail.rs +++ b/src/test/ui/associated-const/defaults-not-assumed-fail.rs @@ -1,4 +1,4 @@ -// compile-fail +// build-fail trait Tr { const A: u8 = 255; From 4d4da926f2633de5da22e2aef7f693c3505aa206 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 15 Feb 2020 12:33:39 +0100 Subject: [PATCH 28/31] Fix rebase damage --- src/librustc_typeck/check/wfcheck.rs | 1 + .../defaults-not-assumed-fail.rs | 1 + .../defaults-not-assumed-fail.stderr | 12 ++++- .../defaults-cyclic-fail-1.stderr | 10 ++-- .../defaults-cyclic-fail-2.rs | 2 - .../defaults-cyclic-fail-2.stderr | 10 ++-- .../defaults-in-other-trait-items.stderr | 2 +- .../ui/associated-types/defaults-mixed.rs | 2 - .../ui/associated-types/defaults-mixed.stderr | 4 +- .../defaults-specialization.rs | 2 - .../defaults-specialization.stderr | 18 +++---- .../associated-types/defaults-suitability.rs | 2 - .../defaults-suitability.stderr | 42 ++++++++------- .../defaults-unsound-62211-1.rs | 2 - .../defaults-unsound-62211-1.stderr | 54 ++++++++++++------- .../defaults-unsound-62211-2.rs | 2 - .../defaults-unsound-62211-2.stderr | 54 ++++++++++++------- 17 files changed, 126 insertions(+), 94 deletions(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index b2169413f46ef..58820dcb381c5 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -443,6 +443,7 @@ fn check_associated_type_defaults(fcx: &FnCtxt<'_, '_>, trait_def_id: DefId) { // `>::Assoc` to the default type. let map = tcx .associated_items(trait_def_id) + .iter() .filter_map(|item| { if item.kind == ty::AssocKind::Type && item.defaultness.has_value() { // `>::Assoc` diff --git a/src/test/ui/associated-const/defaults-not-assumed-fail.rs b/src/test/ui/associated-const/defaults-not-assumed-fail.rs index 5a0704231ad94..d7a48cbd63ecc 100644 --- a/src/test/ui/associated-const/defaults-not-assumed-fail.rs +++ b/src/test/ui/associated-const/defaults-not-assumed-fail.rs @@ -32,6 +32,7 @@ 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!(::A, 254); assert_eq!(::B, 255); diff --git a/src/test/ui/associated-const/defaults-not-assumed-fail.stderr b/src/test/ui/associated-const/defaults-not-assumed-fail.stderr index 365ad3224105b..fe3721a910922 100644 --- a/src/test/ui/associated-const/defaults-not-assumed-fail.stderr +++ b/src/test/ui/associated-const/defaults-not-assumed-fail.stderr @@ -16,8 +16,16 @@ LL | assert_eq!(<() as Tr>::B, 0); // causes the error above | | | referenced constant has errors | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 2 previous errors +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`. diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr b/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr index 4f28a50701ad0..6a8526f6aad1b 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr +++ b/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr @@ -1,29 +1,29 @@ error[E0275]: overflow evaluating the requirement `<() as Tr>::B` - --> $DIR/defaults-cyclic-fail-1.rs:12:6 + --> $DIR/defaults-cyclic-fail-1.rs:10:6 | LL | impl Tr for () {} | ^^ error[E0275]: overflow evaluating the requirement `::B` - --> $DIR/defaults-cyclic-fail-1.rs:30:6 + --> $DIR/defaults-cyclic-fail-1.rs:28:6 | LL | impl Tr for bool { | ^^ error[E0275]: overflow evaluating the requirement `::B` - --> $DIR/defaults-cyclic-fail-1.rs:37:6 + --> $DIR/defaults-cyclic-fail-1.rs:35:6 | LL | impl Tr for usize { | ^^ error[E0275]: overflow evaluating the requirement `::B` - --> $DIR/defaults-cyclic-fail-1.rs:32:5 + --> $DIR/defaults-cyclic-fail-1.rs:30:5 | LL | type A = Box; | ^^^^^^^^^^^^^^^^^^^^^^ error[E0275]: overflow evaluating the requirement `::A` - --> $DIR/defaults-cyclic-fail-1.rs:39:5 + --> $DIR/defaults-cyclic-fail-1.rs:37:5 | LL | type B = &'static Self::A; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-2.rs b/src/test/ui/associated-types/defaults-cyclic-fail-2.rs index 2f2e84c60002a..05091e3f498c7 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-2.rs +++ b/src/test/ui/associated-types/defaults-cyclic-fail-2.rs @@ -1,5 +1,3 @@ -// compile-fail - #![feature(associated_type_defaults)] // A more complex version of `defaults-cyclic-fail-1.rs`, with non-trivial defaults. diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr b/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr index bbc130f11f729..78772df963885 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr +++ b/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr @@ -1,29 +1,29 @@ error[E0275]: overflow evaluating the requirement `<() as Tr>::B` - --> $DIR/defaults-cyclic-fail-2.rs:14:6 + --> $DIR/defaults-cyclic-fail-2.rs:12:6 | LL | impl Tr for () {} | ^^ error[E0275]: overflow evaluating the requirement `::B` - --> $DIR/defaults-cyclic-fail-2.rs:32:6 + --> $DIR/defaults-cyclic-fail-2.rs:30:6 | LL | impl Tr for bool { | ^^ error[E0275]: overflow evaluating the requirement `::B` - --> $DIR/defaults-cyclic-fail-2.rs:39:6 + --> $DIR/defaults-cyclic-fail-2.rs:37:6 | LL | impl Tr for usize { | ^^ error[E0275]: overflow evaluating the requirement `::B` - --> $DIR/defaults-cyclic-fail-2.rs:34:5 + --> $DIR/defaults-cyclic-fail-2.rs:32:5 | LL | type A = Box; | ^^^^^^^^^^^^^^^^^^^^^^ error[E0275]: overflow evaluating the requirement `::A` - --> $DIR/defaults-cyclic-fail-2.rs:41:5 + --> $DIR/defaults-cyclic-fail-2.rs:39:5 | LL | type B = &'static Self::A; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/associated-types/defaults-in-other-trait-items.stderr b/src/test/ui/associated-types/defaults-in-other-trait-items.stderr index b759276d2484b..9ecfe49c2b571 100644 --- a/src/test/ui/associated-types/defaults-in-other-trait-items.stderr +++ b/src/test/ui/associated-types/defaults-in-other-trait-items.stderr @@ -10,7 +10,7 @@ LL | let () = p; = 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:39:25 + --> $DIR/defaults-in-other-trait-items.rs:37:25 | LL | const C: Self::Ty = 0u8; | ^^^ expected associated type, found `u8` diff --git a/src/test/ui/associated-types/defaults-mixed.rs b/src/test/ui/associated-types/defaults-mixed.rs index 7601ab71e4a2b..c91b8de39f52e 100644 --- a/src/test/ui/associated-types/defaults-mixed.rs +++ b/src/test/ui/associated-types/defaults-mixed.rs @@ -1,5 +1,3 @@ -// compile-fail - #![feature(associated_type_defaults)] // Tests that a trait with one defaulted and one non-defaulted assoc. type behaves properly. diff --git a/src/test/ui/associated-types/defaults-mixed.stderr b/src/test/ui/associated-types/defaults-mixed.stderr index 2d31d1dbdfeef..69ddd5f2326d1 100644 --- a/src/test/ui/associated-types/defaults-mixed.stderr +++ b/src/test/ui/associated-types/defaults-mixed.stderr @@ -1,5 +1,5 @@ error[E0046]: not all trait items implemented, missing: `Bar` - --> $DIR/defaults-mixed.rs:13:1 + --> $DIR/defaults-mixed.rs:11:1 | LL | type Bar; | --------- `Bar` from trait @@ -8,7 +8,7 @@ LL | impl Trait for () {} | ^^^^^^^^^^^^^^^^^ missing `Bar` in implementation error[E0046]: not all trait items implemented, missing: `Bar` - --> $DIR/defaults-mixed.rs:16:1 + --> $DIR/defaults-mixed.rs:14:1 | LL | type Bar; | --------- `Bar` from trait diff --git a/src/test/ui/associated-types/defaults-specialization.rs b/src/test/ui/associated-types/defaults-specialization.rs index cb0d231bfcd7c..d0ed718b83923 100644 --- a/src/test/ui/associated-types/defaults-specialization.rs +++ b/src/test/ui/associated-types/defaults-specialization.rs @@ -1,7 +1,5 @@ //! Tests the interaction of associated type defaults and specialization. -// compile-fail - #![feature(associated_type_defaults, specialization)] trait Tr { diff --git a/src/test/ui/associated-types/defaults-specialization.stderr b/src/test/ui/associated-types/defaults-specialization.stderr index 15146d1a9c062..1dd536ec6360f 100644 --- a/src/test/ui/associated-types/defaults-specialization.stderr +++ b/src/test/ui/associated-types/defaults-specialization.stderr @@ -1,5 +1,5 @@ error[E0053]: method `make` has an incompatible type for trait - --> $DIR/defaults-specialization.rs:20:18 + --> $DIR/defaults-specialization.rs:18:18 | LL | fn make() -> Self::Ty { | -------- type in trait @@ -13,7 +13,7 @@ LL | fn make() -> u8 { 0 } = 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:36:18 + --> $DIR/defaults-specialization.rs:34:18 | LL | fn make() -> Self::Ty { | -------- type in trait @@ -27,7 +27,7 @@ LL | fn make() -> bool { true } = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:11:9 + --> $DIR/defaults-specialization.rs:9:9 | LL | fn make() -> Self::Ty { | -------- expected `::Ty` because of return type @@ -40,7 +40,7 @@ LL | 0u8 = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:27:29 + --> $DIR/defaults-specialization.rs:25:29 | LL | fn make() -> Self::Ty { 0u8 } | -------- ^^^ expected associated type, found `u8` @@ -53,7 +53,7 @@ LL | fn make() -> Self::Ty { 0u8 } = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:45:29 + --> $DIR/defaults-specialization.rs:43:29 | LL | fn make() -> Self::Ty { true } | -------- ^^^^ expected associated type, found `bool` @@ -66,7 +66,7 @@ LL | fn make() -> Self::Ty { true } = 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:32 + --> $DIR/defaults-specialization.rs:86:32 | LL | let _: as Tr>::Ty = 0u8; | ----------------- ^^^ expected associated type, found `u8` @@ -79,7 +79,7 @@ LL | let _: as Tr>::Ty = 0u8; = 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:32 + --> $DIR/defaults-specialization.rs:87:32 | LL | let _: as Tr>::Ty = true; | ----------------- ^^^^ expected associated type, found `bool` @@ -92,7 +92,7 @@ LL | let _: as Tr>::Ty = true; = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:90:33 + --> $DIR/defaults-specialization.rs:88:33 | LL | let _: as Tr>::Ty = 0u8; | ------------------ ^^^ expected associated type, found `u8` @@ -105,7 +105,7 @@ LL | let _: as Tr>::Ty = 0u8; = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:91:33 + --> $DIR/defaults-specialization.rs:89:33 | LL | let _: as Tr>::Ty = true; | ------------------ ^^^^ expected associated type, found `bool` diff --git a/src/test/ui/associated-types/defaults-suitability.rs b/src/test/ui/associated-types/defaults-suitability.rs index 5a128e56bcb14..2be01cba105ef 100644 --- a/src/test/ui/associated-types/defaults-suitability.rs +++ b/src/test/ui/associated-types/defaults-suitability.rs @@ -6,8 +6,6 @@ //! (eg. `type Assoc: Clone = NotClone`), and also against where clauses on //! the trait itself when possible -// compile-fail - #![feature(associated_type_defaults)] struct NotClone; diff --git a/src/test/ui/associated-types/defaults-suitability.stderr b/src/test/ui/associated-types/defaults-suitability.stderr index 861f178fd194a..60e1821b300d2 100644 --- a/src/test/ui/associated-types/defaults-suitability.stderr +++ b/src/test/ui/associated-types/defaults-suitability.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:17:14 + --> $DIR/defaults-suitability.rs:15:14 | LL | trait Tr { | -------- required by `Tr` @@ -7,7 +7,7 @@ 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:22:27 + --> $DIR/defaults-suitability.rs:20:27 | LL | trait Tr2 where Self::Ty: Clone { | --------------------------^^^^^ @@ -16,20 +16,22 @@ LL | trait Tr2 where Self::Ty: Clone { | required by `Tr2` error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:35:15 + --> $DIR/defaults-suitability.rs:33:15 | LL | trait Foo { - | ------------ - | | | - | | help: consider restricting this bound: `T: std::clone::Clone` - | required by `Foo` + | ------------ required by `Foo` LL | type Bar: Clone = Vec; | ^^^^^ 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 { + | ^ = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec` error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/defaults-suitability.rs:41:17 + --> $DIR/defaults-suitability.rs:39:17 | LL | trait Bar: Sized { | ---------------- required by `Bar` @@ -38,7 +40,7 @@ LL | type Assoc: Foo = (); | ^^^^^^^^^ the trait `Foo` is not implemented for `()` error[E0277]: the trait bound `NotClone: IsU8` is not satisfied - --> $DIR/defaults-suitability.rs:61:18 + --> $DIR/defaults-suitability.rs:59:18 | LL | / trait D where LL | | Vec: Clone, @@ -51,7 +53,7 @@ LL | | } | |_- required by `D` error[E0277]: the trait bound `bool: IsU8` is not satisfied - --> $DIR/defaults-suitability.rs:63:11 + --> $DIR/defaults-suitability.rs:61:11 | LL | / trait D where LL | | Vec: Clone, @@ -66,7 +68,7 @@ LL | | } | |_- required by `D` error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:59:23 + --> $DIR/defaults-suitability.rs:57:23 | LL | / trait D where LL | | Vec: Clone, @@ -81,7 +83,7 @@ LL | | } = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec` error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:74:15 + --> $DIR/defaults-suitability.rs:72:15 | LL | trait Foo2 { | -------------- help: consider further restricting the associated type: `where >::Baz: std::clone::Clone` @@ -93,7 +95,7 @@ LL | type Bar: Clone = Vec; = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:83:15 + --> $DIR/defaults-suitability.rs:81:15 | LL | trait Foo25 { | ---------------------- help: consider further restricting the associated type: `where >::Baz: std::clone::Clone` @@ -105,22 +107,26 @@ LL | type Bar: Clone = Vec; = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:92:16 + --> $DIR/defaults-suitability.rs:90:16 | LL | / trait Foo3 where LL | | Self::Bar: Clone, LL | | Self::Baz: Clone, - | | ^^^^^ - help: consider further restricting type parameter `T`: `, T: std::clone::Clone` - | | | - | | the trait `std::clone::Clone` is not implemented for `T` + | | ^^^^^ 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 where + | ^ error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/defaults-suitability.rs:29:5 + --> $DIR/defaults-suitability.rs:27:5 | LL | type Ty = Vec<[u8]>; | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.rs b/src/test/ui/associated-types/defaults-unsound-62211-1.rs index 37d52ed16b61c..c8b4734d6edc5 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-1.rs +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.rs @@ -7,8 +7,6 @@ //! Note that the underlying cause of this is still not yet fixed. //! See: https://github.com/rust-lang/rust/issues/33017 -// compile-fail - #![feature(associated_type_defaults)] use std::{ diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr index 35164c4f3d37e..9c4a126013942 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:23:18 + --> $DIR/defaults-unsound-62211-1.rs:21:18 | LL | trait UncheckedCopy: Sized { | -------------------------- required by `UncheckedCopy` @@ -8,7 +8,7 @@ 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:27:7 + --> $DIR/defaults-unsound-62211-1.rs:25:7 | LL | trait UncheckedCopy: Sized { | -------------------------- required by `UncheckedCopy` @@ -19,7 +19,7 @@ LL | + AddAssign<&'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:25:7 + --> $DIR/defaults-unsound-62211-1.rs:23:7 | LL | trait UncheckedCopy: Sized { | -------------------------- required by `UncheckedCopy` @@ -28,7 +28,7 @@ LL | + Deref | ^^^^^^^^^^^^^^^^^^^ 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:30:7 + --> $DIR/defaults-unsound-62211-1.rs:28:7 | LL | trait UncheckedCopy: Sized { | -------------------------- required by `UncheckedCopy` @@ -40,41 +40,55 @@ LL | + Display = 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:43:9 + --> $DIR/defaults-unsound-62211-1.rs:41:9 | LL | impl UncheckedCopy for T {} - | - ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter - | | - | help: consider restricting this bound: `T: std::fmt::Display` + | ^^^^^^^^^^^^^ `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 UncheckedCopy for T {} + | ^ error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:43:9 + --> $DIR/defaults-unsound-62211-1.rs:41:9 + | +LL | impl 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 UncheckedCopy for T {} - | - ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T` - | | - | help: consider restricting this bound: `T: std::ops::Deref` + | ^ error[E0277]: cannot add-assign `&'static str` to `T` - --> $DIR/defaults-unsound-62211-1.rs:43:9 + --> $DIR/defaults-unsound-62211-1.rs:41:9 | LL | impl UncheckedCopy for T {} - | - ^^^^^^^^^^^^^ no implementation for `T += &'static str` - | | - | help: consider restricting this bound: `T: std::ops::AddAssign<&'static str>` + | ^^^^^^^^^^^^^ 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 UncheckedCopy for T {} + | ^ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:43:9 + --> $DIR/defaults-unsound-62211-1.rs:41:9 + | +LL | impl 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 UncheckedCopy for T {} - | - ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` - | | - | help: consider restricting this bound: `T: std::marker::Copy` + | ^ error: aborting due to 8 previous errors diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.rs b/src/test/ui/associated-types/defaults-unsound-62211-2.rs index d042a1478a3aa..aa343e759a8f5 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-2.rs +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.rs @@ -7,8 +7,6 @@ //! Note that the underlying cause of this is still not yet fixed. //! See: https://github.com/rust-lang/rust/issues/33017 -// compile-fail - #![feature(associated_type_defaults)] use std::{ diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr index af66ee117a3a3..4602fbc99fa62 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:23:18 + --> $DIR/defaults-unsound-62211-2.rs:21:18 | LL | trait UncheckedCopy: Sized { | -------------------------- required by `UncheckedCopy` @@ -8,7 +8,7 @@ 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:27:7 + --> $DIR/defaults-unsound-62211-2.rs:25:7 | LL | trait UncheckedCopy: Sized { | -------------------------- required by `UncheckedCopy` @@ -19,7 +19,7 @@ LL | + AddAssign<&'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:25:7 + --> $DIR/defaults-unsound-62211-2.rs:23:7 | LL | trait UncheckedCopy: Sized { | -------------------------- required by `UncheckedCopy` @@ -28,7 +28,7 @@ LL | + Deref | ^^^^^^^^^^^^^^^^^^^ 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:30:7 + --> $DIR/defaults-unsound-62211-2.rs:28:7 | LL | trait UncheckedCopy: Sized { | -------------------------- required by `UncheckedCopy` @@ -40,41 +40,55 @@ LL | + Display = 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:43:9 + --> $DIR/defaults-unsound-62211-2.rs:41:9 | LL | impl UncheckedCopy for T {} - | - ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter - | | - | help: consider restricting this bound: `T: std::fmt::Display` + | ^^^^^^^^^^^^^ `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 UncheckedCopy for T {} + | ^ error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:43:9 + --> $DIR/defaults-unsound-62211-2.rs:41:9 + | +LL | impl 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 UncheckedCopy for T {} - | - ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T` - | | - | help: consider restricting this bound: `T: std::ops::Deref` + | ^ error[E0277]: cannot add-assign `&'static str` to `T` - --> $DIR/defaults-unsound-62211-2.rs:43:9 + --> $DIR/defaults-unsound-62211-2.rs:41:9 | LL | impl UncheckedCopy for T {} - | - ^^^^^^^^^^^^^ no implementation for `T += &'static str` - | | - | help: consider restricting this bound: `T: std::ops::AddAssign<&'static str>` + | ^^^^^^^^^^^^^ 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 UncheckedCopy for T {} + | ^ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:43:9 + --> $DIR/defaults-unsound-62211-2.rs:41:9 + | +LL | impl 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 UncheckedCopy for T {} - | - ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` - | | - | help: consider restricting this bound: `T: std::marker::Copy` + | ^ error: aborting due to 8 previous errors From af2931bdfef3cbb977ebb639e70ed09a1b8afdd8 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 21 Feb 2020 19:43:03 +0100 Subject: [PATCH 29/31] Mark E0399 test as obsolete --- src/librustc_error_codes/error_codes/E0399.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0399.md b/src/librustc_error_codes/error_codes/E0399.md index 71482c3ca64c8..55e1774d9ca98 100644 --- a/src/librustc_error_codes/error_codes/E0399.md +++ b/src/librustc_error_codes/error_codes/E0399.md @@ -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 +```ignore #![feature(associated_type_defaults)] pub trait Foo { @@ -20,7 +22,7 @@ impl Foo for i32 { To fix this, add an implementation for each default method from the trait: -``` +```ignore #![feature(associated_type_defaults)] pub trait Foo { From c60583163a9401382bda1ddcad4d3c377539866d Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 21 Feb 2020 21:46:15 +0100 Subject: [PATCH 30/31] Fix rebase fallout --- src/librustc_typeck/check/wfcheck.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 58820dcb381c5..2061c4f8c9cd8 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -443,7 +443,7 @@ fn check_associated_type_defaults(fcx: &FnCtxt<'_, '_>, trait_def_id: DefId) { // `>::Assoc` to the default type. let map = tcx .associated_items(trait_def_id) - .iter() + .in_definition_order() .filter_map(|item| { if item.kind == ty::AssocKind::Type && item.defaultness.has_value() { // `>::Assoc` From 6cc268b9efcfa6d74e20b0c95e715cb05f41b19e Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 21 Feb 2020 21:46:30 +0100 Subject: [PATCH 31/31] Mark E0399.md as obsolete --- src/librustc_error_codes/error_codes/E0399.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0399.md b/src/librustc_error_codes/error_codes/E0399.md index 55e1774d9ca98..6ea6054b41779 100644 --- a/src/librustc_error_codes/error_codes/E0399.md +++ b/src/librustc_error_codes/error_codes/E0399.md @@ -1,11 +1,11 @@ -Note: This error code is no longer emitted by the compiler. +#### 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: -```ignore +``` #![feature(associated_type_defaults)] pub trait Foo { @@ -22,7 +22,7 @@ impl Foo for i32 { To fix this, add an implementation for each default method from the trait: -```ignore +``` #![feature(associated_type_defaults)] pub trait Foo {