Skip to content

Commit 4bfef5c

Browse files
committed
Error for where-clause with unconstrained late-bound lifetimes
1 parent c8b2d18 commit 4bfef5c

File tree

3 files changed

+106
-2
lines changed

3 files changed

+106
-2
lines changed

src/librustc/ty/fold.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,8 @@ impl<'tcx> TyCtxt<'tcx> {
387387
where T : TypeFoldable<'tcx>
388388
{
389389
let mut collector = LateBoundRegionsCollector::new();
390-
value.skip_binder().visit_with(&mut collector);
390+
let result = value.skip_binder().visit_with(&mut collector);
391+
assert!(!result); // should never have stopped early
391392
collector.regions
392393
}
393394

@@ -667,7 +668,7 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
667668
}
668669
_ => { }
669670
}
670-
true
671+
false
671672
}
672673
}
673674

src/librustc_typeck/astconv.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,10 @@ fn ast_type_binding_to_poly_projection_predicate<'tcx>(
892892
{
893893
let tcx = this.tcx();
894894

895+
debug!("ast_type_binding_to_poly_projection_predicate()");
896+
debug!("trait_ref = {:?}", trait_ref);
897+
debug!("self_ty = {:?}", self_ty);
898+
895899
// Given something like `U : SomeTrait<T=X>`, we want to produce a
896900
// predicate like `<U as SomeTrait>::T = X`. This is somewhat
897901
// subtle in the event that `T` is defined in a supertrait of
@@ -908,6 +912,34 @@ fn ast_type_binding_to_poly_projection_predicate<'tcx>(
908912
//
909913
// We want to produce `<B as SuperTrait<int>>::T == foo`.
910914

915+
// Find any late-bound regions declared in `ty` that are not
916+
// declared in the trait-ref. These are not wellformed.
917+
//
918+
// Example:
919+
//
920+
// for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
921+
// for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
922+
let late_bound_in_trait_ref = tcx.collect_late_bound_regions(&trait_ref);
923+
let late_bound_in_ty = tcx.collect_late_bound_regions(&ty::Binder(binding.ty));
924+
debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref);
925+
debug!("late_bound_in_ty = {:?}", late_bound_in_ty);
926+
for br in late_bound_in_ty.difference(&late_bound_in_trait_ref) {
927+
let br_name = match *br {
928+
ty::BrNamed(_, name) => name,
929+
_ => {
930+
this.tcx().sess.span_bug(
931+
binding.span,
932+
&format!("anonymous bound region {:?} in binding but not trait ref",
933+
br));
934+
}
935+
};
936+
this.tcx().sess.span_err(
937+
binding.span,
938+
&format!("binding for associated type `{}` references lifetime `{}`, \
939+
which does not appear in the trait input types",
940+
binding.item_name, br_name));
941+
}
942+
911943
// Simple case: X is defined in the current trait.
912944
if this.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) {
913945
return Ok(ty::Binder(ty::ProjectionPredicate { // <-------------------+
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// revisions: angle paren ok elision
12+
13+
#![allow(dead_code)]
14+
#![feature(rustc_attrs)]
15+
#![feature(unboxed_closures)]
16+
17+
trait Foo {
18+
type Item;
19+
}
20+
21+
#[cfg(angle)]
22+
fn angle<T: for<'a> Foo<Item=&'a i32>>() {
23+
//[angle]~^ ERROR binding for associated type `Item` references lifetime `'a`
24+
}
25+
26+
#[cfg(angle)]
27+
fn angle1<T>() where T: for<'a> Foo<Item=&'a i32>>() {
28+
//[angle]~^ ERROR binding for associated type `Item` references lifetime `'a`
29+
}
30+
31+
#[cfg(angle)]
32+
fn angle2<T>() where for<'a> T: Foo<Item=&'a i32>>() {
33+
//[angle]~^ ERROR binding for associated type `Item` references lifetime `'a`
34+
}
35+
36+
#[cfg(paren)]
37+
fn paren<T: for<'a> Fn() -> &'a i32>() {
38+
//[paren]~^ ERROR binding for associated type `Output` references lifetime `'a`
39+
}
40+
41+
#[cfg(paren)]
42+
fn paren1<T> where T: for<'a> Fn() -> &'a i32>() {
43+
//[paren]~^ ERROR binding for associated type `Output` references lifetime `'a`
44+
}
45+
46+
#[cfg(paren)]
47+
fn paren2<T> where for<'a> T: Fn() -> &'a i32>() {
48+
//[paren]~^ ERROR binding for associated type `Output` references lifetime `'a`
49+
}
50+
51+
#[cfg(elision)]
52+
fn elision<T: Fn() -> &i32>() {
53+
//[elision]~^ ERROR E0106
54+
}
55+
56+
struct Parameterized<'a> { x: &'a str }
57+
58+
#[cfg(ok)]
59+
fn ok1<T: for<'a> Fn(&Parameterized<'a>) -> &'a i32>() {
60+
}
61+
62+
#[cfg(ok)]
63+
fn ok2<T: for<'a,'b> Fn<(&'b Parameterized<'a>,), Output=&'a i32>>() {
64+
}
65+
66+
#[cfg(ok)]
67+
fn ok3<T> where for<'a> Parameterized<'a>: Foo<Item=&'a i32> {
68+
}
69+
70+
#[rustc_error]
71+
fn main() { } //[ok]~ ERROR compilation successful

0 commit comments

Comments
 (0)