Skip to content

Commit c976e07

Browse files
committed
rustc: don't reveal specializable polymorphic projections.
1 parent ab26dbb commit c976e07

File tree

2 files changed

+48
-35
lines changed

2 files changed

+48
-35
lines changed

src/librustc/traits/project.rs

+36-35
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ pub enum Reveal {
9393
/// }
9494
NotSpecializable,
9595

96-
/// At trans time, all projections will succeed.
96+
/// At trans time, all monomorphic projections will succeed.
9797
All,
9898
}
9999

@@ -878,7 +878,7 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
878878

879879
candidate_set.vec.push(ProjectionTyCandidate::Select);
880880
}
881-
super::VtableImpl(ref impl_data) if selcx.projection_mode() != Reveal::All => {
881+
super::VtableImpl(ref impl_data) => {
882882
// We have to be careful when projecting out of an
883883
// impl because of specialization. If we are not in
884884
// trans (i.e., projection mode is not "any"), and the
@@ -902,37 +902,43 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
902902
impl_data.impl_def_id,
903903
obligation.predicate.item_name);
904904
let new_candidate = if let Some(node_item) = opt_node_item {
905-
if node_item.node.is_from_trait() {
906-
if node_item.item.ty.is_some() {
907-
// The impl inherited a `type Foo =
908-
// Bar` given in the trait, which is
909-
// implicitly default. No candidate.
910-
None
911-
} else {
912-
// The impl did not specify `type` and neither
913-
// did the trait:
914-
//
915-
// ```rust
916-
// trait Foo { type T; }
917-
// impl Foo for Bar { }
918-
// ```
919-
//
920-
// This is an error, but it will be
921-
// reported in `check_impl_items_against_trait`.
922-
// We accept it here but will flag it as
923-
// an error when we confirm the candidate
924-
// (which will ultimately lead to `normalize_to_error`
925-
// being invoked).
905+
let is_default = if node_item.node.is_from_trait() {
906+
// If true, the impl inherited a `type Foo = Bar`
907+
// given in the trait, which is implicitly default.
908+
// Otherwise, the impl did not specify `type` and
909+
// neither did the trait:
910+
//
911+
// ```rust
912+
// trait Foo { type T; }
913+
// impl Foo for Bar { }
914+
// ```
915+
//
916+
// This is an error, but it will be
917+
// reported in `check_impl_items_against_trait`.
918+
// We accept it here but will flag it as
919+
// an error when we confirm the candidate
920+
// (which will ultimately lead to `normalize_to_error`
921+
// being invoked).
922+
node_item.item.ty.is_some()
923+
} else {
924+
node_item.item.defaultness.is_default()
925+
};
926+
927+
// Only reveal a specializable default if we're past type-checking
928+
// and the obligations is monomorphic, otherwise passes such as
929+
// transmute checking and polymorphic MIR optimizations could
930+
// get a result which isn't correct for all monomorphizations.
931+
if !is_default {
932+
Some(ProjectionTyCandidate::Select)
933+
} else if selcx.projection_mode() == Reveal::All {
934+
assert!(!poly_trait_ref.needs_infer());
935+
if !poly_trait_ref.needs_subst() {
926936
Some(ProjectionTyCandidate::Select)
937+
} else {
938+
None
927939
}
928-
} else if node_item.item.defaultness.is_default() {
929-
// The impl specified `default type Foo =
930-
// Bar`. No candidate.
931-
None
932940
} else {
933-
// The impl specified `type Foo = Bar`
934-
// with no default. Add a candidate.
935-
Some(ProjectionTyCandidate::Select)
941+
None
936942
}
937943
} else {
938944
// This is saying that neither the trait nor
@@ -982,11 +988,6 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
982988
};
983989
candidate_set.vec.extend(new_candidate);
984990
}
985-
super::VtableImpl(_) => {
986-
// In trans mode, we can just project out of impls, no prob.
987-
assert!(selcx.projection_mode() == Reveal::All);
988-
candidate_set.vec.push(ProjectionTyCandidate::Select);
989-
}
990991
super::VtableParam(..) => {
991992
// This case tell us nothing about the value of an
992993
// associated type. Consider:

src/test/compile-fail/transmute-different-sizes.rs

+12
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
// Tests that `transmute` cannot be called on types of different size.
1212

1313
#![allow(warnings)]
14+
#![feature(specialization)]
1415

1516
use std::mem::transmute;
1617

@@ -24,4 +25,15 @@ unsafe fn g<T>(x: &T) {
2425
//~^ ERROR transmute called with differently sized types
2526
}
2627

28+
trait Specializable { type Output; }
29+
30+
impl<T> Specializable for T {
31+
default type Output = u16;
32+
}
33+
34+
unsafe fn specializable<T>(x: u16) -> <T as Specializable>::Output {
35+
transmute(x)
36+
//~^ ERROR transmute called with differently sized types
37+
}
38+
2739
fn main() {}

0 commit comments

Comments
 (0)