Skip to content

Commit bfd072d

Browse files
committed
Auto merge of #26038 - eddyb:dst-nested, r=luqmana
Allows `Rc<RefCell<Trait>>` and other containers. Fixes #25351. r? @nrc This is the discussed strategy, more or less.
2 parents d6b8242 + 01dee1b commit bfd072d

File tree

2 files changed

+36
-15
lines changed

2 files changed

+36
-15
lines changed

src/librustc/middle/traits/select.rs

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2523,41 +2523,57 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
25232523
ty::lookup_field_type_unsubstituted(tcx, def_id, f.id)
25242524
}).collect::<Vec<_>>();
25252525

2526-
// FIXME(#25351) The last field of the structure has to exist and be a
2527-
// type parameter (for now, to avoid tracking edge cases).
2528-
let i = if let Some(&ty::ty_param(p)) = fields.last().map(|ty| &ty.sty) {
2529-
assert!(p.space == TypeSpace);
2530-
p.idx as usize
2526+
// The last field of the structure has to exist and contain type parameters.
2527+
let field = if let Some(&field) = fields.last() {
2528+
field
25312529
} else {
25322530
return Err(Unimplemented);
25332531
};
2532+
let mut ty_params = vec![];
2533+
ty::walk_ty(field, |ty| {
2534+
if let ty::ty_param(p) = ty.sty {
2535+
assert!(p.space == TypeSpace);
2536+
let idx = p.idx as usize;
2537+
if !ty_params.contains(&idx) {
2538+
ty_params.push(idx);
2539+
}
2540+
}
2541+
});
2542+
if ty_params.is_empty() {
2543+
return Err(Unimplemented);
2544+
}
25342545

2535-
// Replace the type parameter chosen for unsizing with
2536-
// ty_err and ensure it does not affect any other fields.
2546+
// Replace type parameters used in unsizing with
2547+
// ty_err and ensure they do not affect any other fields.
25372548
// This could be checked after type collection for any struct
25382549
// with a potentially unsized trailing field.
25392550
let mut new_substs = substs_a.clone();
2540-
new_substs.types.get_mut_slice(TypeSpace)[i] = tcx.types.err;
2551+
for &i in &ty_params {
2552+
new_substs.types.get_mut_slice(TypeSpace)[i] = tcx.types.err;
2553+
}
25412554
for &ty in fields.init() {
25422555
if ty::type_is_error(ty.subst(tcx, &new_substs)) {
25432556
return Err(Unimplemented);
25442557
}
25452558
}
25462559

2547-
// Extract T and U from Struct<T> and Struct<U>.
2548-
let inner_source = *substs_a.types.get(TypeSpace, i);
2549-
let inner_target = *substs_b.types.get(TypeSpace, i);
2560+
// Extract Field<T> and Field<U> from Struct<T> and Struct<U>.
2561+
let inner_source = field.subst(tcx, substs_a);
2562+
let inner_target = field.subst(tcx, substs_b);
25502563

2551-
// Check that all the source structure with the unsized
2552-
// type parameter is a subtype of the target.
2553-
new_substs.types.get_mut_slice(TypeSpace)[i] = inner_target;
2564+
// Check that the source structure with the target's
2565+
// type parameters is a subtype of the target.
2566+
for &i in &ty_params {
2567+
let param_b = *substs_b.types.get(TypeSpace, i);
2568+
new_substs.types.get_mut_slice(TypeSpace)[i] = param_b;
2569+
}
25542570
let new_struct = ty::mk_struct(tcx, def_id, tcx.mk_substs(new_substs));
25552571
let origin = infer::Misc(obligation.cause.span);
25562572
if self.infcx.sub_types(false, origin, new_struct, target).is_err() {
25572573
return Err(Unimplemented);
25582574
}
25592575

2560-
// Construct the nested T: Unsize<U> predicate.
2576+
// Construct the nested Field<T>: Unsize<Field<U>> predicate.
25612577
nested.push(util::predicate_for_trait_def(tcx,
25622578
obligation.cause.clone(),
25632579
obligation.predicate.def_id(),

src/test/run-pass/dst-coerce-rc.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#![feature(core)]
1414

15+
use std::cell::RefCell;
1516
use std::rc::Rc;
1617

1718
trait Baz {
@@ -36,4 +37,8 @@ fn main() {
3637
assert_eq!(b.get(), 42);
3738

3839
let _c = b.clone();
40+
41+
let a: Rc<RefCell<i32>> = Rc::new(RefCell::new(42));
42+
let b: Rc<RefCell<Baz>> = a.clone();
43+
assert_eq!(b.borrow().get(), 42);
3944
}

0 commit comments

Comments
 (0)