diff options
20 files changed, 147 insertions, 101 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index be438f02a97..b31d6d68b0a 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -64,7 +64,9 @@ pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind; pub use self::specialize::{specialization_graph, translate_substs, OverlapError}; pub use self::structural_match::search_for_structural_match_violation; pub use self::structural_match::NonStructuralMatchTy; -pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs}; +pub use self::util::{ + elaborate_obligations, elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs, +}; pub use self::util::{expand_trait_aliases, TraitAliasExpander}; pub use self::util::{ get_vtable_index_of_object_method, impl_item_is_final, predicate_for_trait_def, upcast_choices, diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs index 8ecd6034ad6..f4bb5761c19 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -74,7 +74,7 @@ use rustc_infer::infer::{InferCtxt, RegionckMode, TyCtxtInferExt}; use rustc_infer::traits::specialization_graph::Node; use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; use rustc_middle::ty::trait_def::TraitSpecializationKind; -use rustc_middle::ty::{self, InstantiatedPredicates, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; use rustc_span::Span; use rustc_trait_selection::traits::{self, translate_substs, wf}; @@ -294,13 +294,27 @@ fn check_predicates<'tcx>( span: Span, ) { let tcx = infcx.tcx; - let impl1_predicates = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs); + let impl1_predicates: Vec<_> = traits::elaborate_predicates( + tcx, + tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs).predicates.into_iter(), + ) + .map(|obligation| obligation.predicate) + .collect(); + let mut impl2_predicates = if impl2_node.is_from_trait() { // Always applicable traits have to be always applicable without any // assumptions. - InstantiatedPredicates::empty() + Vec::new() } else { - tcx.predicates_of(impl2_node.def_id()).instantiate(tcx, impl2_substs) + traits::elaborate_predicates( + tcx, + tcx.predicates_of(impl2_node.def_id()) + .instantiate(tcx, impl2_substs) + .predicates + .into_iter(), + ) + .map(|obligation| obligation.predicate) + .collect() }; debug!( "check_always_applicable(\nimpl1_predicates={:?},\nimpl2_predicates={:?}\n)", @@ -322,13 +336,12 @@ fn check_predicates<'tcx>( // which is sound because we forbid impls like the following // // impl<D: Debug> AlwaysApplicable for D { } - let always_applicable_traits = - impl1_predicates.predicates.iter().copied().filter(|&predicate| { - matches!( - trait_predicate_kind(tcx, predicate), - Some(TraitSpecializationKind::AlwaysApplicable) - ) - }); + let always_applicable_traits = impl1_predicates.iter().copied().filter(|&predicate| { + matches!( + trait_predicate_kind(tcx, predicate), + Some(TraitSpecializationKind::AlwaysApplicable) + ) + }); // Include the well-formed predicates of the type parameters of the impl. for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().substs { @@ -340,18 +353,19 @@ fn check_predicates<'tcx>( arg, span, ) { - impl2_predicates - .predicates - .extend(obligations.into_iter().map(|obligation| obligation.predicate)) + impl2_predicates.extend( + traits::elaborate_obligations(tcx, obligations) + .map(|obligation| obligation.predicate), + ) } } - impl2_predicates.predicates.extend( + impl2_predicates.extend( traits::elaborate_predicates(tcx, always_applicable_traits) .map(|obligation| obligation.predicate), ); - for predicate in impl1_predicates.predicates { - if !impl2_predicates.predicates.contains(&predicate) { + for predicate in impl1_predicates { + if !impl2_predicates.contains(&predicate) { check_specialization_on(tcx, predicate, span) } } diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 8a2d254a834..18e191f2b59 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -266,14 +266,21 @@ unsafe impl<T, A: Allocator> TrustedLen for IntoIter<T, A> {} #[doc(hidden)] #[unstable(issue = "none", feature = "std_internals")] +#[rustc_unsafe_specialization_marker] +pub trait NonDrop {} + // T: Copy as approximation for !Drop since get_unchecked does not advance self.ptr // and thus we can't implement drop-handling -// +#[unstable(issue = "none", feature = "std_internals")] +impl<T: Copy> NonDrop for T {} + +#[doc(hidden)] +#[unstable(issue = "none", feature = "std_internals")] // TrustedRandomAccess (without NoCoerce) must not be implemented because -// subtypes/supertypes of `T` might not be `Copy` +// subtypes/supertypes of `T` might not be `NonDrop` unsafe impl<T, A: Allocator> TrustedRandomAccessNoCoerce for IntoIter<T, A> where - T: Copy, + T: NonDrop, { const MAY_HAVE_SIDE_EFFECT: bool = false; } diff --git a/library/alloc/src/vec/source_iter_marker.rs b/library/alloc/src/vec/source_iter_marker.rs index e05788d99c0..6e78534cf5b 100644 --- a/library/alloc/src/vec/source_iter_marker.rs +++ b/library/alloc/src/vec/source_iter_marker.rs @@ -6,24 +6,14 @@ use super::{AsIntoIter, InPlaceDrop, SpecFromIter, SpecFromIterNested, Vec}; /// Specialization marker for collecting an iterator pipeline into a Vec while reusing the /// source allocation, i.e. executing the pipeline in place. -/// -/// The SourceIter parent trait is necessary for the specializing function to access the allocation -/// which is to be reused. But it is not sufficient for the specialization to be valid. See -/// additional bounds on the impl. #[rustc_unsafe_specialization_marker] -pub(super) trait SourceIterMarker: SourceIter<Source: AsIntoIter> {} +pub(super) trait InPlaceIterableMarker {} -// The std-internal SourceIter/InPlaceIterable traits are only implemented by chains of -// Adapter<Adapter<Adapter<IntoIter>>> (all owned by core/std). Additional bounds -// on the adapter implementations (beyond `impl<I: Trait> Trait for Adapter<I>`) only depend on other -// traits already marked as specialization traits (Copy, TrustedRandomAccess, FusedIterator). -// I.e. the marker does not depend on lifetimes of user-supplied types. Modulo the Copy hole, which -// several other specializations already depend on. -impl<T> SourceIterMarker for T where T: SourceIter<Source: AsIntoIter> + InPlaceIterable {} +impl<T> InPlaceIterableMarker for T where T: InPlaceIterable {} impl<T, I> SpecFromIter<T, I> for Vec<T> where - I: Iterator<Item = T> + SourceIterMarker, + I: Iterator<Item = T> + SourceIter<Source: AsIntoIter> + InPlaceIterableMarker, { default fn from_iter(mut iterator: I) -> Self { // Additional requirements which cannot expressed via trait bounds. We rely on const eval diff --git a/library/core/src/iter/adapters/enumerate.rs b/library/core/src/iter/adapters/enumerate.rs index c877b45095a..84e4618844a 100644 --- a/library/core/src/iter/adapters/enumerate.rs +++ b/library/core/src/iter/adapters/enumerate.rs @@ -249,14 +249,14 @@ impl<I> FusedIterator for Enumerate<I> where I: FusedIterator {} unsafe impl<I> TrustedLen for Enumerate<I> where I: TrustedLen {} #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<S: Iterator, I: Iterator> SourceIter for Enumerate<I> +unsafe impl<I> SourceIter for Enumerate<I> where - I: SourceIter<Source = S>, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/filter.rs b/library/core/src/iter/adapters/filter.rs index d5f19f12747..a0afaa326ad 100644 --- a/library/core/src/iter/adapters/filter.rs +++ b/library/core/src/iter/adapters/filter.rs @@ -135,15 +135,14 @@ where impl<I: FusedIterator, P> FusedIterator for Filter<I, P> where P: FnMut(&I::Item) -> bool {} #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<S: Iterator, P, I: Iterator> SourceIter for Filter<I, P> +unsafe impl<P, I> SourceIter for Filter<I, P> where - P: FnMut(&I::Item) -> bool, - I: SourceIter<Source = S>, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/filter_map.rs b/library/core/src/iter/adapters/filter_map.rs index 01b7be9d52d..e0d665c9e12 100644 --- a/library/core/src/iter/adapters/filter_map.rs +++ b/library/core/src/iter/adapters/filter_map.rs @@ -129,15 +129,14 @@ where impl<B, I: FusedIterator, F> FusedIterator for FilterMap<I, F> where F: FnMut(I::Item) -> Option<B> {} #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<S: Iterator, B, I: Iterator, F> SourceIter for FilterMap<I, F> +unsafe impl<I, F> SourceIter for FilterMap<I, F> where - F: FnMut(I::Item) -> Option<B>, - I: SourceIter<Source = S>, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/inspect.rs b/library/core/src/iter/adapters/inspect.rs index 36835d12e56..19839fdfe5b 100644 --- a/library/core/src/iter/adapters/inspect.rs +++ b/library/core/src/iter/adapters/inspect.rs @@ -149,15 +149,14 @@ where impl<I: FusedIterator, F> FusedIterator for Inspect<I, F> where F: FnMut(&I::Item) {} #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<S: Iterator, I: Iterator, F> SourceIter for Inspect<I, F> +unsafe impl<I, F> SourceIter for Inspect<I, F> where - F: FnMut(&I::Item), - I: SourceIter<Source = S>, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/map.rs b/library/core/src/iter/adapters/map.rs index 763e253e75a..449650a22f4 100644 --- a/library/core/src/iter/adapters/map.rs +++ b/library/core/src/iter/adapters/map.rs @@ -201,15 +201,14 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<S: Iterator, B, I: Iterator, F> SourceIter for Map<I, F> +unsafe impl<I, F> SourceIter for Map<I, F> where - F: FnMut(I::Item) -> B, - I: SourceIter<Source = S>, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/map_while.rs b/library/core/src/iter/adapters/map_while.rs index 793b05fcf95..1e8d6bf3e00 100644 --- a/library/core/src/iter/adapters/map_while.rs +++ b/library/core/src/iter/adapters/map_while.rs @@ -80,15 +80,14 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<S: Iterator, B, I: Iterator, P> SourceIter for MapWhile<I, P> +unsafe impl<I, P> SourceIter for MapWhile<I, P> where - P: FnMut(I::Item) -> Option<B>, - I: SourceIter<Source = S>, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index 48e7dcfa7d9..1e1ce866ff3 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -92,9 +92,10 @@ pub use self::zip::zip; /// [`as_inner`]: SourceIter::as_inner #[unstable(issue = "none", feature = "inplace_iteration")] #[doc(hidden)] +#[rustc_specialization_trait] pub unsafe trait SourceIter { /// A source stage in an iterator pipeline. - type Source: Iterator; + type Source; /// Retrieve the source of an iterator pipeline. /// @@ -200,14 +201,14 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<S: Iterator, I, E> SourceIter for ResultShunt<'_, I, E> +unsafe impl<I, E> SourceIter for ResultShunt<'_, I, E> where - I: SourceIter<Source = S>, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut Self::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs index 91fa1a9ad35..20aca323bab 100644 --- a/library/core/src/iter/adapters/peekable.rs +++ b/library/core/src/iter/adapters/peekable.rs @@ -321,14 +321,14 @@ impl<I: Iterator> Peekable<I> { unsafe impl<I> TrustedLen for Peekable<I> where I: TrustedLen {} #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<S: Iterator, I: Iterator> SourceIter for Peekable<I> +unsafe impl<I: Iterator> SourceIter for Peekable<I> where - I: SourceIter<Source = S>, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/scan.rs b/library/core/src/iter/adapters/scan.rs index 96705b01f66..80bfd223124 100644 --- a/library/core/src/iter/adapters/scan.rs +++ b/library/core/src/iter/adapters/scan.rs @@ -90,15 +90,14 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<St, F, B, S: Iterator, I: Iterator> SourceIter for Scan<I, St, F> +unsafe impl<St, F, I> SourceIter for Scan<I, St, F> where - I: SourceIter<Source = S>, - F: FnMut(&mut St, I::Item) -> Option<B>, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/skip.rs b/library/core/src/iter/adapters/skip.rs index 9b89ca5a947..565fc224f53 100644 --- a/library/core/src/iter/adapters/skip.rs +++ b/library/core/src/iter/adapters/skip.rs @@ -222,14 +222,14 @@ where impl<I> FusedIterator for Skip<I> where I: FusedIterator {} #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<S: Iterator, I: Iterator> SourceIter for Skip<I> +unsafe impl<I> SourceIter for Skip<I> where - I: SourceIter<Source = S>, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/skip_while.rs b/library/core/src/iter/adapters/skip_while.rs index 93e29edc8df..f29661779c0 100644 --- a/library/core/src/iter/adapters/skip_while.rs +++ b/library/core/src/iter/adapters/skip_while.rs @@ -105,15 +105,14 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<S: Iterator, P, I: Iterator> SourceIter for SkipWhile<I, P> +unsafe impl<P, I> SourceIter for SkipWhile<I, P> where - P: FnMut(&I::Item) -> bool, - I: SourceIter<Source = S>, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs index d0d0128c82b..81f6c294fac 100644 --- a/library/core/src/iter/adapters/take.rs +++ b/library/core/src/iter/adapters/take.rs @@ -130,14 +130,14 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<S: Iterator, I: Iterator> SourceIter for Take<I> +unsafe impl<I> SourceIter for Take<I> where - I: SourceIter<Source = S>, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/take_while.rs b/library/core/src/iter/adapters/take_while.rs index 93457d20f7c..ded216da952 100644 --- a/library/core/src/iter/adapters/take_while.rs +++ b/library/core/src/iter/adapters/take_while.rs @@ -118,15 +118,14 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<S: Iterator, P, I: Iterator> SourceIter for TakeWhile<I, P> +unsafe impl<P, I> SourceIter for TakeWhile<I, P> where - P: FnMut(&I::Item) -> bool, - I: SourceIter<Source = S>, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs index 17697fa0e04..2b7287a4133 100644 --- a/library/core/src/iter/adapters/zip.rs +++ b/library/core/src/iter/adapters/zip.rs @@ -414,16 +414,14 @@ where // Arbitrarily selects the left side of the zip iteration as extractable "source" // it would require negative trait bounds to be able to try both #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<S, A, B> SourceIter for Zip<A, B> +unsafe impl<A, B> SourceIter for Zip<A, B> where - A: SourceIter<Source = S>, - B: Iterator, - S: Iterator, + A: SourceIter, { - type Source = S; + type Source = A::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut A::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.a) } } diff --git a/src/test/ui/specialization/min_specialization/spec-marker-supertraits.rs b/src/test/ui/specialization/min_specialization/spec-marker-supertraits.rs new file mode 100644 index 00000000000..3bb2480e9e2 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/spec-marker-supertraits.rs @@ -0,0 +1,29 @@ +// Check that supertraits cannot be used to work around min_specialization +// limitations. + +#![feature(min_specialization)] +#![feature(rustc_attrs)] + +trait HasMethod { + fn method(&self); +} + +#[rustc_unsafe_specialization_marker] +trait Marker: HasMethod {} + +trait Spec { + fn spec_me(&self); +} + +impl<T> Spec for T { + default fn spec_me(&self) {} +} + +impl<T: Marker> Spec for T { + //~^ ERROR cannot specialize on trait `HasMethod` + fn spec_me(&self) { + self.method(); + } +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/spec-marker-supertraits.stderr b/src/test/ui/specialization/min_specialization/spec-marker-supertraits.stderr new file mode 100644 index 00000000000..964109dd10f --- /dev/null +++ b/src/test/ui/specialization/min_specialization/spec-marker-supertraits.stderr @@ -0,0 +1,13 @@ +error: cannot specialize on trait `HasMethod` + --> $DIR/spec-marker-supertraits.rs:22:1 + | +LL | / impl<T: Marker> Spec for T { +LL | | +LL | | fn spec_me(&self) { +LL | | self.method(); +LL | | } +LL | | } + | |_^ + +error: aborting due to previous error + |
