Skip to content

Commit 0a11f58

Browse files
committed
---
yaml --- r: 278257 b: refs/heads/auto c: b77f2c9 h: refs/heads/master i: 278255: 8bc02cc
1 parent 85680ac commit 0a11f58

File tree

18 files changed

+295
-34
lines changed

18 files changed

+295
-34
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503
88
refs/tags/release-0.3.1: 495bae036dfe5ec6ceafd3312b4dca48741e845b
99
refs/tags/release-0.4: e828ea2080499553b97dfe33b3f4d472b4562ad7
1010
refs/tags/release-0.5: 7e3bcfbf21278251ee936ad53e92e9b719702d73
11-
refs/heads/auto: a5a2f2b951ea982a666eaf52b1874d8f1b17290b
11+
refs/heads/auto: b77f2c9b179e98c88d657078bc793ee241a1b23d
1212
refs/tags/release-0.6: b4ebcfa1812664df5e142f0134a5faea3918544c
1313
refs/tags/0.1: b19db808c2793fe2976759b85a355c3ad8c8b336
1414
refs/tags/0.2: 1754d02027f2924bed83b0160ee340c7f41d5ea1

branches/auto/src/doc/nomicon/vec-alloc.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ LLVM needs to work with different languages' semantics and custom allocators,
150150
it can't really intimately understand allocation. Instead, the main idea behind
151151
allocation is "doesn't overlap with other stuff". That is, heap allocations,
152152
stack allocations, and globals don't randomly overlap. Yep, it's about alias
153-
analysis. As such, Rust can technically play a bit fast an loose with the notion of
153+
analysis. As such, Rust can technically play a bit fast and loose with the notion of
154154
an allocation as long as it's *consistent*.
155155

156156
Getting back to the empty allocation case, there are a couple of places where

branches/auto/src/librustc/infer/region_inference/mod.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,9 +1240,6 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
12401240
orig_node_idx,
12411241
node_idx);
12421242

1243-
// figure out the direction from which this node takes its
1244-
// values, and search for concrete regions etc in that direction
1245-
let dir = graph::INCOMING;
12461243
process_edges(self, &mut state, graph, node_idx, dir);
12471244
}
12481245

branches/auto/src/librustc/middle/resolve_lifetime.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,12 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
193193
})
194194
}
195195
FnKind::Closure(_) => {
196-
self.add_scope_and_walk_fn(fk, fd, b, s, fn_id)
196+
// Closures have their own set of labels, save labels just
197+
// like for foreign items above.
198+
let saved = replace(&mut self.labels_in_fn, vec![]);
199+
let result = self.add_scope_and_walk_fn(fk, fd, b, s, fn_id);
200+
replace(&mut self.labels_in_fn, saved);
201+
result
197202
}
198203
}
199204
}

