Skip to content

Commit 648c5e9

Browse files
committed
auto merge of #7534 : bblum/rust/soundness-messages, r=catamorphism
2 parents 0c6fc46 + 54e01eb commit 648c5e9

5 files changed

+55
-7
lines changed

src/librustc/middle/borrowck/mod.rs

+24-7
Original file line numberDiff line numberDiff line change
@@ -538,12 +538,13 @@ impl BorrowckCtxt {
538538

539539
move_data::MoveExpr(expr) => {
540540
let expr_ty = ty::expr_ty_adjusted(self.tcx, expr);
541+
let suggestion = move_suggestion(self.tcx, expr_ty,
542+
"moved by default (use `copy` to override)");
541543
self.tcx.sess.span_note(
542544
expr.span,
543-
fmt!("`%s` moved here because it has type `%s`, \
544-
which is moved by default (use `copy` to override)",
545+
fmt!("`%s` moved here because it has type `%s`, which is %s",
545546
self.loan_path_to_str(moved_lp),
546-
expr_ty.user_string(self.tcx)));
547+
expr_ty.user_string(self.tcx), suggestion));
547548
}
548549

549550
move_data::MovePat(pat) => {
@@ -557,12 +558,28 @@ impl BorrowckCtxt {
557558
}
558559

559560
move_data::Captured(expr) => {
561+
let expr_ty = ty::expr_ty_adjusted(self.tcx, expr);
562+
let suggestion = move_suggestion(self.tcx, expr_ty,
563+
"moved by default (make a copy and \
564+
capture that instead to override)");
560565
self.tcx.sess.span_note(
561566
expr.span,
562-
fmt!("`%s` moved into closure environment here \
563-
because its type is moved by default \
564-
(make a copy and capture that instead to override)",
565-
self.loan_path_to_str(moved_lp)));
567+
fmt!("`%s` moved into closure environment here because it \
568+
has type `%s`, which is %s",
569+
self.loan_path_to_str(moved_lp),
570+
expr_ty.user_string(self.tcx), suggestion));
571+
}
572+
}
573+
574+
fn move_suggestion(tcx: ty::ctxt, ty: ty::t, default_msg: &'static str)
575+
-> &'static str {
576+
match ty::get(ty).sty {
577+
ty::ty_closure(ref cty) if cty.sigil == ast::BorrowedSigil =>
578+
"a non-copyable stack closure (capture it in a new closure, \
579+
e.g. `|x| f(x)`, to override)",
580+
_ if !ty::type_is_copyable(tcx, ty) =>
581+
"non-copyable (perhaps you meant to use clone()?)",
582+
_ => default_msg,
566583
}
567584
}
568585
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2013 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+
// Ensures that it's legal to create a recursive stack closure as long as
12+
// its environment is copyable
13+
14+
struct R<'self> {
15+
// This struct is needed to create the
16+
// otherwise infinite type of a fn that
17+
// accepts itself as argument:
18+
c: &'self fn:Copy(&R, uint) -> uint
19+
}
20+
21+
fn main() {
22+
// Stupid version of fibonacci.
23+
let fib: &fn:Copy(&R, uint) -> uint = |fib, x| {
24+
if x == 0 || x == 1 {
25+
x
26+
} else {
27+
(fib.c)(fib, x-1) + (fib.c)(fib, x-2)
28+
}
29+
};
30+
assert!(fib(&R { c: fib }, 7) == 13);
31+
}

0 commit comments

Comments
 (0)