diff --git a/src/doc/rust.css b/src/doc/rust.css index cd158283180a2..6204f38a37753 100644 --- a/src/doc/rust.css +++ b/src/doc/rust.css @@ -221,6 +221,10 @@ a > code { color: #428BCA; } +.section-header > a > code { + color: #8D1A38; +} + /* Code highlighting */ pre.rust .kw { color: #8959A8; } pre.rust .kw-2, pre.rust .prelude-ty { color: #4271AE; } diff --git a/src/doc/trpl/SUMMARY.md b/src/doc/trpl/SUMMARY.md index f1e51591aea0e..85f0019276eef 100644 --- a/src/doc/trpl/SUMMARY.md +++ b/src/doc/trpl/SUMMARY.md @@ -16,6 +16,7 @@ * [Iterators](iterators.md) * [Concurrency](concurrency.md) * [Error Handling](error-handling.md) + * [Choosing your Guarantees](choosing-your-guarantees.md) * [FFI](ffi.md) * [Borrow and AsRef](borrow-and-asref.md) * [Release Channels](release-channels.md) diff --git a/src/doc/trpl/choosing-your-guarantees.md b/src/doc/trpl/choosing-your-guarantees.md new file mode 100644 index 0000000000000..3aa8f4db95f77 --- /dev/null +++ b/src/doc/trpl/choosing-your-guarantees.md @@ -0,0 +1,354 @@ +% Choosing your Guarantees + +One important feature of Rust as language is that it lets us control the costs and guarantees +of a program. + +There are various “wrapper type” abstractions in the Rust standard library which embody +a multitude of tradeoffs between cost, ergonomics, and guarantees. Many let one choose between +run time and compile time enforcement. This section will explain a few selected abstractions in +detail. + +Before proceeding, it is highly recommended that one reads about [ownership][ownership] and +[borrowing][borrowing] in Rust. + +[ownership]: ownership.html +[borrowing]: references-and-borrowing.html + +# Basic pointer types + +## `Box` + +[`Box`][box] is pointer which is “owned”, or a “box”. While it can hand +out references to the contained data, it is the only owner of the data. In particular, when +something like the following occurs: + +```rust +let x = Box::new(1); +let y = x; +// x no longer accessible here +``` + +Here, the box was _moved_ into `y`. As `x` no longer owns it, the compiler will no longer allow the +programmer to use `x` after this. A box can similarly be moved _out_ of a function by returning it. + +When a box (that hasn't been moved) goes out of scope, destructors are run. These destructors take +care of deallocating the inner data. + +This is a zero-cost abstraction for dynamic allocation. If you want to allocate some memory on the +heap and safely pass around a pointer to that memory, this is ideal. Note that you will only be +allowed to share references to this by the regular borrowing rules, checked at compile time. + +[box]: ../std/boxed/struct.Box.html + +## `&T` and `&mut T` + +These are immutable and mutable references respectively. They follow the &lquo;read-write lock&rquo; +pattern, such that one may either have only one mutable reference to some data, or any number of +immutable ones, but not both. This guarantee is enforced at compile time, and has no visible cost at +runtime. In most cases these two pointer types suffice for sharing cheap references between sections +of code. + +These pointers cannot be copied in such a way that they outlive the lifetime associated with them. + +## `*const T` and `*mut T` + +These are C-like raw pointers with no lifetime or ownership attached to them. They just point to +some location in memory with no other restrictions. The only guarantee that these provide is that +they cannot be dereferenced except in code marked `unsafe`. + +These are useful when building safe, low cost abstractions like `Vec`, but should be avoided in +safe code. + +## `Rc` + +This is the first wrapper we will cover that has a runtime cost. + +[`Rc`][rc] is a reference counted pointer. In other words, this lets us have multiple "owning" +pointers to the same data, and the data will be dropped (destructors will be run) when all pointers +are out of scope. + +Internally, it contains a shared “reference count” (also called “refcount”), +which is incremented each time the `Rc` is cloned, and decremented each time one of the `Rc`s goes +out of scope. The main responsibility of `Rc` is to ensure that destructors are called for shared +data. + +The internal data here is immutable, and if a cycle of references is created, the data will be +leaked. If we want data that doesn't leak when there are cycles, we need a garbage collector. + +#### Guarantees + +The main guarantee provided here is that the data will not be destroyed until all references to it +are out of scope. + +This should be used when we wish to dynamically allocate and share some data (read-only) between +various portions of yur program, where it is not certain which portion will finish using the pointer +last. It's a viable alternative to `&T` when `&T` is either impossible to statically check for +correctness, or creates extremely unergonomic code where the programmer does not wish to spend the +development cost of working with. + +This pointer is _not_ thread safe, and Rust will not let it be sent or shared with other threads. +This lets one avoid the cost of atomics in situations where they are unnecessary. + +There is a sister smart pointer to this one, `Weak`. This is a non-owning, but also non-borrowed, +smart pointer. It is also similar to `&T`, but it is not restricted in lifetime—a `Weak` +can be held on to forever. However, it is possible that an attempt to access the inner data may fail +and return `None`, since this can outlive the owned `Rc`s. This is useful for cyclic +data structures and other things. + +#### Cost + +As far as memory goes, `Rc` is a single allocation, though it will allocate two extra words (i.e. +two `usize` values) as compared to a regular `Box` (for "strong" and "weak" refcounts). + +`Rc` has the computational cost of incrementing/decrementing the refcount whenever it is cloned +or goes out of scope respectively. Note that a clone will not do a deep copy, rather it will simply +increment the inner reference count and return a copy of the `Rc`. + +[rc]: ../std/rc/struct.Rc.html + +# Cell types + +&lquo;Cell&rquo;s provide interior mutability. In other words, they contain data which can be manipulated even +if the type cannot be obtained in a mutable form (for example, when it is behind an `&`-ptr or +`Rc`). + +[The documentation for the `cell` module has a pretty good explanation for these][cell-mod]. + +These types are _generally_ found in struct fields, but they may be found elsewhere too. + +## `Cell` + +[`Cell`][cell] is a type that provides zero-cost interior mutability, but only for `Copy` types. +Since the compiler knows that all the data owned by the contained value is on the stack, there's +no worry of leaking any data behind references (or worse!) by simply replacing the data. + +It is still possible to violate your own invariants using this wrapper, so be careful when using it. +If a field is wrapped in `Cell`, it's a nice indicator that the chunk of data is mutable and may not +stay the same between the time you first read it and when you intend to use it. + +```rust +let x = Cell::new(1); +let y = &x; +let z = &x; +x.set(2); +y.set(3); +z.set(4); +println!("{}", x.get()); +``` + +Note that here we were able to mutate the same value from various immutable references. + +This has the same runtime cost as the following: + +```rust +let mut x = 1; +let y = &mut x; +let z = &mut x; +x = 2; +*y = 3; +*z = 4; +println!("{}", x; +``` + +but it has the added benefit of actually compiling successfully. + +#### Guarantees + +This relaxes the “no aliasing with mutability” restriction in places where it's +unnecessary. However, this also relaxes the guarantees that the restriction provides; so if your +invariants depend on data stored within `Cell`, you should be careful. + +This is useful for mutating primitives and other `Copy` types when there is no easy way of +doing it in line with the static rules of `&` and `&mut`. + +`Cell` does not let you obtain interior references to the data, which makes it safe to freely +mutate. + +#### Cost + +There is no runtime cost to using `Cell`, however if you are using it to wrap larger (`Copy`) +structs, it might be worthwhile to instead wrap individual fields in `Cell` since each write is +otherwise a full copy of the struct. + + +## `RefCell` + +[`RefCell`][refcell] also provides interior mutability, but isn't restricted to `Copy` types. + +Instead, it has a runtime cost. `RefCell` enforces the read-write lock pattern at runtime (it's +like a single-threaded mutex), unlike `&T`/`&mut T` which do so at compile time. This is done by the +`borrow()` and `borrow_mut()` functions, which modify an internal reference count and return smart +pointers which can be dereferenced immutably and mutably respectively. The refcount is restored when +the smart pointers go out of scope. With this system, we can dynamically ensure that there are never +any other borrows active when a mutable borrow is active. If the programmer attempts to make such a +borrow, the thread will panic. + +```rust +let x = RefCell::new(vec![1,2,3,4]); +{ + println!("{:?}", *x.borrow()) +} + +{ + let my_ref = x.borrow_mut(); + my_ref.push(1); +} +``` + +Similar to `Cell`, this is mainly useful for situations where it's hard or impossible to satisfy the +borrow checker. Generally we know that such mutations won't happen in a nested form, but it's good +to check. + +For large, complicated programs, it becomes useful to put some things in `RefCell`s to make things +simpler. For example, a lot of the maps in [the `ctxt` struct][ctxt] in the rust compiler internals +are inside this wrapper. These are only modified once (during creation, which is not right after +initialization) or a couple of times in well-separated places. However, since this struct is +pervasively used everywhere, juggling mutable and immutable pointers would be hard (perhaps +impossible) and probably form a soup of `&`-ptrs which would be hard to extend. On the other hand, +the `RefCell` provides a cheap (not zero-cost) way of safely accessing these. In the future, if +someone adds some code that attempts to modify the cell when it's already borrowed, it will cause a +(usually deterministic) panic which can be traced back to the offending borrow. + +Similarly, in Servo's DOM there is a lot of mutation, most of which is local to a DOM type, but some +of which crisscrosses the DOM and modifies various things. Using `RefCell` and `Cell` to guard all +mutation lets us avoid worrying about mutability everywhere, and it simultaneously highlights the +places where mutation is _actually_ happening. + +Note that `RefCell` should be avoided if a mostly simple solution is possible with `&` pointers. + +#### Guarantees + +`RefCell` relaxes the _static_ restrictions preventing aliased mutation, and replaces them with +_dynamic_ ones. As such the guarantees have not changed. + +#### Cost + +`RefCell` does not allocate, but it contains an additional "borrow state" +indicator (one word in size) along with the data. + +At runtime each borrow causes a modification/check of the refcount. + +[cell-mod]: ../std/cell/ +[cell]: ../std/cell/struct.Cell.html +[refcell]: ../std/cell/struct.RefCell.html +[ctxt]: ../rustc/middle/ty/struct.ctxt.html + +# Synchronous types + +Many of the types above cannot be used in a threadsafe manner. Particularly, `Rc` and +`RefCell`, which both use non-atomic reference counts (_atomic_ reference counts are those which +can be incremented from multiple threads without causing a data race), cannot be used this way. This +makes them cheaper to use, but we need thread safe versions of these too. They exist, in the form of +`Arc` and `Mutex`/`RWLock` + +Note that the non-threadsafe types _cannot_ be sent between threads, and this is checked at compile +time. + +There are many useful wrappers for concurrent programming in the [sync][sync] module, but only the +major ones will be covered below. + +[sync]: ../std/sync/index.html + +## `Arc` + +[`Arc`][arc] is just a version of `Rc` that uses an atomic reference count (hence, "Arc"). +This can be sent freely between threads. + +C++'s `shared_ptr` is similar to `Arc`, however in the case of C++ the inner data is always mutable. +For semantics similar to that from C++, we should use `Arc>`, `Arc>`, or +`Arc>`[^4] (`UnsafeCell` is a cell type that can be used to hold any data and has +no runtime cost, but accessing it requires `unsafe` blocks). The last one should only be used if we +are certain that the usage won't cause any memory unsafety. Remember that writing to a struct is not +an atomic operation, and many functions like `vec.push()` can reallocate internally and cause unsafe +behavior, so even monotonicity may not be enough to justify `UnsafeCell`. + +[^4]: `Arc>` actually won't compile since `UnsafeCell` isn't `Send` or `Sync`, but we can wrap it in a type and implement `Send`/`Sync` for it manually to get `Arc>` where `Wrapper` is `struct Wrapper(UnsafeCell)`. + +#### Guarantees + +Like `Rc`, this provides the (thread safe) guarantee that the destructor for the internal data will +be run when the last `Arc` goes out of scope (barring any cycles). + +#### Cost + +This has the added cost of using atomics for changing the refcount (which will happen whenever it is +cloned or goes out of scope). When sharing data from an `Arc` in a single thread, it is preferable +to share `&` pointers whenever possible. + +[arc]: ../std/sync/struct.Arc.html + +## `Mutex` and `RwLock` + +[`Mutex`][mutex] and [`RwLock`][rwlock] provide mutual-exclusion via RAII guards (guards are +objects which maintain some state, like a lock, until their destructor is called). For both of +these, the mutex is opaque until we call `lock()` on it, at which point the thread will block +until a lock can be acquired, and then a guard will be returned. This guard can be used to access +the inner data (mutably), and the lock will be released when the guard goes out of scope. + +```rust +{ + let guard = mutex.lock(); + // guard dereferences mutably to the inner type + *guard += 1; +} // lock released when destructor runs +``` + + +`RwLock` has the added benefit of being efficient for multiple reads. It is always safe to have +multiple readers to shared data as long as there are no writers; and `RwLock` lets readers acquire a +"read lock". Such locks can be acquired concurrently and are kept track of via a reference count. +Writers must obtain a "write lock" which can only be obtained when all readers have gone out of +scope. + +#### Guarantees + +Both of these provide safe shared mutability across threads, however they are prone to deadlocks. +Some level of additional protocol safety can be obtained via the type system. +#### Costs + +These use internal atomic-like types to maintain the locks, which are pretty costly (they can block +all memory reads across processors till they're done). Waiting on these locks can also be slow when +there's a lot of concurrent access happening. + +[rwlock]: ../std/sync/struct.RwLock.html +[mutex]: ../std/sync/struct.Mutex.html +[sessions]: https://github.com/Munksgaard/rust-sessions + +# Composition + +A common gripe when reading Rust code is with types like `Rc>>` (or even more more +complicated compositions of such types). It's not always clear what the composition does, or why the +author chose one like this (and when one should be using such a composition in one's own code) + +Usually, it's a case of composing together the guarantees that you need, without paying for stuff +that is unnecessary. + +For example, `Rc>` is one such composition. `Rc` itself can't be dereferenced mutably; +because `Rc` provides sharing and shared mutability can lead to unsafe behavior, so we put +`RefCell` inside to get dynamically verified shared mutability. Now we have shared mutable data, +but it's shared in a way that there can only be one mutator (and no readers) or multiple readers. + +Now, we can take this a step further, and have `Rc>>` or `Rc>>`. These +are both shareable, mutable vectors, but they're not the same. + +With the former, the `RefCell` is wrapping the `Vec`, so the `Vec` in its entirety is +mutable. At the same time, there can only be one mutable borrow of the whole `Vec` at a given time. +This means that your code cannot simultaneously work on different elements of the vector from +different `Rc` handles. However, we are able to push and pop from the `Vec` at will. This is +similar to an `&mut Vec` with the borrow checking done at runtime. + +With the latter, the borrowing is of individual elements, but the overall vector is immutable. Thus, +we can independently borrow separate elements, but we cannot push or pop from the vector. This is +similar to an `&mut [T]`[^3], but, again, the borrow checking is at runtime. + +In concurrent programs, we have a similar situation with `Arc>`, which provides shared +mutability and ownership. + +When reading code that uses these, go in step by step and look at the guarantees/costs provided. + +When choosing a composed type, we must do the reverse; figure out which guarantees we want, and at +which point of the composition we need them. For example, if there is a choice between +`Vec>` and `RefCell>`, we should figure out the tradeoffs as done above and pick +one. + +[^3]: `&[T]` and `&mut [T]` are _slices_; they consist of a pointer and a length and can refer to a portion of a vector or array. `&mut [T]` can have its elements mutated, however its length cannot be touched. diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 88aa805668cfa..c6d0e97a0cd00 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -84,10 +84,18 @@ pub fn from_u32(i: u32) -> Option { if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) { None } else { - Some(unsafe { transmute(i) }) + Some(unsafe { from_u32_unchecked(i) }) } } +/// Converts a `u32` to an `char`, not checking whether it is a valid unicode +/// codepoint. +#[inline] +#[unstable(feature = "char_from_unchecked", reason = "recently added API")] +pub unsafe fn from_u32_unchecked(i: u32) -> char { + transmute(i) +} + /// Converts a number to the character representing it. /// /// # Return value @@ -115,12 +123,11 @@ pub fn from_digit(num: u32, radix: u32) -> Option { panic!("from_digit: radix is too high (maximum 36)"); } if num < radix { - unsafe { - if num < 10 { - Some(transmute('0' as u32 + num)) - } else { - Some(transmute('a' as u32 + num - 10)) - } + let num = num as u8; + if num < 10 { + Some((b'0' + num) as char) + } else { + Some((b'a' + num - 10) as char) } } else { None @@ -318,16 +325,13 @@ impl Iterator for EscapeUnicode { Some('{') } EscapeUnicodeState::Value(offset) => { - let v = match ((self.c as i32) >> (offset * 4)) & 0xf { - i @ 0 ... 9 => '0' as i32 + i, - i => 'a' as i32 + (i - 10) - }; + let c = from_digit(((self.c as u32) >> (offset * 4)) & 0xf, 16).unwrap(); if offset == 0 { self.state = EscapeUnicodeState::RightBrace; } else { self.state = EscapeUnicodeState::Value(offset - 1); } - Some(unsafe { transmute(v) }) + Some(c) } EscapeUnicodeState::RightBrace => { self.state = EscapeUnicodeState::Done; diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 4e21efcf9eb6b..879a2d740cb0b 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -22,6 +22,22 @@ matched, one of the preceding patterns will match. This means that perhaps some of the preceding patterns are too general, this one is too specific or the ordering is incorrect. + +For example, the following `match` block has too many arms: + +``` +match foo { + Some(bar) => {/* ... */} + None => {/* ... */} + _ => {/* ... */} // All possible cases have already been handled +} +``` + +`match` blocks have their patterns matched in order, so, for example, putting +a wildcard arm above a more specific arm will make the latter arm irrelevant. + +Ensure the ordering of the match arm is correct and remove any superfluous +arms. "##, E0002: r##" @@ -31,13 +47,50 @@ it is impossible to create an instance of an empty type, so empty match expressions are almost never desired. This error is typically fixed by adding one or more cases to the match expression. -An example of an empty type is `enum Empty { }`. +An example of an empty type is `enum Empty { }`. So, the following will work: + +``` +fn foo(x: Empty) { + match x { + // empty + } +} +``` + +However, this won't: + +``` +fn foo(x: Option) { + match x { + // empty + } +} +``` "##, E0003: r##" Not-a-Number (NaN) values cannot be compared for equality and hence can never -match the input to a match expression. To match against NaN values, you should -instead use the `is_nan` method in a guard, as in: `x if x.is_nan() => ...` +match the input to a match expression. So, the following will not compile: + +``` +const NAN: f32 = 0.0 / 0.0; + +match number { + NAN => { /* ... */ }, + // ... +} +``` + +To match against NaN values, you should instead use the `is_nan()` method in a +guard, like so: + +``` +match number { + // ... + x if x.is_nan() => { /* ... */ } + // ... +} +``` "##, E0004: r##" @@ -53,7 +106,6 @@ underscore `_` wildcard pattern can be added after all other patterns to match "anything else". "##, -// FIXME: Remove duplication here? E0005: r##" Patterns used to bind names must be irrefutable, that is, they must guarantee that a name will be extracted in all cases. If you encounter this error you @@ -61,13 +113,6 @@ probably need to use a `match` or `if let` to deal with the possibility of failure. "##, -E0006: r##" -Patterns used to bind names must be irrefutable, that is, they must guarantee -that a name will be extracted in all cases. If you encounter this error you -probably need to use a `match` or `if let` to deal with the possibility of -failure. -"##, - E0007: r##" This error indicates that the bindings in a match arm would require a value to be moved into more than one location, thus violating unique ownership. Code like @@ -271,6 +316,28 @@ const FOO: i32 = { const X : i32 = 0; X }; ``` "##, +E0017: r##" +References in statics and constants may only refer to immutable values. Example: + +``` +static X: i32 = 1; +const C: i32 = 2; + +// these three are not allowed: +const CR: &'static mut i32 = &mut C; +static STATIC_REF: &'static mut i32 = &mut X; +static CONST_REF: &'static mut i32 = &mut C; +``` + +Statics are shared everywhere, and if they refer to mutable data one might +violate memory safety since holding multiple mutable references to shared data +is not allowed. + +If you really want global mutable state, try using `static mut` or a global +`UnsafeCell`. + +"##, + E0018: r##" The value of static and const variables must be known at compile time. You can't cast a pointer as an integer because we can't know what value the @@ -318,7 +385,7 @@ fn main() { ``` Remember: you can't use a function call inside a const's initialization -expression! However, you can totally use it elsewhere you want: +expression! However, you can totally use it anywhere else: ``` fn main() { @@ -335,6 +402,24 @@ This error indicates that an attempt was made to divide by zero (or take the remainder of a zero divisor) in a static or constant expression. "##, +E0022: r##" +Constant functions are not allowed to mutate anything. Thus, binding to an +argument with a mutable pattern is not allowed. For example, + +``` +const fn foo(mut x: u8) { + // do stuff +} +``` + +is bad because the function body may not mutate `x`. + +Remove any mutable bindings from the argument list to fix this error. In case +you need to mutate the argument, try lazily initializing a global variable +instead of using a `const fn`, or refactoring the code to a functional style to +avoid mutation if possible. +"##, + E0030: r##" When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to @@ -353,10 +438,297 @@ match 5u32 { ``` "##, +E0038: r####" +Trait objects like `Box` can only be constructed when certain +requirements are satisfied by the trait in question. + +Trait objects are a form of dynamic dispatch and use a dynamically sized type +for the inner type. So, for a given trait `Trait`, when `Trait` is treated as a +type, as in `Box`, the inner type is 'unsized'. In such cases the boxed +pointer is a 'fat pointer' that contains an extra pointer to a table of methods +(among other things) for dynamic dispatch. This design mandates some +restrictions on the types of traits that are allowed to be used in trait +objects, which are collectively termed as 'object safety' rules. + +Attempting to create a trait object for a non object-safe trait will trigger +this error. + +There are various rules: + +### The trait cannot require `Self: Sized` + +When `Trait` is treated as a type, the type does not implement the special +`Sized` trait, because the type does not have a known size at compile time and +can only be accessed behind a pointer. Thus, if we have a trait like the +following: + +``` +trait Foo where Self: Sized { + +} +``` + +we cannot create an object of type `Box` or `&Foo` since in this case +`Self` would not be `Sized`. + +Generally, `Self : Sized` is used to indicate that the trait should not be used +as a trait object. If the trait comes from your own crate, consider removing +this restriction. + +### Method references the `Self` type in its arguments or return type + +This happens when a trait has a method like the following: + +``` +trait Trait { + fn foo(&self) -> Self; +} + +impl Trait for String { + fn foo(&self) -> Self { + "hi".to_owned() + } +} + +impl Trait for u8 { + fn foo(&self) -> Self { + 1 + } +} +``` + +(Note that `&self` and `&mut self` are okay, it's additional `Self` types which +cause this problem) + +In such a case, the compiler cannot predict the return type of `foo()` in a +situation like the following: + +``` +fn call_foo(x: Box) { + let y = x.foo(); // What type is y? + // ... +} +``` + +If only some methods aren't object-safe, you can add a `where Self: Sized` bound +on them to mark them as explicitly unavailable to trait objects. The +functionality will still be available to all other implementers, including +`Box` which is itself sized (assuming you `impl Trait for Box`). + +``` +trait Trait { + fn foo(&self) -> Self where Self: Sized; + // more functions +} +``` + +Now, `foo()` can no longer be called on a trait object, but you will now be +allowed to make a trait object, and that will be able to call any object-safe +methods". With such a bound, one can still call `foo()` on types implementing +that trait that aren't behind trait objects. + +### Method has generic type parameters + +As mentioned before, trait objects contain pointers to method tables. So, if we +have: + +``` +trait Trait { + fn foo(&self); +} +impl Trait for String { + fn foo(&self) { + // implementation 1 + } +} +impl Trait for u8 { + fn foo(&self) { + // implementation 2 + } +} +// ... +``` + +At compile time each implementation of `Trait` will produce a table containing +the various methods (and other items) related to the implementation. + +This works fine, but when the method gains generic parameters, we can have a +problem. + +Usually, generic parameters get _monomorphized_. For example, if I have + +``` +fn foo(x: T) { + // ... +} +``` + +the machine code for `foo::()`, `foo::()`, `foo::()`, or any +other type substitution is different. Hence the compiler generates the +implementation on-demand. If you call `foo()` with a `bool` parameter, the +compiler will only generate code for `foo::()`. When we have additional +type parameters, the number of monomorphized implementations the compiler +generates does not grow drastically, since the compiler will only generate an +implementation if the function is called with unparametrized substitutions +(i.e., substitutions where none of the substituted types are themselves +parametrized). + +However, with trait objects we have to make a table containing _every_ object +that implements the trait. Now, if it has type parameters, we need to add +implementations for every type that implements the trait, and there could +theoretically be an infinite number of types. + +For example, with: + +``` +trait Trait { + fn foo(&self, on: T); + // more methods +} +impl Trait for String { + fn foo(&self, on: T) { + // implementation 1 + } +} +impl Trait for u8 { + fn foo(&self, on: T) { + // implementation 2 + } +} +// 8 more implementations +``` + +Now, if we have the following code: + +``` +fn call_foo(thing: Box) { + thing.foo(true); // this could be any one of the 8 types above + thing.foo(1); + thing.foo("hello"); +} +``` + +we don't just need to create a table of all implementations of all methods of +`Trait`, we need to create such a table, for each different type fed to +`foo()`. In this case this turns out to be (10 types implementing `Trait`)*(3 +types being fed to `foo()`) = 30 implementations! + +With real world traits these numbers can grow drastically. + +To fix this, it is suggested to use a `where Self: Sized` bound similar to the +fix for the sub-error above if you do not intend to call the method with type +parameters: + +``` +trait Trait { + fn foo(&self, on: T) where Self: Sized; + // more methods +} +``` + +If this is not an option, consider replacing the type parameter with another +trait object (e.g. if `T: OtherTrait`, use `on: Box`). If the number +of types you intend to feed to this method is limited, consider manually listing +out the methods of different types. + +### Method has no receiver + +Methods that do not take a `self` parameter can't be called since there won't be +a way to get a pointer to the method table for them + +``` +trait Foo { + fn foo() -> u8; +} +``` + +This could be called as `::foo()`, which would not be able to pick +an implementation. + +Adding a `Self: Sized` bound to these methods will generally make this compile. + +``` +trait Foo { + fn foo() -> u8 where Self: Sized; +} +``` + +### The trait cannot use `Self` as a type parameter in the supertrait listing + +This is similar to the second sub-error, but subtler. It happens in situations +like the following: + +``` +trait Super {} + +trait Trait: Super { +} + +struct Foo; + +impl Super for Foo{} + +impl Trait for Foo {} +``` + +Here, the supertrait might have methods as follows: + +``` +trait Super { + fn get_a(&self) -> A; // note that this is object safe! +} +``` + +If the trait `Foo` was deriving from something like `Super` or +`Super` (where `Foo` itself is `Foo`), this is okay, because given a type +`get_a()` will definitely return an object of that type. + +However, if it derives from `Super`, even though `Super` is object safe, +the method `get_a()` would return an object of unknown type when called on the +function. `Self` type parameters let us make object safe traits no longer safe, +so they are forbidden when specifying supertraits. + +There's no easy fix for this, generally code will need to be refactored so that +you no longer need to derive from `Super`. +"####, + E0079: r##" Enum variants which contain no data can be given a custom integer -representation. This error indicates that the value provided is not an -integer literal and is therefore invalid. +representation. This error indicates that the value provided is not an integer +literal and is therefore invalid. + +For example, in the following code, + +``` +enum Foo { + Q = "32" +} +``` + +we try to set the representation to a string. + +There's no general fix for this; if you can work with an integer then just set +it to one: + +``` +enum Foo { + Q = 32 +} +``` + +however if you actually wanted a mapping between variants and non-integer +objects, it may be preferable to use a method with a match instead: + +``` +enum Foo { Q } +impl Foo { + fn get_str(&self) -> &'static str { + match *self { + Foo::Q => "32", + } + } +} +``` "##, E0080: r##" @@ -388,10 +760,11 @@ type X = u32; // error: type parameters are not allowed on this type Please check that you used the correct type and recheck its definition. Perhaps it doesn't need the type parameter. + Example: ``` -type X = u32; // ok! +type X = u32; // this compiles ``` "##, @@ -404,8 +777,8 @@ type X = u32<'static>; // error: lifetime parameters are not allowed on // this type ``` -Please check that you used the correct type and recheck its definition, -perhaps it doesn't need the lifetime parameter. Example: +Please check that the correct type was used and recheck its definition; perhaps +it doesn't need the lifetime parameter. Example: ``` type X = u32; // ok! @@ -429,12 +802,96 @@ fn main() { See also https://doc.rust-lang.org/book/unsafe.html "##, +// This shouldn't really ever trigger since the repeated value error comes first +E0136: r##" +A binary can only have one entry point, and by default that entry point is the +function `main()`. If there are multiple such functions, please rename one. +"##, + E0137: r##" This error indicates that the compiler found multiple functions with the `#[main]` attribute. This is an error because there must be a unique entry point into a Rust program. "##, +E0138: r##" +This error indicates that the compiler found multiple functions with the +`#[start]` attribute. This is an error because there must be a unique entry +point into a Rust program. +"##, + +// FIXME link this to the relevant turpl chapters for instilling fear of the +// transmute gods in the user +E0139: r##" +There are various restrictions on transmuting between types in Rust; for example +types being transmuted must have the same size. To apply all these restrictions, +the compiler must know the exact types that may be transmuted. When type +parameters are involved, this cannot always be done. + +So, for example, the following is not allowed: + +``` +struct Foo(Vec) + +fn foo(x: Vec) { + // we are transmuting between Vec and Foo here + let y: Foo = unsafe { transmute(x) }; + // do something with y +} +``` + +In this specific case there's a good chance that the transmute is harmless (but +this is not guaranteed by Rust). However, when alignment and enum optimizations +come into the picture, it's quite likely that the sizes may or may not match +with different type parameter substitutions. It's not possible to check this for +_all_ possible types, so `transmute()` simply only accepts types without any +unsubstituted type parameters. + +If you need this, there's a good chance you're doing something wrong. Keep in +mind that Rust doesn't guarantee much about the layout of different structs +(even two structs with identical declarations may have different layouts). If +there is a solution that avoids the transmute entirely, try it instead. + +If it's possible, hand-monomorphize the code by writing the function for each +possible type substitution. It's possible to use traits to do this cleanly, +for example: + +``` +trait MyTransmutableType { + fn transmute(Vec) -> Foo +} + +impl MyTransmutableType for u8 { + fn transmute(x: Foo) -> Vec { + transmute(x) + } +} +impl MyTransmutableType for String { + fn transmute(x: Foo) -> Vec { + transmute(x) + } +} +// ... more impls for the types you intend to transmute + +fn foo(x: Vec) { + let y: Foo = ::transmute(x); + // do something with y +} +``` + +Each impl will be checked for a size match in the transmute as usual, and since +there are no unbound type parameters involved, this should compile unless there +is a size mismatch in one of the impls. + +It is also possible to manually transmute: + +``` +let result: SomeType = mem::uninitialized(); +unsafe { copy_nonoverlapping(&v, &result) }; +result // `v` transmuted to type `SomeType` +``` +"##, + E0152: r##" Lang items are already implemented in the standard library. Unless you are writing a free-standing application (e.g. a kernel), you do not need to provide @@ -552,6 +1009,14 @@ you prefer them unqualified, you can import the variants into scope: use Method::*; enum Method { GET, POST } ``` + +If you want others to be able to import variants from your module directly, use +`pub use`: + +``` +pub use Method::*; +enum Method { GET, POST } +``` "##, E0261: r##" @@ -663,6 +1128,108 @@ fn some_func() { ``` "##, +E0269: r##" +Functions must eventually return a value of their return type. For example, in +the following function + +``` +fn foo(x: u8) -> u8 { + if x > 0 { + x // alternatively, `return x` + } + // nothing here +} +``` + +if the condition is true, the value `x` is returned, but if the condition is +false, control exits the `if` block and reaches a place where nothing is being +returned. All possible control paths must eventually return a `u8`, which is not +happening here. + +An easy fix for this in a complicated function is to specify a default return +value, if possible: + +``` +fn foo(x: u8) -> u8 { + if x > 0 { + x // alternatively, `return x` + } + // lots of other if branches + 0 // return 0 if all else fails +} +``` + +It is advisable to find out what the unhandled cases are and check for them, +returning an appropriate value or panicking if necessary. +"##, + +E0270: r##" +Rust lets you define functions which are known to never return, i.e. are +'diverging', by marking its return type as `!`. + +For example, the following functions never return: + +``` +fn foo() -> ! { + loop {} +} + +fn bar() -> ! { + foo() // foo() is diverging, so this will diverge too +} + +fn baz() -> ! { + panic!(); // this macro internally expands to a call to a diverging function +} + +``` + +Such functions can be used in a place where a value is expected without +returning a value of that type, for instance: + +``` +let y = match x { + 1 => 1, + 2 => 4, + _ => foo() // diverging function called here +}; +println!("{}", y) +``` + +If the third arm of the match block is reached, since `foo()` doesn't ever +return control to the match block, it is fine to use it in a place where an +integer was expected. The `match` block will never finish executing, and any +point where `y` (like the print statement) is needed will not be reached. + +However, if we had a diverging function that actually does finish execution + +``` +fn foo() -> { + loop {break;} +} +``` + +then we would have an unknown value for `y` in the following code: + +``` +let y = match x { + 1 => 1, + 2 => 4, + _ => foo() +}; +println!("{}", y); +``` + +In the previous example, the print statement was never reached when the wildcard +match arm was hit, so we were okay with `foo()` not returning an integer that we +could set to `y`. But in this example, `foo()` actually does return control, so +the print statement will be executed with an uninitialized value. + +Obviously we cannot have functions which are allowed to be used in such +positions and yet can return control. So, if you are defining a function that +returns `!`, make sure that there is no way for it to actually finish executing. +"##, + E0271: r##" This is because of a type mismatch between the associated type of some trait (e.g. `T::Bar`, where `T` implements `trait Quux { type Bar; }`) @@ -799,6 +1366,132 @@ for v in &vs { ``` "##, +E0272: r##" +The `#[rustc_on_unimplemented]` attribute lets you specify a custom error +message for when a particular trait isn't implemented on a type placed in a +position that needs that trait. For example, when the following code is +compiled: + +``` +fn foo>(x: T){} + +#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"] +trait Index { ... } + +foo(true); // `bool` does not implement `Index` +``` + +there will be an error about `bool` not implementing `Index`, followed by a +note saying "the type `bool` cannot be indexed by `u8`". + +As you can see, you can specify type parameters in curly braces for substitution +with the actual types (using the regular format string syntax) in a given +situation. Furthermore, `{Self}` will substitute to the type (in this case, +`bool`) that we tried to use. + +This error appears when the curly braces contain an identifier which doesn't +match with any of the type parameters or the string `Self`. This might happen if +you misspelled a type parameter, or if you intended to use literal curly braces. +If it is the latter, escape the curly braces with a second curly brace of the +same type; e.g. a literal `{` is `{{` +"##, + +E0273: r##" +The `#[rustc_on_unimplemented]` attribute lets you specify a custom error +message for when a particular trait isn't implemented on a type placed in a +position that needs that trait. For example, when the following code is +compiled: + +``` +fn foo>(x: T){} + +#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"] +trait Index { ... } + +foo(true); // `bool` does not implement `Index` +``` + +there will be an error about `bool` not implementing `Index`, followed by a +note saying "the type `bool` cannot be indexed by `u8`". + +As you can see, you can specify type parameters in curly braces for substitution +with the actual types (using the regular format string syntax) in a given +situation. Furthermore, `{Self}` will substitute to the type (in this case, +`bool`) that we tried to use. + +This error appears when the curly braces do not contain an identifier. Please +add one of the same name as a type parameter. If you intended to use literal +braces, use `{{` and `}}` to escape them. +"##, + +E0274: r##" +The `#[rustc_on_unimplemented]` attribute lets you specify a custom error +message for when a particular trait isn't implemented on a type placed in a +position that needs that trait. For example, when the following code is +compiled: + +``` +fn foo>(x: T){} + +#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"] +trait Index { ... } + +foo(true); // `bool` does not implement `Index` +``` + +there will be an error about `bool` not implementing `Index`, followed by a +note saying "the type `bool` cannot be indexed by `u8`". + +For this to work, some note must be specified. An empty attribute will not do +anything, please remove the attribute or add some helpful note for users of the +trait. +"##, + +E0275: r##" +This error occurs when there was a recursive trait requirement that overflowed +before it could be evaluated. Often this means that there is unbounded recursion +in resolving some type bounds. + +For example, in the following code + +``` +trait Foo {} + +struct Bar(T); + +impl Foo for T where Bar: Foo {} +``` + +to determine if a `T` is `Foo`, we need to check if `Bar` is `Foo`. However, +to do this check, we need to determine that `Bar>` is `Foo`. To determine +this, we check if `Bar>>` is `Foo`, and so on. This is clearly a +recursive requirement that can't be resolved directly. + +Consider changing your trait bounds so that they're less self-referential. +"##, + +E0276: r##" +This error occurs when a bound in an implementation of a trait does not match +the bounds specified in the original trait. For example: + +``` +trait Foo { + fn foo(x: T); +} + +impl Foo for bool { + fn foo(x: T) where T: Copy {} +} +``` + +Here, all types implementing `Foo` must have a method `foo(x: T)` which can +take any type `T`. However, in the `impl` for `bool`, we have added an extra +bound that `T` is `Copy`, which isn't compatible with the original trait. + +Consider removing the bound from the method or adding the bound to the original +method definition in the trait. +"##, + E0277: r##" You tried to use a type which doesn't implement some trait in a place which expected that trait. Erroneous code example: @@ -1219,22 +1912,10 @@ contain references (with a maximum lifetime of `'a`). register_diagnostics! { - E0017, - E0022, - E0038, + // E0006 // merged with E0005 // E0134, // E0135, - E0136, - E0138, - E0139, E0264, // unknown external lang item - E0269, // not all control paths return a value - E0270, // computation may converge in a function marked as diverging - E0272, // rustc_on_unimplemented attribute refers to non-existent type parameter - E0273, // rustc_on_unimplemented must have named format arguments - E0274, // rustc_on_unimplemented must have a value - E0275, // overflow evaluating requirement - E0276, // requirement appears on impl method but not on corresponding trait method E0278, // requirement is not satisfied E0279, // requirement is not satisfied E0280, // requirement is not satisfied diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index d8c2341df2d9f..ea86fa318b45d 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -1049,7 +1049,7 @@ fn check_fn(cx: &mut MatchCheckCtxt, for input in &decl.inputs { is_refutable(cx, &*input.pat, |pat| { - span_err!(cx.tcx.sess, input.pat.span, E0006, + span_err!(cx.tcx.sess, input.pat.span, E0005, "refutable pattern in function argument: `{}` not covered", pat_to_string(pat) ); diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index a54aee2436772..c6df1c395ccec 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -698,8 +698,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - fn rollback_to(&self, snapshot: CombinedSnapshot) { - debug!("rollback!"); + fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot) { + debug!("rollback_to(cause={})", cause); let CombinedSnapshot { type_snapshot, int_snapshot, float_snapshot, @@ -759,7 +759,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { debug!("commit_if_ok() -- r.is_ok() = {}", r.is_ok()); match r { Ok(_) => { self.commit_from(snapshot); } - Err(_) => { self.rollback_to(snapshot); } + Err(_) => { self.rollback_to("commit_if_ok -- error", snapshot); } } r } @@ -778,6 +778,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let r = self.commit_if_ok(|_| f()); + debug!("commit_regions_if_ok: rolling back everything but regions"); + // Roll back any non-region bindings - they should be resolved // inside `f`, with, e.g. `resolve_type_vars_if_possible`. self.type_variables @@ -804,7 +806,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { debug!("probe()"); let snapshot = self.start_snapshot(); let r = f(&snapshot); - self.rollback_to(snapshot); + self.rollback_to("probe", snapshot); r } diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 4061581ded8f0..5727f07edb1d0 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1351,11 +1351,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // correct trait, but also the correct type parameters. // For example, we may be trying to upcast `Foo` to `Bar`, // but `Foo` is declared as `trait Foo : Bar`. - let upcast_trait_refs = util::supertraits(self.tcx(), poly_trait_ref) - .filter(|upcast_trait_ref| self.infcx.probe(|_| { - let upcast_trait_ref = upcast_trait_ref.clone(); - self.match_poly_trait_ref(obligation, upcast_trait_ref).is_ok() - })).count(); + let upcast_trait_refs = + util::supertraits(self.tcx(), poly_trait_ref) + .filter(|upcast_trait_ref| { + self.infcx.probe(|_| { + let upcast_trait_ref = upcast_trait_ref.clone(); + self.match_poly_trait_ref(obligation, upcast_trait_ref).is_ok() + }) + }) + .count(); if upcast_trait_refs > 1 { // can be upcast in many ways; need more type information @@ -1627,9 +1631,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let principal = data.principal_trait_ref_with_self_ty(self.tcx(), self.tcx().types.err); - let desired_def_id = obligation.predicate.def_id(); + let copy_def_id = obligation.predicate.def_id(); for tr in util::supertraits(self.tcx(), principal) { - if tr.def_id() == desired_def_id { + if tr.def_id() == copy_def_id { return ok_if(Vec::new()) } } @@ -2282,31 +2286,41 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } }; - // Upcast the object type to the obligation type. There must - // be exactly one applicable trait-reference; if this were not - // the case, we would have reported an ambiguity error rather - // than successfully selecting one of the candidates. - let mut upcast_trait_refs = util::supertraits(self.tcx(), poly_trait_ref) - .map(|upcast_trait_ref| { - (upcast_trait_ref.clone(), self.infcx.probe(|_| { - self.match_poly_trait_ref(obligation, upcast_trait_ref) - }).is_ok()) - }); let mut upcast_trait_ref = None; - let mut vtable_base = 0; + let vtable_base; + + { + // We want to find the first supertrait in the list of + // supertraits that we can unify with, and do that + // unification. We know that there is exactly one in the list + // where we can unify because otherwise select would have + // reported an ambiguity. (When we do find a match, also + // record it for later.) + let nonmatching = + util::supertraits(self.tcx(), poly_trait_ref) + .take_while(|&t| { + match + self.infcx.commit_if_ok( + |_| self.match_poly_trait_ref(obligation, t)) + { + Ok(_) => { upcast_trait_ref = Some(t); false } + Err(_) => { true } + } + }); + + // Additionally, for each of the nonmatching predicates that + // we pass over, we sum up the set of number of vtable + // entries, so that we can compute the offset for the selected + // trait. + vtable_base = + nonmatching.map(|t| util::count_own_vtable_entries(self.tcx(), t)) + .sum(); - while let Some((supertrait, matches)) = upcast_trait_refs.next() { - if matches { - upcast_trait_ref = Some(supertrait); - break; - } - vtable_base += util::count_own_vtable_entries(self.tcx(), supertrait); } - assert!(upcast_trait_refs.all(|(_, matches)| !matches)); VtableObjectData { upcast_trait_ref: upcast_trait_ref.unwrap(), - vtable_base: vtable_base + vtable_base: vtable_base, } } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index aa1c8bfaa904f..84ca7cd437a96 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1985,7 +1985,7 @@ impl<'tcx> PolyTraitRef<'tcx> { /// erase, or otherwise "discharge" these bound regions, we change the /// type from `Binder` to just `T` (see /// e.g. `liberate_late_bound_regions`). -#[derive(Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct Binder(pub T); impl Binder { diff --git a/src/librustc_unicode/char.rs b/src/librustc_unicode/char.rs index 42c19ee6a204d..34b0ae18d4fe8 100644 --- a/src/librustc_unicode/char.rs +++ b/src/librustc_unicode/char.rs @@ -35,7 +35,7 @@ use core::iter::Iterator; use tables::{derived_property, property, general_category, conversions, charwidth}; // stable reexports -pub use core::char::{MAX, from_u32, from_digit, EscapeUnicode, EscapeDefault}; +pub use core::char::{MAX, from_u32, from_u32_unchecked, from_digit, EscapeUnicode, EscapeDefault}; // unstable reexports #[allow(deprecated)] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 907eb3ed401ff..440e3a26f6b33 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -210,6 +210,7 @@ #![feature(borrow_state)] #![feature(box_raw)] #![feature(box_syntax)] +#![feature(char_from_unchecked)] #![feature(char_internals)] #![feature(clone_from_slice)] #![feature(collections)] diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index fc9585d919069..d881acba94ea3 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -185,7 +185,7 @@ mod imp { use io; use mem; use rand::Rng; - use libc::{c_int, size_t}; + use libc::{c_int, c_void, size_t}; /// A random number generator that retrieves randomness straight from /// the operating system. Platform sources: @@ -203,8 +203,9 @@ mod imp { _dummy: (), } - #[repr(C)] - struct SecRandom; + // Fake definition; this is actually a struct, but we don't use the + // contents here. + type SecRandom = c_void; #[allow(non_upper_case_globals)] const kSecRandomDefault: *const SecRandom = 0 as *const SecRandom; diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs index 8ea673d2162d1..6f15d606724e5 100644 --- a/src/libstd/sys/common/wtf8.rs +++ b/src/libstd/sys/common/wtf8.rs @@ -32,17 +32,18 @@ use core::str::next_code_point; use ascii::*; use borrow::Cow; +use char; use cmp; use fmt; use hash::{Hash, Hasher}; use iter::FromIterator; use mem; use ops; +use rustc_unicode::str::{Utf16Item, utf16_items}; use slice; use str; use string::String; use sys_common::AsInner; -use rustc_unicode::str::{Utf16Item, utf16_items}; use vec::Vec; const UTF8_REPLACEMENT_CHARACTER: &'static [u8] = b"\xEF\xBF\xBD"; @@ -107,7 +108,7 @@ impl CodePoint { pub fn to_char(&self) -> Option { match self.value { 0xD800 ... 0xDFFF => None, - _ => Some(unsafe { mem::transmute(self.value) }) + _ => Some(unsafe { char::from_u32_unchecked(self.value) }) } } @@ -213,18 +214,16 @@ impl Wtf8Buf { // Attempt to not use an intermediate buffer by just pushing bytes // directly onto this string. let slice = slice::from_raw_parts_mut( - self.bytes.as_mut_ptr().offset(cur_len as isize), - 4 + self.bytes.as_mut_ptr().offset(cur_len as isize), 4 ); - let used = encode_utf8_raw(code_point.value, mem::transmute(slice)) - .unwrap_or(0); + let used = encode_utf8_raw(code_point.value, slice).unwrap(); self.bytes.set_len(cur_len + used); } } #[inline] pub fn as_slice(&self) -> &Wtf8 { - unsafe { mem::transmute(&*self.bytes) } + unsafe { Wtf8::from_bytes_unchecked(&self.bytes) } } /// Reserves capacity for at least `additional` more bytes to be inserted @@ -457,7 +456,16 @@ impl Wtf8 { /// Since WTF-8 is a superset of UTF-8, this always succeeds. #[inline] pub fn from_str(value: &str) -> &Wtf8 { - unsafe { mem::transmute(value.as_bytes()) } + unsafe { Wtf8::from_bytes_unchecked(value.as_bytes()) } + } + + /// Creates a WTF-8 slice from a WTF-8 byte slice. + /// + /// Since the byte slice is not checked for valid WTF-8, this functions is + /// marked unsafe. + #[inline] + unsafe fn from_bytes_unchecked(value: &[u8]) -> &Wtf8 { + mem::transmute(value) } /// Returns the length, in WTF-8 bytes. @@ -682,7 +690,7 @@ fn decode_surrogate(second_byte: u8, third_byte: u8) -> u16 { #[inline] fn decode_surrogate_pair(lead: u16, trail: u16) -> char { let code_point = 0x10000 + ((((lead - 0xD800) as u32) << 10) | (trail - 0xDC00) as u32); - unsafe { mem::transmute(code_point) } + unsafe { char::from_u32_unchecked(code_point) } } /// Copied from core::str::StrPrelude::is_char_boundary @@ -699,7 +707,7 @@ pub fn is_code_point_boundary(slice: &Wtf8, index: usize) -> bool { #[inline] pub unsafe fn slice_unchecked(s: &Wtf8, begin: usize, end: usize) -> &Wtf8 { // memory layout of an &[u8] and &Wtf8 are the same - mem::transmute(slice::from_raw_parts( + Wtf8::from_bytes_unchecked(slice::from_raw_parts( s.bytes.as_ptr().offset(begin as isize), end - begin )) @@ -821,7 +829,6 @@ mod tests { use prelude::v1::*; use borrow::Cow; use super::*; - use mem::transmute; #[test] fn code_point_from_u32() { @@ -962,7 +969,7 @@ mod tests { string.push_wtf8(Wtf8::from_str(" 💩")); assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9"); - fn w(value: &[u8]) -> &Wtf8 { unsafe { transmute(value) } } + fn w(v: &[u8]) -> &Wtf8 { unsafe { Wtf8::from_bytes_unchecked(v) } } let mut string = Wtf8Buf::new(); string.push_wtf8(w(b"\xED\xA0\xBD")); // lead diff --git a/src/test/run-pass/infer-from-object-trait-issue-26952.rs b/src/test/run-pass/infer-from-object-trait-issue-26952.rs new file mode 100644 index 0000000000000..d5ca90c1a28c4 --- /dev/null +++ b/src/test/run-pass/infer-from-object-trait-issue-26952.rs @@ -0,0 +1,33 @@ +// Copyright 2012 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that when we match a trait reference like `Foo: Foo<_#0t>`, +// we unify with `_#0t` with `A`. In this code, if we failed to do +// that, then you get an unconstrained type-variable in `call`. +// +// Also serves as a regression test for issue #26952, though the test +// was derived from another reported regression with the same cause. + +use std::marker::PhantomData; + +trait Trait { fn foo(&self); } + +struct Type { a: PhantomData } + +fn as_trait(t: &Type) -> &Trait { loop { } } + +fn want+?Sized>(t: &T) { } + +fn call(p: Type) { + let q = as_trait(&p); + want(q); // parameter A to `want` *would* be unconstrained +} + +fn main() { }