branches/auto/src/librustc_borrowck/diagnostics.rs

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,110 @@ fn foo(a: &mut i32) {
454454
```
455455
"##,
456456

457+
E0504: r##"
458+
This error occurs when an attempt is made to move a borrowed variable into a
459+
closure.
460+
461+
Example of erroneous code:
462+
463+
```compile_fail
464+
struct FancyNum {
465+
num: u8
466+
}
467+
468+
fn main() {
469+
let fancy_num = FancyNum { num: 5 };
470+
let fancy_ref = &fancy_num;
471+
472+
let x = move || {
473+
println!("child function: {}", fancy_num.num);
474+
// error: cannot move `fancy_num` into closure because it is borrowed
475+
};
476+
477+
x();
478+
println!("main function: {}", fancy_ref.num);
479+
}
480+
```
481+
482+
Here, `fancy_num` is borrowed by `fancy_ref` and so cannot be moved into
483+
the closure `x`. There is no way to move a value into a closure while it is
484+
borrowed, as that would invalidate the borrow.
485+
486+
If the closure can't outlive the value being moved, try using a reference
487+
rather than moving:
488+
489+
```
490+
struct FancyNum {
491+
num: u8
492+
}
493+
494+
fn main() {
495+
let fancy_num = FancyNum { num: 5 };
496+
let fancy_ref = &fancy_num;
497+
498+
let x = move || {
499+
// fancy_ref is usable here because it doesn't move `fancy_num`
500+
println!("child function: {}", fancy_ref.num);
501+
};
502+
503+
x();
504+
505+
println!("main function: {}", fancy_num.num);
506+
}
507+
```
508+
509+
If the value has to be borrowed and then moved, try limiting the lifetime of
510+
the borrow using a scoped block:
511+
512+
```
513+
struct FancyNum {
514+
num: u8
515+
}
516+
517+
fn main() {
518+
let fancy_num = FancyNum { num: 5 };
519+
520+
{
521+
let fancy_ref = &fancy_num;
522+
println!("main function: {}", fancy_ref.num);
523+
// `fancy_ref` goes out of scope here
524+
}
525+
526+
let x = move || {
527+
// `fancy_num` can be moved now (no more references exist)
528+
println!("child function: {}", fancy_num.num);
529+
};
530+
531+
x();
532+
}
533+
```
534+
535+
If the lifetime of a reference isn't enough, such as in the case of threading,
536+
consider using an `Arc` to create a reference-counted value:
537+
538+
```
539+
use std::sync::Arc;
540+
use std::thread;
541+
542+
struct FancyNum {
543+
num: u8
544+
}
545+
546+
fn main() {
547+
let fancy_ref1 = Arc::new(FancyNum { num: 5 });
548+
let fancy_ref2 = fancy_ref1.clone();
549+
550+
let x = thread::spawn(move || {
551+
// `fancy_ref1` can be moved and has a `'static` lifetime
552+
println!("child thread: {}", fancy_ref1.num);
553+
});
554+
555+
x.join().expect("child thread should finish");
556+
println!("main thread: {}", fancy_ref2.num);
557+
}
558+
```
559+
"##,
560+
457561
E0506: r##"
458562
This error occurs when an attempt is made to assign to a borrowed value.
459563
@@ -756,7 +860,6 @@ register_diagnostics! {
756860
E0500, // closure requires unique access to `..` but .. is already borrowed
757861
E0502, // cannot borrow `..`.. as .. because .. is also borrowed as ...
758862
E0503, // cannot use `..` because it was mutably borrowed
759-
E0504, // cannot move `..` into closure because it is borrowed
760863
E0505, // cannot move out of `..` because it is borrowed
761864
E0508, // cannot move out of type `..`, a non-copy fixed-size array
762865
E0524, // two closures require unique access to `..` at the same time

branches/auto/src/librustc_const_eval/diagnostics.rs

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -215,22 +215,63 @@ match Some("hi".to_string()) {
215215
The variable `s` has type `String`, and its use in the guard is as a variable of
216216
type `String`. The guard code effectively executes in a separate scope to the
217217
body of the arm, so the value would be moved into this anonymous scope and
218-
therefore become unavailable in the body of the arm. Although this example seems
219-
innocuous, the problem is most clear when considering functions that take their
220-
argument by value.
218+
therefore becomes unavailable in the body of the arm.
221219
222-
```compile_fail
220+
The problem above can be solved by using the `ref` keyword.
221+
222+
```
223223
match Some("hi".to_string()) {
224-
Some(s) if { drop(s); false } => (),
225-
Some(s) => {}, // use s.
224+
Some(ref s) if s.len() == 0 => {},
226225
_ => {},
227226
}
228227
```
229228
230-
The value would be dropped in the guard then become unavailable not only in the
231-
body of that arm but also in all subsequent arms! The solution is to bind by
232-
reference when using guards or refactor the entire expression, perhaps by
233-
putting the condition inside the body of the arm.
229+
Though this example seems innocuous and easy to solve, the problem becomes clear
230+
when it encounters functions which consume the value:
231+
232+
```compile_fail
233+
struct A{}
234+
235+
impl A {
236+
fn consume(self) -> usize {
237+
0
238+
}
239+
}
240+
241+
fn main() {
242+
let a = Some(A{});
243+
match a {
244+
Some(y) if y.consume() > 0 => {}
245+
_ => {}
246+
}
247+
}
248+
```
249+
250+
In this situation, even the `ref` keyword cannot solve it, since borrowed
251+
content cannot be moved. This problem cannot be solved generally. If the value
252+
can be cloned, here is a not-so-specific solution:
253+
254+
```
255+
#[derive(Clone)]
256+
struct A{}
257+
258+
impl A {
259+
fn consume(self) -> usize {
260+
0
261+
}
262+
}
263+
264+
fn main() {
265+
let a = Some(A{});
266+
match a{
267+
Some(ref y) if y.clone().consume() > 0 => {}
268+
_ => {}
269+
}
270+
}
271+
```
272+
273+
If the value will be consumed in the pattern guard, using its clone will not
274+
move its ownership, so the code works.
234275
"##,
235276

236277
E0009: r##"

branches/auto/src/librustc_trans/mir/block.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
213213

214214
let extra_args = &args[sig.inputs.len()..];
215215
let extra_args = extra_args.iter().map(|op_arg| {
216-
self.mir.operand_ty(bcx.tcx(), op_arg)
216+
let op_ty = self.mir.operand_ty(bcx.tcx(), op_arg);
217+
bcx.monomorphize(&op_ty)
217218
}).collect::<Vec<_>>();
218219
let fn_ty = callee.direct_fn_type(bcx.ccx(), &extra_args);
219220

branches/auto/src/librustc_trans/mir/lvalue.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ use abi;
1616
use adt;
1717
use base;
1818
use builder::Builder;
19-
use common::{self, BlockAndBuilder, CrateContext, C_uint};
19+
use common::{self, BlockAndBuilder, CrateContext, C_uint, C_undef};
2020
use consts;
2121
use machine;
22+
use type_of::type_of;
2223
use mir::drop;
23-
use llvm;
2424
use Disr;
2525

2626
use std::ptr;
@@ -116,10 +116,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
116116
// Ergo, we return an undef ValueRef, so we do not have to special-case every
117117
// place using lvalues, and could use it the same way you use a regular
118118
// ReturnPointer LValue (i.e. store into it, load from it etc).
119-
let llty = fcx.fn_ty.ret.original_ty.ptr_to();
120-
unsafe {
121-
llvm::LLVMGetUndef(llty.to_ref())
122-
}
119+
C_undef(fcx.fn_ty.ret.original_ty.ptr_to())
123120
};
124121
let fn_return_ty = bcx.monomorphize(&self.mir.return_ty);
125122
let return_ty = fn_return_ty.unwrap();
@@ -228,7 +225,19 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
228225
ret
229226
}
230227
TempRef::Operand(Some(_)) => {
231-
bug!("Lvalue temp already set");
228+
let lvalue_ty = self.mir.lvalue_ty(bcx.tcx(), lvalue);
229+
let lvalue_ty = bcx.monomorphize(&lvalue_ty);
230+
231+
// See comments in TempRef::new_operand as to why
232+
// we always have Some in a ZST TempRef::Operand.
233+
let ty = lvalue_ty.to_ty(bcx.tcx());
234+
if common::type_is_zero_size(bcx.ccx(), ty) {
235+
// Pass an undef pointer as no stores can actually occur.
236+
let llptr = C_undef(type_of(bcx.ccx(), ty).ptr_to());
237+
f(self, LvalueRef::new_sized(llptr, lvalue_ty))
238+
} else {
239+
bug!("Lvalue temp already set");
240+
}
232241
}
233242
}
234243
}

