auto merge of #13525 : Ryman/rust/issue_5997, r=alexcrichton
Closes #5997.
This commit is contained in:
commit
29a39700a1
@ -3507,8 +3507,9 @@ impl<'a> Resolver<'a> {
|
||||
// its scope.
|
||||
|
||||
self.resolve_error(span,
|
||||
"attempt to use a type \
|
||||
argument out of scope");
|
||||
"can't use type parameters from \
|
||||
outer function; try using a local \
|
||||
type parameter instead");
|
||||
}
|
||||
|
||||
return None;
|
||||
@ -3530,8 +3531,9 @@ impl<'a> Resolver<'a> {
|
||||
// its scope.
|
||||
|
||||
self.resolve_error(span,
|
||||
"attempt to use a type \
|
||||
argument out of scope");
|
||||
"can't use type parameters from \
|
||||
outer function; try using a local \
|
||||
type parameter instead");
|
||||
}
|
||||
|
||||
return None;
|
||||
|
@ -95,8 +95,9 @@ impl<'a> TypeFolder for SubstFolder<'a> {
|
||||
root.repr(self.tcx)),
|
||||
None => ~""
|
||||
};
|
||||
let m = format!("missing type param `{}`{}",
|
||||
t.repr(self.tcx), root_msg);
|
||||
let m = format!("can't use type parameters from outer \
|
||||
function{}; try using a local type \
|
||||
parameter instead", root_msg);
|
||||
match self.span {
|
||||
Some(span) => self.tcx.sess.span_err(span, m),
|
||||
None => self.tcx.sess.err(m)
|
||||
|
@ -2416,13 +2416,13 @@ pub enum Representability {
|
||||
|
||||
/// Check whether a type is representable. This means it cannot contain unboxed
|
||||
/// structural recursion. This check is needed for structs and enums.
|
||||
pub fn is_type_representable(cx: &ctxt, ty: t) -> Representability {
|
||||
pub fn is_type_representable(cx: &ctxt, sp: Span, ty: t) -> Representability {
|
||||
|
||||
// Iterate until something non-representable is found
|
||||
fn find_nonrepresentable<It: Iterator<t>>(cx: &ctxt, seen: &mut Vec<DefId>,
|
||||
fn find_nonrepresentable<It: Iterator<t>>(cx: &ctxt, sp: Span, seen: &mut Vec<DefId>,
|
||||
mut iter: It) -> Representability {
|
||||
for ty in iter {
|
||||
let r = type_structurally_recursive(cx, seen, ty);
|
||||
let r = type_structurally_recursive(cx, sp, seen, ty);
|
||||
if r != Representable {
|
||||
return r
|
||||
}
|
||||
@ -2432,7 +2432,7 @@ pub fn is_type_representable(cx: &ctxt, ty: t) -> Representability {
|
||||
|
||||
// Does the type `ty` directly (without indirection through a pointer)
|
||||
// contain any types on stack `seen`?
|
||||
fn type_structurally_recursive(cx: &ctxt, seen: &mut Vec<DefId>,
|
||||
fn type_structurally_recursive(cx: &ctxt, sp: Span, seen: &mut Vec<DefId>,
|
||||
ty: t) -> Representability {
|
||||
debug!("type_structurally_recursive: {}",
|
||||
::util::ppaux::ty_to_str(cx, ty));
|
||||
@ -2455,19 +2455,19 @@ pub fn is_type_representable(cx: &ctxt, ty: t) -> Representability {
|
||||
match get(ty).sty {
|
||||
// Tuples
|
||||
ty_tup(ref ts) => {
|
||||
find_nonrepresentable(cx, seen, ts.iter().map(|t| *t))
|
||||
find_nonrepresentable(cx, sp, seen, ts.iter().map(|t| *t))
|
||||
}
|
||||
// Fixed-length vectors.
|
||||
// FIXME(#11924) Behavior undecided for zero-length vectors.
|
||||
ty_vec(ty, VstoreFixed(_)) => {
|
||||
type_structurally_recursive(cx, seen, ty)
|
||||
type_structurally_recursive(cx, sp, seen, ty)
|
||||
}
|
||||
|
||||
// Push struct and enum def-ids onto `seen` before recursing.
|
||||
ty_struct(did, ref substs) => {
|
||||
seen.push(did);
|
||||
let fields = struct_fields(cx, did, substs);
|
||||
let r = find_nonrepresentable(cx, seen,
|
||||
let r = find_nonrepresentable(cx, sp, seen,
|
||||
fields.iter().map(|f| f.mt.ty));
|
||||
seen.pop();
|
||||
r
|
||||
@ -2478,8 +2478,10 @@ pub fn is_type_representable(cx: &ctxt, ty: t) -> Representability {
|
||||
|
||||
let mut r = Representable;
|
||||
for variant in vs.iter() {
|
||||
let iter = variant.args.iter().map(|aty| subst(cx, substs, *aty));
|
||||
r = find_nonrepresentable(cx, seen, iter);
|
||||
let iter = variant.args.iter().map(|aty| {
|
||||
aty.subst_spanned(cx, substs, Some(sp))
|
||||
});
|
||||
r = find_nonrepresentable(cx, sp, seen, iter);
|
||||
|
||||
if r != Representable { break }
|
||||
}
|
||||
@ -2499,7 +2501,7 @@ pub fn is_type_representable(cx: &ctxt, ty: t) -> Representability {
|
||||
// contains a different, structurally recursive type, maintain a stack
|
||||
// of seen types and check recursion for each of them (issues #3008, #3779).
|
||||
let mut seen: Vec<DefId> = Vec::new();
|
||||
type_structurally_recursive(cx, &mut seen, ty)
|
||||
type_structurally_recursive(cx, sp, &mut seen, ty)
|
||||
}
|
||||
|
||||
pub fn type_is_trait(ty: t) -> bool {
|
||||
|
@ -3356,7 +3356,7 @@ pub fn check_representable(tcx: &ty::ctxt,
|
||||
// recursive type. It is only necessary to throw an error on those that
|
||||
// contain themselves. For case 2, there must be an inner type that will be
|
||||
// caught by case 1.
|
||||
match ty::is_type_representable(tcx, rty) {
|
||||
match ty::is_type_representable(tcx, sp, rty) {
|
||||
ty::SelfRecursive => {
|
||||
tcx.sess.span_err(
|
||||
sp, format!("illegal recursive {} type; \
|
||||
|
@ -945,7 +945,24 @@ pub fn ty_generics(ccx: &CrateCtxt,
|
||||
let param_ty = ty::param_ty {idx: base_index + offset,
|
||||
def_id: local_def(param.id)};
|
||||
let bounds = @compute_bounds(ccx, param_ty, ¶m.bounds);
|
||||
let default = param.default.map(|x| ast_ty_to_ty(ccx, &ExplicitRscope, x));
|
||||
let default = param.default.map(|path| {
|
||||
let ty = ast_ty_to_ty(ccx, &ExplicitRscope, path);
|
||||
let cur_idx = param_ty.idx;
|
||||
|
||||
ty::walk_ty(ty, |t| {
|
||||
match ty::get(t).sty {
|
||||
ty::ty_param(p) => if p.idx > cur_idx {
|
||||
ccx.tcx.sess.span_err(path.span,
|
||||
"type parameters with a default cannot use \
|
||||
forward declared identifiers")
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
|
||||
ty
|
||||
});
|
||||
|
||||
let def = ty::TypeParameterDef {
|
||||
ident: param.ident,
|
||||
def_id: local_def(param.id),
|
||||
|
@ -9,7 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
fn foo<T>() {
|
||||
fn bar(b: T) { } //~ ERROR attempt to use a type argument out of scope
|
||||
fn bar(b: T) { } //~ ERROR can't use type parameters from outer
|
||||
//~^ ERROR use of undeclared type name
|
||||
}
|
||||
fn main() { }
|
||||
|
@ -12,8 +12,7 @@
|
||||
|
||||
// Ensure that we get an error and not an ICE for this problematic case.
|
||||
struct Foo<T = Option<U>, U = bool>;
|
||||
|
||||
//~^ ERROR type parameters with a default cannot use forward declared identifiers
|
||||
fn main() {
|
||||
let x: Foo;
|
||||
//~^ ERROR missing type param `U` in the substitution of `std::option::Option<U>`
|
||||
}
|
||||
|
@ -11,8 +11,8 @@
|
||||
fn siphash<T>() {
|
||||
|
||||
trait t {
|
||||
fn g(&self, x: T) -> T; //~ ERROR attempt to use a type argument out of scope
|
||||
//~^ ERROR attempt to use a type argument out of scope
|
||||
fn g(&self, x: T) -> T; //~ ERROR can't use type parameters from outer function; try using
|
||||
//~^ ERROR can't use type parameters from outer function; try using
|
||||
//~^^ ERROR use of undeclared type name `T`
|
||||
//~^^^ ERROR use of undeclared type name `T`
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
fn foo<T>() {
|
||||
struct foo {
|
||||
x: T, //~ ERROR attempt to use a type argument out of scope
|
||||
x: T, //~ ERROR can't use type parameters from outer function;
|
||||
//~^ ERROR use of undeclared type name
|
||||
}
|
||||
|
||||
|
21
src/test/compile-fail/issue-5997-enum.rs
Normal file
21
src/test/compile-fail/issue-5997-enum.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// 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.
|
||||
|
||||
fn f<Z>() -> bool {
|
||||
enum E { V(Z) }
|
||||
//~^ ERROR can't use type parameters from outer function in the
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let b = f::<int>();
|
||||
assert!(b);
|
||||
}
|
21
src/test/compile-fail/issue-5997-struct.rs
Normal file
21
src/test/compile-fail/issue-5997-struct.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// 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.
|
||||
|
||||
fn f<T>() -> bool {
|
||||
struct S(T); //~ ERROR use of undeclared type name `T`
|
||||
//~^ ERROR can't use type parameters from outer function; try using
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let b = f::<int>();
|
||||
assert!(b);
|
||||
}
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// error-pattern:attempt to use a type argument out of scope
|
||||
// error-pattern:can't use type parameters from outer function; try using
|
||||
fn hd<U>(v: Vec<U> ) -> U {
|
||||
fn hd1(w: [U]) -> U { return w[0]; }
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// error-pattern:attempt to use a type argument out of scope
|
||||
// error-pattern:can't use type parameters from outer function; try using
|
||||
fn foo<T>(x: T) {
|
||||
fn bar(f: |T| -> T) { }
|
||||
}
|
||||
|
22
src/test/run-pass/issue-5997.rs
Normal file
22
src/test/run-pass/issue-5997.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// 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.
|
||||
|
||||
fn f<T>() -> bool {
|
||||
enum E<T> { V(T) }
|
||||
|
||||
struct S<T>(T);
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let b = f::<int>();
|
||||
assert!(b);
|
||||
}
|
Loading…
Reference in New Issue
Block a user