The `MIN` link was broken. Reverts #29624.
CFG_STATIC_LIB_NAME_i686-unknown-freebsd=lib$(1).a
CFG_LIB_GLOB_i686-unknown-freebsd=lib$(1)-*.so
CFG_LIB_DSYM_GLOB_i686-unknown-freebsd=$(1)-*.dylib.dSYM
-CFG_JEMALLOC_CFLAGS_i686-unknown-freebsd := -m32 -arch i386 -I/usr/local/include $(CFLAGS)
+CFG_JEMALLOC_CFLAGS_i686-unknown-freebsd := -m32 -I/usr/local/include $(CFLAGS)
CFG_GCCISH_CFLAGS_i686-unknown-freebsd := -Wall -Werror -g -fPIC -m32 -arch i386 -I/usr/local/include $(CFLAGS)
CFG_GCCISH_LINK_FLAGS_i686-unknown-freebsd := -m32 -shared -fPIC -g -pthread -lrt
CFG_GCCISH_DEF_FLAG_i686-unknown-freebsd := -Wl,--export-dynamic,--dynamic-list=
| Target | std |rustc|cargo| notes |
|-------------------------------|-----|-----|-----|----------------------------|
| `i686-pc-windows-msvc` | ✓ | ✓ | ✓ | 32-bit MSVC (Windows 7+) |
+| `x86_64-unknown-linux-musl` | ✓ | | | 64-bit Linux with MUSL |
+| `arm-linux-androideabi` | ✓ | | | ARM Android |
+| `arm-unknown-linux-gnueabi` | ✓ | ✓ | | ARM Linux (2.6.18+) |
+| `arm-unknown-linux-gnueabihf` | ✓ | ✓ | | ARM Linux (2.6.18+) |
+| `aarch64-unknown-linux-gnu` | ✓ | | | ARM64 Linux (2.6.18+) |
+| `mips-unknown-linux-gnu` | ✓ | | | MIPS Linux (2.6.18+) |
+| `mipsel-unknown-linux-gnu` | ✓ | | | MIPS (LE) Linux (2.6.18+) |
### Tier 3
| Target | std |rustc|cargo| notes |
|-------------------------------|-----|-----|-----|----------------------------|
-| `x86_64-unknown-linux-musl` | ✓ | | | 64-bit Linux with MUSL |
-| `arm-linux-androideabi` | ✓ | | | ARM Android |
| `i686-linux-android` | ✓ | | | 32-bit x86 Android |
| `aarch64-linux-android` | ✓ | | | ARM64 Android |
-| `arm-unknown-linux-gnueabi` | ✓ | ✓ | | ARM Linux (2.6.18+) |
-| `arm-unknown-linux-gnueabihf` | ✓ | ✓ | | ARM Linux (2.6.18+) |
-| `aarch64-unknown-linux-gnu` | ✓ | | | ARM64 Linux (2.6.18+) |
-| `mips-unknown-linux-gnu` | ✓ | | | MIPS Linux (2.6.18+) |
-| `mipsel-unknown-linux-gnu` | ✓ | | | MIPS (LE) Linux (2.6.18+) |
| `powerpc-unknown-linux-gnu` | ✓ | | | PowerPC Linux (2.6.18+) |
| `i386-apple-ios` | ✓ | | | 32-bit x86 iOS |
| `x86_64-apple-ios` | ✓ | | | 64-bit x86 iOS |
You may uninstall later by running /usr/local/lib/rustlib/uninstall.sh,
or by running this script again with the --uninstall flag.
-Continue? (y/N)
+Continue? (y/N)
```
From here, press `y` for ‘yes’, and then follow the rest of the prompts.
Now that you have Rust installed, we'll help you write your first Rust program.
It's traditional when learning a new language to write a little program to
print the text “Hello, world!” to the screen, and in this section, we'll follow
-that tradition.
+that tradition.
The nice thing about starting with such a simple program is that you can
quickly verify that your compiler is installed, and that it's working properly.
> There are a number of extensions in development by the community, and the
> Rust team ships plugins for [various editors]. Configuring your editor or
> IDE is out of the scope of this tutorial, so check the documentation for your
-> specific setup.
+> specific setup.
[SolidOak]: https://github.com/oakes/SolidOak
[various editors]: https://github.com/rust-lang/rust/blob/master/src/etc/CONFIGS.md
```bash
$ rustc main.rs
-$ ./main
+$ ./main
Hello, world!
```
In Windows, just replace `main` with `main.exe`. Regardless of your operating
system, you should see the string `Hello, world!` print to the terminal. If you
did, then congratulations! You've officially written a Rust program. That makes
-you a Rust programmer! Welcome.
+you a Rust programmer! Welcome.
## Anatomy of a Rust Program
This line does all of the work in this little program: it prints text to the
screen. There are a number of details that are important here. The first is
that it’s indented with four spaces, not tabs.
-
+
The second important part is the `println!()` line. This is calling a Rust
*[macro]*, which is how metaprogramming is done in Rust. If it were calling a
function instead, it would look like this: `println()` (without the !). We'll
discuss Rust macros in more detail later, but for now you just need to
know that when you see a `!` that means that you’re calling a macro instead of
-a normal function.
+a normal function.
[macro]: macros.html
## Compiling and Running Are Separate Steps
In "Writing and Running a Rust Program", we showed you how to run a newly
-created program. We'll break that process down and examine each step now.
+created program. We'll break that process down and examine each step now.
Before running a Rust program, you have to compile it. You can use the Rust
compiler by entering the `rustc` command and passing it the name of your source
## Converting to Cargo
Let’s convert the Hello World program to Cargo. To Cargo-fy a project, you need
-to do three things:
+to do three things:
1. Put your source file in the right directory.
2. Get rid of the old executable (`main.exe` on Windows, `main` everywhere else)
first. This leaves the top-level project directory (in this case,
*hello_world*) for READMEs, license information, and anything else not related
to your code. In this way, using Cargo helps you keep your projects nice and
-tidy. There's a place for everything, and everything is in its place.
+tidy. There's a place for everything, and everything is in its place.
Now, copy *main.rs* to the *src* directory, and delete the compiled file you
created with `rustc`. As usual, replace `main` with `main.exe` if you're on
This example retains `main.rs` as the source filename because it's creating an
executable. If you wanted to make a library instead, you'd name the file
`lib.rs`. This convention is used by Cargo to successfully compile your
-projects, but it can be overridden if you wish.
+projects, but it can be overridden if you wish.
### Creating a Configuration File
`Cargo.toml`.
Make sure to capitalize the `C` in `Cargo.toml`, or Cargo won't know what to do
-with the configuration file.
+with the configuration file.
This file is in the *[TOML]* (Tom's Obvious, Minimal Language) format. TOML is
similar to INI, but has some extra goodies, and is used as Cargo’s
Once you've added this information to the *Cargo.toml* file, save it to finish
creating the configuration file.
-## Building and Running a Cargo Project
+## Building and Running a Cargo Project
With your *Cargo.toml* file in place in your project's root directory, you
should be ready to build and run your Hello World program! To do so, enter the
Hello, world!
```
-Bam! If all goes well, `Hello, world!` should print to the terminal once more.
+Bam! If all goes well, `Hello, world!` should print to the terminal once more.
You just built a project with `cargo build` and ran it with
`./target/debug/hello_world`, but you can actually do both in one step with
won't ever need to touch this file yourself; just let Cargo handle it.
That’s it! If you've been following along, you should have successfully built
-`hello_world` with Cargo.
+`hello_world` with Cargo.
Even though the project is simple, it now uses much of the real tooling you’ll
use for the rest of your Rust career. In fact, you can expect to start
}
```
-Cargo has generated a "Hello World!" for you, and you’re ready to start coding!
+Cargo has generated a "Hello World!" for you, and you’re ready to start coding!
> Note: If you want to look at Cargo in more detail, check out the official [Cargo
guide], which covers all of its features.
This chapter covered the basics that will serve you well through the rest of
this book, and the rest of your time with Rust. Now that you’ve got the tools
-down, we'll cover more about the Rust language itself.
+down, we'll cover more about the Rust language itself.
You have two options: Dive into a project with ‘[Learn Rust][learnrust]’, or
start from the bottom and work your way up with ‘[Syntax and
you add more examples.
We haven’t covered all of the details with writing documentation tests. For more,
-please see the [Documentation chapter](documentation.html)
+please see the [Documentation chapter](documentation.html).
One final note: documentation tests *cannot* be run on binary crates.
To see more on file arrangement see the [Crates and
There’s a lot of punctuation in that message, but the core of it makes sense:
you cannot index with an `i32`.
+## Out-of-bounds Access
+
+If you try to access an index that doesn’t exist:
+
+```ignore
+let v = vec![1, 2, 3];
+println!("Item 7 is {}", v[7]);
+```
+
+then the current thread will [panic] with a message like this:
+
+```text
+thread '<main>' panicked at 'index out of bounds: the len is 3 but the index is 7'
+```
+
+If you want to handle out-of-bounds errors without panicking, you can use
+methods like [`get`][get] or [`get_mut`][get_mut] that return `None` when
+given an invalid index:
+
+```rust
+let v = vec![1, 2, 3];
+match v.get(7) {
+ Some(x) => println!("Item 7 is {}", x),
+ None => println!("Sorry, this vector is too short.")
+}
+```
+
## Iterating
Once you have a vector, you can iterate through its elements with `for`. There
[vec]: ../std/vec/index.html
[generic]: generics.html
+[panic]: concurrency.html#panics
+[get]: http://doc.rust-lang.org/std/vec/struct.Vec.html#method.get
+[get_mut]: http://doc.rust-lang.org/std/vec/struct.Vec.html#method.get_mut
* F is *invariant* over `T` otherwise (no subtyping relation can be derived)
(For those of you who are familiar with variance from other languages, what we
-refer to as "just" variance is in fact *covariance*. Rust does not have
-contravariance. Historically Rust did have some contravariance but it was
-scrapped due to poor interactions with other features. If you experience
-contravariance in Rust call your local compiler developer for medical advice.)
+refer to as "just" variance is in fact *covariance*. Rust has *contravariance*
+for functions. The future of contravariance is uncertain and it may be
+scrapped. For now, `fn(T)` is contravariant in `T`, which is used in matching
+methods in trait implementations to the trait definition. Traits don't have
+inferred variance, so `Fn(T)` is invariant in `T`).
Some important variances:
struct Foo<'a, 'b, A: 'a, B: 'b, C, D, E, F, G, H> {
a: &'a A, // variant over 'a and A
- b: &'b mut B, // invariant over 'b and B
+ b: &'b mut B, // variant over 'b and invariant over B
c: *const C, // variant over C
d: *mut D, // invariant over D
e: Vec<E>, // variant over E
/// satisifed:
///
/// * `begin` must come before `end`.
- /// * `begin` and `end` must be bye positions within the string slice.
+ /// * `begin` and `end` must be byte positions within the string slice.
/// * `begin` and `end` must lie on UTF-8 sequence boundaries.
///
/// # Examples
/// satisifed:
///
/// * `begin` must come before `end`.
- /// * `begin` and `end` must be bye positions within the string slice.
+ /// * `begin` and `end` must be byte positions within the string slice.
/// * `begin` and `end` must lie on UTF-8 sequence boundaries.
#[stable(feature = "str_slice_mut", since = "1.5.0")]
#[inline]
use str::FromStr;
use self::parse::{parse_decimal, Decimal, Sign};
-use self::parse::ParseResult::{self, Valid, ShortcutToInf, ShortcutToZero};
+use self::parse::ParseResult::{Valid, Invalid, ShortcutToInf, ShortcutToZero};
use self::num::digits_to_big;
use self::rawfp::RawFloat;
pub mod parse;
macro_rules! from_str_float_impl {
- ($t:ty, $func:ident) => {
+ ($t:ty) => {
#[stable(feature = "rust1", since = "1.0.0")]
impl FromStr for $t {
type Err = ParseFloatError;
}
}
}
-from_str_float_impl!(f32, to_f32);
-from_str_float_impl!(f64, to_f64);
+from_str_float_impl!(f32);
+from_str_float_impl!(f64);
/// An error which can be returned when parsing a float.
#[derive(Debug, Clone, PartialEq)]
}
}
-pub fn pfe_empty() -> ParseFloatError {
+fn pfe_empty() -> ParseFloatError {
ParseFloatError { kind: FloatErrorKind::Empty }
}
-pub fn pfe_invalid() -> ParseFloatError {
+fn pfe_invalid() -> ParseFloatError {
ParseFloatError { kind: FloatErrorKind::Invalid }
}
Valid(decimal) => try!(convert(decimal)),
ShortcutToInf => T::infinity(),
ShortcutToZero => T::zero(),
- ParseResult::Invalid => match s {
+ Invalid => match s {
"inf" => T::infinity(),
"NaN" => T::nan(),
_ => { return Err(pfe_invalid()); }
/// Construct the subnormal. A mantissa of 0 is allowed and constructs zero.
pub fn encode_subnormal<T: RawFloat>(significand: u64) -> T {
assert!(significand < T::min_sig(), "encode_subnormal: not actually subnormal");
- // Êncoded exponent is 0, the sign bit is 0, so we just have to reinterpret the bits.
+ // Encoded exponent is 0, the sign bit is 0, so we just have to reinterpret the bits.
T::from_bits(significand)
}
/// Iterator for the char (representing *Unicode Scalar Values*) of a string
///
-/// Created with the method `.chars()`.
+/// Created with the method [`chars()`].
+///
+/// [`chars()`]: ../primitive.str.html#method.chars
#[derive(Clone)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Chars<'a> {
/// External iterator for a string's bytes.
/// Use with the `std::iter` module.
///
-/// Created with the method `.bytes()`.
+/// Created with the method [`bytes()`].
+///
+/// [`bytes()`]: ../primitive.str.html#method.bytes
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
pub struct Bytes<'a>(Cloned<slice::Iter<'a, u8>>);
generate_pattern_iterators! {
forward:
- /// Created with the method `.split()`.
+ /// Created with the method [`split()`].
+ ///
+ /// [`split()`]: ../primitive.str.html#method.split
struct Split;
reverse:
- /// Created with the method `.rsplit()`.
+ /// Created with the method [`rsplit()`].
+ ///
+ /// [`rsplit()`]: ../primitive.str.html#method.rsplit
struct RSplit;
stability:
#[stable(feature = "rust1", since = "1.0.0")]
generate_pattern_iterators! {
forward:
- /// Created with the method `.split_terminator()`.
+ /// Created with the method [`split_terminator()`].
+ ///
+ /// [`split_terminator()`]: ../primitive.str.html#method.split_terminator
struct SplitTerminator;
reverse:
- /// Created with the method `.rsplit_terminator()`.
+ /// Created with the method [`rsplit_terminator()`].
+ ///
+ /// [`rsplit_terminator()`]: ../primitive.str.html#method.rsplit_terminator
struct RSplitTerminator;
stability:
#[stable(feature = "rust1", since = "1.0.0")]
generate_pattern_iterators! {
forward:
- /// Created with the method `.splitn()`.
+ /// Created with the method [`splitn()`].
+ ///
+ /// [`splitn()`]: ../primitive.str.html#method.splitn
struct SplitN;
reverse:
- /// Created with the method `.rsplitn()`.
+ /// Created with the method [`rsplitn()`].
+ ///
+ /// [`rsplitn()`]: ../primitive.str.html#method.rsplitn
struct RSplitN;
stability:
#[stable(feature = "rust1", since = "1.0.0")]
generate_pattern_iterators! {
forward:
- /// Created with the method `.match_indices()`.
+ /// Created with the method [`match_indices()`].
+ ///
+ /// [`match_indices()`]: ../primitive.str.html#method.match_indices
struct MatchIndices;
reverse:
- /// Created with the method `.rmatch_indices()`.
+ /// Created with the method [`rmatch_indices()`].
+ ///
+ /// [`rmatch_indices()`]: ../primitive.str.html#method.rmatch_indices
struct RMatchIndices;
stability:
#[stable(feature = "str_match_indices", since = "1.5.0")]
generate_pattern_iterators! {
forward:
- /// Created with the method `.matches()`.
+ /// Created with the method [`matches()`].
+ ///
+ /// [`matches()`]: ../primitive.str.html#method.matches
struct Matches;
reverse:
- /// Created with the method `.rmatches()`.
+ /// Created with the method [`rmatches()`].
+ ///
+ /// [`rmatches()`]: ../primitive.str.html#method.rmatches
struct RMatches;
stability:
#[stable(feature = "str_matches", since = "1.2.0")]
delegate double ended;
}
-/// Created with the method `.lines()`.
+/// Created with the method [`lines()`].
+///
+/// [`lines()`]: ../primitive.str.html#method.lines
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
pub struct Lines<'a>(Map<SplitTerminator<'a, char>, LinesAnyMap>);
}
}
-/// Created with the method `.lines_any()`.
+/// Created with the method [`lines_any()`].
+///
+/// [`lines_any()`]: ../primitive.str.html#method.lines_any
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(since = "1.4.0", reason = "use lines()/Lines instead now")]
#[derive(Clone)]
}
},
TypeError::Traits(ref exp_found) => {
- self.tcx.sess.note("errrr0");
report_path_match(exp_found.expected, exp_found.found);
},
_ => () // FIXME(#22750) handle traits and stuff
value.fold_with(&mut r)
}
+ pub fn resolve_type_and_region_vars_if_possible<T>(&self, value: &T) -> T
+ where T: TypeFoldable<'tcx>
+ {
+ let mut r = resolve::OpportunisticTypeAndRegionResolver::new(self);
+ value.fold_with(&mut r)
+ }
+
/// Resolves all type variables in `t` and then, if any were left
/// unresolved, substitutes an error type. This is used after the
/// main checking when doing a second pass before writeback. The
use super::{RegionVariableOrigin, SubregionOrigin, TypeTrace, MiscVariable};
use rustc_data_structures::graph::{self, Direction, NodeIndex};
+use rustc_data_structures::unify::{self, UnificationTable};
use middle::free_region::FreeRegionMap;
use middle::ty::{self, Ty};
use middle::ty::{BoundRegion, FreeRegion, Region, RegionVid};
// bound on a variable and so forth, which can never be rolled
// back.
undo_log: RefCell<Vec<UndoLogEntry>>,
+ unification_table: RefCell<UnificationTable<ty::RegionVid>>,
// This contains the results of inference. It begins as an empty
// option and only acquires a value after inference is complete.
values: RefCell<Option<Vec<VarValue>>>,
}
-#[derive(Debug)]
pub struct RegionSnapshot {
length: usize,
+ region_snapshot: unify::Snapshot<ty::RegionVid>,
skolemization_count: u32,
}
skolemization_count: Cell::new(0),
bound_count: Cell::new(0),
undo_log: RefCell::new(Vec::new()),
+ unification_table: RefCell::new(UnificationTable::new()),
}
}
self.undo_log.borrow_mut().push(OpenSnapshot);
RegionSnapshot {
length: length,
+ region_snapshot: self.unification_table.borrow_mut().snapshot(),
skolemization_count: self.skolemization_count.get(),
}
}
(*undo_log)[snapshot.length] = CommitedSnapshot;
}
self.skolemization_count.set(snapshot.skolemization_count);
+ self.unification_table.borrow_mut().commit(snapshot.region_snapshot);
}
pub fn rollback_to(&self, snapshot: RegionSnapshot) {
let c = undo_log.pop().unwrap();
assert!(c == OpenSnapshot);
self.skolemization_count.set(snapshot.skolemization_count);
+ self.unification_table.borrow_mut()
+ .rollback_to(snapshot.region_snapshot);
}
pub fn num_vars(&self) -> u32 {
pub fn new_region_var(&self, origin: RegionVariableOrigin) -> RegionVid {
let id = self.num_vars();
self.var_origins.borrow_mut().push(origin.clone());
- let vid = RegionVid { index: id };
+ let vid = self.unification_table.borrow_mut().new_key(());
+ assert_eq!(vid.index, id);
if self.in_snapshot() {
self.undo_log.borrow_mut().push(AddVar(vid));
}
// equating regions.
self.make_subregion(origin.clone(), sub, sup);
self.make_subregion(origin, sup, sub);
+
+ if let (ty::ReVar(sub), ty::ReVar(sup)) = (sub, sup) {
+ self.unification_table.borrow_mut().union(sub, sup);
+ }
}
}
}
}
+ pub fn opportunistic_resolve_var(&self, rid: RegionVid) -> ty::Region {
+ ty::ReVar(self.unification_table.borrow_mut().find(rid))
+ }
+
fn combine_map(&self, t: CombineMapType) -> &RefCell<CombineMap> {
match t {
Glb => &self.glbs,
}
}
+impl fmt::Debug for RegionSnapshot {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "RegionSnapshot(length={},skolemization={})",
+ self.length, self.skolemization_count)
+ }
+}
+
impl<'tcx> fmt::Debug for GenericKind<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
}
}
+/// The opportunistic type and region resolver is similar to the
+/// opportunistic type resolver, but also opportunistly resolves
+/// regions. It is useful for canonicalization.
+pub struct OpportunisticTypeAndRegionResolver<'a, 'tcx:'a> {
+ infcx: &'a InferCtxt<'a, 'tcx>,
+}
+
+impl<'a, 'tcx> OpportunisticTypeAndRegionResolver<'a, 'tcx> {
+ pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self {
+ OpportunisticTypeAndRegionResolver { infcx: infcx }
+ }
+}
+
+impl<'a, 'tcx> ty::fold::TypeFolder<'tcx> for OpportunisticTypeAndRegionResolver<'a, 'tcx> {
+ fn tcx(&self) -> &ty::ctxt<'tcx> {
+ self.infcx.tcx
+ }
+
+ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+ if !t.needs_infer() {
+ t // micro-optimize -- if there is nothing in this type that this fold affects...
+ } else {
+ let t0 = self.infcx.shallow_resolve(t);
+ ty::fold::super_fold_ty(self, t0)
+ }
+ }
+
+ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
+ match r {
+ ty::ReVar(rid) => self.infcx.region_vars.opportunistic_resolve_var(rid),
+ _ => r,
+ }
+ }
+}
+
///////////////////////////////////////////////////////////////////////////
// FULL TYPE RESOLUTION
fn tag(_: Option<ty::IntVid>) -> &'static str { "IntVid" }
}
+impl UnifyKey for ty::RegionVid {
+ type Value = ();
+ fn index(&self) -> u32 { self.index }
+ fn from_index(i: u32) -> ty::RegionVid { ty::RegionVid { index: i } }
+ fn tag(_: Option<ty::RegionVid>) -> &'static str { "RegionVid" }
+}
+
impl<'tcx> ToType<'tcx> for IntVarValue {
fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
match *self {
self.check_if_assigned_path_is_moved(id, span,
use_kind, lp_base);
}
- LpExtend(ref lp_base, _, LpInterior(InteriorField(_))) => {
+ LpExtend(ref lp_base, _, LpInterior(_, InteriorField(_))) => {
match lp_base.to_type().sty {
ty::TyStruct(def, _) | ty::TyEnum(def, _) if def.has_dtor() => {
// In the case where the owner implements drop, then
self.check_if_assigned_path_is_moved(id, span,
use_kind, lp_base);
}
- LpExtend(ref lp_base, _, LpInterior(InteriorElement(..))) |
+ LpExtend(ref lp_base, _, LpInterior(_, InteriorElement(..))) |
LpExtend(ref lp_base, _, LpDeref(_)) => {
// assigning to `P[i]` requires `P` is initialized
// assigning to `(*P)` requires `P` is initialized
// bind.
//
// Anyway, for now: LV[j] is not tracked precisely
- LpExtend(_, _, LpInterior(InteriorElement(..))) => {
+ LpExtend(_, _, LpInterior(_, InteriorElement(..))) => {
let mp = this.move_path(tcx, lp.clone());
gathered_fragments.push(AllButOneFrom(mp));
}
// field access LV.x and tuple access LV#k are the cases
// we are interested in
LpExtend(ref loan_parent, mc,
- LpInterior(InteriorField(ref field_name))) => {
+ LpInterior(_, InteriorField(ref field_name))) => {
let enum_variant_info = match loan_parent.kind {
LpDowncast(ref loan_parent_2, variant_def_id) =>
Some((variant_def_id, loan_parent_2.clone())),
LpVar(..) | LpUpvar(..) | LpExtend(..) => enum_variant_did,
};
- let loan_path_elem = LpInterior(InteriorField(new_field_name));
+ let loan_path_elem = LpInterior(opt_variant_did, InteriorField(new_field_name));
let new_lp_type = match new_field_name {
mc::NamedField(ast_name) =>
tcx.named_element_ty(parent.to_type(), ast_name, opt_variant_did),
// Overwriting the base would not change the type of
// the memory, so no additional restrictions are
// needed.
+ let opt_variant_id = match cmt_base.cat {
+ Categorization::Downcast(_, variant_id) => Some(variant_id),
+ _ => None
+ };
let result = self.restrict(cmt_base);
- self.extend(result, &cmt, LpInterior(i.cleaned()))
+ self.extend(result, &cmt, LpInterior(opt_variant_id, i.cleaned()))
}
Categorization::StaticItem => {
}
}
+// This can be:
+// - a pointer dereference (`*LV` in README.md)
+// - a field reference, with an optional definition of the containing
+// enum variant (`LV.f` in README.md)
+// `DefId` is present when the field is part of struct that is in
+// a variant of an enum. For instance in:
+// `enum E { X { foo: u32 }, Y { foo: u32 }}`
+// each `foo` is qualified by the definitition id of the variant (`X` or `Y`).
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub enum LoanPathElem {
- LpDeref(mc::PointerKind), // `*LV` in README.md
- LpInterior(InteriorKind), // `LV.f` in README.md
+ LpDeref(mc::PointerKind),
+ LpInterior(Option<DefId>, InteriorKind),
}
pub fn closure_to_block(closure_id: ast::NodeId,
fn has_fork(&self, other: &LoanPath<'tcx>) -> bool {
match (&self.kind, &other.kind) {
- (&LpExtend(ref base, _, LpInterior(id)), &LpExtend(ref base2, _, LpInterior(id2))) =>
- if id == id2 {
+ (&LpExtend(ref base, _, LpInterior(opt_variant_id, id)),
+ &LpExtend(ref base2, _, LpInterior(opt_variant_id2, id2))) =>
+ if id == id2 && opt_variant_id == opt_variant_id2 {
base.has_fork(&**base2)
} else {
true
fn depth(&self) -> usize {
match self.kind {
LpExtend(ref base, _, LpDeref(_)) => base.depth(),
- LpExtend(ref base, _, LpInterior(_)) => base.depth() + 1,
+ LpExtend(ref base, _, LpInterior(_, _)) => base.depth() + 1,
_ => 0,
}
}
fn common(&self, other: &LoanPath<'tcx>) -> Option<LoanPath<'tcx>> {
match (&self.kind, &other.kind) {
- (&LpExtend(ref base, a, LpInterior(id)),
- &LpExtend(ref base2, _, LpInterior(id2))) => {
- if id == id2 {
+ (&LpExtend(ref base, a, LpInterior(opt_variant_id, id)),
+ &LpExtend(ref base2, _, LpInterior(opt_variant_id2, id2))) => {
+ if id == id2 && opt_variant_id == opt_variant_id2 {
base.common(&**base2).map(|x| {
let xd = x.depth();
if base.depth() == xd && base2.depth() == xd {
assert_eq!(base.ty, base2.ty);
assert_eq!(self.ty, other.ty);
LoanPath {
- kind: LpExtend(Rc::new(x), a, LpInterior(id)),
+ kind: LpExtend(Rc::new(x), a, LpInterior(opt_variant_id, id)),
ty: self.ty,
}
} else {
Categorization::Interior(ref cmt_base, ik) => {
opt_loan_path(cmt_base).map(|lp| {
- new_lp(LpExtend(lp, cmt.mutbl, LpInterior(ik.cleaned())))
+ let opt_variant_id = match cmt_base.cat {
+ Categorization::Downcast(_, did) => Some(did),
+ _ => None
+ };
+ new_lp(LpExtend(lp, cmt.mutbl, LpInterior(opt_variant_id, ik.cleaned())))
})
}
}
- LpExtend(ref lp_base, _, LpInterior(InteriorField(fname))) => {
+ LpExtend(ref lp_base, _, LpInterior(_, InteriorField(fname))) => {
self.append_autoderefd_loan_path_to_string(&**lp_base, out);
match fname {
mc::NamedField(fname) => {
}
}
- LpExtend(ref lp_base, _, LpInterior(InteriorElement(..))) => {
+ LpExtend(ref lp_base, _, LpInterior(_, InteriorElement(..))) => {
self.append_autoderefd_loan_path_to_string(&**lp_base, out);
out.push_str("[..]");
}
write!(f, "{:?}.*", lp)
}
- LpExtend(ref lp, _, LpInterior(ref interior)) => {
+ LpExtend(ref lp, _, LpInterior(_, ref interior)) => {
write!(f, "{:?}.{:?}", lp, interior)
}
}
write!(f, "{}.*", lp)
}
- LpExtend(ref lp, _, LpInterior(ref interior)) => {
+ LpExtend(ref lp, _, LpInterior(_, ref interior)) => {
write!(f, "{}.{:?}", lp, interior)
}
}
LpVar(_) | LpUpvar(_) => {
true
}
- LpExtend(_, _, LpInterior(InteriorKind::InteriorElement(..))) => {
+ LpExtend(_, _, LpInterior(_, InteriorKind::InteriorElement(..))) => {
// Paths involving element accesses a[i] do not refer to a unique
// location, as there is no accurate tracking of the indices.
//
is_public: is_public
};
}
+ } else {
+ // FIXME #30159: This is required for backwards compatability.
+ dest_import_resolution[namespace].is_public |= is_public;
}
};
merge_child_item(ValueNS);
}
hir::PatBox(ref inner) => {
let pat_ty = node_id_type(bcx, inner.id);
- // Don't load DSTs, instead pass along a fat ptr
- let val = if type_is_sized(tcx, pat_ty) {
+ // Pass along DSTs as fat pointers.
+ let val = if type_is_fat_ptr(tcx, pat_ty) {
+ // We need to check for this, as the pattern could be binding
+ // a fat pointer by-value.
+ if let hir::PatIdent(hir::BindByRef(_),_,_) = inner.node {
+ val.val
+ } else {
+ Load(bcx, val.val)
+ }
+ } else if type_is_sized(tcx, pat_ty) {
Load(bcx, val.val)
} else {
val.val
}
hir::PatRegion(ref inner, _) => {
let pat_ty = node_id_type(bcx, inner.id);
- // Don't load DSTs, instead pass along a fat ptr
- let val = if type_is_sized(tcx, pat_ty) {
+ // Pass along DSTs as fat pointers.
+ let val = if type_is_fat_ptr(tcx, pat_ty) {
+ // We need to check for this, as the pattern could be binding
+ // a fat pointer by-value.
+ if let hir::PatIdent(hir::BindByRef(_),_,_) = inner.node {
+ val.val
+ } else {
+ Load(bcx, val.val)
+ }
+ } else if type_is_sized(tcx, pat_ty) {
Load(bcx, val.val)
} else {
val.val
-> Result<ValueRef, ConstEvalFailure> {
debug!("get_const_expr_as_global: {:?}", expr.id);
// Special-case constants to cache a common global for all uses.
- match expr.node {
- hir::ExprPath(..) => {
- let def = ccx.tcx().def_map.borrow().get(&expr.id).unwrap().full_def();
- match def {
- def::DefConst(def_id) | def::DefAssociatedConst(def_id) => {
- if !ccx.tcx().tables.borrow().adjustments.contains_key(&expr.id) {
- debug!("get_const_expr_as_global ({:?}): found const {:?}",
- expr.id, def_id);
- return get_const_val(ccx, def_id, expr);
- }
+ if let hir::ExprPath(..) = expr.node {
+ // `def` must be its own statement and cannot be in the `match`
+ // otherwise the `def_map` will be borrowed for the entire match instead
+ // of just to get the `def` value
+ let def = ccx.tcx().def_map.borrow().get(&expr.id).unwrap().full_def();
+ match def {
+ def::DefConst(def_id) | def::DefAssociatedConst(def_id) => {
+ if !ccx.tcx().tables.borrow().adjustments.contains_key(&expr.id) {
+ debug!("get_const_expr_as_global ({:?}): found const {:?}",
+ expr.id, def_id);
+ return get_const_val(ccx, def_id, expr);
}
- _ => {}
- }
+ },
+ _ => {},
}
- _ => {}
}
let key = (expr.id, param_substs);
- match ccx.const_values().borrow().get(&key) {
- Some(&val) => return Ok(val),
- None => {}
+ if let Some(&val) = ccx.const_values().borrow().get(&key) {
+ return Ok(val);
}
let ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs,
&ccx.tcx().expr_ty(expr));
// references, even when only the latter are correct.
try!(const_expr_unadjusted(ccx, expr, ty, param_substs, None, trueconst))
} else {
- match const_expr(ccx, expr, param_substs, None, trueconst) {
- Err(err) => return Err(err),
- Ok((ok, _)) => ok,
- }
+ try!(const_expr(ccx, expr, param_substs, None, trueconst)).0
};
// boolean SSA values are i1, but they have to be stored in i8 slots,
};
let _icx = push_ctxt("const_expr");
Ok(match e.node {
- hir::ExprLit(ref lit) => {
- const_lit(cx, e, &**lit)
- },
+ hir::ExprLit(ref lit) => const_lit(cx, e, &**lit),
hir::ExprBinary(b, ref e1, ref e2) => {
/* Neither type is bottom, and we expect them to be unified
* already, so the following is safe. */
use middle::subst::{self, Subst};
use middle::traits;
use middle::ty::{self, Ty};
-use util::nodemap::FnvHashSet;
use syntax::ast;
use syntax::codemap::{self, Span};
rcx: rcx,
span: span,
parent_scope: parent_scope,
- breadcrumbs: FnvHashSet()
+ breadcrumbs: Vec::new(),
},
TypeContext::Root,
typ,
struct DropckContext<'a, 'b: 'a, 'tcx: 'b> {
rcx: &'a mut Rcx<'b, 'tcx>,
/// types that have already been traversed
- breadcrumbs: FnvHashSet<Ty<'tcx>>,
+ breadcrumbs: Vec<Ty<'tcx>>,
/// span for error reporting
span: Span,
/// the scope reachable dtorck types must outlive
depth: usize) -> Result<(), Error<'tcx>>
{
let tcx = cx.rcx.tcx();
+ let ty = cx.rcx.infcx().resolve_type_and_region_vars_if_possible(&ty);
+
// Issue #22443: Watch out for overflow. While we are careful to
// handle regular types properly, non-regular ones cause problems.
let recursion_limit = tcx.sess.recursion_limit.get();
return Err(Error::Overflow(context, ty))
}
- if !cx.breadcrumbs.insert(ty) {
- debug!("iterate_over_potentially_unsafe_regions_in_type \
- {}ty: {} scope: {:?} - cached",
- (0..depth).map(|_| ' ').collect::<String>(),
- ty, cx.parent_scope);
- return Ok(()); // we already visited this type
+ for breadcrumb in &mut cx.breadcrumbs {
+ *breadcrumb =
+ cx.rcx.infcx().resolve_type_and_region_vars_if_possible(breadcrumb);
+ if *breadcrumb == ty {
+ debug!("iterate_over_potentially_unsafe_regions_in_type \
+ {}ty: {} scope: {:?} - cached",
+ (0..depth).map(|_| ' ').collect::<String>(),
+ ty, cx.parent_scope);
+ return Ok(()); // we already visited this type
+ }
}
+ cx.breadcrumbs.push(ty);
+
debug!("iterate_over_potentially_unsafe_regions_in_type \
{}ty: {} scope: {:?}",
(0..depth).map(|_| ' ').collect::<String>(),
!remaining_fields.is_empty()
{
span_err!(tcx.sess, span, E0063,
- "missing field{}: {}",
+ "missing field{} {} in initializer of `{}`",
if remaining_fields.len() == 1 {""} else {"s"},
remaining_fields.keys()
.map(|n| format!("`{}`", n))
.collect::<Vec<_>>()
- .join(", "));
+ .join(", "),
+ adt_ty);
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl error::Error for Error {
+ #[allow(deprecated)] // remove with UnexpectedEOF
fn description(&self) -> &str {
match self.repr {
- Repr::Os(..) => "os error",
+ Repr::Os(..) => match self.kind() {
+ ErrorKind::NotFound => "entity not found",
+ ErrorKind::PermissionDenied => "permission denied",
+ ErrorKind::ConnectionRefused => "connection refused",
+ ErrorKind::ConnectionReset => "connection reset",
+ ErrorKind::ConnectionAborted => "connection aborted",
+ ErrorKind::NotConnected => "not connected",
+ ErrorKind::AddrInUse => "address in use",
+ ErrorKind::AddrNotAvailable => "address not available",
+ ErrorKind::BrokenPipe => "broken pipe",
+ ErrorKind::AlreadyExists => "entity already exists",
+ ErrorKind::WouldBlock => "operation would block",
+ ErrorKind::InvalidInput => "invalid input parameter",
+ ErrorKind::InvalidData => "invalid data",
+ ErrorKind::TimedOut => "timed out",
+ ErrorKind::WriteZero => "write zero",
+ ErrorKind::Interrupted => "operation interrupted",
+ ErrorKind::Other => "other os error",
+ ErrorKind::UnexpectedEOF => "unexpected end of file",
+ ErrorKind::UnexpectedEof => "unexpected end of file",
+ ErrorKind::__Nonexhaustive => unreachable!()
+ },
Repr::Custom(ref c) => c.error.description(),
}
}
mod bar {
use foo::bar::f as g; //~ ERROR unresolved import
-
- use foo as f;
- pub use foo::*;
}
-use bar::f::f; //~ ERROR unresolved import
fn main() {}
}
fn main() {
- let foo = BuildData { //~ ERROR missing field: `bar`
+ let foo = BuildData { //~ ERROR missing field `bar` in initializer of `BuildData`
foo: 0
};
}
--- /dev/null
+// Copyright 2015 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.
+
+struct Test<T: ?Sized>(T);
+
+fn main() {
+ let x = Test([1,2,3]);
+ let x : &Test<[i32]> = &x;
+
+ let & ref _y = x;
+
+ // Make sure binding to a fat pointer behind a reference
+ // still works
+ let slice = &[1,2,3];
+ let x = Test(&slice);
+ let Test(&_slice) = x;
+}
--- /dev/null
+// Copyright 2015 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.
+
+// Test that a field can have the same name in different variants
+// of an enum
+// FIXME #27889
+
+pub enum Foo {
+ X { foo: u32 },
+ Y { foo: u32 }
+}
+
+pub fn foo(mut x: Foo) {
+ let mut y = None;
+ let mut z = None;
+ if let Foo::X { ref foo } = x {
+ z = Some(foo);
+ }
+ if let Foo::Y { ref mut foo } = x {
+ y = Some(foo);
+ }
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2015 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.
+
+use std::sync::Arc;
+
+pub struct DescriptorSet<'a> {
+ pub slots: Vec<AttachInfo<'a, Resources>>
+}
+
+pub trait ResourcesTrait<'r>: Sized {
+ type DescriptorSet: 'r;
+}
+
+pub struct Resources;
+
+impl<'a> ResourcesTrait<'a> for Resources {
+ type DescriptorSet = DescriptorSet<'a>;
+}
+
+pub enum AttachInfo<'a, R: ResourcesTrait<'a>> {
+ NextDescriptorSet(Arc<R::DescriptorSet>)
+}
+
+fn main() {
+ let _x = DescriptorSet {slots: Vec::new()};
+}