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:
bors 2019-12-20 16:24:12 +00:00
commit 01a46509a4
147 changed files with 2769 additions and 1500 deletions

View file

@ -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",

View file

@ -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)),
}
})
}

View file

@ -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()))
})
}

View file

@ -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);

View file

@ -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);

View file

@ -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) => {

View file

@ -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) => {

View file

@ -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:
///

View file

@ -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,
}

View file

@ -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,
);
}
}
}

View file

@ -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);
}

View file

@ -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: [],

View file

@ -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(..) |

View file

@ -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 {

View file

@ -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.

View file

@ -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;

View file

@ -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) {

View file

@ -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) => {

View file

@ -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)

View file

@ -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)

View file

@ -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(..)

View file

@ -276,6 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
| ExprKind::Pointer { .. }
| ExprKind::Repeat { .. }
| ExprKind::Borrow { .. }
| ExprKind::AddressOf { .. }
| ExprKind::Match { .. }
| ExprKind::Loop { .. }
| ExprKind::Block { .. }

View file

@ -276,6 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
| ExprKind::NeverToAny { .. }
| ExprKind::Use { .. }
| ExprKind::Borrow { .. }
| ExprKind::AddressOf { .. }
| ExprKind::Adt { .. }
| ExprKind::Loop { .. }
| ExprKind::LogicalOp { .. }

View file

@ -49,6 +49,7 @@ impl Category {
| ExprKind::Use { .. }
| ExprKind::Adt { .. }
| ExprKind::Borrow { .. }
| ExprKind::AddressOf { .. }
| ExprKind::Call { .. } => Some(Category::Rvalue(RvalueFunc::Into)),
ExprKind::Array { .. }

View file

@ -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,

View file

@ -335,6 +335,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
}
}
Rvalue::Ref(..)
| Rvalue::AddressOf(..)
| Rvalue::Discriminant(..)
| Rvalue::Len(..)
| Rvalue::NullaryOp(NullOp::SizeOf, _)

View file

@ -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,

View file

@ -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>>,

View file

@ -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 {

View file

@ -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

View file

@ -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 {

View file

@ -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,
});
}
}

View file

@ -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);

View file

@ -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;

View file

@ -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),
}
}

View file

@ -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)

View file

@ -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) |

View file

@ -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) {

View file

@ -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) => {

View file

@ -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,

View file

@ -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,

View file

@ -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()
};

View file

@ -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)?;

View file

@ -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 {

View file

@ -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)
}

View file

@ -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);

View file

@ -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);

View file

@ -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!"),
}
});

View file

@ -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(_) => {}
}
}

View file

@ -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),

View file

@ -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;
}
}
}

View file

@ -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.
///

View file

@ -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
}

View file

@ -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) {

View file

@ -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);

View file

@ -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());
}
}

View file

@ -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),
}

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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())
}

View file

@ -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),
}
}

View file

@ -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),
}
}

View file

@ -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,
}
}

View file

@ -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

View file

@ -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;
// }

View file

@ -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

View file

@ -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];
// }
//
// ...

View file

@ -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;

View file

@ -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)) };
}

View file

@ -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

View file

@ -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);
}

View file

@ -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() {}

View file

@ -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();
}
}

View file

@ -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);
}
}

View file

@ -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');
}

View file

@ -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() {}

View file

@ -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`.

View file

@ -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() {}

View file

@ -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() {}

View file

@ -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`.

View file

@ -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() {}

View file

@ -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() {}

View file

@ -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`.

View file

@ -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

View file

@ -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
}

View file

@ -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`.

View file

@ -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
}

View file

@ -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`.

View file

@ -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() {}

View file

@ -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`.

View file

@ -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() {}

View file

@ -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`.

View file

@ -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() {}

View file

@ -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;
}

View file

@ -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`.

View file

@ -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() {}

View file

@ -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;
}

View file

@ -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() {}

View file

@ -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`.

View file

@ -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