Auto merge of #67455 - Centril:rollup-mf0yc81, r=Centril
Rollup of 5 pull requests Successful merges: - #64588 (Add a raw "address of" operator) - #67031 (Update tokio crates to latest versions) - #67131 (Merge `TraitItem` & `ImplItem into `AssocItem`) - #67354 (Fix pointing at arg when cause is outside of call) - #67363 (Fix handling of wasm import modules and names) Failed merges: r? @ghost
This commit is contained in:
commit
01a46509a4
152
Cargo.lock
152
Cargo.lock
|
@ -724,16 +724,6 @@ dependencies = [
|
|||
"smallvec 0.6.10",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13"
|
||||
dependencies = [
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils 0.6.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.7.1"
|
||||
|
@ -755,7 +745,7 @@ dependencies = [
|
|||
"crossbeam-utils 0.6.5",
|
||||
"lazy_static 1.3.0",
|
||||
"memoffset",
|
||||
"scopeguard 1.0.0",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1407,7 +1397,7 @@ version = "0.5.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3753954f7bd71f0e671afb8b5a992d1724cf43b7f95a563cd4a0bde94659ca8"
|
||||
dependencies = [
|
||||
"scopeguard 1.0.0",
|
||||
"scopeguard",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
|
@ -1726,7 +1716,7 @@ dependencies = [
|
|||
"jsonrpc-server-utils",
|
||||
"log",
|
||||
"parity-tokio-ipc",
|
||||
"parking_lot 0.9.0",
|
||||
"parking_lot",
|
||||
"tokio-service",
|
||||
]
|
||||
|
||||
|
@ -1738,7 +1728,7 @@ checksum = "e2c08b444cc0ed70263798834343d0ac875e664257df8079160f23ac1ea79446"
|
|||
dependencies = [
|
||||
"jsonrpc-core",
|
||||
"log",
|
||||
"parking_lot 0.9.0",
|
||||
"parking_lot",
|
||||
"serde",
|
||||
]
|
||||
|
||||
|
@ -1850,23 +1840,13 @@ dependencies = [
|
|||
name = "linkchecker"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54"
|
||||
dependencies = [
|
||||
"owning_ref",
|
||||
"scopeguard 0.3.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc"
|
||||
dependencies = [
|
||||
"scopeguard 1.0.0",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2027,7 +2007,7 @@ checksum = "c420bbc064623934620b5ab2dc0cf96451b34163329e82f95e7fa1b7b99a6ac8"
|
|||
dependencies = [
|
||||
"byteorder",
|
||||
"memmap",
|
||||
"parking_lot 0.9.0",
|
||||
"parking_lot",
|
||||
"rustc-hash",
|
||||
]
|
||||
|
||||
|
@ -2320,15 +2300,6 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd20eec3dbe4376829cb7d80ae6ac45e0a766831dca50202ff2d40db46a8a024"
|
||||
|
||||
[[package]]
|
||||
name = "owning_ref"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
|
||||
dependencies = [
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "packed_simd"
|
||||
version = "0.3.1"
|
||||
|
@ -2377,40 +2348,17 @@ dependencies = [
|
|||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337"
|
||||
dependencies = [
|
||||
"lock_api 0.1.3",
|
||||
"parking_lot_core 0.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252"
|
||||
dependencies = [
|
||||
"lock_api 0.3.1",
|
||||
"parking_lot_core 0.6.2",
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
"rustc_version",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand 0.6.1",
|
||||
"rustc_version",
|
||||
"smallvec 0.6.10",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.6.2"
|
||||
|
@ -2879,7 +2827,7 @@ version = "1.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123"
|
||||
dependencies = [
|
||||
"crossbeam-deque 0.7.1",
|
||||
"crossbeam-deque",
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
@ -2890,7 +2838,7 @@ version = "1.6.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b"
|
||||
dependencies = [
|
||||
"crossbeam-deque 0.7.1",
|
||||
"crossbeam-deque",
|
||||
"crossbeam-queue",
|
||||
"crossbeam-utils 0.6.5",
|
||||
"lazy_static 1.3.0",
|
||||
|
@ -3155,7 +3103,7 @@ dependencies = [
|
|||
"log",
|
||||
"measureme",
|
||||
"num_cpus",
|
||||
"parking_lot 0.9.0",
|
||||
"parking_lot",
|
||||
"polonius-engine",
|
||||
"rustc-rayon",
|
||||
"rustc-rayon-core",
|
||||
|
@ -3205,7 +3153,7 @@ dependencies = [
|
|||
"jobserver",
|
||||
"lazy_static 1.3.0",
|
||||
"log",
|
||||
"parking_lot 0.9.0",
|
||||
"parking_lot",
|
||||
"rustc-ap-graphviz",
|
||||
"rustc-ap-rustc_index",
|
||||
"rustc-ap-serialize",
|
||||
|
@ -3360,7 +3308,7 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f32767f90d938f1b7199a174ef249ae1924f6e5bbdb9d112fea141e016f25b3a"
|
||||
dependencies = [
|
||||
"crossbeam-deque 0.7.1",
|
||||
"crossbeam-deque",
|
||||
"either",
|
||||
"rustc-rayon-core",
|
||||
]
|
||||
|
@ -3371,7 +3319,7 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea2427831f0053ea3ea73559c8eabd893133a51b251d142bacee53c62a288cb3"
|
||||
dependencies = [
|
||||
"crossbeam-deque 0.7.1",
|
||||
"crossbeam-deque",
|
||||
"crossbeam-queue",
|
||||
"crossbeam-utils 0.6.5",
|
||||
"lazy_static 1.3.0",
|
||||
|
@ -3515,7 +3463,7 @@ dependencies = [
|
|||
"lazy_static 1.3.0",
|
||||
"log",
|
||||
"measureme",
|
||||
"parking_lot 0.9.0",
|
||||
"parking_lot",
|
||||
"rustc-hash",
|
||||
"rustc-rayon",
|
||||
"rustc-rayon-core",
|
||||
|
@ -4054,12 +4002,6 @@ version = "0.1.9"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.0.0"
|
||||
|
@ -4655,9 +4597,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "0.1.14"
|
||||
version = "0.1.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4790d0be6f4ba6ae4f48190efa2ed7780c9e3567796abdb285003cf39840d9c5"
|
||||
checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures",
|
||||
|
@ -4669,6 +4611,7 @@ dependencies = [
|
|||
"tokio-fs",
|
||||
"tokio-io",
|
||||
"tokio-reactor",
|
||||
"tokio-sync",
|
||||
"tokio-tcp",
|
||||
"tokio-threadpool",
|
||||
"tokio-timer",
|
||||
|
@ -4700,9 +4643,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio-current-thread"
|
||||
version = "0.1.4"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6"
|
||||
checksum = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"tokio-executor",
|
||||
|
@ -4710,9 +4653,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio-executor"
|
||||
version = "0.1.6"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0"
|
||||
checksum = "ca6df436c42b0c3330a82d855d2ef017cd793090ad550a6bc2184f4b933532ab"
|
||||
dependencies = [
|
||||
"crossbeam-utils 0.6.5",
|
||||
"futures",
|
||||
|
@ -4720,9 +4663,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio-fs"
|
||||
version = "0.1.5"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e9cbbc8a3698b7ab652340f46633364f9eaa928ddaaee79d8b8f356dd79a09d"
|
||||
checksum = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"tokio-io",
|
||||
|
@ -4731,9 +4674,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio-io"
|
||||
version = "0.1.11"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b53aeb9d3f5ccf2ebb29e19788f96987fa1355f8fe45ea193928eaaaf3ae820f"
|
||||
checksum = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures",
|
||||
|
@ -4755,12 +4698,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio-process"
|
||||
version = "0.2.3"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88e1281e412013f1ff5787def044a9577a0bed059f451e835f1643201f8b777d"
|
||||
checksum = "afbd6ef1b8cc2bd2c2b580d882774d443ebb1c6ceefe35ba9ea4ab586c89dbe8"
|
||||
dependencies = [
|
||||
"crossbeam-queue",
|
||||
"futures",
|
||||
"lazy_static 1.3.0",
|
||||
"libc",
|
||||
"log",
|
||||
"mio",
|
||||
"mio-named-pipes",
|
||||
"tokio-io",
|
||||
|
@ -4771,9 +4717,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio-reactor"
|
||||
version = "0.1.8"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afbcdb0f0d2a1e4c440af82d7bbf0bf91a8a8c0575bcd20c05d15be7e9d3a02f"
|
||||
checksum = "6732fe6b53c8d11178dcb77ac6d9682af27fc6d4cb87789449152e5377377146"
|
||||
dependencies = [
|
||||
"crossbeam-utils 0.6.5",
|
||||
"futures",
|
||||
|
@ -4781,10 +4727,11 @@ dependencies = [
|
|||
"log",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"parking_lot 0.7.1",
|
||||
"parking_lot",
|
||||
"slab",
|
||||
"tokio-executor",
|
||||
"tokio-io",
|
||||
"tokio-sync",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4813,6 +4760,16 @@ dependencies = [
|
|||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-sync"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d06554cce1ae4a50f42fba8023918afa931413aded705b560e29600ccf7c6d76"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"futures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-tcp"
|
||||
version = "0.1.3"
|
||||
|
@ -4829,25 +4786,26 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio-threadpool"
|
||||
version = "0.1.10"
|
||||
version = "0.1.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17465013014410310f9f61fa10bf4724803c149ea1d51efece131c38efca93aa"
|
||||
checksum = "f0c32ffea4827978e9aa392d2f743d973c1dfa3730a2ed3f22ce1e6984da848c"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque 0.6.3",
|
||||
"crossbeam-deque",
|
||||
"crossbeam-queue",
|
||||
"crossbeam-utils 0.6.5",
|
||||
"futures",
|
||||
"lazy_static 1.3.0",
|
||||
"log",
|
||||
"num_cpus",
|
||||
"rand 0.6.1",
|
||||
"slab",
|
||||
"tokio-executor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-timer"
|
||||
version = "0.2.8"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f37f0111d76cc5da132fe9bc0590b9b9cfd079bc7e75ac3846278430a299ff8"
|
||||
checksum = "1739638e364e558128461fc1ad84d997702c8e31c2e6b18fb99842268199e827"
|
||||
dependencies = [
|
||||
"crossbeam-utils 0.6.5",
|
||||
"futures",
|
||||
|
@ -4857,9 +4815,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio-udp"
|
||||
version = "0.1.3"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92"
|
||||
checksum = "f02298505547f73e60f568359ef0d016d5acd6e830ab9bc7c4a5b3403440121b"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures",
|
||||
|
|
|
@ -477,11 +477,11 @@ impl<'a> LoweringContext<'a> {
|
|||
});
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, item: &'tcx TraitItem) {
|
||||
fn visit_trait_item(&mut self, item: &'tcx AssocItem) {
|
||||
self.lctx.allocate_hir_id_counter(item.id);
|
||||
|
||||
match item.kind {
|
||||
TraitItemKind::Method(_, None) => {
|
||||
AssocItemKind::Fn(_, None) => {
|
||||
// Ignore patterns in trait methods without bodies
|
||||
self.with_hir_id_owner(None, |this| {
|
||||
visit::walk_trait_item(this, item)
|
||||
|
@ -493,7 +493,7 @@ impl<'a> LoweringContext<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, item: &'tcx ImplItem) {
|
||||
fn visit_impl_item(&mut self, item: &'tcx AssocItem) {
|
||||
self.lctx.allocate_hir_id_counter(item.id);
|
||||
self.with_hir_id_owner(Some(item.id), |this| {
|
||||
visit::walk_impl_item(this, item);
|
||||
|
@ -1211,7 +1211,7 @@ impl<'a> LoweringContext<'a> {
|
|||
let ct = self.with_new_scopes(|this| {
|
||||
hir::AnonConst {
|
||||
hir_id: this.lower_node_id(node_id),
|
||||
body: this.lower_const_body(&path_expr),
|
||||
body: this.lower_const_body(path_expr.span, Some(&path_expr)),
|
||||
}
|
||||
});
|
||||
return GenericArg::Const(ConstArg {
|
||||
|
@ -1253,6 +1253,14 @@ impl<'a> LoweringContext<'a> {
|
|||
ty
|
||||
}
|
||||
|
||||
fn ty(&mut self, span: Span, kind: hir::TyKind) -> hir::Ty {
|
||||
hir::Ty { hir_id: self.next_id(), kind, span }
|
||||
}
|
||||
|
||||
fn ty_tup(&mut self, span: Span, tys: HirVec<hir::Ty>) -> hir::Ty {
|
||||
self.ty(span, hir::TyKind::Tup(tys))
|
||||
}
|
||||
|
||||
fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::Ty {
|
||||
let kind = match t.kind {
|
||||
TyKind::Infer => hir::TyKind::Infer,
|
||||
|
@ -1418,7 +1426,13 @@ impl<'a> LoweringContext<'a> {
|
|||
}
|
||||
}
|
||||
TyKind::Mac(_) => bug!("`TyKind::Mac` should have been expanded by now"),
|
||||
TyKind::CVarArgs => bug!("`TyKind::CVarArgs` should have been handled elsewhere"),
|
||||
TyKind::CVarArgs => {
|
||||
self.sess.delay_span_bug(
|
||||
t.span,
|
||||
"`TyKind::CVarArgs` should have been handled elsewhere",
|
||||
);
|
||||
hir::TyKind::Err
|
||||
}
|
||||
};
|
||||
|
||||
hir::Ty {
|
||||
|
@ -2084,32 +2098,19 @@ impl<'a> LoweringContext<'a> {
|
|||
.iter()
|
||||
.map(|ty| this.lower_ty_direct(ty, ImplTraitContext::disallowed()))
|
||||
.collect();
|
||||
let mk_tup = |this: &mut Self, tys, span| {
|
||||
hir::Ty { kind: hir::TyKind::Tup(tys), hir_id: this.next_id(), span }
|
||||
let output_ty = match output {
|
||||
FunctionRetTy::Ty(ty) => this.lower_ty(&ty, ImplTraitContext::disallowed()),
|
||||
FunctionRetTy::Default(_) => P(this.ty_tup(span, hir::HirVec::new())),
|
||||
};
|
||||
let args = hir_vec![GenericArg::Type(this.ty_tup(span, inputs))];
|
||||
let binding = hir::TypeBinding {
|
||||
hir_id: this.next_id(),
|
||||
ident: Ident::with_dummy_span(FN_OUTPUT_NAME),
|
||||
span: output_ty.span,
|
||||
kind: hir::TypeBindingKind::Equality { ty: output_ty },
|
||||
};
|
||||
(
|
||||
hir::GenericArgs {
|
||||
args: hir_vec![GenericArg::Type(mk_tup(this, inputs, span))],
|
||||
bindings: hir_vec![
|
||||
hir::TypeBinding {
|
||||
hir_id: this.next_id(),
|
||||
ident: Ident::with_dummy_span(FN_OUTPUT_NAME),
|
||||
kind: hir::TypeBindingKind::Equality {
|
||||
ty: output
|
||||
.as_ref()
|
||||
.map(|ty| this.lower_ty(
|
||||
&ty,
|
||||
ImplTraitContext::disallowed()
|
||||
))
|
||||
.unwrap_or_else(||
|
||||
P(mk_tup(this, hir::HirVec::new(), span))
|
||||
),
|
||||
},
|
||||
span: output.as_ref().map_or(span, |ty| ty.span),
|
||||
}
|
||||
],
|
||||
parenthesized: true,
|
||||
},
|
||||
hir::GenericArgs { args, bindings: hir_vec![binding], parenthesized: true },
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
@ -2474,17 +2475,13 @@ impl<'a> LoweringContext<'a> {
|
|||
})
|
||||
);
|
||||
|
||||
// Create the `Foo<...>` refernece itself. Note that the `type
|
||||
// Create the `Foo<...>` reference itself. Note that the `type
|
||||
// Foo = impl Trait` is, internally, created as a child of the
|
||||
// async fn, so the *type parameters* are inherited. It's
|
||||
// only the lifetime parameters that we must supply.
|
||||
let opaque_ty_ref = hir::TyKind::Def(hir::ItemId { id: opaque_ty_id }, generic_args.into());
|
||||
|
||||
hir::FunctionRetTy::Return(P(hir::Ty {
|
||||
kind: opaque_ty_ref,
|
||||
span: opaque_ty_span,
|
||||
hir_id: self.next_id(),
|
||||
}))
|
||||
let opaque_ty = self.ty(opaque_ty_span, opaque_ty_ref);
|
||||
hir::FunctionRetTy::Return(P(opaque_ty))
|
||||
}
|
||||
|
||||
/// Transforms `-> T` into `Future<Output = T>`
|
||||
|
@ -2496,16 +2493,8 @@ impl<'a> LoweringContext<'a> {
|
|||
) -> hir::GenericBound {
|
||||
// Compute the `T` in `Future<Output = T>` from the return type.
|
||||
let output_ty = match output {
|
||||
FunctionRetTy::Ty(ty) => {
|
||||
self.lower_ty(ty, ImplTraitContext::OpaqueTy(Some(fn_def_id)))
|
||||
}
|
||||
FunctionRetTy::Default(ret_ty_span) => {
|
||||
P(hir::Ty {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::TyKind::Tup(hir_vec![]),
|
||||
span: *ret_ty_span,
|
||||
})
|
||||
}
|
||||
FunctionRetTy::Ty(ty) => self.lower_ty(ty, ImplTraitContext::OpaqueTy(Some(fn_def_id))),
|
||||
FunctionRetTy::Default(ret_ty_span) => P(self.ty_tup(*ret_ty_span, hir_vec![])),
|
||||
};
|
||||
|
||||
// "<Output = T>"
|
||||
|
@ -3017,7 +3006,7 @@ impl<'a> LoweringContext<'a> {
|
|||
self.with_new_scopes(|this| {
|
||||
hir::AnonConst {
|
||||
hir_id: this.lower_node_id(c.id),
|
||||
body: this.lower_const_body(&c.value),
|
||||
body: this.lower_const_body(c.value.span, Some(&c.value)),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> {
|
|||
}
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, item: &'tcx TraitItem) {
|
||||
fn visit_trait_item(&mut self, item: &'tcx AssocItem) {
|
||||
self.lctx.with_hir_id_owner(item.id, |lctx| {
|
||||
let hir_item = lctx.lower_trait_item(item);
|
||||
let id = hir::TraitItemId { hir_id: hir_item.hir_id };
|
||||
|
@ -97,7 +97,7 @@ impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> {
|
|||
visit::walk_trait_item(self, item);
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, item: &'tcx ImplItem) {
|
||||
fn visit_impl_item(&mut self, item: &'tcx AssocItem) {
|
||||
self.lctx.with_hir_id_owner(item.id, |lctx| {
|
||||
let hir_item = lctx.lower_impl_item(item);
|
||||
let id = hir::ImplItemId { hir_id: hir_item.hir_id };
|
||||
|
@ -250,7 +250,7 @@ impl LoweringContext<'_> {
|
|||
return None;
|
||||
}
|
||||
|
||||
let kind = self.lower_item_kind(i.id, &mut ident, &attrs, &mut vis, &i.kind);
|
||||
let kind = self.lower_item_kind(i.span, i.id, &mut ident, &attrs, &mut vis, &i.kind);
|
||||
|
||||
Some(hir::Item {
|
||||
hir_id: self.lower_node_id(i.id),
|
||||
|
@ -264,6 +264,7 @@ impl LoweringContext<'_> {
|
|||
|
||||
fn lower_item_kind(
|
||||
&mut self,
|
||||
span: Span,
|
||||
id: NodeId,
|
||||
ident: &mut Ident,
|
||||
attrs: &hir::HirVec<Attribute>,
|
||||
|
@ -292,7 +293,7 @@ impl LoweringContext<'_> {
|
|||
}
|
||||
),
|
||||
m,
|
||||
self.lower_const_body(e),
|
||||
self.lower_const_body(span, Some(e)),
|
||||
)
|
||||
}
|
||||
ItemKind::Const(ref t, ref e) => {
|
||||
|
@ -305,7 +306,7 @@ impl LoweringContext<'_> {
|
|||
ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
|
||||
}
|
||||
),
|
||||
self.lower_const_body(e)
|
||||
self.lower_const_body(span, Some(e))
|
||||
)
|
||||
}
|
||||
ItemKind::Fn(FnSig { ref decl, header }, ref generics, ref body) => {
|
||||
|
@ -317,7 +318,12 @@ impl LoweringContext<'_> {
|
|||
// `impl Future<Output = T>` here because lower_body
|
||||
// only cares about the input argument patterns in the function
|
||||
// declaration (decl), not the return types.
|
||||
let body_id = this.lower_maybe_async_body(&decl, header.asyncness.node, body);
|
||||
let body_id = this.lower_maybe_async_body(
|
||||
span,
|
||||
&decl,
|
||||
header.asyncness.node,
|
||||
Some(body),
|
||||
);
|
||||
|
||||
let (generics, decl) = this.add_in_band_defs(
|
||||
generics,
|
||||
|
@ -807,20 +813,20 @@ impl LoweringContext<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
|
||||
fn lower_trait_item(&mut self, i: &AssocItem) -> hir::TraitItem {
|
||||
let trait_item_def_id = self.resolver.definitions().local_def_id(i.id);
|
||||
|
||||
let (generics, kind) = match i.kind {
|
||||
TraitItemKind::Const(ref ty, ref default) => (
|
||||
AssocItemKind::Const(ref ty, ref default) => (
|
||||
self.lower_generics(&i.generics, ImplTraitContext::disallowed()),
|
||||
hir::TraitItemKind::Const(
|
||||
self.lower_ty(ty, ImplTraitContext::disallowed()),
|
||||
default
|
||||
.as_ref()
|
||||
.map(|x| self.lower_const_body(x)),
|
||||
.map(|x| self.lower_const_body(i.span, Some(x))),
|
||||
),
|
||||
),
|
||||
TraitItemKind::Method(ref sig, None) => {
|
||||
AssocItemKind::Fn(ref sig, None) => {
|
||||
let names = self.lower_fn_params_to_names(&sig.decl);
|
||||
let (generics, sig) = self.lower_method_sig(
|
||||
&i.generics,
|
||||
|
@ -831,8 +837,8 @@ impl LoweringContext<'_> {
|
|||
);
|
||||
(generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Required(names)))
|
||||
}
|
||||
TraitItemKind::Method(ref sig, Some(ref body)) => {
|
||||
let body_id = self.lower_fn_body_block(&sig.decl, body);
|
||||
AssocItemKind::Fn(ref sig, Some(ref body)) => {
|
||||
let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body));
|
||||
let (generics, sig) = self.lower_method_sig(
|
||||
&i.generics,
|
||||
sig,
|
||||
|
@ -842,7 +848,7 @@ impl LoweringContext<'_> {
|
|||
);
|
||||
(generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Provided(body_id)))
|
||||
}
|
||||
TraitItemKind::Type(ref bounds, ref default) => {
|
||||
AssocItemKind::TyAlias(ref bounds, ref default) => {
|
||||
let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed());
|
||||
let kind = hir::TraitItemKind::Type(
|
||||
self.lower_param_bounds(bounds, ImplTraitContext::disallowed()),
|
||||
|
@ -853,7 +859,7 @@ impl LoweringContext<'_> {
|
|||
|
||||
(generics, kind)
|
||||
},
|
||||
TraitItemKind::Macro(..) => bug!("macro item shouldn't exist at this point"),
|
||||
AssocItemKind::Macro(..) => bug!("macro item shouldn't exist at this point"),
|
||||
};
|
||||
|
||||
hir::TraitItem {
|
||||
|
@ -866,21 +872,21 @@ impl LoweringContext<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn lower_trait_item_ref(&mut self, i: &TraitItem) -> hir::TraitItemRef {
|
||||
fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
|
||||
let (kind, has_default) = match i.kind {
|
||||
TraitItemKind::Const(_, ref default) => {
|
||||
AssocItemKind::Const(_, ref default) => {
|
||||
(hir::AssocItemKind::Const, default.is_some())
|
||||
}
|
||||
TraitItemKind::Type(_, ref default) => {
|
||||
AssocItemKind::TyAlias(_, ref default) => {
|
||||
(hir::AssocItemKind::Type, default.is_some())
|
||||
}
|
||||
TraitItemKind::Method(ref sig, ref default) => (
|
||||
AssocItemKind::Fn(ref sig, ref default) => (
|
||||
hir::AssocItemKind::Method {
|
||||
has_self: sig.decl.has_self(),
|
||||
},
|
||||
default.is_some(),
|
||||
),
|
||||
TraitItemKind::Macro(..) => unimplemented!(),
|
||||
AssocItemKind::Macro(..) => unimplemented!(),
|
||||
};
|
||||
hir::TraitItemRef {
|
||||
id: hir::TraitItemId { hir_id: self.lower_node_id(i.id) },
|
||||
|
@ -891,21 +897,29 @@ impl LoweringContext<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
|
||||
/// Construct `ExprKind::Err` for the given `span`.
|
||||
fn expr_err(&mut self, span: Span) -> hir::Expr {
|
||||
self.expr(span, hir::ExprKind::Err, ThinVec::new())
|
||||
}
|
||||
|
||||
fn lower_impl_item(&mut self, i: &AssocItem) -> hir::ImplItem {
|
||||
let impl_item_def_id = self.resolver.definitions().local_def_id(i.id);
|
||||
|
||||
let (generics, kind) = match i.kind {
|
||||
ImplItemKind::Const(ref ty, ref expr) => (
|
||||
AssocItemKind::Const(ref ty, ref expr) => (
|
||||
self.lower_generics(&i.generics, ImplTraitContext::disallowed()),
|
||||
hir::ImplItemKind::Const(
|
||||
self.lower_ty(ty, ImplTraitContext::disallowed()),
|
||||
self.lower_const_body(expr),
|
||||
self.lower_const_body(i.span, expr.as_deref()),
|
||||
),
|
||||
),
|
||||
ImplItemKind::Method(ref sig, ref body) => {
|
||||
AssocItemKind::Fn(ref sig, ref body) => {
|
||||
self.current_item = Some(i.span);
|
||||
let body_id = self.lower_maybe_async_body(
|
||||
&sig.decl, sig.header.asyncness.node, body
|
||||
i.span,
|
||||
&sig.decl,
|
||||
sig.header.asyncness.node,
|
||||
body.as_deref(),
|
||||
);
|
||||
let impl_trait_return_allow = !self.is_in_trait_impl;
|
||||
let (generics, sig) = self.lower_method_sig(
|
||||
|
@ -918,21 +932,26 @@ impl LoweringContext<'_> {
|
|||
|
||||
(generics, hir::ImplItemKind::Method(sig, body_id))
|
||||
}
|
||||
ImplItemKind::TyAlias(ref ty) => {
|
||||
AssocItemKind::TyAlias(_, ref ty) => {
|
||||
let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed());
|
||||
let kind = match ty.kind.opaque_top_hack() {
|
||||
let kind = match ty {
|
||||
None => {
|
||||
let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
|
||||
hir::ImplItemKind::TyAlias(ty)
|
||||
hir::ImplItemKind::TyAlias(P(self.ty(i.span, hir::TyKind::Err)))
|
||||
}
|
||||
Some(bs) => {
|
||||
let bounds = self.lower_param_bounds(bs, ImplTraitContext::disallowed());
|
||||
hir::ImplItemKind::OpaqueTy(bounds)
|
||||
Some(ty) => match ty.kind.opaque_top_hack() {
|
||||
None => {
|
||||
let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
|
||||
hir::ImplItemKind::TyAlias(ty)
|
||||
}
|
||||
Some(bs) => {
|
||||
let bs = self.lower_param_bounds(bs, ImplTraitContext::disallowed());
|
||||
hir::ImplItemKind::OpaqueTy(bs)
|
||||
}
|
||||
}
|
||||
};
|
||||
(generics, kind)
|
||||
},
|
||||
ImplItemKind::Macro(..) => bug!("`TyMac` should have been expanded by now"),
|
||||
AssocItemKind::Macro(..) => bug!("`TyMac` should have been expanded by now"),
|
||||
};
|
||||
|
||||
hir::ImplItem {
|
||||
|
@ -949,7 +968,7 @@ impl LoweringContext<'_> {
|
|||
// [1] since `default impl` is not yet implemented, this is always true in impls
|
||||
}
|
||||
|
||||
fn lower_impl_item_ref(&mut self, i: &ImplItem) -> hir::ImplItemRef {
|
||||
fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
|
||||
hir::ImplItemRef {
|
||||
id: hir::ImplItemId { hir_id: self.lower_node_id(i.id) },
|
||||
ident: i.ident,
|
||||
|
@ -957,15 +976,18 @@ impl LoweringContext<'_> {
|
|||
vis: self.lower_visibility(&i.vis, Some(i.id)),
|
||||
defaultness: self.lower_defaultness(i.defaultness, true /* [1] */),
|
||||
kind: match &i.kind {
|
||||
ImplItemKind::Const(..) => hir::AssocItemKind::Const,
|
||||
ImplItemKind::TyAlias(ty) => match ty.kind.opaque_top_hack() {
|
||||
AssocItemKind::Const(..) => hir::AssocItemKind::Const,
|
||||
AssocItemKind::TyAlias(_, ty) => match ty
|
||||
.as_deref()
|
||||
.and_then(|ty| ty.kind.opaque_top_hack())
|
||||
{
|
||||
None => hir::AssocItemKind::Type,
|
||||
Some(_) => hir::AssocItemKind::OpaqueTy,
|
||||
},
|
||||
ImplItemKind::Method(sig, _) => hir::AssocItemKind::Method {
|
||||
AssocItemKind::Fn(sig, _) => hir::AssocItemKind::Method {
|
||||
has_self: sig.decl.has_self(),
|
||||
},
|
||||
ImplItemKind::Macro(..) => unimplemented!(),
|
||||
AssocItemKind::Macro(..) => unimplemented!(),
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -1063,23 +1085,39 @@ impl LoweringContext<'_> {
|
|||
))
|
||||
}
|
||||
|
||||
fn lower_fn_body_block(&mut self, decl: &FnDecl, body: &Block) -> hir::BodyId {
|
||||
self.lower_fn_body(decl, |this| this.lower_block_expr(body))
|
||||
fn lower_fn_body_block(
|
||||
&mut self,
|
||||
span: Span,
|
||||
decl: &FnDecl,
|
||||
body: Option<&Block>,
|
||||
) -> hir::BodyId {
|
||||
self.lower_fn_body(decl, |this| this.lower_block_expr_opt(span, body))
|
||||
}
|
||||
|
||||
pub(super) fn lower_const_body(&mut self, expr: &Expr) -> hir::BodyId {
|
||||
self.lower_body(|this| (hir_vec![], this.lower_expr(expr)))
|
||||
fn lower_block_expr_opt(&mut self, span: Span, block: Option<&Block>) -> hir::Expr {
|
||||
match block {
|
||||
Some(block) => self.lower_block_expr(block),
|
||||
None => self.expr_err(span),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn lower_const_body(&mut self, span: Span, expr: Option<&Expr>) -> hir::BodyId {
|
||||
self.lower_body(|this| (hir_vec![], match expr {
|
||||
Some(expr) => this.lower_expr(expr),
|
||||
None => this.expr_err(span),
|
||||
}))
|
||||
}
|
||||
|
||||
fn lower_maybe_async_body(
|
||||
&mut self,
|
||||
span: Span,
|
||||
decl: &FnDecl,
|
||||
asyncness: IsAsync,
|
||||
body: &Block,
|
||||
body: Option<&Block>,
|
||||
) -> hir::BodyId {
|
||||
let closure_id = match asyncness {
|
||||
IsAsync::Async { closure_id, .. } => closure_id,
|
||||
IsAsync::NotAsync => return self.lower_fn_body_block(decl, body),
|
||||
IsAsync::NotAsync => return self.lower_fn_body_block(span, decl, body),
|
||||
};
|
||||
|
||||
self.lower_body(|this| {
|
||||
|
@ -1213,15 +1251,16 @@ impl LoweringContext<'_> {
|
|||
parameters.push(new_parameter);
|
||||
}
|
||||
|
||||
let body_span = body.map_or(span, |b| b.span);
|
||||
let async_expr = this.make_async_expr(
|
||||
CaptureBy::Value,
|
||||
closure_id,
|
||||
None,
|
||||
body.span,
|
||||
body_span,
|
||||
hir::AsyncGeneratorKind::Fn,
|
||||
|this| {
|
||||
// Create a block from the user's function body:
|
||||
let user_body = this.lower_block_expr(body);
|
||||
let user_body = this.lower_block_expr_opt(body_span, body);
|
||||
|
||||
// Transform into `drop-temps { <user-body> }`, an expression:
|
||||
let desugared_span = this.mark_span_with_reason(
|
||||
|
@ -1251,7 +1290,7 @@ impl LoweringContext<'_> {
|
|||
);
|
||||
this.expr_block(P(body), ThinVec::new())
|
||||
});
|
||||
(HirVec::from(parameters), this.expr(body.span, async_expr, ThinVec::new()))
|
||||
(HirVec::from(parameters), this.expr(body_span, async_expr, ThinVec::new()))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1249,7 +1249,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
ast_visit::walk_poly_trait_ref(self, t, m);
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, trait_item: &'a ast::TraitItem) {
|
||||
fn visit_trait_item(&mut self, trait_item: &'a ast::AssocItem) {
|
||||
self.with_lint_attrs(trait_item.id, &trait_item.attrs, |cx| {
|
||||
run_early_pass!(cx, check_trait_item, trait_item);
|
||||
ast_visit::walk_trait_item(cx, trait_item);
|
||||
|
@ -1257,7 +1257,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
});
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, impl_item: &'a ast::ImplItem) {
|
||||
fn visit_impl_item(&mut self, impl_item: &'a ast::AssocItem) {
|
||||
self.with_lint_attrs(impl_item.id, &impl_item.attrs, |cx| {
|
||||
run_early_pass!(cx, check_impl_item, impl_item);
|
||||
ast_visit::walk_impl_item(cx, impl_item);
|
||||
|
|
|
@ -258,10 +258,10 @@ macro_rules! early_lint_methods {
|
|||
c: Span,
|
||||
d: ast::NodeId
|
||||
);
|
||||
fn check_trait_item(a: &ast::TraitItem);
|
||||
fn check_trait_item_post(a: &ast::TraitItem);
|
||||
fn check_impl_item(a: &ast::ImplItem);
|
||||
fn check_impl_item_post(a: &ast::ImplItem);
|
||||
fn check_trait_item(a: &ast::AssocItem);
|
||||
fn check_trait_item_post(a: &ast::AssocItem);
|
||||
fn check_impl_item(a: &ast::AssocItem);
|
||||
fn check_impl_item_post(a: &ast::AssocItem);
|
||||
fn check_struct_def(a: &ast::VariantData);
|
||||
fn check_struct_def_post(a: &ast::VariantData);
|
||||
fn check_struct_field(a: &ast::StructField);
|
||||
|
|
|
@ -2060,6 +2060,11 @@ pub enum Rvalue<'tcx> {
|
|||
/// &x or &mut x
|
||||
Ref(Region<'tcx>, BorrowKind, Place<'tcx>),
|
||||
|
||||
/// Create a raw pointer to the given place
|
||||
/// Can be generated by raw address of expressions (`&raw const x`),
|
||||
/// or when casting a reference to a raw pointer.
|
||||
AddressOf(Mutability, Place<'tcx>),
|
||||
|
||||
/// length of a [X] or [X;n] value
|
||||
Len(Place<'tcx>),
|
||||
|
||||
|
@ -2214,6 +2219,15 @@ impl<'tcx> Debug for Rvalue<'tcx> {
|
|||
write!(fmt, "&{}{}{:?}", region, kind_str, place)
|
||||
}
|
||||
|
||||
AddressOf(mutability, ref place) => {
|
||||
let kind_str = match mutability {
|
||||
Mutability::Mut => "mut",
|
||||
Mutability::Not => "const",
|
||||
};
|
||||
|
||||
write!(fmt, "&raw {} {:?}", kind_str, place)
|
||||
}
|
||||
|
||||
Aggregate(ref kind, ref places) => {
|
||||
fn fmt_tuple(fmt: &mut Formatter<'_>, places: &[Operand<'_>]) -> fmt::Result {
|
||||
let mut tuple_fmt = fmt.debug_tuple("");
|
||||
|
@ -3085,6 +3099,9 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
|
|||
Ref(region, bk, ref place) => {
|
||||
Ref(region.fold_with(folder), bk, place.fold_with(folder))
|
||||
}
|
||||
AddressOf(mutability, ref place) => {
|
||||
AddressOf(mutability, place.fold_with(folder))
|
||||
}
|
||||
Len(ref place) => Len(place.fold_with(folder)),
|
||||
Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)),
|
||||
BinaryOp(op, ref rhs, ref lhs) => {
|
||||
|
@ -3125,6 +3142,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
|
|||
Use(ref op) => op.visit_with(visitor),
|
||||
Repeat(ref op, _) => op.visit_with(visitor),
|
||||
Ref(region, _, ref place) => region.visit_with(visitor) || place.visit_with(visitor),
|
||||
AddressOf(_, ref place) => place.visit_with(visitor),
|
||||
Len(ref place) => place.visit_with(visitor),
|
||||
Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor),
|
||||
BinaryOp(_, ref rhs, ref lhs) | CheckedBinaryOp(_, ref rhs, ref lhs) => {
|
||||
|
|
|
@ -172,6 +172,13 @@ impl<'tcx> Rvalue<'tcx> {
|
|||
}
|
||||
)
|
||||
}
|
||||
Rvalue::AddressOf(mutability, ref place) => {
|
||||
let place_ty = place.ty(local_decls, tcx).ty;
|
||||
tcx.mk_ptr(ty::TypeAndMut {
|
||||
ty: place_ty,
|
||||
mutbl: mutability.into(),
|
||||
})
|
||||
}
|
||||
Rvalue::Len(..) => tcx.types.usize,
|
||||
Rvalue::Cast(.., ty) => ty,
|
||||
Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
|
||||
|
|
|
@ -570,6 +570,18 @@ macro_rules! make_mir_visitor {
|
|||
self.visit_place(path, ctx, location);
|
||||
}
|
||||
|
||||
Rvalue::AddressOf(m, path) => {
|
||||
let ctx = match m {
|
||||
Mutability::Mut => PlaceContext::MutatingUse(
|
||||
MutatingUseContext::AddressOf
|
||||
),
|
||||
Mutability::Not => PlaceContext::NonMutatingUse(
|
||||
NonMutatingUseContext::AddressOf
|
||||
),
|
||||
};
|
||||
self.visit_place(path, ctx, location);
|
||||
}
|
||||
|
||||
Rvalue::Len(path) => {
|
||||
self.visit_place(
|
||||
path,
|
||||
|
@ -1031,6 +1043,8 @@ pub enum NonMutatingUseContext {
|
|||
ShallowBorrow,
|
||||
/// Unique borrow.
|
||||
UniqueBorrow,
|
||||
/// AddressOf for *const pointer.
|
||||
AddressOf,
|
||||
/// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place.
|
||||
/// For example, the projection `x.y` is not marked as a mutation in these cases:
|
||||
///
|
||||
|
@ -1054,6 +1068,8 @@ pub enum MutatingUseContext {
|
|||
Drop,
|
||||
/// Mutable borrow.
|
||||
Borrow,
|
||||
/// AddressOf for *mut pointer.
|
||||
AddressOf,
|
||||
/// Used as base for another place, e.g., `x` in `x.y`. Could potentially mutate the place.
|
||||
/// For example, the projection `x.y` is marked as a mutation in these cases:
|
||||
///
|
||||
|
|
|
@ -28,8 +28,6 @@ pub enum CastTy<'tcx> {
|
|||
FnPtr,
|
||||
/// Raw pointers
|
||||
Ptr(ty::TypeAndMut<'tcx>),
|
||||
/// References
|
||||
RPtr(ty::TypeAndMut<'tcx>),
|
||||
}
|
||||
|
||||
/// Cast Kind. See RFC 401 (or librustc_typeck/check/cast.rs)
|
||||
|
@ -63,7 +61,6 @@ impl<'tcx> CastTy<'tcx> {
|
|||
ty::Adt(d,_) if d.is_enum() && d.is_payloadfree() =>
|
||||
Some(CastTy::Int(IntTy::CEnum)),
|
||||
ty::RawPtr(mt) => Some(CastTy::Ptr(mt)),
|
||||
ty::Ref(_, ty, mutbl) => Some(CastTy::RPtr(ty::TypeAndMut { ty, mutbl })),
|
||||
ty::FnPtr(..) => Some(CastTy::FnPtr),
|
||||
_ => None,
|
||||
}
|
||||
|
|
|
@ -344,6 +344,17 @@ pub fn from_fn_attrs(
|
|||
const_cstr!("wasm-import-module"),
|
||||
&module,
|
||||
);
|
||||
|
||||
let name = codegen_fn_attrs.link_name.unwrap_or_else(|| {
|
||||
cx.tcx.item_name(instance.def_id())
|
||||
});
|
||||
let name = CString::new(&name.as_str()[..]).unwrap();
|
||||
llvm::AddFunctionAttrStringValue(
|
||||
llfn,
|
||||
llvm::AttributePlace::Function,
|
||||
const_cstr!("wasm-import-name"),
|
||||
&name,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -340,10 +340,12 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
|
|||
PlaceContext::MutatingUse(MutatingUseContext::Store) |
|
||||
PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) |
|
||||
PlaceContext::MutatingUse(MutatingUseContext::Borrow) |
|
||||
PlaceContext::MutatingUse(MutatingUseContext::AddressOf) |
|
||||
PlaceContext::MutatingUse(MutatingUseContext::Projection) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) => {
|
||||
self.not_ssa(local);
|
||||
}
|
||||
|
|
|
@ -448,7 +448,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let cx = self.cx;
|
||||
let tcx = self.cx.tcx();
|
||||
|
||||
let result = match &place_ref {
|
||||
let result = match place_ref {
|
||||
mir::PlaceRef {
|
||||
base: mir::PlaceBase::Local(index),
|
||||
projection: [],
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::MemFlags;
|
|||
use crate::common::{self, RealPredicate, IntPredicate};
|
||||
use crate::traits::*;
|
||||
|
||||
use rustc::ty::{self, Ty, adjustment::{PointerCast}, Instance};
|
||||
use rustc::ty::{self, Ty, TyCtxt, adjustment::{PointerCast}, Instance};
|
||||
use rustc::ty::cast::{CastTy, IntTy};
|
||||
use rustc::ty::layout::{self, LayoutOf, HasTyCtxt};
|
||||
use rustc::mir;
|
||||
|
@ -349,8 +349,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
}
|
||||
(CastTy::Ptr(_), CastTy::Ptr(_)) |
|
||||
(CastTy::FnPtr, CastTy::Ptr(_)) |
|
||||
(CastTy::RPtr(_), CastTy::Ptr(_)) =>
|
||||
(CastTy::FnPtr, CastTy::Ptr(_)) =>
|
||||
bx.pointercast(llval, ll_t_out),
|
||||
(CastTy::Ptr(_), CastTy::Int(_)) |
|
||||
(CastTy::FnPtr, CastTy::Int(_)) =>
|
||||
|
@ -375,24 +374,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
|
||||
mir::Rvalue::Ref(_, bk, ref place) => {
|
||||
let cg_place = self.codegen_place(&mut bx, &place.as_ref());
|
||||
let mk_ref = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| tcx.mk_ref(
|
||||
tcx.lifetimes.re_erased,
|
||||
ty::TypeAndMut { ty, mutbl: bk.to_mutbl_lossy() }
|
||||
);
|
||||
self.codegen_place_to_pointer(bx, place, mk_ref)
|
||||
}
|
||||
|
||||
let ty = cg_place.layout.ty;
|
||||
|
||||
// Note: places are indirect, so storing the `llval` into the
|
||||
// destination effectively creates a reference.
|
||||
let val = if !bx.cx().type_has_metadata(ty) {
|
||||
OperandValue::Immediate(cg_place.llval)
|
||||
} else {
|
||||
OperandValue::Pair(cg_place.llval, cg_place.llextra.unwrap())
|
||||
};
|
||||
(bx, OperandRef {
|
||||
val,
|
||||
layout: self.cx.layout_of(self.cx.tcx().mk_ref(
|
||||
self.cx.tcx().lifetimes.re_erased,
|
||||
ty::TypeAndMut { ty, mutbl: bk.to_mutbl_lossy() }
|
||||
)),
|
||||
})
|
||||
mir::Rvalue::AddressOf(mutability, ref place) => {
|
||||
let mk_ptr = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| tcx.mk_ptr(
|
||||
ty::TypeAndMut { ty, mutbl: mutability.into() }
|
||||
);
|
||||
self.codegen_place_to_pointer(bx, place, mk_ptr)
|
||||
}
|
||||
|
||||
mir::Rvalue::Len(ref place) => {
|
||||
|
@ -548,6 +541,30 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
cg_value.len(bx.cx())
|
||||
}
|
||||
|
||||
/// Codegen an `Rvalue::AddressOf` or `Rvalue::Ref`
|
||||
fn codegen_place_to_pointer(
|
||||
&mut self,
|
||||
mut bx: Bx,
|
||||
place: &mir::Place<'tcx>,
|
||||
mk_ptr_ty: impl FnOnce(TyCtxt<'tcx>, Ty<'tcx>) -> Ty<'tcx>,
|
||||
) -> (Bx, OperandRef<'tcx, Bx::Value>) {
|
||||
let cg_place = self.codegen_place(&mut bx, &place.as_ref());
|
||||
|
||||
let ty = cg_place.layout.ty;
|
||||
|
||||
// Note: places are indirect, so storing the `llval` into the
|
||||
// destination effectively creates a reference.
|
||||
let val = if !bx.cx().type_has_metadata(ty) {
|
||||
OperandValue::Immediate(cg_place.llval)
|
||||
} else {
|
||||
OperandValue::Pair(cg_place.llval, cg_place.llextra.unwrap())
|
||||
};
|
||||
(bx, OperandRef {
|
||||
val,
|
||||
layout: self.cx.layout_of(mk_ptr_ty(self.cx.tcx(), ty)),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn codegen_scalar_binop(
|
||||
&mut self,
|
||||
bx: &mut Bx,
|
||||
|
@ -704,6 +721,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
pub fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>, span: Span) -> bool {
|
||||
match *rvalue {
|
||||
mir::Rvalue::Ref(..) |
|
||||
mir::Rvalue::AddressOf(..) |
|
||||
mir::Rvalue::Len(..) |
|
||||
mir::Rvalue::Cast(..) | // (*)
|
||||
mir::Rvalue::BinaryOp(..) |
|
||||
|
|
|
@ -142,12 +142,32 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol {
|
|||
};
|
||||
|
||||
let attrs = tcx.codegen_fn_attrs(def_id);
|
||||
|
||||
// Foreign items by default use no mangling for their symbol name. There's a
|
||||
// few exceptions to this rule though:
|
||||
//
|
||||
// * This can be overridden with the `#[link_name]` attribute
|
||||
//
|
||||
// * On the wasm32 targets there is a bug (or feature) in LLD [1] where the
|
||||
// same-named symbol when imported from different wasm modules will get
|
||||
// hooked up incorectly. As a result foreign symbols, on the wasm target,
|
||||
// with a wasm import module, get mangled. Additionally our codegen will
|
||||
// deduplicate symbols based purely on the symbol name, but for wasm this
|
||||
// isn't quite right because the same-named symbol on wasm can come from
|
||||
// different modules. For these reasons if `#[link(wasm_import_module)]`
|
||||
// is present we mangle everything on wasm because the demangled form will
|
||||
// show up in the `wasm-import-name` custom attribute in LLVM IR.
|
||||
//
|
||||
// [1]: https://bugs.llvm.org/show_bug.cgi?id=44316
|
||||
if is_foreign {
|
||||
if let Some(name) = attrs.link_name {
|
||||
return name;
|
||||
if tcx.sess.target.target.arch != "wasm32" ||
|
||||
!tcx.wasm_import_module_map(def_id.krate).contains_key(&def_id)
|
||||
{
|
||||
if let Some(name) = attrs.link_name {
|
||||
return name;
|
||||
}
|
||||
return tcx.item_name(def_id);
|
||||
}
|
||||
// Don't mangle foreign items.
|
||||
return tcx.item_name(def_id);
|
||||
}
|
||||
|
||||
if let Some(name) = attrs.export_name {
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
C-variadic has been used on a non-foreign function.
|
||||
The C-variadic type `...` has been nested inside another type.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0743
|
||||
fn foo2(x: u8, ...) {} // error!
|
||||
#![feature(c_variadic)]
|
||||
|
||||
fn foo2(x: u8, y: &...) {} // error!
|
||||
```
|
||||
|
||||
Only foreign functions can use C-variadic (`...`). It is used to give an
|
||||
undefined number of parameters to a given function (like `printf` in C). The
|
||||
equivalent in Rust would be to use macros directly.
|
||||
Only foreign functions can use the C-variadic type (`...`).
|
||||
In such functions, `...` may only occur non-nested.
|
||||
That is, `y: &'a ...` is not allowed.
|
||||
|
||||
A C-variadic type is used to give an undefined number
|
||||
of parameters to a given function (like `printf` in C).
|
||||
The equivalent in Rust would be to use macros directly.
|
||||
|
|
|
@ -11,7 +11,7 @@ fn temp_address() {
|
|||
|
||||
To avoid the error, first bind the temporary to a named local variable.
|
||||
|
||||
```ignore (not yet implemented)
|
||||
```
|
||||
# #![feature(raw_ref_op)]
|
||||
fn temp_address() {
|
||||
let val = 2;
|
||||
|
|
|
@ -643,8 +643,8 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> {
|
|||
ret
|
||||
}
|
||||
|
||||
fn should_ignore_fn(ret_ty: &ast::FnDecl) -> bool {
|
||||
if let ast::FunctionRetTy::Ty(ref ty) = ret_ty.output {
|
||||
fn should_ignore_fn(ret_ty: &ast::FunctionRetTy) -> bool {
|
||||
if let ast::FunctionRetTy::Ty(ref ty) = ret_ty {
|
||||
fn involves_impl_trait(ty: &ast::Ty) -> bool {
|
||||
match ty.kind {
|
||||
ast::TyKind::ImplTrait(..) => true,
|
||||
|
@ -673,7 +673,7 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> {
|
|||
},
|
||||
Some(&ast::GenericArgs::Parenthesized(ref data)) => {
|
||||
any_involves_impl_trait(data.inputs.iter()) ||
|
||||
any_involves_impl_trait(data.output.iter())
|
||||
ReplaceBodyWithLoop::should_ignore_fn(&data.output)
|
||||
}
|
||||
}
|
||||
}),
|
||||
|
@ -693,7 +693,7 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> {
|
|||
|
||||
fn is_sig_const(sig: &ast::FnSig) -> bool {
|
||||
sig.header.constness.node == ast::Constness::Const ||
|
||||
ReplaceBodyWithLoop::should_ignore_fn(&sig.decl)
|
||||
ReplaceBodyWithLoop::should_ignore_fn(&sig.decl.output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -707,22 +707,17 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
|
|||
self.run(is_const, |s| noop_visit_item_kind(i, s))
|
||||
}
|
||||
|
||||
fn flat_map_trait_item(&mut self, i: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> {
|
||||
fn flat_map_trait_item(&mut self, i: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
|
||||
let is_const = match i.kind {
|
||||
ast::TraitItemKind::Const(..) => true,
|
||||
ast::TraitItemKind::Method(ref sig, _) => Self::is_sig_const(sig),
|
||||
ast::AssocItemKind::Const(..) => true,
|
||||
ast::AssocItemKind::Fn(ref sig, _) => Self::is_sig_const(sig),
|
||||
_ => false,
|
||||
};
|
||||
self.run(is_const, |s| noop_flat_map_trait_item(i, s))
|
||||
self.run(is_const, |s| noop_flat_map_assoc_item(i, s))
|
||||
}
|
||||
|
||||
fn flat_map_impl_item(&mut self, i: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> {
|
||||
let is_const = match i.kind {
|
||||
ast::ImplItemKind::Const(..) => true,
|
||||
ast::ImplItemKind::Method(ref sig, _) => Self::is_sig_const(sig),
|
||||
_ => false,
|
||||
};
|
||||
self.run(is_const, |s| noop_flat_map_impl_item(i, s))
|
||||
fn flat_map_impl_item(&mut self, i: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
|
||||
self.flat_map_trait_item(i)
|
||||
}
|
||||
|
||||
fn visit_anon_const(&mut self, c: &mut ast::AnonConst) {
|
||||
|
|
|
@ -268,8 +268,8 @@ impl EarlyLintPass for UnsafeCode {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_trait_item(&mut self, cx: &EarlyContext<'_>, item: &ast::TraitItem) {
|
||||
if let ast::TraitItemKind::Method(ref sig, None) = item.kind {
|
||||
fn check_trait_item(&mut self, cx: &EarlyContext<'_>, item: &ast::AssocItem) {
|
||||
if let ast::AssocItemKind::Fn(ref sig, None) = item.kind {
|
||||
if sig.header.unsafety == ast::Unsafety::Unsafe {
|
||||
self.report_unsafe(cx, item.span, "declaration of an `unsafe` method")
|
||||
}
|
||||
|
@ -615,9 +615,9 @@ declare_lint_pass!(
|
|||
);
|
||||
|
||||
impl EarlyLintPass for AnonymousParameters {
|
||||
fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::TraitItem) {
|
||||
fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) {
|
||||
match it.kind {
|
||||
ast::TraitItemKind::Method(ref sig, _) => {
|
||||
ast::AssocItemKind::Fn(ref sig, _) => {
|
||||
for arg in sig.decl.inputs.iter() {
|
||||
match arg.pat.kind {
|
||||
ast::PatKind::Ident(_, ident, None) => {
|
||||
|
|
|
@ -3,7 +3,7 @@ use rustc::mir::visit::Visitor;
|
|||
use rustc::mir::{BasicBlock, Location, Body, Place, ReadOnlyBodyAndCache, Rvalue};
|
||||
use rustc::mir::{Statement, StatementKind};
|
||||
use rustc::mir::TerminatorKind;
|
||||
use rustc::mir::{Operand, BorrowKind};
|
||||
use rustc::mir::{Operand, BorrowKind, Mutability};
|
||||
use rustc_data_structures::graph::dominators::Dominators;
|
||||
|
||||
use crate::dataflow::indexes::BorrowIndex;
|
||||
|
@ -337,6 +337,22 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
Rvalue::AddressOf(mutability, ref place) => {
|
||||
let access_kind = match mutability {
|
||||
Mutability::Mut => (Deep, Write(WriteKind::MutableBorrow(BorrowKind::Mut {
|
||||
allow_two_phase_borrow: false,
|
||||
}))),
|
||||
Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
|
||||
};
|
||||
|
||||
self.access_place(
|
||||
location,
|
||||
place,
|
||||
access_kind,
|
||||
LocalMutationIsAllowed::No,
|
||||
);
|
||||
}
|
||||
|
||||
Rvalue::Use(ref operand)
|
||||
| Rvalue::Repeat(ref operand, _)
|
||||
| Rvalue::UnaryOp(_ /*un_op*/, ref operand)
|
||||
|
|
|
@ -1233,6 +1233,31 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
Rvalue::AddressOf(mutability, ref place) => {
|
||||
let access_kind = match mutability {
|
||||
Mutability::Mut => (Deep, Write(WriteKind::MutableBorrow(BorrowKind::Mut {
|
||||
allow_two_phase_borrow: false,
|
||||
}))),
|
||||
Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
|
||||
};
|
||||
|
||||
self.access_place(
|
||||
location,
|
||||
(place, span),
|
||||
access_kind,
|
||||
LocalMutationIsAllowed::No,
|
||||
flow_state,
|
||||
);
|
||||
|
||||
self.check_if_path_or_subpath_is_moved(
|
||||
location,
|
||||
InitializationRequiringAction::Borrow,
|
||||
(place.as_ref(), span),
|
||||
flow_state,
|
||||
);
|
||||
}
|
||||
|
||||
Rvalue::Use(ref operand)
|
||||
| Rvalue::Repeat(ref operand, _)
|
||||
| Rvalue::UnaryOp(_ /*un_op*/, ref operand)
|
||||
|
|
|
@ -2273,41 +2273,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
let cast_ty_from = CastTy::from_ty(ty_from);
|
||||
let cast_ty_to = CastTy::from_ty(ty);
|
||||
match (cast_ty_from, cast_ty_to) {
|
||||
(Some(CastTy::RPtr(ref_tm)), Some(CastTy::Ptr(ptr_tm))) => {
|
||||
if let hir::Mutability::Mutable = ptr_tm.mutbl {
|
||||
if let Err(terr) = self.eq_types(
|
||||
ref_tm.ty,
|
||||
ptr_tm.ty,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Cast,
|
||||
) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
rvalue,
|
||||
"equating {:?} with {:?} yields {:?}",
|
||||
ref_tm.ty,
|
||||
ptr_tm.ty,
|
||||
terr
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if let Err(terr) = self.sub_types(
|
||||
ref_tm.ty,
|
||||
ptr_tm.ty,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Cast,
|
||||
) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
rvalue,
|
||||
"relating {:?} with {:?} yields {:?}",
|
||||
ref_tm.ty,
|
||||
ptr_tm.ty,
|
||||
terr
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
(None, _)
|
||||
| (_, None)
|
||||
| (_, Some(CastTy::FnPtr))
|
||||
|
@ -2320,7 +2285,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
ty_from,
|
||||
ty,
|
||||
),
|
||||
_ => (),
|
||||
(Some(CastTy::Int(_)), Some(CastTy::Int(_)))
|
||||
| (Some(CastTy::Float), Some(CastTy::Int(_)))
|
||||
| (Some(CastTy::Int(_)), Some(CastTy::Float))
|
||||
| (Some(CastTy::Float), Some(CastTy::Float))
|
||||
| (Some(CastTy::Ptr(_)), Some(CastTy::Int(_)))
|
||||
| (Some(CastTy::FnPtr), Some(CastTy::Int(_)))
|
||||
| (Some(CastTy::Int(_)), Some(CastTy::Ptr(_)))
|
||||
| (Some(CastTy::Ptr(_)), Some(CastTy::Ptr(_)))
|
||||
| (Some(CastTy::FnPtr), Some(CastTy::Ptr(_))) => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2371,7 +2344,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
Rvalue::Use(..)
|
||||
Rvalue::AddressOf(..)
|
||||
| Rvalue::Use(..)
|
||||
| Rvalue::Len(..)
|
||||
| Rvalue::BinaryOp(..)
|
||||
| Rvalue::CheckedBinaryOp(..)
|
||||
|
@ -2388,6 +2362,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
Rvalue::Use(_)
|
||||
| Rvalue::Repeat(..)
|
||||
| Rvalue::Ref(..)
|
||||
| Rvalue::AddressOf(..)
|
||||
| Rvalue::Len(..)
|
||||
| Rvalue::Cast(..)
|
||||
| Rvalue::BinaryOp(..)
|
||||
|
|
|
@ -276,6 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
| ExprKind::Pointer { .. }
|
||||
| ExprKind::Repeat { .. }
|
||||
| ExprKind::Borrow { .. }
|
||||
| ExprKind::AddressOf { .. }
|
||||
| ExprKind::Match { .. }
|
||||
| ExprKind::Loop { .. }
|
||||
| ExprKind::Block { .. }
|
||||
|
|
|
@ -276,6 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
| ExprKind::NeverToAny { .. }
|
||||
| ExprKind::Use { .. }
|
||||
| ExprKind::Borrow { .. }
|
||||
| ExprKind::AddressOf { .. }
|
||||
| ExprKind::Adt { .. }
|
||||
| ExprKind::Loop { .. }
|
||||
| ExprKind::LogicalOp { .. }
|
||||
|
|
|
@ -49,6 +49,7 @@ impl Category {
|
|||
| ExprKind::Use { .. }
|
||||
| ExprKind::Adt { .. }
|
||||
| ExprKind::Borrow { .. }
|
||||
| ExprKind::AddressOf { .. }
|
||||
| ExprKind::Call { .. } => Some(Category::Rvalue(RvalueFunc::Into)),
|
||||
|
||||
ExprKind::Array { .. }
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
use crate::build::expr::category::{Category, RvalueFunc};
|
||||
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
|
||||
use crate::hair::*;
|
||||
use rustc::hir;
|
||||
use rustc::mir::*;
|
||||
use rustc::ty::{self, CanonicalUserTypeAnnotation};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
|
@ -295,6 +296,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
this.cfg.push_assign(block, source_info, destination, borrow);
|
||||
block.unit()
|
||||
}
|
||||
ExprKind::AddressOf {
|
||||
mutability,
|
||||
arg,
|
||||
} => {
|
||||
let address_of = match mutability {
|
||||
hir::Mutability::Immutable => Rvalue::AddressOf(
|
||||
Mutability::Not,
|
||||
unpack!(block = this.as_read_only_place(block, arg)),
|
||||
),
|
||||
hir::Mutability::Mutable => Rvalue::AddressOf(
|
||||
Mutability::Mut,
|
||||
unpack!(block = this.as_place(block, arg)),
|
||||
),
|
||||
};
|
||||
this.cfg.push_assign(block, source_info, destination, address_of);
|
||||
block.unit()
|
||||
}
|
||||
ExprKind::Adt {
|
||||
adt_def,
|
||||
variant_index,
|
||||
|
|
|
@ -335,6 +335,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
Rvalue::Ref(..)
|
||||
| Rvalue::AddressOf(..)
|
||||
| Rvalue::Discriminant(..)
|
||||
| Rvalue::Len(..)
|
||||
| Rvalue::NullaryOp(NullOp::SizeOf, _)
|
||||
|
|
|
@ -137,8 +137,11 @@ fn apply_adjustment<'a, 'tcx>(
|
|||
arg: expr.to_ref(),
|
||||
}
|
||||
}
|
||||
Adjust::Borrow(AutoBorrow::RawPtr(mutbl)) => {
|
||||
raw_ref_shim(cx, expr.to_ref(), adjustment.target, mutbl, span, temp_lifetime)
|
||||
Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => {
|
||||
ExprKind::AddressOf {
|
||||
mutability,
|
||||
arg: expr.to_ref(),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -262,17 +265,11 @@ fn make_mirror_unadjusted<'a, 'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutbl, ref arg) => {
|
||||
cx.tcx.sess
|
||||
.struct_span_err(
|
||||
expr.span,
|
||||
"raw borrows are not yet implemented"
|
||||
)
|
||||
.note("for more information, see https://github.com/rust-lang/rust/issues/64490")
|
||||
.emit();
|
||||
|
||||
// Lower to an approximation to avoid further errors.
|
||||
raw_ref_shim(cx, arg.to_ref(), expr_ty, mutbl, expr.span, temp_lifetime)
|
||||
hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, ref arg) => {
|
||||
ExprKind::AddressOf {
|
||||
mutability,
|
||||
arg: arg.to_ref(),
|
||||
}
|
||||
}
|
||||
|
||||
hir::ExprKind::Block(ref blk, _) => ExprKind::Block { body: &blk },
|
||||
|
@ -1082,67 +1079,6 @@ fn convert_var(
|
|||
}
|
||||
|
||||
|
||||
/// Fake `&raw [mut|const] expr` using a borrow and a cast until `AddressOf`
|
||||
/// exists in MIR.
|
||||
fn raw_ref_shim<'tcx>(
|
||||
cx: &mut Cx<'_, 'tcx>,
|
||||
arg: ExprRef<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
mutbl: hir::Mutability,
|
||||
span: Span,
|
||||
temp_lifetime: Option<region::Scope>,
|
||||
) -> ExprKind<'tcx> {
|
||||
let arg_tm = if let ty::RawPtr(type_mutbl) = ty.kind {
|
||||
type_mutbl
|
||||
} else {
|
||||
bug!("raw_ref_shim called with non-raw pointer type");
|
||||
};
|
||||
// Convert this to a suitable `&foo` and
|
||||
// then an unsafe coercion.
|
||||
let borrow_expr = Expr {
|
||||
temp_lifetime,
|
||||
ty: cx.tcx.mk_ref(cx.tcx.lifetimes.re_erased, arg_tm),
|
||||
span,
|
||||
kind: ExprKind::Borrow {
|
||||
borrow_kind: mutbl.to_borrow_kind(),
|
||||
arg,
|
||||
},
|
||||
};
|
||||
let cast_expr = Expr {
|
||||
temp_lifetime,
|
||||
ty,
|
||||
span,
|
||||
kind: ExprKind::Cast { source: borrow_expr.to_ref() }
|
||||
};
|
||||
|
||||
// To ensure that both implicit and explicit coercions are
|
||||
// handled the same way, we insert an extra layer of indirection here.
|
||||
// For explicit casts (e.g., 'foo as *const T'), the source of the 'Use'
|
||||
// will be an ExprKind::Hair with the appropriate cast expression. Here,
|
||||
// we make our Use source the generated Cast from the original coercion.
|
||||
//
|
||||
// In both cases, this outer 'Use' ensures that the inner 'Cast' is handled by
|
||||
// as_operand, not by as_rvalue - causing the cast result to be stored in a temporary.
|
||||
// Ordinary, this is identical to using the cast directly as an rvalue. However, if the
|
||||
// source of the cast was previously borrowed as mutable, storing the cast in a
|
||||
// temporary gives the source a chance to expire before the cast is used. For
|
||||
// structs with a self-referential *mut ptr, this allows assignment to work as
|
||||
// expected.
|
||||
//
|
||||
// For example, consider the type 'struct Foo { field: *mut Foo }',
|
||||
// The method 'fn bar(&mut self) { self.field = self }'
|
||||
// triggers a coercion from '&mut self' to '*mut self'. In order
|
||||
// for the assignment to be valid, the implicit borrow
|
||||
// of 'self' involved in the coercion needs to end before the local
|
||||
// containing the '*mut T' is assigned to 'self.field' - otherwise,
|
||||
// we end up trying to assign to 'self.field' while we have another mutable borrow
|
||||
// active.
|
||||
//
|
||||
// We only need to worry about this kind of thing for coercions from refs to ptrs,
|
||||
// since they get rid of a borrow implicitly.
|
||||
ExprKind::Use { source: cast_expr.to_ref() }
|
||||
}
|
||||
|
||||
fn bin_op(op: hir::BinOpKind) -> BinOp {
|
||||
match op {
|
||||
hir::BinOpKind::Add => BinOp::Add,
|
||||
|
|
|
@ -212,6 +212,11 @@ pub enum ExprKind<'tcx> {
|
|||
borrow_kind: BorrowKind,
|
||||
arg: ExprRef<'tcx>,
|
||||
},
|
||||
/// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
|
||||
AddressOf {
|
||||
mutability: hir::Mutability,
|
||||
arg: ExprRef<'tcx>,
|
||||
},
|
||||
Break {
|
||||
label: region::Scope,
|
||||
value: Option<ExprRef<'tcx>>,
|
||||
|
|
|
@ -248,7 +248,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
)?;
|
||||
}
|
||||
|
||||
Ref(_, _, ref place) => {
|
||||
AddressOf(_, ref place) | Ref(_, _, ref place) => {
|
||||
let src = self.eval_place(place)?;
|
||||
let place = self.force_allocation(src)?;
|
||||
if place.layout.size.bytes() > 0 {
|
||||
|
|
|
@ -136,21 +136,9 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
|
|||
// iterate backwards using indices.
|
||||
for i in (0..block_data.statements.len()).rev() {
|
||||
let (retag_kind, place) = match block_data.statements[i].kind {
|
||||
// If we are casting *from* a reference, we may have to retag-as-raw.
|
||||
StatementKind::Assign(box(ref place, Rvalue::Cast(
|
||||
CastKind::Misc,
|
||||
ref src,
|
||||
dest_ty,
|
||||
))) => {
|
||||
let src_ty = src.ty(&*local_decls, tcx);
|
||||
if src_ty.is_region_ptr() {
|
||||
// The only `Misc` casts on references are those creating raw pointers.
|
||||
assert!(dest_ty.is_unsafe_ptr());
|
||||
(RetagKind::Raw, place.clone())
|
||||
} else {
|
||||
// Some other cast, no retag
|
||||
continue
|
||||
}
|
||||
// Retag-as-raw after escaping to a raw pointer.
|
||||
StatementKind::Assign(box (ref place, Rvalue::AddressOf(..))) => {
|
||||
(RetagKind::Raw, place.clone())
|
||||
}
|
||||
// Assignments of reference or ptr type are the ones where we may have
|
||||
// to update tags. This includes `x = &[mut] ...` and hence
|
||||
|
|
|
@ -224,6 +224,23 @@ impl NonConstOp for MutBorrow {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MutAddressOf;
|
||||
impl NonConstOp for MutAddressOf {
|
||||
fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
|
||||
Some(tcx.features().const_mut_refs)
|
||||
}
|
||||
|
||||
fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
|
||||
feature_err(
|
||||
&item.tcx.sess.parse_sess,
|
||||
sym::const_mut_refs,
|
||||
span,
|
||||
&format!("`&raw mut` is not allowed in {}s", item.const_kind())
|
||||
).emit();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MutDeref;
|
||||
impl NonConstOp for MutDeref {
|
||||
|
|
|
@ -151,17 +151,15 @@ pub trait Qualif {
|
|||
Self::in_operand(cx, per_local, lhs) || Self::in_operand(cx, per_local, rhs)
|
||||
}
|
||||
|
||||
Rvalue::Ref(_, _, ref place) => {
|
||||
Rvalue::Ref(_, _, ref place) | Rvalue::AddressOf(_, ref place) => {
|
||||
// Special-case reborrows to be more like a copy of the reference.
|
||||
if let &[ref proj_base @ .., elem] = place.projection.as_ref() {
|
||||
if ProjectionElem::Deref == elem {
|
||||
let base_ty = Place::ty_from(&place.base, proj_base, *cx.body, cx.tcx).ty;
|
||||
if let ty::Ref(..) = base_ty.kind {
|
||||
return Self::in_place(cx, per_local, PlaceRef {
|
||||
base: &place.base,
|
||||
projection: proj_base,
|
||||
});
|
||||
}
|
||||
if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() {
|
||||
let base_ty = Place::ty_from(&place.base, proj_base, *cx.body, cx.tcx).ty;
|
||||
if let ty::Ref(..) = base_ty.kind {
|
||||
return Self::in_place(cx, per_local, PlaceRef {
|
||||
base: &place.base,
|
||||
projection: proj_base,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -276,6 +276,27 @@ impl Validator<'a, 'mir, 'tcx> {
|
|||
self.check_op_spanned(ops::StaticAccess, span)
|
||||
}
|
||||
}
|
||||
|
||||
fn check_immutable_borrow_like(
|
||||
&mut self,
|
||||
location: Location,
|
||||
place: &Place<'tcx>,
|
||||
) {
|
||||
// FIXME: Change the `in_*` methods to take a `FnMut` so we don't have to manually
|
||||
// seek the cursors beforehand.
|
||||
self.qualifs.has_mut_interior.cursor.seek_before(location);
|
||||
self.qualifs.indirectly_mutable.seek(location);
|
||||
|
||||
let borrowed_place_has_mut_interior = HasMutInterior::in_place(
|
||||
&self.item,
|
||||
&|local| self.qualifs.has_mut_interior_eager_seek(local),
|
||||
place.as_ref(),
|
||||
);
|
||||
|
||||
if borrowed_place_has_mut_interior {
|
||||
self.check_op(ops::CellBorrow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
|
||||
|
@ -302,26 +323,44 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
|
|||
trace!("visit_rvalue: rvalue={:?} location={:?}", rvalue, location);
|
||||
|
||||
// Special-case reborrows to be more like a copy of a reference.
|
||||
if let Rvalue::Ref(_, kind, ref place) = *rvalue {
|
||||
if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, *self.body, place) {
|
||||
let ctx = match kind {
|
||||
BorrowKind::Shared => PlaceContext::NonMutatingUse(
|
||||
NonMutatingUseContext::SharedBorrow,
|
||||
),
|
||||
BorrowKind::Shallow => PlaceContext::NonMutatingUse(
|
||||
NonMutatingUseContext::ShallowBorrow,
|
||||
),
|
||||
BorrowKind::Unique => PlaceContext::NonMutatingUse(
|
||||
NonMutatingUseContext::UniqueBorrow,
|
||||
),
|
||||
BorrowKind::Mut { .. } => PlaceContext::MutatingUse(
|
||||
MutatingUseContext::Borrow,
|
||||
),
|
||||
};
|
||||
self.visit_place_base(&place.base, ctx, location);
|
||||
self.visit_projection(&place.base, reborrowed_proj, ctx, location);
|
||||
return;
|
||||
match *rvalue {
|
||||
Rvalue::Ref(_, kind, ref place) => {
|
||||
if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, *self.body, place) {
|
||||
let ctx = match kind {
|
||||
BorrowKind::Shared => PlaceContext::NonMutatingUse(
|
||||
NonMutatingUseContext::SharedBorrow,
|
||||
),
|
||||
BorrowKind::Shallow => PlaceContext::NonMutatingUse(
|
||||
NonMutatingUseContext::ShallowBorrow,
|
||||
),
|
||||
BorrowKind::Unique => PlaceContext::NonMutatingUse(
|
||||
NonMutatingUseContext::UniqueBorrow,
|
||||
),
|
||||
BorrowKind::Mut { .. } => PlaceContext::MutatingUse(
|
||||
MutatingUseContext::Borrow,
|
||||
),
|
||||
};
|
||||
self.visit_place_base(&place.base, ctx, location);
|
||||
self.visit_projection(&place.base, reborrowed_proj, ctx, location);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Rvalue::AddressOf(mutbl, ref place) => {
|
||||
if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, *self.body, place) {
|
||||
let ctx = match mutbl {
|
||||
Mutability::Not => PlaceContext::NonMutatingUse(
|
||||
NonMutatingUseContext::AddressOf,
|
||||
),
|
||||
Mutability::Mut => PlaceContext::MutatingUse(
|
||||
MutatingUseContext::AddressOf,
|
||||
),
|
||||
};
|
||||
self.visit_place_base(&place.base, ctx, location);
|
||||
self.visit_projection(&place.base, reborrowed_proj, ctx, location);
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.super_rvalue(rvalue, location);
|
||||
|
@ -367,34 +406,25 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
Rvalue::AddressOf(Mutability::Mut, _) => {
|
||||
self.check_op(ops::MutAddressOf)
|
||||
}
|
||||
|
||||
// At the moment, `PlaceBase::Static` is only used for promoted MIR.
|
||||
| Rvalue::Ref(_, BorrowKind::Shared, ref place)
|
||||
| Rvalue::Ref(_, BorrowKind::Shallow, ref place)
|
||||
| Rvalue::AddressOf(Mutability::Not, ref place)
|
||||
if matches!(place.base, PlaceBase::Static(_))
|
||||
=> bug!("Saw a promoted during const-checking, which must run before promotion"),
|
||||
|
||||
| Rvalue::Ref(_, kind @ BorrowKind::Shared, ref place)
|
||||
| Rvalue::Ref(_, kind @ BorrowKind::Shallow, ref place)
|
||||
=> {
|
||||
// FIXME: Change the `in_*` methods to take a `FnMut` so we don't have to manually
|
||||
// seek the cursors beforehand.
|
||||
self.qualifs.has_mut_interior.cursor.seek_before(location);
|
||||
self.qualifs.indirectly_mutable.seek(location);
|
||||
| Rvalue::Ref(_, BorrowKind::Shared, ref place)
|
||||
| Rvalue::Ref(_, BorrowKind::Shallow, ref place) => {
|
||||
self.check_immutable_borrow_like(location, place)
|
||||
},
|
||||
|
||||
let borrowed_place_has_mut_interior = HasMutInterior::in_place(
|
||||
&self.item,
|
||||
&|local| self.qualifs.has_mut_interior_eager_seek(local),
|
||||
place.as_ref(),
|
||||
);
|
||||
|
||||
if borrowed_place_has_mut_interior {
|
||||
if let BorrowKind::Mut{ .. } = kind {
|
||||
self.check_op(ops::MutBorrow);
|
||||
} else {
|
||||
self.check_op(ops::CellBorrow);
|
||||
}
|
||||
}
|
||||
}
|
||||
Rvalue::AddressOf(Mutability::Not, ref place) => {
|
||||
self.check_immutable_borrow_like(location, place)
|
||||
},
|
||||
|
||||
Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) => {
|
||||
let operand_ty = operand.ty(*self.body, self.tcx);
|
||||
|
|
|
@ -196,7 +196,12 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> {
|
|||
} else if let TempState::Defined { ref mut uses, .. } = *temp {
|
||||
// We always allow borrows, even mutable ones, as we need
|
||||
// to promote mutable borrows of some ZSTs e.g., `&mut []`.
|
||||
let allowed_use = context.is_borrow() || context.is_nonmutating_use();
|
||||
let allowed_use = match context {
|
||||
PlaceContext::MutatingUse(MutatingUseContext::Borrow)
|
||||
| PlaceContext::NonMutatingUse(_) => true,
|
||||
PlaceContext::MutatingUse(_)
|
||||
| PlaceContext::NonUse(_) => false,
|
||||
};
|
||||
debug!("visit_local: allowed_use={:?}", allowed_use);
|
||||
if allowed_use {
|
||||
*uses += 1;
|
||||
|
@ -618,6 +623,21 @@ impl<'tcx> Validator<'_, 'tcx> {
|
|||
self.validate_operand(rhs)
|
||||
}
|
||||
|
||||
Rvalue::AddressOf(_, place) => {
|
||||
// Raw reborrows can come from reference to pointer coercions,
|
||||
// so are allowed.
|
||||
if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() {
|
||||
let base_ty = Place::ty_from(&place.base, proj_base, *self.body, self.tcx).ty;
|
||||
if let ty::Ref(..) = base_ty.kind {
|
||||
return self.validate_place(PlaceRef {
|
||||
base: &place.base,
|
||||
projection: proj_base,
|
||||
});
|
||||
}
|
||||
}
|
||||
Err(Unpromotable)
|
||||
}
|
||||
|
||||
Rvalue::Ref(_, kind, place) => {
|
||||
if let BorrowKind::Mut { .. } = kind {
|
||||
let ty = place.ty(*self.body, self.tcx).ty;
|
||||
|
@ -950,7 +970,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
|||
Candidate::Ref(loc) => {
|
||||
let ref mut statement = blocks[loc.block].statements[loc.statement_index];
|
||||
match statement.kind {
|
||||
StatementKind::Assign(box(_, Rvalue::Ref(_, _, ref mut place))) => {
|
||||
StatementKind::Assign(box (_, Rvalue::Ref(_, _, ref mut place))) => {
|
||||
// Use the underlying local for this (necessarily interior) borrow.
|
||||
let ty = place.base.ty(local_decls).ty;
|
||||
let span = statement.source_info.span;
|
||||
|
|
|
@ -135,7 +135,10 @@ fn check_rvalue(
|
|||
Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => {
|
||||
check_operand(tcx, operand, span, def_id, body)
|
||||
}
|
||||
Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) => {
|
||||
Rvalue::Len(place)
|
||||
| Rvalue::Discriminant(place)
|
||||
| Rvalue::Ref(_, _, place)
|
||||
| Rvalue::AddressOf(_, place) => {
|
||||
check_place(tcx, place, span, def_id, body)
|
||||
}
|
||||
Rvalue::Cast(CastKind::Misc, operand, cast_ty) => {
|
||||
|
@ -147,9 +150,6 @@ fn check_rvalue(
|
|||
span,
|
||||
"casting pointers to ints is unstable in const fn".into(),
|
||||
)),
|
||||
(CastTy::RPtr(_), CastTy::Float) => bug!(),
|
||||
(CastTy::RPtr(_), CastTy::Int(_)) => bug!(),
|
||||
(CastTy::Ptr(_), CastTy::RPtr(_)) => bug!(),
|
||||
_ => check_operand(tcx, operand, span, def_id, body),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -557,10 +557,10 @@ where
|
|||
/// if can_go then succ else drop-block
|
||||
/// drop-block:
|
||||
/// if ptr_based {
|
||||
/// ptr = &mut *cur
|
||||
/// ptr = cur
|
||||
/// cur = cur.offset(1)
|
||||
/// } else {
|
||||
/// ptr = &mut P[cur]
|
||||
/// ptr = &raw mut P[cur]
|
||||
/// cur = cur + 1
|
||||
/// }
|
||||
/// drop(ptr)
|
||||
|
@ -574,34 +574,28 @@ where
|
|||
unwind: Unwind,
|
||||
ptr_based: bool,
|
||||
) -> BasicBlock {
|
||||
let copy = |place: &Place<'tcx>| Operand::Copy(place.clone());
|
||||
let move_ = |place: &Place<'tcx>| Operand::Move(place.clone());
|
||||
let copy = |place: Place<'tcx>| Operand::Copy(place);
|
||||
let move_ = |place: Place<'tcx>| Operand::Move(place);
|
||||
let tcx = self.tcx();
|
||||
|
||||
let ref_ty = tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut {
|
||||
let ptr_ty = tcx.mk_ptr(ty::TypeAndMut {
|
||||
ty: ety,
|
||||
mutbl: hir::Mutability::Mutable
|
||||
});
|
||||
let ptr = &Place::from(self.new_temp(ref_ty));
|
||||
let can_go = &Place::from(self.new_temp(tcx.types.bool));
|
||||
let ptr = &Place::from(self.new_temp(ptr_ty));
|
||||
let can_go = Place::from(self.new_temp(tcx.types.bool));
|
||||
|
||||
let one = self.constant_usize(1);
|
||||
let (ptr_next, cur_next) = if ptr_based {
|
||||
(Rvalue::Ref(
|
||||
tcx.lifetimes.re_erased,
|
||||
BorrowKind::Mut { allow_two_phase_borrow: false },
|
||||
Place {
|
||||
base: PlaceBase::Local(cur),
|
||||
projection: tcx.intern_place_elems(&vec![ProjectionElem::Deref]),
|
||||
}
|
||||
),
|
||||
Rvalue::BinaryOp(BinOp::Offset, move_(&Place::from(cur)), one))
|
||||
(
|
||||
Rvalue::Use(copy(cur.into())),
|
||||
Rvalue::BinaryOp(BinOp::Offset, move_(cur.into()), one),
|
||||
)
|
||||
} else {
|
||||
(Rvalue::Ref(
|
||||
tcx.lifetimes.re_erased,
|
||||
BorrowKind::Mut { allow_two_phase_borrow: false },
|
||||
tcx.mk_place_index(self.place.clone(), cur)),
|
||||
Rvalue::BinaryOp(BinOp::Add, move_(&Place::from(cur)), one))
|
||||
(
|
||||
Rvalue::AddressOf(Mutability::Mut, tcx.mk_place_index(self.place.clone(), cur)),
|
||||
Rvalue::BinaryOp(BinOp::Add, move_(cur.into()), one),
|
||||
)
|
||||
};
|
||||
|
||||
let drop_block = BasicBlockData {
|
||||
|
@ -620,9 +614,9 @@ where
|
|||
|
||||
let loop_block = BasicBlockData {
|
||||
statements: vec![
|
||||
self.assign(can_go, Rvalue::BinaryOp(BinOp::Eq,
|
||||
copy(&Place::from(cur)),
|
||||
copy(length_or_end)))
|
||||
self.assign(&can_go, Rvalue::BinaryOp(BinOp::Eq,
|
||||
copy(Place::from(cur)),
|
||||
copy(length_or_end.clone())))
|
||||
],
|
||||
is_cleanup: unwind.is_cleanup(),
|
||||
terminator: Some(Terminator {
|
||||
|
@ -725,8 +719,6 @@ where
|
|||
|
||||
let cur = self.new_temp(iter_ty);
|
||||
let length_or_end = if ptr_based {
|
||||
// FIXME check if we want to make it return a `Place` directly
|
||||
// if all use sites want a `Place::Base` anyway.
|
||||
Place::from(self.new_temp(iter_ty))
|
||||
} else {
|
||||
length.clone()
|
||||
|
@ -753,23 +745,16 @@ where
|
|||
let drop_block_stmts = if ptr_based {
|
||||
let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place));
|
||||
let tmp = Place::from(self.new_temp(tmp_ty));
|
||||
// tmp = &mut P;
|
||||
// tmp = &raw mut P;
|
||||
// cur = tmp as *mut T;
|
||||
// end = Offset(cur, len);
|
||||
vec![
|
||||
self.assign(&tmp, Rvalue::Ref(
|
||||
tcx.lifetimes.re_erased,
|
||||
BorrowKind::Mut { allow_two_phase_borrow: false },
|
||||
self.place.clone()
|
||||
)),
|
||||
self.assign(
|
||||
&cur,
|
||||
Rvalue::Cast(CastKind::Misc, Operand::Move(tmp), iter_ty),
|
||||
),
|
||||
self.assign(&tmp, Rvalue::AddressOf(Mutability::Mut, self.place.clone())),
|
||||
self.assign(&cur, Rvalue::Cast(CastKind::Misc, Operand::Move(tmp), iter_ty)),
|
||||
self.assign(
|
||||
&length_or_end,
|
||||
Rvalue::BinaryOp(BinOp::Offset, Operand::Copy(cur), Operand::Move(length)
|
||||
)),
|
||||
Rvalue::BinaryOp(BinOp::Offset, Operand::Copy(cur), Operand::Move(length)),
|
||||
),
|
||||
]
|
||||
} else {
|
||||
// cur = 0 (length already pushed)
|
||||
|
|
|
@ -167,6 +167,8 @@ pub fn categorize(context: PlaceContext) -> Option<DefUse> {
|
|||
PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow) |
|
||||
|
||||
PlaceContext::MutatingUse(MutatingUseContext::AddressOf) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) |
|
||||
|
|
|
@ -344,12 +344,12 @@ impl<'a> MutVisitor for StripUnconfigured<'a> {
|
|||
noop_flat_map_item(configure!(self, item), self)
|
||||
}
|
||||
|
||||
fn flat_map_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> {
|
||||
noop_flat_map_impl_item(configure!(self, item), self)
|
||||
fn flat_map_impl_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
|
||||
noop_flat_map_assoc_item(configure!(self, item), self)
|
||||
}
|
||||
|
||||
fn flat_map_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> {
|
||||
noop_flat_map_trait_item(configure!(self, item), self)
|
||||
fn flat_map_trait_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
|
||||
noop_flat_map_assoc_item(configure!(self, item), self)
|
||||
}
|
||||
|
||||
fn visit_mac(&mut self, _mac: &mut ast::Mac) {
|
||||
|
|
|
@ -305,10 +305,7 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
|
|||
Nonterminal::NtItem(ref item) => {
|
||||
prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span)
|
||||
}
|
||||
Nonterminal::NtTraitItem(ref item) => {
|
||||
prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span)
|
||||
}
|
||||
Nonterminal::NtImplItem(ref item) => {
|
||||
Nonterminal::NtTraitItem(ref item) | Nonterminal::NtImplItem(ref item) => {
|
||||
prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span)
|
||||
}
|
||||
Nonterminal::NtIdent(ident, is_raw) => {
|
||||
|
|
|
@ -1381,7 +1381,7 @@ impl<'a> Parser<'a> {
|
|||
args
|
||||
}
|
||||
};
|
||||
let output = self.parse_ret_ty(true)?;
|
||||
let output = self.parse_ret_ty(true, true)?;
|
||||
|
||||
Ok(P(FnDecl {
|
||||
inputs: inputs_captures,
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::maybe_whole;
|
|||
use rustc_errors::{PResult, Applicability, DiagnosticBuilder, StashKey};
|
||||
use rustc_error_codes::*;
|
||||
use syntax::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, AnonConst, Item};
|
||||
use syntax::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind};
|
||||
use syntax::ast::{AssocItem, AssocItemKind, ItemKind, UseTree, UseTreeKind};
|
||||
use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit};
|
||||
use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind};
|
||||
use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, Variant, VariantData, StructField};
|
||||
|
@ -648,7 +648,7 @@ impl<'a> Parser<'a> {
|
|||
Ok((Ident::invalid(), item_kind, Some(attrs)))
|
||||
}
|
||||
|
||||
fn parse_impl_body(&mut self) -> PResult<'a, (Vec<ImplItem>, Vec<Attribute>)> {
|
||||
fn parse_impl_body(&mut self) -> PResult<'a, (Vec<AssocItem>, Vec<Attribute>)> {
|
||||
self.expect(&token::OpenDelim(token::Brace))?;
|
||||
let attrs = self.parse_inner_attributes()?;
|
||||
|
||||
|
@ -669,60 +669,6 @@ impl<'a> Parser<'a> {
|
|||
Ok((impl_items, attrs))
|
||||
}
|
||||
|
||||
/// Parses an impl item.
|
||||
pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, ImplItem> {
|
||||
maybe_whole!(self, NtImplItem, |x| x);
|
||||
let attrs = self.parse_outer_attributes()?;
|
||||
let mut unclosed_delims = vec![];
|
||||
let (mut item, tokens) = self.collect_tokens(|this| {
|
||||
let item = this.parse_impl_item_(at_end, attrs);
|
||||
unclosed_delims.append(&mut this.unclosed_delims);
|
||||
item
|
||||
})?;
|
||||
self.unclosed_delims.append(&mut unclosed_delims);
|
||||
|
||||
// See `parse_item` for why this clause is here.
|
||||
if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) {
|
||||
item.tokens = Some(tokens);
|
||||
}
|
||||
Ok(item)
|
||||
}
|
||||
|
||||
fn parse_impl_item_(
|
||||
&mut self,
|
||||
at_end: &mut bool,
|
||||
mut attrs: Vec<Attribute>,
|
||||
) -> PResult<'a, ImplItem> {
|
||||
let lo = self.token.span;
|
||||
let vis = self.parse_visibility(FollowedByType::No)?;
|
||||
let defaultness = self.parse_defaultness();
|
||||
let (name, kind, generics) = if self.eat_keyword(kw::Type) {
|
||||
let (name, ty, generics) = self.parse_type_alias()?;
|
||||
(name, ast::ImplItemKind::TyAlias(ty), generics)
|
||||
} else if self.is_const_item() {
|
||||
self.parse_impl_const()?
|
||||
} else if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(&vis), at_end)? {
|
||||
// FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction!
|
||||
(Ident::invalid(), ast::ImplItemKind::Macro(mac), Generics::default())
|
||||
} else {
|
||||
let (name, inner_attrs, generics, kind) = self.parse_impl_method(at_end)?;
|
||||
attrs.extend(inner_attrs);
|
||||
(name, kind, generics)
|
||||
};
|
||||
|
||||
Ok(ImplItem {
|
||||
id: DUMMY_NODE_ID,
|
||||
span: lo.to(self.prev_span),
|
||||
ident: name,
|
||||
vis,
|
||||
defaultness,
|
||||
attrs,
|
||||
generics,
|
||||
kind,
|
||||
tokens: None,
|
||||
})
|
||||
}
|
||||
|
||||
/// Parses defaultness (i.e., `default` or nothing).
|
||||
fn parse_defaultness(&mut self) -> Defaultness {
|
||||
// `pub` is included for better error messages
|
||||
|
@ -745,26 +691,6 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if we are looking at `const ID`
|
||||
/// (returns `false` for things like `const fn`, etc.).
|
||||
fn is_const_item(&self) -> bool {
|
||||
self.token.is_keyword(kw::Const) &&
|
||||
!self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe])
|
||||
}
|
||||
|
||||
/// This parses the grammar:
|
||||
/// ImplItemConst = "const" Ident ":" Ty "=" Expr ";"
|
||||
fn parse_impl_const(&mut self) -> PResult<'a, (Ident, ImplItemKind, Generics)> {
|
||||
self.expect_keyword(kw::Const)?;
|
||||
let name = self.parse_ident()?;
|
||||
self.expect(&token::Colon)?;
|
||||
let typ = self.parse_ty()?;
|
||||
self.expect(&token::Eq)?;
|
||||
let expr = self.parse_expr()?;
|
||||
self.expect_semi()?;
|
||||
Ok((name, ImplItemKind::Const(typ, expr), Generics::default()))
|
||||
}
|
||||
|
||||
/// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`.
|
||||
fn parse_item_trait(&mut self, lo: Span, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
|
||||
// Parse optional `auto` prefix.
|
||||
|
@ -857,13 +783,30 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Parses the items in a trait declaration.
|
||||
pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, TraitItem> {
|
||||
pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, AssocItem> {
|
||||
maybe_whole!(self, NtImplItem, |x| x);
|
||||
self.parse_assoc_item(at_end, |_| true)
|
||||
}
|
||||
|
||||
pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, AssocItem> {
|
||||
maybe_whole!(self, NtTraitItem, |x| x);
|
||||
// This is somewhat dubious; We don't want to allow
|
||||
// param names to be left off if there is a definition...
|
||||
//
|
||||
// We don't allow param names to be left off in edition 2018.
|
||||
self.parse_assoc_item(at_end, |t| t.span.rust_2018())
|
||||
}
|
||||
|
||||
/// Parses associated items.
|
||||
fn parse_assoc_item(
|
||||
&mut self,
|
||||
at_end: &mut bool,
|
||||
is_name_required: fn(&token::Token) -> bool,
|
||||
) -> PResult<'a, AssocItem> {
|
||||
let attrs = self.parse_outer_attributes()?;
|
||||
let mut unclosed_delims = vec![];
|
||||
let (mut item, tokens) = self.collect_tokens(|this| {
|
||||
let item = this.parse_trait_item_(at_end, attrs);
|
||||
let item = this.parse_assoc_item_(at_end, attrs, is_name_required);
|
||||
unclosed_delims.append(&mut this.unclosed_delims);
|
||||
item
|
||||
})?;
|
||||
|
@ -875,54 +818,66 @@ impl<'a> Parser<'a> {
|
|||
Ok(item)
|
||||
}
|
||||
|
||||
fn parse_trait_item_(
|
||||
fn parse_assoc_item_(
|
||||
&mut self,
|
||||
at_end: &mut bool,
|
||||
mut attrs: Vec<Attribute>,
|
||||
) -> PResult<'a, TraitItem> {
|
||||
is_name_required: fn(&token::Token) -> bool,
|
||||
) -> PResult<'a, AssocItem> {
|
||||
let lo = self.token.span;
|
||||
let vis = self.parse_visibility(FollowedByType::No)?;
|
||||
let defaultness = self.parse_defaultness();
|
||||
let (name, kind, generics) = if self.eat_keyword(kw::Type) {
|
||||
self.parse_trait_item_assoc_ty()?
|
||||
self.parse_assoc_ty()?
|
||||
} else if self.is_const_item() {
|
||||
self.parse_trait_item_const()?
|
||||
} else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? {
|
||||
// trait item macro.
|
||||
(Ident::invalid(), TraitItemKind::Macro(mac), Generics::default())
|
||||
self.parse_assoc_const()?
|
||||
} else if let Some(mac) = self.parse_assoc_macro_invoc("associated", Some(&vis), at_end)? {
|
||||
(Ident::invalid(), AssocItemKind::Macro(mac), Generics::default())
|
||||
} else {
|
||||
self.parse_trait_item_method(at_end, &mut attrs)?
|
||||
self.parse_assoc_fn(at_end, &mut attrs, is_name_required)?
|
||||
};
|
||||
|
||||
Ok(TraitItem {
|
||||
Ok(AssocItem {
|
||||
id: DUMMY_NODE_ID,
|
||||
span: lo.to(self.prev_span),
|
||||
ident: name,
|
||||
attrs,
|
||||
vis,
|
||||
defaultness,
|
||||
generics,
|
||||
kind,
|
||||
span: lo.to(self.prev_span),
|
||||
tokens: None,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_trait_item_const(&mut self) -> PResult<'a, (Ident, TraitItemKind, Generics)> {
|
||||
/// Returns `true` if we are looking at `const ID`
|
||||
/// (returns `false` for things like `const fn`, etc.).
|
||||
fn is_const_item(&self) -> bool {
|
||||
self.token.is_keyword(kw::Const) &&
|
||||
!self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe])
|
||||
}
|
||||
|
||||
/// This parses the grammar:
|
||||
///
|
||||
/// AssocConst = "const" Ident ":" Ty "=" Expr ";"
|
||||
fn parse_assoc_const(&mut self) -> PResult<'a, (Ident, AssocItemKind, Generics)> {
|
||||
self.expect_keyword(kw::Const)?;
|
||||
let ident = self.parse_ident()?;
|
||||
self.expect(&token::Colon)?;
|
||||
let ty = self.parse_ty()?;
|
||||
let default = if self.eat(&token::Eq) {
|
||||
let expr = if self.eat(&token::Eq) {
|
||||
Some(self.parse_expr()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
self.expect_semi()?;
|
||||
Ok((ident, TraitItemKind::Const(ty, default), Generics::default()))
|
||||
Ok((ident, AssocItemKind::Const(ty, expr), Generics::default()))
|
||||
}
|
||||
|
||||
/// Parses the following grammar:
|
||||
///
|
||||
/// TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]
|
||||
fn parse_trait_item_assoc_ty(&mut self) -> PResult<'a, (Ident, TraitItemKind, Generics)> {
|
||||
/// AssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]
|
||||
fn parse_assoc_ty(&mut self) -> PResult<'a, (Ident, AssocItemKind, Generics)> {
|
||||
let ident = self.parse_ident()?;
|
||||
let mut generics = self.parse_generics()?;
|
||||
|
||||
|
@ -941,7 +896,7 @@ impl<'a> Parser<'a> {
|
|||
};
|
||||
self.expect_semi()?;
|
||||
|
||||
Ok((ident, TraitItemKind::Type(bounds, default), generics))
|
||||
Ok((ident, AssocItemKind::TyAlias(bounds, default), generics))
|
||||
}
|
||||
|
||||
/// Parses a `UseTree`.
|
||||
|
@ -1772,8 +1727,6 @@ impl<'a> Parser<'a> {
|
|||
pub(super) struct ParamCfg {
|
||||
/// Is `self` is allowed as the first parameter?
|
||||
pub is_self_allowed: bool,
|
||||
/// Is `...` allowed as the tail of the parameter list?
|
||||
pub allow_c_variadic: bool,
|
||||
/// `is_name_required` decides if, per-parameter,
|
||||
/// the parameter must have a pattern or just a type.
|
||||
pub is_name_required: fn(&token::Token) -> bool,
|
||||
|
@ -1789,16 +1742,8 @@ impl<'a> Parser<'a> {
|
|||
attrs: Vec<Attribute>,
|
||||
header: FnHeader,
|
||||
) -> PResult<'a, Option<P<Item>>> {
|
||||
let is_c_abi = match header.ext {
|
||||
ast::Extern::None => false,
|
||||
ast::Extern::Implicit => true,
|
||||
ast::Extern::Explicit(abi) => abi.symbol_unescaped == sym::C,
|
||||
};
|
||||
let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
|
||||
is_self_allowed: false,
|
||||
// FIXME: Parsing should not depend on ABI or unsafety and
|
||||
// the variadic parameter should always be parsed.
|
||||
allow_c_variadic: is_c_abi && header.unsafety == Unsafety::Unsafe,
|
||||
is_name_required: |_| true,
|
||||
})?;
|
||||
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
|
@ -1817,7 +1762,6 @@ impl<'a> Parser<'a> {
|
|||
self.expect_keyword(kw::Fn)?;
|
||||
let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
|
||||
is_self_allowed: false,
|
||||
allow_c_variadic: true,
|
||||
is_name_required: |_| true,
|
||||
})?;
|
||||
let span = lo.to(self.token.span);
|
||||
|
@ -1833,48 +1777,39 @@ impl<'a> Parser<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Parses a method or a macro invocation in a trait impl.
|
||||
fn parse_impl_method(
|
||||
&mut self,
|
||||
at_end: &mut bool,
|
||||
) -> PResult<'a, (Ident, Vec<Attribute>, Generics, ImplItemKind)> {
|
||||
let (ident, sig, generics) = self.parse_method_sig(|_| true)?;
|
||||
*at_end = true;
|
||||
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method(sig, body)))
|
||||
}
|
||||
|
||||
fn parse_trait_item_method(
|
||||
fn parse_assoc_fn(
|
||||
&mut self,
|
||||
at_end: &mut bool,
|
||||
attrs: &mut Vec<Attribute>,
|
||||
) -> PResult<'a, (Ident, TraitItemKind, Generics)> {
|
||||
// This is somewhat dubious; We don't want to allow
|
||||
// argument names to be left off if there is a definition...
|
||||
//
|
||||
// We don't allow argument names to be left off in edition 2018.
|
||||
let (ident, sig, generics) = self.parse_method_sig(|t| t.span.rust_2018())?;
|
||||
let body = self.parse_trait_method_body(at_end, attrs)?;
|
||||
Ok((ident, TraitItemKind::Method(sig, body), generics))
|
||||
is_name_required: fn(&token::Token) -> bool,
|
||||
) -> PResult<'a, (Ident, AssocItemKind, Generics)> {
|
||||
let header = self.parse_fn_front_matter()?;
|
||||
let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
|
||||
is_self_allowed: true,
|
||||
is_name_required,
|
||||
})?;
|
||||
let sig = FnSig { header, decl };
|
||||
let body = self.parse_assoc_fn_body(at_end, attrs)?;
|
||||
Ok((ident, AssocItemKind::Fn(sig, body), generics))
|
||||
}
|
||||
|
||||
/// Parse the "body" of a method in a trait item definition.
|
||||
/// Parse the "body" of a method in an associated item definition.
|
||||
/// This can either be `;` when there's no body,
|
||||
/// or e.g. a block when the method is a provided one.
|
||||
fn parse_trait_method_body(
|
||||
fn parse_assoc_fn_body(
|
||||
&mut self,
|
||||
at_end: &mut bool,
|
||||
attrs: &mut Vec<Attribute>,
|
||||
) -> PResult<'a, Option<P<Block>>> {
|
||||
Ok(match self.token.kind {
|
||||
token::Semi => {
|
||||
debug!("parse_trait_method_body(): parsing required method");
|
||||
debug!("parse_assoc_fn_body(): parsing required method");
|
||||
self.bump();
|
||||
*at_end = true;
|
||||
None
|
||||
}
|
||||
token::OpenDelim(token::Brace) => {
|
||||
debug!("parse_trait_method_body(): parsing provided method");
|
||||
debug!("parse_assoc_fn_body(): parsing provided method");
|
||||
*at_end = true;
|
||||
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
attrs.extend(inner_attrs.iter().cloned());
|
||||
|
@ -1895,21 +1830,6 @@ impl<'a> Parser<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Parse the "signature", including the identifier, parameters, and generics
|
||||
/// of a method. The body is not parsed as that differs between `trait`s and `impl`s.
|
||||
fn parse_method_sig(
|
||||
&mut self,
|
||||
is_name_required: fn(&token::Token) -> bool,
|
||||
) -> PResult<'a, (Ident, FnSig, Generics)> {
|
||||
let header = self.parse_fn_front_matter()?;
|
||||
let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
|
||||
is_self_allowed: true,
|
||||
allow_c_variadic: false,
|
||||
is_name_required,
|
||||
})?;
|
||||
Ok((ident, FnSig { header, decl }, generics))
|
||||
}
|
||||
|
||||
/// Parses all the "front matter" for a `fn` declaration, up to
|
||||
/// and including the `fn` keyword:
|
||||
///
|
||||
|
@ -1959,64 +1879,29 @@ impl<'a> Parser<'a> {
|
|||
) -> PResult<'a, P<FnDecl>> {
|
||||
Ok(P(FnDecl {
|
||||
inputs: self.parse_fn_params(cfg)?,
|
||||
output: self.parse_ret_ty(ret_allow_plus)?,
|
||||
output: self.parse_ret_ty(ret_allow_plus, true)?,
|
||||
}))
|
||||
}
|
||||
|
||||
/// Parses the parameter list of a function, including the `(` and `)` delimiters.
|
||||
fn parse_fn_params(&mut self, mut cfg: ParamCfg) -> PResult<'a, Vec<Param>> {
|
||||
let sp = self.token.span;
|
||||
let is_trait_item = cfg.is_self_allowed;
|
||||
let mut c_variadic = false;
|
||||
// Parse the arguments, starting out with `self` being possibly allowed...
|
||||
let (params, _) = self.parse_paren_comma_seq(|p| {
|
||||
let param = p.parse_param_general(&cfg, is_trait_item);
|
||||
let (mut params, _) = self.parse_paren_comma_seq(|p| {
|
||||
let param = p.parse_param_general(&cfg, is_trait_item).or_else(|mut e| {
|
||||
e.emit();
|
||||
let lo = p.prev_span;
|
||||
// Skip every token until next possible arg or end.
|
||||
p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]);
|
||||
// Create a placeholder argument for proper arg count (issue #34264).
|
||||
Ok(dummy_arg(Ident::new(kw::Invalid, lo.to(p.prev_span))))
|
||||
});
|
||||
// ...now that we've parsed the first argument, `self` is no longer allowed.
|
||||
cfg.is_self_allowed = false;
|
||||
|
||||
match param {
|
||||
Ok(param) => Ok(
|
||||
if let TyKind::CVarArgs = param.ty.kind {
|
||||
c_variadic = true;
|
||||
if p.token != token::CloseDelim(token::Paren) {
|
||||
p.span_err(
|
||||
p.token.span,
|
||||
"`...` must be the last argument of a C-variadic function",
|
||||
);
|
||||
// FIXME(eddyb) this should probably still push `CVarArgs`.
|
||||
// Maybe AST validation/HIR lowering should emit the above error?
|
||||
None
|
||||
} else {
|
||||
Some(param)
|
||||
}
|
||||
} else {
|
||||
Some(param)
|
||||
}
|
||||
),
|
||||
Err(mut e) => {
|
||||
e.emit();
|
||||
let lo = p.prev_span;
|
||||
// Skip every token until next possible arg or end.
|
||||
p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]);
|
||||
// Create a placeholder argument for proper arg count (issue #34264).
|
||||
let span = lo.to(p.prev_span);
|
||||
Ok(Some(dummy_arg(Ident::new(kw::Invalid, span))))
|
||||
}
|
||||
}
|
||||
param
|
||||
})?;
|
||||
|
||||
let mut params: Vec<_> = params.into_iter().filter_map(|x| x).collect();
|
||||
|
||||
// Replace duplicated recovered params with `_` pattern to avoid unnecessary errors.
|
||||
self.deduplicate_recovered_params_names(&mut params);
|
||||
|
||||
if c_variadic && params.len() <= 1 {
|
||||
self.span_err(
|
||||
sp,
|
||||
"C-variadic function must be declared with at least one named argument",
|
||||
);
|
||||
}
|
||||
|
||||
Ok(params)
|
||||
}
|
||||
|
||||
|
@ -2061,12 +1946,12 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
self.eat_incorrect_doc_comment_for_param_type();
|
||||
(pat, self.parse_ty_common(true, true, cfg.allow_c_variadic)?)
|
||||
(pat, self.parse_ty_for_param()?)
|
||||
} else {
|
||||
debug!("parse_param_general ident_to_pat");
|
||||
let parser_snapshot_before_ty = self.clone();
|
||||
self.eat_incorrect_doc_comment_for_param_type();
|
||||
let mut ty = self.parse_ty_common(true, true, cfg.allow_c_variadic);
|
||||
let mut ty = self.parse_ty_for_param();
|
||||
if ty.is_ok() && self.token != token::Comma &&
|
||||
self.token != token::CloseDelim(token::Paren) {
|
||||
// This wasn't actually a type, but a pattern looking like a type,
|
||||
|
|
|
@ -182,11 +182,7 @@ impl<'a> Parser<'a> {
|
|||
// `(T, U) -> R`
|
||||
let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?;
|
||||
let span = ident.span.to(self.prev_span);
|
||||
let output = if self.eat(&token::RArrow) {
|
||||
Some(self.parse_ty_common(false, false, false)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let output = self.parse_ret_ty(false, false)?;
|
||||
ParenthesizedArgs { inputs, output, span }.into()
|
||||
};
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ use syntax::ast::{self, Ty, TyKind, MutTy, BareFnTy, FunctionRetTy, GenericParam
|
|||
use syntax::ast::{TraitBoundModifier, TraitObjectSyntax, GenericBound, GenericBounds, PolyTraitRef};
|
||||
use syntax::ast::{Mutability, AnonConst, Mac};
|
||||
use syntax::token::{self, Token};
|
||||
use syntax::struct_span_fatal;
|
||||
use syntax::struct_span_err;
|
||||
use syntax_pos::source_map::Span;
|
||||
use syntax_pos::symbol::kw;
|
||||
|
||||
|
@ -30,6 +30,13 @@ impl<'a> Parser<'a> {
|
|||
self.parse_ty_common(true, true, false)
|
||||
}
|
||||
|
||||
/// Parse a type suitable for a function or function pointer parameter.
|
||||
/// The difference from `parse_ty` is that this version allows `...`
|
||||
/// (`CVarArgs`) at the top level of the the type.
|
||||
pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, P<Ty>> {
|
||||
self.parse_ty_common(true, true, true)
|
||||
}
|
||||
|
||||
/// Parses a type in restricted contexts where `+` is not permitted.
|
||||
///
|
||||
/// Example 1: `&'a TYPE`
|
||||
|
@ -41,16 +48,26 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
/// Parses an optional return type `[ -> TY ]` in a function declaration.
|
||||
pub(super) fn parse_ret_ty(&mut self, allow_plus: bool) -> PResult<'a, FunctionRetTy> {
|
||||
if self.eat(&token::RArrow) {
|
||||
Ok(FunctionRetTy::Ty(self.parse_ty_common(allow_plus, true, false)?))
|
||||
pub(super) fn parse_ret_ty(
|
||||
&mut self,
|
||||
allow_plus: bool,
|
||||
allow_qpath_recovery: bool,
|
||||
) -> PResult<'a, FunctionRetTy> {
|
||||
Ok(if self.eat(&token::RArrow) {
|
||||
// FIXME(Centril): Can we unconditionally `allow_plus`?
|
||||
FunctionRetTy::Ty(self.parse_ty_common(allow_plus, allow_qpath_recovery, false)?)
|
||||
} else {
|
||||
Ok(FunctionRetTy::Default(self.token.span.shrink_to_lo()))
|
||||
}
|
||||
FunctionRetTy::Default(self.token.span.shrink_to_lo())
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool,
|
||||
allow_c_variadic: bool) -> PResult<'a, P<Ty>> {
|
||||
fn parse_ty_common(
|
||||
&mut self,
|
||||
allow_plus: bool,
|
||||
allow_qpath_recovery: bool,
|
||||
// Is `...` (`CVarArgs`) legal in the immediate top level call?
|
||||
allow_c_variadic: bool,
|
||||
) -> PResult<'a, P<Ty>> {
|
||||
maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
|
||||
maybe_whole!(self, NtTy, |x| x);
|
||||
|
||||
|
@ -192,17 +209,21 @@ impl<'a> Parser<'a> {
|
|||
TyKind::Path(None, path)
|
||||
}
|
||||
}
|
||||
} else if self.check(&token::DotDotDot) {
|
||||
} else if self.eat(&token::DotDotDot) {
|
||||
if allow_c_variadic {
|
||||
self.eat(&token::DotDotDot);
|
||||
TyKind::CVarArgs
|
||||
} else {
|
||||
return Err(struct_span_fatal!(
|
||||
// FIXME(Centril): Should we just allow `...` syntactically
|
||||
// anywhere in a type and use semantic restrictions instead?
|
||||
struct_span_err!(
|
||||
self.sess.span_diagnostic,
|
||||
self.token.span,
|
||||
lo.to(self.prev_span),
|
||||
E0743,
|
||||
"only foreign functions are allowed to be C-variadic",
|
||||
));
|
||||
"C-variadic type `...` may not be nested inside another type",
|
||||
)
|
||||
.emit();
|
||||
|
||||
TyKind::Err
|
||||
}
|
||||
} else {
|
||||
let msg = format!("expected type, found {}", self.this_token_descr());
|
||||
|
@ -287,7 +308,6 @@ impl<'a> Parser<'a> {
|
|||
self.expect_keyword(kw::Fn)?;
|
||||
let cfg = ParamCfg {
|
||||
is_self_allowed: false,
|
||||
allow_c_variadic: true,
|
||||
is_name_required: |_| false,
|
||||
};
|
||||
let decl = self.parse_fn_decl(cfg, false)?;
|
||||
|
|
|
@ -250,6 +250,26 @@ impl<'a> AstValidator<'a> {
|
|||
}
|
||||
|
||||
fn check_fn_decl(&self, fn_decl: &FnDecl) {
|
||||
match &*fn_decl.inputs {
|
||||
[Param { ty, span, .. }] => if let TyKind::CVarArgs = ty.kind {
|
||||
self.err_handler()
|
||||
.span_err(
|
||||
*span,
|
||||
"C-variadic function must be declared with at least one named argument",
|
||||
);
|
||||
},
|
||||
[ps @ .., _] => for Param { ty, span, .. } in ps {
|
||||
if let TyKind::CVarArgs = ty.kind {
|
||||
self.err_handler()
|
||||
.span_err(
|
||||
*span,
|
||||
"`...` must be the last argument of a C-variadic function",
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
fn_decl
|
||||
.inputs
|
||||
.iter()
|
||||
|
@ -259,18 +279,65 @@ impl<'a> AstValidator<'a> {
|
|||
!arr.contains(&attr.name_or_empty()) && attr::is_builtin_attr(attr)
|
||||
})
|
||||
.for_each(|attr| if attr.is_doc_comment() {
|
||||
let mut err = self.err_handler().struct_span_err(
|
||||
self.err_handler().struct_span_err(
|
||||
attr.span,
|
||||
"documentation comments cannot be applied to function parameters"
|
||||
);
|
||||
err.span_label(attr.span, "doc comments are not allowed here");
|
||||
err.emit();
|
||||
}
|
||||
else {
|
||||
)
|
||||
.span_label(attr.span, "doc comments are not allowed here")
|
||||
.emit();
|
||||
} else {
|
||||
self.err_handler().span_err(attr.span, "allow, cfg, cfg_attr, deny, \
|
||||
forbid, and warn are the only allowed built-in attributes in function parameters")
|
||||
});
|
||||
}
|
||||
|
||||
fn check_defaultness(&self, span: Span, defaultness: Defaultness) {
|
||||
if let Defaultness::Default = defaultness {
|
||||
self.err_handler()
|
||||
.struct_span_err(span, "`default` is only allowed on items in `impl` definitions")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
||||
fn check_impl_item_provided<T>(&self, sp: Span, body: &Option<T>, ctx: &str, sugg: &str) {
|
||||
if body.is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.err_handler()
|
||||
.struct_span_err(sp, &format!("associated {} in `impl` without body", ctx))
|
||||
.span_suggestion(
|
||||
self.session.source_map().end_point(sp),
|
||||
&format!("provide a definition for the {}", ctx),
|
||||
sugg.to_string(),
|
||||
Applicability::HasPlaceholders,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
fn check_impl_assoc_type_no_bounds(&self, bounds: &[GenericBound]) {
|
||||
let span = match bounds {
|
||||
[] => return,
|
||||
[b0] => b0.span(),
|
||||
[b0, .., bl] => b0.span().to(bl.span()),
|
||||
};
|
||||
self.err_handler()
|
||||
.struct_span_err(span, "bounds on associated `type`s in `impl`s have no effect")
|
||||
.emit();
|
||||
}
|
||||
|
||||
fn check_c_varadic_type(&self, decl: &FnDecl) {
|
||||
for Param { ty, span, .. } in &decl.inputs {
|
||||
if let TyKind::CVarArgs = ty.kind {
|
||||
self.err_handler()
|
||||
.struct_span_err(
|
||||
*span,
|
||||
"only foreign or `unsafe extern \"C\" functions may be C-variadic",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum GenericPosition {
|
||||
|
@ -477,7 +544,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
}
|
||||
for impl_item in impl_items {
|
||||
self.invalid_visibility(&impl_item.vis, None);
|
||||
if let ImplItemKind::Method(ref sig, _) = impl_item.kind {
|
||||
if let AssocItemKind::Fn(ref sig, _) = impl_item.kind {
|
||||
self.check_trait_fn_not_const(sig.header.constness);
|
||||
self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness.node);
|
||||
}
|
||||
|
@ -519,6 +586,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
// Reject C-varadic type unless the function is `unsafe extern "C"` semantically.
|
||||
match sig.header.ext {
|
||||
Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }) |
|
||||
Extern::Implicit if sig.header.unsafety == Unsafety::Unsafe => {}
|
||||
_ => self.check_c_varadic_type(&sig.decl),
|
||||
}
|
||||
}
|
||||
ItemKind::ForeignMod(..) => {
|
||||
self.invalid_visibility(
|
||||
|
@ -554,26 +627,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
}
|
||||
}
|
||||
self.no_questions_in_bounds(bounds, "supertraits", true);
|
||||
for trait_item in trait_items {
|
||||
if let TraitItemKind::Method(ref sig, ref block) = trait_item.kind {
|
||||
self.check_fn_decl(&sig.decl);
|
||||
self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness.node);
|
||||
self.check_trait_fn_not_const(sig.header.constness);
|
||||
if block.is_none() {
|
||||
Self::check_decl_no_pat(&sig.decl, |span, mut_ident| {
|
||||
if mut_ident {
|
||||
self.lint_buffer.buffer_lint(
|
||||
lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||
trait_item.id, span,
|
||||
"patterns aren't allowed in methods without bodies");
|
||||
} else {
|
||||
struct_span_err!(self.session, span, E0642,
|
||||
"patterns aren't allowed in methods without bodies").emit();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ItemKind::Mod(_) => {
|
||||
// Ensure that `path` attributes on modules are recorded as used (cf. issue #35584).
|
||||
|
@ -639,10 +692,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
}
|
||||
GenericArgs::Parenthesized(ref data) => {
|
||||
walk_list!(self, visit_ty, &data.inputs);
|
||||
if let Some(ref type_) = data.output {
|
||||
if let FunctionRetTy::Ty(ty) = &data.output {
|
||||
// `-> Foo` syntax is essentially an associated type binding,
|
||||
// so it is also allowed to contain nested `impl Trait`.
|
||||
self.with_impl_trait(None, |this| this.visit_ty(type_));
|
||||
self.with_impl_trait(None, |this| this.visit_ty(ty));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -737,17 +790,59 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
|this| visit::walk_enum_def(this, enum_definition, generics, item_id))
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
|
||||
if let ImplItemKind::Method(ref sig, _) = ii.kind {
|
||||
self.check_fn_decl(&sig.decl);
|
||||
fn visit_impl_item(&mut self, ii: &'a AssocItem) {
|
||||
match &ii.kind {
|
||||
AssocItemKind::Const(_, body) => {
|
||||
self.check_impl_item_provided(ii.span, body, "constant", " = <expr>;");
|
||||
}
|
||||
AssocItemKind::Fn(sig, body) => {
|
||||
self.check_impl_item_provided(ii.span, body, "function", " { <body> }");
|
||||
self.check_fn_decl(&sig.decl);
|
||||
}
|
||||
AssocItemKind::TyAlias(bounds, body) => {
|
||||
self.check_impl_item_provided(ii.span, body, "type", " = <type>;");
|
||||
self.check_impl_assoc_type_no_bounds(bounds);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
visit::walk_impl_item(self, ii);
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, ti: &'a TraitItem) {
|
||||
fn visit_trait_item(&mut self, ti: &'a AssocItem) {
|
||||
self.invalid_visibility(&ti.vis, None);
|
||||
self.check_defaultness(ti.span, ti.defaultness);
|
||||
|
||||
if let AssocItemKind::Fn(sig, block) = &ti.kind {
|
||||
self.check_fn_decl(&sig.decl);
|
||||
self.check_trait_fn_not_async(ti.span, sig.header.asyncness.node);
|
||||
self.check_trait_fn_not_const(sig.header.constness);
|
||||
if block.is_none() {
|
||||
Self::check_decl_no_pat(&sig.decl, |span, mut_ident| {
|
||||
if mut_ident {
|
||||
self.lint_buffer.buffer_lint(
|
||||
lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||
ti.id, span,
|
||||
"patterns aren't allowed in methods without bodies"
|
||||
);
|
||||
} else {
|
||||
struct_span_err!(
|
||||
self.session, span, E0642,
|
||||
"patterns aren't allowed in methods without bodies"
|
||||
).emit();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
visit::walk_trait_item(self, ti);
|
||||
}
|
||||
|
||||
fn visit_assoc_item(&mut self, item: &'a AssocItem) {
|
||||
if let AssocItemKind::Fn(sig, _) = &item.kind {
|
||||
self.check_c_varadic_type(&sig.decl);
|
||||
}
|
||||
visit::walk_assoc_item(self, item);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_crate(session: &Session, krate: &Crate, lints: &mut lint::LintBuffer) -> bool {
|
||||
|
|
|
@ -314,12 +314,12 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
|
|||
ast_visit::walk_fn(self, fk, fd, s)
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, ti: &'v ast::TraitItem) {
|
||||
fn visit_trait_item(&mut self, ti: &'v ast::AssocItem) {
|
||||
self.record("TraitItem", Id::None, ti);
|
||||
ast_visit::walk_trait_item(self, ti)
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, ii: &'v ast::ImplItem) {
|
||||
fn visit_impl_item(&mut self, ii: &'v ast::AssocItem) {
|
||||
self.record("ImplItem", Id::None, ii);
|
||||
ast_visit::walk_impl_item(self, ii)
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ use errors::Applicability;
|
|||
use syntax::ast::{Name, Ident};
|
||||
use syntax::attr;
|
||||
use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId};
|
||||
use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind};
|
||||
use syntax::ast::{MetaItemKind, StmtKind, AssocItem, AssocItemKind};
|
||||
use syntax::token::{self, Token};
|
||||
use syntax::span_err;
|
||||
use syntax::source_map::{respan, Spanned};
|
||||
|
@ -1164,10 +1164,10 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
|
|||
self.parent_scope.legacy = orig_current_legacy_scope;
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, item: &'b TraitItem) {
|
||||
fn visit_trait_item(&mut self, item: &'b AssocItem) {
|
||||
let parent = self.parent_scope.module;
|
||||
|
||||
if let TraitItemKind::Macro(_) = item.kind {
|
||||
if let AssocItemKind::Macro(_) = item.kind {
|
||||
self.visit_invoc(item.id);
|
||||
return
|
||||
}
|
||||
|
@ -1175,15 +1175,15 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
|
|||
// Add the item to the trait info.
|
||||
let item_def_id = self.r.definitions.local_def_id(item.id);
|
||||
let (res, ns) = match item.kind {
|
||||
TraitItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS),
|
||||
TraitItemKind::Method(ref sig, _) => {
|
||||
AssocItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS),
|
||||
AssocItemKind::Fn(ref sig, _) => {
|
||||
if sig.decl.has_self() {
|
||||
self.r.has_self.insert(item_def_id);
|
||||
}
|
||||
(Res::Def(DefKind::Method, item_def_id), ValueNS)
|
||||
}
|
||||
TraitItemKind::Type(..) => (Res::Def(DefKind::AssocTy, item_def_id), TypeNS),
|
||||
TraitItemKind::Macro(_) => bug!(), // handled above
|
||||
AssocItemKind::TyAlias(..) => (Res::Def(DefKind::AssocTy, item_def_id), TypeNS),
|
||||
AssocItemKind::Macro(_) => bug!(), // handled above
|
||||
};
|
||||
|
||||
let vis = ty::Visibility::Public;
|
||||
|
@ -1193,8 +1193,8 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
|
|||
visit::walk_trait_item(self, item);
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, item: &'b ast::ImplItem) {
|
||||
if let ast::ImplItemKind::Macro(..) = item.kind {
|
||||
fn visit_impl_item(&mut self, item: &'b ast::AssocItem) {
|
||||
if let ast::AssocItemKind::Macro(..) = item.kind {
|
||||
self.visit_invoc(item.id);
|
||||
} else {
|
||||
self.resolve_visibility(&item.vis);
|
||||
|
|
|
@ -50,7 +50,7 @@ impl<'a> DefCollector<'a> {
|
|||
header: &FnHeader,
|
||||
generics: &'a Generics,
|
||||
decl: &'a FnDecl,
|
||||
body: &'a Block,
|
||||
body: Option<&'a Block>,
|
||||
) {
|
||||
let (closure_id, return_impl_trait_id) = match header.asyncness.node {
|
||||
IsAsync::Async {
|
||||
|
@ -74,7 +74,9 @@ impl<'a> DefCollector<'a> {
|
|||
closure_id, DefPathData::ClosureExpr, span,
|
||||
);
|
||||
this.with_parent(closure_def, |this| {
|
||||
visit::walk_block(this, body);
|
||||
if let Some(body) = body {
|
||||
visit::walk_block(this, body);
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -123,7 +125,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
|||
&sig.header,
|
||||
generics,
|
||||
&sig.decl,
|
||||
body,
|
||||
Some(body),
|
||||
)
|
||||
}
|
||||
ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
|
||||
|
@ -210,23 +212,20 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
|||
visit::walk_generic_param(self, param);
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, ti: &'a TraitItem) {
|
||||
fn visit_trait_item(&mut self, ti: &'a AssocItem) {
|
||||
let def_data = match ti.kind {
|
||||
TraitItemKind::Method(..) | TraitItemKind::Const(..) =>
|
||||
DefPathData::ValueNs(ti.ident.name),
|
||||
TraitItemKind::Type(..) => {
|
||||
DefPathData::TypeNs(ti.ident.name)
|
||||
},
|
||||
TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id),
|
||||
AssocItemKind::Fn(..) | AssocItemKind::Const(..) => DefPathData::ValueNs(ti.ident.name),
|
||||
AssocItemKind::TyAlias(..) => DefPathData::TypeNs(ti.ident.name),
|
||||
AssocItemKind::Macro(..) => return self.visit_macro_invoc(ti.id),
|
||||
};
|
||||
|
||||
let def = self.create_def(ti.id, def_data, ti.span);
|
||||
self.with_parent(def, |this| visit::walk_trait_item(this, ti));
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
|
||||
fn visit_impl_item(&mut self, ii: &'a AssocItem) {
|
||||
let def_data = match ii.kind {
|
||||
ImplItemKind::Method(FnSig {
|
||||
AssocItemKind::Fn(FnSig {
|
||||
ref header,
|
||||
ref decl,
|
||||
}, ref body) if header.asyncness.node.is_async() => {
|
||||
|
@ -237,13 +236,13 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
|||
header,
|
||||
&ii.generics,
|
||||
decl,
|
||||
body,
|
||||
body.as_deref(),
|
||||
)
|
||||
}
|
||||
ImplItemKind::Method(..) |
|
||||
ImplItemKind::Const(..) => DefPathData::ValueNs(ii.ident.name),
|
||||
ImplItemKind::TyAlias(..) => DefPathData::TypeNs(ii.ident.name),
|
||||
ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id),
|
||||
AssocItemKind::Fn(..) |
|
||||
AssocItemKind::Const(..) => DefPathData::ValueNs(ii.ident.name),
|
||||
AssocItemKind::TyAlias(..) => DefPathData::TypeNs(ii.ident.name),
|
||||
AssocItemKind::Macro(..) => return self.visit_macro_invoc(ii.id),
|
||||
};
|
||||
|
||||
let def = self.create_def(ii.id, def_data, ii.span);
|
||||
|
|
|
@ -806,7 +806,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
|||
this.with_generic_param_rib(&trait_item.generics, AssocItemRibKind,
|
||||
|this| {
|
||||
match trait_item.kind {
|
||||
TraitItemKind::Const(ref ty, ref default) => {
|
||||
AssocItemKind::Const(ref ty, ref default) => {
|
||||
this.visit_ty(ty);
|
||||
|
||||
// Only impose the restrictions of
|
||||
|
@ -818,13 +818,13 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
|||
});
|
||||
}
|
||||
}
|
||||
TraitItemKind::Method(_, _) => {
|
||||
AssocItemKind::Fn(_, _) => {
|
||||
visit::walk_trait_item(this, trait_item)
|
||||
}
|
||||
TraitItemKind::Type(..) => {
|
||||
AssocItemKind::TyAlias(..) => {
|
||||
visit::walk_trait_item(this, trait_item)
|
||||
}
|
||||
TraitItemKind::Macro(_) => {
|
||||
AssocItemKind::Macro(_) => {
|
||||
panic!("unexpanded macro in resolve!")
|
||||
}
|
||||
};
|
||||
|
@ -989,13 +989,13 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
|||
/// When evaluating a `trait` use its associated types' idents for suggestionsa in E0412.
|
||||
fn with_trait_items<T>(
|
||||
&mut self,
|
||||
trait_items: &Vec<TraitItem>,
|
||||
trait_items: &Vec<AssocItem>,
|
||||
f: impl FnOnce(&mut Self) -> T,
|
||||
) -> T {
|
||||
let trait_assoc_types = replace(
|
||||
&mut self.diagnostic_metadata.current_trait_assoc_types,
|
||||
trait_items.iter().filter_map(|item| match &item.kind {
|
||||
TraitItemKind::Type(bounds, _) if bounds.len() == 0 => Some(item.ident),
|
||||
AssocItemKind::TyAlias(bounds, _) if bounds.len() == 0 => Some(item.ident),
|
||||
_ => None,
|
||||
}).collect(),
|
||||
);
|
||||
|
@ -1063,7 +1063,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
|||
opt_trait_reference: &Option<TraitRef>,
|
||||
self_type: &Ty,
|
||||
item_id: NodeId,
|
||||
impl_items: &[ImplItem]) {
|
||||
impl_items: &[AssocItem]) {
|
||||
debug!("resolve_implementation");
|
||||
// If applicable, create a rib for the type parameters.
|
||||
self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
|
||||
|
@ -1092,9 +1092,9 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
|||
|this| {
|
||||
use crate::ResolutionError::*;
|
||||
match impl_item.kind {
|
||||
ImplItemKind::Const(..) => {
|
||||
AssocItemKind::Const(..) => {
|
||||
debug!(
|
||||
"resolve_implementation ImplItemKind::Const",
|
||||
"resolve_implementation AssocItemKind::Const",
|
||||
);
|
||||
// If this is a trait impl, ensure the const
|
||||
// exists in trait
|
||||
|
@ -1109,7 +1109,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
|||
visit::walk_impl_item(this, impl_item)
|
||||
});
|
||||
}
|
||||
ImplItemKind::Method(..) => {
|
||||
AssocItemKind::Fn(..) => {
|
||||
// If this is a trait impl, ensure the method
|
||||
// exists in trait
|
||||
this.check_trait_item(impl_item.ident,
|
||||
|
@ -1119,7 +1119,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
|||
|
||||
visit::walk_impl_item(this, impl_item);
|
||||
}
|
||||
ImplItemKind::TyAlias(ref ty) => {
|
||||
AssocItemKind::TyAlias(_, Some(ref ty)) => {
|
||||
// If this is a trait impl, ensure the type
|
||||
// exists in trait
|
||||
this.check_trait_item(impl_item.ident,
|
||||
|
@ -1129,7 +1129,8 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
|||
|
||||
this.visit_ty(ty);
|
||||
}
|
||||
ImplItemKind::Macro(_) =>
|
||||
AssocItemKind::TyAlias(_, None) => {}
|
||||
AssocItemKind::Macro(_) =>
|
||||
panic!("unexpanded macro in resolve!"),
|
||||
}
|
||||
});
|
||||
|
|
|
@ -676,7 +676,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
|
|||
generics: &'l ast::Generics,
|
||||
trait_ref: &'l Option<ast::TraitRef>,
|
||||
typ: &'l ast::Ty,
|
||||
impl_items: &'l [ast::ImplItem],
|
||||
impl_items: &'l [ast::AssocItem],
|
||||
) {
|
||||
if let Some(impl_data) = self.save_ctxt.get_item_data(item) {
|
||||
if !self.span.filter_generated(item.span) {
|
||||
|
@ -707,7 +707,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
|
|||
item: &'l ast::Item,
|
||||
generics: &'l ast::Generics,
|
||||
trait_refs: &'l ast::GenericBounds,
|
||||
methods: &'l [ast::TraitItem],
|
||||
methods: &'l [ast::AssocItem],
|
||||
) {
|
||||
let name = item.ident.to_string();
|
||||
let qualname = format!("::{}",
|
||||
|
@ -811,9 +811,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
|
|||
match **generic_args {
|
||||
ast::GenericArgs::AngleBracketed(ref data) => {
|
||||
for arg in &data.args {
|
||||
match arg {
|
||||
ast::GenericArg::Type(ty) => self.visit_ty(ty),
|
||||
_ => {}
|
||||
if let ast::GenericArg::Type(ty) = arg {
|
||||
self.visit_ty(ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -821,8 +820,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
|
|||
for t in &data.inputs {
|
||||
self.visit_ty(t);
|
||||
}
|
||||
if let Some(ref t) = data.output {
|
||||
self.visit_ty(t);
|
||||
if let ast::FunctionRetTy::Ty(ty) = &data.output {
|
||||
self.visit_ty(ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1030,11 +1029,11 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
|
|||
// }
|
||||
}
|
||||
|
||||
fn process_trait_item(&mut self, trait_item: &'l ast::TraitItem, trait_id: DefId) {
|
||||
fn process_trait_item(&mut self, trait_item: &'l ast::AssocItem, trait_id: DefId) {
|
||||
self.process_macro_use(trait_item.span);
|
||||
let vis_span = trait_item.span.shrink_to_lo();
|
||||
match trait_item.kind {
|
||||
ast::TraitItemKind::Const(ref ty, ref expr) => {
|
||||
ast::AssocItemKind::Const(ref ty, ref expr) => {
|
||||
self.process_assoc_const(
|
||||
trait_item.id,
|
||||
trait_item.ident,
|
||||
|
@ -1045,7 +1044,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
|
|||
&trait_item.attrs,
|
||||
);
|
||||
}
|
||||
ast::TraitItemKind::Method(ref sig, ref body) => {
|
||||
ast::AssocItemKind::Fn(ref sig, ref body) => {
|
||||
self.process_method(
|
||||
sig,
|
||||
body.as_ref().map(|x| &**x),
|
||||
|
@ -1056,7 +1055,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
|
|||
trait_item.span,
|
||||
);
|
||||
}
|
||||
ast::TraitItemKind::Type(ref bounds, ref default_ty) => {
|
||||
ast::AssocItemKind::TyAlias(ref bounds, ref default_ty) => {
|
||||
// FIXME do something with _bounds (for type refs)
|
||||
let name = trait_item.ident.name.to_string();
|
||||
let qualname = format!("::{}",
|
||||
|
@ -1098,28 +1097,28 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
|
|||
self.visit_ty(default_ty)
|
||||
}
|
||||
}
|
||||
ast::TraitItemKind::Macro(_) => {}
|
||||
ast::AssocItemKind::Macro(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn process_impl_item(&mut self, impl_item: &'l ast::ImplItem, impl_id: DefId) {
|
||||
fn process_impl_item(&mut self, impl_item: &'l ast::AssocItem, impl_id: DefId) {
|
||||
self.process_macro_use(impl_item.span);
|
||||
match impl_item.kind {
|
||||
ast::ImplItemKind::Const(ref ty, ref expr) => {
|
||||
ast::AssocItemKind::Const(ref ty, ref expr) => {
|
||||
self.process_assoc_const(
|
||||
impl_item.id,
|
||||
impl_item.ident,
|
||||
&ty,
|
||||
Some(expr),
|
||||
expr.as_deref(),
|
||||
impl_id,
|
||||
impl_item.vis.clone(),
|
||||
&impl_item.attrs,
|
||||
);
|
||||
}
|
||||
ast::ImplItemKind::Method(ref sig, ref body) => {
|
||||
ast::AssocItemKind::Fn(ref sig, ref body) => {
|
||||
self.process_method(
|
||||
sig,
|
||||
Some(body),
|
||||
body.as_deref(),
|
||||
impl_item.id,
|
||||
impl_item.ident,
|
||||
&impl_item.generics,
|
||||
|
@ -1127,13 +1126,14 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
|
|||
impl_item.span,
|
||||
);
|
||||
}
|
||||
ast::ImplItemKind::TyAlias(ref ty) => {
|
||||
ast::AssocItemKind::TyAlias(_, None) => {}
|
||||
ast::AssocItemKind::TyAlias(_, Some(ref ty)) => {
|
||||
// FIXME: uses of the assoc type should ideally point to this
|
||||
// 'def' and the name here should be a ref to the def in the
|
||||
// trait.
|
||||
self.visit_ty(ty)
|
||||
}
|
||||
ast::ImplItemKind::Macro(_) => {}
|
||||
ast::AssocItemKind::Macro(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -469,22 +469,48 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
(Some(t_from), Some(t_cast)) => (t_from, t_cast),
|
||||
// Function item types may need to be reified before casts.
|
||||
(None, Some(t_cast)) => {
|
||||
if let ty::FnDef(..) = self.expr_ty.kind {
|
||||
// Attempt a coercion to a fn pointer type.
|
||||
let f = self.expr_ty.fn_sig(fcx.tcx);
|
||||
let res = fcx.try_coerce(self.expr,
|
||||
self.expr_ty,
|
||||
fcx.tcx.mk_fn_ptr(f),
|
||||
AllowTwoPhase::No);
|
||||
if let Err(TypeError::IntrinsicCast) = res {
|
||||
return Err(CastError::IllegalCast);
|
||||
match self.expr_ty.kind {
|
||||
ty::FnDef(..) => {
|
||||
// Attempt a coercion to a fn pointer type.
|
||||
let f = self.expr_ty.fn_sig(fcx.tcx);
|
||||
let res = fcx.try_coerce(self.expr,
|
||||
self.expr_ty,
|
||||
fcx.tcx.mk_fn_ptr(f),
|
||||
AllowTwoPhase::No);
|
||||
if let Err(TypeError::IntrinsicCast) = res {
|
||||
return Err(CastError::IllegalCast);
|
||||
}
|
||||
if res.is_err() {
|
||||
return Err(CastError::NonScalar);
|
||||
}
|
||||
(FnPtr, t_cast)
|
||||
}
|
||||
if res.is_err() {
|
||||
return Err(CastError::NonScalar);
|
||||
// Special case some errors for references, and check for
|
||||
// array-ptr-casts. `Ref` is not a CastTy because the cast
|
||||
// is split into a coercion to a pointer type, followed by
|
||||
// a cast.
|
||||
ty::Ref(_, inner_ty, mutbl) => {
|
||||
return match t_cast {
|
||||
Int(_) | Float => match inner_ty.kind {
|
||||
ty::Int(_) |
|
||||
ty::Uint(_) |
|
||||
ty::Float(_) |
|
||||
ty::Infer(ty::InferTy::IntVar(_)) |
|
||||
ty::Infer(ty::InferTy::FloatVar(_)) => {
|
||||
Err(CastError::NeedDeref)
|
||||
}
|
||||
_ => Err(CastError::NeedViaPtr),
|
||||
}
|
||||
// array-ptr-cast
|
||||
Ptr(mt) => self.check_ref_cast(
|
||||
fcx,
|
||||
TypeAndMut { mutbl, ty: inner_ty },
|
||||
mt,
|
||||
),
|
||||
_ => Err(CastError::NonScalar),
|
||||
};
|
||||
}
|
||||
(FnPtr, t_cast)
|
||||
} else {
|
||||
return Err(CastError::NonScalar);
|
||||
_ => return Err(CastError::NonScalar),
|
||||
}
|
||||
}
|
||||
_ => return Err(CastError::NonScalar),
|
||||
|
@ -492,7 +518,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
|
||||
match (t_from, t_cast) {
|
||||
// These types have invariants! can't cast into them.
|
||||
(_, RPtr(_)) | (_, Int(CEnum)) | (_, FnPtr) => Err(CastError::NonScalar),
|
||||
(_, Int(CEnum)) | (_, FnPtr) => Err(CastError::NonScalar),
|
||||
|
||||
// * -> Bool
|
||||
(_, Int(Bool)) => Err(CastError::CastToBool),
|
||||
|
@ -517,28 +543,10 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
(Ptr(m_e), Ptr(m_c)) => self.check_ptr_ptr_cast(fcx, m_e, m_c), // ptr-ptr-cast
|
||||
(Ptr(m_expr), Int(_)) => self.check_ptr_addr_cast(fcx, m_expr), // ptr-addr-cast
|
||||
(FnPtr, Int(_)) => Ok(CastKind::FnPtrAddrCast),
|
||||
(RPtr(p), Int(_)) |
|
||||
(RPtr(p), Float) => {
|
||||
match p.ty.kind {
|
||||
ty::Int(_) |
|
||||
ty::Uint(_) |
|
||||
ty::Float(_) => {
|
||||
Err(CastError::NeedDeref)
|
||||
}
|
||||
ty::Infer(t) => {
|
||||
match t {
|
||||
ty::InferTy::IntVar(_) |
|
||||
ty::InferTy::FloatVar(_) => Err(CastError::NeedDeref),
|
||||
_ => Err(CastError::NeedViaPtr),
|
||||
}
|
||||
}
|
||||
_ => Err(CastError::NeedViaPtr),
|
||||
}
|
||||
}
|
||||
|
||||
// * -> ptr
|
||||
(Int(_), Ptr(mt)) => self.check_addr_ptr_cast(fcx, mt), // addr-ptr-cast
|
||||
(FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt),
|
||||
(RPtr(rmt), Ptr(mt)) => self.check_ref_cast(fcx, rmt, mt), // array-ptr-cast
|
||||
|
||||
// prim -> prim
|
||||
(Int(CEnum), Int(_)) => Ok(CastKind::EnumCast),
|
||||
|
|
|
@ -3880,36 +3880,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
call_sp: Span,
|
||||
args: &'tcx [hir::Expr],
|
||||
) {
|
||||
if !call_sp.desugaring_kind().is_some() {
|
||||
// We *do not* do this for desugared call spans to keep good diagnostics when involving
|
||||
// the `?` operator.
|
||||
for error in errors {
|
||||
if let ty::Predicate::Trait(predicate) = error.obligation.predicate {
|
||||
// Collect the argument position for all arguments that could have caused this
|
||||
// `FulfillmentError`.
|
||||
let mut referenced_in = final_arg_types.iter()
|
||||
.map(|(i, checked_ty, _)| (i, checked_ty))
|
||||
.chain(final_arg_types.iter().map(|(i, _, coerced_ty)| (i, coerced_ty)))
|
||||
.flat_map(|(i, ty)| {
|
||||
let ty = self.resolve_vars_if_possible(ty);
|
||||
// We walk the argument type because the argument's type could have
|
||||
// been `Option<T>`, but the `FulfillmentError` references `T`.
|
||||
ty.walk()
|
||||
.filter(|&ty| ty == predicate.skip_binder().self_ty())
|
||||
.map(move |_| *i)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
// We *do not* do this for desugared call spans to keep good diagnostics when involving
|
||||
// the `?` operator.
|
||||
if call_sp.desugaring_kind().is_some() {
|
||||
return
|
||||
}
|
||||
|
||||
// Both checked and coerced types could have matched, thus we need to remove
|
||||
// duplicates.
|
||||
referenced_in.dedup();
|
||||
for error in errors {
|
||||
// Only if the cause is somewhere inside the expression we want try to point at arg.
|
||||
// Otherwise, it means that the cause is somewhere else and we should not change
|
||||
// anything because we can break the correct span.
|
||||
if !call_sp.contains(error.obligation.cause.span) {
|
||||
continue
|
||||
}
|
||||
|
||||
if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) {
|
||||
// We make sure that only *one* argument matches the obligation failure
|
||||
// and we assign the obligation's span to its expression's.
|
||||
error.obligation.cause.span = args[ref_in].span;
|
||||
error.points_at_arg_span = true;
|
||||
}
|
||||
if let ty::Predicate::Trait(predicate) = error.obligation.predicate {
|
||||
// Collect the argument position for all arguments that could have caused this
|
||||
// `FulfillmentError`.
|
||||
let mut referenced_in = final_arg_types.iter()
|
||||
.map(|(i, checked_ty, _)| (i, checked_ty))
|
||||
.chain(final_arg_types.iter().map(|(i, _, coerced_ty)| (i, coerced_ty)))
|
||||
.flat_map(|(i, ty)| {
|
||||
let ty = self.resolve_vars_if_possible(ty);
|
||||
// We walk the argument type because the argument's type could have
|
||||
// been `Option<T>`, but the `FulfillmentError` references `T`.
|
||||
ty.walk()
|
||||
.filter(|&ty| ty == predicate.skip_binder().self_ty())
|
||||
.map(move |_| *i)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Both checked and coerced types could have matched, thus we need to remove
|
||||
// duplicates.
|
||||
referenced_in.dedup();
|
||||
|
||||
if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) {
|
||||
// We make sure that only *one* argument matches the obligation failure
|
||||
// and we assign the obligation's span to its expression's.
|
||||
error.obligation.cause.span = args[ref_in].span;
|
||||
error.points_at_arg_span = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -254,7 +254,7 @@ pub struct ParenthesizedArgs {
|
|||
pub inputs: Vec<P<Ty>>,
|
||||
|
||||
/// `C`
|
||||
pub output: Option<P<Ty>>,
|
||||
pub output: FunctionRetTy,
|
||||
}
|
||||
|
||||
impl ParenthesizedArgs {
|
||||
|
@ -728,13 +728,13 @@ impl Mutability {
|
|||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[derive(RustcEncodable, RustcDecodable, HashStable_Generic)]
|
||||
pub enum BorrowKind {
|
||||
/// A raw borrow, `&raw const $expr` or `&raw mut $expr`.
|
||||
/// The resulting type is either `*const T` or `*mut T`
|
||||
/// where `T = typeof($expr)`.
|
||||
Ref,
|
||||
/// A normal borrow, `&$expr` or `&mut $expr`.
|
||||
/// The resulting type is either `&'a T` or `&'a mut T`
|
||||
/// where `T = typeof($expr)` and `'a` is some lifetime.
|
||||
Ref,
|
||||
/// A raw borrow, `&raw const $expr` or `&raw mut $expr`.
|
||||
/// The resulting type is either `*const T` or `*mut T`
|
||||
/// where `T = typeof($expr)`.
|
||||
Raw,
|
||||
}
|
||||
|
||||
|
@ -1603,35 +1603,10 @@ pub struct FnSig {
|
|||
pub decl: P<FnDecl>,
|
||||
}
|
||||
|
||||
/// Represents an item declaration within a trait declaration,
|
||||
/// possibly including a default implementation. A trait item is
|
||||
/// either required (meaning it doesn't have an implementation, just a
|
||||
/// signature) or provided (meaning it has a default implementation).
|
||||
/// Represents associated items.
|
||||
/// These include items in `impl` and `trait` definitions.
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub struct TraitItem {
|
||||
pub attrs: Vec<Attribute>,
|
||||
pub id: NodeId,
|
||||
pub span: Span,
|
||||
pub vis: Visibility,
|
||||
pub ident: Ident,
|
||||
|
||||
pub generics: Generics,
|
||||
pub kind: TraitItemKind,
|
||||
/// See `Item::tokens` for what this is.
|
||||
pub tokens: Option<TokenStream>,
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub enum TraitItemKind {
|
||||
Const(P<Ty>, Option<P<Expr>>),
|
||||
Method(FnSig, Option<P<Block>>),
|
||||
Type(GenericBounds, Option<P<Ty>>),
|
||||
Macro(Mac),
|
||||
}
|
||||
|
||||
/// Represents anything within an `impl` block.
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub struct ImplItem {
|
||||
pub struct AssocItem {
|
||||
pub attrs: Vec<Attribute>,
|
||||
pub id: NodeId,
|
||||
pub span: Span,
|
||||
|
@ -1640,17 +1615,31 @@ pub struct ImplItem {
|
|||
|
||||
pub defaultness: Defaultness,
|
||||
pub generics: Generics,
|
||||
pub kind: ImplItemKind,
|
||||
pub kind: AssocItemKind,
|
||||
/// See `Item::tokens` for what this is.
|
||||
pub tokens: Option<TokenStream>,
|
||||
}
|
||||
|
||||
/// Represents various kinds of content within an `impl`.
|
||||
///
|
||||
/// The term "provided" in the variants below refers to the item having a default
|
||||
/// definition / body. Meanwhile, a "required" item lacks a definition / body.
|
||||
/// In an implementation, all items must be provided.
|
||||
/// The `Option`s below denote the bodies, where `Some(_)`
|
||||
/// means "provided" and conversely `None` means "required".
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub enum ImplItemKind {
|
||||
Const(P<Ty>, P<Expr>),
|
||||
Method(FnSig, P<Block>),
|
||||
TyAlias(P<Ty>),
|
||||
pub enum AssocItemKind {
|
||||
/// An associated constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`.
|
||||
/// If `def` is parsed, then the associated constant is provided, and otherwise required.
|
||||
Const(P<Ty>, Option<P<Expr>>),
|
||||
|
||||
/// An associated function.
|
||||
Fn(FnSig, Option<P<Block>>),
|
||||
|
||||
/// An associated type.
|
||||
TyAlias(GenericBounds, Option<P<Ty>>),
|
||||
|
||||
/// A macro expanding to an associated item.
|
||||
Macro(Mac),
|
||||
}
|
||||
|
||||
|
@ -2189,7 +2178,7 @@ impl fmt::Debug for ImplPolarity {
|
|||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub enum FunctionRetTy {
|
||||
pub enum FunctionRetTy { // FIXME(Centril): Rename to `FnRetTy` and in HIR also.
|
||||
/// Returns type is not specified.
|
||||
///
|
||||
/// Functions default to `()` and closures default to inference.
|
||||
|
@ -2602,7 +2591,7 @@ pub enum ItemKind {
|
|||
/// A trait declaration (`trait`).
|
||||
///
|
||||
/// E.g., `trait Foo { .. }`, `trait Foo<T> { .. }` or `auto trait Foo {}`.
|
||||
Trait(IsAuto, Unsafety, Generics, GenericBounds, Vec<TraitItem>),
|
||||
Trait(IsAuto, Unsafety, Generics, GenericBounds, Vec<AssocItem>),
|
||||
/// Trait alias
|
||||
///
|
||||
/// E.g., `trait Foo = Bar + Quux;`.
|
||||
|
@ -2617,7 +2606,7 @@ pub enum ItemKind {
|
|||
Generics,
|
||||
Option<TraitRef>, // (optional) trait this impl implements
|
||||
P<Ty>, // self
|
||||
Vec<ImplItem>,
|
||||
Vec<AssocItem>,
|
||||
),
|
||||
/// A macro invocation.
|
||||
///
|
||||
|
|
|
@ -749,6 +749,6 @@ macro_rules! derive_has_attrs {
|
|||
}
|
||||
|
||||
derive_has_attrs! {
|
||||
Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm,
|
||||
Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::AssocItem, ast::Arm,
|
||||
ast::Field, ast::FieldPat, ast::Variant, ast::Param
|
||||
}
|
||||
|
|
|
@ -589,54 +589,52 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
visit::walk_assoc_ty_constraint(self, constraint)
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
|
||||
fn visit_trait_item(&mut self, ti: &'a ast::AssocItem) {
|
||||
match ti.kind {
|
||||
ast::TraitItemKind::Method(ref sig, ref block) => {
|
||||
ast::AssocItemKind::Fn(ref sig, ref block) => {
|
||||
if block.is_none() {
|
||||
self.check_extern(sig.header.ext);
|
||||
}
|
||||
if sig.decl.c_variadic() {
|
||||
gate_feature_post!(&self, c_variadic, ti.span,
|
||||
"C-variadic functions are unstable");
|
||||
}
|
||||
if sig.header.constness.node == ast::Constness::Const {
|
||||
gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
|
||||
}
|
||||
}
|
||||
ast::TraitItemKind::Type(_, ref default) => {
|
||||
if let Some(ty) = default {
|
||||
self.check_impl_trait(ty);
|
||||
gate_feature_post!(&self, associated_type_defaults, ti.span,
|
||||
"associated type defaults are unstable");
|
||||
ast::AssocItemKind::TyAlias(_, ref default) => {
|
||||
if let Some(_) = default {
|
||||
gate_feature_post!(
|
||||
&self, associated_type_defaults, ti.span,
|
||||
"associated type defaults are unstable"
|
||||
);
|
||||
}
|
||||
self.check_gat(&ti.generics, ti.span);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
visit::walk_trait_item(self, ti)
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
|
||||
fn visit_assoc_item(&mut self, ii: &'a ast::AssocItem) {
|
||||
if ii.defaultness == ast::Defaultness::Default {
|
||||
gate_feature_post!(&self, specialization,
|
||||
ii.span,
|
||||
"specialization is unstable");
|
||||
gate_feature_post!(&self, specialization, ii.span, "specialization is unstable");
|
||||
}
|
||||
|
||||
match ii.kind {
|
||||
ast::ImplItemKind::Method(ref sig, _) => {
|
||||
ast::AssocItemKind::Fn(ref sig, _) => {
|
||||
if sig.decl.c_variadic() {
|
||||
gate_feature_post!(&self, c_variadic, ii.span,
|
||||
"C-variadic functions are unstable");
|
||||
gate_feature_post!(
|
||||
&self, c_variadic, ii.span,
|
||||
"C-variadic functions are unstable"
|
||||
);
|
||||
}
|
||||
}
|
||||
ast::ImplItemKind::TyAlias(ref ty) => {
|
||||
self.check_impl_trait(ty);
|
||||
ast::AssocItemKind::TyAlias(_, ref ty) => {
|
||||
if let Some(ty) = ty {
|
||||
self.check_impl_trait(ty);
|
||||
}
|
||||
self.check_gat(&ii.generics, ii.span);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
visit::walk_impl_item(self, ii)
|
||||
visit::walk_assoc_item(self, ii)
|
||||
}
|
||||
|
||||
fn visit_vis(&mut self, vis: &'a ast::Visibility) {
|
||||
|
|
|
@ -103,12 +103,12 @@ pub trait MutVisitor: Sized {
|
|||
noop_visit_item_kind(i, self);
|
||||
}
|
||||
|
||||
fn flat_map_trait_item(&mut self, i: TraitItem) -> SmallVec<[TraitItem; 1]> {
|
||||
noop_flat_map_trait_item(i, self)
|
||||
fn flat_map_trait_item(&mut self, i: AssocItem) -> SmallVec<[AssocItem; 1]> {
|
||||
noop_flat_map_assoc_item(i, self)
|
||||
}
|
||||
|
||||
fn flat_map_impl_item(&mut self, i: ImplItem) -> SmallVec<[ImplItem; 1]> {
|
||||
noop_flat_map_impl_item(i, self)
|
||||
fn flat_map_impl_item(&mut self, i: AssocItem) -> SmallVec<[AssocItem; 1]> {
|
||||
noop_flat_map_assoc_item(i, self)
|
||||
}
|
||||
|
||||
fn visit_fn_decl(&mut self, d: &mut P<FnDecl>) {
|
||||
|
@ -553,7 +553,7 @@ pub fn noop_visit_parenthesized_parameter_data<T: MutVisitor>(args: &mut Parenth
|
|||
vis: &mut T) {
|
||||
let ParenthesizedArgs { inputs, output, span } = args;
|
||||
visit_vec(inputs, |input| vis.visit_ty(input));
|
||||
visit_opt(output, |output| vis.visit_ty(output));
|
||||
noop_visit_fn_ret_ty(output, vis);
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
|
@ -742,7 +742,11 @@ pub fn noop_visit_asyncness<T: MutVisitor>(asyncness: &mut IsAsync, vis: &mut T)
|
|||
pub fn noop_visit_fn_decl<T: MutVisitor>(decl: &mut P<FnDecl>, vis: &mut T) {
|
||||
let FnDecl { inputs, output } = decl.deref_mut();
|
||||
inputs.flat_map_in_place(|param| vis.flat_map_param(param));
|
||||
match output {
|
||||
noop_visit_fn_ret_ty(output, vis);
|
||||
}
|
||||
|
||||
pub fn noop_visit_fn_ret_ty<T: MutVisitor>(fn_ret_ty: &mut FunctionRetTy, vis: &mut T) {
|
||||
match fn_ret_ty {
|
||||
FunctionRetTy::Default(span) => vis.visit_span(span),
|
||||
FunctionRetTy::Ty(ty) => vis.visit_ty(ty),
|
||||
}
|
||||
|
@ -936,41 +940,10 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn noop_flat_map_trait_item<T: MutVisitor>(mut item: TraitItem, visitor: &mut T)
|
||||
-> SmallVec<[TraitItem; 1]>
|
||||
pub fn noop_flat_map_assoc_item<T: MutVisitor>(mut item: AssocItem, visitor: &mut T)
|
||||
-> SmallVec<[AssocItem; 1]>
|
||||
{
|
||||
let TraitItem { id, ident, vis, attrs, generics, kind, span, tokens: _ } = &mut item;
|
||||
visitor.visit_id(id);
|
||||
visitor.visit_ident(ident);
|
||||
visitor.visit_vis(vis);
|
||||
visit_attrs(attrs, visitor);
|
||||
visitor.visit_generics(generics);
|
||||
match kind {
|
||||
TraitItemKind::Const(ty, default) => {
|
||||
visitor.visit_ty(ty);
|
||||
visit_opt(default, |default| visitor.visit_expr(default));
|
||||
}
|
||||
TraitItemKind::Method(sig, body) => {
|
||||
visit_fn_sig(sig, visitor);
|
||||
visit_opt(body, |body| visitor.visit_block(body));
|
||||
}
|
||||
TraitItemKind::Type(bounds, default) => {
|
||||
visit_bounds(bounds, visitor);
|
||||
visit_opt(default, |default| visitor.visit_ty(default));
|
||||
}
|
||||
TraitItemKind::Macro(mac) => {
|
||||
visitor.visit_mac(mac);
|
||||
}
|
||||
}
|
||||
visitor.visit_span(span);
|
||||
|
||||
smallvec![item]
|
||||
}
|
||||
|
||||
pub fn noop_flat_map_impl_item<T: MutVisitor>(mut item: ImplItem, visitor: &mut T)
|
||||
-> SmallVec<[ImplItem; 1]>
|
||||
{
|
||||
let ImplItem { id, ident, vis, defaultness: _, attrs, generics, kind, span, tokens: _ } =
|
||||
let AssocItem { id, ident, vis, defaultness: _, attrs, generics, kind, span, tokens: _ } =
|
||||
&mut item;
|
||||
visitor.visit_id(id);
|
||||
visitor.visit_ident(ident);
|
||||
|
@ -978,16 +951,19 @@ pub fn noop_flat_map_impl_item<T: MutVisitor>(mut item: ImplItem, visitor: &mut
|
|||
visit_attrs(attrs, visitor);
|
||||
visitor.visit_generics(generics);
|
||||
match kind {
|
||||
ImplItemKind::Const(ty, expr) => {
|
||||
AssocItemKind::Const(ty, expr) => {
|
||||
visitor.visit_ty(ty);
|
||||
visitor.visit_expr(expr);
|
||||
visit_opt(expr, |expr| visitor.visit_expr(expr));
|
||||
}
|
||||
ImplItemKind::Method(sig, body) => {
|
||||
AssocItemKind::Fn(sig, body) => {
|
||||
visit_fn_sig(sig, visitor);
|
||||
visitor.visit_block(body);
|
||||
visit_opt(body, |body| visitor.visit_block(body));
|
||||
}
|
||||
ImplItemKind::TyAlias(ty) => visitor.visit_ty(ty),
|
||||
ImplItemKind::Macro(mac) => visitor.visit_mac(mac),
|
||||
AssocItemKind::TyAlias(bounds, ty) => {
|
||||
visit_bounds(bounds, visitor);
|
||||
visit_opt(ty, |ty| visitor.visit_ty(ty));
|
||||
}
|
||||
AssocItemKind::Macro(mac) => visitor.visit_mac(mac),
|
||||
}
|
||||
visitor.visit_span(span);
|
||||
|
||||
|
|
|
@ -335,8 +335,8 @@ pub fn nonterminal_to_string(nt: &Nonterminal) -> String {
|
|||
token::NtLifetime(e) => e.to_string(),
|
||||
token::NtLiteral(ref e) => expr_to_string(e),
|
||||
token::NtTT(ref tree) => tt_to_string(tree.clone()),
|
||||
token::NtImplItem(ref e) => impl_item_to_string(e),
|
||||
token::NtTraitItem(ref e) => trait_item_to_string(e),
|
||||
// FIXME(Centril): merge these variants.
|
||||
token::NtImplItem(ref e) | token::NtTraitItem(ref e) => assoc_item_to_string(e),
|
||||
token::NtVis(ref e) => vis_to_string(e),
|
||||
token::NtForeignItem(ref e) => foreign_item_to_string(e),
|
||||
}
|
||||
|
@ -374,12 +374,8 @@ pub fn item_to_string(i: &ast::Item) -> String {
|
|||
to_string(|s| s.print_item(i))
|
||||
}
|
||||
|
||||
fn impl_item_to_string(i: &ast::ImplItem) -> String {
|
||||
to_string(|s| s.print_impl_item(i))
|
||||
}
|
||||
|
||||
fn trait_item_to_string(i: &ast::TraitItem) -> String {
|
||||
to_string(|s| s.print_trait_item(i))
|
||||
fn assoc_item_to_string(i: &ast::AssocItem) -> String {
|
||||
to_string(|s| s.print_assoc_item(i))
|
||||
}
|
||||
|
||||
pub fn generic_params_to_string(generic_params: &[ast::GenericParam]) -> String {
|
||||
|
@ -887,17 +883,9 @@ impl<'a> PrintState<'a> for State<'a> {
|
|||
|
||||
ast::GenericArgs::Parenthesized(ref data) => {
|
||||
self.s.word("(");
|
||||
self.commasep(
|
||||
Inconsistent,
|
||||
&data.inputs,
|
||||
|s, ty| s.print_type(ty));
|
||||
self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(ty));
|
||||
self.s.word(")");
|
||||
|
||||
if let Some(ref ty) = data.output {
|
||||
self.space_if_not_bol();
|
||||
self.word_space("->");
|
||||
self.print_type(ty);
|
||||
}
|
||||
self.print_fn_ret_ty(&data.output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1128,16 +1116,15 @@ impl<'a> State<'a> {
|
|||
self.s.word(";")
|
||||
}
|
||||
|
||||
fn print_associated_type(&mut self,
|
||||
ident: ast::Ident,
|
||||
bounds: Option<&ast::GenericBounds>,
|
||||
ty: Option<&ast::Ty>)
|
||||
{
|
||||
fn print_associated_type(
|
||||
&mut self,
|
||||
ident: ast::Ident,
|
||||
bounds: &ast::GenericBounds,
|
||||
ty: Option<&ast::Ty>,
|
||||
) {
|
||||
self.word_space("type");
|
||||
self.print_ident(ident);
|
||||
if let Some(bounds) = bounds {
|
||||
self.print_type_bounds(":", bounds);
|
||||
}
|
||||
self.print_type_bounds(":", bounds);
|
||||
if let Some(ty) = ty {
|
||||
self.s.space();
|
||||
self.word_space("=");
|
||||
|
@ -1310,7 +1297,7 @@ impl<'a> State<'a> {
|
|||
self.bopen();
|
||||
self.print_inner_attributes(&item.attrs);
|
||||
for impl_item in impl_items {
|
||||
self.print_impl_item(impl_item);
|
||||
self.print_assoc_item(impl_item);
|
||||
}
|
||||
self.bclose(item.span);
|
||||
}
|
||||
|
@ -1337,7 +1324,7 @@ impl<'a> State<'a> {
|
|||
self.s.word(" ");
|
||||
self.bopen();
|
||||
for trait_item in trait_items {
|
||||
self.print_trait_item(trait_item);
|
||||
self.print_assoc_item(trait_item);
|
||||
}
|
||||
self.bclose(item.span);
|
||||
}
|
||||
|
@ -1531,92 +1518,39 @@ impl<'a> State<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
crate fn print_method_sig(&mut self,
|
||||
ident: ast::Ident,
|
||||
generics: &ast::Generics,
|
||||
m: &ast::FnSig,
|
||||
vis: &ast::Visibility)
|
||||
{
|
||||
self.print_fn(&m.decl,
|
||||
m.header,
|
||||
Some(ident),
|
||||
&generics,
|
||||
vis)
|
||||
}
|
||||
|
||||
crate fn print_trait_item(&mut self, ti: &ast::TraitItem)
|
||||
{
|
||||
self.ann.pre(self, AnnNode::SubItem(ti.id));
|
||||
crate fn print_assoc_item(&mut self, item: &ast::AssocItem) {
|
||||
self.ann.pre(self, AnnNode::SubItem(item.id));
|
||||
self.hardbreak_if_not_bol();
|
||||
self.maybe_print_comment(ti.span.lo());
|
||||
self.print_outer_attributes(&ti.attrs);
|
||||
match ti.kind {
|
||||
ast::TraitItemKind::Const(ref ty, ref default) => {
|
||||
self.print_associated_const(
|
||||
ti.ident,
|
||||
ty,
|
||||
default.as_ref().map(|expr| &**expr),
|
||||
&source_map::respan(ti.span.shrink_to_lo(), ast::VisibilityKind::Inherited),
|
||||
);
|
||||
self.maybe_print_comment(item.span.lo());
|
||||
self.print_outer_attributes(&item.attrs);
|
||||
self.print_defaultness(item.defaultness);
|
||||
match &item.kind {
|
||||
ast::AssocItemKind::Const(ty, expr) => {
|
||||
self.print_associated_const(item.ident, ty, expr.as_deref(), &item.vis);
|
||||
}
|
||||
ast::TraitItemKind::Method(ref sig, ref body) => {
|
||||
ast::AssocItemKind::Fn(sig, body) => {
|
||||
if body.is_some() {
|
||||
self.head("");
|
||||
}
|
||||
self.print_method_sig(
|
||||
ti.ident,
|
||||
&ti.generics,
|
||||
sig,
|
||||
&source_map::respan(ti.span.shrink_to_lo(), ast::VisibilityKind::Inherited),
|
||||
);
|
||||
if let Some(ref body) = *body {
|
||||
self.print_fn(&sig.decl, sig.header, Some(item.ident), &item.generics, &item.vis);
|
||||
if let Some(body) = body {
|
||||
self.nbsp();
|
||||
self.print_block_with_attrs(body, &ti.attrs);
|
||||
self.print_block_with_attrs(body, &item.attrs);
|
||||
} else {
|
||||
self.s.word(";");
|
||||
}
|
||||
}
|
||||
ast::TraitItemKind::Type(ref bounds, ref default) => {
|
||||
self.print_associated_type(ti.ident, Some(bounds),
|
||||
default.as_ref().map(|ty| &**ty));
|
||||
ast::AssocItemKind::TyAlias(bounds, ty) => {
|
||||
self.print_associated_type(item.ident, bounds, ty.as_deref());
|
||||
}
|
||||
ast::TraitItemKind::Macro(ref mac) => {
|
||||
ast::AssocItemKind::Macro(mac) => {
|
||||
self.print_mac(mac);
|
||||
if mac.args.need_semicolon() {
|
||||
self.s.word(";");
|
||||
}
|
||||
}
|
||||
}
|
||||
self.ann.post(self, AnnNode::SubItem(ti.id))
|
||||
}
|
||||
|
||||
crate fn print_impl_item(&mut self, ii: &ast::ImplItem) {
|
||||
self.ann.pre(self, AnnNode::SubItem(ii.id));
|
||||
self.hardbreak_if_not_bol();
|
||||
self.maybe_print_comment(ii.span.lo());
|
||||
self.print_outer_attributes(&ii.attrs);
|
||||
self.print_defaultness(ii.defaultness);
|
||||
match ii.kind {
|
||||
ast::ImplItemKind::Const(ref ty, ref expr) => {
|
||||
self.print_associated_const(ii.ident, ty, Some(expr), &ii.vis);
|
||||
}
|
||||
ast::ImplItemKind::Method(ref sig, ref body) => {
|
||||
self.head("");
|
||||
self.print_method_sig(ii.ident, &ii.generics, sig, &ii.vis);
|
||||
self.nbsp();
|
||||
self.print_block_with_attrs(body, &ii.attrs);
|
||||
}
|
||||
ast::ImplItemKind::TyAlias(ref ty) => {
|
||||
self.print_associated_type(ii.ident, None, Some(ty));
|
||||
}
|
||||
ast::ImplItemKind::Macro(ref mac) => {
|
||||
self.print_mac(mac);
|
||||
if mac.args.need_semicolon() {
|
||||
self.s.word(";");
|
||||
}
|
||||
}
|
||||
}
|
||||
self.ann.post(self, AnnNode::SubItem(ii.id))
|
||||
self.ann.post(self, AnnNode::SubItem(item.id))
|
||||
}
|
||||
|
||||
crate fn print_stmt(&mut self, st: &ast::Stmt) {
|
||||
|
@ -2109,7 +2043,7 @@ impl<'a> State<'a> {
|
|||
self.print_asyncness(asyncness);
|
||||
self.print_capture_clause(capture_clause);
|
||||
|
||||
self.print_fn_block_params(decl);
|
||||
self.print_fn_params_and_ret(decl, true);
|
||||
self.s.space();
|
||||
self.print_expr(body);
|
||||
self.end(); // need to close a box
|
||||
|
@ -2540,36 +2474,16 @@ impl<'a> State<'a> {
|
|||
self.print_ident(name);
|
||||
}
|
||||
self.print_generic_params(&generics.params);
|
||||
self.print_fn_params_and_ret(decl);
|
||||
self.print_fn_params_and_ret(decl, false);
|
||||
self.print_where_clause(&generics.where_clause)
|
||||
}
|
||||
|
||||
crate fn print_fn_params_and_ret(&mut self, decl: &ast::FnDecl) {
|
||||
self.popen();
|
||||
self.commasep(Inconsistent, &decl.inputs, |s, param| s.print_param(param, false));
|
||||
self.pclose();
|
||||
|
||||
self.print_fn_output(decl)
|
||||
}
|
||||
|
||||
crate fn print_fn_block_params(&mut self, decl: &ast::FnDecl) {
|
||||
self.s.word("|");
|
||||
self.commasep(Inconsistent, &decl.inputs, |s, param| s.print_param(param, true));
|
||||
self.s.word("|");
|
||||
|
||||
if let ast::FunctionRetTy::Default(..) = decl.output {
|
||||
return;
|
||||
}
|
||||
|
||||
self.space_if_not_bol();
|
||||
self.word_space("->");
|
||||
match decl.output {
|
||||
ast::FunctionRetTy::Ty(ref ty) => {
|
||||
self.print_type(ty);
|
||||
self.maybe_print_comment(ty.span.lo())
|
||||
}
|
||||
ast::FunctionRetTy::Default(..) => unreachable!(),
|
||||
}
|
||||
crate fn print_fn_params_and_ret(&mut self, decl: &ast::FnDecl, is_closure: bool) {
|
||||
let (open, close) = if is_closure { ("|", "|") } else { ("(", ")") };
|
||||
self.word(open);
|
||||
self.commasep(Inconsistent, &decl.inputs, |s, param| s.print_param(param, is_closure));
|
||||
self.word(close);
|
||||
self.print_fn_ret_ty(&decl.output)
|
||||
}
|
||||
|
||||
crate fn print_movability(&mut self, movability: ast::Movability) {
|
||||
|
@ -2791,24 +2705,14 @@ impl<'a> State<'a> {
|
|||
self.end();
|
||||
}
|
||||
|
||||
crate fn print_fn_output(&mut self, decl: &ast::FnDecl) {
|
||||
if let ast::FunctionRetTy::Default(..) = decl.output {
|
||||
return;
|
||||
}
|
||||
|
||||
self.space_if_not_bol();
|
||||
self.ibox(INDENT_UNIT);
|
||||
self.word_space("->");
|
||||
match decl.output {
|
||||
ast::FunctionRetTy::Default(..) => unreachable!(),
|
||||
ast::FunctionRetTy::Ty(ref ty) =>
|
||||
self.print_type(ty),
|
||||
}
|
||||
self.end();
|
||||
|
||||
match decl.output {
|
||||
ast::FunctionRetTy::Ty(ref output) => self.maybe_print_comment(output.span.lo()),
|
||||
_ => {}
|
||||
crate fn print_fn_ret_ty(&mut self, fn_ret_ty: &ast::FunctionRetTy) {
|
||||
if let ast::FunctionRetTy::Ty(ty) = fn_ret_ty {
|
||||
self.space_if_not_bol();
|
||||
self.ibox(INDENT_UNIT);
|
||||
self.word_space("->");
|
||||
self.print_type(ty);
|
||||
self.end();
|
||||
self.maybe_print_comment(ty.span.lo());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -685,8 +685,8 @@ pub enum Nonterminal {
|
|||
// Used only for passing items to proc macro attributes (they are not
|
||||
// strictly necessary for that, `Annotatable` can be converted into
|
||||
// tokens directly, but doing that naively regresses pretty-printing).
|
||||
NtTraitItem(ast::TraitItem),
|
||||
NtImplItem(ast::ImplItem),
|
||||
NtTraitItem(ast::AssocItem),
|
||||
NtImplItem(ast::AssocItem),
|
||||
NtForeignItem(ast::ForeignItem),
|
||||
}
|
||||
|
||||
|
|
|
@ -73,13 +73,9 @@ impl<'ast> Visitor<'ast> for NodeCounter {
|
|||
self.count += 1;
|
||||
walk_fn(self, fk, fd, s)
|
||||
}
|
||||
fn visit_trait_item(&mut self, ti: &TraitItem) {
|
||||
fn visit_assoc_item(&mut self, ti: &AssocItem) {
|
||||
self.count += 1;
|
||||
walk_trait_item(self, ti)
|
||||
}
|
||||
fn visit_impl_item(&mut self, ii: &ImplItem) {
|
||||
self.count += 1;
|
||||
walk_impl_item(self, ii)
|
||||
walk_assoc_item(self, ti)
|
||||
}
|
||||
fn visit_trait_ref(&mut self, t: &TraitRef) {
|
||||
self.count += 1;
|
||||
|
|
|
@ -25,7 +25,7 @@ pub enum FnKind<'a> {
|
|||
ItemFn(Ident, &'a FnHeader, &'a Visibility, &'a Block),
|
||||
|
||||
/// E.g., `fn foo(&self)`.
|
||||
Method(Ident, &'a FnSig, Option<&'a Visibility>, &'a Block),
|
||||
Method(Ident, &'a FnSig, &'a Visibility, &'a Block),
|
||||
|
||||
/// E.g., `|x, y| body`.
|
||||
Closure(&'a Expr),
|
||||
|
@ -83,8 +83,9 @@ pub trait Visitor<'ast>: Sized {
|
|||
fn visit_fn(&mut self, fk: FnKind<'ast>, fd: &'ast FnDecl, s: Span, _: NodeId) {
|
||||
walk_fn(self, fk, fd, s)
|
||||
}
|
||||
fn visit_trait_item(&mut self, ti: &'ast TraitItem) { walk_trait_item(self, ti) }
|
||||
fn visit_impl_item(&mut self, ii: &'ast ImplItem) { walk_impl_item(self, ii) }
|
||||
fn visit_trait_item(&mut self, i: &'ast AssocItem) { walk_trait_item(self, i) }
|
||||
fn visit_impl_item(&mut self, i: &'ast AssocItem) { walk_impl_item(self, i) }
|
||||
fn visit_assoc_item(&mut self, i: &'ast AssocItem) { walk_assoc_item(self, i) }
|
||||
fn visit_trait_ref(&mut self, t: &'ast TraitRef) { walk_trait_ref(self, t) }
|
||||
fn visit_param_bound(&mut self, bounds: &'ast GenericBound) {
|
||||
walk_param_bound(self, bounds)
|
||||
|
@ -420,7 +421,7 @@ pub fn walk_generic_args<'a, V>(visitor: &mut V,
|
|||
}
|
||||
GenericArgs::Parenthesized(ref data) => {
|
||||
walk_list!(visitor, visit_ty, &data.inputs);
|
||||
walk_list!(visitor, visit_ty, &data.output);
|
||||
walk_fn_ret_ty(visitor, &data.output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -581,52 +582,37 @@ pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl
|
|||
}
|
||||
}
|
||||
|
||||
pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a TraitItem) {
|
||||
visitor.visit_vis(&trait_item.vis);
|
||||
visitor.visit_ident(trait_item.ident);
|
||||
walk_list!(visitor, visit_attribute, &trait_item.attrs);
|
||||
visitor.visit_generics(&trait_item.generics);
|
||||
match trait_item.kind {
|
||||
TraitItemKind::Const(ref ty, ref default) => {
|
||||
pub fn walk_impl_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem) {
|
||||
visitor.visit_assoc_item(item);
|
||||
}
|
||||
|
||||
pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem) {
|
||||
visitor.visit_assoc_item(item);
|
||||
}
|
||||
|
||||
pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem) {
|
||||
visitor.visit_vis(&item.vis);
|
||||
visitor.visit_ident(item.ident);
|
||||
walk_list!(visitor, visit_attribute, &item.attrs);
|
||||
visitor.visit_generics(&item.generics);
|
||||
match item.kind {
|
||||
AssocItemKind::Const(ref ty, ref expr) => {
|
||||
visitor.visit_ty(ty);
|
||||
walk_list!(visitor, visit_expr, default);
|
||||
walk_list!(visitor, visit_expr, expr);
|
||||
}
|
||||
TraitItemKind::Method(ref sig, None) => {
|
||||
AssocItemKind::Fn(ref sig, None) => {
|
||||
visitor.visit_fn_header(&sig.header);
|
||||
walk_fn_decl(visitor, &sig.decl);
|
||||
}
|
||||
TraitItemKind::Method(ref sig, Some(ref body)) => {
|
||||
visitor.visit_fn(FnKind::Method(trait_item.ident, sig, None, body),
|
||||
&sig.decl, trait_item.span, trait_item.id);
|
||||
AssocItemKind::Fn(ref sig, Some(ref body)) => {
|
||||
visitor.visit_fn(FnKind::Method(item.ident, sig, &item.vis, body),
|
||||
&sig.decl, item.span, item.id);
|
||||
}
|
||||
TraitItemKind::Type(ref bounds, ref default) => {
|
||||
AssocItemKind::TyAlias(ref bounds, ref ty) => {
|
||||
walk_list!(visitor, visit_param_bound, bounds);
|
||||
walk_list!(visitor, visit_ty, default);
|
||||
walk_list!(visitor, visit_ty, ty);
|
||||
}
|
||||
TraitItemKind::Macro(ref mac) => {
|
||||
visitor.visit_mac(mac);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_impl_item<'a, V: Visitor<'a>>(visitor: &mut V, impl_item: &'a ImplItem) {
|
||||
visitor.visit_vis(&impl_item.vis);
|
||||
visitor.visit_ident(impl_item.ident);
|
||||
walk_list!(visitor, visit_attribute, &impl_item.attrs);
|
||||
visitor.visit_generics(&impl_item.generics);
|
||||
match impl_item.kind {
|
||||
ImplItemKind::Const(ref ty, ref expr) => {
|
||||
visitor.visit_ty(ty);
|
||||
visitor.visit_expr(expr);
|
||||
}
|
||||
ImplItemKind::Method(ref sig, ref body) => {
|
||||
visitor.visit_fn(FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis), body),
|
||||
&sig.decl, impl_item.span, impl_item.id);
|
||||
}
|
||||
ImplItemKind::TyAlias(ref ty) => {
|
||||
visitor.visit_ty(ty);
|
||||
}
|
||||
ImplItemKind::Macro(ref mac) => {
|
||||
AssocItemKind::Macro(ref mac) => {
|
||||
visitor.visit_mac(mac);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,8 +31,8 @@ crate use syntax_pos::hygiene::MacroKind;
|
|||
#[derive(Debug,Clone)]
|
||||
pub enum Annotatable {
|
||||
Item(P<ast::Item>),
|
||||
TraitItem(P<ast::TraitItem>),
|
||||
ImplItem(P<ast::ImplItem>),
|
||||
TraitItem(P<ast::AssocItem>),
|
||||
ImplItem(P<ast::AssocItem>),
|
||||
ForeignItem(P<ast::ForeignItem>),
|
||||
Stmt(P<ast::Stmt>),
|
||||
Expr(P<ast::Expr>),
|
||||
|
@ -137,14 +137,14 @@ impl Annotatable {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn expect_trait_item(self) -> ast::TraitItem {
|
||||
pub fn expect_trait_item(self) -> ast::AssocItem {
|
||||
match self {
|
||||
Annotatable::TraitItem(i) => i.into_inner(),
|
||||
_ => panic!("expected Item")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expect_impl_item(self) -> ast::ImplItem {
|
||||
pub fn expect_impl_item(self) -> ast::AssocItem {
|
||||
match self {
|
||||
Annotatable::ImplItem(i) => i.into_inner(),
|
||||
_ => panic!("expected Item")
|
||||
|
@ -382,12 +382,12 @@ pub trait MacResult {
|
|||
}
|
||||
|
||||
/// Creates zero or more impl items.
|
||||
fn make_impl_items(self: Box<Self>) -> Option<SmallVec<[ast::ImplItem; 1]>> {
|
||||
fn make_impl_items(self: Box<Self>) -> Option<SmallVec<[ast::AssocItem; 1]>> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Creates zero or more trait items.
|
||||
fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[ast::TraitItem; 1]>> {
|
||||
fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[ast::AssocItem; 1]>> {
|
||||
None
|
||||
}
|
||||
|
||||
|
@ -468,8 +468,8 @@ make_MacEager! {
|
|||
expr: P<ast::Expr>,
|
||||
pat: P<ast::Pat>,
|
||||
items: SmallVec<[P<ast::Item>; 1]>,
|
||||
impl_items: SmallVec<[ast::ImplItem; 1]>,
|
||||
trait_items: SmallVec<[ast::TraitItem; 1]>,
|
||||
impl_items: SmallVec<[ast::AssocItem; 1]>,
|
||||
trait_items: SmallVec<[ast::AssocItem; 1]>,
|
||||
foreign_items: SmallVec<[ast::ForeignItem; 1]>,
|
||||
stmts: SmallVec<[ast::Stmt; 1]>,
|
||||
ty: P<ast::Ty>,
|
||||
|
@ -484,11 +484,11 @@ impl MacResult for MacEager {
|
|||
self.items
|
||||
}
|
||||
|
||||
fn make_impl_items(self: Box<Self>) -> Option<SmallVec<[ast::ImplItem; 1]>> {
|
||||
fn make_impl_items(self: Box<Self>) -> Option<SmallVec<[ast::AssocItem; 1]>> {
|
||||
self.impl_items
|
||||
}
|
||||
|
||||
fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[ast::TraitItem; 1]>> {
|
||||
fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[ast::AssocItem; 1]>> {
|
||||
self.trait_items
|
||||
}
|
||||
|
||||
|
@ -588,11 +588,11 @@ impl MacResult for DummyResult {
|
|||
Some(SmallVec::new())
|
||||
}
|
||||
|
||||
fn make_impl_items(self: Box<DummyResult>) -> Option<SmallVec<[ast::ImplItem; 1]>> {
|
||||
fn make_impl_items(self: Box<DummyResult>) -> Option<SmallVec<[ast::AssocItem; 1]>> {
|
||||
Some(SmallVec::new())
|
||||
}
|
||||
|
||||
fn make_trait_items(self: Box<DummyResult>) -> Option<SmallVec<[ast::TraitItem; 1]>> {
|
||||
fn make_trait_items(self: Box<DummyResult>) -> Option<SmallVec<[ast::AssocItem; 1]>> {
|
||||
Some(SmallVec::new())
|
||||
}
|
||||
|
||||
|
|
|
@ -154,10 +154,10 @@ ast_fragments! {
|
|||
Items(SmallVec<[P<ast::Item>; 1]>) {
|
||||
"item"; many fn flat_map_item; fn visit_item; fn make_items;
|
||||
}
|
||||
TraitItems(SmallVec<[ast::TraitItem; 1]>) {
|
||||
TraitItems(SmallVec<[ast::AssocItem; 1]>) {
|
||||
"trait item"; many fn flat_map_trait_item; fn visit_trait_item; fn make_trait_items;
|
||||
}
|
||||
ImplItems(SmallVec<[ast::ImplItem; 1]>) {
|
||||
ImplItems(SmallVec<[ast::AssocItem; 1]>) {
|
||||
"impl item"; many fn flat_map_impl_item; fn visit_impl_item; fn make_impl_items;
|
||||
}
|
||||
ForeignItems(SmallVec<[ast::ForeignItem; 1]>) {
|
||||
|
@ -1316,7 +1316,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
|||
}
|
||||
}
|
||||
|
||||
fn flat_map_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> {
|
||||
fn flat_map_trait_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
|
||||
let mut item = configure!(self, item);
|
||||
|
||||
let (attr, traits, after_derive) = self.classify_item(&mut item);
|
||||
|
@ -1326,16 +1326,16 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
|||
}
|
||||
|
||||
match item.kind {
|
||||
ast::TraitItemKind::Macro(mac) => {
|
||||
let ast::TraitItem { attrs, span, .. } = item;
|
||||
ast::AssocItemKind::Macro(mac) => {
|
||||
let ast::AssocItem { attrs, span, .. } = item;
|
||||
self.check_attributes(&attrs);
|
||||
self.collect_bang(mac, span, AstFragmentKind::TraitItems).make_trait_items()
|
||||
}
|
||||
_ => noop_flat_map_trait_item(item, self),
|
||||
_ => noop_flat_map_assoc_item(item, self),
|
||||
}
|
||||
}
|
||||
|
||||
fn flat_map_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> {
|
||||
fn flat_map_impl_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
|
||||
let mut item = configure!(self, item);
|
||||
|
||||
let (attr, traits, after_derive) = self.classify_item(&mut item);
|
||||
|
@ -1345,12 +1345,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
|||
}
|
||||
|
||||
match item.kind {
|
||||
ast::ImplItemKind::Macro(mac) => {
|
||||
let ast::ImplItem { attrs, span, .. } = item;
|
||||
ast::AssocItemKind::Macro(mac) => {
|
||||
let ast::AssocItem { attrs, span, .. } = item;
|
||||
self.check_attributes(&attrs);
|
||||
self.collect_bang(mac, span, AstFragmentKind::ImplItems).make_impl_items()
|
||||
}
|
||||
_ => noop_flat_map_impl_item(item, self),
|
||||
_ => noop_flat_map_assoc_item(item, self),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,14 +50,15 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId, vis: Option<ast::Visi
|
|||
kind: ast::ItemKind::Mac(mac_placeholder()),
|
||||
tokens: None,
|
||||
})]),
|
||||
AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![ast::TraitItem {
|
||||
AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![ast::AssocItem {
|
||||
id, span, ident, vis, attrs, generics,
|
||||
kind: ast::TraitItemKind::Macro(mac_placeholder()),
|
||||
kind: ast::AssocItemKind::Macro(mac_placeholder()),
|
||||
defaultness: ast::Defaultness::Final,
|
||||
tokens: None,
|
||||
}]),
|
||||
AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![ast::ImplItem {
|
||||
AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![ast::AssocItem {
|
||||
id, span, ident, vis, attrs, generics,
|
||||
kind: ast::ImplItemKind::Macro(mac_placeholder()),
|
||||
kind: ast::AssocItemKind::Macro(mac_placeholder()),
|
||||
defaultness: ast::Defaultness::Final,
|
||||
tokens: None,
|
||||
}]),
|
||||
|
@ -252,17 +253,17 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
|
|||
noop_flat_map_item(item, self)
|
||||
}
|
||||
|
||||
fn flat_map_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> {
|
||||
fn flat_map_trait_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
|
||||
match item.kind {
|
||||
ast::TraitItemKind::Macro(_) => self.remove(item.id).make_trait_items(),
|
||||
_ => noop_flat_map_trait_item(item, self),
|
||||
ast::AssocItemKind::Macro(_) => self.remove(item.id).make_trait_items(),
|
||||
_ => noop_flat_map_assoc_item(item, self),
|
||||
}
|
||||
}
|
||||
|
||||
fn flat_map_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> {
|
||||
fn flat_map_impl_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
|
||||
match item.kind {
|
||||
ast::ImplItemKind::Macro(_) => self.remove(item.id).make_impl_items(),
|
||||
_ => noop_flat_map_impl_item(item, self),
|
||||
ast::AssocItemKind::Macro(_) => self.remove(item.id).make_impl_items(),
|
||||
_ => noop_flat_map_assoc_item(item, self),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -504,13 +504,13 @@ impl<'a> TraitDef<'a> {
|
|||
type_ident: Ident,
|
||||
generics: &Generics,
|
||||
field_tys: Vec<P<ast::Ty>>,
|
||||
methods: Vec<ast::ImplItem>)
|
||||
methods: Vec<ast::AssocItem>)
|
||||
-> P<ast::Item> {
|
||||
let trait_path = self.path.to_path(cx, self.span, type_ident, generics);
|
||||
|
||||
// Transform associated types from `deriving::ty::Ty` into `ast::ImplItem`
|
||||
// Transform associated types from `deriving::ty::Ty` into `ast::AssocItem`
|
||||
let associated_types = self.associated_types.iter().map(|&(ident, ref type_def)| {
|
||||
ast::ImplItem {
|
||||
ast::AssocItem {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: self.span,
|
||||
ident,
|
||||
|
@ -518,8 +518,10 @@ impl<'a> TraitDef<'a> {
|
|||
defaultness: ast::Defaultness::Final,
|
||||
attrs: Vec::new(),
|
||||
generics: Generics::default(),
|
||||
kind: ast::ImplItemKind::TyAlias(
|
||||
type_def.to_ty(cx, self.span, type_ident, generics)),
|
||||
kind: ast::AssocItemKind::TyAlias(
|
||||
Vec::new(),
|
||||
Some(type_def.to_ty(cx, self.span, type_ident, generics)),
|
||||
),
|
||||
tokens: None,
|
||||
}
|
||||
});
|
||||
|
@ -910,7 +912,7 @@ impl<'a> MethodDef<'a> {
|
|||
explicit_self: Option<ast::ExplicitSelf>,
|
||||
arg_types: Vec<(Ident, P<ast::Ty>)>,
|
||||
body: P<Expr>)
|
||||
-> ast::ImplItem {
|
||||
-> ast::AssocItem {
|
||||
// Create the generics that aren't for `Self`.
|
||||
let fn_generics = self.generics.to_generics(cx, trait_.span, type_ident, generics);
|
||||
|
||||
|
@ -948,7 +950,7 @@ impl<'a> MethodDef<'a> {
|
|||
};
|
||||
|
||||
// Create the method.
|
||||
ast::ImplItem {
|
||||
ast::AssocItem {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
attrs: self.attributes.clone(),
|
||||
generics: fn_generics,
|
||||
|
@ -956,7 +958,7 @@ impl<'a> MethodDef<'a> {
|
|||
vis: respan(trait_lo_sp, ast::VisibilityKind::Inherited),
|
||||
defaultness: ast::Defaultness::Final,
|
||||
ident: method_ident,
|
||||
kind: ast::ImplItemKind::Method(sig, body_block),
|
||||
kind: ast::AssocItemKind::Fn(sig, Some(body_block)),
|
||||
tokens: None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
fn address_of_reborrow() {
|
||||
let y = &[0; 10];
|
||||
let mut z = &mut [0; 10];
|
||||
|
||||
y as *const _;
|
||||
y as *const [i32; 10];
|
||||
y as *const dyn Send;
|
||||
y as *const [i32];
|
||||
y as *const i32; // This is a cast, not a coercion
|
||||
|
||||
let p: *const _ = y;
|
||||
let p: *const [i32; 10] = y;
|
||||
let p: *const dyn Send = y;
|
||||
let p: *const [i32] = y;
|
||||
|
||||
z as *const _;
|
||||
z as *const [i32; 10];
|
||||
z as *const dyn Send;
|
||||
z as *const [i32];
|
||||
|
||||
let p: *const _ = z;
|
||||
let p: *const [i32; 10] = z;
|
||||
let p: *const dyn Send = z;
|
||||
let p: *const [i32] = z;
|
||||
|
||||
z as *mut _;
|
||||
z as *mut [i32; 10];
|
||||
z as *mut dyn Send;
|
||||
z as *mut [i32];
|
||||
|
||||
let p: *mut _ = z;
|
||||
let p: *mut [i32; 10] = z;
|
||||
let p: *mut dyn Send = z;
|
||||
let p: *mut [i32] = z;
|
||||
}
|
||||
|
||||
// The normal borrows here should be preserved
|
||||
fn borrow_and_cast(mut x: i32) {
|
||||
let p = &x as *const i32;
|
||||
let q = &mut x as *const i32;
|
||||
let r = &mut x as *mut i32;
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
// START rustc.address_of_reborrow.SimplifyCfg-initial.after.mir
|
||||
// bb0: {
|
||||
// ...
|
||||
// _5 = &raw const (*_1); // & to *const casts
|
||||
// ...
|
||||
// _7 = &raw const (*_1);
|
||||
// ...
|
||||
// _11 = &raw const (*_1);
|
||||
// ...
|
||||
// _14 = &raw const (*_1);
|
||||
// ...
|
||||
// _16 = &raw const (*_1);
|
||||
// ...
|
||||
// _17 = &raw const (*_1); // & to *const coercions
|
||||
// ...
|
||||
// _18 = &raw const (*_1);
|
||||
// ...
|
||||
// _20 = &raw const (*_1);
|
||||
// ...
|
||||
// _22 = &raw const (*_1);
|
||||
// ...
|
||||
// _24 = &raw const (*_2); // &mut to *const casts
|
||||
// ...
|
||||
// _26 = &raw const (*_2);
|
||||
// ...
|
||||
// _30 = &raw const (*_2);
|
||||
// ...
|
||||
// _33 = &raw const (*_2);
|
||||
// ...
|
||||
// _34 = &raw const (*_2); // &mut to *const coercions
|
||||
// ...
|
||||
// _35 = &raw const (*_2);
|
||||
// ...
|
||||
// _37 = &raw const (*_2);
|
||||
// ...
|
||||
// _39 = &raw const (*_2);
|
||||
// ...
|
||||
// _41 = &raw mut (*_2); // &mut to *mut casts
|
||||
// ...
|
||||
// _43 = &raw mut (*_2);
|
||||
// ...
|
||||
// _47 = &raw mut (*_2);
|
||||
// ...
|
||||
// _50 = &raw mut (*_2);
|
||||
// ...
|
||||
// _51 = &raw mut (*_2); // &mut to *mut coercions
|
||||
// ...
|
||||
// _52 = &raw mut (*_2);
|
||||
// ...
|
||||
// _54 = &raw mut (*_2);
|
||||
// ...
|
||||
// _56 = &raw mut (*_2);
|
||||
// ...
|
||||
// }
|
||||
// END rustc.address_of_reborrow.SimplifyCfg-initial.after.mir
|
||||
|
||||
// START rustc.borrow_and_cast.EraseRegions.after.mir
|
||||
// bb0: {
|
||||
// ...
|
||||
// _4 = &_1;
|
||||
// ...
|
||||
// _7 = &mut _1;
|
||||
// ...
|
||||
// _10 = &mut _1;
|
||||
// ...
|
||||
// }
|
||||
// END rustc.borrow_and_cast.EraseRegions.after.mir
|
|
@ -18,24 +18,23 @@ fn main() {
|
|||
// START rustc.main.EraseRegions.after.mir
|
||||
// bb0: {
|
||||
// ...
|
||||
// _5 = &mut _2;
|
||||
// _4 = &mut (*_5);
|
||||
// _3 = move _4 as *mut usize (Misc);
|
||||
// _4 = &mut _2;
|
||||
// _3 = &raw mut (*_4);
|
||||
// ...
|
||||
// _7 = _3;
|
||||
// _6 = const foo(move _7) -> bb1;
|
||||
// _6 = _3;
|
||||
// _5 = const foo(move _6) -> bb1;
|
||||
// }
|
||||
//
|
||||
// bb1: {
|
||||
// ...
|
||||
// _8 = _2;
|
||||
// _9 = Len(_1);
|
||||
// _10 = Lt(_8, _9);
|
||||
// assert(move _10, "index out of bounds: the len is move _9 but the index is _8") -> bb2;
|
||||
// _7 = _2;
|
||||
// _8 = Len(_1);
|
||||
// _9 = Lt(_7, _8);
|
||||
// assert(move _9, "index out of bounds: the len is move _8 but the index is _7") -> bb2;
|
||||
// }
|
||||
//
|
||||
// bb2: {
|
||||
// _1[_8] = move _6;
|
||||
// _1[_7] = move _5;
|
||||
// ...
|
||||
// return;
|
||||
// }
|
||||
|
|
|
@ -11,25 +11,21 @@ fn main() {
|
|||
// START rustc.main.ConstProp.before.mir
|
||||
// bb0: {
|
||||
// ...
|
||||
// _3 = _4;
|
||||
// _2 = move _3 as *const i32 (Misc);
|
||||
// ...
|
||||
// _2 = &raw const (*_3);
|
||||
// _1 = move _2 as usize (Misc);
|
||||
// ...
|
||||
// _6 = _1;
|
||||
// _5 = const read(move _6) -> bb1;
|
||||
// _5 = _1;
|
||||
// _4 = const read(move _5) -> bb1;
|
||||
// }
|
||||
// END rustc.main.ConstProp.before.mir
|
||||
// START rustc.main.ConstProp.after.mir
|
||||
// bb0: {
|
||||
// ...
|
||||
// _4 = const main::FOO;
|
||||
// _3 = _4;
|
||||
// _2 = move _3 as *const i32 (Misc);
|
||||
// ...
|
||||
// _3 = const main::FOO;
|
||||
// _2 = &raw const (*_3);
|
||||
// _1 = move _2 as usize (Misc);
|
||||
// ...
|
||||
// _6 = _1;
|
||||
// _5 = const read(move _6) -> bb1;
|
||||
// _5 = _1;
|
||||
// _4 = const read(move _5) -> bb1;
|
||||
// }
|
||||
// END rustc.main.ConstProp.after.mir
|
||||
|
|
|
@ -82,18 +82,16 @@ fn main() {
|
|||
// _10 = move _8;
|
||||
// Retag(_10);
|
||||
// ...
|
||||
// _13 = &mut (*_10);
|
||||
// Retag(_13);
|
||||
// _12 = move _13 as *mut i32 (Misc);
|
||||
// _12 = &raw mut (*_10);
|
||||
// Retag([raw] _12);
|
||||
// ...
|
||||
// _16 = move _17(move _18) -> bb5;
|
||||
// _15 = move _16(move _17) -> bb5;
|
||||
// }
|
||||
//
|
||||
// bb5: {
|
||||
// Retag(_16);
|
||||
// Retag(_15);
|
||||
// ...
|
||||
// _20 = const Test::foo_shr(move _21, move _23) -> [return: bb6, unwind: bb7];
|
||||
// _19 = const Test::foo_shr(move _20, move _22) -> [return: bb6, unwind: bb7];
|
||||
// }
|
||||
//
|
||||
// ...
|
||||
|
|
|
@ -10,15 +10,15 @@ fn main() {
|
|||
// let mut _2: usize;
|
||||
// let mut _3: usize;
|
||||
// let mut _4: usize;
|
||||
// let mut _5: &mut std::string::String;
|
||||
// let mut _5: *mut std::string::String;
|
||||
// let mut _6: bool;
|
||||
// let mut _7: &mut std::string::String;
|
||||
// let mut _7: *mut std::string::String;
|
||||
// let mut _8: bool;
|
||||
// let mut _9: *mut std::string::String;
|
||||
// let mut _10: *mut std::string::String;
|
||||
// let mut _11: &mut std::string::String;
|
||||
// let mut _11: *mut std::string::String;
|
||||
// let mut _12: bool;
|
||||
// let mut _13: &mut std::string::String;
|
||||
// let mut _13: *mut std::string::String;
|
||||
// let mut _14: bool;
|
||||
// let mut _15: *mut [std::string::String];
|
||||
// bb0: {
|
||||
|
@ -31,7 +31,7 @@ fn main() {
|
|||
// resume;
|
||||
// }
|
||||
// bb3 (cleanup): {
|
||||
// _5 = &mut (*_1)[_4];
|
||||
// _5 = &raw mut (*_1)[_4];
|
||||
// _4 = Add(move _4, const 1usize);
|
||||
// drop((*_5)) -> bb4;
|
||||
// }
|
||||
|
@ -40,7 +40,7 @@ fn main() {
|
|||
// switchInt(move _6) -> [false: bb3, otherwise: bb2];
|
||||
// }
|
||||
// bb5: {
|
||||
// _7 = &mut (*_1)[_4];
|
||||
// _7 = &raw mut (*_1)[_4];
|
||||
// _4 = Add(move _4, const 1usize);
|
||||
// drop((*_7)) -> [return: bb6, unwind: bb4];
|
||||
// }
|
||||
|
@ -56,7 +56,7 @@ fn main() {
|
|||
// goto -> bb7;
|
||||
// }
|
||||
// bb9 (cleanup): {
|
||||
// _11 = &mut (*_9);
|
||||
// _11 = _9;
|
||||
// _9 = Offset(move _9, const 1usize);
|
||||
// drop((*_11)) -> bb10;
|
||||
// }
|
||||
|
@ -65,7 +65,7 @@ fn main() {
|
|||
// switchInt(move _12) -> [false: bb9, otherwise: bb2];
|
||||
// }
|
||||
// bb11: {
|
||||
// _13 = &mut (*_9);
|
||||
// _13 = _9;
|
||||
// _9 = Offset(move _9, const 1usize);
|
||||
// drop((*_13)) -> [return: bb12, unwind: bb10];
|
||||
// }
|
||||
|
@ -74,7 +74,7 @@ fn main() {
|
|||
// switchInt(move _14) -> [false: bb11, otherwise: bb1];
|
||||
// }
|
||||
// bb13: {
|
||||
// _15 = &mut (*_1);
|
||||
// _15 = &raw mut (*_1);
|
||||
// _9 = move _15 as *mut std::string::String (Misc);
|
||||
// _10 = Offset(_9, move _3);
|
||||
// goto -> bb12;
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
// pp-exact
|
||||
#![feature(raw_ref_op)]
|
||||
|
||||
const C_PTR: () = { let a = 1; &raw const a; };
|
||||
static S_PTR: () = { let b = false; &raw const b; };
|
||||
|
||||
fn main() {
|
||||
let x = 123;
|
||||
let mut y = 345;
|
||||
let c_p = &raw const x;
|
||||
let parens = unsafe { *(&raw mut (y)) };
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
-include ../../run-make-fulldeps/tools.mk
|
||||
|
||||
# only-wasm32-bare
|
||||
|
||||
all:
|
||||
$(RUSTC) foo.rs --target wasm32-unknown-unknown
|
||||
$(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo
|
||||
$(RUSTC) foo.rs --target wasm32-unknown-unknown -C lto
|
||||
$(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo
|
||||
$(RUSTC) foo.rs --target wasm32-unknown-unknown -O
|
||||
$(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo
|
||||
$(RUSTC) foo.rs --target wasm32-unknown-unknown -O -C lto
|
||||
$(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo
|
||||
|
||||
$(RUSTC) bar.rs --target wasm32-unknown-unknown
|
||||
$(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f
|
||||
$(RUSTC) bar.rs --target wasm32-unknown-unknown -C lto
|
||||
$(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f
|
||||
$(RUSTC) bar.rs --target wasm32-unknown-unknown -O
|
||||
$(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f
|
||||
$(RUSTC) bar.rs --target wasm32-unknown-unknown -O -C lto
|
||||
$(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f
|
||||
|
||||
$(RUSTC) baz.rs --target wasm32-unknown-unknown
|
||||
$(NODE) verify-imports.js $(TMPDIR)/baz.wasm sqlite/allocate sqlite/deallocate
|
||||
|
||||
$(RUSTC) log.rs --target wasm32-unknown-unknown
|
||||
$(NODE) verify-imports.js $(TMPDIR)/log.wasm test/log
|
|
@ -0,0 +1,33 @@
|
|||
//! Issue #50021
|
||||
|
||||
#![crate_type = "cdylib"]
|
||||
|
||||
mod m1 {
|
||||
#[link(wasm_import_module = "m1")]
|
||||
extern "C" {
|
||||
pub fn f();
|
||||
}
|
||||
#[link(wasm_import_module = "m1")]
|
||||
extern "C" {
|
||||
pub fn g();
|
||||
}
|
||||
}
|
||||
|
||||
mod m2 {
|
||||
#[link(wasm_import_module = "m2")]
|
||||
extern "C" {
|
||||
pub fn f(_: i32);
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn run() {
|
||||
m1::f();
|
||||
m1::g();
|
||||
|
||||
// In generated code, expected:
|
||||
// (import "m2" "f" (func $f (param i32)))
|
||||
// but got:
|
||||
// (import "m1" "f" (func $f (param i32)))
|
||||
m2::f(0);
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
//! Issue #63562
|
||||
|
||||
#![crate_type = "cdylib"]
|
||||
|
||||
mod foo {
|
||||
#[link(wasm_import_module = "sqlite")]
|
||||
extern "C" {
|
||||
pub fn allocate(size: usize) -> i32;
|
||||
pub fn deallocate(ptr: i32, size: usize);
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn allocate() {
|
||||
unsafe {
|
||||
foo::allocate(1);
|
||||
foo::deallocate(1, 2);
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn deallocate() {}
|
|
@ -0,0 +1,23 @@
|
|||
#![crate_type = "cdylib"]
|
||||
|
||||
mod a {
|
||||
#[link(wasm_import_module = "a")]
|
||||
extern "C" {
|
||||
pub fn foo();
|
||||
}
|
||||
}
|
||||
|
||||
mod b {
|
||||
#[link(wasm_import_module = "b")]
|
||||
extern "C" {
|
||||
pub fn foo();
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn start() {
|
||||
unsafe {
|
||||
a::foo();
|
||||
b::foo();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
//! Issue #56309
|
||||
|
||||
#![crate_type = "cdylib"]
|
||||
|
||||
#[link(wasm_import_module = "test")]
|
||||
extern "C" {
|
||||
fn log(message_data: u32, message_size: u32);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn main() {
|
||||
let message = "Hello, world!";
|
||||
unsafe {
|
||||
log(message.as_ptr() as u32, message.len() as u32);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
const fs = require('fs');
|
||||
const process = require('process');
|
||||
const assert = require('assert');
|
||||
const buffer = fs.readFileSync(process.argv[2]);
|
||||
|
||||
let m = new WebAssembly.Module(buffer);
|
||||
let list = WebAssembly.Module.imports(m);
|
||||
console.log('imports', list);
|
||||
if (list.length !== process.argv.length - 3)
|
||||
throw new Error("wrong number of imports")
|
||||
|
||||
const imports = new Map();
|
||||
for (let i = 3; i < process.argv.length; i++) {
|
||||
const [module, name] = process.argv[i].split('/');
|
||||
if (!imports.has(module))
|
||||
imports.set(module, new Map());
|
||||
imports.get(module).set(name, true);
|
||||
}
|
||||
|
||||
for (let i of list) {
|
||||
if (imports.get(i.module) === undefined || imports.get(i.module).get(i.name) === undefined)
|
||||
throw new Error(`didn't find import of ${i.module}::${i.name}`);
|
||||
imports.get(i.module).delete(i.name);
|
||||
|
||||
if (imports.get(i.module).size === 0)
|
||||
imports.delete(i.module);
|
||||
}
|
||||
|
||||
console.log(imports);
|
||||
if (imports.size !== 0) {
|
||||
throw new Error('extra imports');
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#![feature(raw_ref_op)]
|
||||
|
||||
fn address_of_shared() {
|
||||
let mut x = 0;
|
||||
let y = &x;
|
||||
|
||||
let q = &raw mut x; //~ ERROR cannot borrow
|
||||
|
||||
drop(y);
|
||||
}
|
||||
|
||||
fn address_of_mutably_borrowed() {
|
||||
let mut x = 0;
|
||||
let y = &mut x;
|
||||
|
||||
let p = &raw const x; //~ ERROR cannot borrow
|
||||
let q = &raw mut x; //~ ERROR cannot borrow
|
||||
|
||||
drop(y);
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,40 @@
|
|||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrow-raw-address-of-borrowed.rs:7:13
|
||||
|
|
||||
LL | let y = &x;
|
||||
| -- immutable borrow occurs here
|
||||
LL |
|
||||
LL | let q = &raw mut x;
|
||||
| ^^^^^^^^^^ mutable borrow occurs here
|
||||
LL |
|
||||
LL | drop(y);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrow-raw-address-of-borrowed.rs:16:13
|
||||
|
|
||||
LL | let y = &mut x;
|
||||
| ------ mutable borrow occurs here
|
||||
LL |
|
||||
LL | let p = &raw const x;
|
||||
| ^^^^^^^^^^^^ immutable borrow occurs here
|
||||
...
|
||||
LL | drop(y);
|
||||
| - mutable borrow later used here
|
||||
|
||||
error[E0499]: cannot borrow `x` as mutable more than once at a time
|
||||
--> $DIR/borrow-raw-address-of-borrowed.rs:17:13
|
||||
|
|
||||
LL | let y = &mut x;
|
||||
| ------ first mutable borrow occurs here
|
||||
...
|
||||
LL | let q = &raw mut x;
|
||||
| ^^^^^^^^^^ second mutable borrow occurs here
|
||||
LL |
|
||||
LL | drop(y);
|
||||
| - first borrow later used here
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0499, E0502.
|
||||
For more information about an error, try `rustc --explain E0499`.
|
|
@ -0,0 +1,23 @@
|
|||
// check-pass
|
||||
|
||||
#![feature(raw_ref_op)]
|
||||
|
||||
fn raw_reborrow() {
|
||||
let x = &0;
|
||||
let y = &mut 0;
|
||||
|
||||
let p = &raw const *x;
|
||||
let r = &raw const *y;
|
||||
let s = &raw mut *y;
|
||||
}
|
||||
|
||||
unsafe fn raw_reborrow_of_raw() {
|
||||
let x = &0 as *const i32;
|
||||
let y = &mut 0 as *mut i32;
|
||||
|
||||
let p = &raw const *x;
|
||||
let r = &raw const *y;
|
||||
let s = &raw mut *y;
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,17 @@
|
|||
// Check that `&raw mut` cannot be used to turn a `&T` into a `*mut T`.
|
||||
|
||||
#![feature(raw_ref_op)]
|
||||
|
||||
fn raw_reborrow() {
|
||||
let x = &0;
|
||||
|
||||
let q = &raw mut *x; //~ ERROR cannot borrow
|
||||
}
|
||||
|
||||
unsafe fn raw_reborrow_of_raw() {
|
||||
let x = &0 as *const i32;
|
||||
|
||||
let q = &raw mut *x; //~ ERROR cannot borrow
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,21 @@
|
|||
error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/borrow-raw-address-of-deref-mutability.rs:8:13
|
||||
|
|
||||
LL | let x = &0;
|
||||
| -- help: consider changing this to be a mutable reference: `&mut 0`
|
||||
LL |
|
||||
LL | let q = &raw mut *x;
|
||||
| ^^^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
||||
|
||||
error[E0596]: cannot borrow `*x` as mutable, as it is behind a `*const` pointer
|
||||
--> $DIR/borrow-raw-address-of-deref-mutability.rs:14:13
|
||||
|
|
||||
LL | let x = &0 as *const i32;
|
||||
| -- help: consider changing this to be a mutable pointer: `&mut 0`
|
||||
LL |
|
||||
LL | let q = &raw mut *x;
|
||||
| ^^^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0596`.
|
|
@ -0,0 +1,44 @@
|
|||
// check-pass
|
||||
|
||||
#![feature(raw_ref_op)]
|
||||
|
||||
fn mutable_address_of() {
|
||||
let mut x = 0;
|
||||
let y = &raw mut x;
|
||||
}
|
||||
|
||||
fn mutable_address_of_closure() {
|
||||
let mut x = 0;
|
||||
let mut f = || {
|
||||
let y = &raw mut x;
|
||||
};
|
||||
f();
|
||||
}
|
||||
|
||||
fn const_address_of_closure() {
|
||||
let x = 0;
|
||||
let f = || {
|
||||
let y = &raw const x;
|
||||
};
|
||||
f();
|
||||
}
|
||||
|
||||
fn make_fn<F: Fn()>(f: F) -> F { f }
|
||||
|
||||
fn const_address_of_fn_closure() {
|
||||
let x = 0;
|
||||
let f = make_fn(|| {
|
||||
let y = &raw const x;
|
||||
});
|
||||
f();
|
||||
}
|
||||
|
||||
fn const_address_of_fn_closure_move() {
|
||||
let x = 0;
|
||||
let f = make_fn(move || {
|
||||
let y = &raw const x;
|
||||
});
|
||||
f();
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,42 @@
|
|||
#![feature(raw_ref_op)]
|
||||
|
||||
fn mutable_address_of() {
|
||||
let x = 0;
|
||||
let y = &raw mut x; //~ ERROR cannot borrow
|
||||
}
|
||||
|
||||
fn mutable_address_of_closure() {
|
||||
let x = 0;
|
||||
let mut f = || {
|
||||
let y = &raw mut x; //~ ERROR cannot borrow
|
||||
};
|
||||
f();
|
||||
}
|
||||
|
||||
fn mutable_address_of_imm_closure() {
|
||||
let mut x = 0;
|
||||
let f = || {
|
||||
let y = &raw mut x;
|
||||
};
|
||||
f(); //~ ERROR cannot borrow
|
||||
}
|
||||
|
||||
fn make_fn<F: Fn()>(f: F) -> F { f }
|
||||
|
||||
fn mutable_address_of_fn_closure() {
|
||||
let mut x = 0;
|
||||
let f = make_fn(|| {
|
||||
let y = &raw mut x; //~ ERROR cannot borrow
|
||||
});
|
||||
f();
|
||||
}
|
||||
|
||||
fn mutable_address_of_fn_closure_move() {
|
||||
let mut x = 0;
|
||||
let f = make_fn(move || {
|
||||
let y = &raw mut x; //~ ERROR cannot borrow
|
||||
});
|
||||
f();
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,59 @@
|
|||
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
|
||||
--> $DIR/borrow-raw-address-of-mutability.rs:5:13
|
||||
|
|
||||
LL | let x = 0;
|
||||
| - help: consider changing this to be mutable: `mut x`
|
||||
LL | let y = &raw mut x;
|
||||
| ^^^^^^^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
|
||||
--> $DIR/borrow-raw-address-of-mutability.rs:11:17
|
||||
|
|
||||
LL | let x = 0;
|
||||
| - help: consider changing this to be mutable: `mut x`
|
||||
LL | let mut f = || {
|
||||
LL | let y = &raw mut x;
|
||||
| ^^^^^^^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable
|
||||
--> $DIR/borrow-raw-address-of-mutability.rs:21:5
|
||||
|
|
||||
LL | let f = || {
|
||||
| - help: consider changing this to be mutable: `mut f`
|
||||
...
|
||||
LL | f();
|
||||
| ^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
|
||||
--> $DIR/borrow-raw-address-of-mutability.rs:29:17
|
||||
|
|
||||
LL | let y = &raw mut x;
|
||||
| ^^^^^^^^^^ cannot borrow as mutable
|
||||
|
|
||||
help: consider changing this to accept closures that implement `FnMut`
|
||||
--> $DIR/borrow-raw-address-of-mutability.rs:28:21
|
||||
|
|
||||
LL | let f = make_fn(|| {
|
||||
| _____________________^
|
||||
LL | | let y = &raw mut x;
|
||||
LL | | });
|
||||
| |_____^
|
||||
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
|
||||
--> $DIR/borrow-raw-address-of-mutability.rs:37:17
|
||||
|
|
||||
LL | let y = &raw mut x;
|
||||
| ^^^^^^^^^^ cannot borrow as mutable
|
||||
|
|
||||
help: consider changing this to accept closures that implement `FnMut`
|
||||
--> $DIR/borrow-raw-address-of-mutability.rs:36:21
|
||||
|
|
||||
LL | let f = make_fn(move || {
|
||||
| _____________________^
|
||||
LL | | let y = &raw mut x;
|
||||
LL | | });
|
||||
| |_____^
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0596`.
|
|
@ -1,8 +1,8 @@
|
|||
error: C-variadic function must be declared with at least one named argument
|
||||
--> $DIR/variadic-ffi-no-fixed-args.rs:2:11
|
||||
--> $DIR/variadic-ffi-no-fixed-args.rs:2:12
|
||||
|
|
||||
LL | fn foo(...);
|
||||
| ^
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -5,5 +5,5 @@ fn main() {
|
|||
let t = (1 + 2) as bool; //~ ERROR cannot cast as `bool`
|
||||
//~| HELP compare with zero instead
|
||||
//~| SUGGESTION (1 + 2) != 0
|
||||
let v = "hello" as bool; //~ ERROR cannot cast as `bool`
|
||||
let v = "hello" as bool; //~ ERROR casting `&'static str` as `bool` is invalid
|
||||
}
|
||||
|
|
|
@ -10,12 +10,13 @@ error[E0054]: cannot cast as `bool`
|
|||
LL | let t = (1 + 2) as bool;
|
||||
| ^^^^^^^^^^^^^^^ help: compare with zero instead: `(1 + 2) != 0`
|
||||
|
||||
error[E0054]: cannot cast as `bool`
|
||||
error[E0606]: casting `&'static str` as `bool` is invalid
|
||||
--> $DIR/cast-as-bool.rs:8:13
|
||||
|
|
||||
LL | let v = "hello" as bool;
|
||||
| ^^^^^^^^^^^^^^^ unsupported cast
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0054`.
|
||||
Some errors have detailed explanations: E0054, E0606.
|
||||
For more information about an error, try `rustc --explain E0054`.
|
||||
|
|
|
@ -6,6 +6,7 @@ pub fn no_debug() {
|
|||
pub fn no_hash() {
|
||||
use std::collections::HashSet;
|
||||
let mut set = HashSet::new();
|
||||
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
|
||||
set.insert([0_usize; 33]);
|
||||
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
|
||||
}
|
||||
|
|
|
@ -8,15 +8,24 @@ LL | println!("{:?}", [0_usize; 33]);
|
|||
= note: required by `std::fmt::Debug::fmt`
|
||||
|
||||
error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
||||
--> $DIR/core-traits-no-impls-length-33.rs:9:16
|
||||
--> $DIR/core-traits-no-impls-length-33.rs:10:16
|
||||
|
|
||||
LL | set.insert([0_usize; 33]);
|
||||
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[usize; 33]`
|
||||
|
|
||||
= note: required because of the requirements on the impl of `std::cmp::Eq` for `[usize; 33]`
|
||||
|
||||
error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
||||
--> $DIR/core-traits-no-impls-length-33.rs:8:19
|
||||
|
|
||||
LL | let mut set = HashSet::new();
|
||||
| ^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[usize; 33]`
|
||||
|
|
||||
= note: required because of the requirements on the impl of `std::cmp::Eq` for `[usize; 33]`
|
||||
= note: required by `std::collections::HashSet::<T>::new`
|
||||
|
||||
error[E0369]: binary operation `==` cannot be applied to type `[usize; 33]`
|
||||
--> $DIR/core-traits-no-impls-length-33.rs:14:19
|
||||
--> $DIR/core-traits-no-impls-length-33.rs:15:19
|
||||
|
|
||||
LL | [0_usize; 33] == [1_usize; 33]
|
||||
| ------------- ^^ ------------- [usize; 33]
|
||||
|
@ -26,7 +35,7 @@ LL | [0_usize; 33] == [1_usize; 33]
|
|||
= note: an implementation of `std::cmp::PartialEq` might be missing for `[usize; 33]`
|
||||
|
||||
error[E0369]: binary operation `<` cannot be applied to type `[usize; 33]`
|
||||
--> $DIR/core-traits-no-impls-length-33.rs:19:19
|
||||
--> $DIR/core-traits-no-impls-length-33.rs:20:19
|
||||
|
|
||||
LL | [0_usize; 33] < [1_usize; 33]
|
||||
| ------------- ^ ------------- [usize; 33]
|
||||
|
@ -36,7 +45,7 @@ LL | [0_usize; 33] < [1_usize; 33]
|
|||
= note: an implementation of `std::cmp::PartialOrd` might be missing for `[usize; 33]`
|
||||
|
||||
error[E0277]: the trait bound `&[usize; 33]: std::iter::IntoIterator` is not satisfied
|
||||
--> $DIR/core-traits-no-impls-length-33.rs:24:14
|
||||
--> $DIR/core-traits-no-impls-length-33.rs:25:14
|
||||
|
|
||||
LL | for _ in &[0_usize; 33] {
|
||||
| ^^^^^^^^^^^^^^ the trait `std::iter::IntoIterator` is not implemented for `&[usize; 33]`
|
||||
|
@ -48,7 +57,7 @@ LL | for _ in &[0_usize; 33] {
|
|||
<&'a mut [T] as std::iter::IntoIterator>
|
||||
= note: required by `std::iter::IntoIterator::into_iter`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0369.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
#![feature(raw_ref_op)]
|
||||
|
||||
use std::cell::Cell;
|
||||
|
||||
const A: () = { let x = Cell::new(2); &raw const x; }; //~ ERROR interior mutability
|
||||
|
||||
static B: () = { let x = Cell::new(2); &raw const x; }; //~ ERROR interior mutability
|
||||
|
||||
static mut C: () = { let x = Cell::new(2); &raw const x; }; //~ ERROR interior mutability
|
||||
|
||||
const fn foo() {
|
||||
let x = Cell::new(0);
|
||||
let y = &raw const x; //~ ERROR interior mutability
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,27 @@
|
|||
error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
|
||||
--> $DIR/const-address-of-interior-mut.rs:5:39
|
||||
|
|
||||
LL | const A: () = { let x = Cell::new(2); &raw const x; };
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
|
||||
--> $DIR/const-address-of-interior-mut.rs:7:40
|
||||
|
|
||||
LL | static B: () = { let x = Cell::new(2); &raw const x; };
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
|
||||
--> $DIR/const-address-of-interior-mut.rs:9:44
|
||||
|
|
||||
LL | static mut C: () = { let x = Cell::new(2); &raw const x; };
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
|
||||
--> $DIR/const-address-of-interior-mut.rs:13:13
|
||||
|
|
||||
LL | let y = &raw const x;
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0492`.
|
|
@ -0,0 +1,14 @@
|
|||
#![feature(raw_ref_op)]
|
||||
|
||||
const A: () = { let mut x = 2; &raw mut x; }; //~ ERROR `&raw mut` is not allowed
|
||||
|
||||
static B: () = { let mut x = 2; &raw mut x; }; //~ ERROR `&raw mut` is not allowed
|
||||
|
||||
static mut C: () = { let mut x = 2; &raw mut x; }; //~ ERROR `&raw mut` is not allowed
|
||||
|
||||
const fn foo() {
|
||||
let mut x = 0;
|
||||
let y = &raw mut x; //~ ERROR `&raw mut` is not allowed
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,39 @@
|
|||
error[E0658]: `&raw mut` is not allowed in constants
|
||||
--> $DIR/const-address-of-mut.rs:3:32
|
||||
|
|
||||
LL | const A: () = { let mut x = 2; &raw mut x; };
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/57349
|
||||
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `&raw mut` is not allowed in statics
|
||||
--> $DIR/const-address-of-mut.rs:5:33
|
||||
|
|
||||
LL | static B: () = { let mut x = 2; &raw mut x; };
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/57349
|
||||
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `&raw mut` is not allowed in statics
|
||||
--> $DIR/const-address-of-mut.rs:7:37
|
||||
|
|
||||
LL | static mut C: () = { let mut x = 2; &raw mut x; };
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/57349
|
||||
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `&raw mut` is not allowed in constant functions
|
||||
--> $DIR/const-address-of-mut.rs:11:13
|
||||
|
|
||||
LL | let y = &raw mut x;
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/57349
|
||||
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
|
@ -0,0 +1,19 @@
|
|||
// check-pass
|
||||
|
||||
#![feature(raw_ref_op)]
|
||||
|
||||
const A: *const i32 = &raw const *&2;
|
||||
static B: () = { &raw const *&2; };
|
||||
static mut C: *const i32 = &raw const *&2;
|
||||
const D: () = { let x = 2; &raw const x; };
|
||||
static E: () = { let x = 2; &raw const x; };
|
||||
static mut F: () = { let x = 2; &raw const x; };
|
||||
|
||||
const fn const_ptr() {
|
||||
let x = 0;
|
||||
let ptr = &raw const x;
|
||||
let r = &x;
|
||||
let ptr2 = &raw const *r;
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -2,7 +2,6 @@
|
|||
#![allow(unused)]
|
||||
#![allow(const_err)] // make sure we cannot allow away the errors tested here
|
||||
|
||||
// normalize-stderr-test "alignment \d+" -> "alignment N"
|
||||
// normalize-stderr-test "offset \d+" -> "offset N"
|
||||
// normalize-stderr-test "allocation \d+" -> "allocation N"
|
||||
// normalize-stderr-test "size \d+" -> "size N"
|
||||
|
@ -149,11 +148,23 @@ const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }
|
|||
//~^ ERROR it is undefined behavior to use this value
|
||||
|
||||
// # raw trait object
|
||||
const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust};
|
||||
const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.raw_rust};
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust};
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl } as *const _; // ok because raw
|
||||
|
||||
// Const eval fails for these, so they need to be statics to error.
|
||||
static mut RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF: *const dyn Trait = unsafe {
|
||||
DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust
|
||||
//~^ ERROR could not evaluate static initializer
|
||||
};
|
||||
static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe {
|
||||
DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust
|
||||
//~^ ERROR could not evaluate static initializer
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let _ = RAW_TRAIT_OBJ_VTABLE_NULL;
|
||||
let _ = RAW_TRAIT_OBJ_VTABLE_INVALID;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:87:1
|
||||
--> $DIR/ub-wide-ptr.rs:86:1
|
||||
|
|
||||
LL | const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str};
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds)
|
||||
|
@ -7,7 +7,7 @@ LL | const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr:
|
|||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:90:1
|
||||
--> $DIR/ub-wide-ptr.rs:89:1
|
||||
|
|
||||
LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str};
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
|
||||
|
@ -15,7 +15,7 @@ LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr {
|
|||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:93:1
|
||||
--> $DIR/ub-wide-ptr.rs:92:1
|
||||
|
|
||||
LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str};
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
|
||||
|
@ -23,7 +23,7 @@ LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRe
|
|||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:97:1
|
||||
--> $DIR/ub-wide-ptr.rs:96:1
|
||||
|
|
||||
LL | const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>
|
||||
|
@ -31,7 +31,7 @@ LL | const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
|
|||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:100:1
|
||||
--> $DIR/ub-wide-ptr.rs:99:1
|
||||
|
|
||||
LL | const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>.0
|
||||
|
@ -39,7 +39,7 @@ LL | const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my
|
|||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:107:1
|
||||
--> $DIR/ub-wide-ptr.rs:106:1
|
||||
|
|
||||
LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice};
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered undefined pointer
|
||||
|
@ -47,7 +47,7 @@ LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.sli
|
|||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:110:1
|
||||
--> $DIR/ub-wide-ptr.rs:109:1
|
||||
|
|
||||
LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice};
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds)
|
||||
|
@ -55,7 +55,7 @@ LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { p
|
|||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:113:1
|
||||
--> $DIR/ub-wide-ptr.rs:112:1
|
||||
|
|
||||
LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
|
||||
|
@ -63,7 +63,7 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr
|
|||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:117:1
|
||||
--> $DIR/ub-wide-ptr.rs:116:1
|
||||
|
|
||||
LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>[0], but expected something less or equal to 1
|
||||
|
@ -71,7 +71,7 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.
|
|||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:123:1
|
||||
--> $DIR/ub-wide-ptr.rs:122:1
|
||||
|
|
||||
LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.0, but expected something less or equal to 1
|
||||
|
@ -79,7 +79,7 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute {
|
|||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:126:1
|
||||
--> $DIR/ub-wide-ptr.rs:125:1
|
||||
|
|
||||
LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.1[0], but expected something less or equal to 1
|
||||
|
@ -87,7 +87,7 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTrans
|
|||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:133:1
|
||||
--> $DIR/ub-wide-ptr.rs:132:1
|
||||
|
|
||||
LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice};
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered undefined pointer
|
||||
|
@ -95,7 +95,7 @@ LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr
|
|||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:138:1
|
||||
--> $DIR/ub-wide-ptr.rs:137:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
|
||||
|
@ -103,7 +103,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr:
|
|||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:141:1
|
||||
--> $DIR/ub-wide-ptr.rs:140:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
|
||||
|
@ -111,7 +111,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2:
|
|||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:144:1
|
||||
--> $DIR/ub-wide-ptr.rs:143:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
|
||||
|
@ -119,7 +119,7 @@ LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDy
|
|||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:148:1
|
||||
--> $DIR/ub-wide-ptr.rs:147:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.<dyn-downcast>, but expected something less or equal to 1
|
||||
|
@ -127,21 +127,33 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val
|
|||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:152:1
|
||||
--> $DIR/ub-wide-ptr.rs:151:1
|
||||
|
|
||||
LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust};
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
|
||||
LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.raw_rust};
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:154:1
|
||||
--> $DIR/ub-wide-ptr.rs:153:1
|
||||
|
|
||||
LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust};
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error: aborting due to 18 previous errors
|
||||
error[E0080]: could not evaluate static initializer
|
||||
--> $DIR/ub-wide-ptr.rs:159:5
|
||||
|
|
||||
LL | DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer
|
||||
|
||||
error[E0080]: could not evaluate static initializer
|
||||
--> $DIR/ub-wide-ptr.rs:163:5
|
||||
|
|
||||
LL | DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocation N which has size N
|
||||
|
||||
error: aborting due to 20 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
// check-pass
|
||||
|
||||
#![feature(const_mut_refs)]
|
||||
#![feature(const_fn)]
|
||||
#![feature(raw_ref_op)]
|
||||
|
||||
struct Foo {
|
||||
x: usize
|
||||
}
|
||||
|
||||
const fn foo() -> Foo {
|
||||
Foo { x: 0 }
|
||||
}
|
||||
|
||||
impl Foo {
|
||||
const fn bar(&mut self) -> *mut usize {
|
||||
&raw mut self.x
|
||||
}
|
||||
}
|
||||
|
||||
const fn baz(foo: &mut Foo)-> *mut usize {
|
||||
&raw mut foo.x
|
||||
}
|
||||
|
||||
const _: () = {
|
||||
foo().bar();
|
||||
baz(&mut foo());
|
||||
};
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,7 @@
|
|||
// run-pass (ensure that const-prop is run)
|
||||
|
||||
struct A<T: ?Sized>(T);
|
||||
|
||||
fn main() {
|
||||
let _x = &(&A([2, 3]) as &A<[i32]>).0 as *const [i32] as *const i32;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
#![feature(raw_ref_op)]
|
||||
|
||||
const fn mutable_address_of_in_const() {
|
||||
let mut a = 0;
|
||||
let b = &raw mut a; //~ ERROR `&raw mut` is not allowed
|
||||
}
|
||||
|
||||
struct X;
|
||||
|
||||
impl X {
|
||||
const fn inherent_mutable_address_of_in_const() {
|
||||
let mut a = 0;
|
||||
let b = &raw mut a; //~ ERROR `&raw mut` is not allowed
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,21 @@
|
|||
error[E0658]: `&raw mut` is not allowed in constant functions
|
||||
--> $DIR/address_of.rs:5:13
|
||||
|
|
||||
LL | let b = &raw mut a;
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/57349
|
||||
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `&raw mut` is not allowed in constant functions
|
||||
--> $DIR/address_of.rs:13:17
|
||||
|
|
||||
LL | let b = &raw mut a;
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/57349
|
||||
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
|
@ -0,0 +1,19 @@
|
|||
// check-pass
|
||||
|
||||
#![feature(raw_ref_op)]
|
||||
|
||||
const fn const_address_of_in_const() {
|
||||
let mut a = 0;
|
||||
let b = &raw const a;
|
||||
}
|
||||
|
||||
struct X;
|
||||
|
||||
impl X {
|
||||
const fn inherent_const_address_of_in_const() {
|
||||
let mut a = 0;
|
||||
let b = &raw const a;
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue