Skip to content

Commit 518ec12

Browse files
committed
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.
1 parent cdd5ff8 commit 518ec12

File tree

5 files changed

+149
-66
lines changed

5 files changed

+149
-66
lines changed

src/librustc/middle/ty.rs

Lines changed: 76 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6970,13 +6970,67 @@ pub trait HasProjectionTypes {
69706970
fn has_projection_types(&self) -> bool;
69716971
}
69726972

6973+
impl<'tcx> HasProjectionTypes for ty::GenericBounds<'tcx> {
6974+
fn has_projection_types(&self) -> bool {
6975+
self.predicates.iter().any(|p| p.has_projection_types())
6976+
}
6977+
}
6978+
6979+
impl<'tcx> HasProjectionTypes for Predicate<'tcx> {
6980+
fn has_projection_types(&self) -> bool {
6981+
match *self {
6982+
Predicate::Trait(ref data) => data.has_projection_types(),
6983+
Predicate::Equate(ref data) => data.has_projection_types(),
6984+
Predicate::RegionOutlives(ref data) => data.has_projection_types(),
6985+
Predicate::TypeOutlives(ref data) => data.has_projection_types(),
6986+
Predicate::Projection(ref data) => data.has_projection_types(),
6987+
}
6988+
}
6989+
}
6990+
6991+
impl<'tcx> HasProjectionTypes for TraitPredicate<'tcx> {
6992+
fn has_projection_types(&self) -> bool {
6993+
self.trait_ref.has_projection_types()
6994+
}
6995+
}
6996+
6997+
impl<'tcx> HasProjectionTypes for EquatePredicate<'tcx> {
6998+
fn has_projection_types(&self) -> bool {
6999+
self.0.has_projection_types() || self.1.has_projection_types()
7000+
}
7001+
}
7002+
7003+
impl HasProjectionTypes for Region {
7004+
fn has_projection_types(&self) -> bool {
7005+
false
7006+
}
7007+
}
7008+
7009+
impl<T:HasProjectionTypes,U:HasProjectionTypes> HasProjectionTypes for OutlivesPredicate<T,U> {
7010+
fn has_projection_types(&self) -> bool {
7011+
self.0.has_projection_types() || self.1.has_projection_types()
7012+
}
7013+
}
7014+
7015+
impl<'tcx> HasProjectionTypes for ProjectionPredicate<'tcx> {
7016+
fn has_projection_types(&self) -> bool {
7017+
self.projection_ty.has_projection_types() || self.ty.has_projection_types()
7018+
}
7019+
}
7020+
7021+
impl<'tcx> HasProjectionTypes for ProjectionTy<'tcx> {
7022+
fn has_projection_types(&self) -> bool {
7023+
self.trait_ref.has_projection_types()
7024+
}
7025+
}
7026+
69737027
impl<'tcx> HasProjectionTypes for Ty<'tcx> {
69747028
fn has_projection_types(&self) -> bool {
69757029
ty::type_has_projection(*self)
69767030
}
69777031
}
69787032

6979-
impl<'tcx> HasProjectionTypes for ty::TraitRef<'tcx> {
7033+
impl<'tcx> HasProjectionTypes for TraitRef<'tcx> {
69807034
fn has_projection_types(&self) -> bool {
69817035
self.substs.has_projection_types()
69827036
}
@@ -7012,31 +7066,31 @@ impl<'tcx,T> HasProjectionTypes for Box<T>
70127066
}
70137067
}
70147068

7015-
impl<T> HasProjectionTypes for ty::Binder<T>
7069+
impl<T> HasProjectionTypes for Binder<T>
70167070
where T : HasProjectionTypes
70177071
{
70187072
fn has_projection_types(&self) -> bool {
70197073
self.0.has_projection_types()
70207074
}
70217075
}
70227076

7023-
impl<'tcx> HasProjectionTypes for ty::FnOutput<'tcx> {
7077+
impl<'tcx> HasProjectionTypes for FnOutput<'tcx> {
70247078
fn has_projection_types(&self) -> bool {
70257079
match *self {
7026-
ty::FnConverging(t) => t.has_projection_types(),
7027-
ty::FnDiverging => false,
7080+
FnConverging(t) => t.has_projection_types(),
7081+
FnDiverging => false,
70287082
}
70297083
}
70307084
}
70317085

7032-
impl<'tcx> HasProjectionTypes for ty::FnSig<'tcx> {
7086+
impl<'tcx> HasProjectionTypes for FnSig<'tcx> {
70337087
fn has_projection_types(&self) -> bool {
70347088
self.inputs.iter().any(|t| t.has_projection_types()) ||
70357089
self.output.has_projection_types()
70367090
}
70377091
}
70387092

7039-
impl<'tcx> HasProjectionTypes for ty::BareFnTy<'tcx> {
7093+
impl<'tcx> HasProjectionTypes for BareFnTy<'tcx> {
70407094
fn has_projection_types(&self) -> bool {
70417095
self.sig.has_projection_types()
70427096
}
@@ -7046,7 +7100,7 @@ pub trait ReferencesError {
70467100
fn references_error(&self) -> bool;
70477101
}
70487102

7049-
impl<T:ReferencesError> ReferencesError for ty::Binder<T> {
7103+
impl<T:ReferencesError> ReferencesError for Binder<T> {
70507104
fn references_error(&self) -> bool {
70517105
self.0.references_error()
70527106
}
@@ -7058,58 +7112,58 @@ impl<T:ReferencesError> ReferencesError for Rc<T> {
70587112
}
70597113
}
70607114

7061-
impl<'tcx> ReferencesError for ty::TraitPredicate<'tcx> {
7115+
impl<'tcx> ReferencesError for TraitPredicate<'tcx> {
70627116
fn references_error(&self) -> bool {
70637117
self.trait_ref.references_error()
70647118
}
70657119
}
70667120

7067-
impl<'tcx> ReferencesError for ty::ProjectionPredicate<'tcx> {
7121+
impl<'tcx> ReferencesError for ProjectionPredicate<'tcx> {
70687122
fn references_error(&self) -> bool {
70697123
self.projection_ty.trait_ref.references_error() || self.ty.references_error()
70707124
}
70717125
}
70727126

7073-
impl<'tcx> ReferencesError for ty::TraitRef<'tcx> {
7127+
impl<'tcx> ReferencesError for TraitRef<'tcx> {
70747128
fn references_error(&self) -> bool {
70757129
self.input_types().iter().any(|t| t.references_error())
70767130
}
70777131
}
70787132

7079-
impl<'tcx> ReferencesError for ty::Ty<'tcx> {
7133+
impl<'tcx> ReferencesError for Ty<'tcx> {
70807134
fn references_error(&self) -> bool {
7081-
ty::type_is_error(*self)
7135+
type_is_error(*self)
70827136
}
70837137
}
70847138

7085-
impl<'tcx> ReferencesError for ty::Predicate<'tcx> {
7139+
impl<'tcx> ReferencesError for Predicate<'tcx> {
70867140
fn references_error(&self) -> bool {
70877141
match *self {
7088-
ty::Predicate::Trait(ref data) => data.references_error(),
7089-
ty::Predicate::Equate(ref data) => data.references_error(),
7090-
ty::Predicate::RegionOutlives(ref data) => data.references_error(),
7091-
ty::Predicate::TypeOutlives(ref data) => data.references_error(),
7092-
ty::Predicate::Projection(ref data) => data.references_error(),
7142+
Predicate::Trait(ref data) => data.references_error(),
7143+
Predicate::Equate(ref data) => data.references_error(),
7144+
Predicate::RegionOutlives(ref data) => data.references_error(),
7145+
Predicate::TypeOutlives(ref data) => data.references_error(),
7146+
Predicate::Projection(ref data) => data.references_error(),
70937147
}
70947148
}
70957149
}
70967150

7097-
impl<A,B> ReferencesError for ty::OutlivesPredicate<A,B>
7151+
impl<A,B> ReferencesError for OutlivesPredicate<A,B>
70987152
where A : ReferencesError, B : ReferencesError
70997153
{
71007154
fn references_error(&self) -> bool {
71017155
self.0.references_error() || self.1.references_error()
71027156
}
71037157
}
71047158

7105-
impl<'tcx> ReferencesError for ty::EquatePredicate<'tcx>
7159+
impl<'tcx> ReferencesError for EquatePredicate<'tcx>
71067160
{
71077161
fn references_error(&self) -> bool {
71087162
self.0.references_error() || self.1.references_error()
71097163
}
71107164
}
71117165

7112-
impl ReferencesError for ty::Region
7166+
impl ReferencesError for Region
71137167
{
71147168
fn references_error(&self) -> bool {
71157169
false

src/librustc_typeck/check/assoc.rs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use middle::infer::InferCtxt;
1212
use middle::traits::{ObligationCause, ObligationCauseCode, FulfillmentContext};
13-
use middle::ty::{mod, HasProjectionTypes, Ty};
13+
use middle::ty::{mod, RegionEscape, HasProjectionTypes, Ty};
1414
use middle::ty_fold::{mod, TypeFoldable, TypeFolder};
1515
use syntax::ast;
1616
use syntax::codemap::Span;
@@ -32,8 +32,7 @@ pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
3232
let mut normalizer = AssociatedTypeNormalizer { span: span,
3333
body_id: body_id,
3434
infcx: infcx,
35-
fulfillment_cx: fulfillment_cx,
36-
region_binders: 0 };
35+
fulfillment_cx: fulfillment_cx };
3736
value.fold_with(&mut normalizer)
3837
}
3938

@@ -42,22 +41,13 @@ struct AssociatedTypeNormalizer<'a,'tcx:'a> {
4241
fulfillment_cx: &'a mut FulfillmentContext<'tcx>,
4342
span: Span,
4443
body_id: ast::NodeId,
45-
region_binders: uint,
4644
}
4745

4846
impl<'a,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'tcx> {
4947
fn tcx(&self) -> &ty::ctxt<'tcx> {
5048
self.infcx.tcx
5149
}
5250

53-
fn enter_region_binder(&mut self) {
54-
self.region_binders += 1;
55-
}
56-
57-
fn exit_region_binder(&mut self) {
58-
self.region_binders -= 1;
59-
}
60-
6151
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
6252
// We don't want to normalize associated types that occur inside of region
6353
// binders, because they may contain bound regions, and we can't cope with that.
@@ -69,10 +59,22 @@ impl<'a,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'tcx> {
6959
// Instead of normalizing `<T as Foo<&'a>>::A` here, we'll
7060
// normalize it when we instantiate those bound regions (which
7161
// should occur eventually).
72-
let no_region_binders = self.region_binders == 0;
7362

7463
match ty.sty {
75-
ty::ty_projection(ref data) if no_region_binders => {
64+
ty::ty_projection(ref data) if !data.has_escaping_regions() => { // (*)
65+
66+
// (*) This is kind of hacky -- we need to be able to
67+
// handle normalization within binders because
68+
// otherwise we wind up a need to normalize when doing
69+
// trait matching (since you can have a trait
70+
// obligation like `for<'a> T::B : Fn(&'a int)`), but
71+
// we can't normalize with bound regions in scope. So
72+
// far now we just ignore binders but only normalize
73+
// if all bound regions are gone (and then we still
74+
// have to renormalize whenever we instantiate a
75+
// binder). It would be better to normalize in a
76+
// binding-aware fashion.
77+
7678
let cause =
7779
ObligationCause::new(
7880
self.span,

src/librustc_typeck/check/method/confirm.rs

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,6 @@ struct InstantiatedMethodSig<'tcx> {
4242
/// the method.
4343
all_substs: subst::Substs<'tcx>,
4444

45-
/// Substitution to use when adding obligations from the method
46-
/// bounds. Normally equal to `all_substs` except for object
47-
/// receivers. See FIXME in instantiate_method_sig() for
48-
/// explanation.
49-
method_bounds_substs: subst::Substs<'tcx>,
50-
5145
/// Generic bounds on the method's parameters which must be added
5246
/// as pending obligations.
5347
method_bounds: ty::GenericBounds<'tcx>,
@@ -103,15 +97,15 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
10397

10498
// Create the final signature for the method, replacing late-bound regions.
10599
let InstantiatedMethodSig {
106-
method_sig, all_substs, method_bounds_substs, method_bounds
100+
method_sig, all_substs, method_bounds
107101
} = self.instantiate_method_sig(&pick, all_substs);
108102
let method_self_ty = method_sig.inputs[0];
109103

110104
// Unify the (adjusted) self type with what the method expects.
111105
self.unify_receivers(self_ty, method_self_ty);
112106

113107
// Add any trait/regions obligations specified on the method's type parameters.
114-
self.add_obligations(&pick, &method_bounds_substs, &method_bounds);
108+
self.add_obligations(&pick, &all_substs, &method_bounds);
115109

116110
// Create the final `MethodCallee`.
117111
let fty = ty::mk_bare_fn(self.tcx(), None, self.tcx().mk_bare_fn(ty::BareFnTy {
@@ -403,24 +397,17 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
403397
// type `Trait`, this leads to an obligation
404398
// `Trait:Trait`. Until such time we DST is fully implemented,
405399
// that obligation is not necessarily satisfied. (In the
406-
// future, it would be.)
407-
//
408-
// To sidestep this, we overwrite the binding for `Self` with
409-
// `err` (just for trait objects) when we generate the
410-
// obligations. This causes us to generate the obligation
411-
// `err:Trait`, and the error type is considered to implement
412-
// all traits, so we're all good. Hack hack hack.
413-
let method_bounds_substs = match pick.kind {
400+
// future, it would be.) But we know that the true `Self` DOES implement
401+
// the trait. So we just delete this requirement. Hack hack hack.
402+
let mut method_bounds = pick.method_ty.generics.to_bounds(self.tcx(), &all_substs);
403+
match pick.kind {
414404
probe::ObjectPick(..) => {
415-
let mut temp_substs = all_substs.clone();
416-
temp_substs.types.get_mut_slice(subst::SelfSpace)[0] = self.tcx().types.err;
417-
temp_substs
405+
assert_eq!(method_bounds.predicates.get_slice(subst::SelfSpace).len(), 1);
406+
method_bounds.predicates.pop(subst::SelfSpace);
418407
}
419-
_ => {
420-
all_substs.clone()
421-
}
422-
};
423-
let method_bounds = pick.method_ty.generics.to_bounds(self.tcx(), &method_bounds_substs);
408+
_ => { }
409+
}
410+
let method_bounds = self.fcx.normalize_associated_types_in(self.span, &method_bounds);
424411

425412
debug!("method_bounds after subst = {}",
426413
method_bounds.repr(self.tcx()));
@@ -442,26 +429,25 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
442429
InstantiatedMethodSig {
443430
method_sig: method_sig,
444431
all_substs: all_substs,
445-
method_bounds_substs: method_bounds_substs,
446432
method_bounds: method_bounds,
447433
}
448434
}
449435

450436
fn add_obligations(&mut self,
451437
pick: &probe::Pick<'tcx>,
452-
method_bounds_substs: &subst::Substs<'tcx>,
438+
all_substs: &subst::Substs<'tcx>,
453439
method_bounds: &ty::GenericBounds<'tcx>) {
454-
debug!("add_obligations: pick={} method_bounds_substs={} method_bounds={}",
440+
debug!("add_obligations: pick={} all_substs={} method_bounds={}",
455441
pick.repr(self.tcx()),
456-
method_bounds_substs.repr(self.tcx()),
442+
all_substs.repr(self.tcx()),
457443
method_bounds.repr(self.tcx()));
458444

459445
self.fcx.add_obligations_for_parameters(
460446
traits::ObligationCause::misc(self.span, self.fcx.body_id),
461447
method_bounds);
462448

463449
self.fcx.add_default_region_param_bounds(
464-
method_bounds_substs,
450+
all_substs,
465451
self.call_expr);
466452
}
467453

src/librustc_typeck/collect.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1071,7 +1071,7 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
10711071
debug!("ty_generics_for_trait: assoc_predicates={}", assoc_predicates.repr(ccx.tcx));
10721072

10731073
for assoc_predicate in assoc_predicates.into_iter() {
1074-
generics.predicates.push(subst::SelfSpace, assoc_predicate);
1074+
generics.predicates.push(subst::TypeSpace, assoc_predicate);
10751075
}
10761076

10771077
return generics;

0 commit comments

Comments
 (0)