rustc: don't reveal specializable polymorphic projections.
This commit is contained in:
parent
ab26dbb96f
commit
c976e073fd
2 changed files with 49 additions and 36 deletions
|
@ -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:
|
||||||
|
|
|
@ -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() {}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue