diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index e23826ee99..33b01685df 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -2718,7 +2718,7 @@ fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// Compute the bounds on Self and the type parameters.
let bounds = tcx.predicates_of(def_id).instantiate_identity(tcx);
- let mut predicates = bounds.predicates;
+ let predicates = bounds.predicates;
// Finally, we have to normalize the bounds in the environment, in
// case they contain any associated type projections. This process
@@ -2732,10 +2732,10 @@ fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// are any errors at that point, so after type checking you can be
// sure that this will succeed without errors anyway.
- if is_trait(tcx, def_id) {
- // Add `Self: Trait` into the ParamEnv.
- predicates.push(ty::TraitRef::identity(tcx, def_id).to_predicate());
- }
+ // if is_trait(tcx, def_id) {
+ // // Add `Self: Trait` into the ParamEnv.
+ // predicates.push(ty::TraitRef::identity(tcx, def_id).to_predicate());
+ // }
let unnormalized_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates),
traits::Reveal::UserFacing);
Normalizing the parameter environment for traits fails otherwise. Consider the
following excerpt from libcore
:
pub trait RawFloat
: Float
+ Copy
+ Debug
+ LowerExp
+ Mul<Output=Self>
+ Div<Output=Self>
+ Neg<Output=Self>
where
Self: Float<Bits = <Self as RawFloat>::RawBits>
{ ... }
we are not able to normalize <Self as RawFloat>::RawBits
. Put
another way, on what basis would we conclude that this type is
well-formed?
modified src/librustc/ty/wf.rs
@@ -456,11 +456,11 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
{
// Add in a predicate that `Self:Trait` (where `Trait` is the
// current trait).
- let self_trait = if !trait_ref.has_escaping_regions() {
+ let self_trait = None; /*if !trait_ref.has_escaping_regions() {
Some(trait_ref.to_predicate())
} else {
None
- };
+ };*/
let predicates = self.infcx.tcx.predicates_of(trait_ref.def_id)
We get the following test failures:
https://gist.github.com/nikomatsakis/b2ff6bd75da58c34a5582c9f55655a68
However, it's unclear that all of these are problematic, though some are a bit weird.
modified src/librustc_typeck/check/compare_method.rs
@@ -30,7 +30,6 @@ use super::{Inherited, FnCtxt};
/// - impl_m_span: span to use for reporting errors
/// - trait_m: the method in the trait
/// - impl_trait_ref: the TraitRef corresponding to the trait implementation
-
pub fn compare_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
impl_m: &ty::AssociatedItem,
impl_m_span: Span,
@@ -182,7 +181,31 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let impl_m_generics = tcx.generics_of(impl_m.def_id);
let trait_m_generics = tcx.generics_of(trait_m.def_id);
let impl_m_predicates = tcx.predicates_of(impl_m.def_id);
- let trait_m_predicates = tcx.predicates_of(trait_m.def_id);
+ let mut trait_m_predicates = tcx.predicates_of(trait_m.def_id);
+
+ // A `Self: Trait` predicate on trait items breaks selection, so filter it out.
+ // FIXME: This is a big hack!
+ if let Some(trait_def_id) = trait_m_predicates.parent {
+ trait_m_predicates.predicates.retain(|pred| {
+ match pred {
+ ty::Predicate::Trait(trait_ref) => {
+ if trait_ref.def_id() == trait_def_id {
+ use ty::TypeVariants::TyParam;
+ if let TyParam(param) = trait_ref.skip_binder().self_ty().sty {
+ if param.is_self() {
+ debug!(
+ "compare_impl_method: removing `{:?}` from trait_m_predicates",
+ pred);
+ return false;
+ }
+ }
+ }
+ true
+ }
+ _ => true
+ }
+ });
+ }
It seems clear why this is needed.
@@ -1421,6 +1422,14 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
predicates.push(trait_ref.to_poly_trait_ref().to_predicate());
}
+ // For trait items, add `Self: Trait` predicate.
+ if is_trait_item {
+ let parent_id = tcx.hir.get_parent(node_id);
+ let parent_def_id = tcx.hir.local_def_id(parent_id);
+ debug_assert!(ty::is_trait_node(tcx, parent_id));
+ predicates.push(ty::TraitRef::identity(tcx, parent_def_id).to_predicate());
+ }
+
// Collect the region predicates that were declared inline as
// well. In the case of parameters declared on a fn or method, we
Unstaged changes (4)
modified src/librustc/ty/mod.rs
@@ -2735,6 +2735,8 @@ fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
if is_trait(tcx, def_id) {
// Add `Self: Trait` into the ParamEnv.
predicates.push(ty::TraitRef::identity(tcx, def_id).to_predicate());
+ } else if let Some(trait_def_id) = is_trait_item(tcx, def_id) {
+ predicates.push(ty::TraitRef::identity(tcx, trait_def_id).to_predicate());
}
let unnormalized_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates),
@@ -2755,6 +2757,20 @@ pub fn is_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool {
}
}
+/// If `def_id` is a trait item, returns the def-id of the trait (else `None`).
+fn is_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option<DefId> {
+ // FIXME I would rather do this with the def-key but I can't be bothered
+ // to refactor that right now -- also this is wrong across crates.
+ if let Some(id) = tcx.hir.as_local_node_id(def_id) {
+ match tcx.hir.find(id) {
+ Some(hir::map::NodeTraitItem(_)) => Some(tcx.hir.get_parent_did(id)),
+ _ => None,
+ }
+ } else {
+ None
+ }
+}
+
pub fn is_trait_node<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId) -> bool {
if let Some(hir::map::NodeItem(item)) = tcx.hir.find(id) {
if let hir::ItemTrait(..) = item.node {
modified src/librustc_typeck/check/compare_method.rs
@@ -181,31 +181,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let impl_m_generics = tcx.generics_of(impl_m.def_id);
let trait_m_generics = tcx.generics_of(trait_m.def_id);
let impl_m_predicates = tcx.predicates_of(impl_m.def_id);
- let mut trait_m_predicates = tcx.predicates_of(trait_m.def_id);
-
- // A `Self: Trait` predicate on trait items breaks selection, so filter it out.
- // FIXME: This is a big hack!
- if let Some(trait_def_id) = trait_m_predicates.parent {
- trait_m_predicates.predicates.retain(|pred| {
- match pred {
- ty::Predicate::Trait(trait_ref) => {
- if trait_ref.def_id() == trait_def_id {
- use ty::TypeVariants::TyParam;
- if let TyParam(param) = trait_ref.skip_binder().self_ty().sty {
- if param.is_self() {
- debug!(
- "compare_impl_method: removing `{:?}` from trait_m_predicates",
- pred);
- return false;
- }
- }
- }
- true
- }
- _ => true
- }
- });
- }
+ let trait_m_predicates = tcx.predicates_of(trait_m.def_id);
// Check region bounds.
check_region_bounds_on_impl_method(tcx,
modified src/librustc_typeck/collect.rs
@@ -1321,14 +1321,12 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let node = tcx.hir.get(node_id);
let mut is_trait = None;
- let mut is_trait_item = false;
let mut is_default_impl_trait = None;
let icx = ItemCtxt::new(tcx, def_id);
let no_generics = hir::Generics::empty();
let ast_generics = match node {
NodeTraitItem(item) => {
- is_trait_item = true;
&item.generics
}
@@ -1422,14 +1420,6 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
predicates.push(trait_ref.to_poly_trait_ref().to_predicate());
}
- // For trait items, add `Self: Trait` predicate.
- if is_trait_item {
- let parent_id = tcx.hir.get_parent(node_id);
- let parent_def_id = tcx.hir.local_def_id(parent_id);
- debug_assert!(ty::is_trait_node(tcx, parent_id));
- predicates.push(ty::TraitRef::identity(tcx, parent_def_id).to_predicate());
- }
-
// Collect the region predicates that were declared inline as
// well. In the case of parameters declared on a fn or method, we
// have to be careful to only iterate over early-bound regions.
results in
error[E0282]: type annotations needed
--> libcore/num/dec2flt/rawfp.rs:188:32
|
188 | debug_assert!(x as f32 == fp_to_float(Fp { f: x, e: 0 }));
| ^^ cannot infer type for `_`
(haven't had time to investigate further)