Skip to content

Commit 29a3970

Browse files
committed
auto merge of #13525 : Ryman/rust/issue_5997, r=alexcrichton
Closes #5997.
2 parents 3f8e686 + f829d20 commit 29a3970

14 files changed

+111
-26
lines changed

src/librustc/middle/resolve.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -3507,8 +3507,9 @@ impl<'a> Resolver<'a> {
35073507
// its scope.
35083508

35093509
self.resolve_error(span,
3510-
"attempt to use a type \
3511-
argument out of scope");
3510+
"can't use type parameters from \
3511+
outer function; try using a local \
3512+
type parameter instead");
35123513
}
35133514

35143515
return None;
@@ -3530,8 +3531,9 @@ impl<'a> Resolver<'a> {
35303531
// its scope.
35313532

35323533
self.resolve_error(span,
3533-
"attempt to use a type \
3534-
argument out of scope");
3534+
"can't use type parameters from \
3535+
outer function; try using a local \
3536+
type parameter instead");
35353537
}
35363538

35373539
return None;

src/librustc/middle/subst.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,9 @@ impl<'a> TypeFolder for SubstFolder<'a> {
9595
root.repr(self.tcx)),
9696
None => ~""
9797
};
98-
let m = format!("missing type param `{}`{}",
99-
t.repr(self.tcx), root_msg);
98+
let m = format!("can't use type parameters from outer \
99+
function{}; try using a local type \
100+
parameter instead", root_msg);
100101
match self.span {
101102
Some(span) => self.tcx.sess.span_err(span, m),
102103
None => self.tcx.sess.err(m)

src/librustc/middle/ty.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -2416,13 +2416,13 @@ pub enum Representability {
24162416

24172417
/// Check whether a type is representable. This means it cannot contain unboxed
24182418
/// structural recursion. This check is needed for structs and enums.
2419-
pub fn is_type_representable(cx: &ctxt, ty: t) -> Representability {
2419+
pub fn is_type_representable(cx: &ctxt, sp: Span, ty: t) -> Representability {
24202420

24212421
// Iterate until something non-representable is found
2422-
fn find_nonrepresentable<It: Iterator<t>>(cx: &ctxt, seen: &mut Vec<DefId>,
2422+
fn find_nonrepresentable<It: Iterator<t>>(cx: &ctxt, sp: Span, seen: &mut Vec<DefId>,
24232423
mut iter: It) -> Representability {
24242424
for ty in iter {
2425-
let r = type_structurally_recursive(cx, seen, ty);
2425+
let r = type_structurally_recursive(cx, sp, seen, ty);
24262426
if r != Representable {
24272427
return r
24282428
}
@@ -2432,7 +2432,7 @@ pub fn is_type_representable(cx: &ctxt, ty: t) -> Representability {
24322432

24332433
// Does the type `ty` directly (without indirection through a pointer)
24342434
// contain any types on stack `seen`?
2435-
fn type_structurally_recursive(cx: &ctxt, seen: &mut Vec<DefId>,
2435+
fn type_structurally_recursive(cx: &ctxt, sp: Span, seen: &mut Vec<DefId>,
24362436
ty: t) -> Representability {
24372437
debug!("type_structurally_recursive: {}",
24382438
::util::ppaux::ty_to_str(cx, ty));
@@ -2455,19 +2455,19 @@ pub fn is_type_representable(cx: &ctxt, ty: t) -> Representability {
24552455
match get(ty).sty {
24562456
// Tuples
24572457
ty_tup(ref ts) => {
2458-
find_nonrepresentable(cx, seen, ts.iter().map(|t| *t))
2458+
find_nonrepresentable(cx, sp, seen, ts.iter().map(|t| *t))
24592459
}
24602460
// Fixed-length vectors.
24612461
// FIXME(#11924) Behavior undecided for zero-length vectors.
24622462
ty_vec(ty, VstoreFixed(_)) => {
2463-
type_structurally_recursive(cx, seen, ty)
2463+
type_structurally_recursive(cx, sp, seen, ty)
24642464
}
24652465

24662466
// Push struct and enum def-ids onto `seen` before recursing.
24672467
ty_struct(did, ref substs) => {
24682468
seen.push(did);
24692469
let fields = struct_fields(cx, did, substs);
2470-
let r = find_nonrepresentable(cx, seen,
2470+
let r = find_nonrepresentable(cx, sp, seen,
24712471
fields.iter().map(|f| f.mt.ty));
24722472
seen.pop();
24732473
r
@@ -2478,8 +2478,10 @@ pub fn is_type_representable(cx: &ctxt, ty: t) -> Representability {
24782478

24792479
let mut r = Representable;
24802480
for variant in vs.iter() {
2481-
let iter = variant.args.iter().map(|aty| subst(cx, substs, *aty));
2482-
r = find_nonrepresentable(cx, seen, iter);
2481+
let iter = variant.args.iter().map(|aty| {
2482+
aty.subst_spanned(cx, substs, Some(sp))
2483+
});
2484+
r = find_nonrepresentable(cx, sp, seen, iter);
24832485

24842486
if r != Representable { break }
24852487
}
@@ -2499,7 +2501,7 @@ pub fn is_type_representable(cx: &ctxt, ty: t) -> Representability {
24992501
// contains a different, structurally recursive type, maintain a stack
25002502
// of seen types and check recursion for each of them (issues #3008, #3779).
25012503
let mut seen: Vec<DefId> = Vec::new();
2502-
type_structurally_recursive(cx, &mut seen, ty)
2504+
type_structurally_recursive(cx, sp, &mut seen, ty)
25032505
}
25042506

25052507
pub fn type_is_trait(ty: t) -> bool {

src/librustc/middle/typeck/check/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3356,7 +3356,7 @@ pub fn check_representable(tcx: &ty::ctxt,
33563356
// recursive type. It is only necessary to throw an error on those that
33573357
// contain themselves. For case 2, there must be an inner type that will be
33583358
// caught by case 1.
3359-
match ty::is_type_representable(tcx, rty) {
3359+
match ty::is_type_representable(tcx, sp, rty) {
33603360
ty::SelfRecursive => {
33613361
tcx.sess.span_err(
33623362
sp, format!("illegal recursive {} type; \

src/librustc/middle/typeck/collect.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -945,7 +945,24 @@ pub fn ty_generics(ccx: &CrateCtxt,
945945
let param_ty = ty::param_ty {idx: base_index + offset,
946946
def_id: local_def(param.id)};
947947
let bounds = @compute_bounds(ccx, param_ty, &param.bounds);
948-
let default = param.default.map(|x| ast_ty_to_ty(ccx, &ExplicitRscope, x));
948+
let default = param.default.map(|path| {
949+
let ty = ast_ty_to_ty(ccx, &ExplicitRscope, path);
950+
let cur_idx = param_ty.idx;
951+
952+
ty::walk_ty(ty, |t| {
953+
match ty::get(t).sty {
954+
ty::ty_param(p) => if p.idx > cur_idx {
955+
ccx.tcx.sess.span_err(path.span,
956+
"type parameters with a default cannot use \
957+
forward declared identifiers")
958+
},
959+
_ => {}
960+
}
961+
});
962+
963+
ty
964+
});
965+
949966
let def = ty::TypeParameterDef {
950967
ident: param.ident,
951968
def_id: local_def(param.id),

src/test/compile-fail/bad-type-env-capture.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
fn foo<T>() {
12-
fn bar(b: T) { } //~ ERROR attempt to use a type argument out of scope
12+
fn bar(b: T) { } //~ ERROR can't use type parameters from outer
1313
//~^ ERROR use of undeclared type name
1414
}
1515
fn main() { }

src/test/compile-fail/generic-type-params-forward-mention.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212

1313
// Ensure that we get an error and not an ICE for this problematic case.
1414
struct Foo<T = Option<U>, U = bool>;
15-
15+
//~^ ERROR type parameters with a default cannot use forward declared identifiers
1616
fn main() {
1717
let x: Foo;
18-
//~^ ERROR missing type param `U` in the substitution of `std::option::Option<U>`
1918
}

src/test/compile-fail/issue-3021-c.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
fn siphash<T>() {
1212

1313
trait t {
14-
fn g(&self, x: T) -> T; //~ ERROR attempt to use a type argument out of scope
15-
//~^ ERROR attempt to use a type argument out of scope
14+
fn g(&self, x: T) -> T; //~ ERROR can't use type parameters from outer function; try using
15+
//~^ ERROR can't use type parameters from outer function; try using
1616
//~^^ ERROR use of undeclared type name `T`
1717
//~^^^ ERROR use of undeclared type name `T`
1818
}

src/test/compile-fail/issue-3214.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
fn foo<T>() {
1212
struct foo {
13-
x: T, //~ ERROR attempt to use a type argument out of scope
13+
x: T, //~ ERROR can't use type parameters from outer function;
1414
//~^ ERROR use of undeclared type name
1515
}
1616

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2014 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+
fn f<Z>() -> bool {
12+
enum E { V(Z) }
13+
//~^ ERROR can't use type parameters from outer function in the
14+
15+
true
16+
}
17+
18+
fn main() {
19+
let b = f::<int>();
20+
assert!(b);
21+
}
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2014 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+
fn f<T>() -> bool {
12+
struct S(T); //~ ERROR use of undeclared type name `T`
13+
//~^ ERROR can't use type parameters from outer function; try using
14+
15+
true
16+
}
17+
18+
fn main() {
19+
let b = f::<int>();
20+
assert!(b);
21+
}

src/test/compile-fail/nested-ty-params.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// error-pattern:attempt to use a type argument out of scope
11+
// error-pattern:can't use type parameters from outer function; try using
1212
fn hd<U>(v: Vec<U> ) -> U {
1313
fn hd1(w: [U]) -> U { return w[0]; }
1414

src/test/compile-fail/type-arg-out-of-scope.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// error-pattern:attempt to use a type argument out of scope
11+
// error-pattern:can't use type parameters from outer function; try using
1212
fn foo<T>(x: T) {
1313
fn bar(f: |T| -> T) { }
1414
}

src/test/run-pass/issue-5997.rs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2014 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+
fn f<T>() -> bool {
12+
enum E<T> { V(T) }
13+
14+
struct S<T>(T);
15+
16+
true
17+
}
18+
19+
fn main() {
20+
let b = f::<int>();
21+
assert!(b);
22+
}

0 commit comments

Comments
 (0)