branches/auto/src/librustc_trans/mir/rvalue.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
5555
}
5656

5757
mir::Rvalue::Cast(mir::CastKind::Unsize, ref source, cast_ty) => {
58+
let cast_ty = bcx.monomorphize(&cast_ty);
59+
5860
if common::type_is_fat_ptr(bcx.tcx(), cast_ty) {
5961
// into-coerce of a thin pointer to a fat pointer - just
6062
// use the operand path.

branches/auto/src/librustc_typeck/check/method/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
8383
span: Span,
8484
method_name: ast::Name,
8585
self_ty: ty::Ty<'tcx>,
86-
call_expr_id: ast::NodeId)
86+
call_expr_id: ast::NodeId,
87+
allow_private: bool)
8788
-> bool
8889
{
8990
let mode = probe::Mode::MethodCall;
@@ -92,7 +93,7 @@ pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
9293
Err(NoMatch(..)) => false,
9394
Err(Ambiguity(..)) => true,
9495
Err(ClosureAmbiguity(..)) => true,
95-
Err(PrivateMatch(..)) => true,
96+
Err(PrivateMatch(..)) => allow_private,
9697
}
9798
}
9899

branches/auto/src/librustc_typeck/check/mod.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2947,12 +2947,18 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
29472947

29482948
if let Some((did, field_ty)) = private_candidate {
29492949
let struct_path = fcx.tcx().item_path_str(did);
2950-
let msg = format!("field `{}` of struct `{}` is private", field.node, struct_path);
2951-
fcx.tcx().sess.span_err(expr.span, &msg);
29522950
fcx.write_ty(expr.id, field_ty);
2951+
let msg = format!("field `{}` of struct `{}` is private", field.node, struct_path);
2952+
let mut err = fcx.tcx().sess.struct_span_err(expr.span, &msg);
2953+
// Also check if an accessible method exists, which is often what is meant.
2954+
if method::exists(fcx, field.span, field.node, expr_t, expr.id, false) {
2955+
err.note(&format!("a method `{}` also exists, \
2956+
perhaps you wish to call it", field.node));
2957+
}
2958+
err.emit();
29532959
} else if field.node == keywords::Invalid.name() {
29542960
fcx.write_error(expr.id);
2955-
} else if method::exists(fcx, field.span, field.node, expr_t, expr.id) {
2961+
} else if method::exists(fcx, field.span, field.node, expr_t, expr.id, true) {
29562962
fcx.type_error_struct(field.span,
29572963
|actual| {
29582964
format!("attempted to take value of method `{}` on type \

branches/auto/src/librustc_typeck/diagnostics.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,7 @@ fn f(a: u16, b: &str) {}
742742
743743
Must always be called with exactly two arguments, e.g. `f(2, "test")`.
744744
745-
Note, that Rust does not have a notion of optional function arguments or
745+
Note that Rust does not have a notion of optional function arguments or
746746
variadic functions (except for its C-FFI).
747747
"##,
748748

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2016 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+
mod sub {
12+
pub struct S { len: usize }
13+
impl S {
14+
pub fn new() -> S { S { len: 0 } }
15+
pub fn len(&self) -> usize { self.len }
16+
}
17+
}
18+
19+
fn main() {
20+
let s = sub::S::new();
21+
let v = s.len;
22+
//~^ ERROR field `len` of struct `sub::S` is private
23+
//~| NOTE a method `len` also exists, perhaps you wish to call it
24+
}

0 commit comments

Comments
 (0)