middle::intrinsicck -> rustc_passes
This commit is contained in:
parent
82bfd8eb0d
commit
7c3f65b3c4
@ -3613,6 +3613,8 @@ dependencies = [
|
|||||||
"rustc",
|
"rustc",
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
"rustc_errors",
|
"rustc_errors",
|
||||||
|
"rustc_index",
|
||||||
|
"rustc_target",
|
||||||
"syntax",
|
"syntax",
|
||||||
"syntax_pos",
|
"syntax_pos",
|
||||||
]
|
]
|
||||||
|
@ -1566,33 +1566,6 @@ It is not possible to use stability attributes outside of the standard library.
|
|||||||
Also, for now, it is not possible to write deprecation messages either.
|
Also, for now, it is not possible to write deprecation messages either.
|
||||||
"##,
|
"##,
|
||||||
|
|
||||||
E0512: r##"
|
|
||||||
Transmute with two differently sized types was attempted. Erroneous code
|
|
||||||
example:
|
|
||||||
|
|
||||||
```compile_fail,E0512
|
|
||||||
fn takes_u8(_: u8) {}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
unsafe { takes_u8(::std::mem::transmute(0u16)); }
|
|
||||||
// error: cannot transmute between types of different sizes,
|
|
||||||
// or dependently-sized types
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Please use types with same size or use the expected type directly. Example:
|
|
||||||
|
|
||||||
```
|
|
||||||
fn takes_u8(_: u8) {}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
unsafe { takes_u8(::std::mem::transmute(0i8)); } // ok!
|
|
||||||
// or:
|
|
||||||
unsafe { takes_u8(0u8); } // ok!
|
|
||||||
}
|
|
||||||
```
|
|
||||||
"##,
|
|
||||||
|
|
||||||
E0517: r##"
|
E0517: r##"
|
||||||
This error indicates that a `#[repr(..)]` attribute was placed on an
|
This error indicates that a `#[repr(..)]` attribute was placed on an
|
||||||
unsupported item.
|
unsupported item.
|
||||||
@ -1787,84 +1760,6 @@ See [RFC 1522] for more details.
|
|||||||
[RFC 1522]: https://github.com/rust-lang/rfcs/blob/master/text/1522-conservative-impl-trait.md
|
[RFC 1522]: https://github.com/rust-lang/rfcs/blob/master/text/1522-conservative-impl-trait.md
|
||||||
"##,
|
"##,
|
||||||
|
|
||||||
E0591: r##"
|
|
||||||
Per [RFC 401][rfc401], if you have a function declaration `foo`:
|
|
||||||
|
|
||||||
```
|
|
||||||
// For the purposes of this explanation, all of these
|
|
||||||
// different kinds of `fn` declarations are equivalent:
|
|
||||||
struct S;
|
|
||||||
fn foo(x: S) { /* ... */ }
|
|
||||||
# #[cfg(for_demonstration_only)]
|
|
||||||
extern "C" { fn foo(x: S); }
|
|
||||||
# #[cfg(for_demonstration_only)]
|
|
||||||
impl S { fn foo(self) { /* ... */ } }
|
|
||||||
```
|
|
||||||
|
|
||||||
the type of `foo` is **not** `fn(S)`, as one might expect.
|
|
||||||
Rather, it is a unique, zero-sized marker type written here as `typeof(foo)`.
|
|
||||||
However, `typeof(foo)` can be _coerced_ to a function pointer `fn(S)`,
|
|
||||||
so you rarely notice this:
|
|
||||||
|
|
||||||
```
|
|
||||||
# struct S;
|
|
||||||
# fn foo(_: S) {}
|
|
||||||
let x: fn(S) = foo; // OK, coerces
|
|
||||||
```
|
|
||||||
|
|
||||||
The reason that this matter is that the type `fn(S)` is not specific to
|
|
||||||
any particular function: it's a function _pointer_. So calling `x()` results
|
|
||||||
in a virtual call, whereas `foo()` is statically dispatched, because the type
|
|
||||||
of `foo` tells us precisely what function is being called.
|
|
||||||
|
|
||||||
As noted above, coercions mean that most code doesn't have to be
|
|
||||||
concerned with this distinction. However, you can tell the difference
|
|
||||||
when using **transmute** to convert a fn item into a fn pointer.
|
|
||||||
|
|
||||||
This is sometimes done as part of an FFI:
|
|
||||||
|
|
||||||
```compile_fail,E0591
|
|
||||||
extern "C" fn foo(userdata: Box<i32>) {
|
|
||||||
/* ... */
|
|
||||||
}
|
|
||||||
|
|
||||||
# fn callback(_: extern "C" fn(*mut i32)) {}
|
|
||||||
# use std::mem::transmute;
|
|
||||||
# unsafe {
|
|
||||||
let f: extern "C" fn(*mut i32) = transmute(foo);
|
|
||||||
callback(f);
|
|
||||||
# }
|
|
||||||
```
|
|
||||||
|
|
||||||
Here, transmute is being used to convert the types of the fn arguments.
|
|
||||||
This pattern is incorrect because, because the type of `foo` is a function
|
|
||||||
**item** (`typeof(foo)`), which is zero-sized, and the target type (`fn()`)
|
|
||||||
is a function pointer, which is not zero-sized.
|
|
||||||
This pattern should be rewritten. There are a few possible ways to do this:
|
|
||||||
|
|
||||||
- change the original fn declaration to match the expected signature,
|
|
||||||
and do the cast in the fn body (the preferred option)
|
|
||||||
- cast the fn item fo a fn pointer before calling transmute, as shown here:
|
|
||||||
|
|
||||||
```
|
|
||||||
# extern "C" fn foo(_: Box<i32>) {}
|
|
||||||
# use std::mem::transmute;
|
|
||||||
# unsafe {
|
|
||||||
let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_));
|
|
||||||
let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too
|
|
||||||
# }
|
|
||||||
```
|
|
||||||
|
|
||||||
The same applies to transmutes to `*mut fn()`, which were observed in practice.
|
|
||||||
Note though that use of this type is generally incorrect.
|
|
||||||
The intention is typically to describe a function pointer, but just `fn()`
|
|
||||||
alone suffices for that. `*mut fn()` is a pointer to a fn pointer.
|
|
||||||
(Since these values are typically just passed to C code, however, this rarely
|
|
||||||
makes a difference in practice.)
|
|
||||||
|
|
||||||
[rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
|
|
||||||
"##,
|
|
||||||
|
|
||||||
E0593: r##"
|
E0593: r##"
|
||||||
You tried to supply an `Fn`-based type with an incorrect number of arguments
|
You tried to supply an `Fn`-based type with an incorrect number of arguments
|
||||||
than what was expected.
|
than what was expected.
|
||||||
|
@ -106,7 +106,6 @@ pub mod middle {
|
|||||||
pub mod diagnostic_items;
|
pub mod diagnostic_items;
|
||||||
pub mod exported_symbols;
|
pub mod exported_symbols;
|
||||||
pub mod free_region;
|
pub mod free_region;
|
||||||
pub mod intrinsicck;
|
|
||||||
pub mod lib_features;
|
pub mod lib_features;
|
||||||
pub mod lang_items;
|
pub mod lang_items;
|
||||||
pub mod mem_categorization;
|
pub mod mem_categorization;
|
||||||
|
@ -780,7 +780,6 @@ pub fn default_provide(providers: &mut ty::query::Providers<'_>) {
|
|||||||
ty::provide(providers);
|
ty::provide(providers);
|
||||||
traits::provide(providers);
|
traits::provide(providers);
|
||||||
stability::provide(providers);
|
stability::provide(providers);
|
||||||
middle::intrinsicck::provide(providers);
|
|
||||||
reachable::provide(providers);
|
reachable::provide(providers);
|
||||||
rustc_passes::provide(providers);
|
rustc_passes::provide(providers);
|
||||||
rustc_traits::provide(providers);
|
rustc_traits::provide(providers);
|
||||||
|
@ -15,3 +15,5 @@ rustc_data_structures = { path = "../librustc_data_structures" }
|
|||||||
syntax = { path = "../libsyntax" }
|
syntax = { path = "../libsyntax" }
|
||||||
syntax_pos = { path = "../libsyntax_pos" }
|
syntax_pos = { path = "../libsyntax_pos" }
|
||||||
errors = { path = "../librustc_errors", package = "rustc_errors" }
|
errors = { path = "../librustc_errors", package = "rustc_errors" }
|
||||||
|
rustc_target = { path = "../librustc_target" }
|
||||||
|
rustc_index = { path = "../librustc_index" }
|
||||||
|
@ -396,6 +396,111 @@ If you don't know the basics of Rust, you can go look to the Rust Book to get
|
|||||||
started: https://doc.rust-lang.org/book/
|
started: https://doc.rust-lang.org/book/
|
||||||
"##,
|
"##,
|
||||||
|
|
||||||
|
E0591: r##"
|
||||||
|
Per [RFC 401][rfc401], if you have a function declaration `foo`:
|
||||||
|
|
||||||
|
```
|
||||||
|
// For the purposes of this explanation, all of these
|
||||||
|
// different kinds of `fn` declarations are equivalent:
|
||||||
|
struct S;
|
||||||
|
fn foo(x: S) { /* ... */ }
|
||||||
|
# #[cfg(for_demonstration_only)]
|
||||||
|
extern "C" { fn foo(x: S); }
|
||||||
|
# #[cfg(for_demonstration_only)]
|
||||||
|
impl S { fn foo(self) { /* ... */ } }
|
||||||
|
```
|
||||||
|
|
||||||
|
the type of `foo` is **not** `fn(S)`, as one might expect.
|
||||||
|
Rather, it is a unique, zero-sized marker type written here as `typeof(foo)`.
|
||||||
|
However, `typeof(foo)` can be _coerced_ to a function pointer `fn(S)`,
|
||||||
|
so you rarely notice this:
|
||||||
|
|
||||||
|
```
|
||||||
|
# struct S;
|
||||||
|
# fn foo(_: S) {}
|
||||||
|
let x: fn(S) = foo; // OK, coerces
|
||||||
|
```
|
||||||
|
|
||||||
|
The reason that this matter is that the type `fn(S)` is not specific to
|
||||||
|
any particular function: it's a function _pointer_. So calling `x()` results
|
||||||
|
in a virtual call, whereas `foo()` is statically dispatched, because the type
|
||||||
|
of `foo` tells us precisely what function is being called.
|
||||||
|
|
||||||
|
As noted above, coercions mean that most code doesn't have to be
|
||||||
|
concerned with this distinction. However, you can tell the difference
|
||||||
|
when using **transmute** to convert a fn item into a fn pointer.
|
||||||
|
|
||||||
|
This is sometimes done as part of an FFI:
|
||||||
|
|
||||||
|
```compile_fail,E0591
|
||||||
|
extern "C" fn foo(userdata: Box<i32>) {
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
|
||||||
|
# fn callback(_: extern "C" fn(*mut i32)) {}
|
||||||
|
# use std::mem::transmute;
|
||||||
|
# unsafe {
|
||||||
|
let f: extern "C" fn(*mut i32) = transmute(foo);
|
||||||
|
callback(f);
|
||||||
|
# }
|
||||||
|
```
|
||||||
|
|
||||||
|
Here, transmute is being used to convert the types of the fn arguments.
|
||||||
|
This pattern is incorrect because, because the type of `foo` is a function
|
||||||
|
**item** (`typeof(foo)`), which is zero-sized, and the target type (`fn()`)
|
||||||
|
is a function pointer, which is not zero-sized.
|
||||||
|
This pattern should be rewritten. There are a few possible ways to do this:
|
||||||
|
|
||||||
|
- change the original fn declaration to match the expected signature,
|
||||||
|
and do the cast in the fn body (the preferred option)
|
||||||
|
- cast the fn item fo a fn pointer before calling transmute, as shown here:
|
||||||
|
|
||||||
|
```
|
||||||
|
# extern "C" fn foo(_: Box<i32>) {}
|
||||||
|
# use std::mem::transmute;
|
||||||
|
# unsafe {
|
||||||
|
let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_));
|
||||||
|
let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too
|
||||||
|
# }
|
||||||
|
```
|
||||||
|
|
||||||
|
The same applies to transmutes to `*mut fn()`, which were observed in practice.
|
||||||
|
Note though that use of this type is generally incorrect.
|
||||||
|
The intention is typically to describe a function pointer, but just `fn()`
|
||||||
|
alone suffices for that. `*mut fn()` is a pointer to a fn pointer.
|
||||||
|
(Since these values are typically just passed to C code, however, this rarely
|
||||||
|
makes a difference in practice.)
|
||||||
|
|
||||||
|
[rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
|
||||||
|
"##,
|
||||||
|
|
||||||
|
E0512: r##"
|
||||||
|
Transmute with two differently sized types was attempted. Erroneous code
|
||||||
|
example:
|
||||||
|
|
||||||
|
```compile_fail,E0512
|
||||||
|
fn takes_u8(_: u8) {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
unsafe { takes_u8(::std::mem::transmute(0u16)); }
|
||||||
|
// error: cannot transmute between types of different sizes,
|
||||||
|
// or dependently-sized types
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Please use types with same size or use the expected type directly. Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
fn takes_u8(_: u8) {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
unsafe { takes_u8(::std::mem::transmute(0i8)); } // ok!
|
||||||
|
// or:
|
||||||
|
unsafe { takes_u8(0u8); } // ok!
|
||||||
|
}
|
||||||
|
```
|
||||||
|
"##,
|
||||||
|
|
||||||
;
|
;
|
||||||
E0226, // only a single explicit lifetime bound is permitted
|
E0226, // only a single explicit lifetime bound is permitted
|
||||||
E0472, // asm! is unsupported on this target
|
E0472, // asm! is unsupported on this target
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
use crate::hir::def::{Res, DefKind};
|
use rustc::hir::def::{Res, DefKind};
|
||||||
use crate::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use crate::ty::{self, Ty, TyCtxt};
|
use rustc::ty::{self, Ty, TyCtxt};
|
||||||
use crate::ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx};
|
use rustc::ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx};
|
||||||
use crate::ty::query::Providers;
|
use rustc::ty::query::Providers;
|
||||||
|
|
||||||
use rustc_target::spec::abi::Abi::RustIntrinsic;
|
use rustc_target::spec::abi::Abi::RustIntrinsic;
|
||||||
use rustc_index::vec::Idx;
|
use rustc_index::vec::Idx;
|
||||||
use syntax_pos::{Span, sym};
|
use syntax_pos::{Span, sym};
|
||||||
use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||||
use crate::hir;
|
use rustc::hir;
|
||||||
|
|
||||||
fn check_mod_intrinsics(tcx: TyCtxt<'_>, module_def_id: DefId) {
|
fn check_mod_intrinsics(tcx: TyCtxt<'_>, module_def_id: DefId) {
|
||||||
tcx.hir().visit_item_likes_in_module(
|
tcx.hir().visit_item_likes_in_module(
|
@ -29,9 +29,11 @@ pub mod loops;
|
|||||||
pub mod dead;
|
pub mod dead;
|
||||||
pub mod entry;
|
pub mod entry;
|
||||||
mod liveness;
|
mod liveness;
|
||||||
|
mod intrinsicck;
|
||||||
|
|
||||||
pub fn provide(providers: &mut Providers<'_>) {
|
pub fn provide(providers: &mut Providers<'_>) {
|
||||||
entry::provide(providers);
|
entry::provide(providers);
|
||||||
loops::provide(providers);
|
loops::provide(providers);
|
||||||
liveness::provide(providers);
|
liveness::provide(providers);
|
||||||
|
intrinsicck::provide(providers);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user