diff --git a/Cargo.lock b/Cargo.lock index 1af0442dde7fc..dd7a2147dd1cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -724,16 +724,6 @@ dependencies = [ "smallvec 0.6.10", ] -[[package]] -name = "crossbeam-deque" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils 0.6.5", -] - [[package]] name = "crossbeam-deque" version = "0.7.1" @@ -755,7 +745,7 @@ dependencies = [ "crossbeam-utils 0.6.5", "lazy_static 1.3.0", "memoffset", - "scopeguard 1.0.0", + "scopeguard", ] [[package]] @@ -1407,7 +1397,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3753954f7bd71f0e671afb8b5a992d1724cf43b7f95a563cd4a0bde94659ca8" dependencies = [ - "scopeguard 1.0.0", + "scopeguard", "winapi 0.3.8", ] @@ -1726,7 +1716,7 @@ dependencies = [ "jsonrpc-server-utils", "log", "parity-tokio-ipc", - "parking_lot 0.9.0", + "parking_lot", "tokio-service", ] @@ -1738,7 +1728,7 @@ checksum = "e2c08b444cc0ed70263798834343d0ac875e664257df8079160f23ac1ea79446" dependencies = [ "jsonrpc-core", "log", - "parking_lot 0.9.0", + "parking_lot", "serde", ] @@ -1850,23 +1840,13 @@ dependencies = [ name = "linkchecker" version = "0.1.0" -[[package]] -name = "lock_api" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54" -dependencies = [ - "owning_ref", - "scopeguard 0.3.3", -] - [[package]] name = "lock_api" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" dependencies = [ - "scopeguard 1.0.0", + "scopeguard", ] [[package]] @@ -2027,7 +2007,7 @@ checksum = "c420bbc064623934620b5ab2dc0cf96451b34163329e82f95e7fa1b7b99a6ac8" dependencies = [ "byteorder", "memmap", - "parking_lot 0.9.0", + "parking_lot", "rustc-hash", ] @@ -2320,15 +2300,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd20eec3dbe4376829cb7d80ae6ac45e0a766831dca50202ff2d40db46a8a024" -[[package]] -name = "owning_ref" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" -dependencies = [ - "stable_deref_trait", -] - [[package]] name = "packed_simd" version = "0.3.1" @@ -2377,38 +2348,15 @@ 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", - "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", + "lock_api", + "parking_lot_core", "rustc_version", - "smallvec 0.6.10", - "winapi 0.3.8", ] [[package]] @@ -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", diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index ec9d6802defa3..3f8085f2344b3 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -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 { + 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` @@ -2496,16 +2493,8 @@ impl<'a> LoweringContext<'a> { ) -> hir::GenericBound { // Compute the `T` in `Future` 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![])), }; // "" @@ -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)), } }) } diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index ff9d8c85df8b9..46c944fa67881 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -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, @@ -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` 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)) + } + + 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, expr: &Expr) -> hir::BodyId { - self.lower_body(|this| (hir_vec![], this.lower_expr(expr))) + 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 { }`, 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())) }) } diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 7f72154e42c61..0fdd509a0bbec 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -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); diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index a8d886866795e..0054f149f8c27 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -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); diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index ba8feb4ee739d..3b4adbaf78c74 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -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) => { diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 445fa6ea8cab3..a24b1d863d644 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -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) => { diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 5d273fe85b6d2..fa96b51347d35 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -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: /// diff --git a/src/librustc/ty/cast.rs b/src/librustc/ty/cast.rs index bc12412312deb..fca53db1475a0 100644 --- a/src/librustc/ty/cast.rs +++ b/src/librustc/ty/cast.rs @@ -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, } diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 5479a1f31445e..3f2a51b45bd06 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -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, + ); } } } diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index 6c627085b2ed8..7bcd981678640 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -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); } diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 5e13cabced000..5b21dfbdf1c69 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -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: [], diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 55d63f18cd906..09405cc02b3d4 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -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 ty = cg_place.layout.ty; + 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) + } - // 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(..) | diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index c52c6cfa83c91..922964ee45f6b 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -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 { diff --git a/src/librustc_error_codes/error_codes/E0743.md b/src/librustc_error_codes/error_codes/E0743.md index aaf19d8478ca2..1780fe59cbd69 100644 --- a/src/librustc_error_codes/error_codes/E0743.md +++ b/src/librustc_error_codes/error_codes/E0743.md @@ -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. diff --git a/src/librustc_error_codes/error_codes/E0745.md b/src/librustc_error_codes/error_codes/E0745.md index 39bebdcd3750e..6595691ce786c 100644 --- a/src/librustc_error_codes/error_codes/E0745.md +++ b/src/librustc_error_codes/error_codes/E0745.md @@ -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; diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index c78b3ee07676e..4d686fc310f4a 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -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) { diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 10b00d35d9bca..1fc89961889f1 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -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) => { diff --git a/src/librustc_mir/borrow_check/invalidation.rs b/src/librustc_mir/borrow_check/invalidation.rs index 58fac5512d9b6..d5b9aaf9511a1 100644 --- a/src/librustc_mir/borrow_check/invalidation.rs +++ b/src/librustc_mir/borrow_check/invalidation.rs @@ -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) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 11012ef2fc7ee..2554d5e729da9 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -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) diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 663536bc2b4b6..108279eeef492 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -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(..) diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index ddacda72e1e65..15c7c92d7db51 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -276,6 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::Pointer { .. } | ExprKind::Repeat { .. } | ExprKind::Borrow { .. } + | ExprKind::AddressOf { .. } | ExprKind::Match { .. } | ExprKind::Loop { .. } | ExprKind::Block { .. } diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 37eb0cc9d961e..24282a6617acf 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -276,6 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::NeverToAny { .. } | ExprKind::Use { .. } | ExprKind::Borrow { .. } + | ExprKind::AddressOf { .. } | ExprKind::Adt { .. } | ExprKind::Loop { .. } | ExprKind::LogicalOp { .. } diff --git a/src/librustc_mir/build/expr/category.rs b/src/librustc_mir/build/expr/category.rs index 270a1a6447435..4d0039b2e8cec 100644 --- a/src/librustc_mir/build/expr/category.rs +++ b/src/librustc_mir/build/expr/category.rs @@ -49,6 +49,7 @@ impl Category { | ExprKind::Use { .. } | ExprKind::Adt { .. } | ExprKind::Borrow { .. } + | ExprKind::AddressOf { .. } | ExprKind::Call { .. } => Some(Category::Rvalue(RvalueFunc::Into)), ExprKind::Array { .. } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 07a44b190b20a..6b33e8433f673 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -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, diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index fa0864e0de760..5522da6fbf085 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -335,6 +335,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { } } Rvalue::Ref(..) + | Rvalue::AddressOf(..) | Rvalue::Discriminant(..) | Rvalue::Len(..) | Rvalue::NullaryOp(NullOp::SizeOf, _) diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 8c852854be1f9..6cbc25aa7356e 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -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, -) -> 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, diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 47644d9ba8372..46e0d2a17b32d 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -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>, diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index 33ed69af6ba02..33cdf1b27f8db 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -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 { diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs index dc21c674eea2f..0e4fe3f7f4015 100644 --- a/src/librustc_mir/transform/add_retag.rs +++ b/src/librustc_mir/transform/add_retag.rs @@ -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 diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs index 3df60993d9ad5..e5f3003cd7110 100644 --- a/src/librustc_mir/transform/check_consts/ops.rs +++ b/src/librustc_mir/transform/check_consts/ops.rs @@ -224,6 +224,23 @@ impl NonConstOp for MutBorrow { } } +#[derive(Debug)] +pub struct MutAddressOf; +impl NonConstOp for MutAddressOf { + fn feature_gate(tcx: TyCtxt<'_>) -> Option { + 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 { diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs index 223a5f8d605fc..28243bd71a228 100644 --- a/src/librustc_mir/transform/check_consts/qualifs.rs +++ b/src/librustc_mir/transform/check_consts/qualifs.rs @@ -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, + }); } } diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index 6261315c711cd..0904264586c7c 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -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); - - 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::Ref(_, BorrowKind::Shared, ref place) + | Rvalue::Ref(_, BorrowKind::Shallow, ref place) => { + self.check_immutable_borrow_like(location, place) + }, + + 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); diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 4c723199102be..4e5d8ae08fe5b 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -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; diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index e2530795749a9..a61bff37fc873 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -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), } } diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 67e5bfafafd12..4f482431d3323 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -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) diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 68c2e16399a59..01eebeb8c55a5 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -167,6 +167,8 @@ pub fn categorize(context: PlaceContext) -> Option { 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) | diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs index 1e9203f377f38..38ae7050abe48 100644 --- a/src/librustc_parse/config.rs +++ b/src/librustc_parse/config.rs @@ -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) { diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs index faff386e92318..58c3652438057 100644 --- a/src/librustc_parse/lib.rs +++ b/src/librustc_parse/lib.rs @@ -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) => { diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 3cd4988ce0be5..e4dff07e92cb8 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -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, diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 34ef12e818c57..0840a1551dbf4 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -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, Vec)> { + fn parse_impl_body(&mut self) -> PResult<'a, (Vec, Vec)> { 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, - ) -> 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, - ) -> 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, header: FnHeader, ) -> PResult<'a, Option>> { - 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, 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, - ) -> 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, ) -> PResult<'a, Option>> { 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> { 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> { - 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, diff --git a/src/librustc_parse/parser/path.rs b/src/librustc_parse/parser/path.rs index 5334fc485e7a6..aeba6dd2f67c5 100644 --- a/src/librustc_parse/parser/path.rs +++ b/src/librustc_parse/parser/path.rs @@ -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() }; diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index 84ffef68e9a66..6f7ab0542d5fa 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -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> { + 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> { + 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> { 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)?; diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 202b6ae2f94c4..e90231f984b1f 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -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(&self, sp: Span, body: &Option, 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", " = ;"); + } + AssocItemKind::Fn(sig, body) => { + self.check_impl_item_provided(ii.span, body, "function", " { }"); + self.check_fn_decl(&sig.decl); + } + AssocItemKind::TyAlias(bounds, body) => { + self.check_impl_item_provided(ii.span, body, "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 { diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs index a5924efefc2af..66ceb4212c8ac 100644 --- a/src/librustc_passes/hir_stats.rs +++ b/src/librustc_passes/hir_stats.rs @@ -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) } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index e2578d67e730c..e94e0dc695cd6 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -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); diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs index dd6b1d2119e3d..9bae339f80ea4 100644 --- a/src/librustc_resolve/def_collector.rs +++ b/src/librustc_resolve/def_collector.rs @@ -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); diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 4f95d6fe70f17..4321f62e03bc8 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -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( &mut self, - trait_items: &Vec, + trait_items: &Vec, 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, 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!"), } }); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 396d948433961..df6ad51d1045b 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -676,7 +676,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { generics: &'l ast::Generics, trait_ref: &'l Option, 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(_) => {} } } diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 035ece238104f..21ba02746c79e 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -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), diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 09771bb762536..7f1c6c99cf8d1 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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`, but the `FulfillmentError` references `T`. - ty.walk() - .filter(|&ty| ty == predicate.skip_binder().self_ty()) - .map(move |_| *i) - }) - .collect::>(); + // 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 + } + + 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 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`, but the `FulfillmentError` references `T`. + ty.walk() + .filter(|&ty| ty == predicate.skip_binder().self_ty()) + .map(move |_| *i) + }) + .collect::>(); - // Both checked and coerced types could have matched, thus we need to remove - // duplicates. - referenced_in.dedup(); + // 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; - } + 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; } } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 92ba071a03d68..cf54fd2887af6 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -254,7 +254,7 @@ pub struct ParenthesizedArgs { pub inputs: Vec>, /// `C` - pub output: Option>, + 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,54 +1603,43 @@ pub struct FnSig { pub decl: P, } -/// 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 struct AssocItem { pub attrs: Vec, pub id: NodeId, pub span: Span, pub vis: Visibility, pub ident: Ident, + pub defaultness: Defaultness, pub generics: Generics, - pub kind: TraitItemKind, + pub kind: AssocItemKind, /// See `Item::tokens` for what this is. pub tokens: Option, } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum TraitItemKind { +/// 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 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, Option>), - Method(FnSig, Option>), - Type(GenericBounds, Option>), - Macro(Mac), -} -/// Represents anything within an `impl` block. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct ImplItem { - pub attrs: Vec, - pub id: NodeId, - pub span: Span, - pub vis: Visibility, - pub ident: Ident, + /// An associated function. + Fn(FnSig, Option>), - pub defaultness: Defaultness, - pub generics: Generics, - pub kind: ImplItemKind, - /// See `Item::tokens` for what this is. - pub tokens: Option, -} + /// An associated type. + TyAlias(GenericBounds, Option>), -/// Represents various kinds of content within an `impl`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum ImplItemKind { - Const(P, P), - Method(FnSig, P), - TyAlias(P), + /// 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 { .. }` or `auto trait Foo {}`. - Trait(IsAuto, Unsafety, Generics, GenericBounds, Vec), + Trait(IsAuto, Unsafety, Generics, GenericBounds, Vec), /// Trait alias /// /// E.g., `trait Foo = Bar + Quux;`. @@ -2617,7 +2606,7 @@ pub enum ItemKind { Generics, Option, // (optional) trait this impl implements P, // self - Vec, + Vec, ), /// A macro invocation. /// diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 079a0f6fafa2c..13a9ed5f215d2 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -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 } diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index 99d89183e5b0d..aacd14c3af759 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -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) { diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index f8795d885d216..2a6cff5971c57 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -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) { @@ -553,7 +553,7 @@ pub fn noop_visit_parenthesized_parameter_data(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(asyncness: &mut IsAsync, vis: &mut T) pub fn noop_visit_fn_decl(decl: &mut P, 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(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,58 +940,30 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) { } } -pub fn noop_flat_map_trait_item(mut item: TraitItem, visitor: &mut T) - -> SmallVec<[TraitItem; 1]> +pub fn noop_flat_map_assoc_item(mut item: AssocItem, visitor: &mut T) + -> SmallVec<[AssocItem; 1]> { - let TraitItem { id, ident, vis, attrs, generics, kind, span, tokens: _ } = &mut item; + let AssocItem { id, ident, vis, defaultness: _, 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) => { + match kind { + AssocItemKind::Const(ty, expr) => { visitor.visit_ty(ty); - visit_opt(default, |default| visitor.visit_expr(default)); + visit_opt(expr, |expr| visitor.visit_expr(expr)); } - TraitItemKind::Method(sig, body) => { + AssocItemKind::Fn(sig, body) => { visit_fn_sig(sig, visitor); visit_opt(body, |body| visitor.visit_block(body)); } - TraitItemKind::Type(bounds, default) => { + AssocItemKind::TyAlias(bounds, ty) => { 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(mut item: ImplItem, visitor: &mut T) - -> SmallVec<[ImplItem; 1]> -{ - let ImplItem { id, ident, vis, defaultness: _, 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 { - ImplItemKind::Const(ty, expr) => { - visitor.visit_ty(ty); - visitor.visit_expr(expr); - } - ImplItemKind::Method(sig, body) => { - visit_fn_sig(sig, visitor); - visitor.visit_block(body); + visit_opt(ty, |ty| visitor.visit_ty(ty)); } - ImplItemKind::TyAlias(ty) => visitor.visit_ty(ty), - ImplItemKind::Macro(mac) => visitor.visit_mac(mac), + AssocItemKind::Macro(mac) => visitor.visit_mac(mac), } visitor.visit_span(span); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index f0c5fb32fb16d..87f6ae85b6970 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -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()); } } diff --git a/src/libsyntax/token.rs b/src/libsyntax/token.rs index 6f45211ac5f29..263f8192241f2 100644 --- a/src/libsyntax/token.rs +++ b/src/libsyntax/token.rs @@ -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), } diff --git a/src/libsyntax/util/node_count.rs b/src/libsyntax/util/node_count.rs index a64fec7096132..3db9955d304a3 100644 --- a/src/libsyntax/util/node_count.rs +++ b/src/libsyntax/util/node_count.rs @@ -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; diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 4ee09b4b87afa..51e7fa1eb38b4 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -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); - } - 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); + walk_list!(visitor, visit_ty, ty); } - ImplItemKind::Macro(ref mac) => { + AssocItemKind::Macro(ref mac) => { visitor.visit_mac(mac); } } diff --git a/src/libsyntax_expand/base.rs b/src/libsyntax_expand/base.rs index 72c0b3fde0276..75066a006bf3a 100644 --- a/src/libsyntax_expand/base.rs +++ b/src/libsyntax_expand/base.rs @@ -31,8 +31,8 @@ crate use syntax_pos::hygiene::MacroKind; #[derive(Debug,Clone)] pub enum Annotatable { Item(P), - TraitItem(P), - ImplItem(P), + TraitItem(P), + ImplItem(P), ForeignItem(P), Stmt(P), Expr(P), @@ -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) -> Option> { + fn make_impl_items(self: Box) -> Option> { None } /// Creates zero or more trait items. - fn make_trait_items(self: Box) -> Option> { + fn make_trait_items(self: Box) -> Option> { None } @@ -468,8 +468,8 @@ make_MacEager! { expr: P, pat: P, items: SmallVec<[P; 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, @@ -484,11 +484,11 @@ impl MacResult for MacEager { self.items } - fn make_impl_items(self: Box) -> Option> { + fn make_impl_items(self: Box) -> Option> { self.impl_items } - fn make_trait_items(self: Box) -> Option> { + fn make_trait_items(self: Box) -> Option> { self.trait_items } @@ -588,11 +588,11 @@ impl MacResult for DummyResult { Some(SmallVec::new()) } - fn make_impl_items(self: Box) -> Option> { + fn make_impl_items(self: Box) -> Option> { Some(SmallVec::new()) } - fn make_trait_items(self: Box) -> Option> { + fn make_trait_items(self: Box) -> Option> { Some(SmallVec::new()) } diff --git a/src/libsyntax_expand/expand.rs b/src/libsyntax_expand/expand.rs index dc3d5789d1b55..25c6c287120e9 100644 --- a/src/libsyntax_expand/expand.rs +++ b/src/libsyntax_expand/expand.rs @@ -154,10 +154,10 @@ ast_fragments! { Items(SmallVec<[P; 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), } } diff --git a/src/libsyntax_expand/placeholders.rs b/src/libsyntax_expand/placeholders.rs index faea04e691be5..22e99baae5be0 100644 --- a/src/libsyntax_expand/placeholders.rs +++ b/src/libsyntax_expand/placeholders.rs @@ -50,14 +50,15 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId, vis: Option 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), } } diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 5bd84b43a7801..b7707bfb8e5fb 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -504,13 +504,13 @@ impl<'a> TraitDef<'a> { type_ident: Ident, generics: &Generics, field_tys: Vec>, - methods: Vec) + methods: Vec) -> P { 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, arg_types: Vec<(Ident, P)>, body: P) - -> 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, } } diff --git a/src/test/mir-opt/address-of.rs b/src/test/mir-opt/address-of.rs new file mode 100644 index 0000000000000..bbd1ca68a8672 --- /dev/null +++ b/src/test/mir-opt/address-of.rs @@ -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 diff --git a/src/test/mir-opt/array-index-is-temporary.rs b/src/test/mir-opt/array-index-is-temporary.rs index 00a6b26d0cf22..096f98bade25a 100644 --- a/src/test/mir-opt/array-index-is-temporary.rs +++ b/src/test/mir-opt/array-index-is-temporary.rs @@ -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; // } diff --git a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs index 3f82b81a47de5..3c8c0ff449345 100644 --- a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs +++ b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs @@ -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 diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs index 32995448a21e9..ccecaeac96b83 100644 --- a/src/test/mir-opt/retag.rs +++ b/src/test/mir-opt/retag.rs @@ -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]; // } // // ... diff --git a/src/test/mir-opt/slice-drop-shim.rs b/src/test/mir-opt/slice-drop-shim.rs index f270dec5fe232..5a37b67229c37 100644 --- a/src/test/mir-opt/slice-drop-shim.rs +++ b/src/test/mir-opt/slice-drop-shim.rs @@ -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; diff --git a/src/test/pretty/raw-address-of.rs b/src/test/pretty/raw-address-of.rs new file mode 100644 index 0000000000000..6ccc434a1e79c --- /dev/null +++ b/src/test/pretty/raw-address-of.rs @@ -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)) }; +} diff --git a/src/test/run-make/wasm-symbols-different-module/Makefile b/src/test/run-make/wasm-symbols-different-module/Makefile new file mode 100644 index 0000000000000..bb6a5d3c9d24a --- /dev/null +++ b/src/test/run-make/wasm-symbols-different-module/Makefile @@ -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 diff --git a/src/test/run-make/wasm-symbols-different-module/bar.rs b/src/test/run-make/wasm-symbols-different-module/bar.rs new file mode 100644 index 0000000000000..7567060d7813a --- /dev/null +++ b/src/test/run-make/wasm-symbols-different-module/bar.rs @@ -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); +} diff --git a/src/test/run-make/wasm-symbols-different-module/baz.rs b/src/test/run-make/wasm-symbols-different-module/baz.rs new file mode 100644 index 0000000000000..fbb78619bb8f5 --- /dev/null +++ b/src/test/run-make/wasm-symbols-different-module/baz.rs @@ -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() {} diff --git a/src/test/run-make/wasm-symbols-different-module/foo.rs b/src/test/run-make/wasm-symbols-different-module/foo.rs new file mode 100644 index 0000000000000..a4ba7e714cc77 --- /dev/null +++ b/src/test/run-make/wasm-symbols-different-module/foo.rs @@ -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(); + } +} diff --git a/src/test/run-make/wasm-symbols-different-module/log.rs b/src/test/run-make/wasm-symbols-different-module/log.rs new file mode 100644 index 0000000000000..ea3e0b4b2be91 --- /dev/null +++ b/src/test/run-make/wasm-symbols-different-module/log.rs @@ -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); + } +} diff --git a/src/test/run-make/wasm-symbols-different-module/verify-imports.js b/src/test/run-make/wasm-symbols-different-module/verify-imports.js new file mode 100644 index 0000000000000..7e9f90cf8bdc6 --- /dev/null +++ b/src/test/run-make/wasm-symbols-different-module/verify-imports.js @@ -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'); +} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-borrowed.rs b/src/test/ui/borrowck/borrow-raw-address-of-borrowed.rs new file mode 100644 index 0000000000000..f25fd7f66b3cc --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-borrowed.rs @@ -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() {} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-borrowed.stderr b/src/test/ui/borrowck/borrow-raw-address-of-borrowed.stderr new file mode 100644 index 0000000000000..ff461b748be88 --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-borrowed.stderr @@ -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`. diff --git a/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs new file mode 100644 index 0000000000000..e381384fe65ec --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs @@ -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() {} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.rs b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.rs new file mode 100644 index 0000000000000..712873528b5f1 --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.rs @@ -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() {} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr new file mode 100644 index 0000000000000..31af38507c7d7 --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr @@ -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`. diff --git a/src/test/ui/borrowck/borrow-raw-address-of-mutability-ok.rs b/src/test/ui/borrowck/borrow-raw-address-of-mutability-ok.rs new file mode 100644 index 0000000000000..e1cf2dc53869b --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-mutability-ok.rs @@ -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: 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() {} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-mutability.rs b/src/test/ui/borrowck/borrow-raw-address-of-mutability.rs new file mode 100644 index 0000000000000..320c54b806a72 --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-mutability.rs @@ -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: 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() {} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr b/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr new file mode 100644 index 0000000000000..cf01c362d50bc --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr @@ -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`. diff --git a/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr index cb6060525fc0d..7af38c88f4334 100644 --- a/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr @@ -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 diff --git a/src/test/ui/cast/cast-as-bool.rs b/src/test/ui/cast/cast-as-bool.rs index 8130f4dedc9aa..1aed218aeb473 100644 --- a/src/test/ui/cast/cast-as-bool.rs +++ b/src/test/ui/cast/cast-as-bool.rs @@ -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 } diff --git a/src/test/ui/cast/cast-as-bool.stderr b/src/test/ui/cast/cast-as-bool.stderr index 30f8459c2e1e1..15d94ab69d88c 100644 --- a/src/test/ui/cast/cast-as-bool.stderr +++ b/src/test/ui/cast/cast-as-bool.stderr @@ -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`. diff --git a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs index 8397d204f35cf..7fa059583f539 100644 --- a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs +++ b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs @@ -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 } diff --git a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr index 594a0d4b5d844..d885c98dcb287 100644 --- a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr +++ b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr @@ -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::::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`. diff --git a/src/test/ui/consts/const-address-of-interior-mut.rs b/src/test/ui/consts/const-address-of-interior-mut.rs new file mode 100644 index 0000000000000..60c7c31daca78 --- /dev/null +++ b/src/test/ui/consts/const-address-of-interior-mut.rs @@ -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() {} diff --git a/src/test/ui/consts/const-address-of-interior-mut.stderr b/src/test/ui/consts/const-address-of-interior-mut.stderr new file mode 100644 index 0000000000000..f15174c33b3a0 --- /dev/null +++ b/src/test/ui/consts/const-address-of-interior-mut.stderr @@ -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`. diff --git a/src/test/ui/consts/const-address-of-mut.rs b/src/test/ui/consts/const-address-of-mut.rs new file mode 100644 index 0000000000000..fe9188cb4904c --- /dev/null +++ b/src/test/ui/consts/const-address-of-mut.rs @@ -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() {} diff --git a/src/test/ui/consts/const-address-of-mut.stderr b/src/test/ui/consts/const-address-of-mut.stderr new file mode 100644 index 0000000000000..15f2296c42c25 --- /dev/null +++ b/src/test/ui/consts/const-address-of-mut.stderr @@ -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`. diff --git a/src/test/ui/consts/const-address-of.rs b/src/test/ui/consts/const-address-of.rs new file mode 100644 index 0000000000000..ba162f2a2badf --- /dev/null +++ b/src/test/ui/consts/const-address-of.rs @@ -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() {} diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs index 1f810c40572c0..a5c2a57c6c886 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -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; } diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr index 85fb8ac2a4a36..ce57d680dc95d 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -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 . @@ -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 ..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 .[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 ..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 ..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 .., 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`. diff --git a/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs b/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs new file mode 100644 index 0000000000000..130ba9283b1d9 --- /dev/null +++ b/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs @@ -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() {} diff --git a/src/test/ui/consts/const-prop-ice3.rs b/src/test/ui/consts/const-prop-ice3.rs new file mode 100644 index 0000000000000..8ab011661e3c5 --- /dev/null +++ b/src/test/ui/consts/const-prop-ice3.rs @@ -0,0 +1,7 @@ +// run-pass (ensure that const-prop is run) + +struct A(T); + +fn main() { + let _x = &(&A([2, 3]) as &A<[i32]>).0 as *const [i32] as *const i32; +} diff --git a/src/test/ui/consts/min_const_fn/address_of.rs b/src/test/ui/consts/min_const_fn/address_of.rs new file mode 100644 index 0000000000000..f8506d70b2498 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/address_of.rs @@ -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() {} diff --git a/src/test/ui/consts/min_const_fn/address_of.stderr b/src/test/ui/consts/min_const_fn/address_of.stderr new file mode 100644 index 0000000000000..3554b8112b168 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/address_of.stderr @@ -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`. diff --git a/src/test/ui/consts/min_const_fn/address_of_const.rs b/src/test/ui/consts/min_const_fn/address_of_const.rs new file mode 100644 index 0000000000000..3db19e9cde8f0 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/address_of_const.rs @@ -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() {} diff --git a/src/test/ui/did_you_mean/issue-40006.rs b/src/test/ui/did_you_mean/issue-40006.rs index b3c1f60b7ebf6..ea21592997bfe 100644 --- a/src/test/ui/did_you_mean/issue-40006.rs +++ b/src/test/ui/did_you_mean/issue-40006.rs @@ -18,10 +18,10 @@ trait A { //~ ERROR missing trait B { fn xxx() { ### } //~ ERROR expected } -trait C { //~ ERROR missing `fn`, `type`, or `const` for trait-item declaration +trait C { //~ ERROR missing `fn`, `type`, or `const` for associated-item declaration L = M; } -trait D { //~ ERROR missing `fn`, `type`, or `const` for trait-item declaration +trait D { //~ ERROR missing `fn`, `type`, or `const` for associated-item declaration Z = { 2 + 3 }; } trait E { diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr index 30ae6ed4c6d49..d1e995013cb93 100644 --- a/src/test/ui/did_you_mean/issue-40006.stderr +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -1,4 +1,4 @@ -error: missing `fn`, `type`, or `const` for impl-item declaration +error: missing `fn`, `type`, or `const` for associated-item declaration --> $DIR/issue-40006.rs:1:13 | LL | impl dyn A { @@ -6,7 +6,7 @@ LL | impl dyn A { LL | | Y | |____^ missing `fn`, `type`, or `const` -error: missing `fn`, `type`, or `const` for trait-item declaration +error: missing `fn`, `type`, or `const` for associated-item declaration --> $DIR/issue-40006.rs:7:10 | LL | trait X { @@ -14,7 +14,7 @@ LL | trait X { LL | | X() {} | |____^ missing `fn`, `type`, or `const` -error: missing `fn`, `type`, or `const` for trait-item declaration +error: missing `fn`, `type`, or `const` for associated-item declaration --> $DIR/issue-40006.rs:15:10 | LL | trait A { @@ -28,7 +28,7 @@ error: expected `[`, found `#` LL | fn xxx() { ### } | ^ expected `[` -error: missing `fn`, `type`, or `const` for trait-item declaration +error: missing `fn`, `type`, or `const` for associated-item declaration --> $DIR/issue-40006.rs:21:10 | LL | trait C { @@ -36,7 +36,7 @@ LL | trait C { LL | | L = M; | |____^ missing `fn`, `type`, or `const` -error: missing `fn`, `type`, or `const` for trait-item declaration +error: missing `fn`, `type`, or `const` for associated-item declaration --> $DIR/issue-40006.rs:24:10 | LL | trait D { @@ -50,7 +50,7 @@ error: expected one of `!` or `::`, found `(` LL | ::Y (); | ^ expected one of `!` or `::` -error: missing `fn`, `type`, or `const` for impl-item declaration +error: missing `fn`, `type`, or `const` for associated-item declaration --> $DIR/issue-40006.rs:32:8 | LL | pub hello_method(&self) { diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr index d9ebcdecb9bfd..1f61473c9d2f4 100644 --- a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr +++ b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr @@ -16,15 +16,6 @@ LL | type Baa = impl Debug; = note: for more information, see https://github.com/rust-lang/rust/issues/63063 = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable -error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/feature-gate-type_alias_impl_trait.rs:18:18 - | -LL | type Assoc = impl Debug; - | ^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/63063 - = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable - error[E0658]: associated type defaults are unstable --> $DIR/feature-gate-type_alias_impl_trait.rs:18:5 | @@ -34,6 +25,15 @@ LL | type Assoc = impl Debug; = note: for more information, see https://github.com/rust-lang/rust/issues/29661 = help: add `#![feature(associated_type_defaults)]` to the crate attributes to enable +error[E0658]: `impl Trait` in type aliases is unstable + --> $DIR/feature-gate-type_alias_impl_trait.rs:18:18 + | +LL | type Assoc = impl Debug; + | ^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/63063 + = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable + error[E0658]: `impl Trait` in type aliases is unstable --> $DIR/feature-gate-type_alias_impl_trait.rs:24:24 | diff --git a/src/test/ui/invalid/invalid-variadic-function.rs b/src/test/ui/invalid/invalid-variadic-function.rs deleted file mode 100644 index 8d23f0e477077..0000000000000 --- a/src/test/ui/invalid/invalid-variadic-function.rs +++ /dev/null @@ -1,3 +0,0 @@ -extern "C" fn foo(x: u8, ...); -//~^ ERROR only foreign functions are allowed to be C-variadic -//~| ERROR expected one of `->`, `where`, or `{`, found `;` diff --git a/src/test/ui/invalid/invalid-variadic-function.stderr b/src/test/ui/invalid/invalid-variadic-function.stderr deleted file mode 100644 index 7e58b17e7db74..0000000000000 --- a/src/test/ui/invalid/invalid-variadic-function.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0743]: only foreign functions are allowed to be C-variadic - --> $DIR/invalid-variadic-function.rs:1:26 - | -LL | extern "C" fn foo(x: u8, ...); - | ^^^ - -error: expected one of `->`, `where`, or `{`, found `;` - --> $DIR/invalid-variadic-function.rs:1:30 - | -LL | extern "C" fn foo(x: u8, ...); - | ^ expected one of `->`, `where`, or `{` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0743`. diff --git a/src/test/ui/issues/issue-58856-1.rs b/src/test/ui/issues/issue-58856-1.rs index db3984cd18987..8b1a39a94e67a 100644 --- a/src/test/ui/issues/issue-58856-1.rs +++ b/src/test/ui/issues/issue-58856-1.rs @@ -1,6 +1,8 @@ impl A { + //~^ ERROR cannot find type `A` in this scope fn b(self> //~^ ERROR expected one of `)`, `,`, or `:`, found `>` + //~| ERROR expected `;` or `{`, found `>` } fn main() {} diff --git a/src/test/ui/issues/issue-58856-1.stderr b/src/test/ui/issues/issue-58856-1.stderr index 58ab0a142d6f1..0ea6b01754890 100644 --- a/src/test/ui/issues/issue-58856-1.stderr +++ b/src/test/ui/issues/issue-58856-1.stderr @@ -1,10 +1,23 @@ error: expected one of `)`, `,`, or `:`, found `>` - --> $DIR/issue-58856-1.rs:2:14 + --> $DIR/issue-58856-1.rs:3:14 | LL | fn b(self> | - ^ help: `)` may belong here | | | unclosed delimiter -error: aborting due to previous error +error: expected `;` or `{`, found `>` + --> $DIR/issue-58856-1.rs:3:14 + | +LL | fn b(self> + | ^ expected `;` or `{` + +error[E0412]: cannot find type `A` in this scope + --> $DIR/issue-58856-1.rs:1:6 + | +LL | impl A { + | ^ not found in this scope + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/issues/issue-60075.stderr b/src/test/ui/issues/issue-60075.stderr index e0b15130c337d..e8ef981f515fc 100644 --- a/src/test/ui/issues/issue-60075.stderr +++ b/src/test/ui/issues/issue-60075.stderr @@ -4,7 +4,7 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `}` LL | }); | ^ expected one of `.`, `;`, `?`, `else`, or an operator -error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `;` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `;` --> $DIR/issue-60075.rs:6:11 | LL | fn qux() -> Option { diff --git a/src/test/ui/issues/issue-66923-show-error-for-correct-call.rs b/src/test/ui/issues/issue-66923-show-error-for-correct-call.rs new file mode 100644 index 0000000000000..8332807397247 --- /dev/null +++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.rs @@ -0,0 +1,15 @@ +// This test checks that errors are showed for lines with `collect` rather than `push` method. + +fn main() { + let v = vec![1_f64, 2.2_f64]; + let mut fft: Vec> = vec![]; + + let x1: &[f64] = &v; + let x2: Vec = x1.into_iter().collect(); + //~^ ERROR a value of type + fft.push(x2); + + let x3 = x1.into_iter().collect::>(); + //~^ ERROR a value of type + fft.push(x3); +} diff --git a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr new file mode 100644 index 0000000000000..8e7ee97e0b907 --- /dev/null +++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr @@ -0,0 +1,19 @@ +error[E0277]: a value of type `std::vec::Vec` cannot be built from an iterator over elements of type `&f64` + --> $DIR/issue-66923-show-error-for-correct-call.rs:8:39 + | +LL | let x2: Vec = x1.into_iter().collect(); + | ^^^^^^^ value of type `std::vec::Vec` cannot be built from `std::iter::Iterator` + | + = help: the trait `std::iter::FromIterator<&f64>` is not implemented for `std::vec::Vec` + +error[E0277]: a value of type `std::vec::Vec` cannot be built from an iterator over elements of type `&f64` + --> $DIR/issue-66923-show-error-for-correct-call.rs:12:29 + | +LL | let x3 = x1.into_iter().collect::>(); + | ^^^^^^^ value of type `std::vec::Vec` cannot be built from `std::iter::Iterator` + | + = help: the trait `std::iter::FromIterator<&f64>` is not implemented for `std::vec::Vec` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/lint/lint-unused-mut-variables.rs b/src/test/ui/lint/lint-unused-mut-variables.rs index 1af44ecf362bf..dd8dbda6d4303 100644 --- a/src/test/ui/lint/lint-unused-mut-variables.rs +++ b/src/test/ui/lint/lint-unused-mut-variables.rs @@ -3,7 +3,7 @@ // Exercise the unused_mut attribute in some positive and negative cases #![deny(unused_mut)] -#![feature(async_closure)] +#![feature(async_closure, raw_ref_op)] async fn baz_async( mut a: i32, @@ -177,6 +177,12 @@ fn main() { // leading underscore should avoid the warning, just like the // unused variable lint. let mut _allowed = 1; + + let mut raw_address_of_mut = 1; // OK + let mut_ptr = &raw mut raw_address_of_mut; + + let mut raw_address_of_const = 1; //~ ERROR: variable does not need to be mutable + let const_ptr = &raw const raw_address_of_const; } fn callback(f: F) where F: FnOnce() {} diff --git a/src/test/ui/lint/lint-unused-mut-variables.stderr b/src/test/ui/lint/lint-unused-mut-variables.stderr index 92c2b68652dc2..c1ab0ab33d4cc 100644 --- a/src/test/ui/lint/lint-unused-mut-variables.stderr +++ b/src/test/ui/lint/lint-unused-mut-variables.stderr @@ -180,6 +180,14 @@ LL | let mut v : &mut Vec<()> = &mut vec![]; | | | help: remove this `mut` +error: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:184:9 + | +LL | let mut raw_address_of_const = 1; + | ----^^^^^^^^^^^^^^^^^^^^ + | | + | help: remove this `mut` + error: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:106:13 | @@ -197,7 +205,7 @@ LL | fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] { | help: remove this `mut` error: variable does not need to be mutable - --> $DIR/lint-unused-mut-variables.rs:196:9 + --> $DIR/lint-unused-mut-variables.rs:202:9 | LL | let mut b = vec![2]; | ----^ @@ -205,10 +213,10 @@ LL | let mut b = vec![2]; | help: remove this `mut` | note: lint level defined here - --> $DIR/lint-unused-mut-variables.rs:192:8 + --> $DIR/lint-unused-mut-variables.rs:198:8 | LL | #[deny(unused_mut)] | ^^^^^^^^^^ -error: aborting due to 25 previous errors +error: aborting due to 26 previous errors diff --git a/src/test/ui/packed/packed-struct-address-of-element.rs b/src/test/ui/packed/packed-struct-address-of-element.rs new file mode 100644 index 0000000000000..812d23fb58023 --- /dev/null +++ b/src/test/ui/packed/packed-struct-address-of-element.rs @@ -0,0 +1,37 @@ +// run-pass +#![allow(dead_code)] +#![deny(safe_packed_borrows)] +#![feature(raw_ref_op)] +// ignore-emscripten weird assertion? + +#[repr(packed)] +struct Foo1 { + bar: u8, + baz: usize +} + +#[repr(packed(2))] +struct Foo2 { + bar: u8, + baz: usize +} + +#[repr(C, packed(4))] +struct Foo4C { + bar: u8, + baz: usize +} + +pub fn main() { + let foo = Foo1 { bar: 1, baz: 2 }; + let brw = &raw const foo.baz; + unsafe { assert_eq!(brw.read_unaligned(), 2); } + + let foo = Foo2 { bar: 1, baz: 2 }; + let brw = &raw const foo.baz; + unsafe { assert_eq!(brw.read_unaligned(), 2); } + + let mut foo = Foo4C { bar: 1, baz: 2 }; + let brw = &raw mut foo.baz; + unsafe { assert_eq!(brw.read_unaligned(), 2); } +} diff --git a/src/test/ui/packed/packed-struct-borrow-element.rs b/src/test/ui/packed/packed-struct-borrow-element.rs index 6ac42ed0d471b..0072b6191ebb0 100644 --- a/src/test/ui/packed/packed-struct-borrow-element.rs +++ b/src/test/ui/packed/packed-struct-borrow-element.rs @@ -1,4 +1,4 @@ -// run-pass +// run-pass (note: this is spec-UB, but it works for now) #![allow(dead_code)] // ignore-emscripten weird assertion? diff --git a/src/test/ui/parser/impl-item-const-pass.rs b/src/test/ui/parser/impl-item-const-pass.rs new file mode 100644 index 0000000000000..d1124561374a5 --- /dev/null +++ b/src/test/ui/parser/impl-item-const-pass.rs @@ -0,0 +1,8 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +impl X { + const Y: u8; +} diff --git a/src/test/ui/parser/impl-item-const-semantic-fail.rs b/src/test/ui/parser/impl-item-const-semantic-fail.rs new file mode 100644 index 0000000000000..5d4692f9f14ac --- /dev/null +++ b/src/test/ui/parser/impl-item-const-semantic-fail.rs @@ -0,0 +1,7 @@ +fn main() {} + +struct X; + +impl X { + const Y: u8; //~ ERROR associated constant in `impl` without body +} diff --git a/src/test/ui/parser/impl-item-const-semantic-fail.stderr b/src/test/ui/parser/impl-item-const-semantic-fail.stderr new file mode 100644 index 0000000000000..ec3bee0ce6824 --- /dev/null +++ b/src/test/ui/parser/impl-item-const-semantic-fail.stderr @@ -0,0 +1,10 @@ +error: associated constant in `impl` without body + --> $DIR/impl-item-const-semantic-fail.rs:6:5 + | +LL | const Y: u8; + | ^^^^^^^^^^^- + | | + | help: provide a definition for the constant: `= ;` + +error: aborting due to previous error + diff --git a/src/test/ui/parser/impl-item-fn-no-body-pass.rs b/src/test/ui/parser/impl-item-fn-no-body-pass.rs new file mode 100644 index 0000000000000..16b09d64e8c17 --- /dev/null +++ b/src/test/ui/parser/impl-item-fn-no-body-pass.rs @@ -0,0 +1,8 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +impl X { + fn f(); +} diff --git a/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.rs b/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.rs new file mode 100644 index 0000000000000..cb183db59643e --- /dev/null +++ b/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.rs @@ -0,0 +1,7 @@ +fn main() {} + +struct X; + +impl X { + fn f(); //~ ERROR associated function in `impl` without body +} diff --git a/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.stderr b/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.stderr new file mode 100644 index 0000000000000..1acb727368bce --- /dev/null +++ b/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.stderr @@ -0,0 +1,10 @@ +error: associated function in `impl` without body + --> $DIR/impl-item-fn-no-body-semantic-fail.rs:6:5 + | +LL | fn f(); + | ^^^^^^- + | | + | help: provide a definition for the function: `{ }` + +error: aborting due to previous error + diff --git a/src/test/ui/parser/impl-item-type-no-body-pass.rs b/src/test/ui/parser/impl-item-type-no-body-pass.rs new file mode 100644 index 0000000000000..74a9c6ab7e8a6 --- /dev/null +++ b/src/test/ui/parser/impl-item-type-no-body-pass.rs @@ -0,0 +1,11 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +impl X { + type Y; + type Z: Ord; + type W: Ord where Self: Eq; + type W where Self: Eq; +} diff --git a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs new file mode 100644 index 0000000000000..71c7d4ba21db6 --- /dev/null +++ b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs @@ -0,0 +1,22 @@ +#![feature(generic_associated_types)] +//~^ WARN the feature `generic_associated_types` is incomplete + +fn main() {} + +struct X; + +impl X { + type Y; + //~^ ERROR associated type in `impl` without body + //~| ERROR associated types are not yet supported in inherent impls + type Z: Ord; + //~^ ERROR associated type in `impl` without body + //~| ERROR bounds on associated `type`s in `impl`s have no effect + //~| ERROR associated types are not yet supported in inherent impls + type W: Ord where Self: Eq; + //~^ ERROR associated type in `impl` without body + //~| ERROR bounds on associated `type`s in `impl`s have no effect + //~| ERROR associated types are not yet supported in inherent impls + type W where Self: Eq; + //~^ ERROR associated type in `impl` without body +} diff --git a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr new file mode 100644 index 0000000000000..6f1439c8f0b29 --- /dev/null +++ b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr @@ -0,0 +1,73 @@ +error: associated type in `impl` without body + --> $DIR/impl-item-type-no-body-semantic-fail.rs:9:5 + | +LL | type Y; + | ^^^^^^- + | | + | help: provide a definition for the type: `= ;` + +error: associated type in `impl` without body + --> $DIR/impl-item-type-no-body-semantic-fail.rs:12:5 + | +LL | type Z: Ord; + | ^^^^^^^^^^^- + | | + | help: provide a definition for the type: `= ;` + +error: bounds on associated `type`s in `impl`s have no effect + --> $DIR/impl-item-type-no-body-semantic-fail.rs:12:13 + | +LL | type Z: Ord; + | ^^^ + +error: associated type in `impl` without body + --> $DIR/impl-item-type-no-body-semantic-fail.rs:16:5 + | +LL | type W: Ord where Self: Eq; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the type: `= ;` + +error: bounds on associated `type`s in `impl`s have no effect + --> $DIR/impl-item-type-no-body-semantic-fail.rs:16:13 + | +LL | type W: Ord where Self: Eq; + | ^^^ + +error: associated type in `impl` without body + --> $DIR/impl-item-type-no-body-semantic-fail.rs:20:5 + | +LL | type W where Self: Eq; + | ^^^^^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the type: `= ;` + +warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash + --> $DIR/impl-item-type-no-body-semantic-fail.rs:1:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0202]: associated types are not yet supported in inherent impls (see #8995) + --> $DIR/impl-item-type-no-body-semantic-fail.rs:9:5 + | +LL | type Y; + | ^^^^^^^ + +error[E0202]: associated types are not yet supported in inherent impls (see #8995) + --> $DIR/impl-item-type-no-body-semantic-fail.rs:12:5 + | +LL | type Z: Ord; + | ^^^^^^^^^^^^ + +error[E0202]: associated types are not yet supported in inherent impls (see #8995) + --> $DIR/impl-item-type-no-body-semantic-fail.rs:16:5 + | +LL | type W: Ord where Self: Eq; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0202`. diff --git a/src/test/ui/parser/issue-21153.stderr b/src/test/ui/parser/issue-21153.stderr index 70f55f0aeb9ff..6e20a9ce3c432 100644 --- a/src/test/ui/parser/issue-21153.stderr +++ b/src/test/ui/parser/issue-21153.stderr @@ -1,4 +1,4 @@ -error: missing `fn`, `type`, or `const` for trait-item declaration +error: missing `fn`, `type`, or `const` for associated-item declaration --> $DIR/issue-21153.rs:1:29 | LL | trait MyTrait: Iterator { diff --git a/src/test/ui/parser/issue-32446.stderr b/src/test/ui/parser/issue-32446.stderr index 70256a59231fb..1a97f54160b24 100644 --- a/src/test/ui/parser/issue-32446.stderr +++ b/src/test/ui/parser/issue-32446.stderr @@ -1,8 +1,8 @@ -error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `...` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `...` --> $DIR/issue-32446.rs:4:11 | LL | trait T { ... } - | ^^^ expected one of 9 possible tokens + | ^^^ expected one of 10 possible tokens error: aborting due to previous error diff --git a/src/test/ui/parser/macro/trait-non-item-macros.stderr b/src/test/ui/parser/macro/trait-non-item-macros.stderr index 0a433ab278e43..7647ba500e03a 100644 --- a/src/test/ui/parser/macro/trait-non-item-macros.stderr +++ b/src/test/ui/parser/macro/trait-non-item-macros.stderr @@ -1,8 +1,8 @@ -error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `2` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `2` --> $DIR/trait-non-item-macros.rs:2:19 | LL | ($a:expr) => ($a) - | ^^ expected one of 8 possible tokens + | ^^ expected one of 9 possible tokens ... LL | bah!(2); | -------- in this macro invocation diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr index cbaf9315e8540..7e8abf22d55ab 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr @@ -7,11 +7,11 @@ LL | trait T { LL | fn main() {} | ^ -error: expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`, found keyword `struct` +error: expected one of `async`, `const`, `default`, `extern`, `fn`, `type`, or `unsafe`, found keyword `struct` --> $DIR/missing-close-brace-in-trait.rs:5:12 | LL | pub(crate) struct Bar(); - | ^^^^^^ expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe` + | ^^^^^^ expected one of 7 possible tokens error[E0601]: `main` function not found in crate `missing_close_brace_in_trait` --> $DIR/missing-close-brace-in-trait.rs:1:1 diff --git a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs new file mode 100644 index 0000000000000..09f967f161ede --- /dev/null +++ b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs @@ -0,0 +1,12 @@ +#![feature(specialization)] + +fn main() {} + +trait X { + default const A: u8; //~ ERROR `default` is only allowed on items in `impl` definitions + default const B: u8 = 0; //~ ERROR `default` is only allowed on items in `impl` definitions + default type D; //~ ERROR `default` is only allowed on items in `impl` definitions + default type C: Ord; //~ ERROR `default` is only allowed on items in `impl` definitions + default fn f1(); //~ ERROR `default` is only allowed on items in `impl` definitions + default fn f2() {} //~ ERROR `default` is only allowed on items in `impl` definitions +} diff --git a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr new file mode 100644 index 0000000000000..54111df342343 --- /dev/null +++ b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr @@ -0,0 +1,38 @@ +error: `default` is only allowed on items in `impl` definitions + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:6:5 + | +LL | default const A: u8; + | ^^^^^^^^^^^^^^^^^^^^ + +error: `default` is only allowed on items in `impl` definitions + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:7:5 + | +LL | default const B: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `default` is only allowed on items in `impl` definitions + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:8:5 + | +LL | default type D; + | ^^^^^^^^^^^^^^^ + +error: `default` is only allowed on items in `impl` definitions + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:9:5 + | +LL | default type C: Ord; + | ^^^^^^^^^^^^^^^^^^^^ + +error: `default` is only allowed on items in `impl` definitions + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:10:5 + | +LL | default fn f1(); + | ^^^^^^^^^^^^^^^^ + +error: `default` is only allowed on items in `impl` definitions + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:11:5 + | +LL | default fn f2() {} + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/parser/trait-item-with-defaultness-pass.rs b/src/test/ui/parser/trait-item-with-defaultness-pass.rs new file mode 100644 index 0000000000000..a6318bd99e2f6 --- /dev/null +++ b/src/test/ui/parser/trait-item-with-defaultness-pass.rs @@ -0,0 +1,13 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +trait X { + default const A: u8; + default const B: u8 = 0; + default type D; + default type C: Ord; + default fn f1(); + default fn f2() {} +} diff --git a/src/test/ui/parser/variadic-ffi-3.rs b/src/test/ui/parser/variadic-ffi-3.rs deleted file mode 100644 index ce83cc87abe00..0000000000000 --- a/src/test/ui/parser/variadic-ffi-3.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn foo(x: isize, ...) { - //~^ ERROR: only foreign functions are allowed to be C-variadic -} - -fn main() {} diff --git a/src/test/ui/parser/variadic-ffi-3.stderr b/src/test/ui/parser/variadic-ffi-3.stderr deleted file mode 100644 index aeeebdb991483..0000000000000 --- a/src/test/ui/parser/variadic-ffi-3.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0743]: only foreign functions are allowed to be C-variadic - --> $DIR/variadic-ffi-3.rs:1:18 - | -LL | fn foo(x: isize, ...) { - | ^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0743`. diff --git a/src/test/ui/parser/variadic-ffi-4.rs b/src/test/ui/parser/variadic-ffi-4.rs deleted file mode 100644 index 5f8b3f8f539b8..0000000000000 --- a/src/test/ui/parser/variadic-ffi-4.rs +++ /dev/null @@ -1,5 +0,0 @@ -extern "C" fn foo(x: isize, ...) { - //~^ ERROR: only foreign functions are allowed to be C-variadic -} - -fn main() {} diff --git a/src/test/ui/parser/variadic-ffi-4.stderr b/src/test/ui/parser/variadic-ffi-4.stderr deleted file mode 100644 index da83276c72dd1..0000000000000 --- a/src/test/ui/parser/variadic-ffi-4.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0743]: only foreign functions are allowed to be C-variadic - --> $DIR/variadic-ffi-4.rs:1:29 - | -LL | extern "C" fn foo(x: isize, ...) { - | ^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0743`. diff --git a/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.rs b/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.rs new file mode 100644 index 0000000000000..9eeee195e56e4 --- /dev/null +++ b/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.rs @@ -0,0 +1,9 @@ +fn f1<'a>(x: u8, y: &'a ...) {} +//~^ ERROR C-variadic type `...` may not be nested inside another type + +fn f2<'a>(x: u8, y: Vec<&'a ...>) {} +//~^ ERROR C-variadic type `...` may not be nested inside another type + +fn main() { + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.stderr b/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.stderr new file mode 100644 index 0000000000000..8b9d676a45dae --- /dev/null +++ b/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.stderr @@ -0,0 +1,24 @@ +error[E0743]: C-variadic type `...` may not be nested inside another type + --> $DIR/variadic-ffi-nested-syntactic-fail.rs:1:25 + | +LL | fn f1<'a>(x: u8, y: &'a ...) {} + | ^^^ + +error[E0743]: C-variadic type `...` may not be nested inside another type + --> $DIR/variadic-ffi-nested-syntactic-fail.rs:4:29 + | +LL | fn f2<'a>(x: u8, y: Vec<&'a ...>) {} + | ^^^ + +error[E0308]: mismatched types + --> $DIR/variadic-ffi-nested-syntactic-fail.rs:8:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0743. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs b/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs new file mode 100644 index 0000000000000..aa85f6d6b522b --- /dev/null +++ b/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs @@ -0,0 +1,76 @@ +#![feature(c_variadic)] + +fn main() {} + +fn f1_1(x: isize, ...) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + +fn f1_2(...) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~| ERROR C-variadic function must be declared with at least one named argument + +extern "C" fn f2_1(x: isize, ...) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + +extern "C" fn f2_2(...) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~| ERROR C-variadic function must be declared with at least one named argument + +extern "C" fn f2_3(..., x: isize) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~| ERROR `...` must be the last argument of a C-variadic function + +extern fn f3_1(x: isize, ...) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + +extern fn f3_2(...) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~| ERROR C-variadic function must be declared with at least one named argument + +extern fn f3_3(..., x: isize) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~| ERROR `...` must be the last argument of a C-variadic function + +extern { + fn e_f1(...); + //~^ ERROR C-variadic function must be declared with at least one named argument + fn e_f2(..., x: isize); + //~^ ERROR `...` must be the last argument of a C-variadic function +} + +struct X; + +impl X { + fn i_f1(x: isize, ...) {} + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + fn i_f2(...) {} + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR C-variadic function must be declared with at least one named argument + fn i_f3(..., x: isize, ...) {} + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR `...` must be the last argument of a C-variadic function + fn i_f4(..., x: isize, ...) {} + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR `...` must be the last argument of a C-variadic function +} + +trait T { + fn t_f1(x: isize, ...) {} + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + fn t_f2(x: isize, ...); + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + fn t_f3(...) {} + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR C-variadic function must be declared with at least one named argument + fn t_f4(...); + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR C-variadic function must be declared with at least one named argument + fn t_f5(..., x: isize) {} + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR `...` must be the last argument of a C-variadic function + fn t_f6(..., x: isize); + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR `...` must be the last argument of a C-variadic function +} diff --git a/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr b/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr new file mode 100644 index 0000000000000..21992a29670c9 --- /dev/null +++ b/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr @@ -0,0 +1,206 @@ +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:5:19 + | +LL | fn f1_1(x: isize, ...) {} + | ^^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:8:9 + | +LL | fn f1_2(...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:8:9 + | +LL | fn f1_2(...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:12:30 + | +LL | extern "C" fn f2_1(x: isize, ...) {} + | ^^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:15:20 + | +LL | extern "C" fn f2_2(...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:15:20 + | +LL | extern "C" fn f2_2(...) {} + | ^^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:19:20 + | +LL | extern "C" fn f2_3(..., x: isize) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:19:20 + | +LL | extern "C" fn f2_3(..., x: isize) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:23:26 + | +LL | extern fn f3_1(x: isize, ...) {} + | ^^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:26:16 + | +LL | extern fn f3_2(...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:26:16 + | +LL | extern fn f3_2(...) {} + | ^^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:30:16 + | +LL | extern fn f3_3(..., x: isize) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:30:16 + | +LL | extern fn f3_3(..., x: isize) {} + | ^^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:35:13 + | +LL | fn e_f1(...); + | ^^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:37:13 + | +LL | fn e_f2(..., x: isize); + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:44:23 + | +LL | fn i_f1(x: isize, ...) {} + | ^^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:46:13 + | +LL | fn i_f2(...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:46:13 + | +LL | fn i_f2(...) {} + | ^^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:49:13 + | +LL | fn i_f3(..., x: isize, ...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:49:13 + | +LL | fn i_f3(..., x: isize, ...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:49:28 + | +LL | fn i_f3(..., x: isize, ...) {} + | ^^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:53:13 + | +LL | fn i_f4(..., x: isize, ...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:53:13 + | +LL | fn i_f4(..., x: isize, ...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:53:28 + | +LL | fn i_f4(..., x: isize, ...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:60:23 + | +LL | fn t_f1(x: isize, ...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:62:23 + | +LL | fn t_f2(x: isize, ...); + | ^^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:64:13 + | +LL | fn t_f3(...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:64:13 + | +LL | fn t_f3(...) {} + | ^^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:67:13 + | +LL | fn t_f4(...); + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:67:13 + | +LL | fn t_f4(...); + | ^^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:70:13 + | +LL | fn t_f5(..., x: isize) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:70:13 + | +LL | fn t_f5(..., x: isize) {} + | ^^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:73:13 + | +LL | fn t_f6(..., x: isize); + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:73:13 + | +LL | fn t_f6(..., x: isize); + | ^^^^ + +error: aborting due to 34 previous errors + diff --git a/src/test/ui/parser/variadic-ffi-syntactic-pass.rs b/src/test/ui/parser/variadic-ffi-syntactic-pass.rs new file mode 100644 index 0000000000000..3875d6af13716 --- /dev/null +++ b/src/test/ui/parser/variadic-ffi-syntactic-pass.rs @@ -0,0 +1,53 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +fn f1_1(x: isize, ...) {} + +#[cfg(FALSE)] +fn f1_2(...) {} + +#[cfg(FALSE)] +extern "C" fn f2_1(x: isize, ...) {} + +#[cfg(FALSE)] +extern "C" fn f2_2(...) {} + +#[cfg(FALSE)] +extern "C" fn f2_3(..., x: isize) {} + +#[cfg(FALSE)] +extern fn f3_1(x: isize, ...) {} + +#[cfg(FALSE)] +extern fn f3_2(...) {} + +#[cfg(FALSE)] +extern fn f3_3(..., x: isize) {} + +#[cfg(FALSE)] +extern { + fn e_f1(...); + fn e_f2(..., x: isize); +} + +struct X; + +#[cfg(FALSE)] +impl X { + fn i_f1(x: isize, ...) {} + fn i_f2(...) {} + fn i_f3(..., x: isize, ...) {} + fn i_f4(..., x: isize, ...) {} +} + +#[cfg(FALSE)] +trait T { + fn t_f1(x: isize, ...) {} + fn t_f2(x: isize, ...); + fn t_f3(...) {} + fn t_f4(...); + fn t_f5(..., x: isize) {} + fn t_f6(..., x: isize); +} diff --git a/src/test/ui/raw-ref-op/raw-ref-op.rs b/src/test/ui/raw-ref-op/raw-ref-op.rs index de847909eb371..0c6e23a00d525 100644 --- a/src/test/ui/raw-ref-op/raw-ref-op.rs +++ b/src/test/ui/raw-ref-op/raw-ref-op.rs @@ -1,11 +1,11 @@ -// FIXME(#64490): make this run-pass +// run-pass #![feature(raw_ref_op)] fn main() { let mut x = 123; - let c_p = &raw const x; //~ ERROR not yet implemented - let m_p = &raw mut x; //~ ERROR not yet implemented + let c_p = &raw const x; + let m_p = &raw mut x; let i_r = &x; assert!(c_p == i_r); assert!(c_p == m_p); diff --git a/src/test/ui/raw-ref-op/raw-ref-op.stderr b/src/test/ui/raw-ref-op/raw-ref-op.stderr deleted file mode 100644 index 04c59c95fca1e..0000000000000 --- a/src/test/ui/raw-ref-op/raw-ref-op.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: raw borrows are not yet implemented - --> $DIR/raw-ref-op.rs:7:15 - | -LL | let c_p = &raw const x; - | ^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-op.rs:8:15 - | -LL | let m_p = &raw mut x; - | ^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs b/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs index d251586de5595..a814003aebf20 100644 --- a/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs +++ b/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs @@ -1,4 +1,4 @@ -// FIXME(#64490) This should be check-pass +// check-pass // Check that taking the address of a place that contains a dereference is // allowed. #![feature(raw_ref_op, type_ascription)] @@ -10,15 +10,15 @@ const SLICE_REF: &[i32] = &[5, 6]; fn main() { // These are all OK, we're not taking the address of the temporary - let deref_ref = &raw const *PAIR_REF; //~ ERROR not yet implemented - let field_deref_ref = &raw const PAIR_REF.0; //~ ERROR not yet implemented - let deref_ref = &raw const *ARRAY_REF; //~ ERROR not yet implemented - let index_deref_ref = &raw const ARRAY_REF[0]; //~ ERROR not yet implemented - let deref_ref = &raw const *SLICE_REF; //~ ERROR not yet implemented - let index_deref_ref = &raw const SLICE_REF[1]; //~ ERROR not yet implemented + let deref_ref = &raw const *PAIR_REF; + let field_deref_ref = &raw const PAIR_REF.0; + let deref_ref = &raw const *ARRAY_REF; + let index_deref_ref = &raw const ARRAY_REF[0]; + let deref_ref = &raw const *SLICE_REF; + let index_deref_ref = &raw const SLICE_REF[1]; let x = 0; - let ascribe_ref = &raw const (x: i32); //~ ERROR not yet implemented - let ascribe_deref = &raw const (*ARRAY_REF: [i32; 2]); //~ ERROR not yet implemented - let ascribe_index_deref = &raw const (ARRAY_REF[0]: i32); //~ ERROR not yet implemented + let ascribe_ref = &raw const (x: i32); + let ascribe_deref = &raw const (*ARRAY_REF: [i32; 2]); + let ascribe_index_deref = &raw const (ARRAY_REF[0]: i32); } diff --git a/src/test/ui/raw-ref-op/raw-ref-temp-deref.stderr b/src/test/ui/raw-ref-op/raw-ref-temp-deref.stderr deleted file mode 100644 index b0bfc74903b0c..0000000000000 --- a/src/test/ui/raw-ref-op/raw-ref-temp-deref.stderr +++ /dev/null @@ -1,74 +0,0 @@ -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:13:21 - | -LL | let deref_ref = &raw const *PAIR_REF; - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:14:27 - | -LL | let field_deref_ref = &raw const PAIR_REF.0; - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:15:21 - | -LL | let deref_ref = &raw const *ARRAY_REF; - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:16:27 - | -LL | let index_deref_ref = &raw const ARRAY_REF[0]; - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:17:21 - | -LL | let deref_ref = &raw const *SLICE_REF; - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:18:27 - | -LL | let index_deref_ref = &raw const SLICE_REF[1]; - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:21:23 - | -LL | let ascribe_ref = &raw const (x: i32); - | ^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:22:25 - | -LL | let ascribe_deref = &raw const (*ARRAY_REF: [i32; 2]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:23:31 - | -LL | let ascribe_index_deref = &raw const (ARRAY_REF[0]: i32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: aborting due to 9 previous errors - diff --git a/src/test/ui/raw-ref-op/raw-ref-temp.rs b/src/test/ui/raw-ref-op/raw-ref-temp.rs index ac2445f049c66..32df56468da17 100644 --- a/src/test/ui/raw-ref-op/raw-ref-temp.rs +++ b/src/test/ui/raw-ref-op/raw-ref-temp.rs @@ -1,6 +1,8 @@ // Ensure that we don't allow taking the address of temporary values #![feature(raw_ref_op, type_ascription)] +const FOUR: u64 = 4; + const PAIR: (i32, i64) = (1, 2); const ARRAY: [i32; 2] = [1, 2]; @@ -8,8 +10,8 @@ const ARRAY: [i32; 2] = [1, 2]; fn main() { let ref_expr = &raw const 2; //~ ERROR cannot take address let mut_ref_expr = &raw mut 3; //~ ERROR cannot take address - let ref_const = &raw const 4; //~ ERROR cannot take address - let mut_ref_const = &raw mut 5; //~ ERROR cannot take address + let ref_const = &raw const FOUR; //~ ERROR cannot take address + let mut_ref_const = &raw mut FOUR; //~ ERROR cannot take address let field_ref_expr = &raw const (1, 2).0; //~ ERROR cannot take address let mut_field_ref_expr = &raw mut (1, 2).0; //~ ERROR cannot take address diff --git a/src/test/ui/raw-ref-op/raw-ref-temp.stderr b/src/test/ui/raw-ref-op/raw-ref-temp.stderr index de07073373506..80dea76d5953b 100644 --- a/src/test/ui/raw-ref-op/raw-ref-temp.stderr +++ b/src/test/ui/raw-ref-op/raw-ref-temp.stderr @@ -1,95 +1,95 @@ error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:9:31 + --> $DIR/raw-ref-temp.rs:11:31 | LL | let ref_expr = &raw const 2; | ^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:10:33 + --> $DIR/raw-ref-temp.rs:12:33 | LL | let mut_ref_expr = &raw mut 3; | ^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:11:32 + --> $DIR/raw-ref-temp.rs:13:32 | -LL | let ref_const = &raw const 4; - | ^ temporary value +LL | let ref_const = &raw const FOUR; + | ^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:12:34 + --> $DIR/raw-ref-temp.rs:14:34 | -LL | let mut_ref_const = &raw mut 5; - | ^ temporary value +LL | let mut_ref_const = &raw mut FOUR; + | ^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:14:37 + --> $DIR/raw-ref-temp.rs:16:37 | LL | let field_ref_expr = &raw const (1, 2).0; | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:15:39 + --> $DIR/raw-ref-temp.rs:17:39 | LL | let mut_field_ref_expr = &raw mut (1, 2).0; | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:16:32 + --> $DIR/raw-ref-temp.rs:18:32 | LL | let field_ref = &raw const PAIR.0; | ^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:17:34 + --> $DIR/raw-ref-temp.rs:19:34 | LL | let mut_field_ref = &raw mut PAIR.0; | ^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:19:37 + --> $DIR/raw-ref-temp.rs:21:37 | LL | let index_ref_expr = &raw const [1, 2][0]; | ^^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:20:39 + --> $DIR/raw-ref-temp.rs:22:39 | LL | let mut_index_ref_expr = &raw mut [1, 2][0]; | ^^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:21:32 + --> $DIR/raw-ref-temp.rs:23:32 | LL | let index_ref = &raw const ARRAY[0]; | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:22:34 + --> $DIR/raw-ref-temp.rs:24:34 | LL | let mut_index_ref = &raw mut ARRAY[1]; | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:24:34 + --> $DIR/raw-ref-temp.rs:26:34 | LL | let ref_ascribe = &raw const (2: i32); | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:25:36 + --> $DIR/raw-ref-temp.rs:27:36 | LL | let mut_ref_ascribe = &raw mut (3: i32); | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:27:40 + --> $DIR/raw-ref-temp.rs:29:40 | LL | let ascribe_field_ref = &raw const (PAIR.0: i32); | ^^^^^^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:28:38 + --> $DIR/raw-ref-temp.rs:30:38 | LL | let ascribe_index_ref = &raw mut (ARRAY[0]: i32); | ^^^^^^^^^^^^^^^ temporary value diff --git a/src/test/ui/raw-ref-op/unusual_locations.rs b/src/test/ui/raw-ref-op/unusual_locations.rs index f0a6bcce2ac8a..6bf37408a8bbd 100644 --- a/src/test/ui/raw-ref-op/unusual_locations.rs +++ b/src/test/ui/raw-ref-op/unusual_locations.rs @@ -1,25 +1,22 @@ -// FIXME(#64490): make this check-pass +// check-pass #![feature(raw_ref_op)] -const USES_PTR: () = { let u = (); &raw const u; }; //~ ERROR not yet implemented -static ALSO_USES_PTR: () = { let u = (); &raw const u; }; //~ ERROR not yet implemented +const USES_PTR: () = { let u = (); &raw const u; }; +static ALSO_USES_PTR: () = { let u = (); &raw const u; }; fn main() { - #[cfg(FALSE)] - { - let x: [i32; { let u = 2; let x = &raw const u; 4 }] - = [2; { let v = 3; let y = &raw const v; 4 }]; - let mut one = 1; - let two = 2; - if &raw const one == &raw mut one { - match &raw const two { - _ => {} - } + let x: [i32; { let u = 2; let x = &raw const u; 4 }] + = [2; { let v = 3; let y = &raw const v; 4 }]; + let mut one = 1; + let two = 2; + if &raw const one == &raw mut one { + match &raw const two { + _ => {} } - let three = 3; - let mut four = 4; - println!("{:p}", &raw const three); - unsafe { &raw mut four; } } + let three = 3; + let mut four = 4; + println!("{:p}", &raw const three); + unsafe { &raw mut four; } } diff --git a/src/test/ui/raw-ref-op/unusual_locations.stderr b/src/test/ui/raw-ref-op/unusual_locations.stderr deleted file mode 100644 index 3fae5db3d51a1..0000000000000 --- a/src/test/ui/raw-ref-op/unusual_locations.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: raw borrows are not yet implemented - --> $DIR/unusual_locations.rs:5:36 - | -LL | const USES_PTR: () = { let u = (); &raw const u; }; - | ^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/unusual_locations.rs:6:42 - | -LL | static ALSO_USES_PTR: () = { let u = (); &raw const u; }; - | ^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: aborting due to 2 previous errors -