fn has_projection_types(&self) -> bool;
}
+impl<'tcx> HasProjectionTypes for ty::GenericBounds<'tcx> {
+ fn has_projection_types(&self) -> bool {
+ self.predicates.iter().any(|p| p.has_projection_types())
+ }
+}
+
+impl<'tcx> HasProjectionTypes for Predicate<'tcx> {
+ fn has_projection_types(&self) -> bool {
+ match *self {
+ Predicate::Trait(ref data) => data.has_projection_types(),
+ Predicate::Equate(ref data) => data.has_projection_types(),
+ Predicate::RegionOutlives(ref data) => data.has_projection_types(),
+ Predicate::TypeOutlives(ref data) => data.has_projection_types(),
+ Predicate::Projection(ref data) => data.has_projection_types(),
+ }
+ }
+}
+
+impl<'tcx> HasProjectionTypes for TraitPredicate<'tcx> {
+ fn has_projection_types(&self) -> bool {
+ self.trait_ref.has_projection_types()
+ }
+}
+
+impl<'tcx> HasProjectionTypes for EquatePredicate<'tcx> {
+ fn has_projection_types(&self) -> bool {
+ self.0.has_projection_types() || self.1.has_projection_types()
+ }
+}
+
+impl HasProjectionTypes for Region {
+ fn has_projection_types(&self) -> bool {
+ false
+ }
+}
+
+impl<T:HasProjectionTypes,U:HasProjectionTypes> HasProjectionTypes for OutlivesPredicate<T,U> {
+ fn has_projection_types(&self) -> bool {
+ self.0.has_projection_types() || self.1.has_projection_types()
+ }
+}
+
+impl<'tcx> HasProjectionTypes for ProjectionPredicate<'tcx> {
+ fn has_projection_types(&self) -> bool {
+ self.projection_ty.has_projection_types() || self.ty.has_projection_types()
+ }
+}
+
+impl<'tcx> HasProjectionTypes for ProjectionTy<'tcx> {
+ fn has_projection_types(&self) -> bool {
+ self.trait_ref.has_projection_types()
+ }
+}
+
impl<'tcx> HasProjectionTypes for Ty<'tcx> {
fn has_projection_types(&self) -> bool {
ty::type_has_projection(*self)
}
}
-impl<'tcx> HasProjectionTypes for ty::TraitRef<'tcx> {
+impl<'tcx> HasProjectionTypes for TraitRef<'tcx> {
fn has_projection_types(&self) -> bool {
self.substs.has_projection_types()
}
}
}
-impl<T> HasProjectionTypes for ty::Binder<T>
+impl<T> HasProjectionTypes for Binder<T>
where T : HasProjectionTypes
{
fn has_projection_types(&self) -> bool {
}
}
-impl<'tcx> HasProjectionTypes for ty::FnOutput<'tcx> {
+impl<'tcx> HasProjectionTypes for FnOutput<'tcx> {
fn has_projection_types(&self) -> bool {
match *self {
- ty::FnConverging(t) => t.has_projection_types(),
- ty::FnDiverging => false,
+ FnConverging(t) => t.has_projection_types(),
+ FnDiverging => false,
}
}
}
-impl<'tcx> HasProjectionTypes for ty::FnSig<'tcx> {
+impl<'tcx> HasProjectionTypes for FnSig<'tcx> {
fn has_projection_types(&self) -> bool {
self.inputs.iter().any(|t| t.has_projection_types()) ||
self.output.has_projection_types()
}
}
-impl<'tcx> HasProjectionTypes for ty::BareFnTy<'tcx> {
+impl<'tcx> HasProjectionTypes for BareFnTy<'tcx> {
fn has_projection_types(&self) -> bool {
self.sig.has_projection_types()
}
fn references_error(&self) -> bool;
}
-impl<T:ReferencesError> ReferencesError for ty::Binder<T> {
+impl<T:ReferencesError> ReferencesError for Binder<T> {
fn references_error(&self) -> bool {
self.0.references_error()
}
}
}
-impl<'tcx> ReferencesError for ty::TraitPredicate<'tcx> {
+impl<'tcx> ReferencesError for TraitPredicate<'tcx> {
fn references_error(&self) -> bool {
self.trait_ref.references_error()
}
}
-impl<'tcx> ReferencesError for ty::ProjectionPredicate<'tcx> {
+impl<'tcx> ReferencesError for ProjectionPredicate<'tcx> {
fn references_error(&self) -> bool {
self.projection_ty.trait_ref.references_error() || self.ty.references_error()
}
}
-impl<'tcx> ReferencesError for ty::TraitRef<'tcx> {
+impl<'tcx> ReferencesError for TraitRef<'tcx> {
fn references_error(&self) -> bool {
self.input_types().iter().any(|t| t.references_error())
}
}
-impl<'tcx> ReferencesError for ty::Ty<'tcx> {
+impl<'tcx> ReferencesError for Ty<'tcx> {
fn references_error(&self) -> bool {
- ty::type_is_error(*self)
+ type_is_error(*self)
}
}
-impl<'tcx> ReferencesError for ty::Predicate<'tcx> {
+impl<'tcx> ReferencesError for Predicate<'tcx> {
fn references_error(&self) -> bool {
match *self {
- ty::Predicate::Trait(ref data) => data.references_error(),
- ty::Predicate::Equate(ref data) => data.references_error(),
- ty::Predicate::RegionOutlives(ref data) => data.references_error(),
- ty::Predicate::TypeOutlives(ref data) => data.references_error(),
- ty::Predicate::Projection(ref data) => data.references_error(),
+ Predicate::Trait(ref data) => data.references_error(),
+ Predicate::Equate(ref data) => data.references_error(),
+ Predicate::RegionOutlives(ref data) => data.references_error(),
+ Predicate::TypeOutlives(ref data) => data.references_error(),
+ Predicate::Projection(ref data) => data.references_error(),
}
}
}
-impl<A,B> ReferencesError for ty::OutlivesPredicate<A,B>
+impl<A,B> ReferencesError for OutlivesPredicate<A,B>
where A : ReferencesError, B : ReferencesError
{
fn references_error(&self) -> bool {
}
}
-impl<'tcx> ReferencesError for ty::EquatePredicate<'tcx>
+impl<'tcx> ReferencesError for EquatePredicate<'tcx>
{
fn references_error(&self) -> bool {
self.0.references_error() || self.1.references_error()
}
}
-impl ReferencesError for ty::Region
+impl ReferencesError for Region
{
fn references_error(&self) -> bool {
false
use middle::infer::InferCtxt;
use middle::traits::{ObligationCause, ObligationCauseCode, FulfillmentContext};
-use middle::ty::{mod, HasProjectionTypes, Ty};
+use middle::ty::{mod, RegionEscape, HasProjectionTypes, Ty};
use middle::ty_fold::{mod, TypeFoldable, TypeFolder};
use syntax::ast;
use syntax::codemap::Span;
let mut normalizer = AssociatedTypeNormalizer { span: span,
body_id: body_id,
infcx: infcx,
- fulfillment_cx: fulfillment_cx,
- region_binders: 0 };
+ fulfillment_cx: fulfillment_cx };
value.fold_with(&mut normalizer)
}
fulfillment_cx: &'a mut FulfillmentContext<'tcx>,
span: Span,
body_id: ast::NodeId,
- region_binders: uint,
}
impl<'a,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'tcx> {
self.infcx.tcx
}
- fn enter_region_binder(&mut self) {
- self.region_binders += 1;
- }
-
- fn exit_region_binder(&mut self) {
- self.region_binders -= 1;
- }
-
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
// We don't want to normalize associated types that occur inside of region
// binders, because they may contain bound regions, and we can't cope with that.
// Instead of normalizing `<T as Foo<&'a>>::A` here, we'll
// normalize it when we instantiate those bound regions (which
// should occur eventually).
- let no_region_binders = self.region_binders == 0;
match ty.sty {
- ty::ty_projection(ref data) if no_region_binders => {
+ ty::ty_projection(ref data) if !data.has_escaping_regions() => { // (*)
+
+ // (*) This is kind of hacky -- we need to be able to
+ // handle normalization within binders because
+ // otherwise we wind up a need to normalize when doing
+ // trait matching (since you can have a trait
+ // obligation like `for<'a> T::B : Fn(&'a int)`), but
+ // we can't normalize with bound regions in scope. So
+ // far now we just ignore binders but only normalize
+ // if all bound regions are gone (and then we still
+ // have to renormalize whenever we instantiate a
+ // binder). It would be better to normalize in a
+ // binding-aware fashion.
+
let cause =
ObligationCause::new(
self.span,
/// the method.
all_substs: subst::Substs<'tcx>,
- /// Substitution to use when adding obligations from the method
- /// bounds. Normally equal to `all_substs` except for object
- /// receivers. See FIXME in instantiate_method_sig() for
- /// explanation.
- method_bounds_substs: subst::Substs<'tcx>,
-
/// Generic bounds on the method's parameters which must be added
/// as pending obligations.
method_bounds: ty::GenericBounds<'tcx>,
// Create the final signature for the method, replacing late-bound regions.
let InstantiatedMethodSig {
- method_sig, all_substs, method_bounds_substs, method_bounds
+ method_sig, all_substs, method_bounds
} = self.instantiate_method_sig(&pick, all_substs);
let method_self_ty = method_sig.inputs[0];
self.unify_receivers(self_ty, method_self_ty);
// Add any trait/regions obligations specified on the method's type parameters.
- self.add_obligations(&pick, &method_bounds_substs, &method_bounds);
+ self.add_obligations(&pick, &all_substs, &method_bounds);
// Create the final `MethodCallee`.
let fty = ty::mk_bare_fn(self.tcx(), None, self.tcx().mk_bare_fn(ty::BareFnTy {
// type `Trait`, this leads to an obligation
// `Trait:Trait`. Until such time we DST is fully implemented,
// that obligation is not necessarily satisfied. (In the
- // future, it would be.)
- //
- // To sidestep this, we overwrite the binding for `Self` with
- // `err` (just for trait objects) when we generate the
- // obligations. This causes us to generate the obligation
- // `err:Trait`, and the error type is considered to implement
- // all traits, so we're all good. Hack hack hack.
- let method_bounds_substs = match pick.kind {
+ // future, it would be.) But we know that the true `Self` DOES implement
+ // the trait. So we just delete this requirement. Hack hack hack.
+ let mut method_bounds = pick.method_ty.generics.to_bounds(self.tcx(), &all_substs);
+ match pick.kind {
probe::ObjectPick(..) => {
- let mut temp_substs = all_substs.clone();
- temp_substs.types.get_mut_slice(subst::SelfSpace)[0] = self.tcx().types.err;
- temp_substs
+ assert_eq!(method_bounds.predicates.get_slice(subst::SelfSpace).len(), 1);
+ method_bounds.predicates.pop(subst::SelfSpace);
}
- _ => {
- all_substs.clone()
- }
- };
- let method_bounds = pick.method_ty.generics.to_bounds(self.tcx(), &method_bounds_substs);
+ _ => { }
+ }
+ let method_bounds = self.fcx.normalize_associated_types_in(self.span, &method_bounds);
debug!("method_bounds after subst = {}",
method_bounds.repr(self.tcx()));
InstantiatedMethodSig {
method_sig: method_sig,
all_substs: all_substs,
- method_bounds_substs: method_bounds_substs,
method_bounds: method_bounds,
}
}
fn add_obligations(&mut self,
pick: &probe::Pick<'tcx>,
- method_bounds_substs: &subst::Substs<'tcx>,
+ all_substs: &subst::Substs<'tcx>,
method_bounds: &ty::GenericBounds<'tcx>) {
- debug!("add_obligations: pick={} method_bounds_substs={} method_bounds={}",
+ debug!("add_obligations: pick={} all_substs={} method_bounds={}",
pick.repr(self.tcx()),
- method_bounds_substs.repr(self.tcx()),
+ all_substs.repr(self.tcx()),
method_bounds.repr(self.tcx()));
self.fcx.add_obligations_for_parameters(
method_bounds);
self.fcx.add_default_region_param_bounds(
- method_bounds_substs,
+ all_substs,
self.call_expr);
}
debug!("ty_generics_for_trait: assoc_predicates={}", assoc_predicates.repr(ccx.tcx));
for assoc_predicate in assoc_predicates.into_iter() {
- generics.predicates.push(subst::SelfSpace, assoc_predicate);
+ generics.predicates.push(subst::TypeSpace, assoc_predicate);
}
return generics;
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we normalize associated types that appear in bounds; if
+// we didn't, the call to `self.split2()` fails to type check.
+
+#![feature(associated_types)]
+
+struct Splits<'a, T, P>;
+struct SplitsN<I>;
+
+trait SliceExt2 for Sized? {
+ type Item;
+
+ fn split2<'a, P>(&'a self, pred: P) -> Splits<'a, Self::Item, P>
+ where P: FnMut(&Self::Item) -> bool;
+ fn splitn2<'a, P>(&'a self, n: uint, pred: P) -> SplitsN<Splits<'a, Self::Item, P>>
+ where P: FnMut(&Self::Item) -> bool;
+}
+
+impl<T> SliceExt2 for [T] {
+ type Item = T;
+
+ fn split2<P>(&self, pred: P) -> Splits<T, P> where P: FnMut(&T) -> bool {
+ loop {}
+ }
+
+ fn splitn2<P>(&self, n: uint, pred: P) -> SplitsN<Splits<T, P>> where P: FnMut(&T) -> bool {
+ self.split2(pred);
+ loop {}
+ }
+}
+
+fn main() { }