diff --git a/src/librustc_error_codes/error_codes/E0399.md b/src/librustc_error_codes/error_codes/E0399.md index 71482c3ca64c8..6ea6054b41779 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 +``` #![feature(associated_type_defaults)] pub trait Foo { 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/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 12e6087dbafd6..c13e1e5b668ab 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -425,10 +425,109 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { for_item(tcx, item).with_fcx(|fcx, _| { check_where_clauses(tcx, fcx, item.span, trait_def_id, None); + check_associated_type_defaults(fcx, trait_def_id); + vec![] }); } +/// Checks all associated type defaults of trait `trait_def_id`. +/// +/// Assuming the defaults are used, check that all predicates (bounds on the +/// assoc type and where clauses on the trait) hold. +fn check_associated_type_defaults(fcx: &FnCtxt<'_, '_>, trait_def_id: DefId) { + let tcx = fcx.tcx; + let substs = InternalSubsts::identity_for_item(tcx, trait_def_id); + + // For all assoc. types with defaults, build a map from + // `>::Assoc` to the default type. + let map = tcx + .associated_items(trait_def_id) + .in_definition_order() + .filter_map(|item| { + if item.kind == ty::AssocKind::Type && item.defaultness.has_value() { + // `>::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::>(); + + /// 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. + /// + /// 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>>, + } + + impl<'tcx> ty::fold::TypeFolder<'tcx> for DefaultNormalizer<'tcx> { + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + self.tcx + } + + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + match t.kind { + ty::Projection(proj_ty) => { + if let Some(default) = self.map.get(&proj_ty) { + default + } else { + t.super_fold_with(self) + } + } + _ => t.super_fold_with(self), + } + } + } + + // Now take all predicates defined on the trait, replace any mention of + // the assoc. types with their default, and prove them. + // We only consider predicates that directly mention the assoc. type. + let mut norm = DefaultNormalizer { tcx, map }; + let predicates = fcx.tcx.predicates_of(trait_def_id); + for &(orig_pred, span) in predicates.predicates.iter() { + let pred = orig_pred.fold_with(&mut norm); + if pred != orig_pred { + // Mentions one of the defaulted assoc. types + debug!("default suitability check: proving predicate: {} -> {}", orig_pred, pred); + let pred = fcx.normalize_associated_types_in(span, &pred); + let cause = traits::ObligationCause::new( + span, + fcx.body_id, + traits::ItemObligation(trait_def_id), + ); + let obligation = traits::Obligation::new(cause, fcx.param_env, pred); + + fcx.register_predicate(obligation); + } + } +} + fn check_item_fn(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { for_item(tcx, item).with_fcx(|fcx, tcx| { let def_id = fcx.tcx.hir().local_def_id(item.hir_id); 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..9b899ee316a0e --- /dev/null +++ b/src/test/ui/associated-const/defaults-cyclic-fail.rs @@ -0,0 +1,17 @@ +// build-fail + +// Cyclic assoc. const defaults don't error unless *used* +trait Tr { + const A: u8 = Self::B; + //~^ ERROR cycle detected when const-evaluating + checking `Tr::A` + + const B: u8 = Self::A; +} + +// This impl is *allowed* unless its assoc. consts are used +impl Tr for () {} + +fn main() { + // This triggers the cycle error + assert_eq!(<() as Tr>::A, 0); +} 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..940182d4aa676 --- /dev/null +++ b/src/test/ui/associated-const/defaults-cyclic-fail.stderr @@ -0,0 +1,31 @@ +error[E0391]: cycle detected when const-evaluating + checking `Tr::A` + --> $DIR/defaults-cyclic-fail.rs:5:5 + | +LL | const A: u8 = Self::B; + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires const-evaluating `Tr::A`... + --> $DIR/defaults-cyclic-fail.rs:5:19 + | +LL | const A: u8 = Self::B; + | ^^^^^^^ +note: ...which requires const-evaluating + checking `Tr::B`... + --> $DIR/defaults-cyclic-fail.rs:8:5 + | +LL | const B: u8 = Self::A; + | ^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating `Tr::B`... + --> $DIR/defaults-cyclic-fail.rs:8:19 + | +LL | const B: u8 = Self::A; + | ^^^^^^^ + = note: ...which again requires const-evaluating + checking `Tr::A`, completing the cycle +note: cycle used when const-evaluating `main` + --> $DIR/defaults-cyclic-fail.rs:16:16 + | +LL | assert_eq!(<() as Tr>::A, 0); + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. 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..82105f25f9240 --- /dev/null +++ b/src/test/ui/associated-const/defaults-cyclic-pass.rs @@ -0,0 +1,36 @@ +// run-pass + +// Cyclic assoc. const defaults don't error unless *used* +trait Tr { + const A: u8 = Self::B; + const B: u8 = Self::A; +} + +// This impl is *allowed* unless its assoc. consts are used, matching the +// behavior without defaults. +impl Tr for () {} + +// Overriding either constant breaks the cycle +impl Tr for u8 { + const A: u8 = 42; +} + +impl Tr for u16 { + const B: u8 = 0; +} + +impl Tr for u32 { + const A: u8 = 100; + const B: u8 = 123; +} + +fn main() { + assert_eq!(::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..d7a48cbd63ecc --- /dev/null +++ b/src/test/ui/associated-const/defaults-not-assumed-fail.rs @@ -0,0 +1,45 @@ +// build-fail + +trait Tr { + const A: u8 = 255; + + // This should not be a constant evaluation error (overflow). The value of + // `Self::A` must not be assumed to hold inside the trait. + const B: u8 = Self::A + 1; + //~^ ERROR any use of this value will cause an error +} + +// An impl that doesn't override any constant will NOT cause a const eval error +// just because it's defined, but only if the bad constant is used anywhere. +// This matches the behavior without defaults. +impl Tr for () {} + +// An impl that overrides either constant with a suitable value will be fine. +impl Tr for u8 { + const A: u8 = 254; +} + +impl Tr for u16 { + const B: u8 = 0; +} + +impl Tr for u32 { + const A: u8 = 254; + const B: u8 = 0; +} + +fn main() { + assert_eq!(<() as Tr>::A, 255); + assert_eq!(<() as Tr>::B, 0); // causes the error above + //~^ ERROR evaluation of constant expression failed + //~| ERROR erroneous constant used + + assert_eq!(::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..fe3721a910922 --- /dev/null +++ b/src/test/ui/associated-const/defaults-not-assumed-fail.stderr @@ -0,0 +1,31 @@ +error: any use of this value will cause an error + --> $DIR/defaults-not-assumed-fail.rs:8:19 + | +LL | const B: u8 = Self::A + 1; + | --------------^^^^^^^^^^^- + | | + | attempt to add with overflow + | + = note: `#[deny(const_err)]` on by default + +error[E0080]: evaluation of constant expression failed + --> $DIR/defaults-not-assumed-fail.rs:33:5 + | +LL | assert_eq!(<() as Tr>::B, 0); // causes the error above + | ^^^^^^^^^^^-------------^^^^^ + | | + | referenced constant has errors + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: erroneous constant used + --> $DIR/defaults-not-assumed-fail.rs:33:5 + | +LL | assert_eq!(<() as Tr>::B, 0); // causes the error above + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0080`. 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); +} 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..3e12c92289618 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,9 @@ pub trait Tr { impl Tr for () { type Assoc = (); - //~^ ERROR need to be reimplemented as `Assoc` was overridden: `Assoc2`, `C`, `foo` } -fn main() {} +fn main() { + let _: <() as Tr>::Assoc = (); + let _: <() as Tr>::Assoc2 = (); +} 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-1.rs b/src/test/ui/associated-types/defaults-cyclic-fail-1.rs new file mode 100644 index 0000000000000..71ac914ef5759 --- /dev/null +++ b/src/test/ui/associated-types/defaults-cyclic-fail-1.rs @@ -0,0 +1,45 @@ +#![feature(associated_type_defaults)] + +// Having a cycle in assoc. type defaults is okay... +trait Tr { + type A = Self::B; + type B = Self::A; +} + +// ...but is an error in any impl that doesn't override at least one of the defaults +impl Tr for () {} +//~^ ERROR overflow evaluating the requirement + +// As soon as at least one is redefined, it works: +impl Tr for u8 { + type A = u8; +} + +impl Tr for u16 { + type B = (); +} + +impl Tr for u32 { + type A = (); + type B = u8; +} + +// ...but only if this actually breaks the cycle +impl Tr for bool { +//~^ ERROR overflow evaluating the requirement + type A = Box; + //~^ ERROR overflow evaluating the requirement +} +// (the error is shown twice for some reason) + +impl Tr for usize { +//~^ ERROR overflow evaluating the requirement + type B = &'static Self::A; + //~^ ERROR overflow evaluating the requirement +} + +fn main() { + // We don't check that the types project correctly because the cycle errors stop compilation + // before `main` is type-checked. + // `defaults-cyclic-pass-1.rs` does this. +} 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..6a8526f6aad1b --- /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:10:6 + | +LL | impl Tr for () {} + | ^^ + +error[E0275]: overflow evaluating the requirement `::B` + --> $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:35:6 + | +LL | impl Tr for usize { + | ^^ + +error[E0275]: overflow evaluating the requirement `::B` + --> $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:37:5 + | +LL | type B = &'static Self::A; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0275`. 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..05091e3f498c7 --- /dev/null +++ b/src/test/ui/associated-types/defaults-cyclic-fail-2.rs @@ -0,0 +1,47 @@ +#![feature(associated_type_defaults)] + +// A more complex version of `defaults-cyclic-fail-1.rs`, with non-trivial defaults. + +// Having a cycle in assoc. type defaults is okay... +trait Tr { + type A = Vec; + 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..78772df963885 --- /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:12:6 + | +LL | impl Tr for () {} + | ^^ + +error[E0275]: overflow evaluating the requirement `::B` + --> $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:37:6 + | +LL | impl Tr for usize { + | ^^ + +error[E0275]: overflow evaluating the requirement `::B` + --> $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: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-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-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..a3bfcd8efe29a --- /dev/null +++ b/src/test/ui/associated-types/defaults-in-other-trait-items-pass.rs @@ -0,0 +1,37 @@ +// check-pass + +#![feature(associated_type_defaults)] + +trait Tr { + type Item = u8; + type Container = Vec; +} + +impl Tr for () {} + +impl Tr for u16 { + type Item = u16; +} + +impl Tr for String { + type Container = String; +} + +impl Tr for usize { + type Item = u32; + type Container = Vec<()>; +} + +fn main() { + let _container: <() as Tr>::Container = Vec::::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; +} 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..9f2e8aca47712 --- /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 the associated type + //~| NOTE for more information, visit + } +} + +// An impl that doesn't override the type *can* assume the default. +impl Tr for () { + fn f(p: Self::A) { + let () = p; + } +} + +impl Tr for u8 { + type A = (); + + fn f(p: Self::A) { + let () = p; + } +} + +trait AssocConst { + type Ty = u8; + + // Assoc. consts also cannot assume that default types hold + const C: Self::Ty = 0u8; + //~^ ERROR mismatched types + //~| NOTE expected associated type, found `u8` + //~| NOTE expected associated type `::Ty` + //~| NOTE consider constraining the associated type + //~| NOTE for more information, visit +} + +// An impl can, however +impl AssocConst for () { + const C: Self::Ty = 0u8; +} + +fn main() {} 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/associated-types/defaults-mixed.rs b/src/test/ui/associated-types/defaults-mixed.rs new file mode 100644 index 0000000000000..c91b8de39f52e --- /dev/null +++ b/src/test/ui/associated-types/defaults-mixed.rs @@ -0,0 +1,34 @@ +#![feature(associated_type_defaults)] + +// Tests that a trait with one defaulted and one non-defaulted assoc. type behaves properly. + +trait Trait { + type Foo = u8; + type Bar; +} + +// `Bar` must be specified +impl Trait for () {} +//~^ error: not all trait items implemented, missing: `Bar` + +impl Trait for bool { +//~^ error: not all trait items implemented, missing: `Bar` + type Foo = (); +} + +impl Trait for u8 { + type Bar = (); +} + +impl Trait for u16 { + type Foo = String; + type Bar = bool; +} + +fn main() { + let _: ::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..69ddd5f2326d1 --- /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:11:1 + | +LL | type Bar; + | --------- `Bar` from trait +... +LL | impl Trait for () {} + | ^^^^^^^^^^^^^^^^^ missing `Bar` in implementation + +error[E0046]: not all trait items implemented, missing: `Bar` + --> $DIR/defaults-mixed.rs:14:1 + | +LL | type Bar; + | --------- `Bar` from trait +... +LL | impl Trait for bool { + | ^^^^^^^^^^^^^^^^^^^ missing `Bar` in implementation + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0046`. 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..d0ed718b83923 --- /dev/null +++ b/src/test/ui/associated-types/defaults-specialization.rs @@ -0,0 +1,95 @@ +//! Tests the interaction of associated type defaults and specialization. + +#![feature(associated_type_defaults, specialization)] + +trait Tr { + type Ty = u8; + + fn make() -> Self::Ty { + 0u8 + //~^ error: mismatched types + } +} + +struct A(T); +// 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 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 { + default type Ty = bool; + + fn make() -> bool { true } + //~^ 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 { + 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 } +} + +struct E(T); +impl Tr for E { + default type Ty = bool; + default fn make() -> Self::Ty { panic!(); } +} + +// This impl specializes and sets `Ty`, it can rely on `Ty=String`. +impl Tr for E { + 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 new file mode 100644 index 0000000000000..1dd536ec6360f --- /dev/null +++ b/src/test/ui/associated-types/defaults-specialization.stderr @@ -0,0 +1,123 @@ +error[E0053]: method `make` has an incompatible type for trait + --> $DIR/defaults-specialization.rs:18:18 + | +LL | fn make() -> Self::Ty { + | -------- type in trait +... +LL | fn make() -> u8 { 0 } + | ^^ expected associated type, found `u8` + | + = note: expected fn pointer `fn() -> 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:34:18 + | +LL | fn make() -> Self::Ty { + | -------- type in trait +... +LL | fn make() -> bool { true } + | ^^^^ expected associated type, found `bool` + | + = note: expected fn pointer `fn() -> 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:9:9 + | +LL | fn make() -> Self::Ty { + | -------- expected `::Ty` because of return type +LL | 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[E0308]: mismatched types + --> $DIR/defaults-specialization.rs:25:29 + | +LL | fn make() -> Self::Ty { 0u8 } + | -------- ^^^ expected associated type, found `u8` + | | + | expected ` as Tr>::Ty` because of return type + | + = 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:43:29 + | +LL | fn make() -> Self::Ty { true } + | -------- ^^^^ expected associated type, found `bool` + | | + | expected ` as Tr>::Ty` because of return type + | + = 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:86:32 + | +LL | let _: as Tr>::Ty = 0u8; + | ----------------- ^^^ expected associated type, found `u8` + | | + | expected due to this + | + = 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:87:32 + | +LL | let _: as Tr>::Ty = true; + | ----------------- ^^^^ expected associated type, found `bool` + | | + | expected due to this + | + = 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:88:33 + | +LL | let _: as Tr>::Ty = 0u8; + | ------------------ ^^^ expected associated type, found `u8` + | | + | expected due to this + | + = 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:89:33 + | +LL | let _: as Tr>::Ty = true; + | ------------------ ^^^^ expected associated type, found `bool` + | | + | expected due to this + | + = 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 + +Some errors have detailed explanations: E0053, E0308. +For more information about an error, try `rustc --explain E0053`. 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..2be01cba105ef --- /dev/null +++ b/src/test/ui/associated-types/defaults-suitability.rs @@ -0,0 +1,106 @@ +//! Checks that associated type defaults are properly validated. +//! +//! This means: +//! * Default types are wfchecked +//! * Default types are checked against where clauses on the assoc. type +//! (eg. `type Assoc: Clone = NotClone`), and also against where clauses on +//! the trait itself when possible + +#![feature(associated_type_defaults)] + +struct NotClone; + +// Assoc. type bounds must hold for the default type +trait Tr { + type Ty: Clone = NotClone; + //~^ ERROR the trait bound `NotClone: std::clone::Clone` is not satisfied +} + +// Where-clauses defined on the trait must also be considered +trait Tr2 where Self::Ty: Clone { + //~^ ERROR the trait bound `NotClone: std::clone::Clone` is not satisfied + type Ty = NotClone; +} + +// Independent of where-clauses (there are none here), default types must always be wf +trait Tr3 { + type Ty = Vec<[u8]>; + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time +} + +// Involved type parameters must fulfill all bounds required by defaults that mention them +trait Foo { + 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; +} + +// 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 Baz = T; +} + +// Adding a `T: Clone` bound doesn't help since the requirement doesn't see `T` +// because of the shallow substitution. If we did a deep substitution instead, +// this would be accepted. +trait Foo25 { + 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 + T: Clone, +{ + type Bar: Clone = Vec; + type Baz: Clone = T; +} + +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..60e1821b300d2 --- /dev/null +++ b/src/test/ui/associated-types/defaults-suitability.stderr @@ -0,0 +1,140 @@ +error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:15:14 + | +LL | trait Tr { + | -------- required by `Tr` +LL | type Ty: Clone = NotClone; + | ^^^^^ the trait `std::clone::Clone` is not implemented for `NotClone` + +error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:20:27 + | +LL | trait Tr2 where Self::Ty: Clone { + | --------------------------^^^^^ + | | | + | | the trait `std::clone::Clone` is not implemented for `NotClone` + | required by `Tr2` + +error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:33:15 + | +LL | trait Foo { + | ------------ 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:39: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 `()` + +error[E0277]: the trait bound `NotClone: IsU8` is not satisfied + --> $DIR/defaults-suitability.rs:59:18 + | +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:61:11 + | +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:57:23 + | +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:72:15 + | +LL | trait 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` + | + = 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:81:15 + | +LL | trait 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` + | + = 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:90:16 + | +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 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:27:5 + | +LL | type Ty = Vec<[u8]>; + | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `[u8]` + = note: to learn more, visit + = note: required by `std::vec::Vec` + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0277`. 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..c8b4734d6edc5 --- /dev/null +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.rs @@ -0,0 +1,63 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/62211 +//! +//! The old implementation of defaults did not check whether the provided +//! default actually fulfills all bounds on the assoc. type, leading to +//! unsoundness, demonstrated here as a use-after-free. +//! +//! Note that the underlying cause of this is still not yet fixed. +//! See: https://github.com/rust-lang/rust/issues/33017 + +#![feature(associated_type_defaults)] + +use std::{ + fmt::Display, + ops::{AddAssign, Deref} +}; + + +trait UncheckedCopy: Sized { + // This Output is said to be Copy. Yet we default to Self + // and it's accepted, not knowing if Self ineed is Copy + type Output: Copy + //~^ ERROR the trait bound `Self: std::marker::Copy` is not satisfied + + Deref + //~^ 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..9c4a126013942 --- /dev/null +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr @@ -0,0 +1,95 @@ +error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied + --> $DIR/defaults-unsound-62211-1.rs:21:18 + | +LL | trait UncheckedCopy: Sized { + | -------------------------- required by `UncheckedCopy` +... +LL | type Output: Copy + | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` + +error[E0277]: cannot add-assign `&'static str` to `Self` + --> $DIR/defaults-unsound-62211-1.rs:25:7 + | +LL | trait UncheckedCopy: Sized { + | -------------------------- required by `UncheckedCopy` +... +LL | + AddAssign<&'static str> + | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` + | + = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self` + +error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied + --> $DIR/defaults-unsound-62211-1.rs:23:7 + | +LL | trait UncheckedCopy: Sized { + | -------------------------- required by `UncheckedCopy` +... +LL | + Deref + | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` + +error[E0277]: `Self` doesn't implement `std::fmt::Display` + --> $DIR/defaults-unsound-62211-1.rs:28:7 + | +LL | trait UncheckedCopy: Sized { + | -------------------------- required by `UncheckedCopy` +... +LL | + Display = Self; + | ^^^^^^^ `Self` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `Self` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + +error[E0277]: `T` doesn't implement `std::fmt::Display` + --> $DIR/defaults-unsound-62211-1.rs:41:9 + | +LL | impl UncheckedCopy for T {} + | ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `T` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +help: consider restricting this type parameter with `T: std::fmt::Display` + --> $DIR/defaults-unsound-62211-1.rs:41:6 + | +LL | impl UncheckedCopy for T {} + | ^ + +error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied + --> $DIR/defaults-unsound-62211-1.rs:41:9 + | +LL | impl 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 {} + | ^ + +error[E0277]: cannot add-assign `&'static str` to `T` + --> $DIR/defaults-unsound-62211-1.rs:41: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 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: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 {} + | ^ + +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..aa343e759a8f5 --- /dev/null +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.rs @@ -0,0 +1,63 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/62211 +//! +//! The old implementation of defaults did not check whether the provided +//! default actually fulfills all bounds on the assoc. type, leading to +//! unsoundness and ICEs, the latter being demonstrated here. +//! +//! Note that the underlying cause of this is still not yet fixed. +//! See: https://github.com/rust-lang/rust/issues/33017 + +#![feature(associated_type_defaults)] + +use std::{ + fmt::Display, + ops::{AddAssign, Deref} +}; + + +trait UncheckedCopy: Sized { + // This Output is said to be Copy. Yet we default to Self + // and it's accepted, not knowing if Self ineed is Copy + type Output: Copy + //~^ ERROR the trait bound `Self: std::marker::Copy` is not satisfied + + Deref + //~^ 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..4602fbc99fa62 --- /dev/null +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr @@ -0,0 +1,95 @@ +error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied + --> $DIR/defaults-unsound-62211-2.rs:21:18 + | +LL | trait UncheckedCopy: Sized { + | -------------------------- required by `UncheckedCopy` +... +LL | type Output: Copy + | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` + +error[E0277]: cannot add-assign `&'static str` to `Self` + --> $DIR/defaults-unsound-62211-2.rs:25:7 + | +LL | trait UncheckedCopy: Sized { + | -------------------------- required by `UncheckedCopy` +... +LL | + AddAssign<&'static str> + | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` + | + = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self` + +error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied + --> $DIR/defaults-unsound-62211-2.rs:23:7 + | +LL | trait UncheckedCopy: Sized { + | -------------------------- required by `UncheckedCopy` +... +LL | + Deref + | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` + +error[E0277]: `Self` doesn't implement `std::fmt::Display` + --> $DIR/defaults-unsound-62211-2.rs:28:7 + | +LL | trait UncheckedCopy: Sized { + | -------------------------- required by `UncheckedCopy` +... +LL | + Display = Self; + | ^^^^^^^ `Self` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `Self` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + +error[E0277]: `T` doesn't implement `std::fmt::Display` + --> $DIR/defaults-unsound-62211-2.rs:41:9 + | +LL | impl UncheckedCopy for T {} + | ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `T` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +help: consider restricting this type parameter with `T: std::fmt::Display` + --> $DIR/defaults-unsound-62211-2.rs:41:6 + | +LL | impl UncheckedCopy for T {} + | ^ + +error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied + --> $DIR/defaults-unsound-62211-2.rs:41:9 + | +LL | impl 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 {} + | ^ + +error[E0277]: cannot add-assign `&'static str` to `T` + --> $DIR/defaults-unsound-62211-2.rs:41: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 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: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 {} + | ^ + +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/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..da10933df92b0 --- /dev/null +++ b/src/test/ui/associated-types/issue-26681.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-26681.rs:17:39 + | +LL | const C: ::Bar = 6665; + | ^^^^ expected associated type, found 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 + +For more information about this error, try `rustc --explain E0308`. 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..75a5b3f3551cb --- /dev/null +++ b/src/test/ui/associated-types/issue-43924.stderr @@ -0,0 +1,23 @@ +error[E0277]: the trait bound `(dyn std::string::ToString + 'static): std::default::Default` is not satisfied + --> $DIR/issue-43924.rs:7:15 + | +LL | trait Foo { + | -------------------------------- required by `Foo` +LL | type Out: Default + ToString + ?Sized = dyn ToString; + | ^^^^^^^ the trait `std::default::Default` is not implemented for `(dyn std::string::ToString + 'static)` + +error[E0277]: the trait bound `(dyn std::string::ToString + 'static): std::default::Default` is not satisfied + --> $DIR/issue-43924.rs:10:6 + | +LL | impl Foo 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-54182-1.rs b/src/test/ui/associated-types/issue-54182-1.rs new file mode 100644 index 0000000000000..1a1e98cbac27f --- /dev/null +++ b/src/test/ui/associated-types/issue-54182-1.rs @@ -0,0 +1,92 @@ +// run-pass + +// Tests that the return type of trait methods is correctly normalized when +// checking that a method in an impl matches the trait definition when the +// return type involves a defaulted associated type. +// ie. the trait has a method with return type `-> Self::R`, and `type R = ()`, +// but the impl leaves out the return type (resulting in `()`). +// Note that specialization is not involved in this test; no items in +// implementations may be overridden. If they were, the normalization wouldn't +// happen. + +#![feature(associated_type_defaults)] + +macro_rules! overload { + ($a:expr, $b:expr) => { + overload::overload2($a, $b) + }; + ($a:expr, $b:expr, $c:expr) => { + overload::overload3($a, $b, $c) + } +} + +fn main() { + let () = overload!(42, true); + + let r: f32 = overload!("Hello world", 13.0); + assert_eq!(r, 13.0); + + let () = overload!(42, true, 42.5); + + let r: i32 = overload!("Hello world", 13.0, 42); + assert_eq!(r, 42); +} + +mod overload { + /// This trait has an assoc. type defaulting to `()`, and a required method returning a value + /// of that assoc. type. + pub trait Overload { + // type R; + type R = (); + fn overload(self) -> Self::R; + } + + // overloads for 2 args + impl Overload for (i32, bool) { + // type R = (); + + /// This function has no return type specified, and so defaults to `()`. + /// + /// This should work, but didn't, until RFC 2532 was implemented. + fn overload(self) /*-> Self::R*/ { + let (a, b) = self; // destructure args + println!("i32 and bool {:?}", (a, b)); + } + } + impl<'a> Overload for (&'a str, f32) { + type R = f32; + fn overload(self) -> Self::R { + let (a, b) = self; // destructure args + println!("&str and f32 {:?}", (a, b)); + b + } + } + + // overloads for 3 args + impl Overload for (i32, bool, f32) { + // type R = (); + fn overload(self) /*-> Self::R*/ { + let (a, b, c) = self; // destructure args + println!("i32 and bool and f32 {:?}", (a, b, c)); + } + } + impl<'a> Overload for (&'a str, f32, i32) { + type R = i32; + fn overload(self) -> Self::R { + let (a, b, c) = self; // destructure args + println!("&str and f32 and i32: {:?}", (a, b, c)); + c + } + } + + // overloads for more args + // ... + + pub fn overload2(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..c88c766313671 --- /dev/null +++ b/src/test/ui/associated-types/issue-54182-2.rs @@ -0,0 +1,19 @@ +// check-pass + +// Before RFC 2532, normalizing a defaulted assoc. type didn't work at all, +// unless the impl in question overrides that type, which makes the default +// pointless. + +#![feature(associated_type_defaults)] + +trait Tr { + type Assoc = (); +} + +impl Tr for () {} + +fn f(thing: <() as Tr>::Assoc) { + let c: () = thing; +} + +fn main() {} 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..8dbc24c067320 --- /dev/null +++ b/src/test/ui/associated-types/issue-63593.rs @@ -0,0 +1,13 @@ +#![feature(associated_type_defaults)] + +// Tests that `Self` is not assumed to implement `Sized` when used as an +// associated type default. + +trait Inner {} + +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 new file mode 100644 index 0000000000000..c27800f5a3fb1 --- /dev/null +++ b/src/test/ui/associated-types/issue-63593.stderr @@ -0,0 +1,14 @@ +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/issue-63593.rs:9:5 + | +LL | trait MyTrait { + | ------------- required by `MyTrait` +LL | type This = Self; + | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `Self` + = note: to learn more, visit + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. 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..0ffd6cc2cf230 --- /dev/null +++ b/src/test/ui/associated-types/issue-65774-1.rs @@ -0,0 +1,58 @@ +#![feature(associated_type_defaults)] + +trait MyDisplay { fn method(&self) { } } + +impl<'a, T: MyDisplay> MyDisplay for &'a mut T { } + +struct T; + +trait MPU { + type MpuConfig: MyDisplay = T; + //~^ ERROR the trait bound `T: MyDisplay` is not satisfied +} + +struct S; + +impl MPU for S { } +//~^ ERROR the trait bound `T: MyDisplay` is not satisfied + +trait MyWrite { + fn my_write(&self, _: &dyn MyDisplay) { } +} + +trait ProcessType { + fn process_detail_fmt(&self, _: &mut dyn MyWrite); +} + +struct Process; + +impl ProcessType for Process { + fn process_detail_fmt(&self, writer: &mut dyn MyWrite) + { + + let mut val: Option<::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..31e203a81d397 --- /dev/null +++ b/src/test/ui/associated-types/issue-65774-2.rs @@ -0,0 +1,58 @@ +#![feature(associated_type_defaults)] + +trait MyDisplay { fn method(&self) { } } + +impl<'a, T: MyDisplay> MyDisplay for &'a mut T { } + +struct T; + +trait MPU { + type MpuConfig: MyDisplay = T; + //~^ ERROR the trait bound `T: MyDisplay` is not satisfied +} + +struct S; + +impl MPU for S { } +//~^ ERROR the trait bound `T: MyDisplay` is not satisfied + +trait MyWrite { + fn my_write(&self, _: &dyn MyDisplay) { } +} + +trait ProcessType { + fn process_detail_fmt(&self, _: &mut dyn MyWrite); +} + +struct Process; + +impl ProcessType for Process { + fn process_detail_fmt(&self, writer: &mut dyn MyWrite) + { + + let mut val: Option<::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`. 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 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