Skip to content

Commit

Permalink
relax adt unsizing requirements
Browse files Browse the repository at this point in the history
  • Loading branch information
lcnr committed Feb 3, 2021
1 parent 120b2a7 commit 50e394a
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 8 deletions.
12 changes: 12 additions & 0 deletions compiler/rustc_index/src/bit_set.rs
Expand Up @@ -707,6 +707,18 @@ impl<T: Idx> GrowableBitSet<T> {
self.bit_set.insert(elem)
}

/// Returns `true` if the set has changed.
#[inline]
pub fn remove(&mut self, elem: T) -> bool {
self.ensure(elem.index() + 1);
self.bit_set.remove(elem)
}

#[inline]
pub fn is_empty(&self) -> bool {
self.bit_set.is_empty()
}

#[inline]
pub fn contains(&self, elem: T) -> bool {
let (word_index, mask) = word_index_and_mask(elem);
Expand Down
13 changes: 5 additions & 8 deletions compiler/rustc_trait_selection/src/traits/select/confirmation.rs
Expand Up @@ -829,16 +829,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let tail_field_ty = tcx.type_of(tail_field.did);

let mut unsizing_params = GrowableBitSet::new_empty();
let mut found = false;
for arg in tail_field_ty.walk() {
if let Some(i) = maybe_unsizing_param_idx(arg) {
unsizing_params.insert(i);
found = true;
}
}
if !found {
return Err(Unimplemented);
}

// Ensure none of the other fields mention the parameters used
// in unsizing.
Expand All @@ -848,13 +843,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
for field in prefix_fields {
for arg in tcx.type_of(field.did).walk() {
if let Some(i) = maybe_unsizing_param_idx(arg) {
if unsizing_params.contains(i) {
return Err(Unimplemented);
}
unsizing_params.remove(i);
}
}
}

if unsizing_params.is_empty() {
return Err(Unimplemented);
}

// Extract `TailField<T>` and `TailField<U>` from `Struct<T>` and `Struct<U>`.
let source_tail = tail_field_ty.subst(tcx, substs_a);
let target_tail = tail_field_ty.subst(tcx, substs_b);
Expand Down
11 changes: 11 additions & 0 deletions src/test/ui/unsized/unchanged-param.rs
@@ -0,0 +1,11 @@
// run-pass
// Test that we allow unsizing even if there is an unchanged param in the
// field getting unsized.
struct A<T, U: ?Sized + 'static>(T, B<T, U>);
struct B<T, U: ?Sized>(T, U);

fn main() {
let x: A<[u32; 1], [u32; 1]> = A([0; 1], B([0; 1], [0; 1]));
let y: &A<[u32; 1], [u32]> = &x;
assert_eq!(y.1.1.len(), 1);
}

0 comments on commit 50e394a

Please sign in to comment.