1
Fork 0

rustc: don't reveal specializable polymorphic projections.

This commit is contained in:
Eduard Burtescu 2016-07-01 19:32:53 +03:00
parent ab26dbb96f
commit c976e073fd
2 changed files with 49 additions and 36 deletions

View file

@ -93,7 +93,7 @@ pub enum Reveal {
/// } /// }
NotSpecializable, NotSpecializable,
/// At trans time, all projections will succeed. /// At trans time, all monomorphic projections will succeed.
All, All,
} }
@ -878,7 +878,7 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
candidate_set.vec.push(ProjectionTyCandidate::Select); candidate_set.vec.push(ProjectionTyCandidate::Select);
} }
super::VtableImpl(ref impl_data) if selcx.projection_mode() != Reveal::All => { super::VtableImpl(ref impl_data) => {
// We have to be careful when projecting out of an // We have to be careful when projecting out of an
// impl because of specialization. If we are not in // impl because of specialization. If we are not in
// trans (i.e., projection mode is not "any"), and the // trans (i.e., projection mode is not "any"), and the
@ -902,37 +902,43 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
impl_data.impl_def_id, impl_data.impl_def_id,
obligation.predicate.item_name); obligation.predicate.item_name);
let new_candidate = if let Some(node_item) = opt_node_item { let new_candidate = if let Some(node_item) = opt_node_item {
if node_item.node.is_from_trait() { let is_default = if node_item.node.is_from_trait() {
if node_item.item.ty.is_some() { // If true, the impl inherited a `type Foo = Bar`
// The impl inherited a `type Foo = // given in the trait, which is implicitly default.
// Bar` given in the trait, which is // Otherwise, the impl did not specify `type` and
// implicitly default. No candidate. // neither did the trait:
None //
} else { // ```rust
// The impl did not specify `type` and neither // trait Foo { type T; }
// did the trait: // impl Foo for Bar { }
// // ```
// ```rust //
// trait Foo { type T; } // This is an error, but it will be
// impl Foo for Bar { } // reported in `check_impl_items_against_trait`.
// ``` // We accept it here but will flag it as
// // an error when we confirm the candidate
// This is an error, but it will be // (which will ultimately lead to `normalize_to_error`
// reported in `check_impl_items_against_trait`. // being invoked).
// We accept it here but will flag it as node_item.item.ty.is_some()
// an error when we confirm the candidate
// (which will ultimately lead to `normalize_to_error`
// being invoked).
Some(ProjectionTyCandidate::Select)
}
} else if node_item.item.defaultness.is_default() {
// The impl specified `default type Foo =
// Bar`. No candidate.
None
} else { } else {
// The impl specified `type Foo = Bar` node_item.item.defaultness.is_default()
// with no default. Add a candidate. };
// Only reveal a specializable default if we're past type-checking
// and the obligations is monomorphic, otherwise passes such as
// transmute checking and polymorphic MIR optimizations could
// get a result which isn't correct for all monomorphizations.
if !is_default {
Some(ProjectionTyCandidate::Select) Some(ProjectionTyCandidate::Select)
} else if selcx.projection_mode() == Reveal::All {
assert!(!poly_trait_ref.needs_infer());
if !poly_trait_ref.needs_subst() {
Some(ProjectionTyCandidate::Select)
} else {
None
}
} else {
None
} }
} else { } else {
// This is saying that neither the trait nor // This is saying that neither the trait nor
@ -982,11 +988,6 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
}; };
candidate_set.vec.extend(new_candidate); candidate_set.vec.extend(new_candidate);
} }
super::VtableImpl(_) => {
// In trans mode, we can just project out of impls, no prob.
assert!(selcx.projection_mode() == Reveal::All);
candidate_set.vec.push(ProjectionTyCandidate::Select);
}
super::VtableParam(..) => { super::VtableParam(..) => {
// This case tell us nothing about the value of an // This case tell us nothing about the value of an
// associated type. Consider: // associated type. Consider:

View file

@ -11,6 +11,7 @@
// Tests that `transmute` cannot be called on types of different size. // Tests that `transmute` cannot be called on types of different size.
#![allow(warnings)] #![allow(warnings)]
#![feature(specialization)]
use std::mem::transmute; use std::mem::transmute;
@ -24,4 +25,15 @@ unsafe fn g<T>(x: &T) {
//~^ ERROR transmute called with differently sized types //~^ ERROR transmute called with differently sized types
} }
trait Specializable { type Output; }
impl<T> Specializable for T {
default type Output = u16;
}
unsafe fn specializable<T>(x: u16) -> <T as Specializable>::Output {
transmute(x)
//~^ ERROR transmute called with differently sized types
}
fn main() {} fn main() {}