Skip to content

Commit 2214483

Browse files
committed
Ignore PhantomData when checking CoerceUnsized implementations
1 parent f7b3cd3 commit 2214483

File tree

4 files changed

+81
-1
lines changed

4 files changed

+81
-1
lines changed

src/librustc_trans/trans/expr.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,12 @@ fn coerce_unsized<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
538538
Rvalue::new(ByRef)));
539539
} else {
540540
// Otherwise, simply copy the data from the source.
541-
assert_eq!(src_ty, target_ty);
541+
let is_phantom = if let &ty::TyStruct(def_id, _) = &src_ty.sty {
542+
Some(def_id) == bcx.tcx().lang_items.phantom_data()
543+
} else {
544+
false
545+
};
546+
assert!(is_phantom || src_ty == target_ty);
542547
memcpy_ty(bcx, ll_target, ll_source, src_ty);
543548
}
544549
}

src/librustc_typeck/coherence/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,12 +485,24 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
485485

486486
let origin = infer::Misc(span);
487487
let fields = tcx.lookup_struct_fields(def_id_a);
488+
488489
let diff_fields = fields.iter().enumerate().filter_map(|(i, f)| {
489490
let ty = tcx.lookup_field_type_unsubstituted(def_id_a, f.id);
490491
let (a, b) = (ty.subst(tcx, substs_a), ty.subst(tcx, substs_b));
492+
493+
// Ignore PhantomData -- doesn't matter
494+
if let &ty::TyStruct(def_id, _) = &ty.sty {
495+
if Some(def_id) == tcx.lang_items.phantom_data() {
496+
return None;
497+
}
498+
}
499+
491500
if infcx.sub_types(false, origin, b, a).is_ok() {
501+
// Ignore fields that aren't significantly changed
492502
None
493503
} else {
504+
// Collect up all fields that were significantly changed
505+
// i.e. those that contain T in coerce_unsized T -> U
494506
Some((i, a, b))
495507
}
496508
}).collect::<Vec<_>>();

src/test/compile-fail/issue-26905.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(unsize, coerce_unsized)]
12+
13+
// Verfies that non-PhantomData ZSTs still cause coercions to fail.
14+
// They might have additional semantics that we don't want to bulldoze.
15+
16+
use std::marker::{Unsize, PhantomData};
17+
use std::ops::CoerceUnsized;
18+
19+
struct NotPhantomData<T>(PhantomData<T>);
20+
21+
struct MyRc<T: ?Sized> {
22+
_ptr: *const T,
23+
_boo: NotPhantomData<T>, //~ERROR
24+
}
25+
26+
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<MyRc<U>> for MyRc<T>{ }
27+
28+
fn main() {
29+
let data = [1, 2, 3];
30+
let iter = data.iter();
31+
let x = MyRc { _ptr: &iter, _boo: NotPhantomData(PhantomData) };
32+
let _y: MyRc<Iterator<Item=&u32>> = x;
33+
}

src/test/run-pass/issue-26905.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(unsize, coerce_unsized)]
12+
13+
// Verfies that PhantomData is ignored for DST coercions
14+
15+
use std::marker::{Unsize, PhantomData};
16+
use std::ops::CoerceUnsized;
17+
18+
struct MyRc<T: ?Sized> {
19+
_ptr: *const T,
20+
_boo: PhantomData<T>,
21+
}
22+
23+
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<MyRc<U>> for MyRc<T>{ }
24+
25+
fn main() {
26+
let data = [1, 2, 3];
27+
let iter = data.iter();
28+
let x = MyRc { _ptr: &iter, _boo: PhantomData };
29+
let _y: MyRc<Iterator<Item=&u32>> = x;
30+
}

0 commit comments

Comments
 (0)