From 2cd5030ef592a2d4094145060c031dcae66e624f Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 18 Sep 2019 00:09:19 +0200 Subject: [PATCH 1/8] Deny specializing items not in the parent impl --- src/liballoc/boxed.rs | 5 ++ src/librustc/traits/project.rs | 4 +- src/librustc/traits/specialize/mod.rs | 2 +- .../traits/specialize/specialization_graph.rs | 63 ++++++++++++------- src/librustc/traits/util.rs | 5 +- src/librustc_typeck/check/mod.rs | 55 +++++++++++++--- .../auxiliary/cross_crates_defaults.rs | 4 +- src/test/ui/specialization/issue-36804.rs | 4 ++ .../specialization-default-methods.rs | 5 +- 9 files changed, 104 insertions(+), 43 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index b2789a535fe49..adbc0e6ba2c06 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -871,6 +871,11 @@ impl Iterator for Box { fn nth(&mut self, n: usize) -> Option { (**self).nth(n) } + default fn last(self) -> Option { + let mut last = None; + for x in self { last = Some(x); } + last + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index a7bb29c699e0e..c6255e56b6d1d 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1505,8 +1505,8 @@ fn assoc_ty_def( if let Some(assoc_item) = trait_def .ancestors(tcx, impl_def_id) - .defs(tcx, assoc_ty_name, ty::AssocKind::Type, trait_def_id) - .next() { + .leaf_def(tcx, assoc_ty_name, ty::AssocKind::Type) { + assoc_item } else { // This is saying that neither the trait nor diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index f0389bb037ac5..9c80ef7d4a23e 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -125,7 +125,7 @@ pub fn find_associated_item<'tcx>( let trait_def = tcx.trait_def(trait_def_id); let ancestors = trait_def.ancestors(tcx, impl_data.impl_def_id); - match ancestors.defs(tcx, item.ident, item.kind, trait_def_id).next() { + match ancestors.leaf_def(tcx, item.ident, item.kind) { Some(node_item) => { let substs = tcx.infer_ctxt().enter(|infcx| { let param_env = param_env.with_reveal_all(); diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index 43f558d64430e..0febdbe161d47 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -7,7 +7,6 @@ use crate::traits; use crate::ty::{self, TyCtxt, TypeFoldable}; use crate::ty::fast_reject::{self, SimplifiedType}; use syntax::ast::Ident; -use crate::util::captures::Captures; use crate::util::nodemap::{DefIdMap, FxHashMap}; /// A per-trait graph of impls in specialization order. At the moment, this @@ -419,6 +418,35 @@ impl<'tcx> Node { tcx.associated_items(self.def_id()) } + /// Finds an associated item defined in this node. + /// + /// If this returns `None`, the item can potentially still be found in + /// parents of this node. + pub fn item( + &self, + tcx: TyCtxt<'tcx>, + trait_item_name: Ident, + trait_item_kind: ty::AssocKind, + trait_def_id: DefId, + ) -> Option { + use crate::ty::AssocKind::*; + + tcx.associated_items(self.def_id()) + .find(move |impl_item| match (trait_item_kind, impl_item.kind) { + | (Const, Const) + | (Method, Method) + | (Type, Type) + | (Type, OpaqueTy) + => tcx.hygienic_eq(impl_item.ident, trait_item_name, trait_def_id), + + | (Const, _) + | (Method, _) + | (Type, _) + | (OpaqueTy, _) + => false, + }) + } + pub fn def_id(&self) -> DefId { match *self { Node::Impl(did) => did, @@ -427,6 +455,7 @@ impl<'tcx> Node { } } +#[derive(Copy, Clone)] pub struct Ancestors<'tcx> { trait_def_id: DefId, specialization_graph: &'tcx Graph, @@ -465,32 +494,18 @@ impl NodeItem { } impl<'tcx> Ancestors<'tcx> { - /// Search the items from the given ancestors, returning each definition - /// with the given name and the given kind. - // FIXME(#35870): avoid closures being unexported due to `impl Trait`. - #[inline] - pub fn defs( - self, + /// Finds the bottom-most (ie. most specialized) definition of an associated + /// item. + pub fn leaf_def( + mut self, tcx: TyCtxt<'tcx>, trait_item_name: Ident, trait_item_kind: ty::AssocKind, - trait_def_id: DefId, - ) -> impl Iterator> + Captures<'tcx> + 'tcx { - self.flat_map(move |node| { - use crate::ty::AssocKind::*; - node.items(tcx).filter(move |impl_item| match (trait_item_kind, impl_item.kind) { - | (Const, Const) - | (Method, Method) - | (Type, Type) - | (Type, OpaqueTy) - => tcx.hygienic_eq(impl_item.ident, trait_item_name, trait_def_id), - - | (Const, _) - | (Method, _) - | (Type, _) - | (OpaqueTy, _) - => false, - }).map(move |item| NodeItem { node: node, item: item }) + ) -> Option> { + let trait_def_id = self.trait_def_id; + self.find_map(|node| { + node.item(tcx, trait_item_name, trait_item_kind, trait_def_id) + .map(|item| NodeItem { node, item }) }) } } diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 18ec2241b2df8..d8b1effe09bf4 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -4,7 +4,6 @@ use syntax_pos::Span; use crate::hir; use crate::hir::def_id::DefId; -use crate::traits::specialize::specialization_graph::NodeItem; use crate::ty::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef}; use crate::ty::outlives::Component; use crate::ty::subst::{GenericArg, Subst, SubstsRef}; @@ -667,8 +666,8 @@ impl<'tcx> TyCtxt<'tcx> { } } - pub fn impl_item_is_final(self, node_item: &NodeItem) -> bool { - node_item.item.is_final() && !self.impl_is_default(node_item.node.def_id()) + pub fn impl_item_is_final(self, assoc_item: &ty::AssocItem) -> bool { + assoc_item.defaultness.is_final() && !self.impl_is_default(assoc_item.container.id()) } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7380bf7536de5..f130ee821d17c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1713,8 +1713,6 @@ fn check_specialization_validity<'tcx>( impl_id: DefId, impl_item: &hir::ImplItem, ) { - let ancestors = trait_def.ancestors(tcx, impl_id); - let kind = match impl_item.kind { hir::ImplItemKind::Const(..) => ty::AssocKind::Const, hir::ImplItemKind::Method(..) => ty::AssocKind::Method, @@ -1722,15 +1720,53 @@ fn check_specialization_validity<'tcx>( hir::ImplItemKind::TyAlias(_) => ty::AssocKind::Type, }; - let parent = ancestors.defs(tcx, trait_item.ident, kind, trait_def.def_id).nth(1) - .map(|node_item| node_item.map(|parent| parent.defaultness)); + let mut ancestor_impls = trait_def.ancestors(tcx, impl_id) + .skip(1) + .filter_map(|parent| { + if parent.is_from_trait() { + None + } else { + Some((parent, parent.item(tcx, trait_item.ident, kind, trait_def.def_id))) + } + }) + .peekable(); - if let Some(parent) = parent { - if tcx.impl_item_is_final(&parent) { - report_forbidden_specialization(tcx, impl_item, parent.node.def_id()); - } + if ancestor_impls.peek().is_none() { + // No parent, nothing to specialize. + return; } + let opt_result = ancestor_impls.find_map(|(parent_impl, parent_item)| { + match parent_item { + // Parent impl exists, and contains the parent item we're trying to specialize, but + // doesn't mark it `default`. + Some(parent_item) if tcx.impl_item_is_final(&parent_item) => { + Some(Err(parent_impl.def_id())) + } + + // Parent impl contains item and makes it specializable. + Some(_) => { + Some(Ok(())) + } + + // Parent impl doesn't mention the item. This means it's inherited from the + // grandparent. In that case, if parent is a `default impl`, inherited items use the + // "defaultness" from the grandparent, else they are final. + None => if tcx.impl_is_default(parent_impl.def_id()) { + None + } else { + Some(Err(parent_impl.def_id())) + } + } + }); + + // If `opt_result` is `None`, we have only encoutered `default impl`s that don't contain the + // item. This is allowed, the item isn't actually getting specialized here. + let result = opt_result.unwrap_or(Ok(())); + + if let Err(parent_impl) = result { + report_forbidden_specialization(tcx, impl_item, parent_impl); + } } fn check_impl_items_against_trait<'tcx>( @@ -1846,8 +1882,7 @@ fn check_impl_items_against_trait<'tcx>( let associated_type_overridden = overridden_associated_type.is_some(); for trait_item in tcx.associated_items(impl_trait_ref.def_id) { let is_implemented = trait_def.ancestors(tcx, impl_id) - .defs(tcx, trait_item.ident, trait_item.kind, impl_trait_ref.def_id) - .next() + .leaf_def(tcx, trait_item.ident, trait_item.kind) .map(|node_item| !node_item.node.is_from_trait()) .unwrap_or(false); diff --git a/src/test/ui/specialization/auxiliary/cross_crates_defaults.rs b/src/test/ui/specialization/auxiliary/cross_crates_defaults.rs index 5cf975b5752f0..1e5555355c3b3 100644 --- a/src/test/ui/specialization/auxiliary/cross_crates_defaults.rs +++ b/src/test/ui/specialization/auxiliary/cross_crates_defaults.rs @@ -22,7 +22,9 @@ pub trait Bar { fn bar(&self) -> i32 { 0 } } -impl Bar for T {} // use the provided method +impl Bar for T { + default fn bar(&self) -> i32 { 0 } +} impl Bar for i32 { fn bar(&self) -> i32 { 1 } diff --git a/src/test/ui/specialization/issue-36804.rs b/src/test/ui/specialization/issue-36804.rs index 36cb939bc48fb..9546a5dd5f516 100644 --- a/src/test/ui/specialization/issue-36804.rs +++ b/src/test/ui/specialization/issue-36804.rs @@ -13,6 +13,10 @@ where fn next(&mut self) -> Option { unimplemented!() } + + default fn count(self) -> usize where Self: Sized { + self.fold(0, |cnt, _| cnt + 1) + } } impl<'a, I, T: 'a> Iterator for Cloned diff --git a/src/test/ui/specialization/specialization-default-methods.rs b/src/test/ui/specialization/specialization-default-methods.rs index 5d65a0457e791..9ae3d1e9f3931 100644 --- a/src/test/ui/specialization/specialization-default-methods.rs +++ b/src/test/ui/specialization/specialization-default-methods.rs @@ -55,8 +55,9 @@ trait Bar { // / \ // Vec $Vec -// use the provided method -impl Bar for T {} +impl Bar for T { + default fn bar(&self) -> i32 { 0 } +} impl Bar for i32 { fn bar(&self) -> i32 { 1 } From 55277d4a6ebbf1de00437c268cbf6caf07ddf458 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 18 Sep 2019 23:00:59 +0200 Subject: [PATCH 2/8] Add comment to `Type` and `OpaqueTy` match --- src/librustc/traits/specialize/specialization_graph.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index 0febdbe161d47..c64d6748ea97d 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -436,7 +436,7 @@ impl<'tcx> Node { | (Const, Const) | (Method, Method) | (Type, Type) - | (Type, OpaqueTy) + | (Type, OpaqueTy) // assoc. types can be made opaque in impls => tcx.hygienic_eq(impl_item.ident, trait_item_name, trait_def_id), | (Const, _) From 02f36e52a656f1baa717538e18ae96137cbc83f9 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 18 Sep 2019 23:41:57 +0200 Subject: [PATCH 3/8] Hide the `Iterator` specialization behind a trait --- src/liballoc/boxed.rs | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index adbc0e6ba2c06..9b5d9431ae204 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -871,16 +871,33 @@ impl Iterator for Box { fn nth(&mut self, n: usize) -> Option { (**self).nth(n) } + fn last(self) -> Option { + BoxIter::last(self) + } +} + +trait BoxIter { + type Item; + fn last(self) -> Option; +} + +impl BoxIter for Box { + type Item = I::Item; default fn last(self) -> Option { - let mut last = None; - for x in self { last = Some(x); } - last + #[inline] + fn some(_: Option, x: T) -> Option { + Some(x) + } + + self.fold(None, some) } } +/// Specialization for sized `I`s that uses `I`s implementation of `last()` +/// instead of the default. #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for Box { - fn last(self) -> Option where I: Sized { +impl BoxIter for Box { + fn last(self) -> Option { (*self).last() } } From 9aaef06cf6a0c4e671c51f0d13a4ae6cf8b8dec5 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 19 Sep 2019 00:14:02 +0200 Subject: [PATCH 4/8] Fix the bootstrap --- src/librustc/ty/query/config.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index 91082c59ba05a..c4b7b9d29b96f 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -73,6 +73,14 @@ impl<'tcx, M: QueryAccessors<'tcx, Key = DefId>> QueryDescription<'tcx> for M { format!("processing {:?} with query `{}`", def_id, name).into() } } + + default fn cache_on_disk(_: TyCtxt<'tcx>, _: Self::Key, _: Option<&Self::Value>) -> bool { + false + } + + default fn try_load_from_disk(_: TyCtxt<'tcx>, _: SerializedDepNodeIndex) -> Option { + bug!("QueryDescription::load_from_disk() called for an unsupported query.") + } } impl<'tcx> QueryDescription<'tcx> for queries::analysis<'tcx> { From a0cf5315ef516c4f79bea39c5446a3a6ef6a0d24 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 19 Sep 2019 00:37:28 +0200 Subject: [PATCH 5/8] Test that we get the proper errors --- .../specialization-default-methods-fail.rs | 43 +++++++++++++++++++ ...specialization-default-methods-fail.stderr | 27 ++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 src/test/ui/specialization/specialization-default-methods-fail.rs create mode 100644 src/test/ui/specialization/specialization-default-methods-fail.stderr diff --git a/src/test/ui/specialization/specialization-default-methods-fail.rs b/src/test/ui/specialization/specialization-default-methods-fail.rs new file mode 100644 index 0000000000000..3bd2d31ef6351 --- /dev/null +++ b/src/test/ui/specialization/specialization-default-methods-fail.rs @@ -0,0 +1,43 @@ +// compile-fail + +#![feature(specialization)] + +// Test that attempting to override a non-default method or one not in the +// parent impl causes an error + +trait Foo { + fn foo(&self) -> bool { true } +} + +// Specialization tree for Foo: +// +// Box Vec +// / \ / \ +// Box Box Vec<()> Vec + +impl Foo for Box { + fn foo(&self) -> bool { false } +} + +// Allowed +impl Foo for Box {} + +// Can't override a non-`default` fn +impl Foo for Box { + fn foo(&self) -> bool { true } + //~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` +} + + +// Doesn't mention the method = provided body is used and the method is final +impl Foo for Vec {} + +// Allowed +impl Foo for Vec<()> {} + +impl Foo for Vec { + fn foo(&self) -> bool { true } + //~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` +} + +fn main() {} diff --git a/src/test/ui/specialization/specialization-default-methods-fail.stderr b/src/test/ui/specialization/specialization-default-methods-fail.stderr new file mode 100644 index 0000000000000..f962ccca83d06 --- /dev/null +++ b/src/test/ui/specialization/specialization-default-methods-fail.stderr @@ -0,0 +1,27 @@ +error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-default-methods-fail.rs:27:5 + | +LL | / impl Foo for Box { +LL | | fn foo(&self) -> bool { false } +LL | | } + | |_- parent `impl` is here +... +LL | fn foo(&self) -> bool { true } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo` + | + = note: to specialize, `foo` in the parent `impl` must be marked `default` + +error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-default-methods-fail.rs:39:5 + | +LL | impl Foo for Vec {} + | ------------------------- parent `impl` is here +... +LL | fn foo(&self) -> bool { true } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo` + | + = note: to specialize, `foo` in the parent `impl` must be marked `default` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0520`. From 98f02b23628d3b46e25f83634d5db2ffbe8ee725 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 19 Sep 2019 00:42:50 +0200 Subject: [PATCH 6/8] Pacify tidy --- src/librustc/ty/query/config.rs | 5 ++++- .../ui/specialization/specialization-default-methods-fail.rs | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index c4b7b9d29b96f..c1c6a655d96a9 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -78,7 +78,10 @@ impl<'tcx, M: QueryAccessors<'tcx, Key = DefId>> QueryDescription<'tcx> for M { false } - default fn try_load_from_disk(_: TyCtxt<'tcx>, _: SerializedDepNodeIndex) -> Option { + default fn try_load_from_disk( + _: TyCtxt<'tcx>, + _: SerializedDepNodeIndex, + ) -> Option { bug!("QueryDescription::load_from_disk() called for an unsupported query.") } } diff --git a/src/test/ui/specialization/specialization-default-methods-fail.rs b/src/test/ui/specialization/specialization-default-methods-fail.rs index 3bd2d31ef6351..c50982141884e 100644 --- a/src/test/ui/specialization/specialization-default-methods-fail.rs +++ b/src/test/ui/specialization/specialization-default-methods-fail.rs @@ -25,7 +25,7 @@ impl Foo for Box {} // Can't override a non-`default` fn impl Foo for Box { fn foo(&self) -> bool { true } - //~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` +//~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` } @@ -37,7 +37,7 @@ impl Foo for Vec<()> {} impl Foo for Vec { fn foo(&self) -> bool { true } - //~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` +//~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` } fn main() {} From 33d23cdf042af4a2b8acd32098114ad7e8ac8f5e Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 19 Sep 2019 00:54:47 +0200 Subject: [PATCH 7/8] Extend test and fix nits --- .../specialization-default-methods-fail.rs | 20 +++++-- ...specialization-default-methods-fail.stderr | 60 ++++++++++++++++++- 2 files changed, 72 insertions(+), 8 deletions(-) diff --git a/src/test/ui/specialization/specialization-default-methods-fail.rs b/src/test/ui/specialization/specialization-default-methods-fail.rs index c50982141884e..403f718d7dd9f 100644 --- a/src/test/ui/specialization/specialization-default-methods-fail.rs +++ b/src/test/ui/specialization/specialization-default-methods-fail.rs @@ -1,11 +1,11 @@ -// compile-fail - -#![feature(specialization)] +#![feature(specialization, associated_type_defaults)] // Test that attempting to override a non-default method or one not in the -// parent impl causes an error +// parent impl causes an error. trait Foo { + type Ty = (); + const CONST: u8 = 123; fn foo(&self) -> bool { true } } @@ -16,6 +16,8 @@ trait Foo { // Box Box Vec<()> Vec impl Foo for Box { + type Ty = bool; + const CONST: u8 = 0; fn foo(&self) -> bool { false } } @@ -24,18 +26,26 @@ impl Foo for Box {} // Can't override a non-`default` fn impl Foo for Box { + type Ty = Vec<()>; +//~^ error: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` + const CONST: u8 = 42; +//~^ error: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` fn foo(&self) -> bool { true } //~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` } -// Doesn't mention the method = provided body is used and the method is final +// Doesn't mention the item = provided body/value is used and the method is final. impl Foo for Vec {} // Allowed impl Foo for Vec<()> {} impl Foo for Vec { + type Ty = Vec<()>; +//~^ error: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` + const CONST: u8 = 42; +//~^ error: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` fn foo(&self) -> bool { true } //~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` } diff --git a/src/test/ui/specialization/specialization-default-methods-fail.stderr b/src/test/ui/specialization/specialization-default-methods-fail.stderr index f962ccca83d06..f215191a8cece 100644 --- a/src/test/ui/specialization/specialization-default-methods-fail.stderr +++ b/src/test/ui/specialization/specialization-default-methods-fail.stderr @@ -1,7 +1,39 @@ +error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-default-methods-fail.rs:29:5 + | +LL | / impl Foo for Box { +LL | | type Ty = bool; +LL | | const CONST: u8 = 0; +LL | | fn foo(&self) -> bool { false } +LL | | } + | |_- parent `impl` is here +... +LL | type Ty = Vec<()>; + | ^^^^^^^^^^^^^^^^^^ cannot specialize default item `Ty` + | + = note: to specialize, `Ty` in the parent `impl` must be marked `default` + +error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-default-methods-fail.rs:31:5 + | +LL | / impl Foo for Box { +LL | | type Ty = bool; +LL | | const CONST: u8 = 0; +LL | | fn foo(&self) -> bool { false } +LL | | } + | |_- parent `impl` is here +... +LL | const CONST: u8 = 42; + | ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `CONST` + | + = note: to specialize, `CONST` in the parent `impl` must be marked `default` + error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-default-methods-fail.rs:27:5 + --> $DIR/specialization-default-methods-fail.rs:33:5 | LL | / impl Foo for Box { +LL | | type Ty = bool; +LL | | const CONST: u8 = 0; LL | | fn foo(&self) -> bool { false } LL | | } | |_- parent `impl` is here @@ -11,8 +43,30 @@ LL | fn foo(&self) -> bool { true } | = note: to specialize, `foo` in the parent `impl` must be marked `default` +error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-default-methods-fail.rs:45:5 + | +LL | impl Foo for Vec {} + | ------------------------- parent `impl` is here +... +LL | type Ty = Vec<()>; + | ^^^^^^^^^^^^^^^^^^ cannot specialize default item `Ty` + | + = note: to specialize, `Ty` in the parent `impl` must be marked `default` + +error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-default-methods-fail.rs:47:5 + | +LL | impl Foo for Vec {} + | ------------------------- parent `impl` is here +... +LL | const CONST: u8 = 42; + | ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `CONST` + | + = note: to specialize, `CONST` in the parent `impl` must be marked `default` + error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-default-methods-fail.rs:39:5 + --> $DIR/specialization-default-methods-fail.rs:49:5 | LL | impl Foo for Vec {} | ------------------------- parent `impl` is here @@ -22,6 +76,6 @@ LL | fn foo(&self) -> bool { true } | = note: to specialize, `foo` in the parent `impl` must be marked `default` -error: aborting due to 2 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0520`. From 47f89e7485ed7a76d8bfcbedcad07fd6b74fa927 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 19 Sep 2019 01:04:23 +0200 Subject: [PATCH 8/8] Rename the test --- ...lt-methods-fail.rs => non-defaulted-item-fail.rs} | 0 ...ds-fail.stderr => non-defaulted-item-fail.stderr} | 12 ++++++------ 2 files changed, 6 insertions(+), 6 deletions(-) rename src/test/ui/specialization/{specialization-default-methods-fail.rs => non-defaulted-item-fail.rs} (100%) rename src/test/ui/specialization/{specialization-default-methods-fail.stderr => non-defaulted-item-fail.stderr} (89%) diff --git a/src/test/ui/specialization/specialization-default-methods-fail.rs b/src/test/ui/specialization/non-defaulted-item-fail.rs similarity index 100% rename from src/test/ui/specialization/specialization-default-methods-fail.rs rename to src/test/ui/specialization/non-defaulted-item-fail.rs diff --git a/src/test/ui/specialization/specialization-default-methods-fail.stderr b/src/test/ui/specialization/non-defaulted-item-fail.stderr similarity index 89% rename from src/test/ui/specialization/specialization-default-methods-fail.stderr rename to src/test/ui/specialization/non-defaulted-item-fail.stderr index f215191a8cece..e6c5fc1441b2f 100644 --- a/src/test/ui/specialization/specialization-default-methods-fail.stderr +++ b/src/test/ui/specialization/non-defaulted-item-fail.stderr @@ -1,5 +1,5 @@ error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-default-methods-fail.rs:29:5 + --> $DIR/non-defaulted-item-fail.rs:29:5 | LL | / impl Foo for Box { LL | | type Ty = bool; @@ -14,7 +14,7 @@ LL | type Ty = Vec<()>; = note: to specialize, `Ty` in the parent `impl` must be marked `default` error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-default-methods-fail.rs:31:5 + --> $DIR/non-defaulted-item-fail.rs:31:5 | LL | / impl Foo for Box { LL | | type Ty = bool; @@ -29,7 +29,7 @@ LL | const CONST: u8 = 42; = note: to specialize, `CONST` in the parent `impl` must be marked `default` error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-default-methods-fail.rs:33:5 + --> $DIR/non-defaulted-item-fail.rs:33:5 | LL | / impl Foo for Box { LL | | type Ty = bool; @@ -44,7 +44,7 @@ LL | fn foo(&self) -> bool { true } = note: to specialize, `foo` in the parent `impl` must be marked `default` error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-default-methods-fail.rs:45:5 + --> $DIR/non-defaulted-item-fail.rs:45:5 | LL | impl Foo for Vec {} | ------------------------- parent `impl` is here @@ -55,7 +55,7 @@ LL | type Ty = Vec<()>; = note: to specialize, `Ty` in the parent `impl` must be marked `default` error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-default-methods-fail.rs:47:5 + --> $DIR/non-defaulted-item-fail.rs:47:5 | LL | impl Foo for Vec {} | ------------------------- parent `impl` is here @@ -66,7 +66,7 @@ LL | const CONST: u8 = 42; = note: to specialize, `CONST` in the parent `impl` must be marked `default` error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-default-methods-fail.rs:49:5 + --> $DIR/non-defaulted-item-fail.rs:49:5 | LL | impl Foo for Vec {} | ------------------------- parent `impl` is here