Skip to content

Commit d099489

Browse files
authored
Rollup merge of rust-lang#89413 - matthewjasper:spec-marker-fix, r=nikomatsakis
Correctly handle supertraits for min_specialization Supertraits of specialization markers could circumvent checks for min_specialization. Elaborating predicates prevents this. r? `@nikomatsakis`
2 parents c27b049 + 051d5b0 commit d099489

File tree

20 files changed

+147
-101
lines changed

20 files changed

+147
-101
lines changed

compiler/rustc_trait_selection/src/traits/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
6464
pub use self::specialize::{specialization_graph, translate_substs, OverlapError};
6565
pub use self::structural_match::search_for_structural_match_violation;
6666
pub use self::structural_match::NonStructuralMatchTy;
67-
pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs};
67+
pub use self::util::{
68+
elaborate_obligations, elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs,
69+
};
6870
pub use self::util::{expand_trait_aliases, TraitAliasExpander};
6971
pub use self::util::{
7072
get_vtable_index_of_object_method, impl_item_is_final, predicate_for_trait_def, upcast_choices,

compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs

+31-17
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ use rustc_infer::infer::{InferCtxt, RegionckMode, TyCtxtInferExt};
7474
use rustc_infer::traits::specialization_graph::Node;
7575
use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
7676
use rustc_middle::ty::trait_def::TraitSpecializationKind;
77-
use rustc_middle::ty::{self, InstantiatedPredicates, TyCtxt, TypeFoldable};
77+
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
7878
use rustc_span::Span;
7979
use rustc_trait_selection::traits::{self, translate_substs, wf};
8080

@@ -294,13 +294,27 @@ fn check_predicates<'tcx>(
294294
span: Span,
295295
) {
296296
let tcx = infcx.tcx;
297-
let impl1_predicates = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs);
297+
let impl1_predicates: Vec<_> = traits::elaborate_predicates(
298+
tcx,
299+
tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs).predicates.into_iter(),
300+
)
301+
.map(|obligation| obligation.predicate)
302+
.collect();
303+
298304
let mut impl2_predicates = if impl2_node.is_from_trait() {
299305
// Always applicable traits have to be always applicable without any
300306
// assumptions.
301-
InstantiatedPredicates::empty()
307+
Vec::new()
302308
} else {
303-
tcx.predicates_of(impl2_node.def_id()).instantiate(tcx, impl2_substs)
309+
traits::elaborate_predicates(
310+
tcx,
311+
tcx.predicates_of(impl2_node.def_id())
312+
.instantiate(tcx, impl2_substs)
313+
.predicates
314+
.into_iter(),
315+
)
316+
.map(|obligation| obligation.predicate)
317+
.collect()
304318
};
305319
debug!(
306320
"check_always_applicable(\nimpl1_predicates={:?},\nimpl2_predicates={:?}\n)",
@@ -322,13 +336,12 @@ fn check_predicates<'tcx>(
322336
// which is sound because we forbid impls like the following
323337
//
324338
// impl<D: Debug> AlwaysApplicable for D { }
325-
let always_applicable_traits =
326-
impl1_predicates.predicates.iter().copied().filter(|&predicate| {
327-
matches!(
328-
trait_predicate_kind(tcx, predicate),
329-
Some(TraitSpecializationKind::AlwaysApplicable)
330-
)
331-
});
339+
let always_applicable_traits = impl1_predicates.iter().copied().filter(|&predicate| {
340+
matches!(
341+
trait_predicate_kind(tcx, predicate),
342+
Some(TraitSpecializationKind::AlwaysApplicable)
343+
)
344+
});
332345

333346
// Include the well-formed predicates of the type parameters of the impl.
334347
for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().substs {
@@ -340,18 +353,19 @@ fn check_predicates<'tcx>(
340353
arg,
341354
span,
342355
) {
343-
impl2_predicates
344-
.predicates
345-
.extend(obligations.into_iter().map(|obligation| obligation.predicate))
356+
impl2_predicates.extend(
357+
traits::elaborate_obligations(tcx, obligations)
358+
.map(|obligation| obligation.predicate),
359+
)
346360
}
347361
}
348-
impl2_predicates.predicates.extend(
362+
impl2_predicates.extend(
349363
traits::elaborate_predicates(tcx, always_applicable_traits)
350364
.map(|obligation| obligation.predicate),
351365
);
352366

353-
for predicate in impl1_predicates.predicates {
354-
if !impl2_predicates.predicates.contains(&predicate) {
367+
for predicate in impl1_predicates {
368+
if !impl2_predicates.contains(&predicate) {
355369
check_specialization_on(tcx, predicate, span)
356370
}
357371
}

library/alloc/src/vec/into_iter.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -266,14 +266,21 @@ unsafe impl<T, A: Allocator> TrustedLen for IntoIter<T, A> {}
266266

267267
#[doc(hidden)]
268268
#[unstable(issue = "none", feature = "std_internals")]
269+
#[rustc_unsafe_specialization_marker]
270+
pub trait NonDrop {}
271+
269272
// T: Copy as approximation for !Drop since get_unchecked does not advance self.ptr
270273
// and thus we can't implement drop-handling
271-
//
274+
#[unstable(issue = "none", feature = "std_internals")]
275+
impl<T: Copy> NonDrop for T {}
276+
277+
#[doc(hidden)]
278+
#[unstable(issue = "none", feature = "std_internals")]
272279
// TrustedRandomAccess (without NoCoerce) must not be implemented because
273-
// subtypes/supertypes of `T` might not be `Copy`
280+
// subtypes/supertypes of `T` might not be `NonDrop`
274281
unsafe impl<T, A: Allocator> TrustedRandomAccessNoCoerce for IntoIter<T, A>
275282
where
276-
T: Copy,
283+
T: NonDrop,
277284
{
278285
const MAY_HAVE_SIDE_EFFECT: bool = false;
279286
}

library/alloc/src/vec/source_iter_marker.rs

+3-13
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,14 @@ use super::{AsIntoIter, InPlaceDrop, SpecFromIter, SpecFromIterNested, Vec};
66

77
/// Specialization marker for collecting an iterator pipeline into a Vec while reusing the
88
/// source allocation, i.e. executing the pipeline in place.
9-
///
10-
/// The SourceIter parent trait is necessary for the specializing function to access the allocation
11-
/// which is to be reused. But it is not sufficient for the specialization to be valid. See
12-
/// additional bounds on the impl.
139
#[rustc_unsafe_specialization_marker]
14-
pub(super) trait SourceIterMarker: SourceIter<Source: AsIntoIter> {}
10+
pub(super) trait InPlaceIterableMarker {}
1511

16-
// The std-internal SourceIter/InPlaceIterable traits are only implemented by chains of
17-
// Adapter<Adapter<Adapter<IntoIter>>> (all owned by core/std). Additional bounds
18-
// on the adapter implementations (beyond `impl<I: Trait> Trait for Adapter<I>`) only depend on other
19-
// traits already marked as specialization traits (Copy, TrustedRandomAccess, FusedIterator).
20-
// I.e. the marker does not depend on lifetimes of user-supplied types. Modulo the Copy hole, which
21-
// several other specializations already depend on.
22-
impl<T> SourceIterMarker for T where T: SourceIter<Source: AsIntoIter> + InPlaceIterable {}
12+
impl<T> InPlaceIterableMarker for T where T: InPlaceIterable {}
2313

2414
impl<T, I> SpecFromIter<T, I> for Vec<T>
2515
where
26-
I: Iterator<Item = T> + SourceIterMarker,
16+
I: Iterator<Item = T> + SourceIter<Source: AsIntoIter> + InPlaceIterableMarker,
2717
{
2818
default fn from_iter(mut iterator: I) -> Self {
2919
// Additional requirements which cannot expressed via trait bounds. We rely on const eval

library/core/src/iter/adapters/enumerate.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -249,14 +249,14 @@ impl<I> FusedIterator for Enumerate<I> where I: FusedIterator {}
249249
unsafe impl<I> TrustedLen for Enumerate<I> where I: TrustedLen {}
250250

251251
#[unstable(issue = "none", feature = "inplace_iteration")]
252-
unsafe impl<S: Iterator, I: Iterator> SourceIter for Enumerate<I>
252+
unsafe impl<I> SourceIter for Enumerate<I>
253253
where
254-
I: SourceIter<Source = S>,
254+
I: SourceIter,
255255
{
256-
type Source = S;
256+
type Source = I::Source;
257257

258258
#[inline]
259-
unsafe fn as_inner(&mut self) -> &mut S {
259+
unsafe fn as_inner(&mut self) -> &mut I::Source {
260260
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
261261
unsafe { SourceIter::as_inner(&mut self.iter) }
262262
}

library/core/src/iter/adapters/filter.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -135,15 +135,14 @@ where
135135
impl<I: FusedIterator, P> FusedIterator for Filter<I, P> where P: FnMut(&I::Item) -> bool {}
136136

137137
#[unstable(issue = "none", feature = "inplace_iteration")]
138-
unsafe impl<S: Iterator, P, I: Iterator> SourceIter for Filter<I, P>
138+
unsafe impl<P, I> SourceIter for Filter<I, P>
139139
where
140-
P: FnMut(&I::Item) -> bool,
141-
I: SourceIter<Source = S>,
140+
I: SourceIter,
142141
{
143-
type Source = S;
142+
type Source = I::Source;
144143

145144
#[inline]
146-
unsafe fn as_inner(&mut self) -> &mut S {
145+
unsafe fn as_inner(&mut self) -> &mut I::Source {
147146
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
148147
unsafe { SourceIter::as_inner(&mut self.iter) }
149148
}

library/core/src/iter/adapters/filter_map.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -129,15 +129,14 @@ where
129129
impl<B, I: FusedIterator, F> FusedIterator for FilterMap<I, F> where F: FnMut(I::Item) -> Option<B> {}
130130

131131
#[unstable(issue = "none", feature = "inplace_iteration")]
132-
unsafe impl<S: Iterator, B, I: Iterator, F> SourceIter for FilterMap<I, F>
132+
unsafe impl<I, F> SourceIter for FilterMap<I, F>
133133
where
134-
F: FnMut(I::Item) -> Option<B>,
135-
I: SourceIter<Source = S>,
134+
I: SourceIter,
136135
{
137-
type Source = S;
136+
type Source = I::Source;
138137

139138
#[inline]
140-
unsafe fn as_inner(&mut self) -> &mut S {
139+
unsafe fn as_inner(&mut self) -> &mut I::Source {
141140
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
142141
unsafe { SourceIter::as_inner(&mut self.iter) }
143142
}

library/core/src/iter/adapters/inspect.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -149,15 +149,14 @@ where
149149
impl<I: FusedIterator, F> FusedIterator for Inspect<I, F> where F: FnMut(&I::Item) {}
150150

151151
#[unstable(issue = "none", feature = "inplace_iteration")]
152-
unsafe impl<S: Iterator, I: Iterator, F> SourceIter for Inspect<I, F>
152+
unsafe impl<I, F> SourceIter for Inspect<I, F>
153153
where
154-
F: FnMut(&I::Item),
155-
I: SourceIter<Source = S>,
154+
I: SourceIter,
156155
{
157-
type Source = S;
156+
type Source = I::Source;
158157

159158
#[inline]
160-
unsafe fn as_inner(&mut self) -> &mut S {
159+
unsafe fn as_inner(&mut self) -> &mut I::Source {
161160
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
162161
unsafe { SourceIter::as_inner(&mut self.iter) }
163162
}

library/core/src/iter/adapters/map.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -201,15 +201,14 @@ where
201201
}
202202

203203
#[unstable(issue = "none", feature = "inplace_iteration")]
204-
unsafe impl<S: Iterator, B, I: Iterator, F> SourceIter for Map<I, F>
204+
unsafe impl<I, F> SourceIter for Map<I, F>
205205
where
206-
F: FnMut(I::Item) -> B,
207-
I: SourceIter<Source = S>,
206+
I: SourceIter,
208207
{
209-
type Source = S;
208+
type Source = I::Source;
210209

211210
#[inline]
212-
unsafe fn as_inner(&mut self) -> &mut S {
211+
unsafe fn as_inner(&mut self) -> &mut I::Source {
213212
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
214213
unsafe { SourceIter::as_inner(&mut self.iter) }
215214
}

library/core/src/iter/adapters/map_while.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,14 @@ where
8080
}
8181

8282
#[unstable(issue = "none", feature = "inplace_iteration")]
83-
unsafe impl<S: Iterator, B, I: Iterator, P> SourceIter for MapWhile<I, P>
83+
unsafe impl<I, P> SourceIter for MapWhile<I, P>
8484
where
85-
P: FnMut(I::Item) -> Option<B>,
86-
I: SourceIter<Source = S>,
85+
I: SourceIter,
8786
{
88-
type Source = S;
87+
type Source = I::Source;
8988

9089
#[inline]
91-
unsafe fn as_inner(&mut self) -> &mut S {
90+
unsafe fn as_inner(&mut self) -> &mut I::Source {
9291
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
9392
unsafe { SourceIter::as_inner(&mut self.iter) }
9493
}

library/core/src/iter/adapters/mod.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,10 @@ pub use self::zip::zip;
9292
/// [`as_inner`]: SourceIter::as_inner
9393
#[unstable(issue = "none", feature = "inplace_iteration")]
9494
#[doc(hidden)]
95+
#[rustc_specialization_trait]
9596
pub unsafe trait SourceIter {
9697
/// A source stage in an iterator pipeline.
97-
type Source: Iterator;
98+
type Source;
9899

99100
/// Retrieve the source of an iterator pipeline.
100101
///
@@ -200,14 +201,14 @@ where
200201
}
201202

202203
#[unstable(issue = "none", feature = "inplace_iteration")]
203-
unsafe impl<S: Iterator, I, E> SourceIter for ResultShunt<'_, I, E>
204+
unsafe impl<I, E> SourceIter for ResultShunt<'_, I, E>
204205
where
205-
I: SourceIter<Source = S>,
206+
I: SourceIter,
206207
{
207-
type Source = S;
208+
type Source = I::Source;
208209

209210
#[inline]
210-
unsafe fn as_inner(&mut self) -> &mut S {
211+
unsafe fn as_inner(&mut self) -> &mut Self::Source {
211212
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
212213
unsafe { SourceIter::as_inner(&mut self.iter) }
213214
}

library/core/src/iter/adapters/peekable.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -321,14 +321,14 @@ impl<I: Iterator> Peekable<I> {
321321
unsafe impl<I> TrustedLen for Peekable<I> where I: TrustedLen {}
322322

323323
#[unstable(issue = "none", feature = "inplace_iteration")]
324-
unsafe impl<S: Iterator, I: Iterator> SourceIter for Peekable<I>
324+
unsafe impl<I: Iterator> SourceIter for Peekable<I>
325325
where
326-
I: SourceIter<Source = S>,
326+
I: SourceIter,
327327
{
328-
type Source = S;
328+
type Source = I::Source;
329329

330330
#[inline]
331-
unsafe fn as_inner(&mut self) -> &mut S {
331+
unsafe fn as_inner(&mut self) -> &mut I::Source {
332332
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
333333
unsafe { SourceIter::as_inner(&mut self.iter) }
334334
}

library/core/src/iter/adapters/scan.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -90,15 +90,14 @@ where
9090
}
9191

9292
#[unstable(issue = "none", feature = "inplace_iteration")]
93-
unsafe impl<St, F, B, S: Iterator, I: Iterator> SourceIter for Scan<I, St, F>
93+
unsafe impl<St, F, I> SourceIter for Scan<I, St, F>
9494
where
95-
I: SourceIter<Source = S>,
96-
F: FnMut(&mut St, I::Item) -> Option<B>,
95+
I: SourceIter,
9796
{
98-
type Source = S;
97+
type Source = I::Source;
9998

10099
#[inline]
101-
unsafe fn as_inner(&mut self) -> &mut S {
100+
unsafe fn as_inner(&mut self) -> &mut I::Source {
102101
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
103102
unsafe { SourceIter::as_inner(&mut self.iter) }
104103
}

library/core/src/iter/adapters/skip.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -222,14 +222,14 @@ where
222222
impl<I> FusedIterator for Skip<I> where I: FusedIterator {}
223223

224224
#[unstable(issue = "none", feature = "inplace_iteration")]
225-
unsafe impl<S: Iterator, I: Iterator> SourceIter for Skip<I>
225+
unsafe impl<I> SourceIter for Skip<I>
226226
where
227-
I: SourceIter<Source = S>,
227+
I: SourceIter,
228228
{
229-
type Source = S;
229+
type Source = I::Source;
230230

231231
#[inline]
232-
unsafe fn as_inner(&mut self) -> &mut S {
232+
unsafe fn as_inner(&mut self) -> &mut I::Source {
233233
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
234234
unsafe { SourceIter::as_inner(&mut self.iter) }
235235
}

library/core/src/iter/adapters/skip_while.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -105,15 +105,14 @@ where
105105
}
106106

107107
#[unstable(issue = "none", feature = "inplace_iteration")]
108-
unsafe impl<S: Iterator, P, I: Iterator> SourceIter for SkipWhile<I, P>
108+
unsafe impl<P, I> SourceIter for SkipWhile<I, P>
109109
where
110-
P: FnMut(&I::Item) -> bool,
111-
I: SourceIter<Source = S>,
110+
I: SourceIter,
112111
{
113-
type Source = S;
112+
type Source = I::Source;
114113

115114
#[inline]
116-
unsafe fn as_inner(&mut self) -> &mut S {
115+
unsafe fn as_inner(&mut self) -> &mut I::Source {
117116
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
118117
unsafe { SourceIter::as_inner(&mut self.iter) }
119118
}

library/core/src/iter/adapters/take.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,14 @@ where
130130
}
131131

132132
#[unstable(issue = "none", feature = "inplace_iteration")]
133-
unsafe impl<S: Iterator, I: Iterator> SourceIter for Take<I>
133+
unsafe impl<I> SourceIter for Take<I>
134134
where
135-
I: SourceIter<Source = S>,
135+
I: SourceIter,
136136
{
137-
type Source = S;
137+
type Source = I::Source;
138138

139139
#[inline]
140-
unsafe fn as_inner(&mut self) -> &mut S {
140+
unsafe fn as_inner(&mut self) -> &mut I::Source {
141141
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
142142
unsafe { SourceIter::as_inner(&mut self.iter) }
143143
}

0 commit comments

Comments
 (0)