提交 518ec125 编写于 作者: N Niko Matsakis

Normalize associated types in bounds too. Also, make the workaround

for lack of impl-trait-for-trait just a bit more targeted (don't
substitute err, just drop the troublesome bound for now) -- otherwise
substituting false types leads us into trouble when we normalize etc.
上级 cdd5ff84
......@@ -6970,13 +6970,67 @@ pub trait HasProjectionTypes {
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()
}
......@@ -7012,7 +7066,7 @@ fn has_projection_types(&self) -> bool {
}
}
impl<T> HasProjectionTypes for ty::Binder<T>
impl<T> HasProjectionTypes for Binder<T>
where T : HasProjectionTypes
{
fn has_projection_types(&self) -> bool {
......@@ -7020,23 +7074,23 @@ 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()
}
......@@ -7046,7 +7100,7 @@ pub trait ReferencesError {
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()
}
......@@ -7058,43 +7112,43 @@ fn references_error(&self) -> bool {
}
}
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 {
......@@ -7102,14 +7156,14 @@ 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
......
......@@ -10,7 +10,7 @@
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;
......@@ -32,8 +32,7 @@ pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
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)
}
......@@ -42,7 +41,6 @@ struct AssociatedTypeNormalizer<'a,'tcx:'a> {
fulfillment_cx: &'a mut FulfillmentContext<'tcx>,
span: Span,
body_id: ast::NodeId,
region_binders: uint,
}
impl<'a,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'tcx> {
......@@ -50,14 +48,6 @@ fn tcx(&self) -> &ty::ctxt<'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.
......@@ -69,10 +59,22 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
// 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,
......
......@@ -42,12 +42,6 @@ struct InstantiatedMethodSig<'tcx> {
/// 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>,
......@@ -103,7 +97,7 @@ fn confirm(&mut self,
// 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];
......@@ -111,7 +105,7 @@ fn confirm(&mut self,
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 {
......@@ -403,24 +397,17 @@ fn instantiate_method_sig(&mut self,
// 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()));
......@@ -442,18 +429,17 @@ fn instantiate_method_sig(&mut self,
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(
......@@ -461,7 +447,7 @@ fn add_obligations(&mut self,
method_bounds);
self.fcx.add_default_region_param_bounds(
method_bounds_substs,
all_substs,
self.call_expr);
}
......
......@@ -1071,7 +1071,7 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
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;
......
// 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() { }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册